#include <qqmlengine.h>
#include <private/qv8domerrors_p.h>
#include <QtCore/qnumeric.h>
+#include <private/qquickwindow_p.h>
+#include <private/qquickwindowmanager_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
#ifdef Q_OS_QNX
#include <ctype.h>
/*!
\qmlclass Context2D QQuickContext2D
\inqmlmodule QtQuick 2
+ \ingroup qtquick-canvas
\since QtQuick 2.0
\brief Provides 2D context for shapes on a Canvas item
patternTexture = pixelData->image;
}
} else {
- patternTexture = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+ patternTexture = r->context->createPixmap(QUrl(engine->toString(args[0]->ToString())))->image();
}
if (!patternTexture.isNull()) {
static v8::Handle<v8::Value> ctx2d_drawFocusRing(const v8::Arguments &args)
{
+ Q_UNUSED(args);
+
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
}
static v8::Handle<v8::Value> ctx2d_setCaretSelectionRect(const v8::Arguments &args)
{
+ Q_UNUSED(args);
+
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
}
static v8::Handle<v8::Value> ctx2d_caretBlinkRate(const v8::Arguments &args)
{
+ Q_UNUSED(args);
+
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
}
// text
\qmlclass TextMetrics
\inqmlmodule QtQuick 2
\since QtQuick 2.0
+ \ingroup qtquick-canvas
\brief Provides a Context2D TextMetrics interface
The TextMetrics object can be created by QtQuick2::Context2D::measureText method.
/*!
\qmlmethod QtQuick2::Context2D::drawImage(variant image, real sx, real sy, real sw, sh, real dx, real dy, real dw, dh)
This is an overloaded function.
- Draws the given item as \a image from source point (\a sx, \a sy) and source width \sw, source height \sh
+ Draws the given item as \a image from source point (\a sx, \a sy) and source width \a sw, source height \a sh
onto the canvas at point (\a dx, \a dy) and with width \a dw, height \a dh.
if (!r->context->state.invertibleCTM)
return args.This();
- QImage image;
+ QQmlRefPointer<QQuickCanvasPixmap> pixmap;
+
if (args[0]->IsString()) {
QUrl url(engine->toString(args[0]->ToString()));
if (!url.isValid())
V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
- image = r->context->createImage(url);
+ pixmap = r->context->createPixmap(url);
} else if (args[0]->IsObject()) {
QQuickImage *imageItem = qobject_cast<QQuickImage*>(engine->toQObject(args[0]->ToObject()));
QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(engine->toQObject(args[0]->ToObject()));
QV8Context2DPixelArrayResource *pix = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->GetInternalField(0)->ToObject());
- if (pix) {
- image = pix->image;
+ if (pix && !pix->image.isNull()) {
+ pixmap.take(new QQuickCanvasPixmap(pix->image, r->context->canvas()->window()));
} else if (imageItem) {
- image = imageItem->image();
+ pixmap.take(r->context->createPixmap(imageItem->source()));
} else if (canvas) {
- image = canvas->toImage();
+ QImage img = canvas->toImage();
+ if (!img.isNull())
+ pixmap.take(new QQuickCanvasPixmap(img, canvas->window()));
} else {
V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
} else {
V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
}
+
+ if (pixmap.isNull() || !pixmap->isValid())
+ return args.This();
+
if (args.Length() == 3) {
dx = args[1]->NumberValue();
dy = args[2]->NumberValue();
sx = 0;
sy = 0;
- sw = image.width();
- sh = image.height();
+ sw = pixmap->width();
+ sh = pixmap->height();
dw = sw;
dh = sh;
} else if (args.Length() == 5) {
sx = 0;
sy = 0;
- sw = image.width();
- sh = image.height();
+ sw = pixmap->width();
+ sh = pixmap->height();
dx = args[1]->NumberValue();
dy = args[2]->NumberValue();
dw = args[3]->NumberValue();
|| !qIsFinite(dh))
return args.This();
- if (!image.isNull()) {
- if (sx < 0 || sy < 0 || sw == 0 || sh == 0
- || sx + sw > image.width() || sy + sh > image.height()
- || sx + sw < 0 || sy + sh < 0) {
+ if (sx < 0
+ || sy < 0
+ || sw == 0
+ || sh == 0
+ || sx + sw > pixmap->width()
+ || sy + sh > pixmap->height()
+ || sx + sw < 0 || sy + sh < 0) {
V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
- }
-
- r->context->buffer()->drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
}
+ r->context->buffer()->drawPixmap(pixmap, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh));
+
return args.This();
}
/*!
\qmlclass CanvasImageData
\inqmlmodule QtQuick 2
+ \ingroup qtquick-canvas
\brief Contains image pixel data in RGBA order
The \a QtQuick2::CanvasImageData object holds the image pixel data.
/*!
\qmlclass CanvasPixelArray
\inqmlmodule QtQuick 2
+ \ingroup qtquick-canvas
\brief Provides ordered and indexed access to the components of each pixel in image data
The CanvasPixelArray object provides ordered, indexed access to the color components of each pixel of the image data.
return qt_create_image_data(w, h, engine, QImage());
}
} else if (args[0]->IsString()) {
- QImage image = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+ QImage image = r->context->createPixmap(QUrl(engine->toString(args[0]->ToString())))->image();
return qt_create_image_data(image.width(), image.height(), engine, image);
}
} else if (args.Length() == 2) {
}
QImage image = pixelArray->image.copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
- r->context->buffer()->drawImage(image, dirtyX, dirtyY, dirtyWidth, dirtyHeight, dx, dy, dirtyWidth, dirtyHeight);
+ r->context->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight));
}
return args.This();
}
\qmlclass CanvasGradient
\inqmlmodule QtQuick 2
\since QtQuick 2.0
+ \ingroup qtquick-canvas
\brief Provides an opaque CanvasGradient interface
*/
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
return;
- buffer()->fillRect(x, y, w, h);
+ buffer()->fillRect(QRectF(x, y, w, h));
}
void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
return;
- buffer()->strokeRect(x, y, w, h);
+ buffer()->strokeRect(QRectF(x, y, w, h));
}
void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
return;
- buffer()->clearRect(x, y, w, h);
+ buffer()->clearRect(QRectF(x, y, w, h));
}
void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill)
}
-QImage QQuickContext2D::createImage(const QUrl& url)
+QQmlRefPointer<QQuickCanvasPixmap> QQuickContext2D::createPixmap(const QUrl& url)
{
- return m_canvas->loadedImage(url);
+ return m_canvas->loadedPixmap(url);
}
QPainterPath QQuickContext2D::createTextGlyphs(qreal x, qreal y, const QString& text)
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
, m_v8engine(0)
+ , m_windowManager(0)
+ , m_surface(0)
+ , m_glContext(0)
{
}
m_canvas = canvasItem;
m_renderTarget = canvasItem->renderTarget();
- // For the FBO target we only (currently) support Cooperative
- if (m_renderTarget == QQuickCanvasItem::FramebufferObject) {
- canvasItem->setRenderStrategy(QQuickCanvasItem::Cooperative);
- }
-
+ QQuickWindow *window = canvasItem->window();
+ m_windowManager = QQuickWindowPrivate::get(window)->windowManager;
m_renderStrategy = canvasItem->renderStrategy();
switch (m_renderTarget) {
m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded);
break;
case QQuickCanvasItem::FramebufferObject:
+ {
m_texture = new QQuickContext2DFBOTexture;
+ // No BufferQueueingOpenGL, falls back to Cooperative mode
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL))
+ m_renderStrategy = QQuickCanvasItem::Cooperative;
+ }
break;
}
m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
m_texture->setSmooth(canvasItem->smooth());
+ QThread *renderThread = QThread::currentThread();
+ QThread *sceneGraphThread = window->openglContext() ? window->openglContext()->thread() : 0;
+
+ if (m_renderStrategy == QQuickCanvasItem::Threaded)
+ renderThread = QQuickContext2DRenderThread::instance(qmlEngine(canvasItem));
+ else if (m_renderStrategy == QQuickCanvasItem::Cooperative)
+ renderThread = sceneGraphThread;
+
+ if (m_renderTarget == QQuickCanvasItem::FramebufferObject && renderThread != sceneGraphThread) {
+ QOpenGLContext *cc = QQuickWindowPrivate::get(window)->context->glContext();
+ m_surface = window;
+ m_glContext = new QOpenGLContext;
+ m_glContext->setFormat(cc->format());
+ m_glContext->setShareContext(cc);
+ if (renderThread != QThread::currentThread())
+ m_glContext->moveToThread(renderThread);
+ }
+
connect(m_texture, SIGNAL(textureChanged()), SIGNAL(textureChanged()));
reset();
m_stateStack.clear();
m_stateStack.push(newState);
popState();
- m_buffer->clearRect(0, 0, m_canvas->width(), m_canvas->height());
+ m_buffer->clearRect(QRectF(0, 0, m_canvas->width(), m_canvas->height()));
}
void QQuickContext2D::setV8Engine(QV8Engine *engine)