rewrite context2d with direct QtScript binding
authorCharles Yin <charles.yin@nokia.com>
Mon, 30 May 2011 06:14:42 +0000 (16:14 +1000)
committerCharles Yin <charles.yin@nokia.com>
Fri, 3 Jun 2011 04:27:03 +0000 (14:27 +1000)
for better performance.

Change-Id: I740ad4cbb7446a838954a010b0e5f0b847ec4f53

src/declarative/items/qsgcanvasitem.cpp
src/declarative/items/qsgcanvasitem_p.h
src/declarative/items/qsgcontext2d.cpp
src/declarative/items/qsgcontext2d_p.h

index ba3c4ba..a6403c0 100644 (file)
@@ -56,6 +56,7 @@ class QSGCanvasItemPrivate : public QSGPaintedItemPrivate
 {
 public:
     QSGCanvasItemPrivate();
+    ~QSGCanvasItemPrivate();
     QSGContext2D* context;
 };
 
@@ -69,6 +70,10 @@ QSGCanvasItemPrivate::QSGCanvasItemPrivate()
 {
 }
 
+QSGCanvasItemPrivate::~QSGCanvasItemPrivate()
+{
+}
+
 /*!
     Constructs a QSGCanvasItem with the given \a parent item.
  */
@@ -94,24 +99,25 @@ void QSGCanvasItem::paint(QPainter *painter)
     }
 }
 
-
-QSGContext2D* QSGCanvasItem::getContext(const QString &contextId)
+QScriptValue QSGCanvasItem::getContext(const QString &contextId)
 {
     Q_D(QSGCanvasItem);
+    QScriptEngine* e = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this));
     if (contextId == QLatin1String("2d")) {
         if (!d->context) {
             d->context = new QSGContext2D(this);
+            d->context->setScriptEngine(e);
             connect(d->context, SIGNAL(changed()), this, SLOT(requestPaint()));
         }
-        return d->context;
+        return d->context->scriptValue();
     }
     qDebug("Canvas:requesting unsupported context");
-    return 0;
+    return e->undefinedValue();
 }
 
 void QSGCanvasItem::requestPaint()
 {
-    Q_D(QSGCanvasItem);
+    //Q_D(QSGCanvasItem);
     //TODO:update(d->context->dirtyRect());
     update();
 }
@@ -140,19 +146,19 @@ QString QSGCanvasItem::toDataURL(const QString& mimeType) const
         QString mime = mimeType;
         QString type;
         if (mimeType == QLatin1String("image/bmp"))
-            type = "BMP";
+            type = QLatin1String("BMP");
         else if (mimeType == QLatin1String("image/jpeg"))
-            type = "JPEG";
+            type = QLatin1String("JPEG");
         else if (mimeType == QLatin1String("image/x-portable-pixmap"))
-            type = "PPM";
+            type = QLatin1String("PPM");
         else if (mimeType == QLatin1String("image/tiff"))
-            type = "TIFF";
+            type = QLatin1String("TIFF");
         else if (mimeType == QLatin1String("image/xbm"))
-            type = "XBM";
+            type = QLatin1String("XBM");
         else if (mimeType == QLatin1String("image/xpm"))
-            type = "XPM";
+            type = QLatin1String("XPM");
         else {
-            type = "PNG";
+            type = QLatin1String("PNG");
             mime = QLatin1String("image/png");
         }
         image.save(&buffer, type.toAscii());
@@ -162,280 +168,5 @@ QString QSGCanvasItem::toDataURL(const QString& mimeType) const
     }
     return QLatin1String("data:,");
 }
