diff options
author | Charles Yin <charles.yin@nokia.com> | 2011-07-12 09:21:27 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-07-12 04:25:33 +0200 |
commit | b119220da60453ecf31898f7a57eda9d3c4e9225 (patch) | |
tree | 0b316ed1ef9a5e0e154c0a87628a6a5ff205c9dc /src/declarative/items/qsgcanvasitem.cpp | |
parent | bd4d69c9a88f476b4de4ba80945d39725bb29efa (diff) |
Rewrite the canvas item's paint logic.
1. Only allow the context API calls inside onPaint() slot function,
makes the context2d handle invalid when out of scope.
2. requestPaint() method supports region parameter
3. Emit paint() signal in updatePolish() function to allow
threaded scene graph rendering work properly with context2d api
4. Allow request painting mutiple dirty regions between 2 frames.
5. Add svgpath for context2d
Change-Id: I5ec48f7c0eb6820d5c9c16a8d0dcc0aae8d0fd2f
Reviewed-on: http://codereview.qt.nokia.com/1465
Reviewed-by: Charles Yin <charles.yin@nokia.com>
Diffstat (limited to 'src/declarative/items/qsgcanvasitem.cpp')
-rw-r--r-- | src/declarative/items/qsgcanvasitem.cpp | 119 |
1 files changed, 102 insertions, 17 deletions
diff --git a/src/declarative/items/qsgcanvasitem.cpp b/src/declarative/items/qsgcanvasitem.cpp index f346db4c66..0bd9a47d8d 100644 --- a/src/declarative/items/qsgcanvasitem.cpp +++ b/src/declarative/items/qsgcanvasitem.cpp @@ -58,6 +58,10 @@ public: QSGCanvasItemPrivate(); ~QSGCanvasItemPrivate(); QSGContext2D* context; + QList<QRect> dirtyRegions; + QRect unitedDirtyRegion; + qreal canvasX; + qreal canvasY; }; @@ -67,6 +71,9 @@ public: QSGCanvasItemPrivate::QSGCanvasItemPrivate() : QSGPaintedItemPrivate() , context(0) + , unitedDirtyRegion() + , canvasX(0.) + , canvasY(0.) { } @@ -74,6 +81,40 @@ QSGCanvasItemPrivate::~QSGCanvasItemPrivate() { } + +void QSGCanvasItem::setCanvasX(qreal x) +{ + Q_D(QSGCanvasItem); + if (d->canvasX != x) { + d->canvasX = x; + emit canvasXChanged(); + } +} +void QSGCanvasItem::setCanvasY(qreal y) +{ + Q_D(QSGCanvasItem); + if (d->canvasY != y) { + d->canvasY = y; + emit canvasYChanged(); + } +} + +qreal QSGCanvasItem::canvasX() const +{ + Q_D(const QSGCanvasItem); + return d->canvasX; +} +qreal QSGCanvasItem::canvasY() const +{ + Q_D(const QSGCanvasItem); + return d->canvasY; +} +QPointF QSGCanvasItem::canvasPos() const +{ + Q_D(const QSGCanvasItem); + return QPointF(d->canvasX, d->canvasY); +} + /*! Constructs a QSGCanvasItem with the given \a parent item. */ @@ -92,11 +133,13 @@ QSGCanvasItem::~QSGCanvasItem() void QSGCanvasItem::paint(QPainter *painter) { Q_D(QSGCanvasItem); + if (d->context && d->context->isDirty()) { + painter->setWindow(-d->canvasX, -d->canvasY, d->width, d->height); + painter->setViewport(0, 0, d->width, d->height); + painter->scale(d->contentsScale, d->contentsScale); - if (d->context) { - emit drawRegion(getContext(), QRect(0, 0, width(), height())); d->context->paint(painter); - emit canvasUpdated(); + emit painted(); } } @@ -104,36 +147,59 @@ void QSGCanvasItem::componentComplete() { const QMetaObject *metaObject = this->metaObject(); int propertyCount = metaObject->propertyCount(); - int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); + int requestPaintMethod = metaObject->indexOfMethod("requestPaint(const QRect&)"); for (int ii = QSGCanvasItem::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { QMetaProperty p = metaObject->property(ii); if (p.hasNotifySignal()) QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); } + + createContext(); + QSGPaintedItem::componentComplete(); } +void QSGCanvasItem::createContext() +{ + Q_D(QSGCanvasItem); + + delete d->context; + + d->context = new QSGContext2D(this); + + QV8Engine *e = QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this)); + d->context->setV8Engine(e); +} QDeclarativeV8Handle QSGCanvasItem::getContext(const QString &contextId) { Q_D(QSGCanvasItem); + Q_UNUSED(contextId); - if (contextId == QLatin1String("2d")) { - if (!d->context) { - QV8Engine *e = QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this)); - d->context = new QSGContext2D(this); - d->context->setV8Engine(e); - connect(d->context, SIGNAL(changed()), this, SLOT(requestPaint())); - } - return QDeclarativeV8Handle::fromHandle(d->context->v8value()); - } + if (d->context) + return QDeclarativeV8Handle::fromHandle(d->context->v8value()); return QDeclarativeV8Handle::fromHandle(v8::Undefined()); } -void QSGCanvasItem::requestPaint() +void QSGCanvasItem::requestPaint(const QRect& r) { - //TODO:update(d->context->dirtyRect()); - update(); + Q_D(QSGCanvasItem); + + QRect region; + if (!r.isValid()) + region = QRect(d->canvasX, d->canvasY, d->width, d->height); + else + region = r; + + foreach (const QRect& rect, d->dirtyRegions) { + if (rect.contains(region)) + return; + } + + d->unitedDirtyRegion = d->unitedDirtyRegion.unite(region); + d->dirtyRegions.append(region); + polish(); + update(d->unitedDirtyRegion); } bool QSGCanvasItem::save(const QString &filename) const @@ -147,6 +213,26 @@ bool QSGCanvasItem::save(const QString &filename) const return false; } +void QSGCanvasItem::updatePolish() +{ + Q_D(QSGCanvasItem); + QDeclarativeV8Handle context = QDeclarativeV8Handle::fromHandle(d->context->v8value()); + + d->context->setValid(true); + + // d->context->setTileRect(QRectF(d->canvasX, d->canvasY, d->width, d->height).intersected(QRectF(0, 0, d->width, d->height))); + // d->context->setTileRect(QRectF(d->canvasX, d->canvasY, d->width, d->height)); + + foreach (const QRect& region, d->dirtyRegions) { + emit paint(context, region); + } + d->dirtyRegions.clear(); + + d->context->setValid(false); + + QSGPaintedItem::updatePolish(); +} + QString QSGCanvasItem::toDataURL(const QString& mimeType) const { Q_D(const QSGCanvasItem); @@ -182,5 +268,4 @@ QString QSGCanvasItem::toDataURL(const QString& mimeType) const } return QLatin1String("data:,"); } - QT_END_NAMESPACE |