summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp')
-rw-r--r--src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp518
1 files changed, 518 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp b/src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp
new file mode 100644
index 00000000..1fd98734
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/Controls/WinRenderer.cpp
@@ -0,0 +1,518 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSCommonPrecompile.h"
+
+#include "WinRenderer.h"
+#include "MasterP.h"
+#include "CoreUtils.h"
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * In order for this renderer to be valid, you must do two things: (1) you must
+ * create a CDC and set m_DC equal to it, and (2) you must call PushClippingRect.
+ */
+CWinRenderer::CWinRenderer()
+ : m_painter(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * PushClippingRect must be called in order for this to become valid.
+ */
+CWinRenderer::CWinRenderer(QPainter *inDC)
+{
+ m_painter = inDC;
+}
+
+CWinRenderer::CWinRenderer(QPainter *inDC, const QRect &inClippingRect)
+{
+ m_painter = inDC;
+
+ PushClippingRect(inClippingRect);
+}
+
+CWinRenderer::~CWinRenderer()
+{
+ m_Pens.clear();
+}
+
+//=============================================================================
+/**
+ * Draws a rectangle and fills it with inColor.
+ * The rectangle has no border and is solid.
+ * The coordinates are converted to global space using the current translation.
+ * @param inCoordinates the coordinates of the rectangle.
+ * @param inColor the color of the rectangle to draw.
+ */
+void CWinRenderer::FillSolidRect(const QRect &inCoordinates, const QColor &inColor)
+{
+ QRect theRect(inCoordinates.topLeft() + m_Translation,
+ inCoordinates.size());
+
+ m_painter->fillRect(theRect, inColor);
+}
+
+//=============================================================================
+/**
+ * Draws a rounded rectangle (which actually is just a line) and fills it with inColor.
+ * The coordinates are converted to global space using the current translation.
+ * @param inCoordinates the coordinates of the rectangle.
+ * @param inColor the color of the rectangle to draw.
+ */
+void CWinRenderer::FillRoundedRect(const QRect &inCoordinates, const QColor &inColor,
+ bool vertical)
+{
+ QPen previousPen = m_painter->pen();
+ QRect theRect(inCoordinates.topLeft() + m_Translation, inCoordinates.size());
+ QPointF startPoint = (theRect.bottomLeft() + theRect.topLeft()) / 2.0;
+ QPointF endPoint = (theRect.bottomRight() + theRect.topRight()) / 2.0;
+ qreal lineWidth = theRect.bottom() - theRect.top() + 1.0;
+
+ if (vertical) {
+ lineWidth = theRect.right() - theRect.left() + 1.0;
+ startPoint = (theRect.topRight() + theRect.topLeft()) / 2.0;
+ endPoint = (theRect.bottomRight() + theRect.bottomLeft()) / 2.0;
+ }
+
+ m_painter->setPen(QPen(inColor, lineWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ m_painter->drawLine(startPoint, endPoint);
+
+ // Restore previous pen
+ m_painter->setPen(previousPen);
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen at inPoint but will not draw a line there from the
+ * current location.
+ * @param inPoint the location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(const QPoint &inPoint)
+{
+ m_currentPos = inPoint + m_Translation;
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen to the point but will not draw a line there from the
+ * current location.
+ * @param inX the X location to move to, in local coordinates.
+ * @param inY the Y location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(long inX, long inY)
+{
+ MoveTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to inPoint.
+ * This will draw a line to inPoint and move the current location of the pen
+ * to inPoint.
+ * @param inPoint the location to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(const QPoint &inPoint)
+{
+ const QPoint point = inPoint + m_Translation;
+ m_painter->drawLine(m_currentPos, point);
+ m_painter->drawLine(point, QPoint(point.x(), point.y() + 1));
+ m_currentPos = point;
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to the point.
+ * This will draw a line to the point and move the current location of the pen
+ * to inPoint.
+ * @param inX the X coordinate of the point to draw to, in local coordinates.
+ * @param inY the Y coordinate of the point to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(long inX, long inY)
+{
+ LineTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Change the active pen color.
+ * This acts as a stack so that it does not interfere with previous components.
+ * Once the color is done being used PopPen should be called.
+ * @param inColor the color to make the current pen.
+ * @param inWidth the pen width, in pixels.
+ */
+void CWinRenderer::PushPen(const QColor &inColor, int inWidth)
+{
+ QPen thePen = GetPen(inColor, inWidth, Qt::SolidLine);
+
+ QPen theCurrentPen = m_painter->pen();
+ m_painter->setPen(thePen);
+ m_PenList.push_back(theCurrentPen);
+}
+
+void CWinRenderer::PopPen()
+{
+ QPen thePen = m_PenList.back();
+ m_PenList.pop_back();
+ m_painter->setPen(thePen);
+}
+
+//=============================================================================
+/**
+ * Copy the bits from another renderer into this one.
+ * This will copy the rect from inRenderer into this renderer.
+ * inRect will be offset by this renderer's current translation. inXSrc and inYSrc
+ * will be offset by inRenderer's current translation.
+ * @param inRect the position and size of the area to be copied into this renderer.
+ * @param inPixmap the renderer to copy from.
+ * @param xSrc the x location of the location to copy from in inRenderer.
+ * @param ySrc the y location of the location to copy from in inRenderer.
+ */
+void CWinRenderer::BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc)
+{
+ const auto inTranslation = inRenderer->GetTranslation();
+ inXSrc += inTranslation.x();
+ inYSrc += inTranslation.y();
+
+ auto srcRect = inRect;
+ auto destRect = inRect;
+ destRect.translate(m_Translation);
+ srcRect.moveTo(inXSrc, inYSrc);
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
+ m_painter->drawPixmap(destRect, inRenderer->pixmap(), srcRect);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws text out without clipping it.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+ m_painter->drawText(QPointF(inX, inY), inText);
+}
+
+//=============================================================================
+/**
+ * Draws text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws BOLD text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ QFont font = m_painter->font();
+ font.setBold(true);
+ m_painter->setFont(font);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Gets the dimensions of the text string as it would be written out to the
+ * screen.
+ * @param inText the text to check the length on.
+ * @return the length of the text in pixels.
+ */
+QSize CWinRenderer::GetTextSize(const QString &inText)
+{
+ QFontMetrics fm = m_painter->fontMetrics();
+ return fm.size(Qt::TextSingleLine, inText);
+}
+
+//=============================================================================
+/**
+ * Draws a a three-dimensional rectangle with the top and left sides in the
+ * color specified by inTopLeftColor and the bottom and right sides in the color
+ * specified by inBottomRightColor.
+ *
+ * @param inRect The rectangle to draw
+ * @param inTopLeftColor Color for the top and left sides of the rect
+ * @param inBottomRightColor Color for the bottom and right sides of the rect
+ */
+void CWinRenderer::Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor)
+{
+ auto rect = inRect;
+ rect.translate(m_Translation);
+ m_painter->drawRect(rect);
+ m_painter->save();
+ m_painter->setPen(inTopLeftColor);
+ m_painter->drawLine(rect.topLeft(), rect.bottomLeft());
+ m_painter->drawLine(rect.topLeft(), rect.topRight());
+ m_painter->setPen(inBottomRightColor);
+ m_painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ m_painter->drawLine(rect.bottomRight(), rect.topRight());
+ m_painter->restore();
+}
+
+//==============================================================================
+/**
+ * DrawBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle.
+ *
+ * @param inDC Device context for drawing
+ * @param inPos CPoint position for drawing
+ * @param inBitmap Handle of the bitmap to draw
+ */
+//==============================================================================
+void CWinRenderer::DrawBitmap(const QPoint &inPos, const QPixmap &inImage)
+{
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ m_painter->drawPixmap(inPos + m_Translation, inImage);
+ m_painter->restore();;
+}
+
+void CWinRenderer::PushTranslation(const QPoint &inTranslation)
+{
+ m_Translation += inTranslation;
+
+ m_Translations.push_back(inTranslation);
+}
+
+void CWinRenderer::PopTranslation()
+{
+ QPoint thePreviousTranslation = m_Translations.back();
+ m_Translation -= thePreviousTranslation;
+
+ m_Translations.pop_back();
+}
+
+QPoint CWinRenderer::GetTranslation()
+{
+ return m_Translation;
+}
+
+QPainter* CWinRenderer::GetPainter()
+{
+ return m_painter;
+}
+
+//==============================================================================
+/**
+ * Get the current clipping rect.
+ * The clipping rect is the boundary of pixels that will be drawn to the DC.
+ * This can be used to not draw non-visible objects.
+ * @return the clipping rect in local coordinates.
+ */
+QRect CWinRenderer::GetClippingRect()
+{
+ QRect theClippingRect = m_painter->clipBoundingRect().toRect();
+ theClippingRect.translate(-m_Translation);
+
+ return theClippingRect;
+}
+
+//==============================================================================
+/**
+ * Push a clipping rect onto the stack of clipping rects.
+ * This will cause any drawing outside of the clipping rect to be ignored. The
+ * Control class also uses this to not draw objects outside of this rect.
+ * @param inClippingRect the new clipping rect, in local coordinates.
+ */
+void CWinRenderer::PushClippingRect(const QRect &inClippingRect)
+{
+ QRect clippingRect(inClippingRect);
+ clippingRect.translate(m_Translation);
+
+ const QRegion currentRegion = m_painter->clipRegion();
+ m_painter->setClipRect(clippingRect);
+
+ m_ClippingRegions.push_back(currentRegion);
+}
+
+//==============================================================================
+/**
+ * Pop the current clipping rect.
+ * This will change the clipping rect to use the one previous to the current
+ * one.
+ */
+void CWinRenderer::PopClippingRect()
+{
+ if (m_ClippingRegions.size() > 1) {
+ QRegion thePreviousRegion = m_ClippingRegions.back();
+ m_painter->setClipRegion(thePreviousRegion);
+ m_ClippingRegions.pop_back();
+ }
+}
+
+//==============================================================================
+/**
+ * DrawGradiantBitmap
+ *
+ * Draws a gradiant based on the begin color
+ *
+ * @param inRct Rct tof the control
+ * @param inBeginColor color to start with
+ * @param inInverted true if this is inverted
+ */
+void CWinRenderer::DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor)
+{
+ QRect rect(inRct);
+ QRect theClippingRect = GetClippingRect();
+ rect &= theClippingRect;
+ rect.translate(m_Translation);
+
+ long theHeight = rect.height();
+ long theWidth = rect.width();
+
+ QImage theCompatibleBitmap(1, theHeight, QImage::Format_RGB32);
+
+ int theR = inBeginColor.red();
+ int theG = inBeginColor.green();
+ int theB = inBeginColor.blue();
+
+ double theExtraRModifier = inScalingFactor * (1.0 - (theR / 255.0));
+ double theExtraGModifier = inScalingFactor * (1.0 - (theG / 255.0));
+ double theExtraBModifier = inScalingFactor * (1.0 - (theB / 255.0));
+
+ for (long thePixel = 0; thePixel < theHeight; ++thePixel) {
+ double theNormPixel = (double)thePixel / (theHeight * 4.8);
+ double theCos = 1.0 / (theNormPixel * theNormPixel + 1.0);
+ double theRValue = (double)theR * (theCos + theExtraRModifier);
+ double theGValue = (double)theG * (theCos + theExtraGModifier);
+ double theBValue = (double)theB * (theCos + theExtraBModifier);
+
+ QColor theTempColor(::dtoi(theRValue), ::dtoi(theGValue), ::dtoi(theBValue));
+ if (inInverted) {
+ theCompatibleBitmap.setPixelColor(0, qMax(0l, theHeight - thePixel - 2), theTempColor);
+ } else {
+ theCompatibleBitmap.setPixelColor(0, thePixel, theTempColor);
+ }
+ theExtraRModifier *= 0.3;
+ theExtraGModifier *= 0.3;
+ theExtraBModifier *= 0.3;
+ }
+
+ m_painter->save();
+ m_painter->drawImage(QRect(rect.x(), rect.y(), theWidth, theHeight), theCompatibleBitmap);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draw a gradient over inRect.
+ * This will blend horizontally across the rect from inBeginColor into inEndColor.
+ * This does linear interpolation.
+ * @param inRect the rect to draw on.
+ * @param inBeginColor the start (left most) color.
+ * @param inEndColor the final (right most) color.
+ */
+void CWinRenderer::DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor)
+{
+ const QRect rect = inRect.translated(m_Translation);
+ QLinearGradient gradient(rect.topLeft(), rect.topRight());
+ gradient.setColorAt(0, inBeginColor);
+ gradient.setColorAt(1, inEndColor);
+
+ QBrush brush(gradient);
+ m_painter->fillRect(rect, brush);
+}
+
+void CWinRenderer::FillHashed(const QRect &inRect, const QColor &inForegroundColor)
+{
+ m_painter->save();
+
+ QBrush theBrush(inForegroundColor, Qt::BDiagPattern);
+ QPen pen(inForegroundColor);
+ m_painter->setPen(pen);
+ m_painter->setBrush(theBrush);
+ m_painter->drawRect(inRect.translated(m_Translation));
+
+ m_painter->restore();
+}
+
+QPen CWinRenderer::GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle)
+{
+ QPen thePen;
+ SPenInfo theInfo = { inColor, inWidth, inStyle };
+ TPenMap::iterator thePos = m_Pens.find(theInfo);
+ if (thePos != m_Pens.end()) {
+ thePen = thePos->second;
+ } else {
+ thePen.setColor(inColor);
+ thePen.setWidth(inWidth);
+ m_Pens[theInfo] = thePen;
+ }
+ return thePen;
+}
+
+QPixmap CWinRenderer::pixmap() const
+{
+ return {};
+}