-//CanvasItemTextureProvider::CanvasItemTextureProvider(QObject *parent)
-//    : QSGTextureProvider(parent)
-//    , m_ctx2d(0)
-//    , m_fbo(0)
-//    , m_multisampledFbo(0)
-//    , m_dirtyTexture(true)
-//    , m_multisamplingSupportChecked(false)
-//    , m_multisampling(false)
-//{
-//}
-
-//CanvasItemTextureProvider::~CanvasItemTextureProvider()
-//{
-//    delete m_fbo;
-//    delete m_multisampledFbo;
-//}
-
-//void CanvasItemTextureProvider::updateTexture()
-//{
-//    if (m_dirtyTexture) {
-//        if (!m_ctx2d->isDirty())
-//            return;
-//        if (m_size.isEmpty()) {
-//            m_texture = QSGTextureRef();
-//            delete m_fbo;
-//            delete m_multisampledFbo;
-//            m_multisampledFbo = m_fbo = 0;
-//            return;
-//        }
-
-//#ifndef QSGCANVASITEM_PAINTING_ON_IMAGE
-//        //create texture
-//        if (!m_fbo || m_fbo->size() != m_size )
-//        {
-//            const QGLContext *ctx = QSGContext::current->glContext();
-//            if (!m_multisamplingSupportChecked) {
-//                QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
-//                m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample")
-//                                && extensions.contains("GL_EXT_framebuffer_blit");
-//                m_multisamplingSupportChecked = true;
-//            }
-
-//            if (ctx->format().sampleBuffers() && m_multisampling) {
-//                delete m_fbo;
-//                delete m_multisampledFbo;
-//                QGLFramebufferObjectFormat format;
-
-//                format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
-//                format.setSamples(ctx->format().samples());
-//                m_multisampledFbo = new QGLFramebufferObject(m_size, format);
-//                {
-//                    QGLFramebufferObjectFormat format;
-//                    format.setAttachment(QGLFramebufferObject::NoAttachment);
-//                    m_fbo = new QGLFramebufferObject(m_size, format);
-//                }
-
-//                QSGPlainTexture *tex = new QSGPlainTexture;
-//                tex->setTextureId(m_fbo->texture());
-//                tex->setOwnsTexture(false);
-//                tex->setHasAlphaChannel(true);
-//                setOpaque(!tex->hasAlphaChannel());
-//                m_texture = QSGTextureRef(tex);
-//            } else {
-//                delete m_fbo;
-//                QGLFramebufferObjectFormat format;
-//                format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
-//                m_fbo = new QGLFramebufferObject(m_size, format);
-//                QSGPlainTexture *tex = new QSGPlainTexture;
-//                tex->setTextureId(m_fbo->texture());
-//                tex->setOwnsTexture(false);
-//                tex->setHasAlphaChannel(true);
-//                setOpaque(!tex->hasAlphaChannel());
-//                m_texture = QSGTextureRef(tex);
-//            }
-//        }
-//#endif
-
-//#ifdef QSGCANVASITEM_DEBUG
-//        qDebug() << "painting interval:" << m_elapsedTimer.nsecsElapsed();
-//        m_elapsedTimer.restart();
-//#endif
-//        //paint 2d
-//        if (m_ctx2d) {
-//            QPainter p;
-//#ifndef QSGCANVASITEM_PAINTING_ON_IMAGE
-//            if (m_multisampledFbo)
-//                p.begin(m_multisampledFbo);
-//            else if (m_fbo)
-//                p.begin(m_fbo);
-//            else
-//                return;
-//            // move the origin of coordinates to the down left corner and
-//            // scale coordinates and turn y-axis up
-//            QSize size = m_ctx2d->size();
-//            p.translate( 0, size.height());
-//            p.scale(1, -1);
-
-//            m_ctx2d->paint(&p);
-
-//            p.end();
-
-//            if (m_multisampledFbo) {
-//                QRect r(0, 0, m_fbo->width(), m_fbo->height());
-//                QGLFramebufferObject::blitFramebuffer(m_fbo, r, m_multisampledFbo, r);
-//            }
-
-//            if (m_ctx2d->requireCachedImage())
-//                m_ctx2d->setCachedImage(m_fbo->toImage());
-
-//#else
-//            m_painter.begin(m_ctx2d->paintDevice());
-//            m_ctx2d->paint(&m_painter);
-//            m_painter.end();
-
-//            if (m_texture.isNull()) {
-//                m_texture = QSGContext::current->createTexture(m_ctx2d->toImage());
-//            } else {
-//                QSGPlainTexture* t =static_cast<QSGPlainTexture*>(m_texture.texture());
-//                t->setImage(m_ctx2d->toImage());
-//            }
-//            m_ctx2d->setCachedImage(m_ctx2d->toImage());
-
-//#endif
-
-//#ifdef QSGCANVASITEM_DEBUG
-//            qDebug() << "painting time:" << m_elapsedTimer.nsecsElapsed();
-//            m_elapsedTimer.restart();
-//#endif
-//            emit painted();
-//        }
-//    }
-//}
-
-//QSGTextureRef CanvasItemTextureProvider::texture()
-//{
-//    return m_texture;
-//}
-//void CanvasItemTextureProvider::setContext2D(QSGContext2D *ctx2d)
-//{
-//    if (ctx2d && m_ctx2d != ctx2d) {
-//        m_ctx2d = ctx2d;
-//        connect(this, SIGNAL(painted()), m_ctx2d, SIGNAL(painted()));
-//    }
-//}
-//void CanvasItemTextureProvider::setRect(const QRectF &rect)
-//{
-//    if (rect == m_rect)
-//        return;
-//    m_rect = rect;
-//    markDirtyTexture();
-//}
-
-//void CanvasItemTextureProvider::setSize(const QSize &size)
-//{
-//    if (size == m_size)
-//        return;
-//    m_size = size;
-//    markDirtyTexture();
-//}
-
-//void CanvasItemTextureProvider::markDirtyTexture()
-//{
-//    m_dirtyTexture = true;
-//    emit textureChanged();
-//}
-//QSGCanvasItem::QSGCanvasItem(QSGItem *parent)
-//    : TextureItem(parent)
-//    , m_textureProvider(0)
-//    , m_context2dChanged(false)
-//    , m_context2d( new QSGContext2D(this))
-//    , m_fillMode(QSGCanvasItem::Stretch)
-//    , m_color(Qt::white)
-//{
-//    m_textureProvider = new CanvasItemTextureProvider(this);
-//    m_textureProvider->setContext2D(m_context2d);
-//    setTextureProvider(m_textureProvider, true);
-//    setFlag(QSGItem::ItemHasContents, true);
-//}
-
-//QSGCanvasItem::~QSGCanvasItem()
-//{
-//}
-
-//void QSGCanvasItem::componentComplete()
-//{
-//    m_context2d->setSize(width(), height());
-//    qDebug() << "m_context2d.size:" << m_context2d->size();
-//    connect(m_context2d, SIGNAL(changed()), this, SLOT(requestPaint()));
-//    QScriptEngine* scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this));
-//    if (scriptEngine != m_context2d->scriptEngine())
-//        m_context2d->setScriptEngine(scriptEngine);
-//    QSGItem::componentComplete();
-//}
-
-
-//void QSGCanvasItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-//{
-//    if (width() == 0 && height()
-//        && newGeometry.width() > 0 && newGeometry.height() > 0) {
-//        m_context2d->setSize(width(), height());
-//    }
-//    TextureItem::geometryChanged(newGeometry, oldGeometry);
-//}
-
-//void QSGCanvasItem::setFillMode(FillMode mode)
-//{
-//    if (m_fillMode == mode)
-//        return;
-
-//    m_fillMode = mode;
-//    update();
-//    emit fillModeChanged();
-//}
-
-//QColor QSGCanvasItem::color()
-//{
-//    return m_color;
-//}
-
-//void QSGCanvasItem::setColor(const QColor &color)
-//{
-//    if (m_color !=color) {
-//        m_color = color;
-//        colorChanged();
-//    }
-//}
-
-//QSGCanvasItem::FillMode QSGCanvasItem::fillMode() const
-//{
-//    return m_fillMode;
-//}
-
-
-
-//Node *QSGCanvasItem::updatePaintNode(Node *oldNode, UpdatePaintNodeData *data)
-//{
-//    if (width() <= 0 || height() <= 0) {
-//        delete oldNode;
-//        return 0;
-//    }
-
-//    TextureNodeInterface *node = static_cast<TextureNodeInterface *>(oldNode);
-
-//    if (node && m_context2d->isDirty()) {
-//        QRectF bounds = boundingRect();
-
-//        if (m_textureProvider) {
-//            m_textureProvider->setRect(QRectF(bounds.x(), bounds.y(), width(), height()));
-
-//            m_textureProvider->setSize(QSize(width(), height()));
-//            //m_textureProvider->setOpaque(true);
-//            m_textureProvider->setHorizontalWrapMode(QSGTextureProvider::ClampToEdge);
-//            m_textureProvider->setVerticalWrapMode(QSGTextureProvider::ClampToEdge);
-//            node->setTargetRect(bounds);
-//            node->setSourceRect(QRectF(0, 0, 1, 1));
-//            //            node->setTargetRect(image.rect());
-////            node->setSourceRect(QRectF(0, 0, 1, 1));
-////            d->textureProvider->setHorizontalWrapMode(QSGTextureProvider::ClampToEdge);
-////            d->textureProvider->setVerticalWrapMode(QSGTextureProvider::ClampToEdge);
-////            d->textureProvider->setFiltering(d->smooth ? QSGTextureProvider::Linear : QSGTextureProvider::Nearest);
-//        }
-
-//        if (m_context2dChanged) {
-//            //force textnode update the content
-//            node->setTexture(0);
-//            node->setTexture(m_textureProvider);
-//            m_context2dChanged = false;
-//        }
-//    } else {
-//        if (m_context2d->requireCachedImage())
-//            m_context2d->setCachedImage(QImage(width(), height(), QImage::Format_ARGB32_Premultiplied));
-//    }
-
-//    return TextureItem::updatePaintNode(oldNode, data);
-//}
 
 QT_END_NAMESPACE
