From 65c877f40e965c368fe6e7ed730242461b5824b7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 3 Jun 2016 13:49:51 +0200 Subject: Add cross-backend simple rect, texture, and ninepatch nodes QSGSimpleRectNode is deprecated -> use QSGRectangleNode via QQuickWindow::createRectangleNode() instead. QSGSimpleTextureNode is deprecated -> use QSGImageNode via QQuickWindow::createImageNode() instead. The OpenGL version of the simple rectangle node is switched over to the vertex color material instead of flat, to allow for better batching. Use the same concept for nine patch nodes. The "style" node from Quick Controls 1 is now QSGNinePatchNode in order to provide a proper cross-backend solution which is already necessary due to the software backend, but now generalize it to apply to the accelerated backends with proper materials as well. QC can now simply call createNinePatchNode() without further ado. Also fixes a bug with the D3D12 texture material not enabling blending when needed. When it comes to the internal class names, QSGRectangleNode and QSGImageNode get the Internal prefix in the adaptation layer in order to differentiate from the public API. This involves quite a lot of renaming, but results in a nice and clean public API. Change-Id: Iddf9f9412377843ea6d652bcf25e68d1d74659ea Reviewed-by: Gunnar Sletta --- src/quick/items/context2d/qquickcanvasitem.cpp | 6 +- src/quick/items/qquickborderimage.cpp | 4 +- src/quick/items/qquickimage.cpp | 4 +- src/quick/items/qquickmousearea.cpp | 4 +- src/quick/items/qquickmultipointtoucharea.cpp | 4 +- src/quick/items/qquickrectangle.cpp | 4 +- src/quick/items/qquickshadereffectmesh.cpp | 6 +- src/quick/items/qquickshadereffectsource.cpp | 4 +- src/quick/items/qquickshadereffectsource_p.h | 2 +- src/quick/items/qquicktextedit.cpp | 8 +- src/quick/items/qquicktextnode.cpp | 6 +- src/quick/items/qquicktextnode_p.h | 6 +- src/quick/items/qquickwindow.cpp | 39 ++ src/quick/items/qquickwindow.h | 7 + .../adaptations/software/qsgsoftwarecontext.cpp | 39 +- .../adaptations/software/qsgsoftwarecontext_p.h | 8 +- .../adaptations/software/qsgsoftwareimagenode.cpp | 501 --------------- .../adaptations/software/qsgsoftwareimagenode_p.h | 147 ----- .../software/qsgsoftwareinternalimagenode.cpp | 501 +++++++++++++++ .../software/qsgsoftwareinternalimagenode_p.h | 147 +++++ .../software/qsgsoftwareinternalrectanglenode.cpp | 451 ++++++++++++++ .../software/qsgsoftwareinternalrectanglenode_p.h | 103 +++ .../software/qsgsoftwareninepatchnode.cpp | 109 ---- .../software/qsgsoftwareninepatchnode_p.h | 82 --- .../software/qsgsoftwarepublicnodes.cpp | 146 +++++ .../software/qsgsoftwarepublicnodes_p.h | 137 ++++ .../software/qsgsoftwarerectanglenode.cpp | 451 -------------- .../software/qsgsoftwarerectanglenode_p.h | 103 --- .../software/qsgsoftwarerenderablenode.cpp | 38 +- .../software/qsgsoftwarerenderablenode_p.h | 18 +- .../software/qsgsoftwarerenderablenodeupdater.cpp | 29 +- .../software/qsgsoftwarerenderablenodeupdater_p.h | 10 +- .../software/qsgsoftwarerenderlistbuilder.cpp | 23 +- .../software/qsgsoftwarerenderlistbuilder_p.h | 10 +- .../scenegraph/adaptations/software/software.pri | 12 +- src/quick/scenegraph/coreapi/qsggeometry.cpp | 21 + src/quick/scenegraph/coreapi/qsggeometry.h | 1 + src/quick/scenegraph/coreapi/qsgnode.cpp | 2 - src/quick/scenegraph/qsgadaptationlayer_p.h | 32 +- src/quick/scenegraph/qsgbasicimagenode.cpp | 559 ----------------- src/quick/scenegraph/qsgbasicimagenode_p.h | 109 ---- src/quick/scenegraph/qsgbasicinternalimagenode.cpp | 559 +++++++++++++++++ src/quick/scenegraph/qsgbasicinternalimagenode_p.h | 109 ++++ .../scenegraph/qsgbasicinternalrectanglenode.cpp | 687 +++++++++++++++++++++ .../scenegraph/qsgbasicinternalrectanglenode_p.h | 99 +++ src/quick/scenegraph/qsgbasicrectanglenode.cpp | 687 --------------------- src/quick/scenegraph/qsgbasicrectanglenode_p.h | 99 --- src/quick/scenegraph/qsgcontext.cpp | 4 +- src/quick/scenegraph/qsgcontext_p.h | 19 +- src/quick/scenegraph/qsgdefaultcontext.cpp | 43 +- src/quick/scenegraph/qsgdefaultcontext_p.h | 8 +- src/quick/scenegraph/qsgdefaultimagenode.cpp | 226 ------- src/quick/scenegraph/qsgdefaultimagenode_p.h | 97 --- .../scenegraph/qsgdefaultinternalimagenode.cpp | 226 +++++++ .../scenegraph/qsgdefaultinternalimagenode_p.h | 97 +++ .../scenegraph/qsgdefaultinternalrectanglenode.cpp | 159 +++++ .../scenegraph/qsgdefaultinternalrectanglenode_p.h | 90 +++ src/quick/scenegraph/qsgdefaultrectanglenode.cpp | 159 ----- src/quick/scenegraph/qsgdefaultrectanglenode_p.h | 90 --- src/quick/scenegraph/scenegraph.pri | 33 +- src/quick/scenegraph/util/qsgdefaultimagenode.cpp | 190 ++++++ src/quick/scenegraph/util/qsgdefaultimagenode_p.h | 104 ++++ .../scenegraph/util/qsgdefaultninepatchnode.cpp | 136 ++++ .../scenegraph/util/qsgdefaultninepatchnode_p.h | 86 +++ .../scenegraph/util/qsgdefaultrectanglenode.cpp | 95 +++ .../scenegraph/util/qsgdefaultrectanglenode_p.h | 79 +++ src/quick/scenegraph/util/qsgengine.cpp | 41 ++ src/quick/scenegraph/util/qsgengine.h | 6 + src/quick/scenegraph/util/qsgimagenode.cpp | 175 ++++++ src/quick/scenegraph/util/qsgimagenode.h | 85 +++ src/quick/scenegraph/util/qsgninepatchnode.cpp | 77 +++ src/quick/scenegraph/util/qsgninepatchnode.h | 62 ++ src/quick/scenegraph/util/qsgrectanglenode.cpp | 86 +++ src/quick/scenegraph/util/qsgrectanglenode.h | 62 ++ src/quick/scenegraph/util/qsgsimplerectnode.cpp | 4 + src/quick/scenegraph/util/qsgsimpletexturenode.cpp | 5 + 76 files changed, 5083 insertions(+), 3594 deletions(-) delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode.cpp delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode_p.h create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode.cpp delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode_p.h create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp create mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode.cpp delete mode 100644 src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode_p.h delete mode 100644 src/quick/scenegraph/qsgbasicimagenode.cpp delete mode 100644 src/quick/scenegraph/qsgbasicimagenode_p.h create mode 100644 src/quick/scenegraph/qsgbasicinternalimagenode.cpp create mode 100644 src/quick/scenegraph/qsgbasicinternalimagenode_p.h create mode 100644 src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp create mode 100644 src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h delete mode 100644 src/quick/scenegraph/qsgbasicrectanglenode.cpp delete mode 100644 src/quick/scenegraph/qsgbasicrectanglenode_p.h delete mode 100644 src/quick/scenegraph/qsgdefaultimagenode.cpp delete mode 100644 src/quick/scenegraph/qsgdefaultimagenode_p.h create mode 100644 src/quick/scenegraph/qsgdefaultinternalimagenode.cpp create mode 100644 src/quick/scenegraph/qsgdefaultinternalimagenode_p.h create mode 100644 src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp create mode 100644 src/quick/scenegraph/qsgdefaultinternalrectanglenode_p.h delete mode 100644 src/quick/scenegraph/qsgdefaultrectanglenode.cpp delete mode 100644 src/quick/scenegraph/qsgdefaultrectanglenode_p.h create mode 100644 src/quick/scenegraph/util/qsgdefaultimagenode.cpp create mode 100644 src/quick/scenegraph/util/qsgdefaultimagenode_p.h create mode 100644 src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp create mode 100644 src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h create mode 100644 src/quick/scenegraph/util/qsgdefaultrectanglenode.cpp create mode 100644 src/quick/scenegraph/util/qsgdefaultrectanglenode_p.h create mode 100644 src/quick/scenegraph/util/qsgimagenode.cpp create mode 100644 src/quick/scenegraph/util/qsgimagenode.h create mode 100644 src/quick/scenegraph/util/qsgninepatchnode.cpp create mode 100644 src/quick/scenegraph/util/qsgninepatchnode.h create mode 100644 src/quick/scenegraph/util/qsgrectanglenode.cpp create mode 100644 src/quick/scenegraph/util/qsgrectanglenode.h (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 9d5ddab155..8d91df5a74 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -174,7 +174,7 @@ public: QUrl baseUrl; QMap animationCallbacks; mutable QQuickCanvasTextureProvider *textureProvider; - QSGImageNode *node; + QSGInternalImageNode *node; QSGTexture *nodeTexture; }; @@ -743,9 +743,9 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData return 0; } - QSGImageNode *node = static_cast(oldNode); + QSGInternalImageNode *node = static_cast(oldNode); if (!node) { - node = QQuickWindowPrivate::get(window())->context->sceneGraphContext()->createImageNode(); + node = QQuickWindowPrivate::get(window())->context->sceneGraphContext()->createInternalImageNode(); d->node = node; } diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index b3a35e6219..ca5ad8dbbd 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -631,12 +631,12 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat return 0; } - QSGImageNode *node = static_cast(oldNode); + QSGInternalImageNode *node = static_cast(oldNode); bool updatePixmap = d->pixmapChanged; d->pixmapChanged = false; if (!node) { - node = d->sceneGraphContext()->createImageNode(); + node = d->sceneGraphContext()->createInternalImageNode(); updatePixmap = true; } diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index a168b43fd1..e36c070248 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -614,10 +614,10 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) return 0; } - QSGImageNode *node = static_cast(oldNode); + QSGInternalImageNode *node = static_cast(oldNode); if (!node) { d->pixmapChanged = true; - node = d->sceneGraphContext()->createImageNode(); + node = d->sceneGraphContext()->createInternalImageNode(); } QRectF targetRect; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 297a57e672..33cc6c9a63 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -1354,8 +1354,8 @@ QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData if (!qmlVisualTouchDebugging()) return 0; - QSGRectangleNode *rectangle = static_cast(oldNode); - if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode(); + QSGInternalRectangleNode *rectangle = static_cast(oldNode); + if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode(); rectangle->setRect(QRectF(0, 0, width(), height())); rectangle->setColor(QColor(255, 0, 0, 50)); diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 9d8e7aedd4..ac5598767a 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -940,8 +940,8 @@ QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePain if (!qmlVisualTouchDebugging()) return 0; - QSGRectangleNode *rectangle = static_cast(oldNode); - if (!rectangle) rectangle = QQuickItemPrivate::get(this)->sceneGraphContext()->createRectangleNode(); + QSGInternalRectangleNode *rectangle = static_cast(oldNode); + if (!rectangle) rectangle = QQuickItemPrivate::get(this)->sceneGraphContext()->createInternalRectangleNode(); rectangle->setRect(QRectF(0, 0, width(), height())); rectangle->setColor(QColor(255, 0, 0, 50)); diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp index b8c680433e..223976c32f 100644 --- a/src/quick/items/qquickrectangle.cpp +++ b/src/quick/items/qquickrectangle.cpp @@ -482,8 +482,8 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData return 0; } - QSGRectangleNode *rectangle = static_cast(oldNode); - if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode(); + QSGInternalRectangleNode *rectangle = static_cast(oldNode); + if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode(); rectangle->setRect(QRectF(0, 0, width(), height())); rectangle->setColor(d->color); diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp index f5cc19c877..8616bf8022 100644 --- a/src/quick/items/qquickshadereffectmesh.cpp +++ b/src/quick/items/qquickshadereffectmesh.cpp @@ -42,7 +42,7 @@ #include "qquickshadereffect_p.h" #include "qquickscalegrid_p_p.h" #include "qquickborderimage_p_p.h" -#include +#include QT_BEGIN_NAMESPACE @@ -335,8 +335,8 @@ QSGGeometry *QQuickBorderImageMesh::updateGeometry(QSGGeometry *geometry, int at innerSourceRect.width() * sourceRect.width(), innerSourceRect.height() * sourceRect.height()); - geometry = QSGBasicImageNode::updateGeometry(targetRect, innerTargetRect, sourceRect, - modifiedInnerSourceRect, subSourceRect, geometry); + geometry = QSGBasicInternalImageNode::updateGeometry(targetRect, innerTargetRect, sourceRect, + modifiedInnerSourceRect, subSourceRect, geometry); return geometry; } diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index 338e4dc3a7..d74dd99fe8 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -708,9 +708,9 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint return 0; } - QSGImageNode *node = static_cast(oldNode); + QSGInternalImageNode *node = static_cast(oldNode); if (!node) { - node = d->sceneGraphContext()->createImageNode(); + node = d->sceneGraphContext()->createInternalImageNode(); node->setFlag(QSGNode::UsePreprocess); node->setTexture(m_texture); QQuickShaderSourceAttachedNode *attached = new QQuickShaderSourceAttachedNode; diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index 680ba85aa1..de62c21488 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include #include "qpointer.h" diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 36eb5d3cde..eb568c48d4 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -153,7 +153,7 @@ namespace { newNode->setFlag(QSGNode::OwnedByParent); } - void resetCursorNode(QSGRectangleNode* newNode) + void resetCursorNode(QSGInternalRectangleNode* newNode) { if (cursorNode) removeChildNode(cursorNode); @@ -165,7 +165,7 @@ namespace { } } - QSGRectangleNode *cursorNode; + QSGInternalRectangleNode *cursorNode; QQuickTextNode* frameDecorationsNode; }; @@ -2125,9 +2125,9 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * } if (d->cursorComponent == 0) { - QSGRectangleNode* cursor = 0; + QSGInternalRectangleNode* cursor = 0; if (!isReadOnly() && d->cursorVisible && d->control->cursorOn()) - cursor = d->sceneGraphContext()->createRectangleNode(d->control->cursorRect(), d->color); + cursor = d->sceneGraphContext()->createInternalRectangleNode(d->control->cursorRect(), d->color); rootNode->resetCursorNode(cursor); } diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index 7ee01b5398..0e9d1e3951 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -136,7 +136,7 @@ void QQuickTextNode::setCursor(const QRectF &rect, const QColor &color) delete m_cursorNode; QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); - m_cursorNode = sg->sceneGraphContext()->createRectangleNode(rect, color); + m_cursorNode = sg->sceneGraphContext()->createInternalRectangleNode(rect, color); appendChildNode(m_cursorNode); } @@ -151,14 +151,14 @@ void QQuickTextNode::clearCursor() void QQuickTextNode::addRectangleNode(const QRectF &rect, const QColor &color) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); - appendChildNode(sg->sceneGraphContext()->createRectangleNode(rect, color)); + appendChildNode(sg->sceneGraphContext()->createInternalRectangleNode(rect, color)); } void QQuickTextNode::addImage(const QRectF &rect, const QImage &image) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); - QSGImageNode *node = sg->sceneGraphContext()->createImageNode(); + QSGInternalImageNode *node = sg->sceneGraphContext()->createInternalImageNode(); QSGTexture *texture = sg->createTexture(image); m_textures.append(texture); node->setTargetRect(rect); diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h index 0006cf1156..fb30956fea 100644 --- a/src/quick/items/qquicktextnode_p.h +++ b/src/quick/items/qquicktextnode_p.h @@ -68,7 +68,7 @@ class QColor; class QTextDocument; class QSGContext; class QRawFont; -class QSGRectangleNode; +class QSGInternalRectangleNode; class QSGClipNode; class QSGTexture; @@ -106,7 +106,7 @@ public: void setCursor(const QRectF &rect, const QColor &color); void clearCursor(); - QSGRectangleNode *cursorNode() const { return m_cursorNode; } + QSGInternalRectangleNode *cursorNode() const { return m_cursorNode; } QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color, QQuickText::TextStyle style = QQuickText::Normal, const QColor &styleColor = QColor(), @@ -118,7 +118,7 @@ public: void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; } private: - QSGRectangleNode *m_cursorNode; + QSGInternalRectangleNode *m_cursorNode; QList m_textures; QQuickItem *m_ownerElement; bool m_useNativeRenderer; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 98e450abdb..10b769b5b0 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4513,6 +4513,45 @@ void QQuickWindow::setSceneGraphBackend(const QString &backend) QSGContext::setBackend(backend); } +/*! + Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null. + + This is cross-backend alternative to constructing a QSGSimpleRectNode directly. + + \since 5.8 + \sa QSGRectangleNode + */ +QSGRectangleNode *QQuickWindow::createRectangleNode() const +{ + Q_D(const QQuickWindow); + return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr; +} + +/*! + Creates a simple image node. When the scenegraph is not initialized, the return value is null. + + This is cross-backend alternative to constructing a QSGSimpleTextureNode directly. + + \since 5.8 + \sa QSGImageNode + */ +QSGImageNode *QQuickWindow::createImageNode() const +{ + Q_D(const QQuickWindow); + return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr; +} + +/*! + Creates a nine patch node. When the scenegraph is not initialized, the return value is null. + + \since 5.8 + */ +QSGNinePatchNode *QQuickWindow::createNinePatchNode() const +{ + Q_D(const QQuickWindow); + return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr; +} + #include "moc_qquickwindow.cpp" QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index c741772253..cfadadec2d 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -61,6 +61,9 @@ class QQmlIncubationController; class QInputMethodEvent; class QQuickCloseEvent; class QQuickRenderControl; +class QSGRectangleNode; +class QSGImageNode; +class QSGNinePatchNode; class Q_QUICK_EXPORT QQuickWindow : public QWindow { @@ -159,6 +162,10 @@ public: static void setSceneGraphBackend(QSGRendererInterface::GraphicsApi api); static void setSceneGraphBackend(const QString &backend); + QSGRectangleNode *createRectangleNode() const; + QSGImageNode *createImageNode() const; + QSGNinePatchNode *createNinePatchNode() const; + Q_SIGNALS: void frameSwapped(); Q_REVISION(2) void openglContextCreated(QOpenGLContext *context); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index 15bc32ecb2..921071e32e 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -39,12 +39,12 @@ #include "qsgsoftwarecontext_p.h" -#include "qsgsoftwarerectanglenode_p.h" -#include "qsgsoftwareimagenode_p.h" +#include "qsgsoftwareinternalrectanglenode_p.h" +#include "qsgsoftwareinternalimagenode_p.h" #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" #include "qsgsoftwareglyphnode_p.h" -#include "qsgsoftwareninepatchnode_p.h" +#include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarelayer_p.h" #include "qsgsoftwarerenderer_p.h" @@ -53,11 +53,6 @@ #include -#include -#include -#include -#include - // Used for very high-level info about the renderering and gl context // Includes GL_VERSION, type of render loop, atlas size, etc. Q_LOGGING_CATEGORY(QSG_RASTER_LOG_INFO, "qt.scenegraph.info") @@ -93,14 +88,14 @@ QSGSoftwareContext::QSGSoftwareContext(QObject *parent) { } -QSGRectangleNode *QSGSoftwareContext::createRectangleNode() +QSGInternalRectangleNode *QSGSoftwareContext::createInternalRectangleNode() { - return new QSGSoftwareRectangleNode(); + return new QSGSoftwareInternalRectangleNode(); } -QSGImageNode *QSGSoftwareContext::createImageNode() +QSGInternalImageNode *QSGSoftwareContext::createInternalImageNode() { - return new QSGSoftwareImageNode(); + return new QSGSoftwareInternalImageNode(); } QSGPainterNode *QSGSoftwareContext::createPainterNode(QQuickPaintedItem *item) @@ -115,11 +110,6 @@ QSGGlyphNode *QSGSoftwareContext::createGlyphNode(QSGRenderContext *rc, bool pre return new QSGSoftwareGlyphNode(); } -QSGNinePatchNode *QSGSoftwareContext::createNinePatchNode() -{ - return new QSGSoftwareNinePatchNode(); -} - QSGLayer *QSGSoftwareContext::createLayer(QSGRenderContext *renderContext) { return new QSGSoftwareLayer(renderContext); @@ -169,6 +159,21 @@ QSGRendererInterface *QSGSoftwareContext::rendererInterface(QSGRenderContext *re return this; } +QSGRectangleNode *QSGSoftwareContext::createRectangleNode() +{ + return new QSGSoftwareRectangleNode; +} + +QSGImageNode *QSGSoftwareContext::createImageNode() +{ + return new QSGSoftwareImageNode; +} + +QSGNinePatchNode *QSGSoftwareContext::createNinePatchNode() +{ + return new QSGSoftwareNinePatchNode; +} + QSGRendererInterface::GraphicsApi QSGSoftwareContext::graphicsApi() const { return Software; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h index 992f6f5677..9a939a0948 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h @@ -86,14 +86,16 @@ public: explicit QSGSoftwareContext(QObject *parent = nullptr); QSGRenderContext *createRenderContext() override { return new QSGSoftwareRenderContext(this); } - QSGRectangleNode *createRectangleNode() override; - QSGImageNode *createImageNode() override; + QSGInternalRectangleNode *createInternalRectangleNode() override; + QSGInternalImageNode *createInternalImageNode() override; QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override; QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) override; - QSGNinePatchNode *createNinePatchNode() override; QSGLayer *createLayer(QSGRenderContext *renderContext) override; QSurfaceFormat defaultSurfaceFormat() const override; QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext) override; + QSGRectangleNode *createRectangleNode() override; + QSGImageNode *createImageNode() override; + QSGNinePatchNode *createNinePatchNode() override; GraphicsApi graphicsApi() const override; ShaderType shaderType() const override; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode.cpp deleted file mode 100644 index c92a032623..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgsoftwareimagenode_p.h" - -#include "qsgsoftwarepixmaptexture_p.h" -#include "qsgsoftwarelayer_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -namespace QSGSoftwareHelpers { -// Helper from widgets/styles/qdrawutil.cpp - -static inline QMargins normalizedMargins(const QMargins &m) -{ - return QMargins(qMax(m.left(), 0), qMax(m.top(), 0), qMax(m.right(), 0), qMax(m.bottom(), 0)); -} - -void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMarginsIn, - const QPixmap &pixmap, const QRect &sourceRect, const QMargins &sourceMarginsIn, - const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) -{ - QPainter::PixmapFragment d; - d.opacity = 1.0; - d.rotation = 0.0; - - QPixmapFragmentsArray opaqueData; - QPixmapFragmentsArray translucentData; - - QMargins sourceMargins = normalizedMargins(sourceMarginsIn); - QMargins targetMargins = normalizedMargins(targetMarginsIn); - - // source center - const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); - const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); - const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1; - const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1; - const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft; - const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop; - // target center - const int targetCenterTop = targetRect.top() + targetMargins.top(); - const int targetCenterLeft = targetRect.left() + targetMargins.left(); - const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1; - const int targetCenterRight = targetRect.right() - targetMargins.right() + 1; - const int targetCenterWidth = targetCenterRight - targetCenterLeft; - const int targetCenterHeight = targetCenterBottom - targetCenterTop; - - QVarLengthArray xTarget; // x-coordinates of target rectangles - QVarLengthArray yTarget; // y-coordinates of target rectangles - - int columns = 3; - int rows = 3; - if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) - columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth))); - if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) - rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight))); - - xTarget.resize(columns + 1); - yTarget.resize(rows + 1); - - bool oldAA = painter->testRenderHint(QPainter::Antialiasing); - if (painter->paintEngine()->type() != QPaintEngine::OpenGL - && painter->paintEngine()->type() != QPaintEngine::OpenGL2 - && oldAA && painter->combinedTransform().type() != QTransform::TxNone) { - painter->setRenderHint(QPainter::Antialiasing, false); - } - - xTarget[0] = targetRect.left(); - xTarget[1] = targetCenterLeft; - xTarget[columns - 1] = targetCenterRight; - xTarget[columns] = targetRect.left() + targetRect.width(); - - yTarget[0] = targetRect.top(); - yTarget[1] = targetCenterTop; - yTarget[rows - 1] = targetCenterBottom; - yTarget[rows] = targetRect.top() + targetRect.height(); - - qreal dx = targetCenterWidth; - qreal dy = targetCenterHeight; - - switch (rules.horizontal) { - case Qt::StretchTile: - dx = targetCenterWidth; - break; - case Qt::RepeatTile: - dx = sourceCenterWidth; - break; - case Qt::RoundTile: - dx = targetCenterWidth / qreal(columns - 2); - break; - } - - for (int i = 2; i < columns - 1; ++i) - xTarget[i] = xTarget[i - 1] + dx; - - switch (rules.vertical) { - case Qt::StretchTile: - dy = targetCenterHeight; - break; - case Qt::RepeatTile: - dy = sourceCenterHeight; - break; - case Qt::RoundTile: - dy = targetCenterHeight / qreal(rows - 2); - break; - } - - for (int i = 2; i < rows - 1; ++i) - yTarget[i] = yTarget[i - 1] + dy; - - // corners - if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceRect.top(); - d.width = sourceMargins.left(); - d.height = sourceMargins.top(); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueTopLeft) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceRect.top(); - d.width = sourceMargins.right(); - d.height = sourceMargins.top(); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueTopRight) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceCenterBottom; - d.width = sourceMargins.left(); - d.height = sourceMargins.bottom(); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueBottomLeft) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceCenterBottom; - d.width = sourceMargins.right(); - d.height = sourceMargins.bottom(); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueBottomRight) - opaqueData.append(d); - else - translucentData.append(d); - } - - // horizontal edges - if (targetCenterWidth > 0 && sourceCenterWidth > 0) { - if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceRect.top(); - d.width = sourceCenterWidth; - d.height = sourceMargins.top(); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.scaleX = dx / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); - } - if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceCenterBottom; - d.width = sourceCenterWidth; - d.height = sourceMargins.bottom(); - d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.scaleX = dx / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); - } - } - - // vertical edges - if (targetCenterHeight > 0 && sourceCenterHeight > 0) { - if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData; - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceCenterTop; - d.width = sourceMargins.left(); - d.height = sourceCenterHeight; - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = dy / d.height; - for (int i = 1; i < rows - 1; ++i) { - d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); - data.append(d); - } - if (rules.vertical == Qt::RepeatTile) - data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); - } - if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData; - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceCenterTop; - d.width = sourceMargins.right(); - d.height = sourceCenterHeight; - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = dy / d.height; - for (int i = 1; i < rows - 1; ++i) { - d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); - data.append(d); - } - if (rules.vertical == Qt::RepeatTile) - data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); - } - } - - // center - if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceCenterTop; - d.width = sourceCenterWidth; - d.height = sourceCenterHeight; - d.scaleX = dx / d.width; - d.scaleY = dy / d.height; - - qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX; - qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY; - - for (int j = 1; j < rows - 1; ++j) { - d.y = (0.5 * (yTarget[j + 1] + yTarget[j])); - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = repeatWidth; - } - if (rules.vertical == Qt::RepeatTile) { - for (int i = 1; i < columns - 1; ++i) - data[data.size() - i].height = repeatHeight; - } - } - - if (opaqueData.size()) - painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint); - if (translucentData.size()) - painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap); - - if (oldAA) - painter->setRenderHint(QPainter::Antialiasing, true); -} - -} // QSGSoftwareHelpers namespace - -QSGSoftwareImageNode::QSGSoftwareImageNode() - : m_innerSourceRect(0, 0, 1, 1) - , m_subSourceRect(0, 0, 1, 1) - , m_texture(0) - , m_mirror(false) - , m_smooth(true) - , m_tileHorizontal(false) - , m_tileVertical(false) - , m_cachedMirroredPixmapIsDirty(false) -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - - -void QSGSoftwareImageNode::setTargetRect(const QRectF &rect) -{ - if (rect == m_targetRect) - return; - m_targetRect = rect; - markDirty(DirtyGeometry); -} - -void QSGSoftwareImageNode::setInnerTargetRect(const QRectF &rect) -{ - if (rect == m_innerTargetRect) - return; - m_innerTargetRect = rect; - markDirty(DirtyGeometry); -} - -void QSGSoftwareImageNode::setInnerSourceRect(const QRectF &rect) -{ - if (rect == m_innerSourceRect) - return; - m_innerSourceRect = rect; - markDirty(DirtyGeometry); -} - -void QSGSoftwareImageNode::setSubSourceRect(const QRectF &rect) -{ - if (rect == m_subSourceRect) - return; - m_subSourceRect = rect; - markDirty(DirtyGeometry); -} - -void QSGSoftwareImageNode::setTexture(QSGTexture *texture) -{ - m_texture = texture; - m_cachedMirroredPixmapIsDirty = true; - markDirty(DirtyMaterial); -} - -void QSGSoftwareImageNode::setMirror(bool mirror) -{ - if (m_mirror != mirror) { - m_mirror = mirror; - m_cachedMirroredPixmapIsDirty = true; - markDirty(DirtyMaterial); - } -} - -void QSGSoftwareImageNode::setMipmapFiltering(QSGTexture::Filtering /*filtering*/) -{ -} - -void QSGSoftwareImageNode::setFiltering(QSGTexture::Filtering filtering) -{ - bool smooth = (filtering == QSGTexture::Linear); - if (smooth == m_smooth) - return; - - m_smooth = smooth; - markDirty(DirtyMaterial); -} - -void QSGSoftwareImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) -{ - bool tileHorizontal = (wrapMode == QSGTexture::Repeat); - if (tileHorizontal == m_tileHorizontal) - return; - - m_tileHorizontal = tileHorizontal; - markDirty(DirtyMaterial); -} - -void QSGSoftwareImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) -{ - bool tileVertical = (wrapMode == QSGTexture::Repeat); - if (tileVertical == m_tileVertical) - return; - - m_tileVertical = (wrapMode == QSGTexture::Repeat); - markDirty(DirtyMaterial); -} - -void QSGSoftwareImageNode::update() -{ - if (m_cachedMirroredPixmapIsDirty) { - if (m_mirror) { - m_cachedMirroredPixmap = pixmap().transformed(QTransform(-1, 0, 0, 1, 0, 0)); - } else { - //Cleanup cached pixmap if necessary - if (!m_cachedMirroredPixmap.isNull()) - m_cachedMirroredPixmap = QPixmap(); - } - m_cachedMirroredPixmapIsDirty = false; - } -} - -void QSGSoftwareImageNode::preprocess() -{ - bool doDirty = false; - QSGLayer *t = qobject_cast(m_texture); - if (t) { - doDirty = t->updateTexture(); - markDirty(DirtyGeometry); - } - if (doDirty) - markDirty(DirtyMaterial); -} - -static Qt::TileRule getTileRule(qreal factor) -{ - int ifactor = qRound(factor); - if (qFuzzyCompare(factor, ifactor )) { - if (ifactor == 1 || ifactor == 0) - return Qt::StretchTile; - return Qt::RoundTile; - } - return Qt::RepeatTile; -} - - -void QSGSoftwareImageNode::paint(QPainter *painter) -{ - painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth); - - const QPixmap &pm = m_mirror ? m_cachedMirroredPixmap : pixmap(); - - if (m_innerTargetRect != m_targetRect) { - // border image - QMargins margins(m_innerTargetRect.left() - m_targetRect.left(), m_innerTargetRect.top() - m_targetRect.top(), - m_targetRect.right() - m_innerTargetRect.right(), m_targetRect.bottom() - m_innerTargetRect.bottom()); - QSGSoftwareHelpers::QTileRules tilerules(getTileRule(m_subSourceRect.width()), getTileRule(m_subSourceRect.height())); - QSGSoftwareHelpers::qDrawBorderPixmap(painter, m_targetRect.toRect(), margins, pm, QRect(0, 0, pm.width(), pm.height()), - margins, tilerules, QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints(0)); - return; - } - - if (m_tileHorizontal || m_tileVertical) { - painter->save(); - qreal sx = m_targetRect.width()/(m_subSourceRect.width()*pm.width()); - qreal sy = m_targetRect.height()/(m_subSourceRect.height()*pm.height()); - QMatrix transform(sx, 0, 0, sy, 0, 0); - painter->setMatrix(transform, true); - painter->drawTiledPixmap(QRectF(m_targetRect.x()/sx, m_targetRect.y()/sy, m_targetRect.width()/sx, m_targetRect.height()/sy), - pm, - QPointF(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height())); - painter->restore(); - } else { - QRectF sr(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height(), - m_subSourceRect.width()*pm.width(), m_subSourceRect.height()*pm.height()); - painter->drawPixmap(m_targetRect, pm, sr); - } -} - -QRectF QSGSoftwareImageNode::rect() const -{ - return m_targetRect; -} - -const QPixmap &QSGSoftwareImageNode::pixmap() const -{ - if (QSGSoftwarePixmapTexture *pt = qobject_cast(m_texture)) { - return pt->pixmap(); - } else { - QSGSoftwareLayer *layer = qobject_cast(m_texture); - return layer->pixmap(); - } -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode_p.h deleted file mode 100644 index e42f616757..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareimagenode_p.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSGSOFTWAREIMAGENODE_H -#define QSGSOFTWAREIMAGENODE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -namespace QSGSoftwareHelpers { - -typedef QVarLengthArray QPixmapFragmentsArray; - -struct QTileRules -{ - inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) - : horizontal(horizontalRule), vertical(verticalRule) {} - inline QTileRules(Qt::TileRule rule = Qt::StretchTile) - : horizontal(rule), vertical(rule) {} - Qt::TileRule horizontal; - Qt::TileRule vertical; -}; - -#ifndef Q_QDOC -// For internal use only. -namespace QDrawBorderPixmap -{ - enum DrawingHint - { - OpaqueTopLeft = 0x0001, - OpaqueTop = 0x0002, - OpaqueTopRight = 0x0004, - OpaqueLeft = 0x0008, - OpaqueCenter = 0x0010, - OpaqueRight = 0x0020, - OpaqueBottomLeft = 0x0040, - OpaqueBottom = 0x0080, - OpaqueBottomRight = 0x0100, - OpaqueCorners = OpaqueTopLeft | OpaqueTopRight | OpaqueBottomLeft | OpaqueBottomRight, - OpaqueEdges = OpaqueTop | OpaqueLeft | OpaqueRight | OpaqueBottom, - OpaqueFrame = OpaqueCorners | OpaqueEdges, - OpaqueAll = OpaqueCenter | OpaqueFrame - }; - - Q_DECLARE_FLAGS(DrawingHints, DrawingHint) -} -#endif - -void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, - const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, - const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints); - -} // QSGSoftwareHelpers namespace - -class QSGSoftwareImageNode : public QSGImageNode -{ -public: - QSGSoftwareImageNode(); - - void setTargetRect(const QRectF &rect) override; - void setInnerTargetRect(const QRectF &rect) override; - void setInnerSourceRect(const QRectF &rect) override; - void setSubSourceRect(const QRectF &rect) override; - void setTexture(QSGTexture *texture) override; - void setMirror(bool mirror) override; - void setMipmapFiltering(QSGTexture::Filtering filtering) override; - void setFiltering(QSGTexture::Filtering filtering) override; - void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; - void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; - void update() override; - - void preprocess() override; - - void paint(QPainter *painter); - - QRectF rect() const; - -private: - const QPixmap &pixmap() const; - - QRectF m_targetRect; - QRectF m_innerTargetRect; - QRectF m_innerSourceRect; - QRectF m_subSourceRect; - - QSGTexture *m_texture; - QPixmap m_cachedMirroredPixmap; - - bool m_mirror; - bool m_smooth; - bool m_tileHorizontal; - bool m_tileVertical; - bool m_cachedMirroredPixmapIsDirty; -}; - -QT_END_NAMESPACE - -#endif // QSGSOFTWAREIMAGENODE_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp new file mode 100644 index 0000000000..10291b9cb5 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp @@ -0,0 +1,501 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgsoftwareinternalimagenode_p.h" + +#include "qsgsoftwarepixmaptexture_p.h" +#include "qsgsoftwarelayer_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QSGSoftwareHelpers { +// Helper from widgets/styles/qdrawutil.cpp + +static inline QMargins normalizedMargins(const QMargins &m) +{ + return QMargins(qMax(m.left(), 0), qMax(m.top(), 0), qMax(m.right(), 0), qMax(m.bottom(), 0)); +} + +void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMarginsIn, + const QPixmap &pixmap, const QRect &sourceRect, const QMargins &sourceMarginsIn, + const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) +{ + QPainter::PixmapFragment d; + d.opacity = 1.0; + d.rotation = 0.0; + + QPixmapFragmentsArray opaqueData; + QPixmapFragmentsArray translucentData; + + QMargins sourceMargins = normalizedMargins(sourceMarginsIn); + QMargins targetMargins = normalizedMargins(targetMarginsIn); + + // source center + const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); + const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); + const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1; + const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1; + const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft; + const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop; + // target center + const int targetCenterTop = targetRect.top() + targetMargins.top(); + const int targetCenterLeft = targetRect.left() + targetMargins.left(); + const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1; + const int targetCenterRight = targetRect.right() - targetMargins.right() + 1; + const int targetCenterWidth = targetCenterRight - targetCenterLeft; + const int targetCenterHeight = targetCenterBottom - targetCenterTop; + + QVarLengthArray xTarget; // x-coordinates of target rectangles + QVarLengthArray yTarget; // y-coordinates of target rectangles + + int columns = 3; + int rows = 3; + if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) + columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth))); + if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) + rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight))); + + xTarget.resize(columns + 1); + yTarget.resize(rows + 1); + + bool oldAA = painter->testRenderHint(QPainter::Antialiasing); + if (painter->paintEngine()->type() != QPaintEngine::OpenGL + && painter->paintEngine()->type() != QPaintEngine::OpenGL2 + && oldAA && painter->combinedTransform().type() != QTransform::TxNone) { + painter->setRenderHint(QPainter::Antialiasing, false); + } + + xTarget[0] = targetRect.left(); + xTarget[1] = targetCenterLeft; + xTarget[columns - 1] = targetCenterRight; + xTarget[columns] = targetRect.left() + targetRect.width(); + + yTarget[0] = targetRect.top(); + yTarget[1] = targetCenterTop; + yTarget[rows - 1] = targetCenterBottom; + yTarget[rows] = targetRect.top() + targetRect.height(); + + qreal dx = targetCenterWidth; + qreal dy = targetCenterHeight; + + switch (rules.horizontal) { + case Qt::StretchTile: + dx = targetCenterWidth; + break; + case Qt::RepeatTile: + dx = sourceCenterWidth; + break; + case Qt::RoundTile: + dx = targetCenterWidth / qreal(columns - 2); + break; + } + + for (int i = 2; i < columns - 1; ++i) + xTarget[i] = xTarget[i - 1] + dx; + + switch (rules.vertical) { + case Qt::StretchTile: + dy = targetCenterHeight; + break; + case Qt::RepeatTile: + dy = sourceCenterHeight; + break; + case Qt::RoundTile: + dy = targetCenterHeight / qreal(rows - 2); + break; + } + + for (int i = 2; i < rows - 1; ++i) + yTarget[i] = yTarget[i - 1] + dy; + + // corners + if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceRect.top(); + d.width = sourceMargins.left(); + d.height = sourceMargins.top(); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueTopLeft) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceRect.top(); + d.width = sourceMargins.right(); + d.height = sourceMargins.top(); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueTopRight) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceCenterBottom; + d.width = sourceMargins.left(); + d.height = sourceMargins.bottom(); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueBottomLeft) + opaqueData.append(d); + else + translucentData.append(d); + } + if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceCenterBottom; + d.width = sourceMargins.right(); + d.height = sourceMargins.bottom(); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + if (hints & QDrawBorderPixmap::OpaqueBottomRight) + opaqueData.append(d); + else + translucentData.append(d); + } + + // horizontal edges + if (targetCenterWidth > 0 && sourceCenterWidth > 0) { + if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceRect.top(); + d.width = sourceCenterWidth; + d.height = sourceMargins.top(); + d.y = (0.5 * (yTarget[1] + yTarget[0])); + d.scaleX = dx / d.width; + d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); + } + if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceCenterBottom; + d.width = sourceCenterWidth; + d.height = sourceMargins.bottom(); + d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); + d.scaleX = dx / d.width; + d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); + } + } + + // vertical edges + if (targetCenterHeight > 0 && sourceCenterHeight > 0) { + if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData; + d.sourceLeft = sourceRect.left(); + d.sourceTop = sourceCenterTop; + d.width = sourceMargins.left(); + d.height = sourceCenterHeight; + d.x = (0.5 * (xTarget[1] + xTarget[0])); + d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; + d.scaleY = dy / d.height; + for (int i = 1; i < rows - 1; ++i) { + d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); + data.append(d); + } + if (rules.vertical == Qt::RepeatTile) + data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); + } + if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData; + d.sourceLeft = sourceCenterRight; + d.sourceTop = sourceCenterTop; + d.width = sourceMargins.right(); + d.height = sourceCenterHeight; + d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); + d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; + d.scaleY = dy / d.height; + for (int i = 1; i < rows - 1; ++i) { + d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); + data.append(d); + } + if (rules.vertical == Qt::RepeatTile) + data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); + } + } + + // center + if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { + QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData; + d.sourceLeft = sourceCenterLeft; + d.sourceTop = sourceCenterTop; + d.width = sourceCenterWidth; + d.height = sourceCenterHeight; + d.scaleX = dx / d.width; + d.scaleY = dy / d.height; + + qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX; + qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY; + + for (int j = 1; j < rows - 1; ++j) { + d.y = (0.5 * (yTarget[j + 1] + yTarget[j])); + for (int i = 1; i < columns - 1; ++i) { + d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); + data.append(d); + } + if (rules.horizontal == Qt::RepeatTile) + data[data.size() - 1].width = repeatWidth; + } + if (rules.vertical == Qt::RepeatTile) { + for (int i = 1; i < columns - 1; ++i) + data[data.size() - i].height = repeatHeight; + } + } + + if (opaqueData.size()) + painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint); + if (translucentData.size()) + painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap); + + if (oldAA) + painter->setRenderHint(QPainter::Antialiasing, true); +} + +} // QSGSoftwareHelpers namespace + +QSGSoftwareInternalImageNode::QSGSoftwareInternalImageNode() + : m_innerSourceRect(0, 0, 1, 1) + , m_subSourceRect(0, 0, 1, 1) + , m_texture(0) + , m_mirror(false) + , m_smooth(true) + , m_tileHorizontal(false) + , m_tileVertical(false) + , m_cachedMirroredPixmapIsDirty(false) +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + + +void QSGSoftwareInternalImageNode::setTargetRect(const QRectF &rect) +{ + if (rect == m_targetRect) + return; + m_targetRect = rect; + markDirty(DirtyGeometry); +} + +void QSGSoftwareInternalImageNode::setInnerTargetRect(const QRectF &rect) +{ + if (rect == m_innerTargetRect) + return; + m_innerTargetRect = rect; + markDirty(DirtyGeometry); +} + +void QSGSoftwareInternalImageNode::setInnerSourceRect(const QRectF &rect) +{ + if (rect == m_innerSourceRect) + return; + m_innerSourceRect = rect; + markDirty(DirtyGeometry); +} + +void QSGSoftwareInternalImageNode::setSubSourceRect(const QRectF &rect) +{ + if (rect == m_subSourceRect) + return; + m_subSourceRect = rect; + markDirty(DirtyGeometry); +} + +void QSGSoftwareInternalImageNode::setTexture(QSGTexture *texture) +{ + m_texture = texture; + m_cachedMirroredPixmapIsDirty = true; + markDirty(DirtyMaterial); +} + +void QSGSoftwareInternalImageNode::setMirror(bool mirror) +{ + if (m_mirror != mirror) { + m_mirror = mirror; + m_cachedMirroredPixmapIsDirty = true; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareInternalImageNode::setMipmapFiltering(QSGTexture::Filtering /*filtering*/) +{ +} + +void QSGSoftwareInternalImageNode::setFiltering(QSGTexture::Filtering filtering) +{ + bool smooth = (filtering == QSGTexture::Linear); + if (smooth == m_smooth) + return; + + m_smooth = smooth; + markDirty(DirtyMaterial); +} + +void QSGSoftwareInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) +{ + bool tileHorizontal = (wrapMode == QSGTexture::Repeat); + if (tileHorizontal == m_tileHorizontal) + return; + + m_tileHorizontal = tileHorizontal; + markDirty(DirtyMaterial); +} + +void QSGSoftwareInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) +{ + bool tileVertical = (wrapMode == QSGTexture::Repeat); + if (tileVertical == m_tileVertical) + return; + + m_tileVertical = (wrapMode == QSGTexture::Repeat); + markDirty(DirtyMaterial); +} + +void QSGSoftwareInternalImageNode::update() +{ + if (m_cachedMirroredPixmapIsDirty) { + if (m_mirror) { + m_cachedMirroredPixmap = pixmap().transformed(QTransform(-1, 0, 0, 1, 0, 0)); + } else { + //Cleanup cached pixmap if necessary + if (!m_cachedMirroredPixmap.isNull()) + m_cachedMirroredPixmap = QPixmap(); + } + m_cachedMirroredPixmapIsDirty = false; + } +} + +void QSGSoftwareInternalImageNode::preprocess() +{ + bool doDirty = false; + QSGLayer *t = qobject_cast(m_texture); + if (t) { + doDirty = t->updateTexture(); + markDirty(DirtyGeometry); + } + if (doDirty) + markDirty(DirtyMaterial); +} + +static Qt::TileRule getTileRule(qreal factor) +{ + int ifactor = qRound(factor); + if (qFuzzyCompare(factor, ifactor )) { + if (ifactor == 1 || ifactor == 0) + return Qt::StretchTile; + return Qt::RoundTile; + } + return Qt::RepeatTile; +} + + +void QSGSoftwareInternalImageNode::paint(QPainter *painter) +{ + painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth); + + const QPixmap &pm = m_mirror ? m_cachedMirroredPixmap : pixmap(); + + if (m_innerTargetRect != m_targetRect) { + // border image + QMargins margins(m_innerTargetRect.left() - m_targetRect.left(), m_innerTargetRect.top() - m_targetRect.top(), + m_targetRect.right() - m_innerTargetRect.right(), m_targetRect.bottom() - m_innerTargetRect.bottom()); + QSGSoftwareHelpers::QTileRules tilerules(getTileRule(m_subSourceRect.width()), getTileRule(m_subSourceRect.height())); + QSGSoftwareHelpers::qDrawBorderPixmap(painter, m_targetRect.toRect(), margins, pm, QRect(0, 0, pm.width(), pm.height()), + margins, tilerules, QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints(0)); + return; + } + + if (m_tileHorizontal || m_tileVertical) { + painter->save(); + qreal sx = m_targetRect.width()/(m_subSourceRect.width()*pm.width()); + qreal sy = m_targetRect.height()/(m_subSourceRect.height()*pm.height()); + QMatrix transform(sx, 0, 0, sy, 0, 0); + painter->setMatrix(transform, true); + painter->drawTiledPixmap(QRectF(m_targetRect.x()/sx, m_targetRect.y()/sy, m_targetRect.width()/sx, m_targetRect.height()/sy), + pm, + QPointF(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height())); + painter->restore(); + } else { + QRectF sr(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height(), + m_subSourceRect.width()*pm.width(), m_subSourceRect.height()*pm.height()); + painter->drawPixmap(m_targetRect, pm, sr); + } +} + +QRectF QSGSoftwareInternalImageNode::rect() const +{ + return m_targetRect; +} + +const QPixmap &QSGSoftwareInternalImageNode::pixmap() const +{ + if (QSGSoftwarePixmapTexture *pt = qobject_cast(m_texture)) { + return pt->pixmap(); + } else { + QSGSoftwareLayer *layer = qobject_cast(m_texture); + return layer->pixmap(); + } +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h new file mode 100644 index 0000000000..f21667fdf7 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGSOFTWAREINTERNALIMAGENODE_H +#define QSGSOFTWAREINTERNALIMAGENODE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QSGSoftwareHelpers { + +typedef QVarLengthArray QPixmapFragmentsArray; + +struct QTileRules +{ + inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) + : horizontal(horizontalRule), vertical(verticalRule) {} + inline QTileRules(Qt::TileRule rule = Qt::StretchTile) + : horizontal(rule), vertical(rule) {} + Qt::TileRule horizontal; + Qt::TileRule vertical; +}; + +#ifndef Q_QDOC +// For internal use only. +namespace QDrawBorderPixmap +{ + enum DrawingHint + { + OpaqueTopLeft = 0x0001, + OpaqueTop = 0x0002, + OpaqueTopRight = 0x0004, + OpaqueLeft = 0x0008, + OpaqueCenter = 0x0010, + OpaqueRight = 0x0020, + OpaqueBottomLeft = 0x0040, + OpaqueBottom = 0x0080, + OpaqueBottomRight = 0x0100, + OpaqueCorners = OpaqueTopLeft | OpaqueTopRight | OpaqueBottomLeft | OpaqueBottomRight, + OpaqueEdges = OpaqueTop | OpaqueLeft | OpaqueRight | OpaqueBottom, + OpaqueFrame = OpaqueCorners | OpaqueEdges, + OpaqueAll = OpaqueCenter | OpaqueFrame + }; + + Q_DECLARE_FLAGS(DrawingHints, DrawingHint) +} +#endif + +void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, + const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, + const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints); + +} // QSGSoftwareHelpers namespace + +class QSGSoftwareInternalImageNode : public QSGInternalImageNode +{ +public: + QSGSoftwareInternalImageNode(); + + void setTargetRect(const QRectF &rect) override; + void setInnerTargetRect(const QRectF &rect) override; + void setInnerSourceRect(const QRectF &rect) override; + void setSubSourceRect(const QRectF &rect) override; + void setTexture(QSGTexture *texture) override; + void setMirror(bool mirror) override; + void setMipmapFiltering(QSGTexture::Filtering filtering) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; + void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; + void update() override; + + void preprocess() override; + + void paint(QPainter *painter); + + QRectF rect() const; + +private: + const QPixmap &pixmap() const; + + QRectF m_targetRect; + QRectF m_innerTargetRect; + QRectF m_innerSourceRect; + QRectF m_subSourceRect; + + QSGTexture *m_texture; + QPixmap m_cachedMirroredPixmap; + + bool m_mirror; + bool m_smooth; + bool m_tileHorizontal; + bool m_tileVertical; + bool m_cachedMirroredPixmapIsDirty; +}; + +QT_END_NAMESPACE + +#endif // QSGSOFTWAREINTERNALIMAGENODE_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp new file mode 100644 index 0000000000..ea5124edf9 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp @@ -0,0 +1,451 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgsoftwareinternalrectanglenode_p.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +QSGSoftwareInternalRectangleNode::QSGSoftwareInternalRectangleNode() + : m_penWidth(0) + , m_radius(0) + , m_cornerPixmapIsDirty(true) + , m_devicePixelRatio(1) +{ + m_pen.setJoinStyle(Qt::MiterJoin); + m_pen.setMiterLimit(0); + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void QSGSoftwareInternalRectangleNode::setRect(const QRectF &rect) +{ + QRect alignedRect = rect.toAlignedRect(); + if (m_rect != alignedRect) { + m_rect = alignedRect; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareInternalRectangleNode::setColor(const QColor &color) +{ + if (m_color != color) { + m_color = color; + m_cornerPixmapIsDirty = true; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareInternalRectangleNode::setPenColor(const QColor &color) +{ + if (m_penColor != color) { + m_penColor = color; + m_cornerPixmapIsDirty = true; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareInternalRectangleNode::setPenWidth(qreal width) +{ + if (m_penWidth != width) { + m_penWidth = width; + m_cornerPixmapIsDirty = true; + markDirty(DirtyMaterial); + } +} + +//Move first stop by pos relative to seconds +static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos) +{ + double distance = secondStop.first - firstStop.first; + double distanceDelta = newPos - firstStop.first; + double modifierValue = distanceDelta / distance; + int redDelta = (secondStop.second.red() - firstStop.second.red()) * modifierValue; + int greenDelta = (secondStop.second.green() - firstStop.second.green()) * modifierValue; + int blueDelta = (secondStop.second.blue() - firstStop.second.blue()) * modifierValue; + int alphaDelta = (secondStop.second.alpha() - firstStop.second.alpha()) * modifierValue; + + QGradientStop newStop; + newStop.first = newPos; + newStop.second = QColor(firstStop.second.red() + redDelta, + firstStop.second.green() + greenDelta, + firstStop.second.blue() + blueDelta, + firstStop.second.alpha() + alphaDelta); + + return newStop; +} + +void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &stops) +{ + //normalize stops + bool needsNormalization = false; + foreach (const QGradientStop &stop, stops) { + if (stop.first < 0.0 || stop.first > 1.0) { + needsNormalization = true; + continue; + } + } + + if (needsNormalization) { + QGradientStops normalizedStops; + if (stops.count() == 1) { + //If there is only one stop, then the position does not matter + //It is just treated as a color + QGradientStop stop = stops.at(0); + stop.first = 0.0; + normalizedStops.append(stop); + } else { + //Clip stops to only the first below 0.0 and above 1.0 + int below = -1; + int above = -1; + QVector between; + for (int i = 0; i < stops.count(); ++i) { + if (stops.at(i).first < 0.0) { + below = i; + } else if (stops.at(i).first > 1.0) { + above = i; + break; + } else { + between.append(i); + } + } + + //Interpoloate new color values for above and below + if (below != -1 ) { + //If there are more than one stops left, interpolate + if (below + 1 < stops.count()) { + normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0)); + } else { + QGradientStop singleStop; + singleStop.first = 0.0; + singleStop.second = stops.at(below).second; + normalizedStops.append(singleStop); + } + } + + for (int i = 0; i < between.count(); ++i) + normalizedStops.append(stops.at(between.at(i))); + + if (above != -1) { + //If there stops before above, interpolate + if (above >= 1) { + normalizedStops.append(interpolateStop(stops.at(above), stops.at(above - 1), 1.0)); + } else { + QGradientStop singleStop; + singleStop.first = 1.0; + singleStop.second = stops.at(above).second; + normalizedStops.append(singleStop); + } + } + } + + m_stops = normalizedStops; + + } else { + m_stops = stops; + } + m_cornerPixmapIsDirty = true; + markDirty(DirtyMaterial); +} + +void QSGSoftwareInternalRectangleNode::setRadius(qreal radius) +{ + if (m_radius != radius) { + m_radius = radius; + m_cornerPixmapIsDirty = true; + markDirty(DirtyMaterial); + } +} + +void QSGSoftwareInternalRectangleNode::setAligned(bool /*aligned*/) +{ +} + +void QSGSoftwareInternalRectangleNode::update() +{ + if (!m_penWidth || m_penColor == Qt::transparent) { + m_pen = Qt::NoPen; + } else { + m_pen = QPen(m_penColor); + m_pen.setWidthF(m_penWidth); + } + + if (!m_stops.isEmpty()) { + QLinearGradient gradient(QPoint(0,0), QPoint(0,1)); + gradient.setStops(m_stops); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + m_brush = QBrush(gradient); + } else { + m_brush = QBrush(m_color); + } + + if (m_cornerPixmapIsDirty) { + generateCornerPixmap(); + m_cornerPixmapIsDirty = false; + } +} + +void QSGSoftwareInternalRectangleNode::paint(QPainter *painter) +{ + //We can only check for a device pixel ratio change when we know what + //paint device is being used. + if (painter->device()->devicePixelRatio() != m_devicePixelRatio) { + m_devicePixelRatio = painter->device()->devicePixelRatio(); + generateCornerPixmap(); + } + + if (painter->transform().isRotating()) { + //Rotated rectangles lose the benefits of direct rendering, and have poor rendering + //quality when using only blits and fills. + + if (m_radius == 0 && m_penWidth == 0) { + //Non-Rounded Rects without borders (fall back to drawRect) + //Most common case + painter->setPen(Qt::NoPen); + painter->setBrush(m_brush); + painter->drawRect(m_rect); + } else { + //Rounded Rects and Rects with Borders + //Avoids broken behaviors of QPainter::drawRect/roundedRect + QPixmap pixmap = QPixmap(m_rect.width() * m_devicePixelRatio, m_rect.height() * m_devicePixelRatio); + pixmap.fill(Qt::transparent); + pixmap.setDevicePixelRatio(m_devicePixelRatio); + QPainter pixmapPainter(&pixmap); + paintRectangle(&pixmapPainter, QRect(0, 0, m_rect.width(), m_rect.height())); + + QPainter::RenderHints previousRenderHints = painter->renderHints(); + painter->setRenderHint(QPainter::SmoothPixmapTransform, true); + painter->drawPixmap(m_rect, pixmap); + painter->setRenderHints(previousRenderHints); + } + + + } else { + //Paint directly + paintRectangle(painter, m_rect); + } + +} + +bool QSGSoftwareInternalRectangleNode::isOpaque() const +{ + if (m_radius > 0.0f) + return false; + if (m_color.alpha() < 255) + return false; + if (m_penWidth > 0.0f && m_penColor.alpha() < 255) + return false; + if (m_stops.count() > 0) { + foreach (QGradientStop stop, m_stops) { + if (stop.second.alpha() < 255) + return false; + } + } + + return true; +} + +QRectF QSGSoftwareInternalRectangleNode::rect() const +{ + //TODO: double check that this is correct. + return m_rect; +} + +void QSGSoftwareInternalRectangleNode::paintRectangle(QPainter *painter, const QRect &rect) +{ + //Radius should never exceeds half of the width or half of the height + int radius = qFloor(qMin(qMin(rect.width(), rect.height()) * 0.5, m_radius)); + + QPainter::RenderHints previousRenderHints = painter->renderHints(); + painter->setRenderHint(QPainter::Antialiasing, false); + + if (m_penWidth > 0) { + //Fill border Rects + + //Borders can not be more than half the height/width of a rect + double borderWidth = qMin(m_penWidth, rect.width() * 0.5); + double borderHeight = qMin(m_penWidth, rect.height() * 0.5); + + + + if (borderWidth > radius) { + //4 Rects + QRectF borderTopOutside(QPointF(rect.x() + radius, rect.y()), + QPointF(rect.x() + rect.width() - radius, rect.y() + radius)); + QRectF borderTopInside(QPointF(rect.x() + borderWidth, rect.y() + radius), + QPointF(rect.x() + rect.width() - borderWidth, rect.y() + borderHeight)); + QRectF borderBottomOutside(QPointF(rect.x() + radius, rect.y() + rect.height() - radius), + QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height())); + QRectF borderBottomInside(QPointF(rect.x() + borderWidth, rect.y() + rect.height() - borderHeight), + QPointF(rect.x() + rect.width() - borderWidth, rect.y() + rect.height() - radius)); + + if (borderTopOutside.isValid()) + painter->fillRect(borderTopOutside, m_penColor); + if (borderTopInside.isValid()) + painter->fillRect(borderTopInside, m_penColor); + if (borderBottomOutside.isValid()) + painter->fillRect(borderBottomOutside, m_penColor); + if (borderBottomInside.isValid()) + painter->fillRect(borderBottomInside, m_penColor); + + } else { + //2 Rects + QRectF borderTop(QPointF(rect.x() + radius, rect.y()), + QPointF(rect.x() + rect.width() - radius, rect.y() + borderHeight)); + QRectF borderBottom(QPointF(rect.x() + radius, rect.y() + rect.height() - borderHeight), + QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height())); + if (borderTop.isValid()) + painter->fillRect(borderTop, m_penColor); + if (borderBottom.isValid()) + painter->fillRect(borderBottom, m_penColor); + } + QRectF borderLeft(QPointF(rect.x(), rect.y() + radius), + QPointF(rect.x() + borderWidth, rect.y() + rect.height() - radius)); + QRectF borderRight(QPointF(rect.x() + rect.width() - borderWidth, rect.y() + radius), + QPointF(rect.x() + rect.width(), rect.y() + rect.height() - radius)); + if (borderLeft.isValid()) + painter->fillRect(borderLeft, m_penColor); + if (borderRight.isValid()) + painter->fillRect(borderRight, m_penColor); + } + + + if (radius > 0) { + + if (radius * 2 >= rect.width() && radius * 2 >= rect.height()) { + //Blit whole pixmap for circles + painter->drawPixmap(rect, m_cornerPixmap, m_cornerPixmap.rect()); + } else { + + //blit 4 corners to border + int scaledRadius = radius * m_devicePixelRatio; + QRectF topLeftCorner(QPointF(rect.x(), rect.y()), + QPointF(rect.x() + radius, rect.y() + radius)); + painter->drawPixmap(topLeftCorner, m_cornerPixmap, QRectF(0, 0, scaledRadius, scaledRadius)); + QRectF topRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y()), + QPointF(rect.x() + rect.width(), rect.y() + radius)); + painter->drawPixmap(topRightCorner, m_cornerPixmap, QRectF(scaledRadius, 0, scaledRadius, scaledRadius)); + QRectF bottomLeftCorner(QPointF(rect.x(), rect.y() + rect.height() - radius), + QPointF(rect.x() + radius, rect.y() + rect.height())); + painter->drawPixmap(bottomLeftCorner, m_cornerPixmap, QRectF(0, scaledRadius, scaledRadius, scaledRadius)); + QRectF bottomRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height() - radius), + QPointF(rect.x() + rect.width(), rect.y() + rect.height())); + painter->drawPixmap(bottomRightCorner, m_cornerPixmap, QRectF(scaledRadius, scaledRadius, scaledRadius, scaledRadius)); + + } + + } + + QRectF brushRect = QRectF(rect).marginsRemoved(QMarginsF(m_penWidth, m_penWidth, m_penWidth, m_penWidth)); + if (brushRect.width() < 0) + brushRect.setWidth(0); + if (brushRect.height() < 0) + brushRect.setHeight(0); + double innerRectRadius = qMax(0.0, radius - m_penWidth); + + //If not completely transparent or has a gradient + if (m_color.alpha() > 0 || !m_stops.empty()) { + if (innerRectRadius > 0) { + //Rounded Rect + if (m_stops.empty()) { + //Rounded Rects without gradient need 3 blits + QRectF centerRect(QPointF(brushRect.x() + innerRectRadius, brushRect.y()), + QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + brushRect.height())); + painter->fillRect(centerRect, m_color); + QRectF leftRect(QPointF(brushRect.x(), brushRect.y() + innerRectRadius), + QPointF(brushRect.x() + innerRectRadius, brushRect.y() + brushRect.height() - innerRectRadius)); + painter->fillRect(leftRect, m_color); + QRectF rightRect(QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + innerRectRadius), + QPointF(brushRect.x() + brushRect.width(), brushRect.y() + brushRect.height() - innerRectRadius)); + painter->fillRect(rightRect, m_color); + } else { + //Rounded Rect with gradient (slow) + painter->setPen(Qt::NoPen); + painter->setBrush(m_brush); + painter->drawRoundedRect(brushRect, innerRectRadius, innerRectRadius); + } + } else { + //non-rounded rects only need 1 blit + painter->fillRect(brushRect, m_brush); + } + } + + painter->setRenderHints(previousRenderHints); +} + +void QSGSoftwareInternalRectangleNode::generateCornerPixmap() +{ + //Generate new corner Pixmap + int radius = qFloor(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius)); + + m_cornerPixmap = QPixmap(radius * 2 * m_devicePixelRatio, radius * 2 * m_devicePixelRatio); + m_cornerPixmap.setDevicePixelRatio(m_devicePixelRatio); + m_cornerPixmap.fill(Qt::transparent); + + if (radius > 0) { + QPainter cornerPainter(&m_cornerPixmap); + cornerPainter.setRenderHint(QPainter::Antialiasing); + cornerPainter.setCompositionMode(QPainter::CompositionMode_Source); + + //Paint outer cicle + if (m_penWidth > 0) { + cornerPainter.setPen(Qt::NoPen); + cornerPainter.setBrush(m_penColor); + cornerPainter.drawRoundedRect(QRectF(0, 0, radius * 2, radius *2), radius, radius); + } + + //Paint inner circle + if (radius > m_penWidth) { + cornerPainter.setPen(Qt::NoPen); + if (m_stops.isEmpty()) + cornerPainter.setBrush(m_brush); + else + cornerPainter.setBrush(Qt::transparent); + + QMarginsF adjustmentMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth); + QRectF cornerCircleRect = QRectF(0, 0, radius * 2, radius * 2).marginsRemoved(adjustmentMargins); + cornerPainter.drawRoundedRect(cornerCircleRect, radius, radius); + } + cornerPainter.end(); + } +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h new file mode 100644 index 0000000000..f363e279e1 --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGSOFTWAREINTERNALRECTANGLENODE_H +#define QSGSOFTWAREINTERNALRECTANGLENODE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSGSoftwareInternalRectangleNode : public QSGInternalRectangleNode +{ +public: + QSGSoftwareInternalRectangleNode(); + + void setRect(const QRectF &rect) override; + void setColor(const QColor &color) override; + void setPenColor(const QColor &color) override; + void setPenWidth(qreal width) override; + void setGradientStops(const QGradientStops &stops) override; + void setRadius(qreal radius) override; + void setAntialiasing(bool antialiasing) override { Q_UNUSED(antialiasing) } + void setAligned(bool aligned) override; + + void update() override; + + void paint(QPainter *); + + bool isOpaque() const; + QRectF rect() const; +private: + void paintRectangle(QPainter *painter, const QRect &rect); + void generateCornerPixmap(); + + QRect m_rect; + QColor m_color; + QColor m_penColor; + double m_penWidth; + QGradientStops m_stops; + double m_radius; + QPen m_pen; + QBrush m_brush; + + bool m_cornerPixmapIsDirty; + QPixmap m_cornerPixmap; + + int m_devicePixelRatio; +}; + +QT_END_NAMESPACE + +#endif // QSGSOFTWAREINTERNALRECTANGLENODE_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode.cpp deleted file mode 100644 index 36ff1f2229..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgsoftwareninepatchnode_p.h" -#include "qsgsoftwarepixmaptexture_p.h" -#include "qsgsoftwareimagenode_p.h" - -QT_BEGIN_NAMESPACE - -QSGSoftwareNinePatchNode::QSGSoftwareNinePatchNode() -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - -void QSGSoftwareNinePatchNode::setTexture(QSGTexture *texture) -{ - QSGSoftwarePixmapTexture *pt = qobject_cast(texture); - if (!pt) { - qWarning() << "Image used with invalid texture format."; - return; - } - m_pixmap = pt->pixmap(); - markDirty(DirtyMaterial); -} - -void QSGSoftwareNinePatchNode::setBounds(const QRectF &bounds) -{ - if (m_bounds == bounds) - return; - - m_bounds = bounds; - markDirty(DirtyGeometry); -} - -void QSGSoftwareNinePatchNode::setDevicePixelRatio(qreal ratio) -{ - if (m_pixelRatio == ratio) - return; - - m_pixelRatio = ratio; - markDirty(DirtyGeometry); -} - -void QSGSoftwareNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) -{ - QMargins margins(qRound(left), qRound(top), qRound(right), qRound(bottom)); - if (m_margins == margins) - return; - - m_margins = QMargins(qRound(left), qRound(top), qRound(right), qRound(bottom)); - markDirty(DirtyGeometry); -} - -void QSGSoftwareNinePatchNode::update() -{ -} - -void QSGSoftwareNinePatchNode::paint(QPainter *painter) -{ - if (m_margins.isNull()) - painter->drawPixmap(m_bounds, m_pixmap, QRectF(0, 0, m_pixmap.width(), m_pixmap.height())); - else - QSGSoftwareHelpers::qDrawBorderPixmap(painter, m_bounds.toRect(), m_margins, m_pixmap, QRect(0, 0, m_pixmap.width(), m_pixmap.height()), - m_margins, Qt::StretchTile, QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints(0)); -} - -QRectF QSGSoftwareNinePatchNode::bounds() const -{ - return m_bounds; -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode_p.h deleted file mode 100644 index bc7aec1b5a..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareninepatchnode_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSGSOFTWARENINEPATCHNODE_H -#define QSGSOFTWARENINEPATCHNODE_H - -#include - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_NAMESPACE - -class QSGSoftwareNinePatchNode : public QSGNinePatchNode -{ -public: - QSGSoftwareNinePatchNode(); - - void setTexture(QSGTexture *texture) override; - void setBounds(const QRectF &bounds) override; - void setDevicePixelRatio(qreal ratio) override; - void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; - void update() override; - - void paint(QPainter *painter); - - QRectF bounds() const; - -private: - QPixmap m_pixmap; - QRectF m_bounds; - qreal m_pixelRatio; - QMargins m_margins; -}; - -QT_END_NAMESPACE - -#endif // QSGSOFTWARENINEPATCHNODE_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp new file mode 100644 index 0000000000..53974a77bf --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgsoftwarepublicnodes_p.h" +#include "qsgsoftwarepixmaptexture_p.h" +#include "qsgsoftwareinternalimagenode_p.h" + +QT_BEGIN_NAMESPACE + +QSGSoftwareRectangleNode::QSGSoftwareRectangleNode() + : m_color(QColor(255, 255, 255)) +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void QSGSoftwareRectangleNode::paint(QPainter *painter) +{ + painter->fillRect(m_rect, m_color); +} + +QSGSoftwareImageNode::QSGSoftwareImageNode() + : m_texture(nullptr), + m_owns(false) +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +QSGSoftwareImageNode::~QSGSoftwareImageNode() +{ + if (m_owns) + delete m_texture; +} + +void QSGSoftwareImageNode::paint(QPainter *painter) +{ + if (QSGSoftwarePixmapTexture *pt = dynamic_cast(m_texture)) { + const QPixmap &pm = pt->pixmap(); + painter->drawPixmap(m_rect, pm, QRectF(0, 0, pm.width(), pm.height())); + } else if (QSGPlainTexture *pt = dynamic_cast(m_texture)) { + const QImage &im = pt->image(); + painter->drawImage(m_rect, im, QRectF(0, 0, im.width(), im.height())); + } +} + +QSGSoftwareNinePatchNode::QSGSoftwareNinePatchNode() +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void QSGSoftwareNinePatchNode::setTexture(QSGTexture *texture) +{ + QSGSoftwarePixmapTexture *pt = qobject_cast(texture); + if (!pt) { + qWarning() << "Image used with invalid texture format."; + return; + } + m_pixmap = pt->pixmap(); + markDirty(DirtyMaterial); +} + +void QSGSoftwareNinePatchNode::setBounds(const QRectF &bounds) +{ + if (m_bounds == bounds) + return; + + m_bounds = bounds; + markDirty(DirtyGeometry); +} + +void QSGSoftwareNinePatchNode::setDevicePixelRatio(qreal ratio) +{ + if (m_pixelRatio == ratio) + return; + + m_pixelRatio = ratio; + markDirty(DirtyGeometry); +} + +void QSGSoftwareNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) +{ + QMargins margins(qRound(left), qRound(top), qRound(right), qRound(bottom)); + if (m_margins == margins) + return; + + m_margins = QMargins(qRound(left), qRound(top), qRound(right), qRound(bottom)); + markDirty(DirtyGeometry); +} + +void QSGSoftwareNinePatchNode::update() +{ +} + +void QSGSoftwareNinePatchNode::paint(QPainter *painter) +{ + if (m_margins.isNull()) + painter->drawPixmap(m_bounds, m_pixmap, QRectF(0, 0, m_pixmap.width(), m_pixmap.height())); + else + QSGSoftwareHelpers::qDrawBorderPixmap(painter, m_bounds.toRect(), m_margins, m_pixmap, QRect(0, 0, m_pixmap.width(), m_pixmap.height()), + m_margins, Qt::StretchTile, QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints(0)); +} + +QRectF QSGSoftwareNinePatchNode::bounds() const +{ + return m_bounds; +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h new file mode 100644 index 0000000000..8f5216d03a --- /dev/null +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGSOFTWAREPUBLICNODES_H +#define QSGSOFTWAREPUBLICNODES_H + +#include +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QSGSoftwareRectangleNode : public QSGRectangleNode +{ +public: + QSGSoftwareRectangleNode(); + + void setRect(const QRectF &rect) override { m_rect = rect; markDirty(DirtyMaterial); } + QRectF rect() const override { return m_rect; } + + void setColor(const QColor &color) override { m_color = color; markDirty(DirtyMaterial); } + QColor color() const override { return m_color; } + + void paint(QPainter *painter); + +private: + QRectF m_rect; + QColor m_color; +}; + +class QSGSoftwareImageNode : public QSGImageNode +{ +public: + QSGSoftwareImageNode(); + ~QSGSoftwareImageNode(); + + void setRect(const QRectF &rect) override { m_rect = rect; markDirty(DirtyMaterial); } + QRectF rect() const override { return m_rect; } + + void setSourceRect(const QRectF &r) override { m_sourceRect = r; } + QRectF sourceRect() const override { return m_sourceRect; } + + void setTexture(QSGTexture *texture) override { m_texture = texture; markDirty(DirtyMaterial); } + QSGTexture *texture() const override { return m_texture; } + + void setFiltering(QSGTexture::Filtering) override { } + QSGTexture::Filtering filtering() const override { return QSGTexture::None; } + + void setTextureCoordinatesTransform(TextureCoordinatesTransformMode) override { } + TextureCoordinatesTransformMode textureCoordinatesTransform() const override { return NoTransform; } + + void setOwnsTexture(bool owns) override { m_owns = owns; } + bool ownsTexture() const override { return m_owns; } + + void paint(QPainter *painter); + +private: + QPixmap m_pixmap; + QSGTexture *m_texture; + QRectF m_rect; + QRectF m_sourceRect; + bool m_owns; +}; + +class QSGSoftwareNinePatchNode : public QSGNinePatchNode +{ +public: + QSGSoftwareNinePatchNode(); + + void setTexture(QSGTexture *texture) override; + void setBounds(const QRectF &bounds) override; + void setDevicePixelRatio(qreal ratio) override; + void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; + void update() override; + + void paint(QPainter *painter); + + QRectF bounds() const; + +private: + QPixmap m_pixmap; + QRectF m_bounds; + qreal m_pixelRatio; + QMargins m_margins; +}; + +QT_END_NAMESPACE + +#endif // QSGSOFTWAREPUBLICNODES_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode.cpp deleted file mode 100644 index 7672b14371..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgsoftwarerectanglenode_p.h" -#include - -#include - -QT_BEGIN_NAMESPACE - -QSGSoftwareRectangleNode::QSGSoftwareRectangleNode() - : m_penWidth(0) - , m_radius(0) - , m_cornerPixmapIsDirty(true) - , m_devicePixelRatio(1) -{ - m_pen.setJoinStyle(Qt::MiterJoin); - m_pen.setMiterLimit(0); - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - -void QSGSoftwareRectangleNode::setRect(const QRectF &rect) -{ - QRect alignedRect = rect.toAlignedRect(); - if (m_rect != alignedRect) { - m_rect = alignedRect; - markDirty(DirtyMaterial); - } -} - -void QSGSoftwareRectangleNode::setColor(const QColor &color) -{ - if (m_color != color) { - m_color = color; - m_cornerPixmapIsDirty = true; - markDirty(DirtyMaterial); - } -} - -void QSGSoftwareRectangleNode::setPenColor(const QColor &color) -{ - if (m_penColor != color) { - m_penColor = color; - m_cornerPixmapIsDirty = true; - markDirty(DirtyMaterial); - } -} - -void QSGSoftwareRectangleNode::setPenWidth(qreal width) -{ - if (m_penWidth != width) { - m_penWidth = width; - m_cornerPixmapIsDirty = true; - markDirty(DirtyMaterial); - } -} - -//Move first stop by pos relative to seconds -static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos) -{ - double distance = secondStop.first - firstStop.first; - double distanceDelta = newPos - firstStop.first; - double modifierValue = distanceDelta / distance; - int redDelta = (secondStop.second.red() - firstStop.second.red()) * modifierValue; - int greenDelta = (secondStop.second.green() - firstStop.second.green()) * modifierValue; - int blueDelta = (secondStop.second.blue() - firstStop.second.blue()) * modifierValue; - int alphaDelta = (secondStop.second.alpha() - firstStop.second.alpha()) * modifierValue; - - QGradientStop newStop; - newStop.first = newPos; - newStop.second = QColor(firstStop.second.red() + redDelta, - firstStop.second.green() + greenDelta, - firstStop.second.blue() + blueDelta, - firstStop.second.alpha() + alphaDelta); - - return newStop; -} - -void QSGSoftwareRectangleNode::setGradientStops(const QGradientStops &stops) -{ - //normalize stops - bool needsNormalization = false; - foreach (const QGradientStop &stop, stops) { - if (stop.first < 0.0 || stop.first > 1.0) { - needsNormalization = true; - continue; - } - } - - if (needsNormalization) { - QGradientStops normalizedStops; - if (stops.count() == 1) { - //If there is only one stop, then the position does not matter - //It is just treated as a color - QGradientStop stop = stops.at(0); - stop.first = 0.0; - normalizedStops.append(stop); - } else { - //Clip stops to only the first below 0.0 and above 1.0 - int below = -1; - int above = -1; - QVector between; - for (int i = 0; i < stops.count(); ++i) { - if (stops.at(i).first < 0.0) { - below = i; - } else if (stops.at(i).first > 1.0) { - above = i; - break; - } else { - between.append(i); - } - } - - //Interpoloate new color values for above and below - if (below != -1 ) { - //If there are more than one stops left, interpolate - if (below + 1 < stops.count()) { - normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0)); - } else { - QGradientStop singleStop; - singleStop.first = 0.0; - singleStop.second = stops.at(below).second; - normalizedStops.append(singleStop); - } - } - - for (int i = 0; i < between.count(); ++i) - normalizedStops.append(stops.at(between.at(i))); - - if (above != -1) { - //If there stops before above, interpolate - if (above >= 1) { - normalizedStops.append(interpolateStop(stops.at(above), stops.at(above - 1), 1.0)); - } else { - QGradientStop singleStop; - singleStop.first = 1.0; - singleStop.second = stops.at(above).second; - normalizedStops.append(singleStop); - } - } - } - - m_stops = normalizedStops; - - } else { - m_stops = stops; - } - m_cornerPixmapIsDirty = true; - markDirty(DirtyMaterial); -} - -void QSGSoftwareRectangleNode::setRadius(qreal radius) -{ - if (m_radius != radius) { - m_radius = radius; - m_cornerPixmapIsDirty = true; - markDirty(DirtyMaterial); - } -} - -void QSGSoftwareRectangleNode::setAligned(bool /*aligned*/) -{ -} - -void QSGSoftwareRectangleNode::update() -{ - if (!m_penWidth || m_penColor == Qt::transparent) { - m_pen = Qt::NoPen; - } else { - m_pen = QPen(m_penColor); - m_pen.setWidthF(m_penWidth); - } - - if (!m_stops.isEmpty()) { - QLinearGradient gradient(QPoint(0,0), QPoint(0,1)); - gradient.setStops(m_stops); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - m_brush = QBrush(gradient); - } else { - m_brush = QBrush(m_color); - } - - if (m_cornerPixmapIsDirty) { - generateCornerPixmap(); - m_cornerPixmapIsDirty = false; - } -} - -void QSGSoftwareRectangleNode::paint(QPainter *painter) -{ - //We can only check for a device pixel ratio change when we know what - //paint device is being used. - if (painter->device()->devicePixelRatio() != m_devicePixelRatio) { - m_devicePixelRatio = painter->device()->devicePixelRatio(); - generateCornerPixmap(); - } - - if (painter->transform().isRotating()) { - //Rotated rectangles lose the benefits of direct rendering, and have poor rendering - //quality when using only blits and fills. - - if (m_radius == 0 && m_penWidth == 0) { - //Non-Rounded Rects without borders (fall back to drawRect) - //Most common case - painter->setPen(Qt::NoPen); - painter->setBrush(m_brush); - painter->drawRect(m_rect); - } else { - //Rounded Rects and Rects with Borders - //Avoids broken behaviors of QPainter::drawRect/roundedRect - QPixmap pixmap = QPixmap(m_rect.width() * m_devicePixelRatio, m_rect.height() * m_devicePixelRatio); - pixmap.fill(Qt::transparent); - pixmap.setDevicePixelRatio(m_devicePixelRatio); - QPainter pixmapPainter(&pixmap); - paintRectangle(&pixmapPainter, QRect(0, 0, m_rect.width(), m_rect.height())); - - QPainter::RenderHints previousRenderHints = painter->renderHints(); - painter->setRenderHint(QPainter::SmoothPixmapTransform, true); - painter->drawPixmap(m_rect, pixmap); - painter->setRenderHints(previousRenderHints); - } - - - } else { - //Paint directly - paintRectangle(painter, m_rect); - } - -} - -bool QSGSoftwareRectangleNode::isOpaque() const -{ - if (m_radius > 0.0f) - return false; - if (m_color.alpha() < 255) - return false; - if (m_penWidth > 0.0f && m_penColor.alpha() < 255) - return false; - if (m_stops.count() > 0) { - foreach (QGradientStop stop, m_stops) { - if (stop.second.alpha() < 255) - return false; - } - } - - return true; -} - -QRectF QSGSoftwareRectangleNode::rect() const -{ - //TODO: double check that this is correct. - return m_rect; -} - -void QSGSoftwareRectangleNode::paintRectangle(QPainter *painter, const QRect &rect) -{ - //Radius should never exceeds half of the width or half of the height - int radius = qFloor(qMin(qMin(rect.width(), rect.height()) * 0.5, m_radius)); - - QPainter::RenderHints previousRenderHints = painter->renderHints(); - painter->setRenderHint(QPainter::Antialiasing, false); - - if (m_penWidth > 0) { - //Fill border Rects - - //Borders can not be more than half the height/width of a rect - double borderWidth = qMin(m_penWidth, rect.width() * 0.5); - double borderHeight = qMin(m_penWidth, rect.height() * 0.5); - - - - if (borderWidth > radius) { - //4 Rects - QRectF borderTopOutside(QPointF(rect.x() + radius, rect.y()), - QPointF(rect.x() + rect.width() - radius, rect.y() + radius)); - QRectF borderTopInside(QPointF(rect.x() + borderWidth, rect.y() + radius), - QPointF(rect.x() + rect.width() - borderWidth, rect.y() + borderHeight)); - QRectF borderBottomOutside(QPointF(rect.x() + radius, rect.y() + rect.height() - radius), - QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height())); - QRectF borderBottomInside(QPointF(rect.x() + borderWidth, rect.y() + rect.height() - borderHeight), - QPointF(rect.x() + rect.width() - borderWidth, rect.y() + rect.height() - radius)); - - if (borderTopOutside.isValid()) - painter->fillRect(borderTopOutside, m_penColor); - if (borderTopInside.isValid()) - painter->fillRect(borderTopInside, m_penColor); - if (borderBottomOutside.isValid()) - painter->fillRect(borderBottomOutside, m_penColor); - if (borderBottomInside.isValid()) - painter->fillRect(borderBottomInside, m_penColor); - - } else { - //2 Rects - QRectF borderTop(QPointF(rect.x() + radius, rect.y()), - QPointF(rect.x() + rect.width() - radius, rect.y() + borderHeight)); - QRectF borderBottom(QPointF(rect.x() + radius, rect.y() + rect.height() - borderHeight), - QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height())); - if (borderTop.isValid()) - painter->fillRect(borderTop, m_penColor); - if (borderBottom.isValid()) - painter->fillRect(borderBottom, m_penColor); - } - QRectF borderLeft(QPointF(rect.x(), rect.y() + radius), - QPointF(rect.x() + borderWidth, rect.y() + rect.height() - radius)); - QRectF borderRight(QPointF(rect.x() + rect.width() - borderWidth, rect.y() + radius), - QPointF(rect.x() + rect.width(), rect.y() + rect.height() - radius)); - if (borderLeft.isValid()) - painter->fillRect(borderLeft, m_penColor); - if (borderRight.isValid()) - painter->fillRect(borderRight, m_penColor); - } - - - if (radius > 0) { - - if (radius * 2 >= rect.width() && radius * 2 >= rect.height()) { - //Blit whole pixmap for circles - painter->drawPixmap(rect, m_cornerPixmap, m_cornerPixmap.rect()); - } else { - - //blit 4 corners to border - int scaledRadius = radius * m_devicePixelRatio; - QRectF topLeftCorner(QPointF(rect.x(), rect.y()), - QPointF(rect.x() + radius, rect.y() + radius)); - painter->drawPixmap(topLeftCorner, m_cornerPixmap, QRectF(0, 0, scaledRadius, scaledRadius)); - QRectF topRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y()), - QPointF(rect.x() + rect.width(), rect.y() + radius)); - painter->drawPixmap(topRightCorner, m_cornerPixmap, QRectF(scaledRadius, 0, scaledRadius, scaledRadius)); - QRectF bottomLeftCorner(QPointF(rect.x(), rect.y() + rect.height() - radius), - QPointF(rect.x() + radius, rect.y() + rect.height())); - painter->drawPixmap(bottomLeftCorner, m_cornerPixmap, QRectF(0, scaledRadius, scaledRadius, scaledRadius)); - QRectF bottomRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height() - radius), - QPointF(rect.x() + rect.width(), rect.y() + rect.height())); - painter->drawPixmap(bottomRightCorner, m_cornerPixmap, QRectF(scaledRadius, scaledRadius, scaledRadius, scaledRadius)); - - } - - } - - QRectF brushRect = QRectF(rect).marginsRemoved(QMarginsF(m_penWidth, m_penWidth, m_penWidth, m_penWidth)); - if (brushRect.width() < 0) - brushRect.setWidth(0); - if (brushRect.height() < 0) - brushRect.setHeight(0); - double innerRectRadius = qMax(0.0, radius - m_penWidth); - - //If not completely transparent or has a gradient - if (m_color.alpha() > 0 || !m_stops.empty()) { - if (innerRectRadius > 0) { - //Rounded Rect - if (m_stops.empty()) { - //Rounded Rects without gradient need 3 blits - QRectF centerRect(QPointF(brushRect.x() + innerRectRadius, brushRect.y()), - QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + brushRect.height())); - painter->fillRect(centerRect, m_color); - QRectF leftRect(QPointF(brushRect.x(), brushRect.y() + innerRectRadius), - QPointF(brushRect.x() + innerRectRadius, brushRect.y() + brushRect.height() - innerRectRadius)); - painter->fillRect(leftRect, m_color); - QRectF rightRect(QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + innerRectRadius), - QPointF(brushRect.x() + brushRect.width(), brushRect.y() + brushRect.height() - innerRectRadius)); - painter->fillRect(rightRect, m_color); - } else { - //Rounded Rect with gradient (slow) - painter->setPen(Qt::NoPen); - painter->setBrush(m_brush); - painter->drawRoundedRect(brushRect, innerRectRadius, innerRectRadius); - } - } else { - //non-rounded rects only need 1 blit - painter->fillRect(brushRect, m_brush); - } - } - - painter->setRenderHints(previousRenderHints); -} - -void QSGSoftwareRectangleNode::generateCornerPixmap() -{ - //Generate new corner Pixmap - int radius = qFloor(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius)); - - m_cornerPixmap = QPixmap(radius * 2 * m_devicePixelRatio, radius * 2 * m_devicePixelRatio); - m_cornerPixmap.setDevicePixelRatio(m_devicePixelRatio); - m_cornerPixmap.fill(Qt::transparent); - - if (radius > 0) { - QPainter cornerPainter(&m_cornerPixmap); - cornerPainter.setRenderHint(QPainter::Antialiasing); - cornerPainter.setCompositionMode(QPainter::CompositionMode_Source); - - //Paint outer cicle - if (m_penWidth > 0) { - cornerPainter.setPen(Qt::NoPen); - cornerPainter.setBrush(m_penColor); - cornerPainter.drawRoundedRect(QRectF(0, 0, radius * 2, radius *2), radius, radius); - } - - //Paint inner circle - if (radius > m_penWidth) { - cornerPainter.setPen(Qt::NoPen); - if (m_stops.isEmpty()) - cornerPainter.setBrush(m_brush); - else - cornerPainter.setBrush(Qt::transparent); - - QMarginsF adjustmentMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth); - QRectF cornerCircleRect = QRectF(0, 0, radius * 2, radius * 2).marginsRemoved(adjustmentMargins); - cornerPainter.drawRoundedRect(cornerCircleRect, radius, radius); - } - cornerPainter.end(); - } -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode_p.h deleted file mode 100644 index 9cc0823325..0000000000 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerectanglenode_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSGSOFTWARERECTANGLENODE_H -#define QSGSOFTWARERECTANGLENODE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGSoftwareRectangleNode : public QSGRectangleNode -{ -public: - QSGSoftwareRectangleNode(); - - void setRect(const QRectF &rect) override; - void setColor(const QColor &color) override; - void setPenColor(const QColor &color) override; - void setPenWidth(qreal width) override; - void setGradientStops(const QGradientStops &stops) override; - void setRadius(qreal radius) override; - void setAntialiasing(bool antialiasing) override { Q_UNUSED(antialiasing) } - void setAligned(bool aligned) override; - - void update() override; - - void paint(QPainter *); - - bool isOpaque() const; - QRectF rect() const; -private: - void paintRectangle(QPainter *painter, const QRect &rect); - void generateCornerPixmap(); - - QRect m_rect; - QColor m_color; - QColor m_penColor; - double m_penWidth; - QGradientStops m_stops; - double m_radius; - QPen m_pen; - QBrush m_brush; - - bool m_cornerPixmapIsDirty; - QPixmap m_cornerPixmap; - - int m_devicePixelRatio; -}; - -QT_END_NAMESPACE - -#endif // QSGSOFTWARERECTANGLENODE_H diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index 063242c63b..571f242b67 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -39,10 +39,10 @@ #include "qsgsoftwarerenderablenode_p.h" -#include "qsgsoftwareimagenode_p.h" -#include "qsgsoftwarerectanglenode_p.h" +#include "qsgsoftwareinternalimagenode_p.h" +#include "qsgsoftwareinternalrectanglenode_p.h" #include "qsgsoftwareglyphnode_p.h" -#include "qsgsoftwareninepatchnode_p.h" +#include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" @@ -68,13 +68,13 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod m_handle.simpleTextureNode = static_cast(node); break; case QSGSoftwareRenderableNode::Image: - m_handle.imageNode = static_cast(node); + m_handle.imageNode = static_cast(node); break; case QSGSoftwareRenderableNode::Painter: m_handle.painterNode = static_cast(node); break; case QSGSoftwareRenderableNode::Rectangle: - m_handle.rectangleNode = static_cast(node); + m_handle.rectangleNode = static_cast(node); break; case QSGSoftwareRenderableNode::Glyph: m_handle.glpyhNode = static_cast(node); @@ -82,6 +82,12 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod case QSGSoftwareRenderableNode::NinePatch: m_handle.ninePatchNode = static_cast(node); break; + case QSGSoftwareRenderableNode::SimpleRectangle: + m_handle.simpleRectangleNode = static_cast(node); + break; + case QSGSoftwareRenderableNode::SimpleImage: + m_handle.simpleImageNode = static_cast(node); + break; case QSGSoftwareRenderableNode::Invalid: m_handle.simpleRectNode = nullptr; break; @@ -151,6 +157,22 @@ void QSGSoftwareRenderableNode::update() boundingRect = m_handle.ninePatchNode->bounds().toRect(); break; + case QSGSoftwareRenderableNode::SimpleRectangle: + if (m_handle.simpleRectangleNode->color().alpha() == 255 && !m_transform.isRotating()) + m_isOpaque = true; + else + m_isOpaque = false; + + boundingRect = m_handle.simpleRectangleNode->rect().toRect(); + break; + case QSGSoftwareRenderableNode::SimpleImage: + if (!m_handle.simpleImageNode->texture()->hasAlphaChannel() && !m_transform.isRotating()) + m_isOpaque = true; + else + m_isOpaque = false; + + boundingRect = m_handle.simpleImageNode->rect().toRect(); + break; default: break; } @@ -223,6 +245,12 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu case QSGSoftwareRenderableNode::NinePatch: m_handle.ninePatchNode->paint(painter); break; + case QSGSoftwareRenderableNode::SimpleRectangle: + static_cast(m_handle.simpleRectangleNode)->paint(painter); + break; + case QSGSoftwareRenderableNode::SimpleImage: + static_cast(m_handle.simpleImageNode)->paint(painter); + break; default: break; } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h index 9a5e0a5683..d1a71cd580 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h @@ -54,15 +54,17 @@ #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE -class QSGNode; class QSGSimpleRectNode; class QSGSimpleTextureNode; -class QSGSoftwareImageNode; +class QSGSoftwareInternalImageNode; class QSGSoftwarePainterNode; -class QSGSoftwareRectangleNode; +class QSGSoftwareInternalRectangleNode; class QSGSoftwareGlyphNode; class QSGSoftwareNinePatchNode; @@ -77,7 +79,9 @@ public: Painter, Rectangle, Glyph, - NinePatch + NinePatch, + SimpleRectangle, + SimpleImage }; QSGSoftwareRenderableNode(NodeType type, QSGNode *node); @@ -112,11 +116,13 @@ private: union RenderableNodeHandle { QSGSimpleRectNode *simpleRectNode; QSGSimpleTextureNode *simpleTextureNode; - QSGSoftwareImageNode *imageNode; + QSGSoftwareInternalImageNode *imageNode; QSGSoftwarePainterNode *painterNode; - QSGSoftwareRectangleNode *rectangleNode; + QSGSoftwareInternalRectangleNode *rectangleNode; QSGSoftwareGlyphNode *glpyhNode; QSGSoftwareNinePatchNode *ninePatchNode; + QSGRectangleNode *simpleRectangleNode; + QSGImageNode *simpleImageNode; }; const NodeType m_nodeType; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp index 3d5fe21f7c..1681f3c06b 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp @@ -40,10 +40,10 @@ #include "qsgsoftwarerenderablenodeupdater_p.h" #include "qsgabstractsoftwarerenderer_p.h" -#include "qsgsoftwareimagenode_p.h" -#include "qsgsoftwarerectanglenode_p.h" +#include "qsgsoftwareinternalimagenode_p.h" +#include "qsgsoftwareinternalrectanglenode_p.h" #include "qsgsoftwareglyphnode_p.h" -#include "qsgsoftwareninepatchnode_p.h" +#include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" @@ -100,6 +100,12 @@ bool QSGSoftwareRenderableNodeUpdater::visit(QSGGeometryNode *node) return updateRenderableNode(QSGSoftwareRenderableNode::SimpleRect, rectNode); } else if (QSGSimpleTextureNode *tn = dynamic_cast(node)) { return updateRenderableNode(QSGSoftwareRenderableNode::SimpleTexture, tn); + } else if (QSGNinePatchNode *nn = dynamic_cast(node)) { + return updateRenderableNode(QSGSoftwareRenderableNode::NinePatch, nn); + } else if (QSGRectangleNode *rn = dynamic_cast(node)) { + return updateRenderableNode(QSGSoftwareRenderableNode::SimpleRectangle, rn); + } else if (QSGImageNode *n = dynamic_cast(node)) { + return updateRenderableNode(QSGSoftwareRenderableNode::SimpleImage, n); } else { // We dont know, so skip return false; @@ -122,12 +128,12 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGOpacityNode *) m_opacityState.pop(); } -bool QSGSoftwareRenderableNodeUpdater::visit(QSGImageNode *node) +bool QSGSoftwareRenderableNodeUpdater::visit(QSGInternalImageNode *node) { return updateRenderableNode(QSGSoftwareRenderableNode::Image, node); } -void QSGSoftwareRenderableNodeUpdater::endVisit(QSGImageNode *) +void QSGSoftwareRenderableNodeUpdater::endVisit(QSGInternalImageNode *) { } @@ -140,12 +146,12 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGPainterNode *) { } -bool QSGSoftwareRenderableNodeUpdater::visit(QSGRectangleNode *node) +bool QSGSoftwareRenderableNodeUpdater::visit(QSGInternalRectangleNode *node) { return updateRenderableNode(QSGSoftwareRenderableNode::Rectangle, node); } -void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRectangleNode *) +void QSGSoftwareRenderableNodeUpdater::endVisit(QSGInternalRectangleNode *) { } @@ -158,15 +164,6 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGGlyphNode *) { } -bool QSGSoftwareRenderableNodeUpdater::visit(QSGNinePatchNode *node) -{ - return updateRenderableNode(QSGSoftwareRenderableNode::NinePatch, node); -} - -void QSGSoftwareRenderableNodeUpdater::endVisit(QSGNinePatchNode *) -{ -} - bool QSGSoftwareRenderableNodeUpdater::visit(QSGRootNode *node) { m_stateMap[node] = currentState(node); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h index 562d15769e..97492d4347 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h @@ -76,16 +76,14 @@ public: void endVisit(QSGGeometryNode *) override; bool visit(QSGOpacityNode *) override; void endVisit(QSGOpacityNode *) override; - bool visit(QSGImageNode *) override; - void endVisit(QSGImageNode *) override; + bool visit(QSGInternalImageNode *) override; + void endVisit(QSGInternalImageNode *) override; bool visit(QSGPainterNode *) override; void endVisit(QSGPainterNode *) override; - bool visit(QSGRectangleNode *) override; - void endVisit(QSGRectangleNode *) override; + bool visit(QSGInternalRectangleNode *) override; + void endVisit(QSGInternalRectangleNode *) override; bool visit(QSGGlyphNode *) override; void endVisit(QSGGlyphNode *) override; - bool visit(QSGNinePatchNode *) override; - void endVisit(QSGNinePatchNode *) override; bool visit(QSGRootNode *) override; void endVisit(QSGRootNode *) override; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp index af81ff61c3..ede2005918 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp @@ -41,10 +41,10 @@ #include "qsgsoftwarerenderablenode_p.h" #include "qsgabstractsoftwarerenderer_p.h" -#include "qsgsoftwareimagenode_p.h" -#include "qsgsoftwarerectanglenode_p.h" +#include "qsgsoftwareinternalimagenode_p.h" +#include "qsgsoftwareinternalrectanglenode_p.h" #include "qsgsoftwareglyphnode_p.h" -#include "qsgsoftwareninepatchnode_p.h" +#include "qsgsoftwarepublicnodes_p.h" #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" @@ -95,12 +95,12 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGOpacityNode *) { } -bool QSGSoftwareRenderListBuilder::visit(QSGImageNode *node) +bool QSGSoftwareRenderListBuilder::visit(QSGInternalImageNode *node) { return addRenderableNode(node); } -void QSGSoftwareRenderListBuilder::endVisit(QSGImageNode *) +void QSGSoftwareRenderListBuilder::endVisit(QSGInternalImageNode *) { } @@ -113,12 +113,12 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGPainterNode *) { } -bool QSGSoftwareRenderListBuilder::visit(QSGRectangleNode *node) +bool QSGSoftwareRenderListBuilder::visit(QSGInternalRectangleNode *node) { return addRenderableNode(node); } -void QSGSoftwareRenderListBuilder::endVisit(QSGRectangleNode *) +void QSGSoftwareRenderListBuilder::endVisit(QSGInternalRectangleNode *) { } @@ -131,15 +131,6 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGGlyphNode *) { } -bool QSGSoftwareRenderListBuilder::visit(QSGNinePatchNode *node) -{ - return addRenderableNode(node); -} - -void QSGSoftwareRenderListBuilder::endVisit(QSGNinePatchNode *) -{ -} - bool QSGSoftwareRenderListBuilder::visit(QSGRootNode *) { return true; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h index 94b563564d..ce538f835f 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h @@ -70,16 +70,14 @@ public: void endVisit(QSGGeometryNode *) override; bool visit(QSGOpacityNode *) override; void endVisit(QSGOpacityNode *) override; - bool visit(QSGImageNode *) override; - void endVisit(QSGImageNode *) override; + bool visit(QSGInternalImageNode *) override; + void endVisit(QSGInternalImageNode *) override; bool visit(QSGPainterNode *) override; void endVisit(QSGPainterNode *) override; - bool visit(QSGRectangleNode *) override; - void endVisit(QSGRectangleNode *) override; + bool visit(QSGInternalRectangleNode *) override; + void endVisit(QSGInternalRectangleNode *) override; bool visit(QSGGlyphNode *) override; void endVisit(QSGGlyphNode *) override; - bool visit(QSGNinePatchNode *) override; - void endVisit(QSGNinePatchNode *) override; bool visit(QSGRootNode *) override; void endVisit(QSGRootNode *) override; diff --git a/src/quick/scenegraph/adaptations/software/software.pri b/src/quick/scenegraph/adaptations/software/software.pri index b8cdbc4a25..a8ba77c147 100644 --- a/src/quick/scenegraph/adaptations/software/software.pri +++ b/src/quick/scenegraph/adaptations/software/software.pri @@ -6,10 +6,10 @@ SOURCES += \ $$PWD/qsgsoftwarecontext.cpp \ $$PWD/qsgabstractsoftwarerenderer.cpp \ $$PWD/qsgsoftwareglyphnode.cpp \ - $$PWD/qsgsoftwareimagenode.cpp \ - $$PWD/qsgsoftwareninepatchnode.cpp \ + $$PWD/qsgsoftwareinternalimagenode.cpp \ + $$PWD/qsgsoftwarepublicnodes.cpp \ $$PWD/qsgsoftwarepainternode.cpp \ - $$PWD/qsgsoftwarerectanglenode.cpp \ + $$PWD/qsgsoftwareinternalrectanglenode.cpp \ $$PWD/qsgsoftwarepixmaprenderer.cpp \ $$PWD/qsgsoftwarepixmaptexture.cpp \ $$PWD/qsgsoftwarerenderablenode.cpp \ @@ -24,12 +24,12 @@ HEADERS += \ $$PWD/qsgsoftwarecontext_p.h \ $$PWD/qsgabstractsoftwarerenderer_p.h \ $$PWD/qsgsoftwareglyphnode_p.h \ - $$PWD/qsgsoftwareimagenode_p.h \ - $$PWD/qsgsoftwareninepatchnode_p.h \ + $$PWD/qsgsoftwareinternalimagenode_p.h \ + $$PWD/qsgsoftwarepublicnodes_p.h \ $$PWD/qsgsoftwarepainternode_p.h \ $$PWD/qsgsoftwarepixmaprenderer_p.h \ $$PWD/qsgsoftwarepixmaptexture_p.h \ - $$PWD/qsgsoftwarerectanglenode_p.h \ + $$PWD/qsgsoftwareinternalrectanglenode_p.h \ $$PWD/qsgsoftwarerenderablenode_p.h \ $$PWD/qsgsoftwarerenderablenodeupdater_p.h \ $$PWD/qsgsoftwarerenderer_p.h \ diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 7ec72a6e10..239557d527 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -726,6 +726,27 @@ void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, v[3].ty = textureRect.bottom(); } +/*! + Updates the geometry \a g with the coordinates in \a rect. + + The function assumes the geometry object contains a single triangle strip + of QSGGeometry::ColoredPoint2D vertices + */ +void QSGGeometry::updateColoredRectGeometry(QSGGeometry *g, const QRectF &rect) +{ + ColoredPoint2D *v = g->vertexDataAsColoredPoint2D(); + v[0].x = rect.left(); + v[0].y = rect.top(); + + v[1].x = rect.left(); + v[1].y = rect.bottom(); + + v[2].x = rect.right(); + v[2].y = rect.top(); + + v[3].x = rect.right(); + v[3].y = rect.bottom(); +} /*! diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h index 1f54b7d81b..ae7b2f494c 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.h +++ b/src/quick/scenegraph/coreapi/qsggeometry.h @@ -182,6 +182,7 @@ public: static void updateRectGeometry(QSGGeometry *g, const QRectF &rect); static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect); + static void updateColoredRectGeometry(QSGGeometry *g, const QRectF &rect); void setIndexDataPattern(DataPattern p); DataPattern indexDataPattern() const { return DataPattern(m_index_usage_pattern); } diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 92f783d500..c0967bcb09 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -1466,8 +1466,6 @@ void QSGNodeVisitor::visitChildren(QSGNode *n) visitNode(c); } - - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QSGGeometryNode *n) { diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 179ec3e3fa..bdb8ebb0f1 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -76,11 +76,10 @@ class TextureReference; class QSGDistanceFieldGlyphCacheManager; class QSGDistanceFieldGlyphNode; class QOpenGLContext; -class QSGImageNode; +class QSGInternalImageNode; class QSGPainterNode; -class QSGRectangleNode; +class QSGInternalRectangleNode; class QSGGlyphNode; -class QSGNinePatchNode; class QSGRootNode; class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx @@ -97,16 +96,14 @@ public: virtual void endVisit(QSGGeometryNode *) = 0; virtual bool visit(QSGOpacityNode *) = 0; virtual void endVisit(QSGOpacityNode *) = 0; - virtual bool visit(QSGImageNode *) = 0; - virtual void endVisit(QSGImageNode *) = 0; + virtual bool visit(QSGInternalImageNode *) = 0; + virtual void endVisit(QSGInternalImageNode *) = 0; virtual bool visit(QSGPainterNode *) = 0; virtual void endVisit(QSGPainterNode *) = 0; - virtual bool visit(QSGRectangleNode *) = 0; - virtual void endVisit(QSGRectangleNode *) = 0; + virtual bool visit(QSGInternalRectangleNode *) = 0; + virtual void endVisit(QSGInternalRectangleNode *) = 0; virtual bool visit(QSGGlyphNode *) = 0; virtual void endVisit(QSGGlyphNode *) = 0; - virtual bool visit(QSGNinePatchNode *) = 0; - virtual void endVisit(QSGNinePatchNode *) = 0; virtual bool visit(QSGRootNode *) = 0; virtual void endVisit(QSGRootNode *) = 0; @@ -122,7 +119,7 @@ public: virtual void accept(QSGNodeVisitorEx *) = 0; }; -class Q_QUICK_PRIVATE_EXPORT QSGRectangleNode : public QSGVisitableNode +class Q_QUICK_PRIVATE_EXPORT QSGInternalRectangleNode : public QSGVisitableNode { public: virtual void setRect(const QRectF &rect) = 0; @@ -140,7 +137,7 @@ public: }; -class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode +class Q_QUICK_PRIVATE_EXPORT QSGInternalImageNode : public QSGVisitableNode { public: virtual void setTargetRect(const QRectF &rect) = 0; @@ -186,19 +183,6 @@ public: virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } }; -class Q_QUICK_PRIVATE_EXPORT QSGNinePatchNode : public QSGVisitableNode -{ -public: - virtual void setTexture(QSGTexture *texture) = 0; - virtual void setBounds(const QRectF &bounds) = 0; - virtual void setDevicePixelRatio(qreal ratio) = 0; - virtual void setPadding(qreal left, qreal top, qreal right, qreal bottom) = 0; - - virtual void update() = 0; - - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } -}; - class Q_QUICK_EXPORT QSGLayer : public QSGDynamicTexture { Q_OBJECT diff --git a/src/quick/scenegraph/qsgbasicimagenode.cpp b/src/quick/scenegraph/qsgbasicimagenode.cpp deleted file mode 100644 index 24077cc947..0000000000 --- a/src/quick/scenegraph/qsgbasicimagenode.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgbasicimagenode_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -namespace -{ - struct SmoothVertex - { - float x, y, u, v; - float dx, dy, du, dv; - }; - - const QSGGeometry::AttributeSet &smoothAttributeSet() - { - static QSGGeometry::Attribute data[] = { - QSGGeometry::Attribute::createWithSemantic(0, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::POSITION), - QSGGeometry::Attribute::createWithSemantic(1, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD), - QSGGeometry::Attribute::createWithSemantic(2, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD1), - QSGGeometry::Attribute::createWithSemantic(3, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD2) - }; - static QSGGeometry::AttributeSet attrs = { 4, sizeof(SmoothVertex), data }; - return attrs; - } -} - -QSGBasicImageNode::QSGBasicImageNode() - : m_innerSourceRect(0, 0, 1, 1) - , m_subSourceRect(0, 0, 1, 1) - , m_antialiasing(false) - , m_mirror(false) - , m_dirtyGeometry(false) - , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) - , m_dynamicTexture(nullptr) -{ - setGeometry(&m_geometry); - -#ifdef QSG_RUNTIME_DESCRIPTION - qsgnode_set_description(this, QLatin1String("image")); -#endif -} - -void QSGBasicImageNode::setTargetRect(const QRectF &rect) -{ - if (rect == m_targetRect) - return; - m_targetRect = rect; - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setInnerTargetRect(const QRectF &rect) -{ - if (rect == m_innerTargetRect) - return; - m_innerTargetRect = rect; - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setInnerSourceRect(const QRectF &rect) -{ - if (rect == m_innerSourceRect) - return; - m_innerSourceRect = rect; - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setSubSourceRect(const QRectF &rect) -{ - if (rect == m_subSourceRect) - return; - m_subSourceRect = rect; - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setTexture(QSGTexture *texture) -{ - Q_ASSERT(texture); - - setMaterialTexture(texture); - updateMaterialBlending(); - - markDirty(DirtyMaterial); - - // Because the texture can be a different part of the atlas, we need to update it... - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setAntialiasing(bool antialiasing) -{ - if (antialiasing == m_antialiasing) - return; - m_antialiasing = antialiasing; - if (m_antialiasing) { - setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); - setFlag(OwnsGeometry, true); - } else { - setGeometry(&m_geometry); - setFlag(OwnsGeometry, false); - } - updateMaterialAntialiasing(); - m_dirtyGeometry = true; -} - -void QSGBasicImageNode::setMirror(bool mirror) -{ - if (mirror == m_mirror) - return; - m_mirror = mirror; - m_dirtyGeometry = true; -} - - -void QSGBasicImageNode::update() -{ - if (m_dirtyGeometry) - updateGeometry(); -} - -void QSGBasicImageNode::preprocess() -{ - bool doDirty = false; - QSGDynamicTexture *t = qobject_cast(materialTexture()); - if (t) { - doDirty = t->updateTexture(); - if (doDirty) { - // The geometry may need updating. This is expensive however, so do - // it only when something relevant has changed. - if (t != m_dynamicTexture - || t->textureSize() != m_dynamicTextureSize - || t->normalizedTextureSubRect() != m_dynamicTextureSubRect) { - updateGeometry(); - m_dynamicTextureSize = t->textureSize(); - m_dynamicTextureSubRect = t->normalizedTextureSubRect(); - } - } - } - m_dynamicTexture = t; - - if (updateMaterialBlending()) - doDirty = true; - - if (doDirty) - markDirty(DirtyMaterial); -} - -namespace { - struct X { float x, tx; }; - struct Y { float y, ty; }; -} - -static inline void appendQuad(quint16 **indices, quint16 topLeft, quint16 topRight, - quint16 bottomLeft, quint16 bottomRight) -{ - *(*indices)++ = topLeft; - *(*indices)++ = bottomLeft; - *(*indices)++ = bottomRight; - *(*indices)++ = bottomRight; - *(*indices)++ = topRight; - *(*indices)++ = topLeft; -} - -QSGGeometry *QSGBasicImageNode::updateGeometry(const QRectF &targetRect, - const QRectF &innerTargetRect, - const QRectF &sourceRect, - const QRectF &innerSourceRect, - const QRectF &subSourceRect, - QSGGeometry *geometry, - bool mirror, - bool antialiasing) -{ - int floorLeft = qFloor(subSourceRect.left()); - int ceilRight = qCeil(subSourceRect.right()); - int floorTop = qFloor(subSourceRect.top()); - int ceilBottom = qCeil(subSourceRect.bottom()); - int hTiles = ceilRight - floorLeft; - int vTiles = ceilBottom - floorTop; - - int hCells = hTiles; - int vCells = vTiles; - if (innerTargetRect.width() == 0) - hCells = 0; - if (innerTargetRect.left() != targetRect.left()) - ++hCells; - if (innerTargetRect.right() != targetRect.right()) - ++hCells; - if (innerTargetRect.height() == 0) - vCells = 0; - if (innerTargetRect.top() != targetRect.top()) - ++vCells; - if (innerTargetRect.bottom() != targetRect.bottom()) - ++vCells; - QVarLengthArray xData(2 * hCells); - QVarLengthArray yData(2 * vCells); - X *xs = xData.data(); - Y *ys = yData.data(); - - if (innerTargetRect.left() != targetRect.left()) { - xs[0].x = targetRect.left(); - xs[0].tx = sourceRect.left(); - xs[1].x = innerTargetRect.left(); - xs[1].tx = innerSourceRect.left(); - xs += 2; - } - if (innerTargetRect.width() != 0) { - xs[0].x = innerTargetRect.left(); - xs[0].tx = innerSourceRect.x() + (subSourceRect.left() - floorLeft) * innerSourceRect.width(); - ++xs; - float b = innerTargetRect.width() / subSourceRect.width(); - float a = innerTargetRect.x() - subSourceRect.x() * b; - for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) { - xs[0].x = xs[1].x = a + b * i; - xs[0].tx = innerSourceRect.right(); - xs[1].tx = innerSourceRect.left(); - xs += 2; - } - xs[0].x = innerTargetRect.right(); - xs[0].tx = innerSourceRect.x() + (subSourceRect.right() - ceilRight + 1) * innerSourceRect.width(); - ++xs; - } - if (innerTargetRect.right() != targetRect.right()) { - xs[0].x = innerTargetRect.right(); - xs[0].tx = innerSourceRect.right(); - xs[1].x = targetRect.right(); - xs[1].tx = sourceRect.right(); - xs += 2; - } - Q_ASSERT(xs == xData.data() + xData.size()); - if (mirror) { - float leftPlusRight = targetRect.left() + targetRect.right(); - int count = xData.size(); - xs = xData.data(); - for (int i = 0; i < count >> 1; ++i) - qSwap(xs[i], xs[count - 1 - i]); - for (int i = 0; i < count; ++i) - xs[i].x = leftPlusRight - xs[i].x; - } - - if (innerTargetRect.top() != targetRect.top()) { - ys[0].y = targetRect.top(); - ys[0].ty = sourceRect.top(); - ys[1].y = innerTargetRect.top(); - ys[1].ty = innerSourceRect.top(); - ys += 2; - } - if (innerTargetRect.height() != 0) { - ys[0].y = innerTargetRect.top(); - ys[0].ty = innerSourceRect.y() + (subSourceRect.top() - floorTop) * innerSourceRect.height(); - ++ys; - float b = innerTargetRect.height() / subSourceRect.height(); - float a = innerTargetRect.y() - subSourceRect.y() * b; - for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) { - ys[0].y = ys[1].y = a + b * i; - ys[0].ty = innerSourceRect.bottom(); - ys[1].ty = innerSourceRect.top(); - ys += 2; - } - ys[0].y = innerTargetRect.bottom(); - ys[0].ty = innerSourceRect.y() + (subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height(); - ++ys; - } - if (innerTargetRect.bottom() != targetRect.bottom()) { - ys[0].y = innerTargetRect.bottom(); - ys[0].ty = innerSourceRect.bottom(); - ys[1].y = targetRect.bottom(); - ys[1].ty = sourceRect.bottom(); - ys += 2; - } - Q_ASSERT(ys == yData.data() + yData.size()); - - if (antialiasing) { - QSGGeometry *g = geometry; - Q_ASSERT(g); - - g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4, - hCells * vCells * 6 + (hCells + vCells) * 12); - g->setDrawingMode(QSGGeometry::DrawTriangles); - SmoothVertex *vertices = reinterpret_cast(g->vertexData()); - memset(vertices, 0, g->vertexCount() * g->sizeOfVertex()); - quint16 *indices = g->indexDataAsUShort(); - - // The deltas are how much the fuzziness can reach into the image. - // Only the border vertices are moved by the vertex shader, so the fuzziness - // can't reach further into the image than the closest interior vertices. - float leftDx = xData.at(1).x - xData.at(0).x; - float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x; - float topDy = yData.at(1).y - yData.at(0).y; - float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y; - - float leftDu = xData.at(1).tx - xData.at(0).tx; - float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx; - float topDv = yData.at(1).ty - yData.at(0).ty; - float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty; - - if (hCells == 1) { - leftDx = rightDx *= 0.5f; - leftDu = rightDu *= 0.5f; - } - if (vCells == 1) { - topDy = bottomDy *= 0.5f; - topDv = bottomDv *= 0.5f; - } - - // This delta is how much the fuzziness can reach out from the image. - float delta = float(qAbs(targetRect.width()) < qAbs(targetRect.height()) - ? targetRect.width() : targetRect.height()) * 0.5f; - - quint16 index = 0; - ys = yData.data(); - for (int j = 0; j < vCells; ++j, ys += 2) { - xs = xData.data(); - bool isTop = j == 0; - bool isBottom = j == vCells - 1; - for (int i = 0; i < hCells; ++i, xs += 2) { - bool isLeft = i == 0; - bool isRight = i == hCells - 1; - - SmoothVertex *v = vertices + index; - - quint16 topLeft = index; - for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) { - v->x = xs[0].x; - v->u = xs[0].tx; - v->y = ys[0].y; - v->v = ys[0].ty; - } - - quint16 topRight = index; - for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) { - v->x = xs[1].x; - v->u = xs[1].tx; - v->y = ys[0].y; - v->v = ys[0].ty; - } - - quint16 bottomLeft = index; - for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) { - v->x = xs[0].x; - v->u = xs[0].tx; - v->y = ys[1].y; - v->v = ys[1].ty; - } - - quint16 bottomRight = index; - for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) { - v->x = xs[1].x; - v->u = xs[1].tx; - v->y = ys[1].y; - v->v = ys[1].ty; - } - - appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight); - - if (isTop) { - vertices[topLeft].dy = vertices[topRight].dy = topDy; - vertices[topLeft].dv = vertices[topRight].dv = topDv; - vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; - appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); - } - - if (isBottom) { - vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; - vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; - vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; - appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); - } - - if (isLeft) { - vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; - vertices[topLeft].du = vertices[bottomLeft].du = leftDu; - vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; - appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); - } - - if (isRight) { - vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; - vertices[topRight].du = vertices[bottomRight].du = -rightDu; - vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; - appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); - } - } - } - - Q_ASSERT(index == g->vertexCount()); - Q_ASSERT(indices - g->indexCount() == g->indexData()); - } else { - if (!geometry) { - geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), - hCells * vCells * 4, hCells * vCells * 6, - QSGGeometry::TypeUnsignedShort); - } else { - geometry->allocate(hCells * vCells * 4, hCells * vCells * 6); - } - geometry->setDrawingMode(QSGGeometry::DrawTriangles); - QSGGeometry::TexturedPoint2D *vertices = geometry->vertexDataAsTexturedPoint2D(); - ys = yData.data(); - for (int j = 0; j < vCells; ++j, ys += 2) { - xs = xData.data(); - for (int i = 0; i < hCells; ++i, xs += 2) { - vertices[0].x = vertices[2].x = xs[0].x; - vertices[0].tx = vertices[2].tx = xs[0].tx; - vertices[1].x = vertices[3].x = xs[1].x; - vertices[1].tx = vertices[3].tx = xs[1].tx; - - vertices[0].y = vertices[1].y = ys[0].y; - vertices[0].ty = vertices[1].ty = ys[0].ty; - vertices[2].y = vertices[3].y = ys[1].y; - vertices[2].ty = vertices[3].ty = ys[1].ty; - - vertices += 4; - } - } - - quint16 *indices = geometry->indexDataAsUShort(); - for (int i = 0; i < 4 * vCells * hCells; i += 4) - appendQuad(&indices, i, i + 1, i + 2, i + 3); - } - return geometry; -} - -void QSGBasicImageNode::updateGeometry() -{ - Q_ASSERT(!m_targetRect.isEmpty()); - const QSGTexture *t = materialTexture(); - if (!t) { - QSGGeometry *g = geometry(); - g->allocate(4); - g->setDrawingMode(QSGGeometry::DrawTriangleStrip); - memset(g->vertexData(), 0, g->sizeOfVertex() * 4); - } else { - QRectF sourceRect = t->normalizedTextureSubRect(); - - QRectF innerSourceRect(sourceRect.x() + m_innerSourceRect.x() * sourceRect.width(), - sourceRect.y() + m_innerSourceRect.y() * sourceRect.height(), - m_innerSourceRect.width() * sourceRect.width(), - m_innerSourceRect.height() * sourceRect.height()); - - bool hasMargins = m_targetRect != m_innerTargetRect; - - int floorLeft = qFloor(m_subSourceRect.left()); - int ceilRight = qCeil(m_subSourceRect.right()); - int floorTop = qFloor(m_subSourceRect.top()); - int ceilBottom = qCeil(m_subSourceRect.bottom()); - int hTiles = ceilRight - floorLeft; - int vTiles = ceilBottom - floorTop; - - bool hasTiles = hTiles != 1 || vTiles != 1; - bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1); - - // An image can be rendered as a single quad if: - // - There are no margins, and either: - // - the image isn't repeated - // - the source rectangle fills the entire texture so that texture wrapping can be used, - // and NPOT is supported - if (!hasMargins && (!hasTiles || (fullTexture && supportsWrap(t->textureSize())))) { - QRectF sr; - if (!fullTexture) { - sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), - innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(), - m_subSourceRect.width() * innerSourceRect.width(), - m_subSourceRect.height() * innerSourceRect.height()); - } else { - sr = QRectF(m_subSourceRect.left() - floorLeft, m_subSourceRect.top() - floorTop, - m_subSourceRect.width(), m_subSourceRect.height()); - } - if (m_mirror) { - qreal oldLeft = sr.left(); - sr.setLeft(sr.right()); - sr.setRight(oldLeft); - } - - if (m_antialiasing) { - QSGGeometry *g = geometry(); - Q_ASSERT(g != &m_geometry); - g->allocate(8, 14); - g->setDrawingMode(QSGGeometry::DrawTriangleStrip); - SmoothVertex *vertices = reinterpret_cast(g->vertexData()); - float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) - ? m_targetRect.width() : m_targetRect.height()) * 0.5f; - float sx = float(sr.width() / m_targetRect.width()); - float sy = float(sr.height() / m_targetRect.height()); - for (int d = -1; d <= 1; d += 2) { - for (int j = 0; j < 2; ++j) { - for (int i = 0; i < 2; ++i, ++vertices) { - vertices->x = m_targetRect.x() + i * m_targetRect.width(); - vertices->y = m_targetRect.y() + j * m_targetRect.height(); - vertices->u = sr.x() + i * sr.width(); - vertices->v = sr.y() + j * sr.height(); - vertices->dx = (i == 0 ? delta : -delta) * d; - vertices->dy = (j == 0 ? delta : -delta) * d; - vertices->du = (d < 0 ? 0 : vertices->dx * sx); - vertices->dv = (d < 0 ? 0 : vertices->dy * sy); - } - } - } - Q_ASSERT(vertices - g->vertexCount() == g->vertexData()); - static const quint16 indices[] = { - 0, 4, 1, 5, 3, 7, 2, 6, 0, 4, - 4, 6, 5, 7 - }; - Q_ASSERT(g->sizeOfIndex() * g->indexCount() == sizeof(indices)); - memcpy(g->indexDataAsUShort(), indices, sizeof(indices)); - } else { - m_geometry.allocate(4); - m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); - QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr); - } - } else { - QSGGeometry *g = m_antialiasing ? geometry() : &m_geometry; - updateGeometry(m_targetRect, m_innerTargetRect, - sourceRect, innerSourceRect, m_subSourceRect, - g, m_mirror, m_antialiasing); - } - } - markDirty(DirtyGeometry); - m_dirtyGeometry = false; -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgbasicimagenode_p.h b/src/quick/scenegraph/qsgbasicimagenode_p.h deleted file mode 100644 index 4a96e1a9f6..0000000000 --- a/src/quick/scenegraph/qsgbasicimagenode_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSGBASICIMAGENODE_P_H -#define QSGBASICIMAGENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class Q_QUICK_PRIVATE_EXPORT QSGBasicImageNode : public QSGImageNode -{ -public: - QSGBasicImageNode(); - - void setTargetRect(const QRectF &rect) override; - void setInnerTargetRect(const QRectF &rect) override; - void setInnerSourceRect(const QRectF &rect) override; - void setSubSourceRect(const QRectF &rect) override; - void setTexture(QSGTexture *texture) override; - void setAntialiasing(bool antialiasing) override; - void setMirror(bool mirror) override; - void update() override; - void preprocess() override; - - static QSGGeometry *updateGeometry(const QRectF &targetRect, - const QRectF &innerTargetRect, - const QRectF &sourceRect, - const QRectF &innerSourceRect, - const QRectF &subSourceRect, - QSGGeometry *geometry, - bool mirror = false, - bool antialiasing = false); - -protected: - virtual void updateMaterialAntialiasing() = 0; - virtual void setMaterialTexture(QSGTexture *texture) = 0; - virtual QSGTexture *materialTexture() const = 0; - virtual bool updateMaterialBlending() = 0; - virtual bool supportsWrap(const QSize &size) const = 0; - - void updateGeometry(); - - QRectF m_targetRect; - QRectF m_innerTargetRect; - QRectF m_innerSourceRect; - QRectF m_subSourceRect; - - uint m_antialiasing : 1; - uint m_mirror : 1; - uint m_dirtyGeometry : 1; - - QSGGeometry m_geometry; - - QSGDynamicTexture *m_dynamicTexture; - QSize m_dynamicTextureSize; - QRectF m_dynamicTextureSubRect; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/quick/scenegraph/qsgbasicinternalimagenode.cpp b/src/quick/scenegraph/qsgbasicinternalimagenode.cpp new file mode 100644 index 0000000000..685a51550d --- /dev/null +++ b/src/quick/scenegraph/qsgbasicinternalimagenode.cpp @@ -0,0 +1,559 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgbasicinternalimagenode_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + struct SmoothVertex + { + float x, y, u, v; + float dx, dy, du, dv; + }; + + const QSGGeometry::AttributeSet &smoothAttributeSet() + { + static QSGGeometry::Attribute data[] = { + QSGGeometry::Attribute::createWithSemantic(0, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::POSITION), + QSGGeometry::Attribute::createWithSemantic(1, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD), + QSGGeometry::Attribute::createWithSemantic(2, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD1), + QSGGeometry::Attribute::createWithSemantic(3, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD2) + }; + static QSGGeometry::AttributeSet attrs = { 4, sizeof(SmoothVertex), data }; + return attrs; + } +} + +QSGBasicInternalImageNode::QSGBasicInternalImageNode() + : m_innerSourceRect(0, 0, 1, 1) + , m_subSourceRect(0, 0, 1, 1) + , m_antialiasing(false) + , m_mirror(false) + , m_dirtyGeometry(false) + , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) + , m_dynamicTexture(nullptr) +{ + setGeometry(&m_geometry); + +#ifdef QSG_RUNTIME_DESCRIPTION + qsgnode_set_description(this, QLatin1String("internalimage")); +#endif +} + +void QSGBasicInternalImageNode::setTargetRect(const QRectF &rect) +{ + if (rect == m_targetRect) + return; + m_targetRect = rect; + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setInnerTargetRect(const QRectF &rect) +{ + if (rect == m_innerTargetRect) + return; + m_innerTargetRect = rect; + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setInnerSourceRect(const QRectF &rect) +{ + if (rect == m_innerSourceRect) + return; + m_innerSourceRect = rect; + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setSubSourceRect(const QRectF &rect) +{ + if (rect == m_subSourceRect) + return; + m_subSourceRect = rect; + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setTexture(QSGTexture *texture) +{ + Q_ASSERT(texture); + + setMaterialTexture(texture); + updateMaterialBlending(); + + markDirty(DirtyMaterial); + + // Because the texture can be a different part of the atlas, we need to update it... + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setAntialiasing(bool antialiasing) +{ + if (antialiasing == m_antialiasing) + return; + m_antialiasing = antialiasing; + if (m_antialiasing) { + setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); + setFlag(OwnsGeometry, true); + } else { + setGeometry(&m_geometry); + setFlag(OwnsGeometry, false); + } + updateMaterialAntialiasing(); + m_dirtyGeometry = true; +} + +void QSGBasicInternalImageNode::setMirror(bool mirror) +{ + if (mirror == m_mirror) + return; + m_mirror = mirror; + m_dirtyGeometry = true; +} + + +void QSGBasicInternalImageNode::update() +{ + if (m_dirtyGeometry) + updateGeometry(); +} + +void QSGBasicInternalImageNode::preprocess() +{ + bool doDirty = false; + QSGDynamicTexture *t = qobject_cast(materialTexture()); + if (t) { + doDirty = t->updateTexture(); + if (doDirty) { + // The geometry may need updating. This is expensive however, so do + // it only when something relevant has changed. + if (t != m_dynamicTexture + || t->textureSize() != m_dynamicTextureSize + || t->normalizedTextureSubRect() != m_dynamicTextureSubRect) { + updateGeometry(); + m_dynamicTextureSize = t->textureSize(); + m_dynamicTextureSubRect = t->normalizedTextureSubRect(); + } + } + } + m_dynamicTexture = t; + + if (updateMaterialBlending()) + doDirty = true; + + if (doDirty) + markDirty(DirtyMaterial); +} + +namespace { + struct X { float x, tx; }; + struct Y { float y, ty; }; +} + +static inline void appendQuad(quint16 **indices, quint16 topLeft, quint16 topRight, + quint16 bottomLeft, quint16 bottomRight) +{ + *(*indices)++ = topLeft; + *(*indices)++ = bottomLeft; + *(*indices)++ = bottomRight; + *(*indices)++ = bottomRight; + *(*indices)++ = topRight; + *(*indices)++ = topLeft; +} + +QSGGeometry *QSGBasicInternalImageNode::updateGeometry(const QRectF &targetRect, + const QRectF &innerTargetRect, + const QRectF &sourceRect, + const QRectF &innerSourceRect, + const QRectF &subSourceRect, + QSGGeometry *geometry, + bool mirror, + bool antialiasing) +{ + int floorLeft = qFloor(subSourceRect.left()); + int ceilRight = qCeil(subSourceRect.right()); + int floorTop = qFloor(subSourceRect.top()); + int ceilBottom = qCeil(subSourceRect.bottom()); + int hTiles = ceilRight - floorLeft; + int vTiles = ceilBottom - floorTop; + + int hCells = hTiles; + int vCells = vTiles; + if (innerTargetRect.width() == 0) + hCells = 0; + if (innerTargetRect.left() != targetRect.left()) + ++hCells; + if (innerTargetRect.right() != targetRect.right()) + ++hCells; + if (innerTargetRect.height() == 0) + vCells = 0; + if (innerTargetRect.top() != targetRect.top()) + ++vCells; + if (innerTargetRect.bottom() != targetRect.bottom()) + ++vCells; + QVarLengthArray xData(2 * hCells); + QVarLengthArray yData(2 * vCells); + X *xs = xData.data(); + Y *ys = yData.data(); + + if (innerTargetRect.left() != targetRect.left()) { + xs[0].x = targetRect.left(); + xs[0].tx = sourceRect.left(); + xs[1].x = innerTargetRect.left(); + xs[1].tx = innerSourceRect.left(); + xs += 2; + } + if (innerTargetRect.width() != 0) { + xs[0].x = innerTargetRect.left(); + xs[0].tx = innerSourceRect.x() + (subSourceRect.left() - floorLeft) * innerSourceRect.width(); + ++xs; + float b = innerTargetRect.width() / subSourceRect.width(); + float a = innerTargetRect.x() - subSourceRect.x() * b; + for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) { + xs[0].x = xs[1].x = a + b * i; + xs[0].tx = innerSourceRect.right(); + xs[1].tx = innerSourceRect.left(); + xs += 2; + } + xs[0].x = innerTargetRect.right(); + xs[0].tx = innerSourceRect.x() + (subSourceRect.right() - ceilRight + 1) * innerSourceRect.width(); + ++xs; + } + if (innerTargetRect.right() != targetRect.right()) { + xs[0].x = innerTargetRect.right(); + xs[0].tx = innerSourceRect.right(); + xs[1].x = targetRect.right(); + xs[1].tx = sourceRect.right(); + xs += 2; + } + Q_ASSERT(xs == xData.data() + xData.size()); + if (mirror) { + float leftPlusRight = targetRect.left() + targetRect.right(); + int count = xData.size(); + xs = xData.data(); + for (int i = 0; i < count >> 1; ++i) + qSwap(xs[i], xs[count - 1 - i]); + for (int i = 0; i < count; ++i) + xs[i].x = leftPlusRight - xs[i].x; + } + + if (innerTargetRect.top() != targetRect.top()) { + ys[0].y = targetRect.top(); + ys[0].ty = sourceRect.top(); + ys[1].y = innerTargetRect.top(); + ys[1].ty = innerSourceRect.top(); + ys += 2; + } + if (innerTargetRect.height() != 0) { + ys[0].y = innerTargetRect.top(); + ys[0].ty = innerSourceRect.y() + (subSourceRect.top() - floorTop) * innerSourceRect.height(); + ++ys; + float b = innerTargetRect.height() / subSourceRect.height(); + float a = innerTargetRect.y() - subSourceRect.y() * b; + for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) { + ys[0].y = ys[1].y = a + b * i; + ys[0].ty = innerSourceRect.bottom(); + ys[1].ty = innerSourceRect.top(); + ys += 2; + } + ys[0].y = innerTargetRect.bottom(); + ys[0].ty = innerSourceRect.y() + (subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height(); + ++ys; + } + if (innerTargetRect.bottom() != targetRect.bottom()) { + ys[0].y = innerTargetRect.bottom(); + ys[0].ty = innerSourceRect.bottom(); + ys[1].y = targetRect.bottom(); + ys[1].ty = sourceRect.bottom(); + ys += 2; + } + Q_ASSERT(ys == yData.data() + yData.size()); + + if (antialiasing) { + QSGGeometry *g = geometry; + Q_ASSERT(g); + + g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4, + hCells * vCells * 6 + (hCells + vCells) * 12); + g->setDrawingMode(QSGGeometry::DrawTriangles); + SmoothVertex *vertices = reinterpret_cast(g->vertexData()); + memset(vertices, 0, g->vertexCount() * g->sizeOfVertex()); + quint16 *indices = g->indexDataAsUShort(); + + // The deltas are how much the fuzziness can reach into the image. + // Only the border vertices are moved by the vertex shader, so the fuzziness + // can't reach further into the image than the closest interior vertices. + float leftDx = xData.at(1).x - xData.at(0).x; + float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x; + float topDy = yData.at(1).y - yData.at(0).y; + float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y; + + float leftDu = xData.at(1).tx - xData.at(0).tx; + float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx; + float topDv = yData.at(1).ty - yData.at(0).ty; + float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty; + + if (hCells == 1) { + leftDx = rightDx *= 0.5f; + leftDu = rightDu *= 0.5f; + } + if (vCells == 1) { + topDy = bottomDy *= 0.5f; + topDv = bottomDv *= 0.5f; + } + + // This delta is how much the fuzziness can reach out from the image. + float delta = float(qAbs(targetRect.width()) < qAbs(targetRect.height()) + ? targetRect.width() : targetRect.height()) * 0.5f; + + quint16 index = 0; + ys = yData.data(); + for (int j = 0; j < vCells; ++j, ys += 2) { + xs = xData.data(); + bool isTop = j == 0; + bool isBottom = j == vCells - 1; + for (int i = 0; i < hCells; ++i, xs += 2) { + bool isLeft = i == 0; + bool isRight = i == hCells - 1; + + SmoothVertex *v = vertices + index; + + quint16 topLeft = index; + for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) { + v->x = xs[0].x; + v->u = xs[0].tx; + v->y = ys[0].y; + v->v = ys[0].ty; + } + + quint16 topRight = index; + for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) { + v->x = xs[1].x; + v->u = xs[1].tx; + v->y = ys[0].y; + v->v = ys[0].ty; + } + + quint16 bottomLeft = index; + for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) { + v->x = xs[0].x; + v->u = xs[0].tx; + v->y = ys[1].y; + v->v = ys[1].ty; + } + + quint16 bottomRight = index; + for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) { + v->x = xs[1].x; + v->u = xs[1].tx; + v->y = ys[1].y; + v->v = ys[1].ty; + } + + appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight); + + if (isTop) { + vertices[topLeft].dy = vertices[topRight].dy = topDy; + vertices[topLeft].dv = vertices[topRight].dv = topDv; + vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; + appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); + } + + if (isBottom) { + vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; + vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; + vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; + appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); + } + + if (isLeft) { + vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; + vertices[topLeft].du = vertices[bottomLeft].du = leftDu; + vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; + appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); + } + + if (isRight) { + vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; + vertices[topRight].du = vertices[bottomRight].du = -rightDu; + vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; + appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); + } + } + } + + Q_ASSERT(index == g->vertexCount()); + Q_ASSERT(indices - g->indexCount() == g->indexData()); + } else { + if (!geometry) { + geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), + hCells * vCells * 4, hCells * vCells * 6, + QSGGeometry::TypeUnsignedShort); + } else { + geometry->allocate(hCells * vCells * 4, hCells * vCells * 6); + } + geometry->setDrawingMode(QSGGeometry::DrawTriangles); + QSGGeometry::TexturedPoint2D *vertices = geometry->vertexDataAsTexturedPoint2D(); + ys = yData.data(); + for (int j = 0; j < vCells; ++j, ys += 2) { + xs = xData.data(); + for (int i = 0; i < hCells; ++i, xs += 2) { + vertices[0].x = vertices[2].x = xs[0].x; + vertices[0].tx = vertices[2].tx = xs[0].tx; + vertices[1].x = vertices[3].x = xs[1].x; + vertices[1].tx = vertices[3].tx = xs[1].tx; + + vertices[0].y = vertices[1].y = ys[0].y; + vertices[0].ty = vertices[1].ty = ys[0].ty; + vertices[2].y = vertices[3].y = ys[1].y; + vertices[2].ty = vertices[3].ty = ys[1].ty; + + vertices += 4; + } + } + + quint16 *indices = geometry->indexDataAsUShort(); + for (int i = 0; i < 4 * vCells * hCells; i += 4) + appendQuad(&indices, i, i + 1, i + 2, i + 3); + } + return geometry; +} + +void QSGBasicInternalImageNode::updateGeometry() +{ + Q_ASSERT(!m_targetRect.isEmpty()); + const QSGTexture *t = materialTexture(); + if (!t) { + QSGGeometry *g = geometry(); + g->allocate(4); + g->setDrawingMode(QSGGeometry::DrawTriangleStrip); + memset(g->vertexData(), 0, g->sizeOfVertex() * 4); + } else { + QRectF sourceRect = t->normalizedTextureSubRect(); + + QRectF innerSourceRect(sourceRect.x() + m_innerSourceRect.x() * sourceRect.width(), + sourceRect.y() + m_innerSourceRect.y() * sourceRect.height(), + m_innerSourceRect.width() * sourceRect.width(), + m_innerSourceRect.height() * sourceRect.height()); + + bool hasMargins = m_targetRect != m_innerTargetRect; + + int floorLeft = qFloor(m_subSourceRect.left()); + int ceilRight = qCeil(m_subSourceRect.right()); + int floorTop = qFloor(m_subSourceRect.top()); + int ceilBottom = qCeil(m_subSourceRect.bottom()); + int hTiles = ceilRight - floorLeft; + int vTiles = ceilBottom - floorTop; + + bool hasTiles = hTiles != 1 || vTiles != 1; + bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1); + + // An image can be rendered as a single quad if: + // - There are no margins, and either: + // - the image isn't repeated + // - the source rectangle fills the entire texture so that texture wrapping can be used, + // and NPOT is supported + if (!hasMargins && (!hasTiles || (fullTexture && supportsWrap(t->textureSize())))) { + QRectF sr; + if (!fullTexture) { + sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), + innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(), + m_subSourceRect.width() * innerSourceRect.width(), + m_subSourceRect.height() * innerSourceRect.height()); + } else { + sr = QRectF(m_subSourceRect.left() - floorLeft, m_subSourceRect.top() - floorTop, + m_subSourceRect.width(), m_subSourceRect.height()); + } + if (m_mirror) { + qreal oldLeft = sr.left(); + sr.setLeft(sr.right()); + sr.setRight(oldLeft); + } + + if (m_antialiasing) { + QSGGeometry *g = geometry(); + Q_ASSERT(g != &m_geometry); + g->allocate(8, 14); + g->setDrawingMode(QSGGeometry::DrawTriangleStrip); + SmoothVertex *vertices = reinterpret_cast(g->vertexData()); + float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) + ? m_targetRect.width() : m_targetRect.height()) * 0.5f; + float sx = float(sr.width() / m_targetRect.width()); + float sy = float(sr.height() / m_targetRect.height()); + for (int d = -1; d <= 1; d += 2) { + for (int j = 0; j < 2; ++j) { + for (int i = 0; i < 2; ++i, ++vertices) { + vertices->x = m_targetRect.x() + i * m_targetRect.width(); + vertices->y = m_targetRect.y() + j * m_targetRect.height(); + vertices->u = sr.x() + i * sr.width(); + vertices->v = sr.y() + j * sr.height(); + vertices->dx = (i == 0 ? delta : -delta) * d; + vertices->dy = (j == 0 ? delta : -delta) * d; + vertices->du = (d < 0 ? 0 : vertices->dx * sx); + vertices->dv = (d < 0 ? 0 : vertices->dy * sy); + } + } + } + Q_ASSERT(vertices - g->vertexCount() == g->vertexData()); + static const quint16 indices[] = { + 0, 4, 1, 5, 3, 7, 2, 6, 0, 4, + 4, 6, 5, 7 + }; + Q_ASSERT(g->sizeOfIndex() * g->indexCount() == sizeof(indices)); + memcpy(g->indexDataAsUShort(), indices, sizeof(indices)); + } else { + m_geometry.allocate(4); + m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); + QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr); + } + } else { + QSGGeometry *g = m_antialiasing ? geometry() : &m_geometry; + updateGeometry(m_targetRect, m_innerTargetRect, + sourceRect, innerSourceRect, m_subSourceRect, + g, m_mirror, m_antialiasing); + } + } + markDirty(DirtyGeometry); + m_dirtyGeometry = false; +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgbasicinternalimagenode_p.h b/src/quick/scenegraph/qsgbasicinternalimagenode_p.h new file mode 100644 index 0000000000..a5689b20aa --- /dev/null +++ b/src/quick/scenegraph/qsgbasicinternalimagenode_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGBASICINTERNALIMAGENODE_P_H +#define QSGBASICINTERNALIMAGENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGBasicInternalImageNode : public QSGInternalImageNode +{ +public: + QSGBasicInternalImageNode(); + + void setTargetRect(const QRectF &rect) override; + void setInnerTargetRect(const QRectF &rect) override; + void setInnerSourceRect(const QRectF &rect) override; + void setSubSourceRect(const QRectF &rect) override; + void setTexture(QSGTexture *texture) override; + void setAntialiasing(bool antialiasing) override; + void setMirror(bool mirror) override; + void update() override; + void preprocess() override; + + static QSGGeometry *updateGeometry(const QRectF &targetRect, + const QRectF &innerTargetRect, + const QRectF &sourceRect, + const QRectF &innerSourceRect, + const QRectF &subSourceRect, + QSGGeometry *geometry, + bool mirror = false, + bool antialiasing = false); + +protected: + virtual void updateMaterialAntialiasing() = 0; + virtual void setMaterialTexture(QSGTexture *texture) = 0; + virtual QSGTexture *materialTexture() const = 0; + virtual bool updateMaterialBlending() = 0; + virtual bool supportsWrap(const QSize &size) const = 0; + + void updateGeometry(); + + QRectF m_targetRect; + QRectF m_innerTargetRect; + QRectF m_innerSourceRect; + QRectF m_subSourceRect; + + uint m_antialiasing : 1; + uint m_mirror : 1; + uint m_dirtyGeometry : 1; + + QSGGeometry m_geometry; + + QSGDynamicTexture *m_dynamicTexture; + QSize m_dynamicTextureSize; + QRectF m_dynamicTextureSubRect; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp b/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp new file mode 100644 index 0000000000..8fc850b60c --- /dev/null +++ b/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp @@ -0,0 +1,687 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgbasicinternalrectanglenode_p.h" + +#include + +QT_BEGIN_NAMESPACE + +namespace +{ + struct Color4ub + { + unsigned char r, g, b, a; + }; + + Color4ub operator *(Color4ub c, float t) { c.a *= t; c.r *= t; c.g *= t; c.b *= t; return c; } + Color4ub operator +(Color4ub a, Color4ub b) { a.a += b.a; a.r += b.r; a.g += b.g; a.b += b.b; return a; } + + inline Color4ub colorToColor4ub(const QColor &c) + { + Color4ub color = { uchar(qRound(c.redF() * c.alphaF() * 255)), + uchar(qRound(c.greenF() * c.alphaF() * 255)), + uchar(qRound(c.blueF() * c.alphaF() * 255)), + uchar(qRound(c.alphaF() * 255)) + }; + return color; + } + + // Same layout as QSGGeometry::ColoredPoint2D, but uses Color4ub for convenience. + struct Vertex + { + float x, y; + Color4ub color; + void set(float nx, float ny, Color4ub ncolor) + { + x = nx; y = ny; color = ncolor; + } + }; + + struct SmoothVertex : public Vertex + { + float dx, dy; + void set(float nx, float ny, Color4ub ncolor, float ndx, float ndy) + { + Vertex::set(nx, ny, ncolor); + dx = ndx; dy = ndy; + } + }; + + const QSGGeometry::AttributeSet &smoothAttributeSet() + { + static QSGGeometry::Attribute data[] = { + QSGGeometry::Attribute::createWithSemantic(0, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::POSITION), + QSGGeometry::Attribute::createWithSemantic(1, 4, QSGGeometry::TypeUnsignedByte, QSGGeometry::Attribute::COLOR), + QSGGeometry::Attribute::createWithSemantic(2, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD) + }; + static QSGGeometry::AttributeSet attrs = { 3, sizeof(SmoothVertex), data }; + return attrs; + } +} + +QSGBasicInternalRectangleNode::QSGBasicInternalRectangleNode() + : m_radius(0) + , m_pen_width(0) + , m_aligned(true) + , m_antialiasing(false) + , m_gradient_is_opaque(true) + , m_dirty_geometry(false) + , m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0) +{ + setGeometry(&m_geometry); + +#ifdef QSG_RUNTIME_DESCRIPTION + qsgnode_set_description(this, QLatin1String("internalrectangle")); +#endif +} + +void QSGBasicInternalRectangleNode::setRect(const QRectF &rect) +{ + if (rect == m_rect) + return; + m_rect = rect; + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setColor(const QColor &color) +{ + if (color == m_color) + return; + m_color = color; + if (m_gradient_stops.isEmpty()) + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setPenColor(const QColor &color) +{ + if (color == m_border_color) + return; + m_border_color = color; + if (m_pen_width > 0) + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setPenWidth(qreal width) +{ + if (width == m_pen_width) + return; + m_pen_width = width; + m_dirty_geometry = true; +} + + +void QSGBasicInternalRectangleNode::setGradientStops(const QGradientStops &stops) +{ + if (stops.constData() == m_gradient_stops.constData()) + return; + + m_gradient_stops = stops; + + m_gradient_is_opaque = true; + for (int i = 0; i < stops.size(); ++i) + m_gradient_is_opaque &= stops.at(i).second.alpha() == 0xff; + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setRadius(qreal radius) +{ + if (radius == m_radius) + return; + m_radius = radius; + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setAntialiasing(bool antialiasing) +{ + if (!supportsAntialiasing()) + return; + + if (antialiasing == m_antialiasing) + return; + m_antialiasing = antialiasing; + if (m_antialiasing) { + setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); + setFlag(OwnsGeometry, true); + } else { + setGeometry(&m_geometry); + setFlag(OwnsGeometry, false); + } + updateMaterialAntialiasing(); + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::setAligned(bool aligned) +{ + if (aligned == m_aligned) + return; + m_aligned = aligned; + m_dirty_geometry = true; +} + +void QSGBasicInternalRectangleNode::update() +{ + if (m_dirty_geometry) { + updateGeometry(); + m_dirty_geometry = false; + + QSGNode::DirtyState state = QSGNode::DirtyGeometry; + updateMaterialBlending(&state); + markDirty(state); + } +} + +void QSGBasicInternalRectangleNode::updateGeometry() +{ + float width = float(m_rect.width()); + float height = float(m_rect.height()); + float penWidth = qMin(qMin(width, height) * 0.5f, float(m_pen_width)); + + if (m_aligned) + penWidth = qRound(penWidth); + + QSGGeometry *g = geometry(); + g->setDrawingMode(QSGGeometry::DrawTriangleStrip); + int vertexStride = g->sizeOfVertex(); + + union { + Vertex *vertices; + SmoothVertex *smoothVertices; + }; + + Color4ub fillColor = colorToColor4ub(m_color); + Color4ub borderColor = colorToColor4ub(m_border_color); + Color4ub transparent = { 0, 0, 0, 0 }; + const QGradientStops &stops = m_gradient_stops; + + int nextGradientStop = 0; + float gradientPos = penWidth / height; + while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos) + ++nextGradientStop; + int lastGradientStop = stops.size() - 1; + float lastGradientPos = 1.0f - penWidth / height; + while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos) + --lastGradientStop; + int gradientIntersections = (lastGradientStop - nextGradientStop + 1); + + if (m_radius > 0) { + // Rounded corners. + + // Radius should never exceeds half of the width or half of the height + float radius = qMin(qMin(width, height) * 0.5f, float(m_radius)); + QRectF innerRect = m_rect; + innerRect.adjust(radius, radius, -radius, -radius); + + float innerRadius = radius - penWidth * 1.0f; + float outerRadius = radius; + float delta = qMin(width, height) * 0.5f; + + // Number of segments per corner, approximately one per 3 pixels. + int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18); + + /* + + --+--__ + --+--__--__ + | --__--__ + | seg --__--+ + --+-__ ment _+ \ + --+-__--__ - \ \ + --__--+ se \ \ + + \ g \ \ + \ \ m \ \ + -----------+--+ e \ \ <- gradient line + \ \ nt\ \ + fill +--+----+--+ + | | | | + border + inner AA outer AA (AA = antialiasing) + + */ + + int innerVertexCount = (segments + 1) * 4 + gradientIntersections * 2; + int outerVertexCount = (segments + 1) * 4; + int vertexCount = innerVertexCount; + if (m_antialiasing || penWidth) + vertexCount += innerVertexCount; + if (penWidth) + vertexCount += outerVertexCount; + if (m_antialiasing && penWidth) + vertexCount += outerVertexCount; + + int fillIndexCount = innerVertexCount; + int innerAAIndexCount = innerVertexCount * 2 + 2; + int borderIndexCount = innerVertexCount * 2 + 2; + int outerAAIndexCount = outerVertexCount * 2 + 2; + int indexCount = 0; + int fillHead = 0; + int innerAAHead = 0; + int innerAATail = 0; + int borderHead = 0; + int borderTail = 0; + int outerAAHead = 0; + int outerAATail = 0; + bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); + if (hasFill) + indexCount += fillIndexCount; + if (m_antialiasing) { + innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1; + indexCount += innerAAIndexCount; + } + if (penWidth) { + borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1; + indexCount += borderIndexCount; + } + if (m_antialiasing && penWidth) { + outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1; + indexCount += outerAAIndexCount; + } + + g->allocate(vertexCount, indexCount); + vertices = reinterpret_cast(g->vertexData()); + memset(vertices, 0, vertexCount * vertexStride); + quint16 *indices = g->indexDataAsUShort(); + quint16 index = 0; + + float py = 0; // previous inner y-coordinate. + float plx = 0; // previous inner left x-coordinate. + float prx = 0; // previous inner right x-coordinate. + + float angle = 0.5f * float(M_PI) / segments; + float cosStep = qFastCos(angle); + float sinStep = qFastSin(angle); + + for (int part = 0; part < 2; ++part) { + float c = 1 - part; + float s = part; + for (int i = 0; i <= segments; ++i) { + float y, lx, rx; + if (innerRadius > 0) { + y = (part ? innerRect.bottom() : innerRect.top()) - innerRadius * c; // current inner y-coordinate. + lx = innerRect.left() - innerRadius * s; // current inner left x-coordinate. + rx = innerRect.right() + innerRadius * s; // current inner right x-coordinate. + gradientPos = ((part ? innerRect.height() : 0) + radius - innerRadius * c) / height; + } else { + y = (part ? innerRect.bottom() + innerRadius : innerRect.top() - innerRadius); // current inner y-coordinate. + lx = innerRect.left() - innerRadius; // current inner left x-coordinate. + rx = innerRect.right() + innerRadius; // current inner right x-coordinate. + gradientPos = ((part ? innerRect.height() + innerRadius : -innerRadius) + radius) / height; + } + float Y = (part ? innerRect.bottom() : innerRect.top()) - outerRadius * c; // current outer y-coordinate. + float lX = innerRect.left() - outerRadius * s; // current outer left x-coordinate. + float rX = innerRect.right() + outerRadius * s; // current outer right x-coordinate. + + while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) { + // Insert vertices at gradient stops. + float gy = (innerRect.top() - radius) + stops.at(nextGradientStop).first * height; + float t = (gy - py) / (y - py); + float glx = plx * (1 - t) + t * lx; + float grx = prx * (1 - t) + t * rx; + + fillColor = colorToColor4ub(stops.at(nextGradientStop).second); + + if (hasFill) { + indices[fillHead++] = index; + indices[fillHead++] = index + 1; + } + + if (penWidth) { + --borderHead; + indices[borderHead] = indices[borderHead + 2]; + indices[--borderHead] = index + 2; + indices[borderTail++] = index + 3; + indices[borderTail] = indices[borderTail - 2]; + ++borderTail; + } + + if (m_antialiasing) { + indices[--innerAAHead] = index + 2; + indices[--innerAAHead] = index; + indices[innerAATail++] = index + 1; + indices[innerAATail++] = index + 3; + + bool lower = stops.at(nextGradientStop).first > 0.5f; + float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy); + smoothVertices[index++].set(grx, gy, fillColor, width - grx - delta, dy); + smoothVertices[index++].set(glx, gy, fillColor, delta - glx, dy); + if (penWidth) { + smoothVertices[index++].set(grx, gy, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c); + smoothVertices[index++].set(glx, gy, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c); + } else { + dy = lower ? delta : -delta; + smoothVertices[index++].set(grx, gy, transparent, delta, dy); + smoothVertices[index++].set(glx, gy, transparent, -delta, dy); + } + } else { + vertices[index++].set(grx, gy, fillColor); + vertices[index++].set(glx, gy, fillColor); + if (penWidth) { + vertices[index++].set(grx, gy, borderColor); + vertices[index++].set(glx, gy, borderColor); + } + } + ++nextGradientStop; + } + + if (!stops.isEmpty()) { + if (nextGradientStop == 0) { + fillColor = colorToColor4ub(stops.at(0).second); + } else if (nextGradientStop == stops.size()) { + fillColor = colorToColor4ub(stops.last().second); + } else { + const QGradientStop &prev = stops.at(nextGradientStop - 1); + const QGradientStop &next = stops.at(nextGradientStop); + float t = (gradientPos - prev.first) / (next.first - prev.first); + fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t; + } + } + + if (hasFill) { + indices[fillHead++] = index; + indices[fillHead++] = index + 1; + } + + if (penWidth) { + indices[--borderHead] = index + 4; + indices[--borderHead] = index + 2; + indices[borderTail++] = index + 3; + indices[borderTail++] = index + 5; + } + + if (m_antialiasing) { + indices[--innerAAHead] = index + 2; + indices[--innerAAHead] = index; + indices[innerAATail++] = index + 1; + indices[innerAATail++] = index + 3; + + float dy = part ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y); + smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy); + smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy); + + dy = part ? delta : -delta; + if (penWidth) { + smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c); + smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c); + smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth * s, 0.49f * penWidth * c); + smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth * s, 0.49f * penWidth * c); + smoothVertices[index++].set(rX, Y, transparent, delta, dy); + smoothVertices[index++].set(lX, Y, transparent, -delta, dy); + + indices[--outerAAHead] = index - 2; + indices[--outerAAHead] = index - 4; + indices[outerAATail++] = index - 3; + indices[outerAATail++] = index - 1; + } else { + smoothVertices[index++].set(rx, y, transparent, delta, dy); + smoothVertices[index++].set(lx, y, transparent, -delta, dy); + } + } else { + vertices[index++].set(rx, y, fillColor); + vertices[index++].set(lx, y, fillColor); + if (penWidth) { + vertices[index++].set(rx, y, borderColor); + vertices[index++].set(lx, y, borderColor); + vertices[index++].set(rX, Y, borderColor); + vertices[index++].set(lX, Y, borderColor); + } + } + + py = y; + plx = lx; + prx = rx; + + // Rotate + qreal tmp = c; + c = c * cosStep - s * sinStep; + s = s * cosStep + tmp * sinStep; + } + } + Q_ASSERT(index == vertexCount); + + // Close the triangle strips. + if (m_antialiasing) { + indices[--innerAAHead] = indices[innerAATail - 1]; + indices[--innerAAHead] = indices[innerAATail - 2]; + Q_ASSERT(innerAATail <= indexCount); + } + if (penWidth) { + indices[--borderHead] = indices[borderTail - 1]; + indices[--borderHead] = indices[borderTail - 2]; + Q_ASSERT(borderTail <= indexCount); + } + if (m_antialiasing && penWidth) { + indices[--outerAAHead] = indices[outerAATail - 1]; + indices[--outerAAHead] = indices[outerAATail - 2]; + Q_ASSERT(outerAATail == indexCount); + } + } else { + // Straight corners. + QRectF innerRect = m_rect; + QRectF outerRect = m_rect; + + if (penWidth) + innerRect.adjust(1.0f * penWidth, 1.0f * penWidth, -1.0f * penWidth, -1.0f * penWidth); + + float delta = qMin(width, height) * 0.5f; + int innerVertexCount = 4 + gradientIntersections * 2; + int outerVertexCount = 4; + int vertexCount = innerVertexCount; + if (m_antialiasing || penWidth) + vertexCount += innerVertexCount; + if (penWidth) + vertexCount += outerVertexCount; + if (m_antialiasing && penWidth) + vertexCount += outerVertexCount; + + int fillIndexCount = innerVertexCount; + int innerAAIndexCount = innerVertexCount * 2 + 2; + int borderIndexCount = innerVertexCount * 2 + 2; + int outerAAIndexCount = outerVertexCount * 2 + 2; + int indexCount = 0; + int fillHead = 0; + int innerAAHead = 0; + int innerAATail = 0; + int borderHead = 0; + int borderTail = 0; + int outerAAHead = 0; + int outerAATail = 0; + bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); + if (hasFill) + indexCount += fillIndexCount; + if (m_antialiasing) { + innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1; + indexCount += innerAAIndexCount; + } + if (penWidth) { + borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1; + indexCount += borderIndexCount; + } + if (m_antialiasing && penWidth) { + outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1; + indexCount += outerAAIndexCount; + } + + g->allocate(vertexCount, indexCount); + vertices = reinterpret_cast(g->vertexData()); + memset(vertices, 0, vertexCount * vertexStride); + quint16 *indices = g->indexDataAsUShort(); + quint16 index = 0; + + float lx = innerRect.left(); + float rx = innerRect.right(); + float lX = outerRect.left(); + float rX = outerRect.right(); + + for (int part = -1; part <= 1; part += 2) { + float y = (part == 1 ? innerRect.bottom() : innerRect.top()); + float Y = (part == 1 ? outerRect.bottom() : outerRect.top()); + gradientPos = (y - innerRect.top() + penWidth) / height; + + while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) { + // Insert vertices at gradient stops. + float gy = (innerRect.top() - penWidth) + stops.at(nextGradientStop).first * height; + + fillColor = colorToColor4ub(stops.at(nextGradientStop).second); + + if (hasFill) { + indices[fillHead++] = index; + indices[fillHead++] = index + 1; + } + + if (penWidth) { + --borderHead; + indices[borderHead] = indices[borderHead + 2]; + indices[--borderHead] = index + 2; + indices[borderTail++] = index + 3; + indices[borderTail] = indices[borderTail - 2]; + ++borderTail; + } + + if (m_antialiasing) { + indices[--innerAAHead] = index + 2; + indices[--innerAAHead] = index; + indices[innerAATail++] = index + 1; + indices[innerAATail++] = index + 3; + + bool lower = stops.at(nextGradientStop).first > 0.5f; + float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy); + smoothVertices[index++].set(rx, gy, fillColor, width - rx - delta, dy); + smoothVertices[index++].set(lx, gy, fillColor, delta - lx, dy); + if (penWidth) { + smoothVertices[index++].set(rx, gy, borderColor, 0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth); + smoothVertices[index++].set(lx, gy, borderColor, -0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth); + } else { + smoothVertices[index++].set(rx, gy, transparent, delta, lower ? delta : -delta); + smoothVertices[index++].set(lx, gy, transparent, -delta, lower ? delta : -delta); + } + } else { + vertices[index++].set(rx, gy, fillColor); + vertices[index++].set(lx, gy, fillColor); + if (penWidth) { + vertices[index++].set(rx, gy, borderColor); + vertices[index++].set(lx, gy, borderColor); + } + } + ++nextGradientStop; + } + + if (!stops.isEmpty()) { + if (nextGradientStop == 0) { + fillColor = colorToColor4ub(stops.at(0).second); + } else if (nextGradientStop == stops.size()) { + fillColor = colorToColor4ub(stops.last().second); + } else { + const QGradientStop &prev = stops.at(nextGradientStop - 1); + const QGradientStop &next = stops.at(nextGradientStop); + float t = (gradientPos - prev.first) / (next.first - prev.first); + fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t; + } + } + + if (hasFill) { + indices[fillHead++] = index; + indices[fillHead++] = index + 1; + } + + if (penWidth) { + indices[--borderHead] = index + 4; + indices[--borderHead] = index + 2; + indices[borderTail++] = index + 3; + indices[borderTail++] = index + 5; + } + + if (m_antialiasing) { + indices[--innerAAHead] = index + 2; + indices[--innerAAHead] = index; + indices[innerAATail++] = index + 1; + indices[innerAATail++] = index + 3; + + float dy = part == 1 ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y); + smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy); + smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy); + + if (penWidth) { + smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth, 0.49f * penWidth * part); + smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth, 0.49f * penWidth * part); + smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth, -0.49f * penWidth * part); + smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth, -0.49f * penWidth * part); + smoothVertices[index++].set(rX, Y, transparent, delta, delta * part); + smoothVertices[index++].set(lX, Y, transparent, -delta, delta * part); + + indices[--outerAAHead] = index - 2; + indices[--outerAAHead] = index - 4; + indices[outerAATail++] = index - 3; + indices[outerAATail++] = index - 1; + } else { + smoothVertices[index++].set(rx, y, transparent, delta, delta * part); + smoothVertices[index++].set(lx, y, transparent, -delta, delta * part); + } + } else { + vertices[index++].set(rx, y, fillColor); + vertices[index++].set(lx, y, fillColor); + if (penWidth) { + vertices[index++].set(rx, y, borderColor); + vertices[index++].set(lx, y, borderColor); + vertices[index++].set(rX, Y, borderColor); + vertices[index++].set(lX, Y, borderColor); + } + } + } + Q_ASSERT(index == vertexCount); + + // Close the triangle strips. + if (m_antialiasing) { + indices[--innerAAHead] = indices[innerAATail - 1]; + indices[--innerAAHead] = indices[innerAATail - 2]; + Q_ASSERT(innerAATail <= indexCount); + } + if (penWidth) { + indices[--borderHead] = indices[borderTail - 1]; + indices[--borderHead] = indices[borderTail - 2]; + Q_ASSERT(borderTail <= indexCount); + } + if (m_antialiasing && penWidth) { + indices[--outerAAHead] = indices[outerAATail - 1]; + indices[--outerAAHead] = indices[outerAATail - 2]; + Q_ASSERT(outerAATail == indexCount); + } + } +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h b/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h new file mode 100644 index 0000000000..98e53669ce --- /dev/null +++ b/src/quick/scenegraph/qsgbasicinternalrectanglenode_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSGBASICINTERNALRECTANGLENODE_P_H +#define QSGBASICINTERNALRECTANGLENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGBasicInternalRectangleNode : public QSGInternalRectangleNode +{ +public: + QSGBasicInternalRectangleNode(); + + void setRect(const QRectF &rect) override; + void setColor(const QColor &color) override; + void setPenColor(const QColor &color) override; + void setPenWidth(qreal width) override; + void setGradientStops(const QGradientStops &stops) override; + void setRadius(qreal radius) override; + void setAntialiasing(bool antialiasing) override; + void setAligned(bool aligned) override; + void update() override; + +protected: + virtual bool supportsAntialiasing() const { return true; } + virtual void updateMaterialAntialiasing() = 0; + virtual void updateMaterialBlending(QSGNode::DirtyState *state) = 0; + + void updateGeometry(); + void updateGradientTexture(); + + QRectF m_rect; + QGradientStops m_gradient_stops; + QColor m_color; + QColor m_border_color; + qreal m_radius; + qreal m_pen_width; + + uint m_aligned : 1; + uint m_antialiasing : 1; + uint m_gradient_is_opaque : 1; + uint m_dirty_geometry : 1; + + QSGGeometry m_geometry; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/qsgbasicrectanglenode.cpp b/src/quick/scenegraph/qsgbasicrectanglenode.cpp deleted file mode 100644 index 14d2dc9677..0000000000 --- a/src/quick/scenegraph/qsgbasicrectanglenode.cpp +++ /dev/null @@ -1,687 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgbasicrectanglenode_p.h" - -#include - -QT_BEGIN_NAMESPACE - -namespace -{ - struct Color4ub - { - unsigned char r, g, b, a; - }; - - Color4ub operator *(Color4ub c, float t) { c.a *= t; c.r *= t; c.g *= t; c.b *= t; return c; } - Color4ub operator +(Color4ub a, Color4ub b) { a.a += b.a; a.r += b.r; a.g += b.g; a.b += b.b; return a; } - - inline Color4ub colorToColor4ub(const QColor &c) - { - Color4ub color = { uchar(qRound(c.redF() * c.alphaF() * 255)), - uchar(qRound(c.greenF() * c.alphaF() * 255)), - uchar(qRound(c.blueF() * c.alphaF() * 255)), - uchar(qRound(c.alphaF() * 255)) - }; - return color; - } - - // Same layout as QSGGeometry::ColoredPoint2D, but uses Color4ub for convenience. - struct Vertex - { - float x, y; - Color4ub color; - void set(float nx, float ny, Color4ub ncolor) - { - x = nx; y = ny; color = ncolor; - } - }; - - struct SmoothVertex : public Vertex - { - float dx, dy; - void set(float nx, float ny, Color4ub ncolor, float ndx, float ndy) - { - Vertex::set(nx, ny, ncolor); - dx = ndx; dy = ndy; - } - }; - - const QSGGeometry::AttributeSet &smoothAttributeSet() - { - static QSGGeometry::Attribute data[] = { - QSGGeometry::Attribute::createWithSemantic(0, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::POSITION), - QSGGeometry::Attribute::createWithSemantic(1, 4, QSGGeometry::TypeUnsignedByte, QSGGeometry::Attribute::COLOR), - QSGGeometry::Attribute::createWithSemantic(2, 2, QSGGeometry::TypeFloat, QSGGeometry::Attribute::TEXCOORD) - }; - static QSGGeometry::AttributeSet attrs = { 3, sizeof(SmoothVertex), data }; - return attrs; - } -} - -QSGBasicRectangleNode::QSGBasicRectangleNode() - : m_radius(0) - , m_pen_width(0) - , m_aligned(true) - , m_antialiasing(false) - , m_gradient_is_opaque(true) - , m_dirty_geometry(false) - , m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0) -{ - setGeometry(&m_geometry); - -#ifdef QSG_RUNTIME_DESCRIPTION - qsgnode_set_description(this, QLatin1String("rectangle")); -#endif -} - -void QSGBasicRectangleNode::setRect(const QRectF &rect) -{ - if (rect == m_rect) - return; - m_rect = rect; - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setColor(const QColor &color) -{ - if (color == m_color) - return; - m_color = color; - if (m_gradient_stops.isEmpty()) - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setPenColor(const QColor &color) -{ - if (color == m_border_color) - return; - m_border_color = color; - if (m_pen_width > 0) - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setPenWidth(qreal width) -{ - if (width == m_pen_width) - return; - m_pen_width = width; - m_dirty_geometry = true; -} - - -void QSGBasicRectangleNode::setGradientStops(const QGradientStops &stops) -{ - if (stops.constData() == m_gradient_stops.constData()) - return; - - m_gradient_stops = stops; - - m_gradient_is_opaque = true; - for (int i = 0; i < stops.size(); ++i) - m_gradient_is_opaque &= stops.at(i).second.alpha() == 0xff; - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setRadius(qreal radius) -{ - if (radius == m_radius) - return; - m_radius = radius; - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setAntialiasing(bool antialiasing) -{ - if (!supportsAntialiasing()) - return; - - if (antialiasing == m_antialiasing) - return; - m_antialiasing = antialiasing; - if (m_antialiasing) { - setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); - setFlag(OwnsGeometry, true); - } else { - setGeometry(&m_geometry); - setFlag(OwnsGeometry, false); - } - updateMaterialAntialiasing(); - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::setAligned(bool aligned) -{ - if (aligned == m_aligned) - return; - m_aligned = aligned; - m_dirty_geometry = true; -} - -void QSGBasicRectangleNode::update() -{ - if (m_dirty_geometry) { - updateGeometry(); - m_dirty_geometry = false; - - QSGNode::DirtyState state = QSGNode::DirtyGeometry; - updateMaterialBlending(&state); - markDirty(state); - } -} - -void QSGBasicRectangleNode::updateGeometry() -{ - float width = float(m_rect.width()); - float height = float(m_rect.height()); - float penWidth = qMin(qMin(width, height) * 0.5f, float(m_pen_width)); - - if (m_aligned) - penWidth = qRound(penWidth); - - QSGGeometry *g = geometry(); - g->setDrawingMode(QSGGeometry::DrawTriangleStrip); - int vertexStride = g->sizeOfVertex(); - - union { - Vertex *vertices; - SmoothVertex *smoothVertices; - }; - - Color4ub fillColor = colorToColor4ub(m_color); - Color4ub borderColor = colorToColor4ub(m_border_color); - Color4ub transparent = { 0, 0, 0, 0 }; - const QGradientStops &stops = m_gradient_stops; - - int nextGradientStop = 0; - float gradientPos = penWidth / height; - while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos) - ++nextGradientStop; - int lastGradientStop = stops.size() - 1; - float lastGradientPos = 1.0f - penWidth / height; - while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos) - --lastGradientStop; - int gradientIntersections = (lastGradientStop - nextGradientStop + 1); - - if (m_radius > 0) { - // Rounded corners. - - // Radius should never exceeds half of the width or half of the height - float radius = qMin(qMin(width, height) * 0.5f, float(m_radius)); - QRectF innerRect = m_rect; - innerRect.adjust(radius, radius, -radius, -radius); - - float innerRadius = radius - penWidth * 1.0f; - float outerRadius = radius; - float delta = qMin(width, height) * 0.5f; - - // Number of segments per corner, approximately one per 3 pixels. - int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18); - - /* - - --+--__ - --+--__--__ - | --__--__ - | seg --__--+ - --+-__ ment _+ \ - --+-__--__ - \ \ - --__--+ se \ \ - + \ g \ \ - \ \ m \ \ - -----------+--+ e \ \ <- gradient line - \ \ nt\ \ - fill +--+----+--+ - | | | | - border - inner AA outer AA (AA = antialiasing) - - */ - - int innerVertexCount = (segments + 1) * 4 + gradientIntersections * 2; - int outerVertexCount = (segments + 1) * 4; - int vertexCount = innerVertexCount; - if (m_antialiasing || penWidth) - vertexCount += innerVertexCount; - if (penWidth) - vertexCount += outerVertexCount; - if (m_antialiasing && penWidth) - vertexCount += outerVertexCount; - - int fillIndexCount = innerVertexCount; - int innerAAIndexCount = innerVertexCount * 2 + 2; - int borderIndexCount = innerVertexCount * 2 + 2; - int outerAAIndexCount = outerVertexCount * 2 + 2; - int indexCount = 0; - int fillHead = 0; - int innerAAHead = 0; - int innerAATail = 0; - int borderHead = 0; - int borderTail = 0; - int outerAAHead = 0; - int outerAATail = 0; - bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); - if (hasFill) - indexCount += fillIndexCount; - if (m_antialiasing) { - innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1; - indexCount += innerAAIndexCount; - } - if (penWidth) { - borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1; - indexCount += borderIndexCount; - } - if (m_antialiasing && penWidth) { - outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1; - indexCount += outerAAIndexCount; - } - - g->allocate(vertexCount, indexCount); - vertices = reinterpret_cast(g->vertexData()); - memset(vertices, 0, vertexCount * vertexStride); - quint16 *indices = g->indexDataAsUShort(); - quint16 index = 0; - - float py = 0; // previous inner y-coordinate. - float plx = 0; // previous inner left x-coordinate. - float prx = 0; // previous inner right x-coordinate. - - float angle = 0.5f * float(M_PI) / segments; - float cosStep = qFastCos(angle); - float sinStep = qFastSin(angle); - - for (int part = 0; part < 2; ++part) { - float c = 1 - part; - float s = part; - for (int i = 0; i <= segments; ++i) { - float y, lx, rx; - if (innerRadius > 0) { - y = (part ? innerRect.bottom() : innerRect.top()) - innerRadius * c; // current inner y-coordinate. - lx = innerRect.left() - innerRadius * s; // current inner left x-coordinate. - rx = innerRect.right() + innerRadius * s; // current inner right x-coordinate. - gradientPos = ((part ? innerRect.height() : 0) + radius - innerRadius * c) / height; - } else { - y = (part ? innerRect.bottom() + innerRadius : innerRect.top() - innerRadius); // current inner y-coordinate. - lx = innerRect.left() - innerRadius; // current inner left x-coordinate. - rx = innerRect.right() + innerRadius; // current inner right x-coordinate. - gradientPos = ((part ? innerRect.height() + innerRadius : -innerRadius) + radius) / height; - } - float Y = (part ? innerRect.bottom() : innerRect.top()) - outerRadius * c; // current outer y-coordinate. - float lX = innerRect.left() - outerRadius * s; // current outer left x-coordinate. - float rX = innerRect.right() + outerRadius * s; // current outer right x-coordinate. - - while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) { - // Insert vertices at gradient stops. - float gy = (innerRect.top() - radius) + stops.at(nextGradientStop).first * height; - float t = (gy - py) / (y - py); - float glx = plx * (1 - t) + t * lx; - float grx = prx * (1 - t) + t * rx; - - fillColor = colorToColor4ub(stops.at(nextGradientStop).second); - - if (hasFill) { - indices[fillHead++] = index; - indices[fillHead++] = index + 1; - } - - if (penWidth) { - --borderHead; - indices[borderHead] = indices[borderHead + 2]; - indices[--borderHead] = index + 2; - indices[borderTail++] = index + 3; - indices[borderTail] = indices[borderTail - 2]; - ++borderTail; - } - - if (m_antialiasing) { - indices[--innerAAHead] = index + 2; - indices[--innerAAHead] = index; - indices[innerAATail++] = index + 1; - indices[innerAATail++] = index + 3; - - bool lower = stops.at(nextGradientStop).first > 0.5f; - float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy); - smoothVertices[index++].set(grx, gy, fillColor, width - grx - delta, dy); - smoothVertices[index++].set(glx, gy, fillColor, delta - glx, dy); - if (penWidth) { - smoothVertices[index++].set(grx, gy, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c); - smoothVertices[index++].set(glx, gy, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c); - } else { - dy = lower ? delta : -delta; - smoothVertices[index++].set(grx, gy, transparent, delta, dy); - smoothVertices[index++].set(glx, gy, transparent, -delta, dy); - } - } else { - vertices[index++].set(grx, gy, fillColor); - vertices[index++].set(glx, gy, fillColor); - if (penWidth) { - vertices[index++].set(grx, gy, borderColor); - vertices[index++].set(glx, gy, borderColor); - } - } - ++nextGradientStop; - } - - if (!stops.isEmpty()) { - if (nextGradientStop == 0) { - fillColor = colorToColor4ub(stops.at(0).second); - } else if (nextGradientStop == stops.size()) { - fillColor = colorToColor4ub(stops.last().second); - } else { - const QGradientStop &prev = stops.at(nextGradientStop - 1); - const QGradientStop &next = stops.at(nextGradientStop); - float t = (gradientPos - prev.first) / (next.first - prev.first); - fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t; - } - } - - if (hasFill) { - indices[fillHead++] = index; - indices[fillHead++] = index + 1; - } - - if (penWidth) { - indices[--borderHead] = index + 4; - indices[--borderHead] = index + 2; - indices[borderTail++] = index + 3; - indices[borderTail++] = index + 5; - } - - if (m_antialiasing) { - indices[--innerAAHead] = index + 2; - indices[--innerAAHead] = index; - indices[innerAATail++] = index + 1; - indices[innerAATail++] = index + 3; - - float dy = part ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y); - smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy); - smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy); - - dy = part ? delta : -delta; - if (penWidth) { - smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth * s, -0.49f * penWidth * c); - smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth * s, -0.49f * penWidth * c); - smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth * s, 0.49f * penWidth * c); - smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth * s, 0.49f * penWidth * c); - smoothVertices[index++].set(rX, Y, transparent, delta, dy); - smoothVertices[index++].set(lX, Y, transparent, -delta, dy); - - indices[--outerAAHead] = index - 2; - indices[--outerAAHead] = index - 4; - indices[outerAATail++] = index - 3; - indices[outerAATail++] = index - 1; - } else { - smoothVertices[index++].set(rx, y, transparent, delta, dy); - smoothVertices[index++].set(lx, y, transparent, -delta, dy); - } - } else { - vertices[index++].set(rx, y, fillColor); - vertices[index++].set(lx, y, fillColor); - if (penWidth) { - vertices[index++].set(rx, y, borderColor); - vertices[index++].set(lx, y, borderColor); - vertices[index++].set(rX, Y, borderColor); - vertices[index++].set(lX, Y, borderColor); - } - } - - py = y; - plx = lx; - prx = rx; - - // Rotate - qreal tmp = c; - c = c * cosStep - s * sinStep; - s = s * cosStep + tmp * sinStep; - } - } - Q_ASSERT(index == vertexCount); - - // Close the triangle strips. - if (m_antialiasing) { - indices[--innerAAHead] = indices[innerAATail - 1]; - indices[--innerAAHead] = indices[innerAATail - 2]; - Q_ASSERT(innerAATail <= indexCount); - } - if (penWidth) { - indices[--borderHead] = indices[borderTail - 1]; - indices[--borderHead] = indices[borderTail - 2]; - Q_ASSERT(borderTail <= indexCount); - } - if (m_antialiasing && penWidth) { - indices[--outerAAHead] = indices[outerAATail - 1]; - indices[--outerAAHead] = indices[outerAATail - 2]; - Q_ASSERT(outerAATail == indexCount); - } - } else { - // Straight corners. - QRectF innerRect = m_rect; - QRectF outerRect = m_rect; - - if (penWidth) - innerRect.adjust(1.0f * penWidth, 1.0f * penWidth, -1.0f * penWidth, -1.0f * penWidth); - - float delta = qMin(width, height) * 0.5f; - int innerVertexCount = 4 + gradientIntersections * 2; - int outerVertexCount = 4; - int vertexCount = innerVertexCount; - if (m_antialiasing || penWidth) - vertexCount += innerVertexCount; - if (penWidth) - vertexCount += outerVertexCount; - if (m_antialiasing && penWidth) - vertexCount += outerVertexCount; - - int fillIndexCount = innerVertexCount; - int innerAAIndexCount = innerVertexCount * 2 + 2; - int borderIndexCount = innerVertexCount * 2 + 2; - int outerAAIndexCount = outerVertexCount * 2 + 2; - int indexCount = 0; - int fillHead = 0; - int innerAAHead = 0; - int innerAATail = 0; - int borderHead = 0; - int borderTail = 0; - int outerAAHead = 0; - int outerAATail = 0; - bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); - if (hasFill) - indexCount += fillIndexCount; - if (m_antialiasing) { - innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1; - indexCount += innerAAIndexCount; - } - if (penWidth) { - borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1; - indexCount += borderIndexCount; - } - if (m_antialiasing && penWidth) { - outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1; - indexCount += outerAAIndexCount; - } - - g->allocate(vertexCount, indexCount); - vertices = reinterpret_cast(g->vertexData()); - memset(vertices, 0, vertexCount * vertexStride); - quint16 *indices = g->indexDataAsUShort(); - quint16 index = 0; - - float lx = innerRect.left(); - float rx = innerRect.right(); - float lX = outerRect.left(); - float rX = outerRect.right(); - - for (int part = -1; part <= 1; part += 2) { - float y = (part == 1 ? innerRect.bottom() : innerRect.top()); - float Y = (part == 1 ? outerRect.bottom() : outerRect.top()); - gradientPos = (y - innerRect.top() + penWidth) / height; - - while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) { - // Insert vertices at gradient stops. - float gy = (innerRect.top() - penWidth) + stops.at(nextGradientStop).first * height; - - fillColor = colorToColor4ub(stops.at(nextGradientStop).second); - - if (hasFill) { - indices[fillHead++] = index; - indices[fillHead++] = index + 1; - } - - if (penWidth) { - --borderHead; - indices[borderHead] = indices[borderHead + 2]; - indices[--borderHead] = index + 2; - indices[borderTail++] = index + 3; - indices[borderTail] = indices[borderTail - 2]; - ++borderTail; - } - - if (m_antialiasing) { - indices[--innerAAHead] = index + 2; - indices[--innerAAHead] = index; - indices[innerAATail++] = index + 1; - indices[innerAATail++] = index + 3; - - bool lower = stops.at(nextGradientStop).first > 0.5f; - float dy = lower ? qMin(0.0f, height - gy - delta) : qMax(0.0f, delta - gy); - smoothVertices[index++].set(rx, gy, fillColor, width - rx - delta, dy); - smoothVertices[index++].set(lx, gy, fillColor, delta - lx, dy); - if (penWidth) { - smoothVertices[index++].set(rx, gy, borderColor, 0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth); - smoothVertices[index++].set(lx, gy, borderColor, -0.49f * penWidth, (lower ? 0.49f : -0.49f) * penWidth); - } else { - smoothVertices[index++].set(rx, gy, transparent, delta, lower ? delta : -delta); - smoothVertices[index++].set(lx, gy, transparent, -delta, lower ? delta : -delta); - } - } else { - vertices[index++].set(rx, gy, fillColor); - vertices[index++].set(lx, gy, fillColor); - if (penWidth) { - vertices[index++].set(rx, gy, borderColor); - vertices[index++].set(lx, gy, borderColor); - } - } - ++nextGradientStop; - } - - if (!stops.isEmpty()) { - if (nextGradientStop == 0) { - fillColor = colorToColor4ub(stops.at(0).second); - } else if (nextGradientStop == stops.size()) { - fillColor = colorToColor4ub(stops.last().second); - } else { - const QGradientStop &prev = stops.at(nextGradientStop - 1); - const QGradientStop &next = stops.at(nextGradientStop); - float t = (gradientPos - prev.first) / (next.first - prev.first); - fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t; - } - } - - if (hasFill) { - indices[fillHead++] = index; - indices[fillHead++] = index + 1; - } - - if (penWidth) { - indices[--borderHead] = index + 4; - indices[--borderHead] = index + 2; - indices[borderTail++] = index + 3; - indices[borderTail++] = index + 5; - } - - if (m_antialiasing) { - indices[--innerAAHead] = index + 2; - indices[--innerAAHead] = index; - indices[innerAATail++] = index + 1; - indices[innerAATail++] = index + 3; - - float dy = part == 1 ? qMin(0.0f, height - y - delta) : qMax(0.0f, delta - y); - smoothVertices[index++].set(rx, y, fillColor, width - rx - delta, dy); - smoothVertices[index++].set(lx, y, fillColor, delta - lx, dy); - - if (penWidth) { - smoothVertices[index++].set(rx, y, borderColor, 0.49f * penWidth, 0.49f * penWidth * part); - smoothVertices[index++].set(lx, y, borderColor, -0.49f * penWidth, 0.49f * penWidth * part); - smoothVertices[index++].set(rX, Y, borderColor, -0.49f * penWidth, -0.49f * penWidth * part); - smoothVertices[index++].set(lX, Y, borderColor, 0.49f * penWidth, -0.49f * penWidth * part); - smoothVertices[index++].set(rX, Y, transparent, delta, delta * part); - smoothVertices[index++].set(lX, Y, transparent, -delta, delta * part); - - indices[--outerAAHead] = index - 2; - indices[--outerAAHead] = index - 4; - indices[outerAATail++] = index - 3; - indices[outerAATail++] = index - 1; - } else { - smoothVertices[index++].set(rx, y, transparent, delta, delta * part); - smoothVertices[index++].set(lx, y, transparent, -delta, delta * part); - } - } else { - vertices[index++].set(rx, y, fillColor); - vertices[index++].set(lx, y, fillColor); - if (penWidth) { - vertices[index++].set(rx, y, borderColor); - vertices[index++].set(lx, y, borderColor); - vertices[index++].set(rX, Y, borderColor); - vertices[index++].set(lX, Y, borderColor); - } - } - } - Q_ASSERT(index == vertexCount); - - // Close the triangle strips. - if (m_antialiasing) { - indices[--innerAAHead] = indices[innerAATail - 1]; - indices[--innerAAHead] = indices[innerAATail - 2]; - Q_ASSERT(innerAATail <= indexCount); - } - if (penWidth) { - indices[--borderHead] = indices[borderTail - 1]; - indices[--borderHead] = indices[borderTail - 2]; - Q_ASSERT(borderTail <= indexCount); - } - if (m_antialiasing && penWidth) { - indices[--outerAAHead] = indices[outerAATail - 1]; - indices[--outerAAHead] = indices[outerAATail - 2]; - Q_ASSERT(outerAATail == indexCount); - } - } -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgbasicrectanglenode_p.h b/src/quick/scenegraph/qsgbasicrectanglenode_p.h deleted file mode 100644 index b1d1457590..0000000000 --- a/src/quick/scenegraph/qsgbasicrectanglenode_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QSGBASICRECTANGLENODE_P_H -#define QSGBASICRECTANGLENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class Q_QUICK_PRIVATE_EXPORT QSGBasicRectangleNode : public QSGRectangleNode -{ -public: - QSGBasicRectangleNode(); - - void setRect(const QRectF &rect) override; - void setColor(const QColor &color) override; - void setPenColor(const QColor &color) override; - void setPenWidth(qreal width) override; - void setGradientStops(const QGradientStops &stops) override; - void setRadius(qreal radius) override; - void setAntialiasing(bool antialiasing) override; - void setAligned(bool aligned) override; - void update() override; - -protected: - virtual bool supportsAntialiasing() const { return true; } - virtual void updateMaterialAntialiasing() = 0; - virtual void updateMaterialBlending(QSGNode::DirtyState *state) = 0; - - void updateGeometry(); - void updateGradientTexture(); - - QRectF m_rect; - QGradientStops m_gradient_stops; - QColor m_color; - QColor m_border_color; - qreal m_radius; - qreal m_pen_width; - - uint m_aligned : 1; - uint m_antialiasing : 1; - uint m_gradient_is_opaque : 1; - uint m_dirty_geometry : 1; - - QSGGeometry m_geometry; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 40d65d99aa..fa77c2d6cc 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -268,9 +268,9 @@ void QSGContext::renderContextInvalidated(QSGRenderContext *) /*! Convenience factory function for creating a colored rectangle with the given geometry. */ -QSGRectangleNode *QSGContext::createRectangleNode(const QRectF &rect, const QColor &c) +QSGInternalRectangleNode *QSGContext::createInternalRectangleNode(const QRectF &rect, const QColor &c) { - QSGRectangleNode *node = createRectangleNode(); + QSGInternalRectangleNode *node = createInternalRectangleNode(); node->setRect(rect); node->setColor(c); node->update(); diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 2527be0480..e34d2c3ebf 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -66,11 +66,10 @@ QT_BEGIN_NAMESPACE class QSGContextPrivate; -class QSGRectangleNode; -class QSGImageNode; +class QSGInternalRectangleNode; +class QSGInternalImageNode; class QSGPainterNode; class QSGGlyphNode; -class QSGNinePatchNode; class QSGRenderer; class QSGDistanceFieldGlyphCache; class QQuickWindow; @@ -85,6 +84,9 @@ class QQuickPaintedItem; class QSGRendererInterface; class QSGShaderEffectNode; class QSGGuiThreadShaderEffectManager; +class QSGRectangleNode; +class QSGImageNode; +class QSGNinePatchNode; Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP) Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION) @@ -163,12 +165,11 @@ public: virtual void renderContextInvalidated(QSGRenderContext *renderContext); virtual QSGRenderContext *createRenderContext() = 0; - QSGRectangleNode *createRectangleNode(const QRectF &rect, const QColor &c); - virtual QSGRectangleNode *createRectangleNode() = 0; - virtual QSGImageNode *createImageNode() = 0; + QSGInternalRectangleNode *createInternalRectangleNode(const QRectF &rect, const QColor &c); + virtual QSGInternalRectangleNode *createInternalRectangleNode() = 0; + virtual QSGInternalImageNode *createInternalImageNode() = 0; virtual QSGPainterNode *createPainterNode(QQuickPaintedItem *item) = 0; virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) = 0; - virtual QSGNinePatchNode *createNinePatchNode() = 0; virtual QSGLayer *createLayer(QSGRenderContext *renderContext) = 0; virtual QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager(); virtual QSGShaderEffectNode *createShaderEffectNode(QSGRenderContext *renderContext, @@ -180,6 +181,10 @@ public: virtual QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext); + virtual QSGRectangleNode *createRectangleNode() = 0; + virtual QSGImageNode *createImageNode() = 0; + virtual QSGNinePatchNode *createNinePatchNode() = 0; + static QSGContext *createDefaultContext(); static QQuickTextureFactory *createTextureFactoryFromImage(const QImage &image); static QSGRenderLoop *createWindowManager(); diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp index f9978e816c..a33f4b174f 100644 --- a/src/quick/scenegraph/qsgdefaultcontext.cpp +++ b/src/quick/scenegraph/qsgdefaultcontext.cpp @@ -40,8 +40,8 @@ #include "qsgdefaultcontext_p.h" #include -#include -#include +#include +#include #include #include #include @@ -49,6 +49,9 @@ #include #include #include +#include +#include +#include #include #include @@ -60,13 +63,13 @@ QT_BEGIN_NAMESPACE namespace QSGMultisampleAntialiasing { - class ImageNode : public QSGDefaultImageNode { + class ImageNode : public QSGDefaultInternalImageNode { public: void setAntialiasing(bool) { } }; - class RectangleNode : public QSGDefaultRectangleNode { + class RectangleNode : public QSGDefaultInternalRectangleNode { public: void setAntialiasing(bool) { } }; @@ -170,18 +173,18 @@ QSGRenderContext *QSGDefaultContext::createRenderContext() return new QSGDefaultRenderContext(this); } -QSGRectangleNode *QSGDefaultContext::createRectangleNode() +QSGInternalRectangleNode *QSGDefaultContext::createInternalRectangleNode() { return m_antialiasingMethod == MsaaAntialiasing ? new QSGMultisampleAntialiasing::RectangleNode - : new QSGDefaultRectangleNode; + : new QSGDefaultInternalRectangleNode; } -QSGImageNode *QSGDefaultContext::createImageNode() +QSGInternalImageNode *QSGDefaultContext::createInternalImageNode() { return m_antialiasingMethod == MsaaAntialiasing ? new QSGMultisampleAntialiasing::ImageNode - : new QSGDefaultImageNode; + : new QSGDefaultInternalImageNode; } QSGPainterNode *QSGDefaultContext::createPainterNode(QQuickPaintedItem *item) @@ -200,15 +203,6 @@ QSGGlyphNode *QSGDefaultContext::createGlyphNode(QSGRenderContext *rc, bool pref } } -/*! - * Factory function for scene graph backends of the QStyle stylable elements. Returns a - * null pointer if the backend doesn't provide its own node type. - */ -QSGNinePatchNode *QSGDefaultContext::createNinePatchNode() -{ - return nullptr; -} - QSGLayer *QSGDefaultContext::createLayer(QSGRenderContext *renderContext) { return new QSGDefaultLayer(renderContext); @@ -246,6 +240,21 @@ QSGRendererInterface *QSGDefaultContext::rendererInterface(QSGRenderContext *ren return this; } +QSGRectangleNode *QSGDefaultContext::createRectangleNode() +{ + return new QSGDefaultRectangleNode; +} + +QSGImageNode *QSGDefaultContext::createImageNode() +{ + return new QSGDefaultImageNode; +} + +QSGNinePatchNode *QSGDefaultContext::createNinePatchNode() +{ + return new QSGDefaultNinePatchNode; +} + QSGRendererInterface::GraphicsApi QSGDefaultContext::graphicsApi() const { return OpenGL; diff --git a/src/quick/scenegraph/qsgdefaultcontext_p.h b/src/quick/scenegraph/qsgdefaultcontext_p.h index 6686ab98a0..63c817cc7b 100644 --- a/src/quick/scenegraph/qsgdefaultcontext_p.h +++ b/src/quick/scenegraph/qsgdefaultcontext_p.h @@ -66,14 +66,16 @@ public: void renderContextInitialized(QSGRenderContext *renderContext) override; void renderContextInvalidated(QSGRenderContext *) override; QSGRenderContext *createRenderContext() override; - QSGRectangleNode *createRectangleNode() override; - QSGImageNode *createImageNode() override; + QSGInternalRectangleNode *createInternalRectangleNode() override; + QSGInternalImageNode *createInternalImageNode() override; QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override; QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) override; - QSGNinePatchNode *createNinePatchNode() override; QSGLayer *createLayer(QSGRenderContext *renderContext) override; QSurfaceFormat defaultSurfaceFormat() const override; QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext) override; + QSGRectangleNode *createRectangleNode() override; + QSGImageNode *createImageNode() override; + QSGNinePatchNode *createNinePatchNode() override; void setDistanceFieldEnabled(bool enabled); bool isDistanceFieldEnabled() const; diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp deleted file mode 100644 index 9fed70a7de..0000000000 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgdefaultimagenode_p.h" -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class SmoothTextureMaterialShader : public QSGTextureMaterialShader -{ -public: - SmoothTextureMaterialShader(); - - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); - virtual char const *const *attributeNames() const; - -protected: - virtual void initialize(); - - int m_pixelSizeLoc; -}; - - -QSGSmoothTextureMaterial::QSGSmoothTextureMaterial() -{ - setFlag(RequiresFullMatrixExceptTranslate, true); - setFlag(Blending, true); -} - -void QSGSmoothTextureMaterial::setTexture(QSGTexture *texture) -{ - m_texture = texture; -} - -QSGMaterialType *QSGSmoothTextureMaterial::type() const -{ - static QSGMaterialType type; - return &type; -} - -QSGMaterialShader *QSGSmoothTextureMaterial::createShader() const -{ - return new SmoothTextureMaterialShader; -} - -SmoothTextureMaterialShader::SmoothTextureMaterialShader() - : QSGTextureMaterialShader() -{ - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothtexture.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothtexture.frag")); -} - -void SmoothTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) -{ - if (oldEffect == 0) { - // The viewport is constant, so set the pixel size uniform only once. - QRect r = state.viewportRect(); - program()->setUniformValue(m_pixelSizeLoc, 2.0f / r.width(), 2.0f / r.height()); - } - QSGTextureMaterialShader::updateState(state, newEffect, oldEffect); -} - -char const *const *SmoothTextureMaterialShader::attributeNames() const -{ - static char const *const attributes[] = { - "vertex", - "multiTexCoord", - "vertexOffset", - "texCoordOffset", - 0 - }; - return attributes; -} - -void SmoothTextureMaterialShader::initialize() -{ - m_pixelSizeLoc = program()->uniformLocation("pixelSize"); - QSGTextureMaterialShader::initialize(); -} - -QSGDefaultImageNode::QSGDefaultImageNode() -{ - setMaterial(&m_materialO); - setOpaqueMaterial(&m_material); -} - -void QSGDefaultImageNode::setFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.filtering() == filtering) - return; - - m_material.setFiltering(filtering); - m_materialO.setFiltering(filtering); - m_smoothMaterial.setFiltering(filtering); - markDirty(DirtyMaterial); -} - -void QSGDefaultImageNode::setMipmapFiltering(QSGTexture::Filtering filtering) -{ - if (m_material.mipmapFiltering() == filtering) - return; - - m_material.setMipmapFiltering(filtering); - m_materialO.setMipmapFiltering(filtering); - m_smoothMaterial.setMipmapFiltering(filtering); - markDirty(DirtyMaterial); -} - -void QSGDefaultImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) -{ - if (m_material.verticalWrapMode() == wrapMode) - return; - - m_material.setVerticalWrapMode(wrapMode); - m_materialO.setVerticalWrapMode(wrapMode); - m_smoothMaterial.setVerticalWrapMode(wrapMode); - markDirty(DirtyMaterial); -} - -void QSGDefaultImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) -{ - if (m_material.horizontalWrapMode() == wrapMode) - return; - - m_material.setHorizontalWrapMode(wrapMode); - m_materialO.setHorizontalWrapMode(wrapMode); - m_smoothMaterial.setHorizontalWrapMode(wrapMode); - markDirty(DirtyMaterial); -} - -void QSGDefaultImageNode::updateMaterialAntialiasing() -{ - if (m_antialiasing) { - setMaterial(&m_smoothMaterial); - setOpaqueMaterial(0); - } else { - setMaterial(&m_materialO); - setOpaqueMaterial(&m_material); - } -} - -void QSGDefaultImageNode::setMaterialTexture(QSGTexture *texture) -{ - m_material.setTexture(texture); - m_materialO.setTexture(texture); - m_smoothMaterial.setTexture(texture); -} - -QSGTexture *QSGDefaultImageNode::materialTexture() const -{ - return m_material.texture(); -} - -bool QSGDefaultImageNode::updateMaterialBlending() -{ - const bool alpha = m_material.flags() & QSGMaterial::Blending; - if (materialTexture() && alpha != materialTexture()->hasAlphaChannel()) { - m_material.setFlag(QSGMaterial::Blending, !alpha); - return true; - } - return false; -} - -inline static bool isPowerOfTwo(int x) -{ - // Assumption: x >= 1 - return x == (x & -x); -} - -bool QSGDefaultImageNode::supportsWrap(const QSize &size) const -{ - bool wrapSupported = true; - - QOpenGLContext *ctx = QOpenGLContext::currentContext(); -#ifndef QT_OPENGL_ES_2 - if (ctx->isOpenGLES()) -#endif - { - bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); - const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); - wrapSupported = npotSupported || !isNpot; - } - - return wrapSupported; -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h deleted file mode 100644 index 688c5a5039..0000000000 --- a/src/quick/scenegraph/qsgdefaultimagenode_p.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QSGDEFAULTIMAGENODE_P_H -#define QSGDEFAULTIMAGENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Q_QUICK_PRIVATE_EXPORT QSGSmoothTextureMaterial : public QSGTextureMaterial -{ -public: - QSGSmoothTextureMaterial(); - - void setTexture(QSGTexture *texture); - -protected: - QSGMaterialType *type() const override; - QSGMaterialShader *createShader() const override; -}; - -class Q_QUICK_PRIVATE_EXPORT QSGDefaultImageNode : public QSGBasicImageNode -{ -public: - QSGDefaultImageNode(); - - void setMipmapFiltering(QSGTexture::Filtering filtering) override; - void setFiltering(QSGTexture::Filtering filtering) override; - void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; - void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; - - void updateMaterialAntialiasing() override; - void setMaterialTexture(QSGTexture *texture) override; - QSGTexture *materialTexture() const override; - bool updateMaterialBlending() override; - bool supportsWrap(const QSize &size) const override; - -private: - QSGOpaqueTextureMaterial m_material; - QSGTextureMaterial m_materialO; - QSGSmoothTextureMaterial m_smoothMaterial; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp new file mode 100644 index 0000000000..1d54628acd --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgdefaultinternalimagenode_p.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class SmoothTextureMaterialShader : public QSGTextureMaterialShader +{ +public: + SmoothTextureMaterialShader(); + + virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); + virtual char const *const *attributeNames() const; + +protected: + virtual void initialize(); + + int m_pixelSizeLoc; +}; + + +QSGSmoothTextureMaterial::QSGSmoothTextureMaterial() +{ + setFlag(RequiresFullMatrixExceptTranslate, true); + setFlag(Blending, true); +} + +void QSGSmoothTextureMaterial::setTexture(QSGTexture *texture) +{ + m_texture = texture; +} + +QSGMaterialType *QSGSmoothTextureMaterial::type() const +{ + static QSGMaterialType type; + return &type; +} + +QSGMaterialShader *QSGSmoothTextureMaterial::createShader() const +{ + return new SmoothTextureMaterialShader; +} + +SmoothTextureMaterialShader::SmoothTextureMaterialShader() + : QSGTextureMaterialShader() +{ + setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothtexture.vert")); + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothtexture.frag")); +} + +void SmoothTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) +{ + if (oldEffect == 0) { + // The viewport is constant, so set the pixel size uniform only once. + QRect r = state.viewportRect(); + program()->setUniformValue(m_pixelSizeLoc, 2.0f / r.width(), 2.0f / r.height()); + } + QSGTextureMaterialShader::updateState(state, newEffect, oldEffect); +} + +char const *const *SmoothTextureMaterialShader::attributeNames() const +{ + static char const *const attributes[] = { + "vertex", + "multiTexCoord", + "vertexOffset", + "texCoordOffset", + 0 + }; + return attributes; +} + +void SmoothTextureMaterialShader::initialize() +{ + m_pixelSizeLoc = program()->uniformLocation("pixelSize"); + QSGTextureMaterialShader::initialize(); +} + +QSGDefaultInternalImageNode::QSGDefaultInternalImageNode() +{ + setMaterial(&m_materialO); + setOpaqueMaterial(&m_material); +} + +void QSGDefaultInternalImageNode::setFiltering(QSGTexture::Filtering filtering) +{ + if (m_material.filtering() == filtering) + return; + + m_material.setFiltering(filtering); + m_materialO.setFiltering(filtering); + m_smoothMaterial.setFiltering(filtering); + markDirty(DirtyMaterial); +} + +void QSGDefaultInternalImageNode::setMipmapFiltering(QSGTexture::Filtering filtering) +{ + if (m_material.mipmapFiltering() == filtering) + return; + + m_material.setMipmapFiltering(filtering); + m_materialO.setMipmapFiltering(filtering); + m_smoothMaterial.setMipmapFiltering(filtering); + markDirty(DirtyMaterial); +} + +void QSGDefaultInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) +{ + if (m_material.verticalWrapMode() == wrapMode) + return; + + m_material.setVerticalWrapMode(wrapMode); + m_materialO.setVerticalWrapMode(wrapMode); + m_smoothMaterial.setVerticalWrapMode(wrapMode); + markDirty(DirtyMaterial); +} + +void QSGDefaultInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) +{ + if (m_material.horizontalWrapMode() == wrapMode) + return; + + m_material.setHorizontalWrapMode(wrapMode); + m_materialO.setHorizontalWrapMode(wrapMode); + m_smoothMaterial.setHorizontalWrapMode(wrapMode); + markDirty(DirtyMaterial); +} + +void QSGDefaultInternalImageNode::updateMaterialAntialiasing() +{ + if (m_antialiasing) { + setMaterial(&m_smoothMaterial); + setOpaqueMaterial(0); + } else { + setMaterial(&m_materialO); + setOpaqueMaterial(&m_material); + } +} + +void QSGDefaultInternalImageNode::setMaterialTexture(QSGTexture *texture) +{ + m_material.setTexture(texture); + m_materialO.setTexture(texture); + m_smoothMaterial.setTexture(texture); +} + +QSGTexture *QSGDefaultInternalImageNode::materialTexture() const +{ + return m_material.texture(); +} + +bool QSGDefaultInternalImageNode::updateMaterialBlending() +{ + const bool alpha = m_material.flags() & QSGMaterial::Blending; + if (materialTexture() && alpha != materialTexture()->hasAlphaChannel()) { + m_material.setFlag(QSGMaterial::Blending, !alpha); + return true; + } + return false; +} + +inline static bool isPowerOfTwo(int x) +{ + // Assumption: x >= 1 + return x == (x & -x); +} + +bool QSGDefaultInternalImageNode::supportsWrap(const QSize &size) const +{ + bool wrapSupported = true; + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); +#ifndef QT_OPENGL_ES_2 + if (ctx->isOpenGLES()) +#endif + { + bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); + const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); + wrapSupported = npotSupported || !isNpot; + } + + return wrapSupported; +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultinternalimagenode_p.h b/src/quick/scenegraph/qsgdefaultinternalimagenode_p.h new file mode 100644 index 0000000000..1fc7834bd1 --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultinternalimagenode_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSGDEFAULTINTERNALIMAGENODE_P_H +#define QSGDEFAULTINTERNALIMAGENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGSmoothTextureMaterial : public QSGTextureMaterial +{ +public: + QSGSmoothTextureMaterial(); + + void setTexture(QSGTexture *texture); + +protected: + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; +}; + +class Q_QUICK_PRIVATE_EXPORT QSGDefaultInternalImageNode : public QSGBasicInternalImageNode +{ +public: + QSGDefaultInternalImageNode(); + + void setMipmapFiltering(QSGTexture::Filtering filtering) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; + void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; + + void updateMaterialAntialiasing() override; + void setMaterialTexture(QSGTexture *texture) override; + QSGTexture *materialTexture() const override; + bool updateMaterialBlending() override; + bool supportsWrap(const QSize &size) const override; + +private: + QSGOpaqueTextureMaterial m_material; + QSGTextureMaterial m_materialO; + QSGSmoothTextureMaterial m_smoothMaterial; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp new file mode 100644 index 0000000000..94414444ba --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultinternalrectanglenode.cpp @@ -0,0 +1,159 @@ + +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgdefaultinternalrectanglenode_p.h" + +#include +#include + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class SmoothColorMaterialShader : public QSGMaterialShader +{ +public: + SmoothColorMaterialShader(); + + virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); + virtual char const *const *attributeNames() const; + +private: + virtual void initialize(); + + int m_matrixLoc; + int m_opacityLoc; + int m_pixelSizeLoc; +}; + +SmoothColorMaterialShader::SmoothColorMaterialShader() + : QSGMaterialShader() +{ + setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothcolor.vert")); + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothcolor.frag")); +} + +void SmoothColorMaterialShader::updateState(const RenderState &state, QSGMaterial *, QSGMaterial *oldEffect) +{ + if (state.isOpacityDirty()) + program()->setUniformValue(m_opacityLoc, state.opacity()); + + if (state.isMatrixDirty()) + program()->setUniformValue(m_matrixLoc, state.combinedMatrix()); + + if (oldEffect == 0) { + // The viewport is constant, so set the pixel size uniform only once. + QRect r = state.viewportRect(); + program()->setUniformValue(m_pixelSizeLoc, 2.0f / r.width(), 2.0f / r.height()); + } +} + +char const *const *SmoothColorMaterialShader::attributeNames() const +{ + static char const *const attributes[] = { + "vertex", + "vertexColor", + "vertexOffset", + 0 + }; + return attributes; +} + +void SmoothColorMaterialShader::initialize() +{ + m_matrixLoc = program()->uniformLocation("matrix"); + m_opacityLoc = program()->uniformLocation("opacity"); + m_pixelSizeLoc = program()->uniformLocation("pixelSize"); +} + +QSGSmoothColorMaterial::QSGSmoothColorMaterial() +{ + setFlag(RequiresFullMatrixExceptTranslate, true); + setFlag(Blending, true); +} + +int QSGSmoothColorMaterial::compare(const QSGMaterial *) const +{ + return 0; +} + +QSGMaterialType *QSGSmoothColorMaterial::type() const +{ + static QSGMaterialType type; + return &type; +} + +QSGMaterialShader *QSGSmoothColorMaterial::createShader() const +{ + return new SmoothColorMaterialShader; +} + +QSGDefaultInternalRectangleNode::QSGDefaultInternalRectangleNode() +{ + setMaterial(&m_material); +} + +void QSGDefaultInternalRectangleNode::updateMaterialAntialiasing() +{ + if (m_antialiasing) + setMaterial(&m_smoothMaterial); + else + setMaterial(&m_material); +} + +void QSGDefaultInternalRectangleNode::updateMaterialBlending(QSGNode::DirtyState *state) +{ + // smoothed material is always blended, so no change in material state + if (material() == &m_material) { + bool wasBlending = (m_material.flags() & QSGMaterial::Blending); + bool isBlending = (m_gradient_stops.size() > 0 && !m_gradient_is_opaque) + || (m_color.alpha() < 255 && m_color.alpha() != 0) + || (m_pen_width > 0 && m_border_color.alpha() < 255); + if (wasBlending != isBlending) { + m_material.setFlag(QSGMaterial::Blending, isBlending); + *state |= QSGNode::DirtyMaterial; + } + } +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultinternalrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultinternalrectanglenode_p.h new file mode 100644 index 0000000000..941d870c8b --- /dev/null +++ b/src/quick/scenegraph/qsgdefaultinternalrectanglenode_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSGDEFAULTINTERNALRECTANGLENODE_P_H +#define QSGDEFAULTINTERNALRECTANGLENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSGContext; + +class Q_QUICK_PRIVATE_EXPORT QSGSmoothColorMaterial : public QSGMaterial +{ +public: + QSGSmoothColorMaterial(); + + int compare(const QSGMaterial *other) const; + +protected: + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; +}; + +class Q_QUICK_PRIVATE_EXPORT QSGDefaultInternalRectangleNode : public QSGBasicInternalRectangleNode +{ +public: + QSGDefaultInternalRectangleNode(); + +private: + void updateMaterialAntialiasing() override; + void updateMaterialBlending(QSGNode::DirtyState *state) override; + + QSGVertexColorMaterial m_material; + QSGSmoothColorMaterial m_smoothMaterial; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp deleted file mode 100644 index 117a9272e5..0000000000 --- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp +++ /dev/null @@ -1,159 +0,0 @@ - -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsgdefaultrectanglenode_p.h" - -#include -#include - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -class SmoothColorMaterialShader : public QSGMaterialShader -{ -public: - SmoothColorMaterialShader(); - - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); - virtual char const *const *attributeNames() const; - -private: - virtual void initialize(); - - int m_matrixLoc; - int m_opacityLoc; - int m_pixelSizeLoc; -}; - -SmoothColorMaterialShader::SmoothColorMaterialShader() - : QSGMaterialShader() -{ - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothcolor.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/smoothcolor.frag")); -} - -void SmoothColorMaterialShader::updateState(const RenderState &state, QSGMaterial *, QSGMaterial *oldEffect) -{ - if (state.isOpacityDirty()) - program()->setUniformValue(m_opacityLoc, state.opacity()); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrixLoc, state.combinedMatrix()); - - if (oldEffect == 0) { - // The viewport is constant, so set the pixel size uniform only once. - QRect r = state.viewportRect(); - program()->setUniformValue(m_pixelSizeLoc, 2.0f / r.width(), 2.0f / r.height()); - } -} - -char const *const *SmoothColorMaterialShader::attributeNames() const -{ - static char const *const attributes[] = { - "vertex", - "vertexColor", - "vertexOffset", - 0 - }; - return attributes; -} - -void SmoothColorMaterialShader::initialize() -{ - m_matrixLoc = program()->uniformLocation("matrix"); - m_opacityLoc = program()->uniformLocation("opacity"); - m_pixelSizeLoc = program()->uniformLocation("pixelSize"); -} - -QSGSmoothColorMaterial::QSGSmoothColorMaterial() -{ - setFlag(RequiresFullMatrixExceptTranslate, true); - setFlag(Blending, true); -} - -int QSGSmoothColorMaterial::compare(const QSGMaterial *) const -{ - return 0; -} - -QSGMaterialType *QSGSmoothColorMaterial::type() const -{ - static QSGMaterialType type; - return &type; -} - -QSGMaterialShader *QSGSmoothColorMaterial::createShader() const -{ - return new SmoothColorMaterialShader; -} - -QSGDefaultRectangleNode::QSGDefaultRectangleNode() -{ - setMaterial(&m_material); -} - -void QSGDefaultRectangleNode::updateMaterialAntialiasing() -{ - if (m_antialiasing) - setMaterial(&m_smoothMaterial); - else - setMaterial(&m_material); -} - -void QSGDefaultRectangleNode::updateMaterialBlending(QSGNode::DirtyState *state) -{ - // smoothed material is always blended, so no change in material state - if (material() == &m_material) { - bool wasBlending = (m_material.flags() & QSGMaterial::Blending); - bool isBlending = (m_gradient_stops.size() > 0 && !m_gradient_is_opaque) - || (m_color.alpha() < 255 && m_color.alpha() != 0) - || (m_pen_width > 0 && m_border_color.alpha() < 255); - if (wasBlending != isBlending) { - m_material.setFlag(QSGMaterial::Blending, isBlending); - *state |= QSGNode::DirtyMaterial; - } - } -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h deleted file mode 100644 index f30a3beed7..0000000000 --- a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QSGDEFAULTRECTANGLENODE_P_H -#define QSGDEFAULTRECTANGLENODE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QSGContext; - -class Q_QUICK_PRIVATE_EXPORT QSGSmoothColorMaterial : public QSGMaterial -{ -public: - QSGSmoothColorMaterial(); - - int compare(const QSGMaterial *other) const; - -protected: - QSGMaterialType *type() const override; - QSGMaterialShader *createShader() const override; -}; - -class Q_QUICK_PRIVATE_EXPORT QSGDefaultRectangleNode : public QSGBasicRectangleNode -{ -public: - QSGDefaultRectangleNode(); - -private: - void updateMaterialAntialiasing() override; - void updateMaterialBlending(QSGNode::DirtyState *state) override; - - QSGVertexColorMaterial m_material; - QSGSmoothColorMaterial m_smoothMaterial; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index d8dfd01e7a..5b13b7449a 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -52,7 +52,10 @@ HEADERS += \ $$PWD/util/qsgsimplematerial.h \ $$PWD/util/qsgtexturematerial.h \ $$PWD/util/qsgtexturematerial_p.h \ - $$PWD/util/qsgvertexcolormaterial.h + $$PWD/util/qsgvertexcolormaterial.h \ + $$PWD/util/qsgrectanglenode.h \ + $$PWD/util/qsgimagenode.h \ + $$PWD/util/qsgninepatchnode.h SOURCES += \ $$PWD/util/qsgareaallocator.cpp \ @@ -65,7 +68,11 @@ SOURCES += \ $$PWD/util/qsgflatcolormaterial.cpp \ $$PWD/util/qsgsimplematerial.cpp \ $$PWD/util/qsgtexturematerial.cpp \ - $$PWD/util/qsgvertexcolormaterial.cpp + $$PWD/util/qsgvertexcolormaterial.cpp \ + $$PWD/util/qsgrectanglenode.cpp \ + $$PWD/util/qsgimagenode.cpp \ + $$PWD/util/qsgninepatchnode.cpp + contains(QT_CONFIG, opengl(es1|es2)?) { HEADERS += \ $$PWD/util/qsgdepthstencilbuffer_p.h \ @@ -83,8 +90,8 @@ HEADERS += \ $$PWD/qsgadaptationlayer_p.h \ $$PWD/qsgcontext_p.h \ $$PWD/qsgcontextplugin_p.h \ - $$PWD/qsgbasicrectanglenode_p.h \ - $$PWD/qsgbasicimagenode_p.h \ + $$PWD/qsgbasicinternalrectanglenode_p.h \ + $$PWD/qsgbasicinternalimagenode_p.h \ $$PWD/qsgbasicglyphnode_p.h \ $$PWD/qsgrenderloop_p.h @@ -92,8 +99,8 @@ SOURCES += \ $$PWD/qsgadaptationlayer.cpp \ $$PWD/qsgcontext.cpp \ $$PWD/qsgcontextplugin.cpp \ - $$PWD/qsgbasicrectanglenode.cpp \ - $$PWD/qsgbasicimagenode.cpp \ + $$PWD/qsgbasicinternalrectanglenode.cpp \ + $$PWD/qsgbasicinternalimagenode.cpp \ $$PWD/qsgbasicglyphnode.cpp \ $$PWD/qsgrenderloop.cpp @@ -104,11 +111,14 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qsgdefaultdistancefieldglyphcache.cpp \ $$PWD/qsgdistancefieldglyphnode.cpp \ $$PWD/qsgdistancefieldglyphnode_p.cpp \ - $$PWD/qsgdefaultimagenode.cpp \ - $$PWD/qsgdefaultrectanglenode.cpp \ + $$PWD/qsgdefaultinternalimagenode.cpp \ + $$PWD/qsgdefaultinternalrectanglenode.cpp \ $$PWD/qsgdefaultrendercontext.cpp \ $$PWD/qsgdefaultcontext.cpp \ $$PWD/util/qsgdefaultpainternode.cpp \ + $$PWD/util/qsgdefaultrectanglenode.cpp \ + $$PWD/util/qsgdefaultimagenode.cpp \ + $$PWD/util/qsgdefaultninepatchnode.cpp \ $$PWD/qsgdefaultlayer.cpp \ $$PWD/qsgthreadedrenderloop.cpp \ $$PWD/qsgwindowsrenderloop.cpp @@ -118,11 +128,14 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qsgdistancefieldglyphnode_p.h \ $$PWD/qsgdistancefieldglyphnode_p_p.h \ $$PWD/qsgdefaultglyphnode_p_p.h \ - $$PWD/qsgdefaultimagenode_p.h \ - $$PWD/qsgdefaultrectanglenode_p.h \ + $$PWD/qsgdefaultinternalimagenode_p.h \ + $$PWD/qsgdefaultinternalrectanglenode_p.h \ $$PWD/qsgdefaultrendercontext_p.h \ $$PWD/qsgdefaultcontext_p.h \ $$PWD/util/qsgdefaultpainternode_p.h \ + $$PWD/util/qsgdefaultrectanglenode_p.h \ + $$PWD/util/qsgdefaultimagenode_p.h \ + $$PWD/util/qsgdefaultninepatchnode_p.h \ $$PWD/qsgdefaultlayer_p.h \ $$PWD/qsgthreadedrenderloop_p.h \ $$PWD/qsgwindowsrenderloop_p.h diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode.cpp b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp new file mode 100644 index 0000000000..ed3d73adb4 --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgdefaultimagenode_p.h" +#include + +QT_BEGIN_NAMESPACE + +QSGDefaultImageNode::QSGDefaultImageNode() + : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) + , m_texCoordMode(QSGDefaultImageNode::NoTransform) + , m_isAtlasTexture(false) + , m_ownsTexture(false) +{ + setGeometry(&m_geometry); + setMaterial(&m_material); + setOpaqueMaterial(&m_opaque_material); + m_material.setMipmapFiltering(QSGTexture::None); + m_opaque_material.setMipmapFiltering(QSGTexture::None); +#ifdef QSG_RUNTIME_DESCRIPTION + qsgnode_set_description(this, QLatin1String("image")); +#endif +} + +QSGDefaultImageNode::~QSGDefaultImageNode() +{ + if (m_ownsTexture) + delete m_material.texture(); +} + +void QSGDefaultImageNode::setFiltering(QSGTexture::Filtering filtering) +{ + if (m_material.filtering() == filtering) + return; + + m_material.setFiltering(filtering); + m_opaque_material.setFiltering(filtering); + markDirty(DirtyMaterial); +} + +QSGTexture::Filtering QSGDefaultImageNode::filtering() const +{ + return m_material.filtering(); +} + +void QSGDefaultImageNode::setRect(const QRectF &r) +{ + if (m_rect == r) + return; + + m_rect = r; + rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + markDirty(DirtyGeometry); +} + +QRectF QSGDefaultImageNode::rect() const +{ + return m_rect; +} + +void QSGDefaultImageNode::setSourceRect(const QRectF &r) +{ + if (m_sourceRect == r) + return; + + m_sourceRect = r; + rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + markDirty(DirtyGeometry); +} + +QRectF QSGDefaultImageNode::sourceRect() const +{ + return m_sourceRect; +} + +void QSGDefaultImageNode::setTexture(QSGTexture *texture) +{ + Q_ASSERT(texture); + if (m_ownsTexture) + delete m_material.texture(); + m_material.setTexture(texture); + m_opaque_material.setTexture(texture); + rebuildGeometry(&m_geometry, texture, m_rect, m_sourceRect, m_texCoordMode); + + DirtyState dirty = DirtyMaterial; + // It would be tempting to skip the extra bit here and instead use + // m_material.texture to get the old state, but that texture could + // have been deleted in the mean time. + bool wasAtlas = m_isAtlasTexture; + m_isAtlasTexture = texture->isAtlasTexture(); + if (wasAtlas || m_isAtlasTexture) + dirty |= DirtyGeometry; + markDirty(dirty); +} + +QSGTexture *QSGDefaultImageNode::texture() const +{ + return m_material.texture(); +} + +void QSGDefaultImageNode::setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) +{ + if (m_texCoordMode == mode) + return; + m_texCoordMode = mode; + rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + markDirty(DirtyMaterial); +} + +QSGDefaultImageNode::TextureCoordinatesTransformMode QSGDefaultImageNode::textureCoordinatesTransform() const +{ + return m_texCoordMode; +} + +void QSGDefaultImageNode::setOwnsTexture(bool owns) +{ + m_ownsTexture = owns; +} + +bool QSGDefaultImageNode::ownsTexture() const +{ + return m_ownsTexture; +} + +void QSGDefaultImageNode::rebuildGeometry(QSGGeometry *g, + QSGTexture *texture, + const QRectF &rect, + QRectF sourceRect, + TextureCoordinatesTransformMode texCoordMode) +{ + if (!texture) + return; + + if (!sourceRect.width() || !sourceRect.height()) { + QSize ts = texture->textureSize(); + sourceRect = QRectF(0, 0, ts.width(), ts.height()); + } + + // Maybe transform the texture coordinates + if (texCoordMode.testFlag(QSGImageNode::MirrorHorizontally)) { + float tmp = sourceRect.left(); + sourceRect.setLeft(sourceRect.right()); + sourceRect.setRight(tmp); + } + if (texCoordMode.testFlag(QSGImageNode::MirrorVertically)) { + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + } + + QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect)); +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode_p.h b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h new file mode 100644 index 0000000000..5316542cff --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGDEFAULTIMAGENODE_P_H +#define QSGDEFAULTIMAGENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGDefaultImageNode : public QSGImageNode +{ +public: + QSGDefaultImageNode(); + ~QSGDefaultImageNode(); + + void setRect(const QRectF &rect) override; + QRectF rect() const override; + + void setSourceRect(const QRectF &r) override; + QRectF sourceRect() const override; + + void setTexture(QSGTexture *texture) override; + QSGTexture *texture() const override; + + void setFiltering(QSGTexture::Filtering filtering) override; + QSGTexture::Filtering filtering() const override; + + void setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) override; + TextureCoordinatesTransformMode textureCoordinatesTransform() const override; + + void setOwnsTexture(bool owns) override; + bool ownsTexture() const override; + + static void rebuildGeometry(QSGGeometry *g, + QSGTexture *texture, + const QRectF &rect, + QRectF sourceRect, + TextureCoordinatesTransformMode texCoordMode); + +private: + QSGGeometry m_geometry; + QSGOpaqueTextureMaterial m_opaque_material; + QSGTextureMaterial m_material; + QRectF m_rect; + QRectF m_sourceRect; + TextureCoordinatesTransformMode m_texCoordMode; + uint m_isAtlasTexture : 1; + uint m_ownsTexture : 1; +}; + +QT_END_NAMESPACE + +#endif // QSGDEFAULTIMAGENODE_P_H diff --git a/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp b/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp new file mode 100644 index 0000000000..e5a53a3617 --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgdefaultninepatchnode_p.h" + +QT_BEGIN_NAMESPACE + +QSGDefaultNinePatchNode::QSGDefaultNinePatchNode() + : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) +{ + m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip); + setGeometry(&m_geometry); + setMaterial(&m_material); +} + +QSGDefaultNinePatchNode::~QSGDefaultNinePatchNode() +{ + delete m_material.texture(); +} + +void QSGDefaultNinePatchNode::setTexture(QSGTexture *texture) +{ + delete m_material.texture(); + m_material.setTexture(texture); +} + +void QSGDefaultNinePatchNode::setBounds(const QRectF &bounds) +{ + m_bounds = bounds; +} + +void QSGDefaultNinePatchNode::setDevicePixelRatio(qreal ratio) +{ + m_devicePixelRatio = ratio; +} + +void QSGDefaultNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) +{ + m_padding = QVector4D(left, top, right, bottom); +} + +void QSGDefaultNinePatchNode::update() +{ + rebuildGeometry(m_material.texture(), &m_geometry, m_padding, m_bounds, m_devicePixelRatio); + markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); +} + +void QSGDefaultNinePatchNode::rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, const QVector4D &padding, + const QRectF &bounds, qreal dpr) +{ + if (padding.x() <= 0 && padding.y() <= 0 && padding.z() <= 0 && padding.w() <= 0) { + geometry->allocate(4, 0); + QSGGeometry::updateTexturedRectGeometry(geometry, bounds, texture->normalizedTextureSubRect()); + return; + } + + QRectF tc = texture->normalizedTextureSubRect(); + QSize ts = texture->textureSize(); + ts.setHeight(ts.height() / dpr); + ts.setWidth(ts.width() / dpr); + + qreal invtw = tc.width() / ts.width(); + qreal invth = tc.height() / ts.height(); + + struct Coord { qreal p; qreal t; }; + Coord cx[4] = { { bounds.left(), tc.left() }, + { bounds.left() + padding.x(), tc.left() + padding.x() * invtw }, + { bounds.right() - padding.z(), tc.right() - padding.z() * invtw }, + { bounds.right(), tc.right() } + }; + Coord cy[4] = { { bounds.top(), tc.top() }, + { bounds.top() + padding.y(), tc.top() + padding.y() * invth }, + { bounds.bottom() - padding.w(), tc.bottom() - padding.w() * invth }, + { bounds.bottom(), tc.bottom() } + }; + + geometry->allocate(16, 28); + QSGGeometry::TexturedPoint2D *v = geometry->vertexDataAsTexturedPoint2D(); + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + v->set(cx[x].p, cy[y].p, cx[x].t, cy[y].t); + ++v; + } + } + + quint16 *i = geometry->indexDataAsUShort(); + for (int r = 0; r < 3; ++r) { + if (r > 0) + *i++ = 4 * r; + for (int c = 0; c < 4; ++c) { + i[0] = 4 * r + c; + i[1] = 4 * r + c + 4; + i += 2; + } + if (r < 2) + *i++ = 4 * r + 3 + 4; + } +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h b/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h new file mode 100644 index 0000000000..675cf48f47 --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGDEFAULTNINEPATCHNODE_P_H +#define QSGDEFAULTNINEPATCHNODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGDefaultNinePatchNode : public QSGNinePatchNode +{ +public: + QSGDefaultNinePatchNode(); + ~QSGDefaultNinePatchNode(); + + void setTexture(QSGTexture *texture) override; + void setBounds(const QRectF &bounds) override; + void setDevicePixelRatio(qreal ratio) override; + void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; + void update() override; + + static void rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, const QVector4D &padding, + const QRectF &bounds, qreal dpr); + +private: + QRectF m_bounds; + qreal m_devicePixelRatio; + QVector4D m_padding; + QSGGeometry m_geometry; + QSGTextureMaterial m_material; +}; + +QT_END_NAMESPACE + +#endif // QSGDEFAULTNINEPATCHNODE_P_H diff --git a/src/quick/scenegraph/util/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/util/qsgdefaultrectanglenode.cpp new file mode 100644 index 0000000000..41db4f1c03 --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultrectanglenode.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgdefaultrectanglenode_p.h" +#include "qsgflatcolormaterial.h" + +QT_BEGIN_NAMESPACE + +// Unlike our predecessor, QSGSimpleRectNode, use QSGVertexColorMaterial +// instead of Flat in order to allow better batching in the renderer. + +QSGDefaultRectangleNode::QSGDefaultRectangleNode() + : m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 4) + , m_color(QColor(255, 255, 255)) +{ + QSGGeometry::updateColoredRectGeometry(&m_geometry, QRectF()); + setMaterial(&m_material); + setGeometry(&m_geometry); +#ifdef QSG_RUNTIME_DESCRIPTION + qsgnode_set_description(this, QLatin1String("rectangle")); +#endif +} + +void QSGDefaultRectangleNode::setRect(const QRectF &rect) +{ + QSGGeometry::updateColoredRectGeometry(&m_geometry, rect); + markDirty(QSGNode::DirtyGeometry); +} + +QRectF QSGDefaultRectangleNode::rect() const +{ + const QSGGeometry::ColoredPoint2D *pts = m_geometry.vertexDataAsColoredPoint2D(); + return QRectF(pts[0].x, + pts[0].y, + pts[3].x - pts[0].x, + pts[3].y - pts[0].y); +} + +void QSGDefaultRectangleNode::setColor(const QColor &color) +{ + if (color != m_color) { + m_color = color; + QSGGeometry::ColoredPoint2D *pts = m_geometry.vertexDataAsColoredPoint2D(); + for (int i = 0; i < 4; ++i) { + pts[i].r = uchar(qRound(m_color.redF() * m_color.alphaF() * 255)); + pts[i].g = uchar(qRound(m_color.greenF() * m_color.alphaF() * 255)); + pts[i].b = uchar(qRound(m_color.blueF() * m_color.alphaF() * 255)); + pts[i].a = uchar(qRound(m_color.alphaF() * 255)); + } + markDirty(QSGNode::DirtyGeometry); + } +} + +QColor QSGDefaultRectangleNode::color() const +{ + return m_color; +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/util/qsgdefaultrectanglenode_p.h new file mode 100644 index 0000000000..965aa8dabb --- /dev/null +++ b/src/quick/scenegraph/util/qsgdefaultrectanglenode_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGDEFAULTRECTANGLENODE_P_H +#define QSGDEFAULTRECTANGLENODE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSGDefaultRectangleNode : public QSGRectangleNode +{ +public: + QSGDefaultRectangleNode(); + + void setRect(const QRectF &rect) override; + QRectF rect() const override; + + void setColor(const QColor &color) override; + QColor color() const override; + +private: + QSGVertexColorMaterial m_material; + QSGGeometry m_geometry; + QColor m_color; +}; + +QT_END_NAMESPACE + +#endif // QSGDEFAULTRECTANGLENODE_P_H diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp index f4d86bba04..988dcffbd8 100644 --- a/src/quick/scenegraph/util/qsgengine.cpp +++ b/src/quick/scenegraph/util/qsgengine.cpp @@ -221,4 +221,45 @@ QSGRendererInterface *QSGEngine::rendererInterface() const : nullptr; } +/*! + Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null. + + This is cross-backend alternative to constructing a QSGSimpleRectNode directly. + + \since 5.8 + \sa QSGRectangleNode + */ +QSGRectangleNode *QSGEngine::createRectangleNode() const +{ + Q_D(const QSGEngine); + return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createRectangleNode() : nullptr; +} + +/*! + Creates a simple image node. When the scenegraph is not initialized, the return value is null. + + This is cross-backend alternative to constructing a QSGSimpleTextureNode directly. + + \since 5.8 + \sa QSGImageNode + */ + +QSGImageNode *QSGEngine::createImageNode() const +{ + Q_D(const QSGEngine); + return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createImageNode() : nullptr; +} + +/*! + Creates a nine patch node. When the scenegraph is not initialized, the return value is null. + + \since 5.8 + */ + +QSGNinePatchNode *QSGEngine::createNinePatchNode() const +{ + Q_D(const QSGEngine); + return d->sgRenderContext->isValid() ? d->sgRenderContext->sceneGraphContext()->createNinePatchNode() : nullptr; +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h index 9d27fb5525..3c8b61852e 100644 --- a/src/quick/scenegraph/util/qsgengine.h +++ b/src/quick/scenegraph/util/qsgengine.h @@ -50,6 +50,9 @@ class QSGAbstractRenderer; class QSGEnginePrivate; class QSGTexture; class QSGRendererInterface; +class QSGRectangleNode; +class QSGImageNode; +class QSGNinePatchNode; class Q_QUICK_EXPORT QSGEngine : public QObject { @@ -74,6 +77,9 @@ public: QSGTexture *createTextureFromImage(const QImage &image, CreateTextureOptions options = CreateTextureOption()) const; QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption()) const; QSGRendererInterface *rendererInterface() const; + QSGRectangleNode *createRectangleNode() const; + QSGImageNode *createImageNode() const; + QSGNinePatchNode *createNinePatchNode() const; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgimagenode.cpp b/src/quick/scenegraph/util/qsgimagenode.cpp new file mode 100644 index 0000000000..0387efc62b --- /dev/null +++ b/src/quick/scenegraph/util/qsgimagenode.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgimagenode.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QSGImageNode + \brief The QSGImageNode class is provided for convenience to easily draw + textured content using the QML scene graph. + + \inmodule QtQuick + \since 5.8 + + \warning The image node class must have a texture before being + added to the scene graph to be rendered. + */ + +/*! + \fn void QSGImageNode::setRect(const QRectF &rect) + + Sets the target rect of this image node to \a r. + */ + +/*! + \fn void QSGImageNode::setRect(qreal x, qreal y, qreal w, qreal h) + \overload + + Sets the rectangle of this image node to begin at (\a x, \a y) and have + width \a w and height \a h. + */ + +/*! + \fn QRectF QSGImageNode::rect() const + + Returns the target rect of this image node. + */ + +/*! + \fn void QSGImageNode::setSourceRect(const QRectF &rect) + + Sets the source rect of this image node to \a r. + */ + +/*! + \fn void QSGImageNode::setSourceRect(qreal x, qreal y, qreal w, qreal h) + \overload + + Sets the rectangle of this image node to show its texture from (\a x, \a y) and + have width \a w and height \a h relatively to the QSGTexture::textureSize. + */ + +/*! + \fn QRectF QSGImageNode::sourceRect() const + + Returns the source rect of this image node. + */ + +/*! + \fn void QSGImageNode::setTexture(QSGTexture *texture) + + Sets the texture of this image node to \a texture. + + Use setOwnsTexture() to set whether the node should take + ownership of the texture. By default, the node does not + take ownership. + + \warning An image node must have a texture before being added to the + scenegraph to be rendered. + */ + +/*! + \fn QSGTexture *QSGImageNode::texture() const + + Returns the texture for this image node. + */ + +/*! + \fn void QSGImageNode::setFiltering(QSGTexture::Filtering filtering) + + Sets the filtering to be used for this image node to \a filtering. + + For smooth scaling, use QSGTexture::Linear. For normal scaling, use + QSGTexture::Nearest. + */ + +/*! + \fn QSGTexture::Filtering QSGImageNode::filtering() const + + Returns the filtering for this image node. + */ + +/*! + \enum QSGImageNode::TextureCoordinatesTransformFlag + + The TextureCoordinatesTransformFlag enum is used to specify the mode used + to generate texture coordinates for a textured quad. + + \value NoTransform Texture coordinates are oriented with window coordinates + i.e. with origin at top-left. + + \value MirrorHorizontally Texture coordinates are inverted in the horizontal axis with + respect to window coordinates + + \value MirrorVertically Texture coordinates are inverted in the vertical axis with + respect to window coordinates + */ + +/*! + \fn void QSGImageNode::setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) + + Sets the method used to generate texture coordinates to \a mode. This can + be used to obtain correct orientation of the texture. This is commonly + needed when using a third-party OpenGL library to render to texture as + OpenGL has an inverted y-axis relative to Qt Quick. + */ + +/*! + \fn QSGImageNode::TextureCoordinatesTransformMode textureCoordinatesTransform() const + + Returns the mode used to generate texture coordinates for this node. + */ + +/*! + \fn void QSGImageNode::setOwnsTexture(bool owns) + + Sets whether the node takes ownership of the texture to \a owns. + + By default, the node does not take ownership of the texture. + */ + +/*! + \fn bool QSGImageNode::ownsTexture() const + + \return \c true if the node takes ownership of the texture; otherwise \c false. + */ + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgimagenode.h b/src/quick/scenegraph/util/qsgimagenode.h new file mode 100644 index 0000000000..a094924ac3 --- /dev/null +++ b/src/quick/scenegraph/util/qsgimagenode.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGIMAGENODE_H +#define QSGIMAGENODE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QSGImageNode : public QSGGeometryNode +{ +public: + virtual ~QSGImageNode() { } + + virtual void setRect(const QRectF &rect) = 0; + inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); } + virtual QRectF rect() const = 0; + + virtual void setSourceRect(const QRectF &r) = 0; + inline void setSourceRect(qreal x, qreal y, qreal w, qreal h) { setSourceRect(QRectF(x, y, w, h)); } + virtual QRectF sourceRect() const = 0; + + virtual void setTexture(QSGTexture *texture) = 0; + virtual QSGTexture *texture() const = 0; + + virtual void setFiltering(QSGTexture::Filtering filtering) = 0; + virtual QSGTexture::Filtering filtering() const = 0; + + enum TextureCoordinatesTransformFlag { + NoTransform = 0x00, + MirrorHorizontally = 0x01, + MirrorVertically = 0x02 + }; + Q_DECLARE_FLAGS(TextureCoordinatesTransformMode, TextureCoordinatesTransformFlag) + + virtual void setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode) = 0; + virtual TextureCoordinatesTransformMode textureCoordinatesTransform() const = 0; + + virtual void setOwnsTexture(bool owns) = 0; + virtual bool ownsTexture() const = 0; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGImageNode::TextureCoordinatesTransformMode) + +QT_END_NAMESPACE + +#endif // QSGIMAGENODE_H diff --git a/src/quick/scenegraph/util/qsgninepatchnode.cpp b/src/quick/scenegraph/util/qsgninepatchnode.cpp new file mode 100644 index 0000000000..9c167ca76f --- /dev/null +++ b/src/quick/scenegraph/util/qsgninepatchnode.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgninepatchnode.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QSGNinePatchNode + \inmodule QtQuick + \since 5.8 + \internal + */ + +/*! + \fn void QSGNinePatchNode::setTexture(QSGTexture *texture) + \internal + */ + +/*! + \fn void QSGNinePatchNode::setBounds(const QRectF &bounds) + \internal + */ + +/*! + \fn void QSGNinePatchNode::setDevicePixelRatio(qreal ratio) + \internal + */ + +/*! + \fn void QSGNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) + \internal + */ + + +/*! + \fn void QSGNinePatchNode::update() + \internal + */ + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgninepatchnode.h b/src/quick/scenegraph/util/qsgninepatchnode.h new file mode 100644 index 0000000000..8677a432ba --- /dev/null +++ b/src/quick/scenegraph/util/qsgninepatchnode.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGNINEPATCHNODE_H +#define QSGNINEPATCHNODE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QSGNinePatchNode : public QSGGeometryNode +{ +public: + virtual ~QSGNinePatchNode() { } + + virtual void setTexture(QSGTexture *texture) = 0; + virtual void setBounds(const QRectF &bounds) = 0; + virtual void setDevicePixelRatio(qreal ratio) = 0; + virtual void setPadding(qreal left, qreal top, qreal right, qreal bottom) = 0; + virtual void update() = 0; +}; + +QT_END_NAMESPACE + +#endif // QSGNINEPATCHNODE_H diff --git a/src/quick/scenegraph/util/qsgrectanglenode.cpp b/src/quick/scenegraph/util/qsgrectanglenode.cpp new file mode 100644 index 0000000000..38c1f16a63 --- /dev/null +++ b/src/quick/scenegraph/util/qsgrectanglenode.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgrectanglenode.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QSGRectangleNode + + \brief The QSGRectangleNode class is a convenience class for drawing + solid filled rectangles using scenegraph. + \inmodule QtQuick + \since 5.8 + */ + +/*! + \fn void QSGRectangleNode::setRect(const QRectF &rect) + + Sets the rectangle of this rect node to \a rect. + */ + +/*! + \fn void QSGRectangleNode::setRect(qreal x, qreal y, qreal w, qreal h) + \overload + + Sets the rectangle of this rect node to begin at (\a x, \a y) and have + width \a w and height \a h. + */ + +/*! + \fn QRectF QSGRectangleNode::rect() const + + Returns the rectangle that this rect node covers. + */ + +/*! + \fn void QSGRectangleNode::setColor(const QColor &color) + + Sets the color of this rectangle to \a color. The default color will be + white. + */ + +/*! + \fn QColor QSGRectangleNode::color() const + + Returns the color of this rectangle. + */ + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgrectanglenode.h b/src/quick/scenegraph/util/qsgrectanglenode.h new file mode 100644 index 0000000000..8e0da1d9c7 --- /dev/null +++ b/src/quick/scenegraph/util/qsgrectanglenode.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGRECTANGLENODE_H +#define QSGRECTANGLENODE_H + +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_EXPORT QSGRectangleNode : public QSGGeometryNode +{ +public: + virtual ~QSGRectangleNode() { } + + virtual void setRect(const QRectF &rect) = 0; + inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); } + virtual QRectF rect() const = 0; + + virtual void setColor(const QColor &color) = 0; + virtual QColor color() const = 0; +}; + +QT_END_NAMESPACE + +#endif // QSGRECTANGLENODE_H diff --git a/src/quick/scenegraph/util/qsgsimplerectnode.cpp b/src/quick/scenegraph/util/qsgsimplerectnode.cpp index 3f6b8b0eec..e20c051f9a 100644 --- a/src/quick/scenegraph/util/qsgsimplerectnode.cpp +++ b/src/quick/scenegraph/util/qsgsimplerectnode.cpp @@ -49,6 +49,10 @@ QT_BEGIN_NAMESPACE solid filled rectangles using scenegraph. \inmodule QtQuick + \warning This utility class is only functional when running with the OpenGL + or software backends of the Qt Quick scenegraph. For a proper cross-platform + alternative prefer using QSGSimpleRectangleNode via + QQuickWindow::createSimpleRectangleNode() or QSGEngine::createSimpleRectangleNode(). */ diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 1208a6bc72..4ed0445ce1 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -97,6 +97,11 @@ static void qsgsimpletexturenode_update(QSGGeometry *g, \warning The simple texture node class must have a texture before being added to the scene graph to be rendered. + + \warning This utility class is only functional when running with the OpenGL + or software backends of the Qt Quick scenegraph. For a proper cross-platform + alternative prefer using QSGSimpleImageNode via + QQuickWindow::createSimpleImageNode() or QSGEngine::createSimpleImageNode(). */ /*! -- cgit v1.2.3