diff options
Diffstat (limited to 'src/declarative/items/context2d/qquickcanvasitem.cpp')
-rw-r--r-- | src/declarative/items/context2d/qquickcanvasitem.cpp | 714 |
1 files changed, 0 insertions, 714 deletions
diff --git a/src/declarative/items/context2d/qquickcanvasitem.cpp b/src/declarative/items/context2d/qquickcanvasitem.cpp deleted file mode 100644 index 81b7a49722..0000000000 --- a/src/declarative/items/context2d/qquickcanvasitem.cpp +++ /dev/null @@ -1,714 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qsgadaptationlayer_p.h> -#include "qquickcanvasitem_p.h" -#include <private/qquickitem_p.h> -#include "qquickcontext2d_p.h" -#include "qquickcontext2dnode_p.h" -#include "qquickcontext2dtexture_p.h" -#include <private/qdeclarativepixmapcache_p.h> - -#include <qdeclarativeinfo.h> -#include <private/qdeclarativeengine_p.h> -#include <QtCore/QBuffer> - -QT_BEGIN_NAMESPACE - -class QQuickCanvasItemPrivate : public QQuickItemPrivate -{ -public: - QQuickCanvasItemPrivate(); - ~QQuickCanvasItemPrivate(); - QQuickContext2D* context; - QQuickContext2DTexture* texture; - QSizeF canvasSize; - QSize tileSize; - QRectF canvasWindow; - QRectF dirtyRect; - uint renderInThread : 1; - uint hasCanvasSize :1; - uint hasTileSize :1; - uint hasCanvasWindow :1; - uint componentCompleted :1; - QQuickCanvasItem::RenderTarget renderTarget; - QHash<QUrl, QDeclarativePixmap*> images; - QUrl baseUrl; -}; - -QQuickCanvasItemPrivate::QQuickCanvasItemPrivate() - : QQuickItemPrivate() - , context(0) - , texture(0) - , canvasSize(1, 1) - , tileSize(1, 1) - , renderInThread(false) - , hasCanvasSize(false) - , hasTileSize(false) - , hasCanvasWindow(false) - , componentCompleted(false) - , renderTarget(QQuickCanvasItem::FramebufferObject) -{ -} - -QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() -{ - qDeleteAll(images); -} - -/*! - \qmlclass Canvas QQuickCanvasItem - \inqmlmodule QtQuick 2 - \since QtQuick 2.0 - \brief The Canvas item provides a 2D canvas element which enables drawing via Javascript. - \inherits Item - \ingroup qml-basic-visual-elements - - The Canvas item allows drawing of straight and curved lines, simple and - complex shapes, graphs, and referenced graphic images. It can also add text, colors, - shadows, gradients, and patterns, and do low level pixel operations. The Canvas - output may be saved as an image file or serialized to a url. - - To define a drawing area in the Canvas item set the \c width and \c height properties. - For example, the following code creates a Canvas item which has a drawing area with a height of 100 - pixels and width of 200 pixels: - \qml - import QtQuick 2.0 - Canvas { - id:mycanvas - width:100 - height:200 - } - \endqml - - Currently the Canvas item only supports the two-dimensional rendering context. - - \section1 Threaded Rendering and Render Target - - The Canvas item supports two render targets: \c Canvas.Image and \c Canvas.FramebufferObject. - - The \c Canvas.Image render target is a \a QImage object. This render target supports background - thread rendering, allowing complex or long running painting to be executed without blocking the UI. - - The Canvas.FramebufferObject render target utilizes OpenGL hardware accelaration rather than rendering into - system memory, which in many cases results in faster rendering. - - The default render target is Canvas.Image and the default renderInThread property is - false. - - \section1 Tiled Canvas - The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize - and \l canvasWindow properties. - - Tiling allows efficient display of a very large virtual via a smaller canvas - window. The actual memory consumption is in relatation to the canvas window size. The painting - code can draw within the virtual canvas without handling coordinate system transformations. - - The tiles overlapping with the canvas window may be cached eliminating the need to redraw, - which can lead to significantly improved performance in some situations. - - \section1 Pixel Operations - All HTML5 2D context pixel operations are supported. In order to ensure improved - pixel reading/writing performance the \a Canvas.Image render target should be chosen. The - \a Canvas.FramebufferObject render target requires the pixel data to be exchanged between - the system memory and the graphic card, which is significantly more expensive. Rendering - may also be synchronized with the V-sync signal (to avoid {en.wikipedia.org/wiki/Screen_tearing}{screen tearing}) - which will futher impact pixel operations with \c Canvas.FrambufferObject render target. - - \section1 Tips for Porting Existing HTML5 Canvas applications - - Although the Canvas item is provides a HTML5 like API, HTML5 canvas applications - need to be modified to run in the Canvas item: - \list - \o Replace all DOM API calls with QML property bindings or Canvas item methods. - \o Replace all HTML event handlers with the \a MouseArea item. - \o Change setInterval/setTimeout function calls with the \a Timer item. - \o Place painting code into the \a QtQuick2::Canvas::onPaint handler and trigger - painting by calling the \c markDirty or \c requestPaint methods. - \o To draw images, load them by calling the Canvas's loadImage method and then request to paint - them in the onImageLoaded handler. - \endlist - - \sa QtQuick2::Context2D -*/ - -QQuickCanvasItem::QQuickCanvasItem(QQuickItem *parent) - : QQuickItem(*(new QQuickCanvasItemPrivate), parent) -{ - setFlag(ItemHasContents); -} - -QQuickCanvasItem::~QQuickCanvasItem() -{ - Q_D(QQuickCanvasItem); - delete d->context; -} - -/*! - \qmlproperty size QtQuick2::Canvas::canvasSize - Holds the logical canvas size that the context paints on. - - By default, the canvas size is the same size as the current canvas item size. - By setting the canvasSize, tileSize and canvasWindow, the Canvas - item can act as a large virtual canvas with many seperately rendered tile rectangles - Only those tiles within the current canvas window are painted by - the Canvas render engine. - - \sa QtQuick2::Canvas::tileSize QtQuick2::Canvas::canvasWindow -*/ -QSizeF QQuickCanvasItem::canvasSize() const -{ - Q_D(const QQuickCanvasItem); - return d->canvasSize; -} - -void QQuickCanvasItem::setCanvasSize(const QSizeF & size) -{ - Q_D(QQuickCanvasItem); - if (d->canvasSize != size) { - d->hasCanvasSize = true; - d->canvasSize = size; - emit canvasSizeChanged(); - polish(); - update(); - } -} - -/*! - \qmlproperty size QtQuick2::Canvas::tileSize - Holds the canvas rendering tile size. - - The Canvas item enters tiled mode by setting canvasSize, tileSize and - the canvasWindow. This can improve rendering performance - by rendering and caching tiles instead of rendering the whole canvas every time. - - Memory will be consumed only by those tiles within the current visible region. - - By default the tileSize is the same as the canvasSize. - - \sa QtQuick2::Canvas::canvaasSize QtQuick2::Canvas::canvasWindow -*/ -QSize QQuickCanvasItem::tileSize() const -{ - Q_D(const QQuickCanvasItem); - return d->tileSize; -} - -void QQuickCanvasItem::setTileSize(const QSize & size) -{ - Q_D(QQuickCanvasItem); - if (d->tileSize != size) { - d->hasTileSize = true; - d->tileSize = size; - - emit tileSizeChanged(); - polish(); - update(); - } -} - -/*! - \qmlproperty rect QtQuick2::Canvas::canvasWindow - Holds the current canvas visible window. - - By default the canvasWindow size is the same as the Canvas item - size with the topleft point as (0, 0). - - If the canvasSize is different to the Canvas item size, the Canvas - item can display different visible areas by changing the canvas windowSize - and/or position. - - \sa QtQuick2::Canvas::canvasSize QtQuick2::Canvas::tileSize -*/ -QRectF QQuickCanvasItem::canvasWindow() const -{ - Q_D(const QQuickCanvasItem); - return d->canvasWindow; -} - -void QQuickCanvasItem::setCanvasWindow(const QRectF& rect) -{ - Q_D(QQuickCanvasItem); - if (d->canvasWindow != rect) { - d->canvasWindow = rect; - - d->hasCanvasWindow = true; - emit canvasWindowChanged(); - polish(); - update(); - } -} - - -QQuickContext2D* QQuickCanvasItem::context() const -{ - Q_D(const QQuickCanvasItem); - return d->context; -} -/*! - \qmlproperty bool QtQuick2::Canvas::renderInThread - Holds the current canvas rendering mode. - - Set renderInThread to true to render complex and long - running painting in a dedicated background - thread, avoiding blocking the main UI. - - \note: Not all renderTargets support background rendering. If background rendering - is not supported by the current renderTarget, the renderInThread - property is ignored. - - The default value is false. - \sa QtQuick2::Canvas::renderTarget -*/ -bool QQuickCanvasItem::renderInThread() const -{ - Q_D(const QQuickCanvasItem); - return d->renderInThread; -} -/*! - \qmlproperty bool QtQuick2::Canvas::renderTarget - Holds the current canvas render target. - - \list - \o Canvas.Image - render to an in memory image buffer, the render - target supports background rendering. - \o Canvas.FramebufferObject - render to an OpenGL frame buffer, - this render target will ignore the - renderInThread property. The actual - rendering happens in the main QML rendering - process, which may be in a seperate render thread - or in the main GUI thread depending upon the platform. - \endlist - - The default render target is \c Canvas.Image. - \sa QtQuick2::Canvas::renderInThread -*/ -QQuickCanvasItem::RenderTarget QQuickCanvasItem::renderTarget() const -{ - Q_D(const QQuickCanvasItem); - return d->renderTarget; -} - -void QQuickCanvasItem::setRenderTarget(RenderTarget target) -{ - Q_D(QQuickCanvasItem); - if (d->renderTarget != target) { - d->renderTarget = target; - - if (d->componentCompleted) - createTexture(); - emit renderTargetChanged(); - } -} - -void QQuickCanvasItem::_doPainting(const QRectF& region) -{ - Q_D(QQuickCanvasItem); - emit paint(QDeclarativeV8Handle::fromHandle(d->context->v8value()) - , QQuickContext2DTexture::tiledRect(region, d->tileSize)); - if (d->texture) - d->texture->wake(); -} - -void QQuickCanvasItem::setRenderInThread(bool renderInThread) -{ - Q_D(QQuickCanvasItem); - if (d->renderInThread != renderInThread) { - d->renderInThread = renderInThread; - - if (d->componentCompleted) - createTexture(); - - if (d->renderInThread) - connect(this, SIGNAL(painted()), SLOT(update())); - else - disconnect(this, SIGNAL(painted()), this, SLOT(update())); - emit renderInThreadChanged(); - polish(); - update(); - } -} - -void QQuickCanvasItem::geometryChanged(const QRectF &newGeometry, - const QRectF &oldGeometry) -{ - Q_D(QQuickCanvasItem); - QQuickItem::geometryChanged(newGeometry, oldGeometry); - - const qreal w = newGeometry.width(); - const qreal h = newGeometry.height(); - - if (!d->hasCanvasSize) { - d->canvasSize = QSizeF(w, h); - emit canvasSizeChanged(); - } - - if (!d->hasTileSize) { - d->tileSize = d->canvasSize.toSize(); - emit tileSizeChanged(); - } - - if (!d->hasCanvasWindow) { - d->canvasWindow = newGeometry; - emit canvasWindowChanged(); - } - - polish(); - update(); -} - -void QQuickCanvasItem::componentComplete() -{ - Q_D(QQuickCanvasItem); - QQuickItem::componentComplete(); - - if (!d->context) - createContext(); - createTexture(); - - d->baseUrl = qmlEngine(this)->contextForObject(this)->baseUrl(); - requestPaint(); - updatePolish(); //force update the canvas sizes to texture for the first time - update(); - d->componentCompleted = true; -} - -void QQuickCanvasItem::updatePolish() -{ - Q_D(QQuickCanvasItem); - QQuickItem::updatePolish(); - if (d->texture) { - if (!d->renderInThread && d->dirtyRect.isValid()) - _doPainting(d->dirtyRect); - - d->texture->canvasChanged(d->canvasSize.toSize() - , d->tileSize - , d->canvasWindow.toAlignedRect() - , d->dirtyRect.toAlignedRect() - , d->smooth); - d->dirtyRect = QRectF(); - } -} - -QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) -{ - Q_D(QQuickCanvasItem); - QQuickContext2DNode *node = static_cast<QQuickContext2DNode *>(oldNode); - if (!node) - node = new QQuickContext2DNode(this); - - node->setTexture(d->texture); - node->setSize(d->canvasWindow.size()); - node->update(); - return node; -} - -void QQuickCanvasItem::createTexture() -{ - Q_D(QQuickCanvasItem); - - if (!d->texture - || d->texture->threadRendering() != d->renderInThread - || d->texture->renderTarget() != d->renderTarget) { - if (d->texture) { - d->texture->deleteLater(); - d->texture = 0; - } - - if (d->renderTarget == QQuickCanvasItem::Image) { - d->texture = new QQuickContext2DImageTexture(d->renderInThread); - } else if (d->renderTarget == QQuickCanvasItem::FramebufferObject) { - d->texture = new QQuickContext2DFBOTexture(); - } - - if (d->renderInThread && !d->texture->supportThreadRendering()) { - qWarning("Canvas: render target does not support thread rendering, force to non-thread rendering mode."); - d->renderInThread = false; - emit renderInThreadChanged(); - } - - if (d->renderInThread) - connect(d->texture, SIGNAL(textureChanged()), this, SLOT(update())); - - d->texture->setItem(this); - } -} - -void QQuickCanvasItem::createContext() -{ - Q_D(QQuickCanvasItem); - - delete d->context; - - d->context = new QQuickContext2D(this); - - QV8Engine *e = QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this)); - d->context->setV8Engine(e); -} - -/*! - \qmlmethod object QtQuick2::Canvas::getContext(string contextId) - - Currently, the canvas item only supports the 2D context. If the \a contextId - parameter isn't provided or is "2d", then the QtQuick2::Context2D object is - returned, otherwise returns an invalid value. - */ -QDeclarativeV8Handle QQuickCanvasItem::getContext(const QString &contextId) -{ - Q_D(QQuickCanvasItem); - - if (contextId.toLower() != QLatin1String("2d")) - return QDeclarativeV8Handle::fromHandle(v8::Undefined()); - - if (!d->context) - createContext(); - return QDeclarativeV8Handle::fromHandle(d->context->v8value()); -} - -/*! - \qmlmethod void QtQuick2::Canvas::markDirty(rect region) - - Mark the given \a region as dirty, so that when this region is visible - the canvas renderer will redraw it. This will trigger the "onPaint" signal - handler function. - - \sa QtQuick2::Canvas::paint QtQuick2::Canvas::requestPaint - */ -void QQuickCanvasItem::markDirty(const QRectF& region) -{ - Q_D(QQuickCanvasItem); - d->dirtyRect |= region; - if (d->componentCompleted) - polish(); - update(); -} - - -/*! - \qmlmethod bool QtQuick2::Canvas::save(string filename) - - Save the current canvas content into an image file \a filename. - The saved image format is automatically decided by the \a filename's - suffix. - - Note: calling this method will force painting the whole canvas, not just the - current canvas visible window. - - \sa canvasWindow canvasSize toDataURL - */ -bool QQuickCanvasItem::save(const QString &filename) const -{ - Q_D(const QQuickCanvasItem); - QUrl url = d->baseUrl.resolved(QUrl::fromLocalFile(filename)); - return toImage().save(url.toLocalFile()); -} - -QImage QQuickCanvasItem::loadedImage(const QUrl& url) -{ - Q_D(QQuickCanvasItem); - QUrl fullPathUrl = d->baseUrl.resolved(url); - if (!d->images.contains(fullPathUrl)) { - loadImage(url); - } - QDeclarativePixmap* pix = d->images.value(fullPathUrl); - if (pix->isLoading() || pix->isError()) { - return QImage(); - } - return pix->image(); -} - -/*! - \qmlmethod void QtQuick2::Canvas::loadImage(url image) - Loads the given \c image asynchronously. - - When the image is ready, onImageLoaded will be emitted. - The loaded image can be unloaded by the \a QtQuick2::Canvas::unloadImage method. - - Note: Only loaded images can be painted on the Canvas item. - \sa QtQuick2::Canvas::unloadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded - \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage - */ -void QQuickCanvasItem::loadImage(const QUrl& url) -{ - Q_D(QQuickCanvasItem); - QUrl fullPathUrl = d->baseUrl.resolved(url); - if (!d->images.contains(fullPathUrl)) { - QDeclarativePixmap* pix = new QDeclarativePixmap(); - d->images.insert(fullPathUrl, pix); - - pix->load(qmlEngine(this) - , fullPathUrl - , QDeclarativePixmap::Cache | QDeclarativePixmap::Asynchronous); - pix->connectFinished(this, SIGNAL(imageLoaded())); - } -} -/*! - \qmlmethod void QtQuick2::Canvas::unloadImage(url image) - Unloads the \c image. - - Once an image is unloaded it cannot be painted by the canvas context - unless it is loaded again. - - \sa QtQuick2::Canvas::loadImage QtQuick2::Canvas::imageLoaded QtQuick2::Canvas::isImageLoaded - \sa QtQuick2::Context2D::createImageData QtQuick2::Context2D::drawImage - */ -void QQuickCanvasItem::unloadImage(const QUrl& url) -{ - Q_D(QQuickCanvasItem); - QUrl removeThis = d->baseUrl.resolved(url); - if (d->images.contains(removeThis)) { - delete d->images.value(removeThis); - d->images.remove(removeThis); - } -} - -/*! - \qmlmethod void QtQuick2::Canvas::isImageError(url image) - Returns true if the \a image failed to load. - - \sa QtQuick2::Canvas::loadImage - */ -bool QQuickCanvasItem::isImageError(const QUrl& url) const -{ - Q_D(const QQuickCanvasItem); - QUrl fullPathUrl = d->baseUrl.resolved(url); - return d->images.contains(fullPathUrl) - && d->images.value(fullPathUrl)->isError(); -} - -/*! - \qmlmethod void QtQuick2::Canvas::isImageLoading(url image) - Returns true if the \a image is currently loading. - - \sa QtQuick2::Canvas::loadImage - */ -bool QQuickCanvasItem::isImageLoading(const QUrl& url) const -{ - Q_D(const QQuickCanvasItem); - QUrl fullPathUrl = d->baseUrl.resolved(url); - return d->images.contains(fullPathUrl) - && d->images.value(fullPathUrl)->isLoading(); -} -/*! - \qmlmethod void QtQuick2::Canvas::isImageLoaded(url image) - Returns true if the \a image is sucessfully loaded and ready to use. - - \sa QtQuick2::Canvas::loadImage - */ -bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const -{ - Q_D(const QQuickCanvasItem); - QUrl fullPathUrl = d->baseUrl.resolved(url); - return d->images.contains(fullPathUrl) - && d->images.value(fullPathUrl)->isReady(); -} - -QImage QQuickCanvasItem::toImage(const QRectF& region) const -{ - Q_D(const QQuickCanvasItem); - if (d->texture) { - if (region.isEmpty()) - return d->texture->toImage(canvasWindow()); - else - return d->texture->toImage(region); - } - return QImage(); -} - -/*! - \qmlmethod string QtQuick2::Canvas::toDataURL(string mimeType) - - Returns a data URL for the image in the canvas. - - The default \a mimeType is "image/png". - - \sa QtQuick2::Canvas::save - */ -QString QQuickCanvasItem::toDataURL(const QString& mimeType) const -{ - QImage image = toImage(); - - if (!image.isNull()) { - QByteArray ba; - QBuffer buffer(&ba); - buffer.open(QIODevice::WriteOnly); - QString mime = mimeType.toLower(); - QString type; - if (mime == QLatin1Literal("image/png")) { - type = QLatin1Literal("PNG"); - } else if (mime == QLatin1Literal("image/bmp")) - type = QLatin1Literal("BMP"); - else if (mime == QLatin1Literal("image/jpeg")) - type = QLatin1Literal("JPEG"); - else if (mime == QLatin1Literal("image/x-portable-pixmap")) - type = QLatin1Literal("PPM"); - else if (mime == QLatin1Literal("image/tiff")) - type = QLatin1Literal("TIFF"); - else if (mime == QLatin1Literal("image/xpm")) - type = QLatin1Literal("XPM"); - else - return QLatin1Literal("data:,"); - - image.save(&buffer, type.toAscii()); - buffer.close(); - QString dataUrl = QLatin1Literal("data:%1;base64,%2"); - return dataUrl.arg(mime).arg(QLatin1String(ba.toBase64().constData())); - } - return QLatin1Literal("data:,"); -} - -/*! - \qmlsignal QtQuick2::Canvas::onPaint(QtQuick2::Context2D context, rect region) - - This handler is called to render the \a region. - - This signal can be triggered by QtQuick2::Canvas::markdirty, QtQuick2::Canvas::requestPaint - or by changing the current canvas window. -*/ - -/*! - \qmlsignal QtQuick2::Canvas::onPainted() - - This handler is called after all context painting commands are executed and - the Canvas has been rendered. -*/ - -QT_END_NAMESPACE |