diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickpainteditem.cpp | 106 | ||||
-rw-r--r-- | src/quick/items/qquickpainteditem.h | 6 | ||||
-rw-r--r-- | src/quick/items/qquickpainteditem_p.h | 1 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgadaptationlayer_p.h | 1 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgdefaultpainternode.cpp | 58 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgdefaultpainternode_p.h | 7 |
6 files changed, 137 insertions, 42 deletions
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index 033000c159..4172b83419 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -67,15 +67,11 @@ public: To enable QPainter to do anti-aliased rendering, use setAntialiasing(). - To write your own painted item, you first create a subclass of QQuickPaintedItem, and then - start by implementing its only pure virtual public function: paint(), which implements - the actual painting. To get the size of the area painted by the item, use - contentsBoundingRect(). - - Starting Qt 5.4, the QQuickPaintedItem is a - \l{QSGTextureProvider}{texture provider} - and can be used directly in \l {ShaderEffect}{ShaderEffects} and other - classes that consume texture providers. + To write your own painted item, you first create a subclass of + QQuickPaintedItem, and then start by implementing its only pure virtual + public function: paint(), which implements the actual painting. The + painting will be inside the rectangle spanning from 0,0 to + width(),height(). */ /*! @@ -333,16 +329,47 @@ void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints update(); } +QSize QQuickPaintedItem::textureSize() const +{ + Q_D(const QQuickPaintedItem); + return d->textureSize; +} + /*! - This function returns the outer bounds of the item as a rectangle; all painting must be - restricted to inside an item's bounding rect. + \property QQuickPaintedItem::textureSize + + \brief Defines the size of the texture. + + Changing the texture's size does not affect the coordinate system used in + paint(). A scale factor is instead applied so painting should still happen + inside 0,0 to width(),height(). + + By default, the texture size will have the same size as this item. + + \note If the item is on a window with a device pixel ratio different from + 1, this scale factor will be implicitly applied to the texture size. + + */ +void QQuickPaintedItem::setTextureSize(const QSize &size) +{ + Q_D(QQuickPaintedItem); + if (d->textureSize == size) + return; + d->textureSize = size; + emit textureSizeChanged(); +} + +#if QT_VERSION >= 0x060000 +#warning "Remove: QQuickPaintedItem::contentsBoundingRect, contentsScale, contentsSize. Also remove them from qsgadaptationlayer_p.h and qsgdefaultpainternode.h/cpp." +#endif - If the contents size has not been set it reflects the size of the item; otherwise - it reflects the contents size scaled by the contents scale. +/*! + \obsolete - Use this function to know the area painted by the item. + This function is provided for compatibility, use size in combination + with textureSize to decide the size of what you are drawing. - \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale() + \sa width(), height(), textureSize() */ QRectF QQuickPaintedItem::contentsBoundingRect() const { @@ -361,11 +388,13 @@ QRectF QQuickPaintedItem::contentsBoundingRect() const /*! \property QQuickPaintedItem::contentsSize - \brief The size of the contents + \brief Obsolete method for setting the contents size. + \obsolete + + This function is provided for compatibility, use size in combination + with textureSize to decide the size of what you are drawing. - The contents size is the size of the item in regards to how it is painted - using the paint() function. This is distinct from the size of the - item in regards to height() and width(). + \sa width(), height(), textureSize() */ QSize QQuickPaintedItem::contentsSize() const { @@ -387,6 +416,7 @@ void QQuickPaintedItem::setContentsSize(const QSize &size) } /*! + \obsolete This convenience function is equivalent to calling setContentsSize(QSize()). */ void QQuickPaintedItem::resetContentsSize() @@ -396,12 +426,13 @@ void QQuickPaintedItem::resetContentsSize() /*! \property QQuickPaintedItem::contentsScale - \brief The scale of the contents + \brief Obsolete method for scaling the contents. + \obsolete - All painting happening in paint() is scaled by the contents scale. This is distinct - from the scale of the item in regards to scale(). + This function is provided for compatibility, use size() in combination + with textureSize() to decide the size of what you are drawing. - The default value is 1. + \sa width(), height(), textureSize() */ qreal QQuickPaintedItem::contentsScale() const { @@ -488,6 +519,9 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target) This function, which is usually called by the QML Scene Graph, paints the contents of an item in local coordinates. + The underlying texture will have a size defined by textureSize when set, + or the item's size, multiplied by the window's device pixel ratio. + The function is called after the item has been filled with the fillColor. Reimplement this function in a QQuickPaintedItem subclass to provide the @@ -501,6 +535,8 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target) \warning Extreme caution must be used when creating QObjects, emitting signals, starting timers and similar inside this function as these will have affinity to the rendering thread. + + \sa width(), height(), textureSize */ /*! @@ -526,17 +562,35 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat d->node = node; } - QRectF br = contentsBoundingRect(); + bool hasTextureSize = d->textureSize.width() > 0 && d->textureSize.height() > 0; + + // Use the compat mode if any of the compat things are set and + // textureSize is 0x0. + if (!hasTextureSize + && (d->contentsScale != 1 + || (d->contentsSize.width() > 0 && d->contentsSize.height() > 0))) { + QRectF br = contentsBoundingRect(); + node->setContentsScale(d->contentsScale); + QSize size = QSize(qRound(br.width()), qRound(br.height())); + node->setSize(size); + node->setTextureSize(size); + } else { + // The default, use textureSize or item's size * device pixel ratio + node->setContentsScale(1); + QSize itemSize(qRound(width()), qRound(height())); + node->setSize(itemSize); + QSize textureSize = (hasTextureSize ? d->textureSize : itemSize) + * window()->effectiveDevicePixelRatio(); + node->setTextureSize(textureSize); + } node->setPreferredRenderTarget(d->renderTarget); node->setFastFBOResizing(d->performanceHints & FastFBOResizing); - node->setSize(QSize(qRound(br.width()), qRound(br.height()))); node->setSmoothPainting(d->antialiasing); node->setLinearFiltering(d->smooth); node->setMipmapping(d->mipmap); node->setOpaquePainting(d->opaquePainting); node->setFillColor(d->fillColor); - node->setContentsScale(d->contentsScale); node->setDirty(d->dirtyRect); node->update(); diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h index 28eb3398a0..8c9ae2eebb 100644 --- a/src/quick/items/qquickpainteditem.h +++ b/src/quick/items/qquickpainteditem.h @@ -48,6 +48,8 @@ class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged) Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged) Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged) + Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged) + public: QQuickPaintedItem(QQuickItem *parent = 0); virtual ~QQuickPaintedItem(); @@ -88,6 +90,9 @@ public: qreal contentsScale() const; void setContentsScale(qreal); + QSize textureSize() const; + void setTextureSize(const QSize &size); + QColor fillColor() const; void setFillColor(const QColor&); @@ -104,6 +109,7 @@ Q_SIGNALS: void contentsSizeChanged(); void contentsScaleChanged(); void renderTargetChanged(); + void textureSizeChanged(); protected: QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0); diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h index 2759d9d683..e77254c0e6 100644 --- a/src/quick/items/qquickpainteditem_p.h +++ b/src/quick/items/qquickpainteditem_p.h @@ -52,6 +52,7 @@ public: QColor fillColor; QQuickPaintedItem::RenderTarget renderTarget; QQuickPaintedItem::PerformanceHints performanceHints; + QSize textureSize; QRect dirtyRect; diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index fde3fa06b2..ceb455fb28 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -160,6 +160,7 @@ public: virtual void setFillColor(const QColor &c) = 0; virtual void setContentsScale(qreal s) = 0; virtual void setFastFBOResizing(bool dynamic) = 0; + virtual void setTextureSize(const QSize &size) = 0; virtual QImage toImage() const = 0; virtual void update() = 0; diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp index 0ba9781e68..38bcc7a3f3 100644 --- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp +++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp @@ -136,18 +136,35 @@ void QSGDefaultPainterNode::paint() painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); } - painter.scale(m_contentsScale, m_contentsScale); - - QRect sclip(qFloor(dirtyRect.x()/m_contentsScale), - qFloor(dirtyRect.y()/m_contentsScale), - qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)), - qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale))); + QRect clipRect; + QRect dirtyTextureRect; + + if (m_contentsScale == 1) { + qreal scaleX = m_textureSize.width() / (qreal) m_size.width(); + qreal scaleY = m_textureSize.height() / (qreal) m_size.height(); + painter.scale(scaleX, scaleY); + clipRect = dirtyRect; + dirtyTextureRect = QRectF(dirtyRect.x() * scaleX, + dirtyRect.y() * scaleY, + dirtyRect.width() * scaleX, + dirtyRect.height() * scaleY).toAlignedRect(); + } else { + painter.scale(m_contentsScale, m_contentsScale); + QRect sclip(qFloor(dirtyRect.x()/m_contentsScale), + qFloor(dirtyRect.y()/m_contentsScale), + qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)), + qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale))); + clipRect = sclip; + dirtyTextureRect = dirtyRect; + } - if (!m_dirtyRect.isNull()) - painter.setClipRect(sclip); + // only clip if we were originally updating only a subrect + if (!m_dirtyRect.isNull()) { + painter.setClipRect(clipRect); + } painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(sclip, m_fillColor); + painter.fillRect(clipRect, m_fillColor); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); m_item->paint(&painter); @@ -155,9 +172,9 @@ void QSGDefaultPainterNode::paint() if (m_actualRenderTarget == QQuickPaintedItem::Image) { m_texture->setImage(m_image); - m_texture->setDirtyRect(dirtyRect); + m_texture->setDirtyRect(dirtyTextureRect); } else if (m_multisampledFbo) { - QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect); + QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyTextureRect, m_multisampledFbo, dirtyTextureRect); } if (m_multisampledFbo) @@ -276,7 +293,7 @@ void QSGDefaultPainterNode::updateRenderTarget() if (!m_image.isNull() && !m_dirtyGeometry) return; - m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied); + m_image = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied); m_image.fill(Qt::transparent); } @@ -302,12 +319,12 @@ void QSGDefaultPainterNode::updateFBOSize() int fboWidth; int fboHeight; if (m_fastFBOResizing) { - fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.width() - 1)); - fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.height() - 1)); + fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.width() - 1)); + fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.height() - 1)); } else { QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize(); - fboWidth = qMax(minimumFBOSize.width(), m_size.width()); - fboHeight = qMax(minimumFBOSize.height(), m_size.height()); + fboWidth = qMax(minimumFBOSize.width(), m_textureSize.width()); + fboHeight = qMax(minimumFBOSize.height(), m_textureSize.height()); } m_fboSize = QSize(fboWidth, fboHeight); @@ -331,6 +348,15 @@ void QSGDefaultPainterNode::setSize(const QSize &size) return; m_size = size; + m_dirtyGeometry = true; +} + +void QSGDefaultPainterNode::setTextureSize(const QSize &size) +{ + if (size == m_textureSize) + return; + + m_textureSize = size; updateFBOSize(); if (m_fbo) diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h index 99e415b2d1..115ddc66f2 100644 --- a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h +++ b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h @@ -94,6 +94,9 @@ public: void setFastFBOResizing(bool dynamic); bool fastFBOResizing() const { return m_fastFBOResizing; } + void setTextureSize(const QSize &textureSize); + QSize textureSize() const { return m_textureSize; } + QImage toImage() const; void update(); @@ -126,8 +129,12 @@ private: QSize m_size; QSize m_fboSize; + QSize m_textureSize; QRect m_dirtyRect; QColor m_fillColor; +#if QT_VERSION >= 0x060000 +#warning "Remove m_contentsScale and assume 1 everywhere" +#endif qreal m_contentsScale; bool m_dirtyContents : 1; |