From 6dbd4286eb19e9ac45665046a43342bcdc8b127e Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Mon, 30 May 2011 16:14:42 +1000 Subject: [PATCH] rewrite context2d with direct QtScript binding for better performance. Change-Id: I740ad4cbb7446a838954a010b0e5f0b847ec4f53 --- src/declarative/items/qsgcanvasitem.cpp | 305 +--------------- src/declarative/items/qsgcanvasitem_p.h | 3 +- src/declarative/items/qsgcontext2d.cpp | 608 ++++++++++++++++++++++++++++++- src/declarative/items/qsgcontext2d_p.h | 34 +-- 4 files changed, 614 insertions(+), 336 deletions(-) diff --git a/src/declarative/items/qsgcanvasitem.cpp b/src/declarative/items/qsgcanvasitem.cpp index ba3c4ba..a6403c0 100644 --- a/src/declarative/items/qsgcanvasitem.cpp +++ b/src/declarative/items/qsgcanvasitem.cpp @@ -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 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(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(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 diff --git a/src/declarative/items/qsgcanvasitem_p.h b/src/declarative/items/qsgcanvasitem_p.h index a358c35..b501901 100644 --- a/src/declarative/items/qsgcanvasitem_p.h +++ b/src/declarative/items/qsgcanvasitem_p.h @@ -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 diff --git a/src/declarative/items/qsgcontext2d.cpp b/src/declarative/items/qsgcontext2d.cpp index 6f7121a..2e60de1 100644 --- a/src/declarative/items/qsgcontext2d.cpp +++ b/src/declarative/items/qsgcontext2d.cpp @@ -366,6 +366,536 @@ static QString compositeOperatorToString(QPainter::CompositionMode op) return QString(); } + + #include + +//static QtScript functions +static QScriptValue ctx2d_sync(QScriptContext *c, QScriptEngine* e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(c->thisObject().data()); + return e->newQObject(ctx2d->canvas()); +} + +// state +static QScriptValue ctx2d_restore(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(c->thisObject().data()); + ctx2d->restore(); + return e->nullValue(); +} + +static QScriptValue ctx2d_save(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(c->thisObject().data()); + ctx2d->save(); + return e->nullValue(); +} + +// transformations +static QScriptValue ctx2d_rotate(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(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(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(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(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(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(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(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(c->thisObject().data()); + if (c->argumentCount() == 1) {//setter + ctx2d->setFillColor(c->argument(0).toVariant().value()); + } + return e->toScriptValue(ctx2d->fillColor()); +} + + +//getter/setter +static QScriptValue ctx2d_strokeStyle(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(c->thisObject().data()); + if (c->argumentCount() == 1) {//setter + ctx2d->setStrokeColor(c->argument(0).toVariant().value()); + } + return e->toScriptValue(ctx2d->strokeColor()); +} + +static QScriptValue ctx2d_createLinearGradient(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(c->thisObject().data()); + ctx2d->beginPath(); + return e->nullValue(); +} +static QScriptValue ctx2d_bezierCurveTo(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(c->thisObject().data()); + ctx2d->clip(); + return e->nullValue(); +} +static QScriptValue ctx2d_closePath(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(c->thisObject().data()); + ctx2d->closePath(); + return e->nullValue(); +} +static QScriptValue ctx2d_fill(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(c->thisObject().data()); + ctx2d->fill(); + return e->nullValue(); +} +static QScriptValue ctx2d_lineTo(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(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(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(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(c->thisObject().data()); + ctx2d->stroke(); + return e->nullValue(); +} +static QScriptValue ctx2d_isPointInPath(QScriptContext *c, QScriptEngine *e) +{ + QSGContext2D* ctx2d = qscriptvalue_cast(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(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(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(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(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 diff --git a/src/declarative/items/qsgcontext2d_p.h b/src/declarative/items/qsgcontext2d_p.h index 1a90010..335f71b 100644 --- a/src/declarative/items/qsgcontext2d_p.h +++ b/src/declarative/items/qsgcontext2d_p.h @@ -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; -- 1.7.2.5