#include <private/qsgcontext_p.h>
#include <private/qsgadaptationlayer_p.h>
+#include <qmath.h>
QT_BEGIN_NAMESPACE
When a QGLFramebufferObject is used, QPainter paints directly onto the texture.
Call update() to trigger a repaint.
- Set the \l smooth property to true to enable QPainter to do anti-aliased rendering.
+ To enable QPainter to do anti-aliased rendering, use setAntialiasing().
QSGPaintedItem is meant to make it easier to port old code that is using the
QPainter API to the QML Scene Graph API and it should be used only for that purpose.
To write your own painted item, you first create a subclass of QSGPaintedItem, 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
- QSGItem::width() and QSGItem::height().
+ contentsBoundingRect().
*/
/*!
*/
QSGPaintedItemPrivate::QSGPaintedItemPrivate()
: QSGItemPrivate()
+ , contentsScale(1.0)
, fillColor(Qt::transparent)
, renderTarget(QSGPaintedItem::Image)
, geometryDirty(false)
{
Q_D(QSGPaintedItem);
d->contentsDirty = true;
- if (rect.isNull() && !d->dirtyRect.isNull())
- d->dirtyRect = boundingRect().toAlignedRect();
+
+ QRect srect(qCeil(rect.x()*d->contentsScale),
+ qCeil(rect.y()*d->contentsScale),
+ qCeil(rect.width()*d->contentsScale),
+ qCeil(rect.height()*d->contentsScale));
+
+ if (srect.isNull() && !d->dirtyRect.isNull())
+ d->dirtyRect = contentsBoundingRect().toAlignedRect();
else
- d->dirtyRect |= (boundingRect() & rect).toAlignedRect();
+ d->dirtyRect |= (contentsBoundingRect() & srect).toAlignedRect();
QSGItem::update();
}
update();
}
+/*!
+ This function returns the outer bounds of the item as a rectangle; all painting must be
+ restricted to inside an item's bounding rect.
+
+ 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.
+
+ Use this function to know the area painted by the item.
+
+ \sa QSGItem::width(), QSGItem::height(), contentsSize(), contentsScale()
+*/
+QRectF QSGPaintedItem::contentsBoundingRect() const
+{
+ Q_D(const QSGPaintedItem);
+
+ qreal w = d->width;
+ QSizeF sz = d->contentsSize * d->contentsScale;
+ if (w < sz.width())
+ w = sz.width();
+ qreal h = d->height;
+ if (h < sz.height())
+ h = sz.height();
+
+ return QRectF(0, 0, w, h);
+}
+
+/*!
+ \property QSGPaintedItem::contentsSize
+ \brief The size of the contents
+
+ 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().
+*/
QSize QSGPaintedItem::contentsSize() const
{
- // XXX todo
- return QSize();
+ Q_D(const QSGPaintedItem);
+ return d->contentsSize;
}
-void QSGPaintedItem::setContentsSize(const QSize &)
+void QSGPaintedItem::setContentsSize(const QSize &size)
{
- // XXX todo
+ Q_D(QSGPaintedItem);
+
+ if (d->contentsSize == size)
+ return;
+
+ d->contentsSize = size;
+ update();
}
+/*!
+ This convenience function is equivalent to calling setContentsSize(QSize()).
+*/
void QSGPaintedItem::resetContentsSize()
{
- // XXX todo
+ setContentsSize(QSize());
}
+/*!
+ \property QSGPaintedItem::contentsScale
+ \brief The scale of the contents
+
+ All painting happening in paint() is scaled by the contents scale. This is distinct
+ from the scale of the item in regards to scale().
+
+ The default value is 1.
+*/
qreal QSGPaintedItem::contentsScale() const
{
- // XXX todo
- return 1;
+ Q_D(const QSGPaintedItem);
+ return d->contentsScale;
}
-void QSGPaintedItem::setContentsScale(qreal)
+void QSGPaintedItem::setContentsScale(qreal scale)
{
- // XXX todo
+ Q_D(QSGPaintedItem);
+
+ if (d->contentsScale == scale)
+ return;
+
+ d->contentsScale = scale;
+ update();
}
/*!
if (!node)
node = new QSGPainterNode(this);
+ QRectF br = contentsBoundingRect();
+
node->setPreferredRenderTarget(d->renderTarget);
- node->setSize(QSize(d->width, d->height));
+ node->setSize(QSize(qRound(br.width()), qRound(br.height())));
node->setSmoothPainting(d->antialiasing);
node->setLinearFiltering(d->smooth);
node->setOpaquePainting(d->opaquePainting);
node->setFillColor(d->fillColor);
+ node->setContentsScale(d->contentsScale);
node->setDirty(d->contentsDirty || d->geometryDirty, d->dirtyRect);
node->update();
#include <private/qsgcontext_p.h>
#include <qglframebufferobject.h>
#include <qglfunctions.h>
+#include <qmath.h>
QT_BEGIN_NAMESPACE
, m_extensionsChecked(false)
, m_multisamplingSupported(false)
, m_fillColor(Qt::transparent)
+ , m_contentsScale(1.0)
, m_dirtyGeometry(false)
, m_dirtyRenderTarget(false)
, m_dirtyTexture(false)
| 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)));
+
+ if (!m_dirtyRect.isNull())
+ painter.setClipRect(sclip);
+
painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(dirtyRect, m_fillColor);
+ painter.fillRect(sclip, m_fillColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
- if (!m_dirtyRect.isNull())
- painter.setClipRect(dirtyRect);
m_item->paint(&painter);
painter.end();
markDirty(DirtyMaterial);
}
+void QSGPainterNode::setContentsScale(qreal s)
+{
+ if (s == m_contentsScale)
+ return;
+
+ m_contentsScale = s;
+ markDirty(DirtyMaterial);
+}
+
QT_END_NAMESPACE