diff options
-rw-r--r-- | examples/declarative/canvas/svgpath/tiger.js | 8 | ||||
-rw-r--r-- | examples/declarative/canvas/svgpath/tiger.qml | 86 | ||||
-rw-r--r-- | src/declarative/items/qsgcanvasitem.cpp | 119 | ||||
-rw-r--r-- | src/declarative/items/qsgcanvasitem_p.h | 20 | ||||
-rw-r--r-- | src/declarative/items/qsgcontext2d.cpp | 427 | ||||
-rw-r--r-- | src/declarative/items/qsgcontext2d_p.h | 19 | ||||
-rw-r--r-- | src/declarative/items/qsgcontext2d_p_p.h | 4 |
7 files changed, 490 insertions, 193 deletions
diff --git a/examples/declarative/canvas/svgpath/tiger.js b/examples/declarative/canvas/svgpath/tiger.js index 2695cd52fe..d8657b5abe 100644 --- a/examples/declarative/canvas/svgpath/tiger.js +++ b/examples/declarative/canvas/svgpath/tiger.js @@ -724,6 +724,7 @@ var tiger = [ function draw(ctx, frame) { + var startTime = new Date(); var totalPaths = tiger.length; if (frame > totalPaths) @@ -731,14 +732,12 @@ function draw(ctx, frame) ctx.reset(); ctx.globalCompositeOperation = "source-over"; ctx.fillStyle = "rgba(0,0,0,0)"; - //ctx.fillRect(0, 0, 600, 600); ctx.fillRect(0, 0, 1900, 1200); ctx.strokeColor = Qt.rgba(133, 133, 133,1); ctx.lineWidth = 1; - //ctx.translate(200, 200); ctx.translate(750, 350); - ctx.scale(2,2); + ctx.scale(5,5); for (var i = 0; i < frame; i++) { if (tiger[i].width != undefined) ctx.lineWidth = tiger[i].width; @@ -756,6 +755,9 @@ function draw(ctx, frame) ctx.stroke(); } } + var endTime = new Date(); + console.log("Javascript time:" + (endTime.valueOf() - startTime.valueOf())); + } diff --git a/examples/declarative/canvas/svgpath/tiger.qml b/examples/declarative/canvas/svgpath/tiger.qml index 96d19d3dba..77161e7c46 100644 --- a/examples/declarative/canvas/svgpath/tiger.qml +++ b/examples/declarative/canvas/svgpath/tiger.qml @@ -5,29 +5,81 @@ Canvas { id:canvas width:1900 height:1100 + fillColor:"#000000" + focus:true + renderTarget:PaintedItem.FramebufferObject property int frame:0 - - Timer { - repeat:true - interval:100 - running:true - onTriggered: { + property date paintingTime + Component.onCompleted: { + canvas.frame++; + canvas.requestPaint(); + } + onPainted: { + var endPaintingTime = new Date; + console.log("painting time:" + (endPaintingTime.valueOf() - canvas.paintingTime.valueOf())); canvas.frame++; if (canvas.frame > Tiger.tiger.length) { - canvas.frame = 0; +// canvas.frame = 0; + canvas.frame = Tiger.tiger.length; } else { - Tiger.draw(canvas.getContext(), canvas.frame); + canvas.requestPaint(); } - } } -/* - onDrawRegion:{ + onPaint:{ + canvas.paintingTime = new Date(); Tiger.draw(context, canvas.frame); } -Text { - anchors.top : parent.top - font.pixelSize : 30 - text: "drawing path:" + canvas.frame + "/" + Tiger.tiger.length; -} -*/ + Keys.onPressed : { + if (event.key == Qt.Key_Plus) { + canvas.contentsScale *= 1.5; + } + if (event.key == Qt.Key_Minus) { + canvas.contentsScale *= 0.7; + } + if (event.key == Qt.Key_Left) { + canvas.canvasX +=60; + } + if (event.key == Qt.Key_Right) { + canvas.canvasX -= 60; + } + if (event.key == Qt.Key_Up) { + canvas.canvasY += 40; + } + if (event.key == Qt.Key_Down) { + canvas.canvasY -= 40; + } + + canvas.requestPaint(); + } + Rectangle { + anchors.bottom : parent.bottom + color: "white" + opacity:0.7 + height:50 + width:canvas.width + radius:4 + Text { + anchors.bottom : parent.bottom + font.pixelSize : 30 + text: "drawing path:" + canvas.frame + "/" + Tiger.tiger.length + + " moving to:(" + canvas.canvasX + "," + canvas.canvasY + ")" + + " scale:" + canvas.contentsScale; + } + } + + MouseArea { + id:mouseArea + anchors.fill:parent + property real pressedX; + property real pressedY; + onPressed: { + pressedX = mouseX; + pressedY = mouseY; + } + onPositionChanged : { + canvas.canvasX = mouseX - pressedX; + canvas.canvasY = mouseY - pressedY; + canvas.requestPaint(); + } + } } 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 diff --git a/src/declarative/items/qsgcanvasitem_p.h b/src/declarative/items/qsgcanvasitem_p.h index 71358c4d9e..9a6ccc27ed 100644 --- a/src/declarative/items/qsgcanvasitem_p.h +++ b/src/declarative/items/qsgcanvasitem_p.h @@ -61,26 +61,36 @@ class QSGCanvasItemPrivate; class QSGCanvasItem : public QSGPaintedItem { Q_OBJECT + Q_PROPERTY(QPointF canvasPos READ canvasPos FINAL) + Q_PROPERTY(qreal canvasX READ canvasX WRITE setCanvasX NOTIFY canvasXChanged FINAL) + Q_PROPERTY(qreal canvasY READ canvasY WRITE setCanvasY NOTIFY canvasYChanged FINAL) public: QSGCanvasItem(QSGItem *parent = 0); ~QSGCanvasItem(); - + void setCanvasX(qreal x); + void setCanvasY(qreal y); + qreal canvasX() const; + qreal canvasY() const; + QPointF canvasPos() const; Q_SIGNALS: - void canvasUpdated(); - void drawRegion(QDeclarativeV8Handle context, const QRect ®ion); - + void painted(); + void paint(QDeclarativeV8Handle context, const QRect ®ion); + void canvasXChanged(); + void canvasYChanged(); public Q_SLOTS: QString toDataURL(const QString& type = QLatin1String("image/png")) const; QDeclarativeV8Handle getContext(const QString & = QLatin1String("2d")); - void requestPaint(); + void requestPaint(const QRect& region = QRect()); // Save current canvas to disk bool save(const QString& filename) const; protected: + void updatePolish(); void paint(QPainter *painter); virtual void componentComplete(); private: + void createContext(); Q_DECLARE_PRIVATE(QSGCanvasItem) friend class QSGContext2D; }; diff --git a/src/declarative/items/qsgcontext2d.cpp b/src/declarative/items/qsgcontext2d.cpp index f3371ed982..6f3b117661 100644 --- a/src/declarative/items/qsgcontext2d.cpp +++ b/src/declarative/items/qsgcontext2d.cpp @@ -82,10 +82,20 @@ void copy_vector(QVector<T>* dst, const QVector<T>& src) // But it really should be considered private API void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); - +static bool parsePathDataFast(const QString &dataStr, QPainterPath &path); #define DEGREES(t) ((t) * 180.0 / Q_PI) #define qClamp(val, min, max) qMin(qMax(val, min), max) +#define CHECK_CONTEXT(r) if (!r || !r->context) \ + V8THROW_ERROR("Not a Context2D object"); \ + if (!r->context->valid()) \ + V8THROW_ERROR("Context2D object is out of scope, please only access context2d APIs from onPaint method."); + +#define CHECK_CONTEXT_SETTER(r) if (!r || !r->context) \ + V8THROW_ERROR_SETTER("Not a Context2D object"); \ + if (!r->context->valid()) \ + V8THROW_ERROR_SETTER("Context2D object is out of scope, please only access context2d APIs from onPaint method."); + static inline int extractInt(const char **name) { int result = 0; @@ -380,8 +390,8 @@ public: static v8::Handle<v8::Value> ctx2d_sync(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->sync(); @@ -392,8 +402,8 @@ static v8::Handle<v8::Value> ctx2d_sync(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_canvas(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -404,8 +414,8 @@ static v8::Handle<v8::Value> ctx2d_canvas(v8::Local<v8::String>, const v8::Acces static v8::Handle<v8::Value> ctx2d_restore(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->restore(); @@ -415,8 +425,8 @@ static v8::Handle<v8::Value> ctx2d_restore(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->reset(); @@ -426,8 +436,8 @@ static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_save(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->save(); @@ -438,8 +448,8 @@ static v8::Handle<v8::Value> ctx2d_save(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 1) r->context->rotate(args[0]->NumberValue()); @@ -450,8 +460,8 @@ static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 2) r->context->scale(args[0]->NumberValue(), args[1]->NumberValue()); @@ -462,8 +472,8 @@ static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 6) { r->context->setTransform(args[0]->NumberValue(), @@ -480,8 +490,8 @@ static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 6) { r->context->transform(args[0]->NumberValue(), @@ -498,8 +508,8 @@ static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 2) { r->context->translate(args[0]->NumberValue(), @@ -514,8 +524,8 @@ static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_globalAlpha(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->globalAlpha()); } @@ -523,18 +533,30 @@ static v8::Handle<v8::Value> ctx2d_globalAlpha(v8::Local<v8::String>, const v8:: static void ctx2d_globalAlpha_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setGlobalAlpha(value->NumberValue()); } +// read only property to indicate the validation of the context object +static v8::Handle<v8::Value> ctx2d_valid(v8::Local<v8::String>, const v8::AccessorInfo &info) +{ + QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); + CHECK_CONTEXT(r) + + + QV8Engine *engine = V8ENGINE_ACCESSOR(); + + return v8::Boolean::New(r->context->valid()); +} + + // string getter/setter default "source-over" static v8::Handle<v8::Value> ctx2d_globalCompositeOperation(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -544,8 +566,7 @@ static v8::Handle<v8::Value> ctx2d_globalCompositeOperation(v8::Local<v8::String static void ctx2d_globalCompositeOperation_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -557,8 +578,8 @@ static void ctx2d_globalCompositeOperation_set(v8::Local<v8::String>, v8::Local< static v8::Handle<v8::Value> ctx2d_fillStyle(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -568,8 +589,7 @@ static v8::Handle<v8::Value> ctx2d_fillStyle(v8::Local<v8::String>, const v8::Ac static void ctx2d_fillStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -581,8 +601,8 @@ static void ctx2d_fillStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> valu static v8::Handle<v8::Value> ctx2d_fillColor(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -592,8 +612,7 @@ static v8::Handle<v8::Value> ctx2d_fillColor(v8::Local<v8::String>, const v8::Ac static void ctx2d_fillColor_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -604,8 +623,8 @@ static void ctx2d_fillColor_set(v8::Local<v8::String>, v8::Local<v8::Value> valu v8::Handle<v8::Value> ctx2d_strokeStyle(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -615,8 +634,7 @@ v8::Handle<v8::Value> ctx2d_strokeStyle(v8::Local<v8::String>, const v8::Accesso static void ctx2d_strokeStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -628,8 +646,8 @@ static void ctx2d_strokeStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> va v8::Handle<v8::Value> ctx2d_strokeColor(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -639,8 +657,7 @@ v8::Handle<v8::Value> ctx2d_strokeColor(v8::Local<v8::String>, const v8::Accesso static void ctx2d_strokeColor_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -650,8 +667,8 @@ static void ctx2d_strokeColor_set(v8::Local<v8::String>, v8::Local<v8::Value> va static v8::Handle<v8::Value> ctx2d_createLinearGradient(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); @@ -669,8 +686,8 @@ static v8::Handle<v8::Value> ctx2d_createLinearGradient(const v8::Arguments &arg static v8::Handle<v8::Value> ctx2d_createRadialGradient(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); @@ -698,8 +715,8 @@ static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args) v8::Handle<v8::Value> ctx2d_lineCap(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -709,8 +726,7 @@ v8::Handle<v8::Value> ctx2d_lineCap(v8::Local<v8::String>, const v8::AccessorInf static void ctx2d_lineCap_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -721,8 +737,8 @@ static void ctx2d_lineCap_set(v8::Local<v8::String>, v8::Local<v8::Value> value, v8::Handle<v8::Value> ctx2d_lineJoin(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -732,8 +748,7 @@ v8::Handle<v8::Value> ctx2d_lineJoin(v8::Local<v8::String>, const v8::AccessorIn static void ctx2d_lineJoin_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -744,8 +759,8 @@ static void ctx2d_lineJoin_set(v8::Local<v8::String>, v8::Local<v8::Value> value v8::Handle<v8::Value> ctx2d_lineWidth(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->lineWidth()); } @@ -753,8 +768,7 @@ v8::Handle<v8::Value> ctx2d_lineWidth(v8::Local<v8::String>, const v8::AccessorI static void ctx2d_lineWidth_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setLineWidth(value->NumberValue()); } @@ -763,8 +777,8 @@ static void ctx2d_lineWidth_set(v8::Local<v8::String>, v8::Local<v8::Value> valu v8::Handle<v8::Value> ctx2d_miterLimit(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->miterLimit()); } @@ -772,8 +786,7 @@ v8::Handle<v8::Value> ctx2d_miterLimit(v8::Local<v8::String>, const v8::Accessor static void ctx2d_miterLimit_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setMiterLimit(value->NumberValue()); } @@ -783,8 +796,8 @@ static void ctx2d_miterLimit_set(v8::Local<v8::String>, v8::Local<v8::Value> val v8::Handle<v8::Value> ctx2d_shadowBlur(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->shadowBlur()); } @@ -792,8 +805,7 @@ v8::Handle<v8::Value> ctx2d_shadowBlur(v8::Local<v8::String>, const v8::Accessor static void ctx2d_shadowBlur_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setShadowBlur(value->NumberValue()); } @@ -801,8 +813,8 @@ static void ctx2d_shadowBlur_set(v8::Local<v8::String>, v8::Local<v8::Value> val v8::Handle<v8::Value> ctx2d_shadowColor(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -812,8 +824,7 @@ v8::Handle<v8::Value> ctx2d_shadowColor(v8::Local<v8::String>, const v8::Accesso static void ctx2d_shadowColor_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) QV8Engine *engine = V8ENGINE_ACCESSOR(); @@ -823,8 +834,8 @@ static void ctx2d_shadowColor_set(v8::Local<v8::String>, v8::Local<v8::Value> va v8::Handle<v8::Value> ctx2d_shadowOffsetX(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->shadowOffsetX()); } @@ -832,8 +843,7 @@ v8::Handle<v8::Value> ctx2d_shadowOffsetX(v8::Local<v8::String>, const v8::Acces static void ctx2d_shadowOffsetX_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setShadowOffsetX(value->NumberValue()); } @@ -841,8 +851,8 @@ static void ctx2d_shadowOffsetX_set(v8::Local<v8::String>, v8::Local<v8::Value> v8::Handle<v8::Value> ctx2d_shadowOffsetY(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Number::New(r->context->shadowOffsetY()); } @@ -850,8 +860,7 @@ v8::Handle<v8::Value> ctx2d_shadowOffsetY(v8::Local<v8::String>, const v8::Acces static void ctx2d_shadowOffsetY_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) r->context->setShadowOffsetY(value->NumberValue()); } @@ -860,8 +869,8 @@ static void ctx2d_shadowOffsetY_set(v8::Local<v8::String>, v8::Local<v8::Value> static v8::Handle<v8::Value> ctx2d_clearRect(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 4) { r->context->clearRect(args[0]->NumberValue(), @@ -876,8 +885,8 @@ static v8::Handle<v8::Value> ctx2d_clearRect(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_fillRect(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 4) { r->context->fillRect(args[0]->NumberValue(), @@ -892,8 +901,8 @@ static v8::Handle<v8::Value> ctx2d_fillRect(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_strokeRect(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 4) { r->context->strokeRect(args[0]->NumberValue(), @@ -909,8 +918,8 @@ static v8::Handle<v8::Value> ctx2d_strokeRect(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_arc(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 6) { r->context->arc(args[0]->NumberValue(), @@ -927,8 +936,8 @@ static v8::Handle<v8::Value> ctx2d_arc(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_arcTo(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 5) { r->context->arcTo(args[0]->NumberValue(), @@ -944,8 +953,8 @@ static v8::Handle<v8::Value> ctx2d_arcTo(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_beginPath(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->beginPath(); @@ -955,8 +964,8 @@ static v8::Handle<v8::Value> ctx2d_beginPath(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_bezierCurveTo(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 5) { r->context->bezierCurveTo(args[0]->NumberValue(), @@ -973,8 +982,8 @@ static v8::Handle<v8::Value> ctx2d_bezierCurveTo(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_clip(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->clip(); @@ -984,8 +993,8 @@ static v8::Handle<v8::Value> ctx2d_clip(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_closePath(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->closePath(); @@ -995,8 +1004,8 @@ static v8::Handle<v8::Value> ctx2d_closePath(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->fill(); @@ -1006,8 +1015,8 @@ static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_lineTo(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 2) { r->context->lineTo(args[0]->NumberValue(), @@ -1020,8 +1029,8 @@ static v8::Handle<v8::Value> ctx2d_lineTo(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_moveTo(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 2) { r->context->moveTo(args[0]->NumberValue(), @@ -1034,8 +1043,8 @@ static v8::Handle<v8::Value> ctx2d_moveTo(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_quadraticCurveTo(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 4) { r->context->quadraticCurveTo(args[0]->NumberValue(), @@ -1050,8 +1059,8 @@ static v8::Handle<v8::Value> ctx2d_quadraticCurveTo(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_rect(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + if (args.Length() == 4) { r->context->rect(args[0]->NumberValue(), @@ -1066,8 +1075,8 @@ static v8::Handle<v8::Value> ctx2d_rect(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_stroke(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + r->context->stroke(); @@ -1077,8 +1086,8 @@ static v8::Handle<v8::Value> ctx2d_stroke(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + bool pointInPath = false; if (args.Length() == 2) { @@ -1092,8 +1101,8 @@ static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_setPathString(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); if (args.Length() == 1) { @@ -1102,12 +1111,48 @@ static v8::Handle<v8::Value> ctx2d_setPathString(const v8::Arguments &args) return v8::Undefined(); } +static v8::Handle<v8::Value> ctx2d_path(v8::Local<v8::String>, const v8::AccessorInfo &info) +{ +// QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); +// CHECK_CONTEXT(r) + +// QV8Engine *engine = V8ENGINE(); + + return v8::Undefined(); +} + +static v8::Handle<v8::Value> ctx2d_path_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) +{ +// QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); +// CHECK_CONTEXT(r) + + +// QV8Engine *engine = V8ENGINE(); +// if (args.Length() == 1) { +// r->context->setPathString(engine->toString(args[0])); +// } + return v8::Undefined(); +} + +static v8::Handle<v8::Value> ctx2d_createPath(const v8::Arguments &args) +{ +// QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); +// CHECK_CONTEXT(r) + + +// QV8Engine *engine = V8ENGINE(); +// if (args.Length() == 1) { +// r->context->setPathString(engine->toString(args[0])); +// } + return v8::Undefined(); +} + // text v8::Handle<v8::Value> ctx2d_font(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Undefined(); } @@ -1115,8 +1160,7 @@ v8::Handle<v8::Value> ctx2d_font(v8::Local<v8::String>, const v8::AccessorInfo & static void ctx2d_font_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) Q_UNUSED(value); } @@ -1124,8 +1168,8 @@ static void ctx2d_font_set(v8::Local<v8::String>, v8::Local<v8::Value> value, co v8::Handle<v8::Value> ctx2d_textAlign(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Undefined(); } @@ -1133,8 +1177,7 @@ v8::Handle<v8::Value> ctx2d_textAlign(v8::Local<v8::String>, const v8::AccessorI static void ctx2d_textAlign_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) Q_UNUSED(value); } @@ -1142,8 +1185,8 @@ static void ctx2d_textAlign_set(v8::Local<v8::String>, v8::Local<v8::Value> valu v8::Handle<v8::Value> ctx2d_textBaseline(v8::Local<v8::String>, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + return v8::Undefined(); } @@ -1151,8 +1194,7 @@ v8::Handle<v8::Value> ctx2d_textBaseline(v8::Local<v8::String>, const v8::Access static void ctx2d_textBaseline_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This()); - if (!r || !r->context) - V8THROW_ERROR_SETTER("Not a Context2D object"); + CHECK_CONTEXT_SETTER(r) Q_UNUSED(value); } @@ -1160,8 +1202,8 @@ static void ctx2d_textBaseline_set(v8::Local<v8::String>, v8::Local<v8::Value> v static v8::Handle<v8::Value> ctx2d_fillText(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); @@ -1177,8 +1219,8 @@ static v8::Handle<v8::Value> ctx2d_fillText(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); @@ -1195,8 +1237,8 @@ static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args) static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args) { QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This()); - if (!r || !r->context) - V8THROW_ERROR("Not a Context2D object"); + CHECK_CONTEXT(r) + QV8Engine *engine = V8ENGINE(); @@ -1509,20 +1551,38 @@ void QSGContext2DPrivate::clearRect(qreal x, qreal y, void QSGContext2DPrivate::fillRect(qreal x, qreal y, qreal w, qreal h) { - commands.push_back(QSGContext2D::FillRect); - reals.push_back(x); - reals.push_back(y); - reals.push_back(w); - reals.push_back(h); + QRectF rect; + if (tileRect.isValid()) { + rect = tileRect.intersect(QRect(x, y, w, h)); + } else { + rect = QRectF(x, y, w, h); + } + + if (rect.isValid()) { + commands.push_back(QSGContext2D::FillRect); + reals.push_back(rect.x()); + reals.push_back(rect.y()); + reals.push_back(rect.width()); + reals.push_back(rect.height()); + } } void QSGContext2DPrivate::strokeRect(qreal x, qreal y, qreal w, qreal h) { - QPainterPath path; - path.addRect(x, y, w, h); - commands.push_back(QSGContext2D::Stroke); - pathes.push_back(path); + QPainterPath p; + p.addRect(x, y, w, h); + + if (tileRect.isValid()) { + QPainterPath tr; + tr.addRect(tileRect); + p = p.intersected(tr); + } + + if (!p.isEmpty()) { + commands.push_back(QSGContext2D::Stroke); + pathes.push_back(p); + } } void QSGContext2DPrivate::beginPath() @@ -1633,21 +1693,39 @@ void QSGContext2DPrivate::arc(qreal xc, void QSGContext2DPrivate::fill() { - commands.push_back(QSGContext2D::Fill); - pathes.push_back(path); + QPainterPath tr; + if (tileRect.isValid()) { + tr.addRect(tileRect); + tr = tr.intersected(path); + } else { + tr = path; + } + + if (!tr.isEmpty()) { + commands.push_back(QSGContext2D::Fill); + pathes.push_back(tr); + } } void QSGContext2DPrivate::stroke() { - commands.push_back(QSGContext2D::Stroke); - pathes.push_back(path); -// painter->setMatrix(state.matrix, false); -// QPainterPath tmp = state.matrix.inverted().map(path); //why? -// painter->strokePath(tmp, painter->pen()); + QPainterPath tr; + if (tileRect.isValid()) { + tr.addRect(tileRect); + tr = tr.intersected(path); + } else { + tr = path; + } + + if (!tr.isEmpty()) { + commands.push_back(QSGContext2D::Stroke); + pathes.push_back(tr); + } } void QSGContext2DPrivate::clip() { + //TODO:XXX state.clipPath = path; pathes.push_back(state.clipPath); commands.push_back(QSGContext2D::Clip); @@ -2214,6 +2292,26 @@ void QSGContext2D::setShadowColor(const QString &str) d->setShadowColor(str); } +QSGCanvasPath* QSGContext2D::path() +{ + Q_D(const QSGContext2D); + return new QSGCanvasPath(d->path, this); +} +void QSGContext2D::setPath(QSGCanvasPath* path) +{ + Q_D(QSGContext2D); + d->path = path->m_path; +} + +QSGCanvasPath* QSGContext2D::createPath(const QString& pathString) +{ + QPainterPath path; + if (parsePathDataFast(pathString, path)) { + return new QSGCanvasPath(path, this); + } + return 0; +} + QString QSGContext2D::textBaseline() const { Q_D(const QSGContext2D); @@ -3140,6 +3238,7 @@ QSGContext2DEngineData::QSGContext2DEngineData(QV8Engine *engine) ft->PrototypeTemplate()->Set(v8::String::New("setTransform"), V8FUNCTION(ctx2d_setTransform, engine)); ft->PrototypeTemplate()->Set(v8::String::New("transform"), V8FUNCTION(ctx2d_transform, engine)); ft->PrototypeTemplate()->Set(v8::String::New("translate"), V8FUNCTION(ctx2d_translate, engine)); + ft->InstanceTemplate()->SetAccessor(v8::String::New("valid"), ctx2d_valid, 0, v8::External::Wrap(engine)); ft->InstanceTemplate()->SetAccessor(v8::String::New("globalAlpha"), ctx2d_globalAlpha, ctx2d_globalAlpha_set, v8::External::Wrap(engine)); ft->InstanceTemplate()->SetAccessor(v8::String::New("globalCompositeOperation"), ctx2d_globalCompositeOperation, ctx2d_globalCompositeOperation_set, v8::External::Wrap(engine)); ft->InstanceTemplate()->SetAccessor(v8::String::New("fillStyle"), ctx2d_fillStyle, ctx2d_fillStyle_set, v8::External::Wrap(engine)); @@ -3195,8 +3294,17 @@ QSGContext2DEngineData::~QSGContext2DEngineData() V8_DEFINE_EXTENSION(QSGContext2DEngineData, engineData); +QV8Engine* QSGContext2D::v8Engine() const +{ + Q_D(const QSGContext2D); + return d->v8engine; +} + void QSGContext2D::setV8Engine(QV8Engine *engine) { + v8::HandleScope handle_scope; + v8::Context::Scope scope(engine->context()); + Q_D(QSGContext2D); if (d->v8engine != engine) { d->v8engine = engine; @@ -3214,6 +3322,23 @@ void QSGContext2D::setV8Engine(QV8Engine *engine) } } +bool QSGContext2D::valid() const +{ + Q_D(const QSGContext2D); + return d->valid; +} + +void QSGContext2D::setValid(bool valid) +{ + Q_D(QSGContext2D); + d->valid = valid; +} +void QSGContext2D::setTileRect(const QRectF& rect) +{ + Q_D(QSGContext2D); + if (d->tileRect != rect) + d->tileRect = rect; +} void QSGContext2D::addref() { Q_D(QSGContext2D); @@ -3538,7 +3663,7 @@ void QSGContext2D::paint(QPainter* p) { Q_D(QSGContext2D); - QTransform transform = p->worldTransform(); + QMatrix originMatrix = p->matrix(); if (!d->commands.isEmpty()) { int matrix_idx, real_idx, int_idx, variant_idx, string_idx,color_idx,cmd_idx, pen_idx, brush_idx, font_idx, path_idx, image_idx, size_idx; @@ -3551,7 +3676,7 @@ void QSGContext2D::paint(QPainter* p) case UpdateMatrix: { d->state.matrix = d->matrixes[matrix_idx++]; - p->setMatrix(d->state.matrix); + p->setMatrix(d->state.matrix * originMatrix); break; } case ClearRect: diff --git a/src/declarative/items/qsgcontext2d_p.h b/src/declarative/items/qsgcontext2d_p.h index 924c4bf780..335d954fc1 100644 --- a/src/declarative/items/qsgcontext2d_p.h +++ b/src/declarative/items/qsgcontext2d_p.h @@ -86,6 +86,16 @@ public: Q_DECLARE_METATYPE(QSGCanvasGradient*) +class QSGCanvasPath : QObject +{ + Q_OBJECT +public: + QSGCanvasPath(const QPainterPath& path, QObject* parent = 0) : QObject(parent), m_path(path) {} + + QPainterPath m_path; +}; +Q_DECLARE_METATYPE(QSGCanvasPath*) + class QSGContext2DWorkerAgent; class QSGContext2DPrivate; class QSGCanvasItem; @@ -113,6 +123,8 @@ class QSGContext2D : public QObject Q_PROPERTY(QString font READ font WRITE setFont) Q_PROPERTY(QString textBaseline READ textBaseline WRITE setTextBaseline) Q_PROPERTY(QString textAlign READ textAlign WRITE setTextAlign) + + Q_PROPERTY(QSGCanvasPath* path READ path WRITE setPath) Q_ENUMS(PaintCommand) public: enum TextBaseLineType { Alphabetic=0, Top, Middle, Bottom, Hanging}; @@ -245,6 +257,8 @@ public: void setShadowBlur(qreal b); void setShadowColor(const QString &str); + QSGCanvasPath* path(); + void setPath(QSGCanvasPath* path); public slots: void save(); // push state on state stack void restore(); // pop state stack and restore state @@ -295,6 +309,7 @@ public slots: //implement the W3C SVG path spec: //http://www.w3.org/TR/SVG/paths.html void setPathString(const QString& path); + QSGCanvasPath* createPath(const QString& pathString); QSGImage *createImage(const QString &url); @@ -315,8 +330,12 @@ signals: public: bool isDirty() const; v8::Handle<v8::Object> v8value() const; + QV8Engine* v8Engine() const; void setV8Engine(QV8Engine *eng); + bool valid() const; + void setValid(bool valid); + void setTileRect(const QRectF& region); void addref(); void release(); diff --git a/src/declarative/items/qsgcontext2d_p_p.h b/src/declarative/items/qsgcontext2d_p_p.h index 4fcf40406e..ed73b2fbd2 100644 --- a/src/declarative/items/qsgcontext2d_p_p.h +++ b/src/declarative/items/qsgcontext2d_p_p.h @@ -82,6 +82,7 @@ public: , cachedImage(1,1, QImage::Format_ARGB32) , canvas(0) , waitingForPainting(false) + , valid(false) { } ~QSGContext2DPrivate() @@ -180,6 +181,7 @@ public: void clearCommands() { + qDebug() << "painting commands:" << commands.size(); commands.remove(0, commands.size()); variants.remove(0, variants.size()); pens.remove(0, pens.size()); @@ -227,6 +229,8 @@ public: QImage cachedImage; QSGCanvasItem* canvas; bool waitingForPainting; + bool valid; + QRectF tileRect; }; QT_END_NAMESPACE |