-
Marius Storm-Olsen authored
Ensure comma between elements (16 missing), single space and curly- braces around title elements, etc. Change-Id: I74e5a42e4a7054265c5c8445f8d2e2e6f46d0cf9 Reviewed-by:
Casper van Donderen <casper.vandonderen@nokia.com>
2959cef7
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtQml 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 "qquickcontext2d_p.h"
#include "qquickcontext2dcommandbuffer_p.h"
#include "qquickcanvasitem_p.h"
#include <private/qquickcontext2dtexture_p.h>
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickshadereffectsource_p.h>
#include <QtGui/qopenglframebufferobject.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qquicksvgparser_p.h>
#include <private/qquickpath_p.h>
#include <private/qquickimage_p_p.h>
#include <QtGui/qguiapplication.h>
#include <qqmlinfo.h>
#include <QtCore/qmath.h>
#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <private/qv8domerrors_p.h>
#include <QtCore/qnumeric.h>
#ifdef Q_OS_QNX
#include <ctype.h>
#endif
QT_BEGIN_NAMESPACE
/*!
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
\qmlclass Context2D QQuickContext2D
\inqmlmodule QtQuick 2
\since QtQuick 2.0
\brief The Context2D API allows you to draw 2d graphic shapes on the \c
Canvas item.
The Context2D object can be created by \c Canvas item's \c getContext()
method:
\code
Canvas {
id:canvas
onPaint:{
var ctx = canvas.getContext('2d');
//...
}
}
\endcode
The Context2D API implements the same \l
{http://www.w3.org/TR/2dcontext}{W3C Canvas 2D Context API standard} with
some enhanced features.
The Context2D API provides the rendering \b{context} which defines the
methods and attributes needed to draw on the \c Canvas item. The following
assigns the canvas rendering context to a \c{context} variable:
\code
var context = mycanvas.getContext("2d")
\endcode
The Context2D API renders the canvas as a coordinate system whose origin
(0,0) is at the top left corner, as shown in the figure below. Coordinates
increase along the \c{x} axis from left to right and along the \c{y} axis
from top to bottom of the canvas.
\image qml-item-canvas-context.gif
*/
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
static const double Q_PI = 3.14159265358979323846; // pi
#define DEGREES(t) ((t) * 180.0 / Q_PI)
#define CHECK_CONTEXT(r) if (!r || !r->context || !r->context->bufferValid()) \
V8THROW_ERROR("Not a Context2D object");
#define CHECK_CONTEXT_SETTER(r) if (!r || !r->context || !r->context->bufferValid()) \
V8THROW_ERROR_SETTER("Not a Context2D object");
#define qClamp(val, min, max) qMin(qMax(val, min), max)
#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
QColor qt_color_from_string(v8::Local<v8::Value> name)
{
v8::String::AsciiValue str(name);
char *p = *str;
int len = str.length();
//rgb/hsl color string has at least 7 characters
if (!p || len > 255 || len <= 7)
return QColor(p);
else {
bool isRgb(false), isHsl(false), hasAlpha(false);
Q_UNUSED(isHsl)
while (isspace(*p)) p++;
if (strncmp(p, "rgb", 3) == 0)
isRgb = true;
else if (strncmp(p, "hsl", 3) == 0)
isHsl = true;
else
return QColor(p);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
p+=3; //skip "rgb" or "hsl"
hasAlpha = (*p == 'a') ? true : false;
++p; //skip "("
if (hasAlpha) ++p; //skip "a"
int rh, gs, bl, alpha = 255;
//red
while (isspace(*p)) p++;
rh = strtol(p, &p, 10);
if (*p == '%') {
rh = qRound(rh/100.0 * 255);
++p;
}
if (*p++ != ',') return QColor();
//green
while (isspace(*p)) p++;
gs = strtol(p, &p, 10);
if (*p == '%') {
gs = qRound(gs/100.0 * 255);
++p;
}
if (*p++ != ',') return QColor();
//blue
while (isspace(*p)) p++;
bl = strtol(p, &p, 10);
if (*p == '%') {
bl = qRound(bl/100.0 * 255);
++p;
}
if (hasAlpha) {
if (*p++!= ',') return QColor();
while (isspace(*p)) p++;
bool ok = false;
alpha = qRound(qstrtod(p, const_cast<const char **>(&p), &ok) * 255);
}
if (*p != ')') return QColor();
if (isRgb)
return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
else if (isHsl)
return QColor::fromHsl(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
}
return QColor();
}
QFont qt_font_from_string(const QString& fontString) {
QFont font;
// ### this is simplified and incomplete
// ### TODO:get code from Qt webkit
QStringList tokens = fontString.split(QLatin1String(" "));
foreach (const QString &token, tokens) {
if (token == QLatin1String("italic"))
font.setItalic(true);
else if (token == QLatin1String("bold"))
font.setBold(true);
else if (token.endsWith(QLatin1String("px"))) {
QString number = token;
number.remove(QLatin1String("px"));
//font.setPointSizeF(number.trimmed().toFloat());
font.setPixelSize(number.trimmed().toInt());
} else
font.setFamily(token);
}
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
return font;
}
class QQuickContext2DEngineData : public QV8Engine::Deletable
{
public:
QQuickContext2DEngineData(QV8Engine *engine);
~QQuickContext2DEngineData();
v8::Persistent<v8::Function> constructorContext;
v8::Persistent<v8::Function> constructorGradient;
v8::Persistent<v8::Function> constructorPattern;
v8::Persistent<v8::Function> constructorPixelArray;
v8::Persistent<v8::Function> constructorImageData;
};
V8_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
class QV8Context2DResource : public QV8ObjectResource
{
V8_RESOURCE_TYPE(Context2DType)
public:
QV8Context2DResource(QV8Engine *e) : QV8ObjectResource(e) {}
QQuickContext2D* context;
};
class QV8Context2DStyleResource : public QV8ObjectResource
{
V8_RESOURCE_TYPE(Context2DStyleType)
public:
QV8Context2DStyleResource(QV8Engine *e)
: QV8ObjectResource(e)
, patternRepeatX(false)
, patternRepeatY(false)
{}
QBrush brush;
bool patternRepeatX:1;
bool patternRepeatY:1;
};
class QV8Context2DPixelArrayResource : public QV8ObjectResource
{
V8_RESOURCE_TYPE(Context2DPixelArrayType)
public:
QV8Context2DPixelArrayResource(QV8Engine *e) : QV8ObjectResource(e) {}
QImage image;
};
QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
{
int sides = radius ? radius : qRound(qSqrt(weights.size()));
int half = qFloor(sides/2);
QImage dst = QImage(src.size(), src.format());
int w = src.width();
int h = src.height();
for (int y = 0; y < dst.height(); ++y) {
QRgb *dr = (QRgb*)dst.scanLine(y);
for (int x = 0; x < dst.width(); ++x) {
unsigned char* dRgb = ((unsigned char*)&dr[x]);
unsigned char red=0, green=0, blue=0, alpha=0;
int sy = y;
int sx = x;
for (int cy=0; cy<sides; cy++) {
for (int cx=0; cx<sides; cx++) {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
int scy = sy + cy - half;
int scx = sx + cx - half;
if (scy >= 0 && scy < w && scx >= 0 && scx < h) {
const QRgb *sr = (const QRgb*)(src.constScanLine(scy));
const unsigned char* sRgb = ((const unsigned char*)&sr[scx]);
qreal wt = radius ? weights[0] : weights[cy*sides+cx];
red += sRgb[0] * wt;
green += sRgb[1] * wt;
blue += sRgb[2] * wt;
alpha += sRgb[3] * wt;
}
}
}
dRgb[0] = red;
dRgb[1] = green;
dRgb[2] = blue;
dRgb[3] = alpha;
}
}
return dst;
}
void qt_image_boxblur(QImage& image, int radius, bool quality)
{
int passes = quality? 3: 1;
for (int i=0; i < passes; i++) {
image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0/(radius * radius * 1.0), radius);
}
}
static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
{
if (compositeOperator == QLatin1String("source-over")) {
return QPainter::CompositionMode_SourceOver;
} else if (compositeOperator == QLatin1String("source-out")) {
return QPainter::CompositionMode_SourceOut;
} else if (compositeOperator == QLatin1String("source-in")) {
return QPainter::CompositionMode_SourceIn;
} else if (compositeOperator == QLatin1String("source-atop")) {
return QPainter::CompositionMode_SourceAtop;
} else if (compositeOperator == QLatin1String("destination-atop")) {
return QPainter::CompositionMode_DestinationAtop;
} else if (compositeOperator == QLatin1String("destination-in")) {
return QPainter::CompositionMode_DestinationIn;
} else if (compositeOperator == QLatin1String("destination-out")) {
return QPainter::CompositionMode_DestinationOut;
} else if (compositeOperator == QLatin1String("destination-over")) {
return QPainter::CompositionMode_DestinationOver;
} else if (compositeOperator == QLatin1String("lighter")) {
return QPainter::CompositionMode_Lighten;
} else if (compositeOperator == QLatin1String("copy")) {
return QPainter::CompositionMode_Source;
} else if (compositeOperator == QLatin1String("xor")) {
return QPainter::CompositionMode_Xor;
} else if (compositeOperator == QLatin1String("qt-clear")) {
return QPainter::CompositionMode_Clear;
} else if (compositeOperator == QLatin1String("qt-destination")) {
return QPainter::CompositionMode_Destination;
} else if (compositeOperator == QLatin1String("qt-multiply")) {
return QPainter::CompositionMode_Multiply;
} else if (compositeOperator == QLatin1String("qt-screen")) {
return QPainter::CompositionMode_Screen;
} else if (compositeOperator == QLatin1String("qt-overlay")) {
return QPainter::CompositionMode_Overlay;
} else if (compositeOperator == QLatin1String("qt-darken")) {
return QPainter::CompositionMode_Darken;
} else if (compositeOperator == QLatin1String("qt-lighten")) {
return QPainter::CompositionMode_Lighten;
} else if (compositeOperator == QLatin1String("qt-color-dodge")) {
return QPainter::CompositionMode_ColorDodge;
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
} else if (compositeOperator == QLatin1String("qt-color-burn")) {
return QPainter::CompositionMode_ColorBurn;
} else if (compositeOperator == QLatin1String("qt-hard-light")) {
return QPainter::CompositionMode_HardLight;
} else if (compositeOperator == QLatin1String("qt-soft-light")) {
return QPainter::CompositionMode_SoftLight;
} else if (compositeOperator == QLatin1String("qt-difference")) {
return QPainter::CompositionMode_Difference;
} else if (compositeOperator == QLatin1String("qt-exclusion")) {
return QPainter::CompositionMode_Exclusion;
}
return QPainter::CompositionMode_SourceOver;
}
static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
{
switch (op) {
case QPainter::CompositionMode_SourceOver:
return QLatin1String("source-over");
case QPainter::CompositionMode_DestinationOver:
return QLatin1String("destination-over");
case QPainter::CompositionMode_Clear:
return QLatin1String("qt-clear");
case QPainter::CompositionMode_Source:
return QLatin1String("copy");
case QPainter::CompositionMode_Destination:
return QLatin1String("qt-destination");
case QPainter::CompositionMode_SourceIn:
return QLatin1String("source-in");
case QPainter::CompositionMode_DestinationIn:
return QLatin1String("destination-in");
case QPainter::CompositionMode_SourceOut:
return QLatin1String("source-out");
case QPainter::CompositionMode_DestinationOut:
return QLatin1String("destination-out");
case QPainter::CompositionMode_SourceAtop:
return QLatin1String("source-atop");
case QPainter::CompositionMode_DestinationAtop:
return QLatin1String("destination-atop");
case QPainter::CompositionMode_Xor:
return QLatin1String("xor");
case QPainter::CompositionMode_Plus:
return QLatin1String("plus");
case QPainter::CompositionMode_Multiply:
return QLatin1String("qt-multiply");
case QPainter::CompositionMode_Screen:
return QLatin1String("qt-screen");
case QPainter::CompositionMode_Overlay:
return QLatin1String("qt-overlay");
case QPainter::CompositionMode_Darken:
return QLatin1String("qt-darken");
case QPainter::CompositionMode_Lighten:
return QLatin1String("lighter");
case QPainter::CompositionMode_ColorDodge:
return QLatin1String("qt-color-dodge");
case QPainter::CompositionMode_ColorBurn:
return QLatin1String("qt-color-burn");
case QPainter::CompositionMode_HardLight:
return QLatin1String("qt-hard-light");
case QPainter::CompositionMode_SoftLight:
return QLatin1String("qt-soft-light");
case QPainter::CompositionMode_Difference:
return QLatin1String("qt-difference");
case QPainter::CompositionMode_Exclusion:
return QLatin1String("qt-exclusion");
default:
break;
}
return QString();
}
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
static v8::Local<v8::Object> qt_create_image_data(qreal w, qreal h, QV8Engine* engine, const QImage& image)
{
QQuickContext2DEngineData *ed = engineData(engine);
v8::Local<v8::Object> imageData = ed->constructorImageData->NewInstance();
QV8Context2DPixelArrayResource *r = new QV8Context2DPixelArrayResource(engine);
if (image.isNull()) {
r->image = QImage(w, h, QImage::Format_ARGB32);
r->image.fill(0x00000000);
} else {
Q_ASSERT(image.width() == w && image.height() == h);
r->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
v8::Local<v8::Object> pixelData = ed->constructorPixelArray->NewInstance();
pixelData->SetExternalResource(r);
imageData->SetInternalField(0, pixelData);
return imageData;
}
//static script functions
/*!
\qmlproperty QtQuick2::Canvas QtQuick2::Context2D::canvas
Holds the canvas item that the context paints on.
This property is read only.
*/
static v8::Handle<v8::Value> ctx2d_canvas(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
return engine->newQObject(r->context->canvas());
}
/*!
\qmlmethod object QtQuick2::Context2D::restore()
Pops the top state on the stack, restoring the context to that state.
\sa QtQuick2::Context2D::save()
*/
static v8::Handle<v8::Value> ctx2d_restore(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
r->context->popState();
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::reset()
Resets the context state and properties to the default values.
*/
static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
r->context->reset();
return args.This();
}
/*!
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
\qmlmethod object QtQuick2::Context2D::save()
Pushes the current state onto the state stack.
Before changing any state attributes, you should save the current state
for future reference. The context maintains a stack of drawing states.
Each state consists of the current transformation matrix, clipping region,
and values of the following attributes:
\list
\li\a QtQuick2::Context2D::strokeStyle
\li\a QtQuick2::Context2D::fillStyle
\li\a QtQuick2::Context2D::fillRule
\li\a QtQuick2::Context2D::globalAlpha
\li\a QtQuick2::Context2D::lineWidth
\li\a QtQuick2::Context2D::lineCap
\li\a QtQuick2::Context2D::lineJoin
\li\a QtQuick2::Context2D::miterLimit
\li\a QtQuick2::Context2D::shadowOffsetX
\li\a QtQuick2::Context2D::shadowOffsetY
\li\a QtQuick2::Context2D::shadowBlur
\li\a QtQuick2::Context2D::shadowColor
\li\a QtQuick2::Context2D::globalCompositeOperation
\li\a QtQuick2::Context2D::font
\li\a QtQuick2::Context2D::textAlign
\li\a QtQuick2::Context2D::textBaseline
\endlist
The current path is NOT part of the drawing state. The path can be reset by
invoking the \a QtQuick2::Context2D::beginPath() method.
*/
static v8::Handle<v8::Value> ctx2d_save(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
r->context->pushState();
return args.This();
}
// transformations
/*!
\qmlmethod object QtQuick2::Context2D::rotate(real angle)
Rotate the canvas around the current origin by \c angle in radians and clockwise direction.
\code
ctx.rotate(Math.PI/2);
\endcode
\image qml-item-canvas-rotate.png
The rotation transformation matrix is as follows:
\image qml-item-canvas-math-rotate.png
where the \c angle of rotation is in radians.
*/
static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 1)
r->context->rotate(args[0]->NumberValue());
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::scale(real x, real y)
Increases or decreases the size of each unit in the canvas grid by multiplying the scale factors
to the current tranform matrix.
Where \c x is the scale factor in the horizontal direction and \c y is the scale factor in the
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
vertical direction.
The following code doubles the horizontal size of an object drawn on the canvas and half its
vertical size:
\code
ctx.scale(2.0, 0.5);
\endcode
\image qml-item-canvas-scale.png
*/
static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 2)
r->context->scale(args[0]->NumberValue(), args[1]->NumberValue());
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::setTransform(real a, real b, real c, real d, real e, real f)
Changes the transformation matrix to the matrix given by the arguments as described below.
Modifying the transformation matrix directly enables you to perform scaling,
rotating, and translating transformations in a single step.
Each point on the canvas is multiplied by the matrix before anything is
drawn. The \l{HTML5 Canvas API} defines the transformation matrix as:
\image qml-item-canvas-math.png
where:
\list
\li \c{a} is the scale factor in the horizontal (x) direction
\image qml-item-canvas-scalex.png
\li \c{c} is the skew factor in the x direction
\image qml-item-canvas-canvas-skewx.png
\li \c{e} is the translation in the x direction
\image qml-item-canvas-canvas-translate.png
\li \c{b} is the skew factor in the y (vertical) direction
\image qml-item-canvas-canvas-skewy.png
\li \c{d} is the scale factor in the y direction
\image qml-item-canvas-canvas-scaley.png
\li \c{f} is the translation in the y direction
\image qml-item-canvas-canvas-translatey.png
\li the last row remains constant
\endlist
The scale factors and skew factors are multiples; \c{e} and \c{f} are
coordinate space units, just like the units in the \a QtQuick2::Context2D::translate(x,y)
method.
\sa QtQuick2::Context2D::transform()
*/
static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 6)
r->context->setTransform( args[0]->NumberValue()
, args[1]->NumberValue()
, args[2]->NumberValue()
, args[3]->NumberValue()
, args[4]->NumberValue()
, args[5]->NumberValue());
return args.This();
}
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
/*!
\qmlmethod object QtQuick2::Context2D::transform(real a, real b, real c, real d, real e, real f)
This method is very similar to \a QtQuick2::Context2D::setTransform(), but instead of replacing the old
tranform matrix, this method applies the given tranform matrix to the current matrix by mulitplying to it.
The \a setTransform(a, b, c, d, e, f) method actually resets the current transform to the identity matrix,
and then invokes the transform(a, b, c, d, e, f) method with the same arguments.
\sa QtQuick2::Context2D::setTransform()
*/
static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 6)
r->context->transform( args[0]->NumberValue()
, args[1]->NumberValue()
, args[2]->NumberValue()
, args[3]->NumberValue()
, args[4]->NumberValue()
, args[5]->NumberValue());
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::translate(real x, real y)
Translates the origin of the canvas to point (\c x, \c y).
\c x is the horizontal distance that the origin is translated, in coordinate space units,
\c y is the vertical distance that the origin is translated, in coordinate space units.
Translating the origin enables you to draw patterns of different objects on the canvas
without having to measure the coordinates manually for each shape.
*/
static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 2)
r->context->translate(args[0]->NumberValue(), args[1]->NumberValue());
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::resetTransform()
Reset the transformation matrix to default value.
\sa QtQuick2::Context2D::transform(), QtQuick2::Context2D::setTransform(), QtQuick2::Context2D::reset()
*/
static v8::Handle<v8::Value> ctx2d_resetTransform(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
r->context->setTransform(1, 0, 0, 1, 0, 0);
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::shear(real sh, real sv )
Shear the transformation matrix with \a sh in horizontal direction and \a sv in vertical direction.
*/
static v8::Handle<v8::Value> ctx2d_shear(const v8::Arguments &args)
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
if (args.Length() == 2)
r->context->shear(args[0]->NumberValue(), args[1]->NumberValue());
return args.This();
}
// compositing
/*!
\qmlproperty real QtQuick2::Context2D::globalAlpha
Holds the the current alpha value applied to rendering operations.
The value must be in the range from 0.0 (fully transparent) to 1.0 (fully opque).
The default value is 1.0.
*/
static v8::Handle<v8::Value> ctx2d_globalAlpha(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT(r)
return v8::Number::New(r->context->state.globalAlpha);
}
static void ctx2d_globalAlpha_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT_SETTER(r)
qreal globalAlpha = value->NumberValue();
if (!qIsFinite(globalAlpha))
return;
if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->context->state.globalAlpha != globalAlpha) {
r->context->state.globalAlpha = globalAlpha;
r->context->buffer()->setGlobalAlpha(r->context->state.globalAlpha);
}
}
/*!
\qmlproperty string QtQuick2::Context2D::globalCompositeOperation
Holds the the current the current composition operation, from the list below:
\list
\li source-atop - A atop B. Display the source image wherever both images are opaque.
Display the destination image wherever the destination image is opaque but the source image is transparent.
Display transparency elsewhere.
\li source-in - A in B. Display the source image wherever both the source image and destination image are opaque.
Display transparency elsewhere.
\li source-out - A out B. Display the source image wherever the source image is opaque and the destination image is transparent.
Display transparency elsewhere.
\li source-over - (default) A over B. Display the source image wherever the source image is opaque.
Display the destination image elsewhere.
\li destination-atop - B atop A. Same as source-atop but using the destination image instead of the source image and vice versa.
\li destination-in - B in A. Same as source-in but using the destination image instead of the source image and vice versa.
\li destination-out - B out A. Same as source-out but using the destination image instead of the source image and vice versa.
\li destination-over - B over A. Same as source-over but using the destination image instead of the source image and vice versa.
\li lighter - A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit.
\li copy - A (B is ignored). Display the source image instead of the destination image.
\li xor - A xor B. Exclusive OR of the source image and destination image.
\endlist
Additionally, this property also accepts the compositon modes listed in \a {QPainter::CompositionMode}. According to the W3C standard, these
extension composition modes are provided as "vendorName-operationName" syntax, for example: \c {QPainter::CompositionMode_Exclusion} is porvided as
"qt-exclusion".
*/
static v8::Handle<v8::Value> ctx2d_globalCompositeOperation(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
return engine->toString(qt_composite_mode_to_string(r->context->state.globalCompositeOperation));
}
static void ctx2d_globalCompositeOperation_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT_SETTER(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
QString mode = engine->toString(value);
QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over"))
return;
if (cm != r->context->state.globalCompositeOperation) {
r->context->state.globalCompositeOperation = cm;
r->context->buffer()->setGlobalCompositeOperation(cm);
}
}
// colors and styles
/*!
\qmlproperty variant QtQuick2::Context2D::fillStyle
Holds the current style used for filling shapes.
The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object. Invalid values are ignored.
This property accepts several color syntaxes:
\list
\li 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)'
\li 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)'
\li 'hsl(hue, saturation, lightness)'
\li 'hsla(hue, saturation, lightness, alpha)'
\li '#RRGGBB' - for example: '#00FFCC'
\li Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0)
\endlist
If the \a fillStyle or \a strokeStyle is assigned many times in a loop, the last Qt.rgba() syntax should be chosen, as it has the
best performance, because it's already a valid QColor value, does not need to be parsed everytime.
The default value is '#000000'.
\sa QtQuick2::Context2D::createLinearGradient
\sa QtQuick2::Context2D::createRadialGradient
\sa QtQuick2::Context2D::createPattern
\sa QtQuick2::Context2D::strokeStyle
*/
static v8::Handle<v8::Value> ctx2d_fillStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
QColor color = r->context->state.fillStyle.color();
if (color.isValid()) {
if (color.alpha() == 255)
return engine->toString(color.name());
QString alphaString = QString::number(color.alphaF(), 'f');
while (alphaString.endsWith(QLatin1Char('0')))
alphaString.chop(1);
if (alphaString.endsWith(QLatin1Char('.')))
alphaString += QLatin1Char('0');
return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
}
return r->context->m_fillStyle;
}
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
static void ctx2d_fillStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT_SETTER(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
if (value->IsObject()) {
QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->context->state.fillStyle = color;
r->context->buffer()->setFillStyle(color);
r->context->m_fillStyle = value;
} else {
QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
if (style && style->brush != r->context->state.fillStyle) {
r->context->state.fillStyle = style->brush;
r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
r->context->m_fillStyle = value;
r->context->state.fillPatternRepeatX = style->patternRepeatX;
r->context->state.fillPatternRepeatY = style->patternRepeatY;
}
}
} else if (value->IsString()) {
QColor color = qt_color_from_string(value);
if (color.isValid() && r->context->state.fillStyle != QBrush(color)) {
r->context->state.fillStyle = QBrush(color);
r->context->buffer()->setFillStyle(r->context->state.fillStyle);
r->context->m_fillStyle = value;
}
}
}
/*!
\qmlproperty enumeration QtQuick2::Context2D::fillRule
Holds the current fill rule used for filling shapes. The following fill rules supported:
\list
\li Qt.OddEvenFill
\li Qt.WindingFill
\endlist
Note: Unlike the \a QPainterPath, the Canvas API uses the winding fill as the default fill rule.
The fillRule property is part of the context rendering state.
\sa QtQuick2::Context2D::fillStyle
*/
static v8::Handle<v8::Value> ctx2d_fillRule(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
return engine->fromVariant(r->context->state.fillRule);
}
static void ctx2d_fillRule_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT_SETTER(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
if ((value->IsString() && engine->toString(value) == QStringLiteral("WindingFill"))
||(value->IsNumber() && value->NumberValue() == Qt::WindingFill)) {
r->context->state.fillRule = Qt::WindingFill;
} else if ((value->IsString() && engine->toString(value) == QStringLiteral("OddEvenFill"))
||(value->IsNumber() && value->NumberValue() == Qt::OddEvenFill)) {
r->context->state.fillRule = Qt::OddEvenFill;
} else {
//error
}
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
r->context->m_path.setFillRule(r->context->state.fillRule);
}
/*!
\qmlproperty variant QtQuick2::Context2D::strokeStyle
Holds the current color or style to use for the lines around shapes,
The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object.
Invalid values are ignored.
The default value is '#000000'.
\sa QtQuick2::Context2D::createLinearGradient
\sa QtQuick2::Context2D::createRadialGradient
\sa QtQuick2::Context2D::createPattern
\sa QtQuick2::Context2D::fillStyle
*/
v8::Handle<v8::Value> ctx2d_strokeStyle(v8::Local<v8::String>, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
QColor color = r->context->state.strokeStyle.color();
if (color.isValid()) {
if (color.alpha() == 255)
return engine->toString(color.name());
QString alphaString = QString::number(color.alphaF(), 'f');
while (alphaString.endsWith(QLatin1Char('0')))
alphaString.chop(1);
if (alphaString.endsWith(QLatin1Char('.')))
alphaString += QLatin1Char('0');
return engine->toString(QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString));
}
return r->context->m_strokeStyle;
}
static void ctx2d_strokeStyle_set(v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(info.This());
CHECK_CONTEXT_SETTER(r)
QV8Engine *engine = V8ENGINE_ACCESSOR();
if (value->IsObject()) {
QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->context->state.fillStyle = color;
r->context->buffer()->setStrokeStyle(color);
r->context->m_strokeStyle = value;
} else {
QV8Context2DStyleResource *style = v8_resource_cast<QV8Context2DStyleResource>(value->ToObject());
if (style && style->brush != r->context->state.strokeStyle) {
r->context->state.strokeStyle = style->brush;
r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
r->context->m_strokeStyle = value;
r->context->state.strokePatternRepeatX = style->patternRepeatX;
r->context->state.strokePatternRepeatY = style->patternRepeatY;
}
}
} else if (value->IsString()) {
QColor color = qt_color_from_string(value);
if (color.isValid() && r->context->state.strokeStyle != QBrush(color)) {
r->context->state.strokeStyle = QBrush(color);
r->context->buffer()->setStrokeStyle(r->context->state.strokeStyle);
r->context->m_strokeStyle = value;
}
}
}
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
/*!
\qmlmethod object QtQuick2::Context2D::createLinearGradient(real x0, real y0, real x1, real y1)
Returns a CanvasGradient object that represents a linear gradient that transitions the color along a line between
the start point (\a x0, \a y0) and the end point (\a x1, \a y1).
A gradient is a smooth transition between colors. There are two types of gradients: linear and radial.
Gradients must have two or more color stops, representing color shifts positioned from 0 to 1 between
to the gradient's starting and end points or circles.
\sa QtQuick2::Context2D::CanvasGradient::addColorStop
\sa QtQuick2::Context2D::createRadialGradient
\sa QtQuick2::Context2D::ctx2d_createConicalGradient
\sa QtQuick2::Context2D::createPattern
\sa QtQuick2::Context2D::fillStyle
\sa QtQuick2::Context2D::strokeStyle
*/
static v8::Handle<v8::Value> ctx2d_createLinearGradient(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE();
if (args.Length() == 4) {
QQuickContext2DEngineData *ed = engineData(engine);
v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
qreal x0 = args[0]->NumberValue();
qreal y0 = args[1]->NumberValue();
qreal x1 = args[2]->NumberValue();
qreal y1 = args[3]->NumberValue();
if (!qIsFinite(x0)
|| !qIsFinite(y0)
|| !qIsFinite(x1)
|| !qIsFinite(y1))
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
r->brush = QLinearGradient(x0, y0, x1, y1);
gradient->SetExternalResource(r);
return gradient;
}
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::createRadialGradient(real x0, real y0, real r0, real x1, real y1, real r1)
Returns a CanvasGradient object that represents a radial gradient that paints along the cone given by the start circle with
origin (x0, y0) and radius r0, and the end circle with origin (x1, y1) and radius r1.
\sa QtQuick2::Context2D::CanvasGradient::addColorStop
\sa QtQuick2::Context2D::createLinearGradient
\sa QtQuick2::Context2D::ctx2d_createConicalGradient
\sa QtQuick2::Context2D::createPattern
\sa QtQuick2::Context2D::fillStyle
\sa QtQuick2::Context2D::strokeStyle
*/
static v8::Handle<v8::Value> ctx2d_createRadialGradient(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE();
if (args.Length() == 6) {
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
QQuickContext2DEngineData *ed = engineData(engine);
v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
qreal x0 = args[0]->NumberValue();
qreal y0 = args[1]->NumberValue();
qreal r0 = args[2]->NumberValue();
qreal x1 = args[3]->NumberValue();
qreal y1 = args[4]->NumberValue();
qreal r1 = args[5]->NumberValue();
if (!qIsFinite(x0)
|| !qIsFinite(y0)
|| !qIsFinite(x1)
|| !qIsFinite(r0)
|| !qIsFinite(r1)
|| !qIsFinite(y1))
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
if (r0 < 0 || r1 < 0)
V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
r->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
gradient->SetExternalResource(r);
return gradient;
}
return args.This();
}
/*!
\qmlmethod object QtQuick2::Context2D::createConicalGradient(real x, real y, real angle)
Returns a CanvasGradient object that represents a conical gradient that interpolate colors counter-clockwise around a center point (\c x, \c y)
with start angle \c angle in units of radians.
\sa QtQuick2::Context2D::CanvasGradient::addColorStop
\sa QtQuick2::Context2D::createLinearGradient
\sa QtQuick2::Context2D::ctx2d_createRadialGradient
\sa QtQuick2::Context2D::createPattern
\sa QtQuick2::Context2D::fillStyle
\sa QtQuick2::Context2D::strokeStyle
*/
static v8::Handle<v8::Value> ctx2d_createConicalGradient(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE();
if (args.Length() == 6) {
QQuickContext2DEngineData *ed = engineData(engine);
v8::Local<v8::Object> gradient = ed->constructorGradient->NewInstance();
QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
qreal x = args[0]->NumberValue();
qreal y = args[1]->NumberValue();
qreal angle = DEGREES(args[2]->NumberValue());
if (!qIsFinite(x) || !qIsFinite(y))
V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
if (!qIsFinite(angle))
V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
r->brush = QConicalGradient(x, y, angle);
gradient->SetExternalResource(r);
return gradient;
}
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
return args.This();
}
/*!
\qmlmethod variant createPattern(Color color, enumeration patternMode)
This is a overload function.
Returns a CanvasPattern object that uses the given \c color and \c patternMode.
The valid pattern modes are:
\list
\li Qt.SolidPattern
\li Qt.Dense1Pattern
\li Qt.Dense2Pattern
\li Qt.Dense3Pattern
\li Qt.Dense4Pattern
\li Qt.Dense5Pattern
\li Qt.Dense6Pattern
\li Qt.Dense7Pattern
\li Qt.HorPattern
\li Qt.VerPattern
\li Qt.CrossPattern
\li Qt.BDiagPattern
\li Qt.FDiagPattern
\li Qt.DiagCrossPattern
\endlist
\sa Qt::BrushStyle
*/
/*!
\qmlmethod variant createPattern(Image image, string repetition)
Returns a CanvasPattern object that uses the given image and repeats in the direction(s) given by the repetition argument.
The \a image parameter must be a valid Image item, a valid \a QtQuick2::CanvasImageData object or loaded image url, if there is no image data, throws an INVALID_STATE_ERR exception.
The allowed values for \a repetition are:
\list
\li "repeat" - both directions
\li "repeat-x - horizontal only
\li "repeat-y" - vertical only
\li "no-repeat" - neither
\endlist
If the repetition argument is empty or null, the value "repeat" is used.
\sa QtQuick2::Context2D::strokeStyle
\sa QtQuick2::Context2D::fillStyle
*/
static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE();
if (args.Length() == 2) {
QQuickContext2DEngineData *ed = engineData(engine);
QV8Context2DStyleResource *styleResouce = new QV8Context2DStyleResource(engine);
QColor color = engine->toVariant(args[0], qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
int patternMode = args[1]->IntegerValue();
Qt::BrushStyle style = Qt::SolidPattern;
if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) {
style = static_cast<Qt::BrushStyle>(patternMode);
}
styleResouce->brush = QBrush(color, style);
} else {
QImage patternTexture;
if (args[0]->IsObject()) {