index a358c35..b501901 100644 (file)
@@ -55,6 +55,7 @@ QT_BEGIN_HEADER
 QT_BEGIN_NAMESPACE
 
 QT_MODULE(Declarative)
+class QScriptValue;
 class QSGContext2D;
 class QSGCanvasItemPrivate;
 class QSGCanvasItem : public QSGPaintedItem
@@ -68,7 +69,7 @@ signals:
     void canvasUpdated();
 public Q_SLOTS:
     QString toDataURL(const QString& type = QLatin1String("image/png")) const;
-    QSGContext2D* getContext(const QString & = QLatin1String("2d"));
+    QScriptValue getContext(const QString & = QLatin1String("2d"));
     void requestPaint();
 
     // Save current canvas to disk
index 6f7121a..2e60de1 100644 (file)
@@ -366,6 +366,536 @@ static QString compositeOperatorToString(QPainter::CompositionMode op)
     return QString();
 }
 
+
+ #include <QScriptEngine>
+
+//static QtScript functions
+static QScriptValue ctx2d_sync(QScriptContext *c, QScriptEngine* e)
+{
+  QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+  ctx2d->sync();
+  return e->nullValue();
+}
+
+
+// back-reference to the canvas, getter
+static QScriptValue ctx2d_canvas(QScriptContext *c, QScriptEngine* e)
+{
+  QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+  return e->newQObject(ctx2d->canvas());
+}
+
+// state
+static QScriptValue ctx2d_restore(QScriptContext *c, QScriptEngine *e)
+{
+  QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+  ctx2d->restore();
+  return e->nullValue();
+}
+
+static QScriptValue ctx2d_save(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->save();
+    return e->nullValue();
+}
+
+// transformations
+static QScriptValue ctx2d_rotate(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {
+        ctx2d->rotate(c->argument(0).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_scale(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 2) {
+        ctx2d->scale(c->argument(0).toNumber(), c->argument(1).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_setTransform(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 6) {
+        ctx2d->setTransform(c->argument(0).toNumber()
+                          , c->argument(1).toNumber()
+                          , c->argument(2).toNumber()
+                          , c->argument(3).toNumber()
+                          , c->argument(4).toNumber()
+                          , c->argument(5).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_transform(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 6) {
+        ctx2d->transform(c->argument(0).toNumber()
+                       , c->argument(1).toNumber()
+                       , c->argument(2).toNumber()
+                       , c->argument(3).toNumber()
+                       , c->argument(4).toNumber()
+                       , c->argument(5).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_translate(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 2) {
+        ctx2d->translate(c->argument(0).toNumber()
+                       , c->argument(1).toNumber());
+    }
+    return e->nullValue();
+}
+
+// compositing
+// float getter/setter default 1.0
+static QScriptValue ctx2d_globalAlpha(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setGlobalAlpha(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->globalAlpha());
+}
+
+// string getter/setter default "source-over"
+static QScriptValue ctx2d_globalCompositeOperation(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (ctx2d) {
+        if (c->argumentCount() == 1) {//setter
+            ctx2d->setGlobalCompositeOperation(c->argument(0).toString());
+        }
+        return e->toScriptValue(ctx2d->globalCompositeOperation());
+    }
+    return e->nullValue();
+}
+
+// colors and styles
+// getter/setter
+static QScriptValue ctx2d_fillStyle(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setFillStyle(c->argument(0).toVariant());
+    }
+    return e->toScriptValue(ctx2d->fillStyle());
+}
+
+// colors and styles
+// getter/setter
+static QScriptValue ctx2d_fillColor(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setFillColor(c->argument(0).toVariant().value<QColor>());
+    }
+    return e->toScriptValue(ctx2d->fillColor());
+}
+
+
+//getter/setter
+static QScriptValue ctx2d_strokeStyle(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setStrokeStyle(c->argument(0).toVariant());
+    }
+    return e->toScriptValue(ctx2d->strokeStyle());
+}
+
+// colors and styles
+// getter/setter
+static QScriptValue ctx2d_strokeColor(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setStrokeColor(c->argument(0).toVariant().value<QColor>());
+    }
+    return e->toScriptValue(ctx2d->strokeColor());
+}
+
+static QScriptValue ctx2d_createLinearGradient(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        QObject* gradient = ctx2d->createLinearGradient( c->argument(0).toNumber()
+                                                        ,c->argument(1).toNumber()
+                                                        ,c->argument(2).toNumber()
+                                                        ,c->argument(3).toNumber());
+        return e->toScriptValue(gradient);
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_createRadialGradient(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 6) {
+        QObject* gradient = ctx2d->createRadialGradient( c->argument(0).toNumber()
+                                                        ,c->argument(1).toNumber()
+                                                        ,c->argument(2).toNumber()
+                                                        ,c->argument(3).toNumber()
+                                                        ,c->argument(4).toNumber()
+                                                        ,c->argument(5).toNumber());
+        return e->toScriptValue(gradient);
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_createPattern(QScriptContext *c, QScriptEngine *e)
+{
+    //TODO
+    return e->nullValue();
+}
+
+// line styles
+// string getter/setter
+static QScriptValue ctx2d_lineCap(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setLineCap(c->argument(0).toString());
+    }
+    return e->toScriptValue(ctx2d->lineCap());
+}
+
+// string getter/setter
+static QScriptValue ctx2d_lineJoin(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setLineJoin(c->argument(0).toString());
+    }
+    return e->toScriptValue(ctx2d->lineJoin());
+}
+// float getter/setter
+static QScriptValue ctx2d_lineWidth(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setLineWidth(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->lineWidth());
+}
+// float getter/setter
+static QScriptValue ctx2d_miterLimit(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setMiterLimit(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->miterLimit());
+}
+
+// shadows
+// float getter/setter
+static QScriptValue ctx2d_shadowBlur(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setShadowBlur(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->shadowBlur());
+}
+static QScriptValue ctx2d_shadowColor(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setShadowColor(c->argument(0).toString());
+    }
+    return e->toScriptValue(ctx2d->shadowColor());
+}
+static QScriptValue ctx2d_shadowOffsetX(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setShadowOffsetX(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->shadowOffsetX());
+}
+
+static QScriptValue ctx2d_shadowOffsetY(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 1) {//setter
+        ctx2d->setShadowOffsetY(c->argument(0).toNumber());
+    }
+    return e->toScriptValue(ctx2d->shadowOffsetY());
+}
+
+//rects
+static QScriptValue ctx2d_clearRect(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        ctx2d->clearRect(c->argument(0).toNumber()
+                        ,c->argument(1).toNumber()
+                        ,c->argument(2).toNumber()
+                        ,c->argument(3).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_fillRect(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        ctx2d->fillRect(c->argument(0).toNumber()
+                       ,c->argument(1).toNumber()
+                       ,c->argument(2).toNumber()
+                       ,c->argument(3).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_strokeRect(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        ctx2d->strokeRect(c->argument(0).toNumber()
+                         ,c->argument(1).toNumber()
+                         ,c->argument(2).toNumber()
+                         ,c->argument(3).toNumber());
+    }
+    return e->nullValue();
+}
+
+// Complex shapes (paths) API
+static QScriptValue ctx2d_arc(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 6) {
+        ctx2d->arc(c->argument(0).toNumber()
+                  ,c->argument(1).toNumber()
+                  ,c->argument(2).toNumber()
+                  ,c->argument(3).toNumber()
+                  ,c->argument(4).toNumber()
+                  ,c->argument(5).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_arcTo(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 5) {
+        ctx2d->arcTo(c->argument(0).toNumber()
+                    ,c->argument(1).toNumber()
+                    ,c->argument(2).toNumber()
+                    ,c->argument(3).toNumber()
+                    ,c->argument(4).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_beginPath(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->beginPath();
+    return e->nullValue();
+}
+static QScriptValue ctx2d_bezierCurveTo(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 5) {
+        ctx2d->bezierCurveTo(c->argument(0).toNumber()
+                            ,c->argument(1).toNumber()
+                            ,c->argument(2).toNumber()
+                            ,c->argument(3).toNumber()
+                            ,c->argument(4).toNumber()
+                            ,c->argument(5).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_clip(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->clip();
+    return e->nullValue();
+}
+static QScriptValue ctx2d_closePath(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->closePath();
+    return e->nullValue();
+}
+static QScriptValue ctx2d_fill(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->fill();
+    return e->nullValue();
+}
+static QScriptValue ctx2d_lineTo(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 2) {
+        ctx2d->lineTo(c->argument(0).toNumber()
+                     ,c->argument(1).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_moveTo(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 2) {
+        ctx2d->moveTo(c->argument(0).toNumber()
+                     ,c->argument(1).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_quadraticCurveTo(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        ctx2d->quadraticCurveTo(c->argument(0).toNumber()
+                               ,c->argument(1).toNumber()
+                               ,c->argument(2).toNumber()
+                               ,c->argument(3).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_rect(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 4) {
+        ctx2d->rect(c->argument(0).toNumber()
+                   ,c->argument(1).toNumber()
+                   ,c->argument(2).toNumber()
+                   ,c->argument(3).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_stroke(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    ctx2d->stroke();
+    return e->nullValue();
+}
+static QScriptValue ctx2d_isPointInPath(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    bool pointInPath = false;
+    if (c->argumentCount() == 2) {
+        pointInPath = ctx2d->isPointInPath(c->argument(0).toNumber()
+                                          ,c->argument(1).toNumber());
+    }
+    return e->toScriptValue(pointInPath);
+}
+
+// text
+static QScriptValue ctx2d_font(QScriptContext *c, QScriptEngine *e)
+{
+}
+static QScriptValue ctx2d_textAlign(QScriptContext *c, QScriptEngine *e)
+{
+}
+static QScriptValue ctx2d_textBaseline(QScriptContext *c, QScriptEngine *e)
+{
+}
+static QScriptValue ctx2d_fillText(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 3) {
+        ctx2d->fillText(c->argument(0).toString()
+                       ,c->argument(1).toNumber()
+                       ,c->argument(2).toNumber());
+    }
+    return e->nullValue();
+}
+static QScriptValue ctx2d_strokeText(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 3) {
+        ctx2d->strokeText(c->argument(0).toString()
+                         ,c->argument(1).toNumber()
+                         ,c->argument(2).toNumber());
+    }
+    return e->nullValue();
+}
+
+// drawing images
+static QScriptValue ctx2d_drawImage(QScriptContext *c, QScriptEngine *e)
+{
+    QSGContext2D* ctx2d = qscriptvalue_cast<QSGContext2D*>(c->thisObject().data());
+    if (c->argumentCount() == 3) {
+        ctx2d->drawImage(c->argument(0).toString()
+                        ,c->argument(1).toNumber()
+                        ,c->argument(2).toNumber());
+    } else if (c->argumentCount() == 5) {
+        ctx2d->drawImage(c->argument(0).toString()
+                        ,c->argument(1).toNumber()
+                        ,c->argument(2).toNumber()
+                        ,c->argument(3).toNumber()
+                        ,c->argument(4).toNumber());
+    } else if (c->argumentCount() == 9) {
+        ctx2d->drawImage(c->argument(0).toString()
+                        ,c->argument(1).toNumber()
+                        ,c->argument(2).toNumber()
+                        ,c->argument(3).toNumber()
+                        ,c->argument(4).toNumber()
+                        ,c->argument(5).toNumber()
+                        ,c->argument(6).toNumber()
+                        ,c->argument(7).toNumber()
+                        ,c->argument(8).toNumber());
+    }
+    return e->nullValue();
+}
+
+// pixel manipulation
+static QScriptValue ctx2d_createImageData(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+static QScriptValue ctx2d_getImageData(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+static QScriptValue ctx2d_putImageData(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+
+//Image Data Interface
+static QScriptValue ctx2d_imageData_data(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+static QScriptValue ctx2d_imageData_height(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+static QScriptValue ctx2d_imageData_width(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+
+//CanvasPixelArray interface
+static QScriptValue ctx2d_pixelArray_length(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+//getter/setter by index how to?
+static QScriptValue ctx2d_pixelArray(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+}
+
+//CanvasGradient interface
+static QScriptValue ctx2d_gradient_addColorStop(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+
+}
+
+//TextMetrics
+static QScriptValue ctx2d_textMetrics_width(QScriptContext *c, QScriptEngine *e)
+{
+    //#TODO
+
+}
+
+
 bool QSGContext2DPrivate::hasShadow() const
 {
     return state.shadowColor.isValid()
@@ -1623,6 +2153,11 @@ QSGContext2D::QSGContext2D(QSGContext2D *orig, QSGContext2DWorkerAgent* agentDat
     d->canvas = qobject_cast<QSGCanvasItem*>(orig);
 }
 
+QSGCanvasItem*  QSGContext2D::canvas() const
+{
+    Q_D(const QSGContext2D);
+    return d->canvas;
+}
 QSGContext2D::~QSGContext2D()
 {
     Q_D(QSGContext2D);
@@ -1649,24 +2184,60 @@ void QSGContext2D::setScriptEngine(QScriptEngine *eng)
     Q_D(QSGContext2D);
     if (d->scriptEngine != eng) {
         d->scriptEngine = eng;
-//        QScriptValue agent = d->scriptEngine->globalObject().property(QLatin1String("Context2DAgent"));
-//        if (!agent.isValid()) {
-//            d->scriptEngine->evaluate(QLatin1String(
-//                "(function CanvasImageData(w, h, d) {"
-//                "     this.widht = w;"
-//                "     this.height = h;"
-//                "     this.data = d;"
-//                "  })"));
-//            d->scriptEngine->evaluate(agentScript());
-//            agent = d->scriptEngine->globalObject().property(QLatin1String("Context2DAgent"));
-//            if (!agent.isValid()) {
-//                qWarning() << "QSGContext2D:error when evaluating context2d script value!";
-//                d->scriptValue = QScriptValue();
-//                return;
-//            }
-//        }
-//        QScriptValue o = d->scriptEngine->newQObject(this);
-//        d->scriptValue = agent.construct(QScriptValueList() << o);
+        d->scriptValue = eng->newObject();
+        d->scriptValue.setData(eng->toScriptValue(this));
+        d->scriptValue.setProperty(QLatin1String("sync"), eng->newFunction(ctx2d_sync));
+        d->scriptValue.setProperty(QLatin1String("canvas"), eng->newFunction(ctx2d_canvas),QScriptValue::PropertyGetter);
+        d->scriptValue.setProperty(QLatin1String("restore"), eng->newFunction(ctx2d_restore));
+        d->scriptValue.setProperty(QLatin1String("save"), eng->newFunction(ctx2d_save));
+        d->scriptValue.setProperty(QLatin1String("rotate"), eng->newFunction(ctx2d_rotate, 1));
+        d->scriptValue.setProperty(QLatin1String("scale"), eng->newFunction(ctx2d_scale, 2));
+        d->scriptValue.setProperty(QLatin1String("setTransform"), eng->newFunction(ctx2d_setTransform, 6));
+        d->scriptValue.setProperty(QLatin1String("transform"), eng->newFunction(ctx2d_transform, 6));
+        d->scriptValue.setProperty(QLatin1String("translate"), eng->newFunction(ctx2d_translate, 2));
+        d->scriptValue.setProperty(QLatin1String("globalAlpha"), eng->newFunction(ctx2d_globalAlpha), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("globalCompositeOperation"), eng->newFunction(ctx2d_globalCompositeOperation), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("fillStyle"), eng->newFunction(ctx2d_fillStyle), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("strokeStyle"), eng->newFunction(ctx2d_strokeStyle),  QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("fillColor"), eng->newFunction(ctx2d_fillColor), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("strokeColor"), eng->newFunction(ctx2d_strokeColor),  QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("createLinearGradient"), eng->newFunction(ctx2d_createLinearGradient, 4));
+        d->scriptValue.setProperty(QLatin1String("createRadialGradient"), eng->newFunction(ctx2d_createRadialGradient, 6));
+        d->scriptValue.setProperty(QLatin1String("createPattern"), eng->newFunction(ctx2d_createPattern, 2));
+        d->scriptValue.setProperty(QLatin1String("lineCap"), eng->newFunction(ctx2d_lineCap), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("lineJoin"), eng->newFunction(ctx2d_lineJoin), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("lineWidth"), eng->newFunction(ctx2d_lineWidth), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("miterLimit"), eng->newFunction(ctx2d_miterLimit), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("shadowBlur"), eng->newFunction(ctx2d_shadowBlur), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("shadowColor"), eng->newFunction(ctx2d_shadowColor), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("shadowOffsetX"), eng->newFunction(ctx2d_shadowOffsetX), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("shadowOffsetY"), eng->newFunction(ctx2d_shadowOffsetY), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("clearRect"), eng->newFunction(ctx2d_clearRect, 4));
+        d->scriptValue.setProperty(QLatin1String("fillRect"), eng->newFunction(ctx2d_fillRect, 4));
+        d->scriptValue.setProperty(QLatin1String("strokeRect"), eng->newFunction(ctx2d_strokeRect, 4));
+        d->scriptValue.setProperty(QLatin1String("arc"), eng->newFunction(ctx2d_arc, 6));
+        d->scriptValue.setProperty(QLatin1String("arcTo"), eng->newFunction(ctx2d_arcTo, 5));
+        d->scriptValue.setProperty(QLatin1String("beginPath"), eng->newFunction(ctx2d_beginPath));
+        d->scriptValue.setProperty(QLatin1String("bezierCurveTo"), eng->newFunction(ctx2d_bezierCurveTo, 6));
+        d->scriptValue.setProperty(QLatin1String("clip"), eng->newFunction(ctx2d_clip));
+        d->scriptValue.setProperty(QLatin1String("closePath"), eng->newFunction(ctx2d_closePath));
+        d->scriptValue.setProperty(QLatin1String("fill"), eng->newFunction(ctx2d_fill));
+        d->scriptValue.setProperty(QLatin1String("lineTo"), eng->newFunction(ctx2d_lineTo, 2));
+        d->scriptValue.setProperty(QLatin1String("moveTo"), eng->newFunction(ctx2d_moveTo, 2));
+        d->scriptValue.setProperty(QLatin1String("quadraticCurveTo"), eng->newFunction(ctx2d_quadraticCurveTo, 4));
+        d->scriptValue.setProperty(QLatin1String("rect"), eng->newFunction(ctx2d_rect, 4));
+        d->scriptValue.setProperty(QLatin1String("stroke"), eng->newFunction(ctx2d_stroke));
+        d->scriptValue.setProperty(QLatin1String("isPointInPath"), eng->newFunction(ctx2d_isPointInPath, 2));
+        d->scriptValue.setProperty(QLatin1String("font"), eng->newFunction(ctx2d_font), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("textAlign"), eng->newFunction(ctx2d_textAlign), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("textBaseline"), eng->newFunction(ctx2d_textBaseline), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+        d->scriptValue.setProperty(QLatin1String("fillText"), eng->newFunction(ctx2d_fillText, 4));
+        //d->scriptValue.setProperty(QLatin1String("measureText"), eng->newFunction(ctx2d_measureText, 1));
+        d->scriptValue.setProperty(QLatin1String("strokeText"), eng->newFunction(ctx2d_strokeText, 4));
+        d->scriptValue.setProperty(QLatin1String("drawImage"), eng->newFunction(ctx2d_drawImage, 9));
+        d->scriptValue.setProperty(QLatin1String("createImageData"), eng->newFunction(ctx2d_createImageData, 2));
+        d->scriptValue.setProperty(QLatin1String("getImageData"), eng->newFunction(ctx2d_getImageData, 4));
+        d->scriptValue.setProperty(QLatin1String("putImageData"), eng->newFunction(ctx2d_putImageData, 7));
     }
 }
 
@@ -2380,6 +2951,7 @@ void QSGContext2D::paint(QPainter* p)
                 qreal y = d->reals[real_idx++];
                 qreal w = d->reals[real_idx++];
                 qreal h = d->reals[real_idx++];
+//                qDebug() << "fillRect(" << x << y << w << h << ")";
                 if (d->hasShadow())
                     d->fillRectShadow(p, QRectF(x, y, w, h));
                 else
index 1a90010..335f71b 100644 (file)
@@ -85,38 +85,9 @@ public:
 Q_DECLARE_METATYPE(QSGCanvasGradient*)
 
 
-//class QSGCanvasImage: public QObject
-//{
-//    Q_OBJECT
-//    Q_PROPERTY(QString src READ src WRITE setSrc NOTIFY sourceChanged)
-//public:
-//    QSGCanvasImage() {}
-//    QSGCanvasImage(const QString &url) : m_image(url), m_src(url) {
-//    }
-//    QSGCanvasImage(const QImage &img) {m_image = img;}
-
-//public slots:
-//    QImage &value() { return m_image; }
-//    const QImage &value() const{ return m_image; }
-//    QString src() { return m_src; }
-//    void setSrc(const QString &src) { m_src = src; m_image.load(src); emit sourceChanged();}
-//signals:
-//    void sourceChanged();
-
-//private:
-//    QSGImage* img;
-//    QString   src;
-//};
-
-//Q_DECLARE_METATYPE(QSGCanvasImage*)
-
-
-/*
-
-  */
-
 class QSGContext2DWorkerAgent;
 class QSGContext2DPrivate;
+class QSGCanvasItem;
 class QSGContext2D : public QObject
 {
     Q_OBJECT
@@ -215,6 +186,9 @@ public:
     QSGContext2D(QObject *parent = 0);
     QSGContext2D(QSGContext2D *ctx2d, QSGContext2DWorkerAgent* agentData);
     ~QSGContext2D();
+
+    QSGCanvasItem*  canvas() const;
+
     void setSize(int width, int height);
     void setSize(const QSize &size);
     QSize size() const;