aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCharles Yin <charles.yin@nokia.com>2011-07-12 09:21:27 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-12 04:25:33 +0200
commitb119220da60453ecf31898f7a57eda9d3c4e9225 (patch)
tree0b316ed1ef9a5e0e154c0a87628a6a5ff205c9dc /src
parentbd4d69c9a88f476b4de4ba80945d39725bb29efa (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')
-rw-r--r--src/declarative/items/qsgcanvasitem.cpp119
-rw-r--r--src/declarative/items/qsgcanvasitem_p.h20
-rw-r--r--src/declarative/items/qsgcontext2d.cpp427
-rw-r--r--src/declarative/items/qsgcontext2d_p.h19
-rw-r--r--src/declarative/items/qsgcontext2d_p_p.h4
5 files changed, 416 insertions, 173 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
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 &region);
-
+ void painted();
+ void paint(QDeclarativeV8Handle context, const QRect &region);
+ 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