Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickcontext2d.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickcontext2d_p.h"
7#include <private/qtquickglobal_p.h>
8#include <private/qquickcontext2dtexture_p.h>
9#include <private/qquickitem_p.h>
10#if QT_CONFIG(quick_shadereffect)
11#include <QtQuick/private/qquickshadereffectsource_p.h>
12#endif
14
15#include <QtQuick/private/qsgcontext_p.h>
16#include <private/qquicksvgparser_p.h>
17#if QT_CONFIG(quick_path)
18#include <private/qquickpath_p.h>
19#endif
20#include <private/qquickimage_p_p.h>
21
22#include <qqmlinfo.h>
23
24#include <qqmlengine.h>
25#include <private/qv4domerrors_p.h>
26#include <private/qv4engine_p.h>
27#include <private/qv4object_p.h>
28#include <private/qv4qobjectwrapper_p.h>
29#include <private/qquickwindow_p.h>
30
31#include <private/qv4value_p.h>
32#include <private/qv4functionobject_p.h>
33#include <private/qv4objectproto_p.h>
34#include <private/qv4scopedvalue_p.h>
35#include <private/qlocale_tools_p.h>
36
37#include <QtCore/qmath.h>
38#include <QtCore/qvector.h>
39#include <QtCore/private/qnumeric_p.h>
40#include <QtCore/QRunnable>
41#include <QtGui/qguiapplication.h>
42#include <private/qguiapplication_p.h>
43#include <qpa/qplatformintegration.h>
44
45#include <private/qsgdefaultrendercontext_p.h>
46
47#include <cmath>
48#if defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
49#include <ctype.h>
50#endif
51
92#define CHECK_CONTEXT(r) if (!r || !r->d()->context() || !r->d()->context()->bufferValid()) \
93 THROW_GENERIC_ERROR("Not a Context2D object");
94
95#define CHECK_CONTEXT_SETTER(r) if (!r || !r->d()->context() || !r->d()->context()->bufferValid()) \
96 THROW_GENERIC_ERROR("Not a Context2D object");
97#define qClamp(val, min, max) qMin(qMax(val, min), max)
98#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
99Q_QUICK_PRIVATE_EXPORT QColor qt_color_from_string(const QV4::Value &name)
100{
101 QByteArray str = name.toQString().toUtf8();
102
103 char *p = str.data();
104 int len = str.size();
105 //rgb/hsl color string has at least 7 characters
106 if (!p || len > 255 || len <= 7)
107 return QColor::fromString(p);
108 else {
109 bool isRgb(false), isHsl(false), hasAlpha(false);
110 Q_UNUSED(isHsl);
111
112 while (isspace(*p)) p++;
113 if (strncmp(p, "rgb", 3) == 0)
114 isRgb = true;
115 else if (strncmp(p, "hsl", 3) == 0)
116 isHsl = true;
117 else
118 return QColor::fromString(p);
119
120 p+=3; //skip "rgb" or "hsl"
121 hasAlpha = (*p == 'a') ? true : false;
122
123 ++p; //skip "("
124
125 if (hasAlpha) ++p; //skip "a"
126
127 int rh, gs, bl, alpha = 255;
128
129 //red
130 while (isspace(*p)) p++;
131 rh = strtol(p, &p, 10);
132 if (*p == '%') {
133 rh = qRound(rh/100.0 * 255);
134 ++p;
135 }
136 if (*p++ != ',') return QColor();
137
138 //green
139 while (isspace(*p)) p++;
140 gs = strtol(p, &p, 10);
141 if (*p == '%') {
142 gs = qRound(gs/100.0 * 255);
143 ++p;
144 }
145 if (*p++ != ',') return QColor();
146
147 //blue
148 while (isspace(*p)) p++;
149 bl = strtol(p, &p, 10);
150 if (*p == '%') {
151 bl = qRound(bl/100.0 * 255);
152 ++p;
153 }
154
155 if (hasAlpha) {
156 if (*p++!= ',') return QColor();
157 while (isspace(*p)) p++;
158 bool ok = false;
159 alpha = qRound(qstrtod(p, const_cast<const char **>(&p), &ok) * 255);
160 }
161
162 if (*p != ')') return QColor();
163 if (isRgb)
164 return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
165 else if (isHsl)
166 return QColor::fromHsl(qClamp(rh, 0, 359), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
167 }
168 return QColor();
169}
170
171static int qParseFontSizeFromToken(QStringView fontSizeToken, bool &ok)
172{
173 ok = false;
174 float size = fontSizeToken.trimmed().toFloat(&ok);
175 if (ok) {
176 return int(size);
177 }
178 qWarning().nospace() << "Context2D: A font size of " << fontSizeToken << " is invalid.";
179 return 0;
180}
181
182/*
183 Attempts to set the font size of \a font to \a fontSizeToken, returning
184 \c true if successful. If the font size is invalid, \c false is returned
185 and a warning is printed.
186*/
187static bool qSetFontSizeFromToken(QFont &font, QStringView fontSizeToken)
188{
189 const QStringView trimmedToken = fontSizeToken.trimmed();
190 const QStringView unitStr = trimmedToken.right(2);
191 const QStringView value = trimmedToken.left(trimmedToken.size() - 2);
192 bool ok = false;
193 int size = 0;
194 if (unitStr == QLatin1String("px")) {
196 if (ok) {
198 return true;
199 }
200 } else if (unitStr == QLatin1String("pt")) {
202 if (ok) {
204 return true;
205 }
206 } else {
207 qWarning().nospace() << "Context2D: Invalid font size unit in font string.";
208 }
209 return false;
210}
211
212/*
213 Returns a list of all of the families in \a fontFamiliesString, where
214 each family is separated by spaces. Families with spaces in their name
215 must be quoted.
216*/
218{
219 QStringList extractedFamilies;
220 int quoteIndex = -1;
221 QString currentFamily;
222 for (int index = 0; index < fontFamiliesString.size(); ++index) {
223 const QChar ch = fontFamiliesString.at(index);
224 if (ch == u'"' || ch == u'\'') {
225 if (quoteIndex == -1) {
226 quoteIndex = index;
227 } else {
228 if (ch == fontFamiliesString.at(quoteIndex)) {
229 // Found the matching quote. +1/-1 because we don't want the quote as part of the name.
230 const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1).toString();
231 extractedFamilies.push_back(family);
232 currentFamily.clear();
233 quoteIndex = -1;
234 } else {
235 qWarning().nospace() << "Context2D: Mismatched quote in font string.";
236 return QStringList();
237 }
238 }
239 } else if (ch == u' ' && quoteIndex == -1) {
240 // This is a space that's not within quotes...
241 if (!currentFamily.isEmpty()) {
242 // and there is a current family; consider it the end of the current family.
243 extractedFamilies.push_back(currentFamily);
244 currentFamily.clear();
245 } // else: ignore the space
246 } else {
247 currentFamily.push_back(ch);
248 }
249 }
250 if (!currentFamily.isEmpty()) {
251 if (quoteIndex == -1) {
252 // This is the end of the string, so add this family to our list.
253 extractedFamilies.push_back(currentFamily);
254 } else {
255 qWarning().nospace() << "Context2D: Unclosed quote in font string.";
256 return QStringList();
257 }
258 }
259 if (extractedFamilies.isEmpty()) {
260 qWarning().nospace() << "Context2D: Missing or misplaced font family in font string"
261 << " (it must come after the font size).";
262 }
263 return extractedFamilies;
264}
265
266/*
267 Tries to set a family on \a font using the families provided in \a fontFamilyTokens.
268
269 The list is ordered by preference, with the first family having the highest preference.
270 If the first family is invalid, the next family in the list is evaluated.
271 This process is repeated until a valid font is found (at which point the function
272 will return \c true and the family set on \a font) or there are no more
273 families left, at which point a warning is printed and \c false is returned.
274*/
275static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens)
276{
277 for (const QString &fontFamilyToken : fontFamilyTokens) {
278 if (QFontDatabase::hasFamily(fontFamilyToken)) {
279 font.setFamily(fontFamilyToken);
280 return true;
281 } else {
282 // Can't find a family matching this name; if it's a generic family,
283 // try searching for the default family for it by using style hints.
284 int styleHint = -1;
285 if (fontFamilyToken.compare(QLatin1String("serif")) == 0) {
286 styleHint = QFont::Serif;
287 } else if (fontFamilyToken.compare(QLatin1String("sans-serif")) == 0) {
288 styleHint = QFont::SansSerif;
289 } else if (fontFamilyToken.compare(QLatin1String("cursive")) == 0) {
290 styleHint = QFont::Cursive;
291 } else if (fontFamilyToken.compare(QLatin1String("monospace")) == 0) {
292 styleHint = QFont::Monospace;
293 } else if (fontFamilyToken.compare(QLatin1String("fantasy")) == 0) {
294 styleHint = QFont::Fantasy;
295 }
296 if (styleHint != -1) {
297 QFont tmp;
298 tmp.setStyleHint(static_cast<QFont::StyleHint>(styleHint));
300 return true;
301 }
302 }
303 }
304 qWarning("Context2D: The font families specified are invalid: %s", qPrintable(fontFamilyTokens.join(QString()).trimmed()));
305 return false;
306}
307
309{
310 NoTokens = 0x00,
311 FontStyle = 0x01,
313 FontWeight = 0x04
315
316#define Q_TRY_SET_TOKEN(token, value, setStatement) \
317if (!(usedTokens & token)) { \
318 usedTokens |= token; \
319 setStatement; \
320} else { \
321 qWarning().nospace() << "Context2D: Duplicate token " << QLatin1String(value) << " found in font string."; \
322 return currentFont; \
323}
324
325/*
326 Parses a font string based on the CSS shorthand font property.
327
328 See: http://www.w3.org/TR/css3-fonts/#font-prop
329*/
330static QFont qt_font_from_string(const QString& fontString, const QFont &currentFont) {
331 if (fontString.isEmpty()) {
332 qWarning().nospace() << "Context2D: Font string is empty.";
333 return currentFont;
334 }
335
336 // We know that font-size must be specified and it must be before font-family
337 // (which could potentially have "px" or "pt" in its name), so extract it now.
338 int fontSizeEnd = fontString.indexOf(QLatin1String("px"));
339 if (fontSizeEnd == -1)
340 fontSizeEnd = fontString.indexOf(QLatin1String("pt"));
341 if (fontSizeEnd == -1) {
342 qWarning().nospace() << "Context2D: Invalid font size unit in font string.";
343 return currentFont;
344 }
345
346 int fontSizeStart = fontString.lastIndexOf(u' ', fontSizeEnd);
347 if (fontSizeStart == -1) {
348 // The font size might be the first token in the font string, which is OK.
349 // Regardless, we'll find out if the font is invalid with qSetFontSizeFromToken().
350 fontSizeStart = 0;
351 } else {
352 // Don't want to take the leading space.
353 ++fontSizeStart;
354 }
355
356 // + 2 for the unit, +1 for the space that we require.
357 fontSizeEnd += 3;
358
359 QFont newFont;
360 if (!qSetFontSizeFromToken(newFont, QStringView{fontString}.mid(fontSizeStart, fontSizeEnd - fontSizeStart)))
361 return currentFont;
362
363 // We don't want to parse the size twice, so remove it now.
364 QString remainingFontString = fontString;
365 remainingFontString.remove(fontSizeStart, fontSizeEnd - fontSizeStart);
366 QStringView remainingFontStringRef(remainingFontString);
367
368 // Next, we have to take any font families out, as QString::split() will ruin quoted family names.
369 const QStringView fontFamiliesString = remainingFontStringRef.mid(fontSizeStart);
370 remainingFontStringRef.truncate(fontSizeStart);
371 QStringList fontFamilies = qExtractFontFamiliesFromString(fontFamiliesString);
372 if (fontFamilies.isEmpty()) {
373 return currentFont;
374 }
375 if (!qSetFontFamilyFromTokens(newFont, fontFamilies))
376 return currentFont;
377
378 // Now that we've removed the messy parts, we can split the font string on spaces.
379 const QStringView trimmedTokensStr = remainingFontStringRef.trimmed();
380 if (trimmedTokensStr.isEmpty()) {
381 // No optional properties.
382 return newFont;
383 }
384 const auto tokens = trimmedTokensStr.split(QLatin1Char(' '));
385
386 int usedTokens = NoTokens;
387 // Optional properties can be in any order, but font-size and font-family must be last.
388 for (const QStringView &token : tokens) {
389 if (token.compare(QLatin1String("normal")) == 0) {
390 if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
391 // Could be font-style, font-variant or font-weight.
392 if (!(usedTokens & FontStyle)) {
393 // QFont::StyleNormal is the default for QFont::style.
394 usedTokens = usedTokens | FontStyle;
395 } else if (!(usedTokens & FontVariant)) {
396 // QFont::MixedCase is the default for QFont::capitalization.
397 usedTokens |= FontVariant;
398 } else if (!(usedTokens & FontWeight)) {
399 // QFont::Normal is the default for QFont::weight.
400 usedTokens |= FontWeight;
401 }
402 } else {
403 qWarning().nospace() << "Context2D: Duplicate token \"normal\" found in font string.";
404 return currentFont;
405 }
406 } else if (token.compare(QLatin1String("bold")) == 0) {
407 Q_TRY_SET_TOKEN(FontWeight, "bold", newFont.setBold(true))
408 } else if (token.compare(QLatin1String("italic")) == 0) {
410 } else if (token.compare(QLatin1String("oblique")) == 0) {
412 } else if (token.compare(QLatin1String("small-caps")) == 0) {
414 } else {
415 bool conversionOk = false;
416 int weight = token.toInt(&conversionOk);
417 if (conversionOk) {
418 Q_TRY_SET_TOKEN(FontWeight, "<font-weight>",
420 } else {
421 // The token is invalid or in the wrong place/order in the font string.
422 qWarning().nospace() << "Context2D: Invalid or misplaced token " << token
423 << " found in font string.";
424 return currentFont;
425 }
426 }
427 }
428 return newFont;
429}
430
432{
433public:
436
440};
441
443
444namespace QV4 {
445namespace Heap {
446
448 void init()
449 {
450 Object::init();
451 m_context = nullptr;
452 }
453
454 void destroy()
455 {
456 delete m_context;
457 Object::destroy();
458 }
459
460 QQuickContext2D *context() { return m_context ? *m_context : nullptr; }
462 {
463 if (m_context)
464 *m_context = context;
465 else
466 m_context = new QPointer<QQuickContext2D>(context);
467 }
468
469private:
470 QPointer<QQuickContext2D>* m_context;
471};
472
474 void init() { Object::init(); }
475};
476
478 void init()
479 {
480 brush = new QBrush;
481 patternRepeatX = false;
482 patternRepeatY = false;
483 }
484 void destroy() {
485 delete brush;
486 Object::destroy();
487 }
488
492};
493
495 void init();
496 void destroy() {
497 delete image;
498 Object::destroy();
499 }
500
502};
503
505 void init();
506
507 static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
508 static_cast<QQuickJSContext2DImageData *>(that)->pixelData.mark(markStack);
509 Object::markObjects(that, markStack);
510 }
511
513};
514
515}
516}
517
519{
522
523 static QV4::ReturnedValue method_get_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
524 static QV4::ReturnedValue method_set_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
525 static QV4::ReturnedValue method_get_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
526 static QV4::ReturnedValue method_set_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
527 static QV4::ReturnedValue method_get_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
528 static QV4::ReturnedValue method_set_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
529 static QV4::ReturnedValue method_get_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
530 static QV4::ReturnedValue method_set_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
531 static QV4::ReturnedValue method_get_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
532 static QV4::ReturnedValue method_set_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
533
534 static QV4::ReturnedValue method_get_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
535 static QV4::ReturnedValue method_set_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
536 static QV4::ReturnedValue method_get_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
537 static QV4::ReturnedValue method_set_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
538 static QV4::ReturnedValue method_get_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
539 static QV4::ReturnedValue method_set_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
540 static QV4::ReturnedValue method_get_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
541 static QV4::ReturnedValue method_set_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
542 static QV4::ReturnedValue method_set_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
543 static QV4::ReturnedValue method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
544
545 static QV4::ReturnedValue method_get_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
546 static QV4::ReturnedValue method_set_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
547 static QV4::ReturnedValue method_get_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
548 static QV4::ReturnedValue method_set_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
549 static QV4::ReturnedValue method_get_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
550 static QV4::ReturnedValue method_set_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
551 static QV4::ReturnedValue method_get_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
552 static QV4::ReturnedValue method_set_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
553
554 // should these two be on the proto?
555#if QT_CONFIG(quick_path)
556 static QV4::ReturnedValue method_get_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
557 static QV4::ReturnedValue method_set_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
558#endif
559 static QV4::ReturnedValue method_get_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
560 static QV4::ReturnedValue method_set_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
561 static QV4::ReturnedValue method_get_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
562 static QV4::ReturnedValue method_set_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
563 static QV4::ReturnedValue method_get_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
564 static QV4::ReturnedValue method_set_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
565};
566
568
569
571{
573public:
575 {
576 QV4::Scope scope(engine);
578
579 o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
580 o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
581 o->defineDefaultProperty(QStringLiteral("moveTo"), method_moveTo, 0);
582 o->defineDefaultProperty(QStringLiteral("lineTo"), method_lineTo, 0);
583 o->defineDefaultProperty(QStringLiteral("caretBlinkRate"), method_caretBlinkRate, 0);
584 o->defineDefaultProperty(QStringLiteral("clip"), method_clip, 0);
585 o->defineDefaultProperty(QStringLiteral("setTransform"), method_setTransform, 0);
586 o->defineDefaultProperty(QStringLiteral("text"), method_text, 0);
587 o->defineDefaultProperty(QStringLiteral("roundedRect"), method_roundedRect, 0);
588 o->defineDefaultProperty(QStringLiteral("createPattern"), method_createPattern, 0);
589 o->defineDefaultProperty(QStringLiteral("stroke"), method_stroke, 0);
590 o->defineDefaultProperty(QStringLiteral("arc"), method_arc, 0);
591 o->defineDefaultProperty(QStringLiteral("createImageData"), method_createImageData, 0);
592 o->defineDefaultProperty(QStringLiteral("measureText"), method_measureText, 0);
593 o->defineDefaultProperty(QStringLiteral("ellipse"), method_ellipse, 0);
594 o->defineDefaultProperty(QStringLiteral("fill"), method_fill, 0);
595 o->defineDefaultProperty(QStringLiteral("save"), method_save, 0);
596 o->defineDefaultProperty(QStringLiteral("scale"), method_scale, 0);
597 o->defineDefaultProperty(QStringLiteral("drawImage"), method_drawImage, 0);
598 o->defineDefaultProperty(QStringLiteral("transform"), method_transform, 0);
599 o->defineDefaultProperty(QStringLiteral("fillText"), method_fillText, 0);
600 o->defineDefaultProperty(QStringLiteral("strokeText"), method_strokeText, 0);
601 o->defineDefaultProperty(QStringLiteral("translate"), method_translate, 0);
602 o->defineDefaultProperty(QStringLiteral("createRadialGradient"), method_createRadialGradient, 0);
603 o->defineDefaultProperty(QStringLiteral("shear"), method_shear, 0);
604 o->defineDefaultProperty(QStringLiteral("isPointInPath"), method_isPointInPath, 0);
605 o->defineDefaultProperty(QStringLiteral("bezierCurveTo"), method_bezierCurveTo, 0);
606 o->defineDefaultProperty(QStringLiteral("resetTransform"), method_resetTransform, 0);
607 o->defineDefaultProperty(QStringLiteral("arcTo"), method_arcTo, 0);
608 o->defineDefaultProperty(QStringLiteral("fillRect"), method_fillRect, 0);
609 o->defineDefaultProperty(QStringLiteral("createConicalGradient"), method_createConicalGradient, 0);
610 o->defineDefaultProperty(QStringLiteral("drawFocusRing"), method_drawFocusRing, 0);
611 o->defineDefaultProperty(QStringLiteral("beginPath"), method_beginPath, 0);
612 o->defineDefaultProperty(QStringLiteral("clearRect"), method_clearRect, 0);
613 o->defineDefaultProperty(QStringLiteral("rect"), method_rect, 0);
614 o->defineDefaultProperty(QStringLiteral("reset"), method_reset, 0);
615 o->defineDefaultProperty(QStringLiteral("rotate"), method_rotate, 0);
616 o->defineDefaultProperty(QStringLiteral("setCaretSelectionRect"), method_setCaretSelectionRect, 0);
617 o->defineDefaultProperty(QStringLiteral("putImageData"), method_putImageData, 0);
618 o->defineDefaultProperty(QStringLiteral("getImageData"), method_getImageData, 0);
619 o->defineDefaultProperty(QStringLiteral("createLinearGradient"), method_createLinearGradient, 0);
620 o->defineDefaultProperty(QStringLiteral("strokeRect"), method_strokeRect, 0);
621 o->defineDefaultProperty(QStringLiteral("closePath"), method_closePath, 0);
622 o->defineDefaultProperty(QStringLiteral("setLineDash"), method_setLineDash, 0);
623 o->defineDefaultProperty(QStringLiteral("getLineDash"), method_getLineDash, 0);
624 o->defineAccessorProperty(QStringLiteral("canvas"), QQuickJSContext2DPrototype::method_get_canvas, nullptr);
625
626 return o->d();
627 }
628
629 static QV4::ReturnedValue method_get_canvas(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
630 static QV4::ReturnedValue method_restore(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
631 static QV4::ReturnedValue method_reset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
632 static QV4::ReturnedValue method_save(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
633 static QV4::ReturnedValue method_rotate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
634 static QV4::ReturnedValue method_scale(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
635 static QV4::ReturnedValue method_translate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
636 static QV4::ReturnedValue method_setTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
637 static QV4::ReturnedValue method_transform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
638 static QV4::ReturnedValue method_resetTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
639 static QV4::ReturnedValue method_shear(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
640 static QV4::ReturnedValue method_createLinearGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
641 static QV4::ReturnedValue method_createRadialGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
642 static QV4::ReturnedValue method_createConicalGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
643 static QV4::ReturnedValue method_createPattern(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
644 static QV4::ReturnedValue method_clearRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
645 static QV4::ReturnedValue method_fillRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
646 static QV4::ReturnedValue method_strokeRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
647 static QV4::ReturnedValue method_arc(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
648 static QV4::ReturnedValue method_arcTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
649 static QV4::ReturnedValue method_beginPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
650 static QV4::ReturnedValue method_bezierCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
651 static QV4::ReturnedValue method_clip(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
652 static QV4::ReturnedValue method_closePath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
653 static QV4::ReturnedValue method_fill(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
654 static QV4::ReturnedValue method_lineTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
655 static QV4::ReturnedValue method_moveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
656 static QV4::ReturnedValue method_quadraticCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
657 static QV4::ReturnedValue method_rect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
658 static QV4::ReturnedValue method_roundedRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
659 static QV4::ReturnedValue method_ellipse(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
660 static QV4::ReturnedValue method_text(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
661 static QV4::ReturnedValue method_stroke(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
662 static QV4::ReturnedValue method_isPointInPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
663 static QV4::ReturnedValue method_drawFocusRing(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
664 static QV4::ReturnedValue method_setCaretSelectionRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
665 static QV4::ReturnedValue method_caretBlinkRate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
666 static QV4::ReturnedValue method_fillText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
667 static QV4::ReturnedValue method_strokeText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
668 static QV4::ReturnedValue method_measureText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
669 static QV4::ReturnedValue method_drawImage(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
670 static QV4::ReturnedValue method_createImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
671 static QV4::ReturnedValue method_getImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
672 static QV4::ReturnedValue method_putImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
673 static QV4::ReturnedValue method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
674 static QV4::ReturnedValue method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
675
676};
677
679
680
682{
685
686 static QV4::ReturnedValue gradient_proto_addColorStop(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
687};
688
689
690
692
694{
695 // weights 3x3 => delta 1
696 int delta = radius ? radius : qFloor(qSqrt(weights.size()) / qreal(2));
697 int filterDim = 2 * delta + 1;
698
699 QImage dst = QImage(src.size(), src.format());
700
701 int w = src.width();
702 int h = src.height();
703
704 const QRgb *sr = (const QRgb *)(src.constBits());
705 int srcStride = src.bytesPerLine() / 4;
706
707 QRgb *dr = (QRgb*)dst.bits();
708 int dstStride = dst.bytesPerLine() / 4;
709
710 for (int y = 0; y < h; ++y) {
711 for (int x = 0; x < w; ++x) {
712 int red = 0;
713 int green = 0;
714 int blue = 0;
715 int alpha = 0;
716
717 qreal redF = 0;
718 qreal greenF = 0;
719 qreal blueF = 0;
720 qreal alphaF = 0;
721
722 int sy = y;
723 int sx = x;
724
725 for (int cy = 0; cy < filterDim; ++cy) {
726 int scy = sy + cy - delta;
727
728 if (scy < 0 || scy >= h)
729 continue;
730
731 const QRgb *sry = sr + scy * srcStride;
732
733 for (int cx = 0; cx < filterDim; ++cx) {
734 int scx = sx + cx - delta;
735
736 if (scx < 0 || scx >= w)
737 continue;
738
739 const QRgb col = sry[scx];
740
741 if (radius) {
742 red += qRed(col);
743 green += qGreen(col);
744 blue += qBlue(col);
745 alpha += qAlpha(col);
746 } else {
747 qreal wt = weights[cy * filterDim + cx];
748
749 redF += qRed(col) * wt;
750 greenF += qGreen(col) * wt;
751 blueF += qBlue(col) * wt;
752 alphaF += qAlpha(col) * wt;
753 }
754 }
755 }
756
757 if (radius)
758 dr[x] = qRgba(qRound(red * weights[0]), qRound(green * weights[0]), qRound(blue * weights[0]), qRound(alpha * weights[0]));
759 else
760 dr[x] = qRgba(qRound(redF), qRound(greenF), qRound(blueF), qRound(alphaF));
761 }
762
763 dr += dstStride;
764 }
765
766 return dst;
767}
768
769void qt_image_boxblur(QImage& image, int radius, bool quality)
770{
771 int passes = quality? 3: 1;
772 int filterSize = 2 * radius + 1;
773 for (int i = 0; i < passes; ++i)
774 image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0 / (filterSize * filterSize), radius);
775}
776
778{
779 if (compositeOperator == QLatin1String("source-over")) {
781 } else if (compositeOperator == QLatin1String("source-out")) {
783 } else if (compositeOperator == QLatin1String("source-in")) {
785 } else if (compositeOperator == QLatin1String("source-atop")) {
787 } else if (compositeOperator == QLatin1String("destination-atop")) {
789 } else if (compositeOperator == QLatin1String("destination-in")) {
791 } else if (compositeOperator == QLatin1String("destination-out")) {
793 } else if (compositeOperator == QLatin1String("destination-over")) {
795 } else if (compositeOperator == QLatin1String("lighter")) {
797 } else if (compositeOperator == QLatin1String("copy")) {
799 } else if (compositeOperator == QLatin1String("xor")) {
801 } else if (compositeOperator == QLatin1String("qt-clear")) {
803 } else if (compositeOperator == QLatin1String("qt-destination")) {
805 } else if (compositeOperator == QLatin1String("qt-multiply")) {
807 } else if (compositeOperator == QLatin1String("qt-screen")) {
809 } else if (compositeOperator == QLatin1String("qt-overlay")) {
811 } else if (compositeOperator == QLatin1String("qt-darken")) {
813 } else if (compositeOperator == QLatin1String("qt-lighten")) {
815 } else if (compositeOperator == QLatin1String("qt-color-dodge")) {
817 } else if (compositeOperator == QLatin1String("qt-color-burn")) {
819 } else if (compositeOperator == QLatin1String("qt-hard-light")) {
821 } else if (compositeOperator == QLatin1String("qt-soft-light")) {
823 } else if (compositeOperator == QLatin1String("qt-difference")) {
825 } else if (compositeOperator == QLatin1String("qt-exclusion")) {
827 }
829}
830
832{
833 switch (op) {
835 return QStringLiteral("source-over");
837 return QStringLiteral("destination-over");
839 return QStringLiteral("qt-clear");
841 return QStringLiteral("copy");
843 return QStringLiteral("qt-destination");
845 return QStringLiteral("source-in");
847 return QStringLiteral("destination-in");
849 return QStringLiteral("source-out");
851 return QStringLiteral("destination-out");
853 return QStringLiteral("source-atop");
855 return QStringLiteral("destination-atop");
857 return QStringLiteral("xor");
859 return QStringLiteral("lighter");
861 return QStringLiteral("qt-multiply");
863 return QStringLiteral("qt-screen");
865 return QStringLiteral("qt-overlay");
867 return QStringLiteral("qt-darken");
869 return QStringLiteral("lighter");
871 return QStringLiteral("qt-color-dodge");
873 return QStringLiteral("qt-color-burn");
875 return QStringLiteral("qt-hard-light");
877 return QStringLiteral("qt-soft-light");
879 return QStringLiteral("qt-difference");
881 return QStringLiteral("qt-exclusion");
882 default:
883 break;
884 }
885 return QString();
886}
887
889{
892
893 static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty);
894 static bool virtualPut(QV4::Managed *m, QV4::PropertyKey id, const QV4::Value &value, Value *receiver);
895
896 static QV4::ReturnedValue proto_get_length(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
897};
898
900{
901 Object::init();
902 image = new QImage;
904 QV4::ScopedObject o(scope, this);
905 o->setArrayType(QV4::Heap::ArrayData::Custom);
906}
907
909
911{
913
914 static QV4::ReturnedValue method_get_width(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
915 static QV4::ReturnedValue method_get_height(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
916 static QV4::ReturnedValue method_get_data(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
917
918};
919
921{
922 Object::init();
923 pixelData = QV4::Value::undefinedValue();
924
925 QV4::Scope scope(internalClass->engine);
926 QV4::ScopedObject o(scope, this);
927
928 o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, nullptr);
929 o->defineAccessorProperty(QStringLiteral("height"), ::QQuickJSContext2DImageData::method_get_height, nullptr);
930 o->defineAccessorProperty(QStringLiteral("data"), ::QQuickJSContext2DImageData::method_get_data, nullptr);
931}
932
934
936{
937 QV4::Scope scope(v4);
938 QQuickContext2DEngineData *ed = engineData(scope.engine);
941 pixelData->setPrototypeOf(p);
942
943 if (image.isNull()) {
944 *pixelData->d()->image = QImage(qRound(w), qRound(h), QImage::Format_ARGB32);
945 pixelData->d()->image->fill(0x00000000);
946 } else {
947 // After qtbase 88e56d0932a3615231adf40d5ae033e742d72c33, the image size can be off by one.
948 Q_ASSERT(qAbs(image.width() - qRound(w * image.devicePixelRatio())) <= 1 && qAbs(image.height() - qRound(h * image.devicePixelRatio())) <= 1);
949 *pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
950 }
951
953 imageData->d()->pixelData = pixelData.asReturnedValue();
954 return imageData.asReturnedValue();
955}
956
957//static script functions
958
966{
967 QV4::Scope scope(b);
970
971 RETURN_RESULT(QV4::QObjectWrapper::wrap(scope.engine, r->d()->context()->canvas()));
972}
973
981{
982 QV4::Scope scope(b);
985
986 r->d()->context()->popState();
987 RETURN_RESULT(thisObject->asReturnedValue());
988}
989
995{
996 QV4::Scope scope(b);
999
1000 r->d()->context()->reset();
1001
1002 RETURN_RESULT(thisObject->asReturnedValue());
1003}
1004
1036{
1037 QV4::Scope scope(b);
1040
1041 r->d()->context()->pushState();
1042
1043 RETURN_RESULT(*thisObject);
1044}
1045
1046// transformations
1065{
1066 QV4::Scope scope(b);
1069
1070 if (argc >= 1)
1071 r->d()->context()->rotate(argv[0].toNumber());
1072 RETURN_RESULT(*thisObject);
1073}
1074
1093{
1094 QV4::Scope scope(b);
1097
1098
1099 if (argc >= 2)
1100 r->d()->context()->scale(argv[0].toNumber(), argv[1].toNumber());
1101 RETURN_RESULT(*thisObject);
1102
1103}
1104
1142{
1143 QV4::Scope scope(b);
1146
1147
1148 if (argc >= 6)
1149 r->d()->context()->setTransform( argv[0].toNumber()
1150 , argv[1].toNumber()
1151 , argv[2].toNumber()
1152 , argv[3].toNumber()
1153 , argv[4].toNumber()
1154 , argv[5].toNumber());
1155
1156 RETURN_RESULT(*thisObject);
1157
1158}
1159
1175{
1176 QV4::Scope scope(b);
1179
1180 if (argc >= 6)
1181 r->d()->context()->transform( argv[0].toNumber()
1182 , argv[1].toNumber()
1183 , argv[2].toNumber()
1184 , argv[3].toNumber()
1185 , argv[4].toNumber()
1186 , argv[5].toNumber());
1187
1188 RETURN_RESULT(*thisObject);
1189
1190}
1191
1202{
1203 QV4::Scope scope(b);
1206
1207 if (argc >= 2)
1208 r->d()->context()->translate(argv[0].toNumber(), argv[1].toNumber());
1209 RETURN_RESULT(*thisObject);
1210
1211}
1212
1213
1223{
1224 QV4::Scope scope(b);
1227
1228 r->d()->context()->setTransform(1, 0, 0, 1, 0, 0);
1229
1230 RETURN_RESULT(*thisObject);
1231
1232}
1233
1234
1242{
1243 QV4::Scope scope(b);
1246
1247 if (argc >= 2)
1248 r->d()->context()->shear(argv[0].toNumber(), argv[1].toNumber());
1249
1250 RETURN_RESULT(*thisObject);
1251
1252}
1253// compositing
1254
1263{
1264 QV4::Scope scope(b);
1267
1268 RETURN_RESULT(QV4::Encode(r->d()->context()->state.globalAlpha));
1269}
1270
1272{
1273 QV4::Scope scope(b);
1276
1277 double globalAlpha = argc ? argv[0].toNumber() : qt_qnan();
1278
1279
1280 if (!qt_is_finite(globalAlpha))
1282
1283 if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context()->state.globalAlpha != globalAlpha) {
1284 r->d()->context()->state.globalAlpha = globalAlpha;
1285 r->d()->context()->buffer()->setGlobalAlpha(r->d()->context()->state.globalAlpha);
1286 }
1288}
1289
1369{
1370 QV4::Scope scope(b);
1373
1374 RETURN_RESULT(scope.engine->newString(qt_composite_mode_to_string(r->d()->context()->state.globalCompositeOperation)));
1375}
1376
1378{
1379 QV4::Scope scope(b);
1382
1383 if (!argc)
1385
1386 QString mode = argv[0].toQString();
1388 if (cm == QPainter::CompositionMode_SourceOver && mode != QLatin1String("source-over"))
1390
1391 if (cm != r->d()->context()->state.globalCompositeOperation) {
1392 r->d()->context()->state.globalCompositeOperation = cm;
1393 r->d()->context()->buffer()->setGlobalCompositeOperation(cm);
1394 }
1395
1397}
1398
1399// colors and styles
1423{
1424 QV4::Scope scope(b);
1427
1428 const QColor color = r->d()->context()->state.fillStyle.color().toRgb();
1429 if (color.isValid()) {
1430 if (color.alpha() == 255)
1431 RETURN_RESULT(scope.engine->newString(color.name()));
1432 QString alphaString = QString::number(color.alphaF(), 'f');
1433 while (alphaString.endsWith(QLatin1Char('0')))
1434 alphaString.chop(1);
1435 if (alphaString.endsWith(QLatin1Char('.')))
1436 alphaString += QLatin1Char('0');
1437 QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString);
1439 }
1440 RETURN_RESULT(r->d()->context()->m_fillStyle.value());
1441}
1442
1444{
1445 QV4::Scope scope(b);
1448
1449 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1450
1451 if (value->as<Object>()) {
1452 QColor color = QV4::ExecutionEngine::toVariant(value, QMetaType::fromType<QColor>()).value<QColor>();
1453 if (color.isValid()) {
1454 r->d()->context()->state.fillStyle = color;
1455 r->d()->context()->buffer()->setFillStyle(color);
1456 r->d()->context()->m_fillStyle.set(scope.engine, value);
1457 } else {
1459 if (style && *style->d()->brush != r->d()->context()->state.fillStyle) {
1460 r->d()->context()->state.fillStyle = *style->d()->brush;
1461 r->d()->context()->buffer()->setFillStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
1462 r->d()->context()->m_fillStyle.set(scope.engine, value);
1463 r->d()->context()->state.fillPatternRepeatX = style->d()->patternRepeatX;
1464 r->d()->context()->state.fillPatternRepeatY = style->d()->patternRepeatY;
1465 }
1466 }
1467 } else if (value->isString()) {
1469 if (color.isValid() && r->d()->context()->state.fillStyle != QBrush(color)) {
1470 r->d()->context()->state.fillStyle = QBrush(color);
1471 r->d()->context()->buffer()->setFillStyle(r->d()->context()->state.fillStyle);
1472 r->d()->context()->m_fillStyle.set(scope.engine, value);
1473 }
1474 }
1476}
1477
1491{
1492 QV4::Scope scope(b);
1495
1496 RETURN_RESULT(scope.engine->fromVariant(r->d()->context()->state.fillRule));
1497}
1498
1500{
1501 QV4::Scope scope(b);
1504
1505 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1506
1507 if ((value->isString() && value->toQString() == QLatin1String("WindingFill"))
1508 || (value->isInt32() && value->integerValue() == Qt::WindingFill)) {
1509 r->d()->context()->state.fillRule = Qt::WindingFill;
1510 } else if ((value->isString() && value->toQStringNoThrow() == QLatin1String("OddEvenFill"))
1511 || (value->isInt32() && value->integerValue() == Qt::OddEvenFill)) {
1512 r->d()->context()->state.fillRule = Qt::OddEvenFill;
1513 } else {
1514 //error
1515 }
1516 r->d()->context()->m_path.setFillRule(r->d()->context()->state.fillRule);
1518}
1533{
1534 QV4::Scope scope(b);
1537
1538 const QColor color = r->d()->context()->state.strokeStyle.color().toRgb();
1539 if (color.isValid()) {
1540 if (color.alpha() == 255)
1541 RETURN_RESULT(scope.engine->newString(color.name()));
1542 QString alphaString = QString::number(color.alphaF(), 'f');
1543 while (alphaString.endsWith(QLatin1Char('0')))
1544 alphaString.chop(1);
1545 if (alphaString.endsWith(QLatin1Char('.')))
1546 alphaString += QLatin1Char('0');
1547 QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString);
1549 }
1550 RETURN_RESULT(r->d()->context()->m_strokeStyle.value());
1551}
1552
1554{
1555 QV4::Scope scope(b);
1558
1559 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1560
1561 if (value->as<Object>()) {
1562 QColor color = QV4::ExecutionEngine::toVariant(value, QMetaType::fromType<QColor>()).value<QColor>();
1563 if (color.isValid()) {
1564 r->d()->context()->state.strokeStyle = color;
1565 r->d()->context()->buffer()->setStrokeStyle(color);
1566 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1567 } else {
1569 if (style && *style->d()->brush != r->d()->context()->state.strokeStyle) {
1570 r->d()->context()->state.strokeStyle = *style->d()->brush;
1571 r->d()->context()->buffer()->setStrokeStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
1572 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1573 r->d()->context()->state.strokePatternRepeatX = style->d()->patternRepeatX;
1574 r->d()->context()->state.strokePatternRepeatY = style->d()->patternRepeatY;
1575 } else if (!style && r->d()->context()->state.strokeStyle != QBrush(QColor())) {
1576 // If there is no style object, then ensure that the strokeStyle is at least
1577 // QColor in case it was previously set
1578 r->d()->context()->state.strokeStyle = QBrush(QColor());
1579 r->d()->context()->buffer()->setStrokeStyle(r->d()->context()->state.strokeStyle);
1580 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1581 }
1582 }
1583 } else if (value->isString()) {
1585 if (color.isValid() && r->d()->context()->state.strokeStyle != QBrush(color)) {
1586 r->d()->context()->state.strokeStyle = QBrush(color);
1587 r->d()->context()->buffer()->setStrokeStyle(r->d()->context()->state.strokeStyle);
1588 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1589 }
1590 }
1592}
1593
1612{
1613 QV4::Scope scope(b);
1616
1617 if (argc >= 4) {
1618 qreal x0 = argv[0].toNumber();
1619 qreal y0 = argv[1].toNumber();
1620 qreal x1 = argv[2].toNumber();
1621 qreal y1 = argv[3].toNumber();
1622
1623 if (!qt_is_finite(x0)
1624 || !qt_is_finite(y0)
1625 || !qt_is_finite(x1)
1626 || !qt_is_finite(y1)) {
1627 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
1628 }
1629 QQuickContext2DEngineData *ed = engineData(scope.engine);
1630
1632 QV4::ScopedObject p(scope, ed->gradientProto.value());
1633 gradient->setPrototypeOf(p);
1634 *gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
1635 RETURN_RESULT(*gradient);
1636 }
1637
1638 RETURN_RESULT(*thisObject);
1639
1640}
1641
1659{
1660 QV4::Scope scope(b);
1663
1664 if (argc >= 6) {
1665 qreal x0 = argv[0].toNumber();
1666 qreal y0 = argv[1].toNumber();
1667 qreal r0 = argv[2].toNumber();
1668 qreal x1 = argv[3].toNumber();
1669 qreal y1 = argv[4].toNumber();
1670 qreal r1 = argv[5].toNumber();
1671
1672 if (!qt_is_finite(x0)
1673 || !qt_is_finite(y0)
1674 || !qt_is_finite(x1)
1675 || !qt_is_finite(r0)
1676 || !qt_is_finite(r1)
1677 || !qt_is_finite(y1)) {
1678 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
1679 }
1680
1681 if (r0 < 0 || r1 < 0)
1682 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
1683
1684 QQuickContext2DEngineData *ed = engineData(scope.engine);
1685
1687 QV4::ScopedObject p(scope, ed->gradientProto.value());
1688 gradient->setPrototypeOf(p);
1689 *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0);
1690 RETURN_RESULT(*gradient);
1691 }
1692
1693 RETURN_RESULT(*thisObject);
1694
1695}
1696
1713{
1714 QV4::Scope scope(b);
1717
1718 if (argc >= 3) {
1719 qreal x = argv[0].toNumber();
1720 qreal y = argv[1].toNumber();
1722 if (!qt_is_finite(x) || !qt_is_finite(y)) {
1723 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
1724 }
1725
1726 if (!qt_is_finite(angle)) {
1727 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
1728 }
1729
1730 QQuickContext2DEngineData *ed = engineData(scope.engine);
1731
1733 QV4::ScopedObject p(scope, ed->gradientProto.value());
1734 gradient->setPrototypeOf(p);
1735 *gradient->d()->brush = QConicalGradient(x, y, angle);
1736 RETURN_RESULT(*gradient);
1737 }
1738
1739 RETURN_RESULT(*thisObject);
1740
1741}
1787{
1788 QV4::Scope scope(b);
1789 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1791
1792 if (argc >= 2) {
1794
1796 argv[0], QMetaType::fromType<QColor>()).value<QColor>();
1797 if (color.isValid()) {
1798 int patternMode = argv[1].toInt32();
1800 if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) {
1801 style = static_cast<Qt::BrushStyle>(patternMode);
1802 }
1803 *pattern->d()->brush = QBrush(color, style);
1804 } else {
1805 QImage patternTexture;
1806
1807 if (const QV4::Object *o = argv[0].as<Object>()) {
1808 QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data")));
1809 QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s));
1810 if (!!pixelData) {
1811 patternTexture = *pixelData->d()->image;
1812 }
1813 } else {
1814 patternTexture = r->d()->context()->createPixmap(QUrl(argv[0].toQStringNoThrow()))->image();
1815 }
1816
1817 if (!patternTexture.isNull()) {
1818 pattern->d()->brush->setTextureImage(patternTexture);
1819
1820 QString repetition = argv[1].toQStringNoThrow();
1821 if (repetition == QLatin1String("repeat") || repetition.isEmpty()) {
1822 pattern->d()->patternRepeatX = true;
1823 pattern->d()->patternRepeatY = true;
1824 } else if (repetition == QLatin1String("repeat-x")) {
1825 pattern->d()->patternRepeatX = true;
1826 pattern->d()->patternRepeatY = false;
1827 } else if (repetition == QLatin1String("repeat-y")) {
1828 pattern->d()->patternRepeatX = false;
1829 pattern->d()->patternRepeatY = true;
1830 } else if (repetition == QLatin1String("no-repeat")) {
1831 pattern->d()->patternRepeatX = false;
1832 pattern->d()->patternRepeatY = false;
1833 } else {
1834 //TODO: exception: SYNTAX_ERR
1835 }
1836
1837 }
1838 }
1839
1841
1842 }
1844}
1845
1846// line styles
1866{
1867 QV4::Scope scope(b);
1868 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1870
1871 switch (r->d()->context()->state.lineCap) {
1872 case Qt::RoundCap:
1873 RETURN_RESULT(scope.engine->newString(QStringLiteral("round")));
1874 case Qt::SquareCap:
1875 RETURN_RESULT(scope.engine->newString(QStringLiteral("square")));
1876 case Qt::FlatCap:
1877 default:
1878 break;
1879 }
1881}
1882
1884{
1885 if (!argc)
1886 return QV4::Encode::undefined();
1887
1888 QV4::Scope scope(b);
1889 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1891
1892 QString lineCap = argv[0].toQString();
1894 if (lineCap == QLatin1String("round"))
1895 cap = Qt::RoundCap;
1896 else if (lineCap == QLatin1String("butt"))
1897 cap = Qt::FlatCap;
1898 else if (lineCap == QLatin1String("square"))
1900 else
1902
1903 if (cap != r->d()->context()->state.lineCap) {
1904 r->d()->context()->state.lineCap = cap;
1905 r->d()->context()->buffer()->setLineCap(cap);
1906 }
1908}
1909
1927{
1928 QV4::Scope scope(b);
1929 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1931
1932 switch (r->d()->context()->state.lineJoin) {
1933 case Qt::RoundJoin:
1934 RETURN_RESULT(scope.engine->newString(QStringLiteral("round")));
1935 case Qt::BevelJoin:
1936 RETURN_RESULT(scope.engine->newString(QStringLiteral("bevel")));
1937 case Qt::MiterJoin:
1938 default:
1939 break;
1940 }
1941 RETURN_RESULT(scope.engine->newString(QStringLiteral("miter")));
1942}
1943
1945{
1946 QV4::Scope scope(b);
1947 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1949
1950 if (!argc)
1952
1953 QString lineJoin = argv[0].toQString();
1954 Qt::PenJoinStyle join;
1955 if (lineJoin == QLatin1String("round"))
1956 join = Qt::RoundJoin;
1957 else if (lineJoin == QLatin1String("bevel"))
1958 join = Qt::BevelJoin;
1959 else if (lineJoin == QLatin1String("miter"))
1960 join = Qt::SvgMiterJoin;
1961 else
1963
1964 if (join != r->d()->context()->state.lineJoin) {
1965 r->d()->context()->state.lineJoin = join;
1966 r->d()->context()->buffer()->setLineJoin(join);
1967 }
1969}
1970
1976{
1977 QV4::Scope scope(b);
1978 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1980
1981 RETURN_RESULT(QV4::Encode(r->d()->context()->state.lineWidth));
1982}
1983
1985{
1986 QV4::Scope scope(b);
1987 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1989
1990 qreal w = argc ? argv[0].toNumber() : -1;
1991
1992 if (w > 0 && qt_is_finite(w) && w != r->d()->context()->state.lineWidth) {
1993 r->d()->context()->state.lineWidth = w;
1994 r->d()->context()->buffer()->setLineWidth(w);
1995 }
1997}
1998
2005{
2006 QV4::Scope scope(b);
2007 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2009
2010 RETURN_RESULT(QV4::Encode(r->d()->context()->state.miterLimit));
2011}
2012
2014{
2015 QV4::Scope scope(b);
2016 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2018
2019 qreal ml = argc ? argv[0].toNumber() : -1;
2020
2021 if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context()->state.miterLimit) {
2022 r->d()->context()->state.miterLimit = ml;
2023 r->d()->context()->buffer()->setMiterLimit(ml);
2024 }
2026}
2027
2036{
2037 QV4::Scope scope(b);
2038 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2040
2041 const QVector<qreal> pattern = r->d()->context()->state.lineDash;
2043 array->arrayReserve(pattern.size());
2044 for (int i = 0; i < pattern.size(); i++)
2046
2047 array->setArrayLengthUnchecked(pattern.size());
2048
2050}
2051
2077{
2078 QV4::Scope scope(b);
2079 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2081
2082 if (!argc)
2084
2085 QV4::ScopedArrayObject array(scope, argv[0]);
2086 if (!array)
2088
2089 QV4::ScopedValue v(scope);
2090 const uint arrayLength = array->getLength();
2091 QVector<qreal> dashes;
2092 dashes.reserve(arrayLength);
2093 for (uint i = 0; i < arrayLength; ++i) {
2094 v = array->get(i);
2095 const double number = v->toNumber();
2096
2097 if (!qt_is_finite(number) || (number < 0))
2099
2100 dashes.append(v->toNumber());
2101 }
2102 if (dashes.size() % 2 != 0) {
2103 dashes += dashes;
2104 }
2105
2106 r->d()->context()->state.lineDash = dashes;
2107 r->d()->context()->buffer()->setLineDash(dashes);
2108
2110}
2111
2122{
2123 QV4::Scope scope(b);
2124 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2126
2127 RETURN_RESULT(QV4::Encode(r->d()->context()->state.lineDashOffset));
2128}
2129
2131{
2132 QV4::Scope scope(b);
2133 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2135
2136 const qreal offset = argc ? argv[0].toNumber() : -1;
2137
2138 if (qt_is_finite(offset) && offset != r->d()->context()->state.lineDashOffset) {
2139 r->d()->context()->state.lineDashOffset = offset;
2140 r->d()->context()->buffer()->setLineDashOffset(offset);
2141 }
2143}
2144
2145
2146// shadows
2152{
2153 QV4::Scope scope(b);
2154 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2156
2157 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowBlur));
2158}
2159
2161{
2162 QV4::Scope scope(b);
2163 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2165
2166 qreal blur = argc ? argv[0].toNumber() : -1;
2167
2168 if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context()->state.shadowBlur) {
2169 r->d()->context()->state.shadowBlur = blur;
2170 r->d()->context()->buffer()->setShadowBlur(blur);
2171 }
2173}
2174
2180{
2181 QV4::Scope scope(b);
2182 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2184
2185 RETURN_RESULT(scope.engine->newString(r->d()->context()->state.shadowColor.name()));
2186}
2187
2189{
2190 QV4::Scope scope(b);
2191 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2193
2194 QColor color;
2195 if (argc)
2196 color = qt_color_from_string(argv[0]);
2197
2198 if (color.isValid() && color != r->d()->context()->state.shadowColor) {
2199 r->d()->context()->state.shadowColor = color;
2200 r->d()->context()->buffer()->setShadowColor(color);
2201 }
2203}
2204
2205
2213{
2214 QV4::Scope scope(b);
2215 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2217
2218 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowOffsetX));
2219}
2220
2222{
2223 QV4::Scope scope(b);
2224 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2226
2227 qreal offsetX = argc ? argv[0].toNumber() : qt_qnan();
2228 if (qt_is_finite(offsetX) && offsetX != r->d()->context()->state.shadowOffsetX) {
2229 r->d()->context()->state.shadowOffsetX = offsetX;
2230 r->d()->context()->buffer()->setShadowOffsetX(offsetX);
2231 }
2233}
2241{
2242 QV4::Scope scope(b);
2243 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2245
2246 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowOffsetY));
2247}
2248
2250{
2251 QV4::Scope scope(b);
2252 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2254
2255 qreal offsetY = argc ? argv[0].toNumber() : qt_qnan();
2256 if (qt_is_finite(offsetY) && offsetY != r->d()->context()->state.shadowOffsetY) {
2257 r->d()->context()->state.shadowOffsetY = offsetY;
2258 r->d()->context()->buffer()->setShadowOffsetY(offsetY);
2259 }
2261}
2262
2263#if QT_CONFIG(quick_path)
2264QV4::ReturnedValue QQuickJSContext2D::method_get_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
2265{
2266 QV4::Scope scope(b);
2267 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2269
2270 RETURN_RESULT(r->d()->context()->m_v4path.value());
2271}
2272
2273QV4::ReturnedValue QQuickJSContext2D::method_set_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
2274{
2275 QV4::Scope scope(b);
2276 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2278
2279 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
2280 r->d()->context()->beginPath();
2281 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, value);
2282 if (!!qobjectWrapper) {
2283 if (QQuickPath *path = qobject_cast<QQuickPath*>(qobjectWrapper->object()))
2284 r->d()->context()->m_path = path->path();
2285 } else {
2286 QString path =value->toQStringNoThrow();
2287 QQuickSvgParser::parsePathDataFast(path, r->d()->context()->m_path);
2288 }
2289 r->d()->context()->m_v4path.set(scope.engine, value);
2291}
2292#endif // QT_CONFIG(quick_path)
2293
2294//rects
2302{
2303 QV4::Scope scope(b);
2304 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2306
2307
2308 if (argc >= 4)
2309 r->d()->context()->clearRect(argv[0].toNumber(),
2310 argv[1].toNumber(),
2311 argv[2].toNumber(),
2312 argv[3].toNumber());
2313
2314 RETURN_RESULT(*thisObject);
2315
2316}
2325{
2326 QV4::Scope scope(b);
2327 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2329
2330 if (argc >= 4)
2331 r->d()->context()->fillRect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2332 RETURN_RESULT(*thisObject);
2333
2334}
2335
2345{
2346 QV4::Scope scope(b);
2347 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2349
2350 if (argc >= 4)
2351 r->d()->context()->strokeRect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2352
2353 RETURN_RESULT(*thisObject);
2354
2355}
2356
2357// Complex shapes (paths) API
2379{
2380 QV4::Scope scope(b);
2381 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2383
2384 if (argc >= 5) {
2385 bool antiClockwise = false;
2386
2387 if (argc == 6)
2388 antiClockwise = argv[5].toBoolean();
2389
2390 qreal radius = argv[2].toNumber();
2391
2392 if (qt_is_finite(radius) && radius < 0)
2393 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
2394
2395 r->d()->context()->arc(argv[0].toNumber(),
2396 argv[1].toNumber(),
2397 radius,
2398 argv[3].toNumber(),
2399 argv[4].toNumber(),
2400 antiClockwise);
2401 }
2402
2403 RETURN_RESULT(*thisObject);
2404
2405}
2406
2431{
2432 QV4::Scope scope(b);
2433 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2435
2436 if (argc >= 5) {
2437 qreal radius = argv[4].toNumber();
2438
2439 if (qt_is_finite(radius) && radius < 0)
2440 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
2441
2442 r->d()->context()->arcTo(argv[0].toNumber(),
2443 argv[1].toNumber(),
2444 argv[2].toNumber(),
2445 argv[3].toNumber(),
2446 radius);
2447 }
2448
2449 RETURN_RESULT(*thisObject);
2450
2451}
2452
2459{
2460 QV4::Scope scope(b);
2461 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2463
2464 r->d()->context()->beginPath();
2465
2466 RETURN_RESULT(*thisObject);
2467
2468}
2469
2493{
2494 QV4::Scope scope(b);
2495 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2497
2498 if (argc >= 6) {
2499 qreal cp1x = argv[0].toNumber();
2500 qreal cp1y = argv[1].toNumber();
2501 qreal cp2x = argv[2].toNumber();
2502 qreal cp2y = argv[3].toNumber();
2503 qreal x = argv[4].toNumber();
2504 qreal y = argv[5].toNumber();
2505
2506 if (!qt_is_finite(cp1x) || !qt_is_finite(cp1y) || !qt_is_finite(cp2x) || !qt_is_finite(cp2y) || !qt_is_finite(x) || !qt_is_finite(y))
2508
2509 r->d()->context()->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
2510 }
2511 RETURN_RESULT(*thisObject);
2512}
2513
2539{
2540 QV4::Scope scope(b);
2541 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2543
2544 r->d()->context()->clip();
2545 RETURN_RESULT(*thisObject);
2546}
2547
2556{
2557 QV4::Scope scope(b);
2558 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2560
2561 r->d()->context()->closePath();
2562
2563 RETURN_RESULT(*thisObject);
2564}
2565
2576{
2577 QV4::Scope scope(b);
2578 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2580 r->d()->context()->fill();
2581 RETURN_RESULT(*thisObject);
2582}
2583
2590{
2591 QV4::Scope scope(b);
2592 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2594
2595 if (argc >= 2) {
2596 qreal x = argv[0].toNumber();
2597 qreal y = argv[1].toNumber();
2598
2599 if (!qt_is_finite(x) || !qt_is_finite(y))
2601
2602 r->d()->context()->lineTo(x, y);
2603 }
2604
2605 RETURN_RESULT(*thisObject);
2606}
2607
2614{
2615 QV4::Scope scope(b);
2616 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2618
2619 if (argc >= 2) {
2620 qreal x = argv[0].toNumber();
2621 qreal y = argv[1].toNumber();
2622
2623 if (!qt_is_finite(x) || !qt_is_finite(y))
2625 r->d()->context()->moveTo(x, y);
2626 }
2627
2628 RETURN_RESULT(*thisObject);
2629}
2630
2640{
2641 QV4::Scope scope(b);
2642 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2644
2645 if (argc >= 4) {
2646 qreal cpx = argv[0].toNumber();
2647 qreal cpy = argv[1].toNumber();
2648 qreal x = argv[2].toNumber();
2649 qreal y = argv[3].toNumber();
2650
2651 if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y))
2653
2654 r->d()->context()->quadraticCurveTo(cpx, cpy, x, y);
2655 }
2656
2657 RETURN_RESULT(*thisObject);
2658}
2659
2667{
2668 QV4::Scope scope(b);
2669 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2671
2672 if (argc >= 4)
2673 r->d()->context()->rect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2674 RETURN_RESULT(*thisObject);
2675
2676}
2677
2686{
2687 QV4::Scope scope(b);
2688 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2690
2691 if (argc >= 6)
2692 r->d()->context()->roundedRect(argv[0].toNumber()
2693 , argv[1].toNumber()
2694 , argv[2].toNumber()
2695 , argv[3].toNumber()
2696 , argv[4].toNumber()
2697 , argv[5].toNumber());
2698 RETURN_RESULT(*thisObject);
2699
2700}
2701
2713{
2714 QV4::Scope scope(b);
2715 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2717
2718 if (argc >= 4)
2719 r->d()->context()->ellipse(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2720
2721 RETURN_RESULT(*thisObject);
2722
2723}
2724
2735{
2736 QV4::Scope scope(b);
2737 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2739
2740 if (argc >= 3) {
2741 qreal x = argv[1].toNumber();
2742 qreal y = argv[2].toNumber();
2743
2744 if (!qt_is_finite(x) || !qt_is_finite(y))
2746 r->d()->context()->text(argv[0].toQStringNoThrow(), x, y);
2747 }
2748
2749 RETURN_RESULT(*thisObject);
2750}
2751
2760{
2761 QV4::Scope scope(b);
2762 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2764
2765 r->d()->context()->stroke();
2766 RETURN_RESULT(*thisObject);
2767
2768}
2769
2778{
2779 QV4::Scope scope(b);
2780 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2782
2783 bool pointInPath = false;
2784 if (argc >= 2)
2785 pointInPath = r->d()->context()->isPointInPath(argv[0].toNumber(), argv[1].toNumber());
2787}
2788
2790{
2791 QV4::Scope scope(b);
2792 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
2793}
2794
2796{
2797 QV4::Scope scope(b);
2798 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
2799}
2800
2802{
2803 QV4::Scope scope(b);
2804 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
2805}
2806
2831{
2832 QV4::Scope scope(b);
2833 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2835
2836 RETURN_RESULT(scope.engine->newString(r->d()->context()->state.font.toString()));
2837}
2838
2840{
2841 QV4::Scope scope(b);
2842 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2844
2846 if (scope.hasException())
2848 QFont font = qt_font_from_string(s->toQString(), r->d()->context()->state.font);
2849 if (font != r->d()->context()->state.font) {
2850 r->d()->context()->state.font = font;
2851 }
2853}
2854
2871{
2872 QV4::Scope scope(b);
2873 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2875
2876 switch (r->d()->context()->state.textAlign) {
2882 RETURN_RESULT(scope.engine->newString(QStringLiteral("right")));
2884 RETURN_RESULT(scope.engine->newString(QStringLiteral("center")));
2886 default:
2887 break;
2888 }
2889 RETURN_RESULT(scope.engine->newString(QStringLiteral("start")));
2890}
2891
2893{
2894 QV4::Scope scope(b);
2895 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2897
2899 if (scope.hasException())
2901 QString textAlign = s->toQString();
2902
2904 if (textAlign == QLatin1String("start"))
2906 else if (textAlign == QLatin1String("end"))
2908 else if (textAlign == QLatin1String("left"))
2910 else if (textAlign == QLatin1String("right"))
2912 else if (textAlign == QLatin1String("center"))
2914 else
2916
2917 if (ta != r->d()->context()->state.textAlign)
2918 r->d()->context()->state.textAlign = ta;
2919
2921}
2922
2938{
2939 QV4::Scope scope(b);
2940 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2942
2943 switch (r->d()->context()->state.textBaseline) {
2945 RETURN_RESULT(scope.engine->newString(QStringLiteral("hanging")));
2949 RETURN_RESULT(scope.engine->newString(QStringLiteral("bottom")));
2951 RETURN_RESULT(scope.engine->newString(QStringLiteral("middle")));
2953 default:
2954 break;
2955 }
2956 RETURN_RESULT(scope.engine->newString(QStringLiteral("alphabetic")));
2957}
2958
2960{
2961 QV4::Scope scope(b);
2962 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2965 if (scope.hasException())
2967 QString textBaseline = s->toQString();
2968
2970 if (textBaseline == QLatin1String("alphabetic"))
2972 else if (textBaseline == QLatin1String("hanging"))
2974 else if (textBaseline == QLatin1String("top"))
2976 else if (textBaseline == QLatin1String("bottom"))
2978 else if (textBaseline == QLatin1String("middle"))
2980 else
2982
2983 if (tb != r->d()->context()->state.textBaseline)
2984 r->d()->context()->state.textBaseline = tb;
2985
2987}
2988
3000{
3001 QV4::Scope scope(b);
3002 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3004
3005 if (argc >= 3) {
3006 qreal x = argv[1].toNumber();
3007 qreal y = argv[2].toNumber();
3008 if (!qt_is_finite(x) || !qt_is_finite(y))
3010 QPainterPath textPath = r->d()->context()->createTextGlyphs(x, y, argv[0].toQStringNoThrow());
3011 r->d()->context()->buffer()->fill(textPath);
3012 }
3013
3014 RETURN_RESULT(*thisObject);
3015}
3027{
3028 QV4::Scope scope(b);
3029 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3031
3032 if (argc >= 3)
3033 r->d()->context()->drawText(argv[0].toQStringNoThrow(), argv[1].toNumber(), argv[2].toNumber(), false);
3034
3035 RETURN_RESULT(*thisObject);
3036}
3037
3046{
3047 QV4::Scope scope(b);
3048 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3050
3051 if (argc >= 1) {
3052 QFontMetrics fm(r->d()->context()->state.font);
3054 QV4::ScopedObject tm(scope, scope.engine->newObject());
3055 tm->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("width"))).getPointer(),
3057 RETURN_RESULT(*tm);
3058 }
3060}
3061
3062// drawing images
3122{
3123 QV4::Scope scope(b);
3124 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3126
3127 qreal sx, sy, sw, sh, dx, dy, dw, dh;
3128
3129 if (!argc)
3131
3132 //FIXME:This function should be moved to QQuickContext2D::drawImage(...)
3133 if (!r->d()->context()->state.invertibleCTM)
3135
3137
3138 QV4::ScopedValue arg(scope, argv[0]);
3139 if (arg->isString()) {
3140 QUrl url(arg->toQString());
3141 if (!url.isValid())
3142 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3143
3144 pixmap = r->d()->context()->createPixmap(url);
3145 } else if (arg->isObject()) {
3146 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, arg);
3147 if (!!qobjectWrapper) {
3148 if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
3149 pixmap = r->d()->context()->createPixmap(imageItem->source());
3150 } else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
3151 QImage img = canvas->toImage();
3152 if (!img.isNull())
3153 pixmap.adopt(new QQuickCanvasPixmap(img));
3154 } else {
3155 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3156 }
3157 } else {
3159 if (!!imageData) {
3161 if (pix && !pix->d()->image->isNull()) {
3162 pixmap.adopt(new QQuickCanvasPixmap(*pix->d()->image));
3163 } else {
3164 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3165 }
3166 } else {
3167 QUrl url(arg->toQStringNoThrow());
3168 if (url.isValid())
3169 pixmap = r->d()->context()->createPixmap(url);
3170 else
3171 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3172 }
3173 }
3174 } else {
3175 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3176 }
3177
3178 if (pixmap.isNull() || !pixmap->isValid())
3180
3181 if (argc >= 9) {
3182 sx = argv[1].toNumber();
3183 sy = argv[2].toNumber();
3184 sw = argv[3].toNumber();
3185 sh = argv[4].toNumber();
3186 dx = argv[5].toNumber();
3187 dy = argv[6].toNumber();
3188 dw = argv[7].toNumber();
3189 dh = argv[8].toNumber();
3190 } else if (argc >= 5) {
3191 sx = 0;
3192 sy = 0;
3193 sw = pixmap->width();
3194 sh = pixmap->height();
3195 dx = argv[1].toNumber();
3196 dy = argv[2].toNumber();
3197 dw = argv[3].toNumber();
3198 dh = argv[4].toNumber();
3199 } else if (argc >= 3) {
3200 dx = argv[1].toNumber();
3201 dy = argv[2].toNumber();
3202 sx = 0;
3203 sy = 0;
3204 sw = pixmap->width();
3205 sh = pixmap->height();
3206 dw = sw;
3207 dh = sh;
3208 } else {
3210 }
3211
3212 if (!qt_is_finite(sx)
3213 || !qt_is_finite(sy)
3214 || !qt_is_finite(sw)
3215 || !qt_is_finite(sh)
3216 || !qt_is_finite(dx)
3217 || !qt_is_finite(dy)
3218 || !qt_is_finite(dw)
3219 || !qt_is_finite(dh))
3221
3222 if (sx < 0
3223 || sy < 0
3224 || sw == 0
3225 || sh == 0
3226 || sx + sw > pixmap->width()
3227 || sy + sh > pixmap->height()
3228 || sx + sw < 0 || sy + sh < 0) {
3229 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
3230 }
3231
3232 r->d()->context()->buffer()->drawPixmap(pixmap, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh));
3233
3234 RETURN_RESULT(*thisObject);
3235}
3236
3237// pixel manipulation
3262{
3263 QV4::Scope scope(b);
3265 if (!imageData)
3268 int width = r ? r->d()->image->width() : 0;
3270}
3271
3277{
3278 QV4::Scope scope(b);
3280 if (!imageData)
3283 int height = r ? r->d()->image->height() : 0;
3285}
3286
3292{
3293 QV4::Scope scope(b);
3295 if (!imageData)
3297 RETURN_RESULT(imageData->d()->pixelData);
3298}
3299
3319{
3320 QV4::Scope scope(b);
3322 if (!r || r->d()->image->isNull())
3324
3325 RETURN_RESULT(QV4::Encode(r->d()->image->width() * r->d()->image->height() * 4));
3326}
3327
3329{
3330 if (!id.isArrayIndex())
3331 return QV4::Object::virtualGet(m, id, receiver, hasProperty);
3332
3333 uint index = id.asArrayIndex();
3335 QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine();
3336 QV4::Scope scope(v4);
3338
3339 if (index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4)) {
3340 if (hasProperty)
3341 *hasProperty = true;
3342 const quint32 w = r->d()->image->width();
3343 const quint32 row = (index / 4) / w;
3344 const quint32 col = (index / 4) % w;
3345 const QRgb* pixel = reinterpret_cast<const QRgb*>(r->d()->image->constScanLine(row));
3346 pixel += col;
3347 switch (index % 4) {
3348 case 0:
3349 return QV4::Encode(qRed(*pixel));
3350 case 1:
3351 return QV4::Encode(qGreen(*pixel));
3352 case 2:
3353 return QV4::Encode(qBlue(*pixel));
3354 case 3:
3355 return QV4::Encode(qAlpha(*pixel));
3356 }
3357 }
3358
3359 if (hasProperty)
3360 *hasProperty = false;
3361 return QV4::Encode::undefined();
3362}
3363
3365{
3366 if (!id.isArrayIndex())
3367 return Object::virtualPut(m, id, value, receiver);
3368
3371 QV4::Scope scope(v4);
3372 if (scope.hasException())
3373 return false;
3374
3375 uint index = id.asArrayIndex();
3377
3378 const int v = value.toInt32();
3379 if (r && index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4) && v >= 0 && v <= 255) {
3380 const quint32 w = r->d()->image->width();
3381 const quint32 row = (index / 4) / w;
3382 const quint32 col = (index / 4) % w;
3383
3384 QRgb* pixel = reinterpret_cast<QRgb*>(r->d()->image->scanLine(row));
3385 pixel += col;
3386 switch (index % 4) {
3387 case 0:
3388 *pixel = qRgba(v, qGreen(*pixel), qBlue(*pixel), qAlpha(*pixel));
3389 break;
3390 case 1:
3391 *pixel = qRgba(qRed(*pixel), v, qBlue(*pixel), qAlpha(*pixel));
3392 break;
3393 case 2:
3394 *pixel = qRgba(qRed(*pixel), qGreen(*pixel), v, qAlpha(*pixel));
3395 break;
3396 case 3:
3397 *pixel = qRgba(qRed(*pixel), qGreen(*pixel), qBlue(*pixel), v);
3398 break;
3399 }
3400 return true;
3401 }
3402
3403 return false;
3404}
3427{
3428 QV4::Scope scope(b);
3431
3432 if (argc == 1) {
3433 QV4::ScopedValue arg0(scope, argv[0]);
3434 QV4::Scoped<QQuickJSContext2DImageData> imgData(scope, arg0);
3435 if (!!imgData) {
3436 QV4::Scoped<QQuickJSContext2DPixelData> pa(scope, imgData->d()->pixelData.as<QQuickJSContext2DPixelData>());
3437 if (pa) {
3438 qreal w = pa->d()->image->width();
3439 qreal h = pa->d()->image->height();
3441 }
3442 } else if (arg0->isString()) {
3443 QImage image = r->d()->context()->createPixmap(QUrl(arg0->toQStringNoThrow()))->image();
3444 RETURN_RESULT(qt_create_image_data(image.width(), image.height(), scope.engine, image));
3445 }
3446 } else if (argc == 2) {
3447 qreal w = argv[0].toNumber();
3448 qreal h = argv[1].toNumber();
3449
3450 if (!qt_is_finite(w) || !qt_is_finite(h))
3451 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
3452
3453 if (w > 0 && h > 0)
3455 else
3456 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments");
3457 }
3459}
3460
3468{
3469 QV4::Scope scope(b);
3472
3473 if (argc >= 4) {
3474 qreal x = argv[0].toNumber();
3475 qreal y = argv[1].toNumber();
3476 qreal w = argv[2].toNumber();
3477 qreal h = argv[3].toNumber();
3478 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3479 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
3480
3481 if (w <= 0 || h <= 0)
3482 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments");
3483
3484 QImage image = r->d()->context()->canvas()->toImage(QRectF(x, y, w, h));
3486 }
3488}
3489
3500{
3501 QV4::Scope scope(b);
3504 if (argc < 7)
3506
3507 QV4::ScopedValue arg0(scope, argv[0]);
3508 if (!arg0->isObject())
3509 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch");
3510
3511 qreal dx = argv[1].toNumber();
3512 qreal dy = argv[2].toNumber();
3513 qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
3514
3515 if (!qt_is_finite(dx) || !qt_is_finite(dy))
3516 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
3517
3519 if (!imageData)
3521
3522 QV4::Scoped<QQuickJSContext2DPixelData> pixelArray(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
3523 if (pixelArray) {
3524 w = pixelArray->d()->image->width();
3525 h = pixelArray->d()->image->height();
3526
3527 if (argc == 7) {
3528 dirtyX = argv[3].toNumber();
3529 dirtyY = argv[4].toNumber();
3530 dirtyWidth = argv[5].toNumber();
3531 dirtyHeight = argv[6].toNumber();
3532
3533 if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight))
3534 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
3535
3536
3537 if (dirtyWidth < 0) {
3538 dirtyX = dirtyX+dirtyWidth;
3539 dirtyWidth = -dirtyWidth;
3540 }
3541
3542 if (dirtyHeight < 0) {
3543 dirtyY = dirtyY+dirtyHeight;
3544 dirtyHeight = -dirtyHeight;
3545 }
3546
3547 if (dirtyX < 0) {
3548 dirtyWidth = dirtyWidth+dirtyX;
3549 dirtyX = 0;
3550 }
3551
3552 if (dirtyY < 0) {
3553 dirtyHeight = dirtyHeight+dirtyY;
3554 dirtyY = 0;
3555 }
3556
3557 if (dirtyX+dirtyWidth > w) {
3558 dirtyWidth = w - dirtyX;
3559 }
3560
3561 if (dirtyY+dirtyHeight > h) {
3562 dirtyHeight = h - dirtyY;
3563 }
3564
3565 if (dirtyWidth <=0 || dirtyHeight <= 0)
3567 } else {
3568 dirtyX = 0;
3569 dirtyY = 0;
3570 dirtyWidth = w;
3571 dirtyHeight = h;
3572 }
3573
3574 QImage image = pixelArray->d()->image->copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
3575 r->d()->context()->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight));
3576 }
3577
3578 RETURN_RESULT(*thisObject);
3579}
3580
3604{
3605 QV4::Scope scope(b);
3606 QV4::Scoped<QQuickContext2DStyle> style(scope, thisObject->as<QQuickContext2DStyle>());
3607 if (!style)
3608 THROW_GENERIC_ERROR("Not a CanvasGradient object");
3609
3610 if (argc == 2) {
3611
3612 if (!style->d()->brush->gradient())
3613 THROW_GENERIC_ERROR("Not a valid CanvasGradient object, can't get the gradient information");
3614 QGradient gradient = *(style->d()->brush->gradient());
3615 qreal pos = argv[0].toNumber();
3616 QColor color;
3617
3618 if (argv[1].as<Object>()) {
3620 argv[1], QMetaType::fromType<QColor>()).value<QColor>();
3621 } else {
3622 color = qt_color_from_string(argv[1]);
3623 }
3624 if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) {
3625 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
3626 }
3627
3628 if (color.isValid()) {
3629 gradient.setColorAt(pos, color);
3630 } else {
3631 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string");
3632 }
3633 *style->d()->brush = gradient;
3634 }
3635
3636 return thisObject->asReturnedValue();
3637}
3638
3640{
3641 if (!state.invertibleCTM)
3642 return;
3643
3644 if (!qt_is_finite(x) || !qt_is_finite(y))
3645 return;
3646
3647 QTransform newTransform = state.matrix;
3648 newTransform.scale(x, y);
3649
3650 if (!newTransform.isInvertible()) {
3651 state.invertibleCTM = false;
3652 return;
3653 }
3654
3655 state.matrix = newTransform;
3656 buffer()->updateMatrix(state.matrix);
3657 m_path = QTransform().scale(1.0 / x, 1.0 / y).map(m_path);
3658}
3659
3661{
3662 if (!state.invertibleCTM)
3663 return;
3664
3665 if (!qt_is_finite(angle))
3666 return;
3667
3668 QTransform newTransform =state.matrix;
3669 newTransform.rotate(qRadiansToDegrees(angle));
3670
3671 if (!newTransform.isInvertible()) {
3672 state.invertibleCTM = false;
3673 return;
3674 }
3675
3676 state.matrix = newTransform;
3677 buffer()->updateMatrix(state.matrix);
3678 m_path = QTransform().rotate(-qRadiansToDegrees(angle)).map(m_path);
3679}
3680
3682{
3683 if (!state.invertibleCTM)
3684 return;
3685
3686 if (!qt_is_finite(h) || !qt_is_finite(v))
3687 return ;
3688
3689 QTransform newTransform = state.matrix;
3690 newTransform.shear(h, v);
3691
3692 if (!newTransform.isInvertible()) {
3693 state.invertibleCTM = false;
3694 return;
3695 }
3696
3697 state.matrix = newTransform;
3698 buffer()->updateMatrix(state.matrix);
3699 m_path = QTransform().shear(-h, -v).map(m_path);
3700}
3701
3703{
3704 if (!state.invertibleCTM)
3705 return;
3706
3707 if (!qt_is_finite(x) || !qt_is_finite(y))
3708 return ;
3709
3710 QTransform newTransform = state.matrix;
3711 newTransform.translate(x, y);
3712
3713 if (!newTransform.isInvertible()) {
3714 state.invertibleCTM = false;
3715 return;
3716 }
3717
3718 state.matrix = newTransform;
3719 buffer()->updateMatrix(state.matrix);
3720 m_path = QTransform().translate(-x, -y).map(m_path);
3721}
3722
3724{
3725 if (!state.invertibleCTM)
3726 return;
3727
3729 return;
3730
3731 QTransform transform(a, b, c, d, e, f);
3732 QTransform newTransform = state.matrix * transform;
3733
3734 if (!newTransform.isInvertible()) {
3735 state.invertibleCTM = false;
3736 return;
3737 }
3738 state.matrix = newTransform;
3739 buffer()->updateMatrix(state.matrix);
3740 m_path = transform.inverted().map(m_path);
3741}
3742
3744{
3746 return;
3747
3748 QTransform ctm = state.matrix;
3749 if (!ctm.isInvertible())
3750 return;
3751
3752 state.matrix = ctm.inverted() * state.matrix;
3753 m_path = ctm.map(m_path);
3754 state.invertibleCTM = true;
3755 transform(a, b, c, d, e, f);
3756}
3757
3759{
3760 if (!state.invertibleCTM)
3761 return;
3762
3763 if (!m_path.elementCount())
3764 return;
3765
3766 m_path.setFillRule(state.fillRule);
3767 buffer()->fill(m_path);
3768}
3769
3771{
3772 if (!state.invertibleCTM)
3773 return;
3774
3775 QPainterPath clipPath = m_path;
3776 clipPath.closeSubpath();
3777 if (state.clip) {
3778 state.clipPath = clipPath.intersected(state.clipPath);
3779 } else {
3780 state.clip = true;
3781 state.clipPath = clipPath;
3782 }
3783 buffer()->clip(state.clip, state.clipPath);
3784}
3785
3787{
3788 if (!state.invertibleCTM)
3789 return;
3790
3791 if (!m_path.elementCount())
3792 return;
3793
3794 buffer()->stroke(m_path);
3795}
3796
3798{
3799 if (!state.invertibleCTM)
3800 return;
3801
3802 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3803 return;
3804
3805 buffer()->fillRect(QRectF(x, y, w, h));
3806}
3807
3809{
3810 if (!state.invertibleCTM)
3811 return;
3812
3813 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3814 return;
3815
3816 buffer()->strokeRect(QRectF(x, y, w, h));
3817}
3818
3820{
3821 if (!state.invertibleCTM)
3822 return;
3823
3824 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3825 return;
3826
3827 buffer()->clearRect(QRectF(x, y, w, h));
3828}
3829
3831{
3832 if (!state.invertibleCTM)
3833 return;
3834
3835 if (!qt_is_finite(x) || !qt_is_finite(y))
3836 return;
3837
3838 QPainterPath textPath = createTextGlyphs(x, y, text);
3839 if (fill)
3840 buffer()->fill(textPath);
3841 else
3842 buffer()->stroke(textPath);
3843}
3844
3845
3847{
3848 if (!m_path.elementCount())
3849 return;
3850 m_path = QPainterPath();
3851}
3852
3854{
3855 if (!m_path.elementCount())
3856 return;
3857
3858 QRectF boundRect = m_path.boundingRect();
3859 if (boundRect.width() || boundRect.height())
3860 m_path.closeSubpath();
3861 //FIXME:QPainterPath set the current point to (0,0) after close subpath
3862 //should be the first point of the previous subpath
3863}
3864
3866{
3867 if (!state.invertibleCTM)
3868 return;
3869
3870 //FIXME: moveTo should not close the previous subpath
3871 m_path.moveTo(QPointF(x, y));
3872}
3873
3875{
3876 if (!state.invertibleCTM)
3877 return;
3878
3879 QPointF pt(x, y);
3880
3881 if (!m_path.elementCount())
3882 m_path.moveTo(pt);
3883 else if (m_path.currentPosition() != pt)
3884 m_path.lineTo(pt);
3885}
3886
3888 qreal x, qreal y)
3889{
3890 if (!state.invertibleCTM)
3891 return;
3892
3893 if (!m_path.elementCount())
3894 m_path.moveTo(QPointF(cpx, cpy));
3895
3896 QPointF pt(x, y);
3897 if (m_path.currentPosition() != pt)
3898 m_path.quadTo(QPointF(cpx, cpy), pt);
3899}
3900
3902 qreal cp2x, qreal cp2y,
3903 qreal x, qreal y)
3904{
3905 if (!state.invertibleCTM)
3906 return;
3907
3908 if (!m_path.elementCount())
3909 m_path.moveTo(QPointF(cp1x, cp1y));
3910
3911 QPointF pt(x, y);
3912 if (m_path.currentPosition() != pt)
3913 m_path.cubicTo(QPointF(cp1x, cp1y), QPointF(cp2x, cp2y), pt);
3914}
3915
3917{
3918 QPointF p0(m_path.currentPosition());
3919
3920 QPointF p1p0((p0.x() - p1.x()), (p0.y() - p1.y()));
3921 QPointF p1p2((p2.x() - p1.x()), (p2.y() - p1.y()));
3922 qreal p1p0_length = std::hypot(p1p0.x(), p1p0.y());
3923 qreal p1p2_length = std::hypot(p1p2.x(), p1p2.y());
3924
3925 qreal cos_phi = QPointF::dotProduct(p1p0, p1p2) / (p1p0_length * p1p2_length);
3926
3927 // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8)
3928 // We could have used areCollinear() here, but since we're reusing
3929 // the variables computed above later on we keep this logic.
3930 if (qFuzzyCompare(std::abs(cos_phi), 1.0)) {
3931 m_path.lineTo(p1);
3932 return;
3933 }
3934
3935 qreal tangent = radius / std::tan(std::acos(cos_phi) / 2);
3936 qreal factor_p1p0 = tangent / p1p0_length;
3937 QPointF t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));
3938
3939 QPointF orth_p1p0(p1p0.y(), -p1p0.x());
3940 qreal orth_p1p0_length = std::hypot(orth_p1p0.x(), orth_p1p0.y());
3941 qreal factor_ra = radius / orth_p1p0_length;
3942
3943 // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
3944 qreal cos_alpha = QPointF::dotProduct(orth_p1p0, p1p2) / (orth_p1p0_length * p1p2_length);
3945 if (cos_alpha < 0.f)
3946 orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
3947
3948 QPointF p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));
3949
3950 // calculate angles for addArc
3951 orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
3952 qreal sa = std::atan2(orth_p1p0.y(), orth_p1p0.x());
3953
3954 // anticlockwise logic
3955 bool anticlockwise = false;
3956
3957 qreal factor_p1p2 = tangent / p1p2_length;
3958 QPointF t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
3959 QPointF orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y()));
3960 qreal ea = std::atan2(orth_p1p2.y(), orth_p1p2.x());
3961 if ((sa > ea) && ((sa - ea) < M_PI))
3962 anticlockwise = true;
3963 if ((sa < ea) && ((ea - sa) > M_PI))
3964 anticlockwise = true;
3965
3966 arc(p.x(), p.y(), radius, sa, ea, anticlockwise);
3967}
3968
3970 qreal x2, qreal y2,
3971 qreal radius)
3972{
3973 if (!state.invertibleCTM)
3974 return;
3975
3976 if (!qt_is_finite(x1) || !qt_is_finite(y1) || !qt_is_finite(x2) || !qt_is_finite(y2) || !qt_is_finite(radius))
3977 return;
3978
3979 QPointF st(x1, y1);
3980 QPointF end(x2, y2);
3981
3982 if (!m_path.elementCount())
3983 m_path.moveTo(st);
3984 else if (st == m_path.currentPosition() || st == end || !radius)
3985 lineTo(x1, y1);
3986 else
3987 addArcTo(st, end, radius);
3988 }
3989
3991{
3992 if (!state.invertibleCTM)
3993 return;
3994 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3995 return;
3996
3997 if (!w && !h) {
3998 m_path.moveTo(x, y);
3999 return;
4000 }
4001 m_path.addRect(x, y, w, h);
4002}
4003
4005 qreal w, qreal h,
4006 qreal xr, qreal yr)
4007{
4008 if (!state.invertibleCTM)
4009 return;
4010
4011 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h) || !qt_is_finite(xr) || !qt_is_finite(yr))
4012 return;
4013
4014 if (!w && !h) {
4015 m_path.moveTo(x, y);
4016 return;
4017 }
4018 m_path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
4019}
4020
4022 qreal w, qreal h)
4023{
4024 if (!state.invertibleCTM)
4025 return;
4026
4027 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
4028 return;
4029
4030 if (!w && !h) {
4031 m_path.moveTo(x, y);
4032 return;
4033 }
4034
4035 m_path.addEllipse(x, y, w, h);
4036}
4037
4039{
4040 if (!state.invertibleCTM)
4041 return;
4042
4044 path.addText(x, y, state.font, str);
4045 m_path.addPath(path);
4046}
4047
4048void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear, bool antiClockWise)
4049{
4050 if (!state.invertibleCTM)
4051 return;
4052
4053 if (!qt_is_finite(xc) || !qt_is_finite(yc) || !qt_is_finite(sar) || !qt_is_finite(ear) || !qt_is_finite(radius))
4054 return;
4055
4056 if (sar == ear)
4057 return;
4058
4059
4060 //### HACK
4061
4062 // In Qt we don't switch the coordinate system for degrees
4063 // and still use the 0,0 as bottom left for degrees so we need
4064 // to switch
4065 sar = -sar;
4066 ear = -ear;
4067 antiClockWise = !antiClockWise;
4068 //end hack
4069
4070 float sa = qRadiansToDegrees(sar);
4071 float ea = qRadiansToDegrees(ear);
4072
4073 double span = 0;
4074
4075 double xs = xc - radius;
4076 double ys = yc - radius;
4077 double width = radius*2;
4078 double height = radius*2;
4079 if ((!antiClockWise && (ea - sa >= 360)) || (antiClockWise && (sa - ea >= 360)))
4080 // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
4081 // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
4082 // circumference of this circle.
4083 span = 360;
4084 else {
4085 if (!antiClockWise && (ea < sa)) {
4086 span += 360;
4087 } else if (antiClockWise && (sa < ea)) {
4088 span -= 360;
4089 }
4090 //### this is also due to switched coordinate system
4091 // we would end up with a 0 span instead of 360
4092 if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
4093 qFuzzyCompare(qAbs(span), 360))) {
4094 span += ea - sa;
4095 }
4096 }
4097
4098 // If the path is empty, move to where the arc will start to avoid painting a line from (0,0)
4099 if (!m_path.elementCount())
4100 m_path.arcMoveTo(xs, ys, width, height, sa);
4101 else if (!radius) {
4102 m_path.lineTo(xc, yc);
4103 return;
4104 }
4105
4106 m_path.arcTo(xs, ys, width, height, sa, span);
4107}
4108
4110{
4111 int offset = 0;
4112 switch (value) {
4115 break;
4117 offset = (metrics.ascent() >> 1) + metrics.height() - metrics.ascent();
4118 break;
4120 offset = metrics.ascent();
4121 break;
4123 offset = metrics.height();
4124 break;
4125 }
4126 return offset;
4127}
4128
4130{
4131 int offset = 0;
4134 else if (value == QQuickContext2D::End)
4136 switch (value) {
4138 offset = metrics.horizontalAdvance(text) / 2;
4139 break;
4141 offset = metrics.horizontalAdvance(text);
4143 default:
4144 break;
4145 }
4146 return offset;
4147}
4148
4150{
4151 m_grabbedImage = grab;
4152 m_grabbed = true;
4153}
4154
4156{
4157 return m_canvas->loadedPixmap(url, sourceSize);
4158}
4159
4161{
4162 const QFontMetrics metrics(state.font);
4163 int yoffset = baseLineOffset(static_cast<QQuickContext2D::TextBaseLineType>(state.textBaseline), metrics);
4165
4166 QPainterPath textPath;
4167
4168 textPath.addText(x - xoffset, y - yoffset+metrics.ascent(), state.font, text);
4169 return textPath;
4170}
4171
4172
4173static inline bool areCollinear(const QPointF& a, const QPointF& b, const QPointF& c)
4174{
4175 // Solved from comparing the slopes of a to b and b to c: (ay-by)/(ax-bx) == (cy-by)/(cx-bx)
4176 return qFuzzyCompare((c.y() - b.y()) * (a.x() - b.x()), (a.y() - b.y()) * (c.x() - b.x()));
4177}
4178
4179static inline bool withinRange(qreal p, qreal a, qreal b)
4180{
4181 return (p >= a && p <= b) || (p >= b && p <= a);
4182}
4183
4185{
4186 if (!state.invertibleCTM)
4187 return false;
4188
4189 if (!m_path.elementCount())
4190 return false;
4191
4192 if (!qt_is_finite(x) || !qt_is_finite(y))
4193 return false;
4194
4195 QPointF point(x, y);
4196 QTransform ctm = state.matrix;
4197 QPointF p = ctm.inverted().map(point);
4198 if (!qt_is_finite(p.x()) || !qt_is_finite(p.y()))
4199 return false;
4200
4201 const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule);
4202
4203 bool contains = m_path.contains(p);
4204
4205 if (!contains) {
4206 // check whether the point is on the border
4207 QPolygonF border = m_path.toFillPolygon();
4208
4209 QPointF p1 = border.at(0);
4210 QPointF p2;
4211
4212 for (int i = 1; i < border.size(); ++i) {
4213 p2 = border.at(i);
4214 if (areCollinear(p, p1, p2)
4215 // Once we know that the points are collinear we
4216 // only need to check one of the coordinates
4217 && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ?
4218 withinRange(p.x(), p1.x(), p2.x()) :
4219 withinRange(p.y(), p1.y(), p2.y()))) {
4220 return true;
4221 }
4222 p1 = p2;
4223 }
4224 }
4225 return contains;
4226}
4227
4229
4232 , m_buffer(new QQuickContext2DCommandBuffer)
4233 , m_v4engine(nullptr)
4234 , m_surface(nullptr)
4235 , m_thread(nullptr)
4236 , m_grabbed(false)
4237{
4238}
4239
4241{
4242 mutex.lock();
4243 m_texture->setItem(nullptr);
4244 delete m_buffer;
4246
4247 mutex.unlock();
4248}
4249
4251{
4252 return m_v4value.value();
4253}
4254
4256{
4257 return QStringList() << QStringLiteral("2d");
4258}
4259
4261{
4262 Q_UNUSED(args);
4263
4264 m_canvas = canvasItem;
4265 m_renderTarget = canvasItem->renderTarget();
4266 m_renderStrategy = canvasItem->renderStrategy();
4267
4268 // Disable threaded background rendering if the platform has issues with it
4273 }
4274
4275 // Disable framebuffer object based rendering always in Qt 6. It
4276 // is not implemented in the new RHI-based graphics stack, but the
4277 // enum value is still present. Switch to Image instead.
4280
4282
4283 m_texture->setItem(canvasItem);
4284 m_texture->setCanvasWindow(canvasItem->canvasWindow().toRect());
4285 m_texture->setTileSize(canvasItem->tileSize());
4286 m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
4287 m_texture->setSmooth(canvasItem->smooth());
4288 m_texture->setAntialiasing(canvasItem->antialiasing());
4291
4292 QThread *renderThread = m_thread;
4294 renderThread = QQuickContext2DRenderThread::instance(qmlEngine(canvasItem));
4295 if (renderThread && renderThread != QThread::currentThread())
4296 m_texture->moveToThread(renderThread);
4298
4299 reset();
4300}
4301
4302void QQuickContext2D::prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing)
4303{
4305 m_texture->canvasChanged(canvasSize, tileSize, canvasWindow, dirtyRect, smooth, antialiasing);
4306 } else {
4308 tileSize,
4309 canvasWindow,
4310 dirtyRect,
4311 smooth,
4312 antialiasing);
4314 }
4315}
4316
4318{
4319 if (m_buffer) {
4322 else
4324 }
4326}
4327
4329{
4330 return m_texture;
4331}
4332
4334{
4336 flush();
4337 m_texture->grabImage(bounds);
4339 qWarning() << "Pixel readback is not supported in Cooperative mode, please try Threaded or Immediate mode";
4340 return QImage();
4341 } else {
4342 flush();
4345 "grabImage",
4347 Q_ARG(QRectF, bounds));
4348 }
4351 m_grabbed = false;
4352 return img;
4353}
4354
4355
4357{
4358 QV4::Scope scope(v4);
4359
4373#if QT_CONFIG(quick_path)
4374 proto->defineAccessorProperty(QStringLiteral("path"), QQuickJSContext2D::method_get_path, QQuickJSContext2D::method_set_path);
4375#endif
4381 contextPrototype = proto;
4382
4383 proto = scope.engine->newObject();
4384 proto->defineDefaultProperty(QStringLiteral("addColorStop"), QQuickContext2DStyle::gradient_proto_addColorStop, 0);
4385 gradientProto = proto;
4386
4387 proto = scope.engine->newObject();
4388 proto->defineAccessorProperty(scope.engine->id_length(), QQuickJSContext2DPixelData::proto_get_length, nullptr);
4389 pixelArrayProto = proto;
4390}
4391
4393{
4394}
4395
4397{
4398 if (m_stateStack.isEmpty())
4399 return;
4400
4402
4403 if (state.matrix != newState.matrix)
4404 buffer()->updateMatrix(newState.matrix);
4405
4406 if (newState.globalAlpha != state.globalAlpha)
4407 buffer()->setGlobalAlpha(newState.globalAlpha);
4408
4409 if (newState.globalCompositeOperation != state.globalCompositeOperation)
4410 buffer()->setGlobalCompositeOperation(newState.globalCompositeOperation);
4411
4412 if (newState.fillStyle != state.fillStyle)
4413 buffer()->setFillStyle(newState.fillStyle);
4414
4415 if (newState.strokeStyle != state.strokeStyle)
4416 buffer()->setStrokeStyle(newState.strokeStyle);
4417
4418 if (newState.lineWidth != state.lineWidth)
4419 buffer()->setLineWidth(newState.lineWidth);
4420
4421 if (newState.lineCap != state.lineCap)
4422 buffer()->setLineCap(newState.lineCap);
4423
4424 if (newState.lineJoin != state.lineJoin)
4425 buffer()->setLineJoin(newState.lineJoin);
4426
4427 if (newState.miterLimit != state.miterLimit)
4428 buffer()->setMiterLimit(newState.miterLimit);
4429
4430 if (newState.clip != state.clip || newState.clipPath != state.clipPath)
4431 buffer()->clip(newState.clip, newState.clipPath);
4432
4433 if (newState.shadowBlur != state.shadowBlur)
4434 buffer()->setShadowBlur(newState.shadowBlur);
4435
4436 if (newState.shadowColor != state.shadowColor)
4437 buffer()->setShadowColor(newState.shadowColor);
4438
4439 if (newState.shadowOffsetX != state.shadowOffsetX)
4440 buffer()->setShadowOffsetX(newState.shadowOffsetX);
4441
4442 if (newState.shadowOffsetY != state.shadowOffsetY)
4443 buffer()->setShadowOffsetY(newState.shadowOffsetY);
4444
4445 if (newState.lineDash != state.lineDash)
4446 buffer()->setLineDash(newState.lineDash);
4447
4449 state = newState;
4451}
4453{
4455}
4456
4458{
4460
4461 m_path = QPainterPath();
4462
4463 newState.clipPath.setFillRule(Qt::WindingFill);
4464
4467 popState();
4469}
4470
4472{
4473 return m_v4engine;
4474}
4475
4477{
4478 if (m_v4engine != engine) {
4480
4481 if (m_v4engine == nullptr)
4482 return;
4483
4484 QQuickContext2DEngineData *ed = engineData(engine);
4485 QV4::Scope scope(engine);
4486 QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocate<QQuickJSContext2D>());
4488 wrapper->setPrototypeOf(p);
4489 wrapper->d()->setContext(this);
4491 }
4492}
4493
4495
4496#include "moc_qquickcontext2d_p.cpp"
Definition main.cpp:8
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qchar.h:48
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QColor fromRgba(QRgb rgba) noexcept
Static convenience function that returns a QColor constructed from the given QRgb value rgba.
Definition qcolor.cpp:2385
static QColor fromString(QAnyStringView name) noexcept
Definition qcolor.cpp:980
static QColor fromHsl(int h, int s, int l, int a=255)
Definition qcolor.cpp:2562
\inmodule QtGui
Definition qbrush.h:446
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
Definition qcoreevent.h:45
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
static bool hasFamily(const QString &family)
\reentrant \inmodule QtGui
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
\reentrant
Definition qfont.h:20
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:23
@ Monospace
Definition qfont.h:31
@ Serif
Definition qfont.h:25
@ Cursive
Definition qfont.h:30
@ Fantasy
Definition qfont.h:32
@ SansSerif
Definition qfont.h:24
void setStyle(Style style)
Sets the style of the font to style.
Definition qfont.cpp:1101
void setPointSize(int)
Sets the point size to pointSize.
Definition qfont.cpp:970
@ SmallCaps
Definition qfont.h:98
void setCapitalization(Capitalization)
Definition qfont.cpp:1702
void setFamily(const QString &)
Sets the family name of the font.
Definition qfont.cpp:814
QString defaultFamily() const
Returns the family name that corresponds to the current style hint.
Definition qfont.cpp:2450
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1034
void setBold(bool)
If enable is true sets the font's weight to \l{Weight}{QFont::Bold}; otherwise sets the weight to \l{...
Definition qfont.h:312
void setStyleHint(StyleHint, StyleStrategy=PreferDefault)
Sets the style hint and strategy to hint and strategy, respectively.
Definition qfont.cpp:1482
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:60
void setWeight(Weight weight)
Sets the weight of the font to weight, using the scale defined by \l QFont::Weight enumeration.
Definition qfont.cpp:1190
@ StyleItalic
Definition qfont.h:75
@ StyleOblique
Definition qfont.h:76
\inmodule QtGui
Definition qbrush.h:135
void setColorAt(qreal pos, const QColor &color)
Creates a stop point at the given position with the given color.
Definition qbrush.cpp:1563
static QPlatformIntegration * platformIntegration()
Qt::LayoutDirection layoutDirection
the default layout direction for this application
\inmodule QtGui
Definition qimage.h:37
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition qimage.cpp:1197
@ Format_ARGB32
Definition qimage.h:47
\inmodule QtGui
Definition qbrush.h:394
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qmutex.h:285
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:293
void lock() noexcept
Locks the mutex.
Definition qmutex.h:290
\inmodule QtCore
Definition qobject.h:90
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition qobject.cpp:1606
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtGui
QPainterPath intersected(const QPainterPath &r) const
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
void addText(const QPointF &point, const QFont &f, const QString &text)
Adds the given text to this path as a set of closed subpaths created from the font supplied.
CompositionMode
Defines the modes supported for digital image compositing.
Definition qpainter.h:97
@ CompositionMode_Xor
Definition qpainter.h:109
@ CompositionMode_Destination
Definition qpainter.h:102
@ CompositionMode_Lighten
Definition qpainter.h:117
@ CompositionMode_ColorDodge
Definition qpainter.h:118
@ CompositionMode_DestinationAtop
Definition qpainter.h:108
@ CompositionMode_SourceOver
Definition qpainter.h:98
@ CompositionMode_DestinationOut
Definition qpainter.h:106
@ CompositionMode_Clear
Definition qpainter.h:100
@ CompositionMode_SourceAtop
Definition qpainter.h:107
@ CompositionMode_Plus
Definition qpainter.h:112
@ CompositionMode_Overlay
Definition qpainter.h:115
@ CompositionMode_Multiply
Definition qpainter.h:113
@ CompositionMode_Darken
Definition qpainter.h:116
@ CompositionMode_DestinationOver
Definition qpainter.h:99
@ CompositionMode_HardLight
Definition qpainter.h:120
@ CompositionMode_Exclusion
Definition qpainter.h:123
@ CompositionMode_Source
Definition qpainter.h:101
@ CompositionMode_ColorBurn
Definition qpainter.h:119
@ CompositionMode_Difference
Definition qpainter.h:122
@ CompositionMode_SoftLight
Definition qpainter.h:121
@ CompositionMode_DestinationIn
Definition qpainter.h:104
@ CompositionMode_Screen
Definition qpainter.h:114
@ CompositionMode_SourceOut
Definition qpainter.h:105
@ CompositionMode_SourceIn
Definition qpainter.h:103
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:460
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
static constexpr qreal dotProduct(const QPointF &p1, const QPointF &p2)
Definition qpoint.h:239
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
\inmodule QtCore
Definition qpointer.h:18
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
RenderStrategy renderStrategy
RenderTarget renderTarget
void updateMatrix(const QTransform &matrix)
void setGlobalCompositeOperation(QPainter::CompositionMode cm)
void setStrokeStyle(const QBrush &style, bool repeatX=false, bool repeatY=false)
void setFillStyle(const QBrush &style, bool repeatX=false, bool repeatY=false)
void setLineDash(const QVector< qreal > &pattern)
void clip(bool enabled, const QPainterPath &path)
QV4::PersistentValue gradientProto
QQuickContext2DEngineData(QV4::ExecutionEngine *engine)
QV4::PersistentValue contextPrototype
QV4::PersistentValue pixelArrayProto
static QQuickContext2DRenderThread * instance(QQmlEngine *engine)
void setItem(QQuickCanvasItem *item)
bool setCanvasWindow(const QRect &canvasWindow)
void canvasChanged(const QSize &canvasSize, const QSize &tileSize, const QRect &canvasWindow, const QRect &dirtyRect, bool smooth, bool antialiasing)
virtual void grabImage(const QRectF &region=QRectF())=0
void paint(QQuickContext2DCommandBuffer *ccb)
bool setCanvasSize(const QSize &size)
bool setTileSize(const QSize &size)
void setAntialiasing(bool antialiasing)
QPainterPath createTextGlyphs(qreal x, qreal y, const QString &text)
bool isPointInPath(qreal x, qreal y) const
void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius)
void translate(qreal x, qreal y)
QQuickContext2DTexture * texture() const
QV4::ExecutionEngine * v4Engine() const override
void strokeRect(qreal x, qreal y, qreal w, qreal h)
void text(const QString &str, qreal x, qreal y)
void ellipse(qreal x, qreal y, qreal w, qreal h)
QV4::ExecutionEngine * m_v4engine
void flush() override
QV4::ReturnedValue v4value() const override
void setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
QImage toImage(const QRectF &bounds) override
void arc(qreal x, qreal y, qreal radius, qreal startAngle, qreal endAngle, bool anticlockwise)
QStringList contextNames() const override
void setGrabbedImage(const QImage &grab)
void lineTo(qreal x, qreal y)
QQuickContext2D(QObject *parent=nullptr)
void init(QQuickCanvasItem *canvasItem, const QVariantMap &args) override
QQuickContext2DCommandBuffer * buffer() const
void scale(qreal x, qreal y)
void bezierCurveTo(qreal cp1x, qreal cp1y, qreal cp2x, qreal cp2y, qreal x, qreal y)
void prepare(const QSize &canvasSize, const QSize &tileSize, const QRect &canvasWindow, const QRect &dirtyRect, bool smooth, bool antialiasing) override
QQuickContext2DTexture * m_texture
QQuickCanvasItem * m_canvas
void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y)
void rotate(qreal angle)
QQuickCanvasItem::RenderStrategy m_renderStrategy
void drawText(const QString &text, qreal x, qreal y, bool fill)
void roundedRect(qreal x, qreal y, qreal w, qreal h, qreal xr, qreal yr)
static QMutex mutex
QQuickCanvasItem::RenderTarget m_renderTarget
QQmlRefPointer< QQuickCanvasPixmap > createPixmap(const QUrl &url, QSizeF sourceSize=QSizeF())
void setV4Engine(QV4::ExecutionEngine *eng) override
void shear(qreal h, qreal v)
QQuickContext2DCommandBuffer * m_buffer
void clearRect(qreal x, qreal y, qreal w, qreal h)
void addArcTo(const QPointF &p1, const QPointF &p2, qreal radius)
void transform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
QV4::PersistentValue m_v4value
void rect(qreal x, qreal y, qreal w, qreal h)
void moveTo(qreal x, qreal y)
void fillRect(qreal x, qreal y, qreal w, qreal h)
QStack< QQuickContext2D::State > m_stateStack
qreal width
This property holds the width of this item.
Definition qquickitem.h:76
bool antialiasing
\qmlproperty bool QtQuick::Item::antialiasing
Definition qquickitem.h:112
bool smooth
\qmlproperty bool QtQuick::Item::smooth
Definition qquickitem.h:111
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:207
constexpr QSize toSize() const noexcept
Returns an integer based copy of this size.
Definition qsize.h:390
\inmodule QtCore
Definition qsize.h:25
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
void push(const T &t)
Adds element t to the top of the stack.
Definition qstack.h:17
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr void truncate(qsizetype n) noexcept
Truncates this string view to length length.
Q_CORE_EXPORT float toFloat(bool *ok=nullptr) const
Returns the string view converted to a float value.
Definition qstring.cpp:7693
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
constexpr qsizetype size() const noexcept
Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for...
constexpr QStringView left(qsizetype n) const noexcept
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:7987
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1014
constexpr QStringView right(qsizetype n) const noexcept
constexpr QChar at(qsizetype n) const noexcept
Returns the character at position n in this string view.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
QStringView trimmed() const noexcept
Strips leading and trailing whitespace and returns the result.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6180
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.h:868
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3435
QByteArray toUtf8() const &
Definition qstring.h:563
static QThread * currentThread()
Definition qthread.cpp:966
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis, qreal distanceToPlane=1024.0f)
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
QPoint map(const QPoint &p) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QTransform & shear(qreal sh, qreal sv)
Shears the coordinate system by sh horizontally and sv vertically, and returns a reference to the mat...
QTransform inverted(bool *invertible=nullptr) const
Returns an inverted copy of this matrix.
bool isInvertible() const
Returns true if the matrix is invertible, otherwise returns false.
Definition qtransform.h:174
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
\inmodule QtCore
Definition qurl.h:94
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1874
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:199
ReturnedValue value() const
T value() const &
Definition qvariant.h:511
QString str
[2]
QPixmap p2
QPixmap p1
[0]
QString text
double e
QPixmap pix
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Token token
Definition keywords.cpp:444
bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
@ AbsoluteSize
@ LeftToRight
PenJoinStyle
@ SvgMiterJoin
@ BevelJoin
@ MiterJoin
@ RoundJoin
BrushStyle
@ SolidPattern
@ LinearGradientPattern
@ BlockingQueuedConnection
@ WindingFill
@ OddEvenFill
PenCapStyle
@ SquareCap
@ RoundCap
@ FlatCap
Definition brush.cpp:5
Definition image.cpp:4
static int arrayLength(const QString &rawType)
Definition provider.cpp:52
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:243
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
double qstrtod(const char *s00, char const **se, bool *ok)
#define qWarning
Definition qlogging.h:162
constexpr float qRadiansToDegrees(float radians)
Definition qmath.h:281
int qFloor(T v)
Definition qmath.h:42
#define M_PI
Definition qmath.h:209
static QT_BEGIN_NAMESPACE const int tileSize
Definition qmemrotate.cpp:9
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
constexpr static Q_DECL_CONST_FUNCTION double qt_qnan() noexcept
Definition qnumeric_p.h:94
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
Definition qnumeric_p.h:111
#define Q_ARG(Type, data)
Definition qobjectdefs.h:62
#define SIGNAL(a)
Definition qobjectdefs.h:52
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLsizei const GLuint const GLfloat * weights
GLboolean r
[2]
GLuint GLuint end
GLuint GLfloat GLfloat GLfloat x1
GLint GLenum GLsizei GLsizei GLsizei GLint border
GLfloat GLfloat f
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLuint GLuint GLfloat weight
GLenum src
GLenum GLuint buffer
GLint GLint GLint yoffset
GLint GLsizei width
GLenum GLenum dst
GLuint GLfloat x0
GLfloat angle
GLint GLint xoffset
GLenum GLuint GLintptr offset
GLuint name
GLuint GLfloat GLfloat y0
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint GLenum GLenum transform
GLbyte GLbyte blue
Definition qopenglext.h:385
const GLubyte * c
GLfixed GLfixed GLfixed y2
GLint void * img
Definition qopenglext.h:233
GLenum array
GLenum GLsizei len
GLfixed GLfixed x2
GLsizei const GLchar *const * path
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void GLsizei void void * span
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLbyte green
Definition qopenglext.h:385
GLubyte * pattern
GLenum cap
static bool hasAlpha(const QImage &image)
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
static bool withinRange(qreal p, qreal a, qreal b)
#define qClamp(val, min, max)
static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
static QFont qt_font_from_string(const QString &fontString, const QFont &currentFont)
QImage qt_image_convolute_filter(const QImage &src, const QVector< qreal > &weights, int radius=0)
@ NoTokens
@ FontWeight
@ FontVariant
@ FontStyle
static int textAlignOffset(QQuickContext2D::TextAlignType value, const QFontMetrics &metrics, const QString &text)
#define CHECK_CONTEXT(r)
\qmltype Context2D \instantiates QQuickContext2D \inqmlmodule QtQuick
#define Q_TRY_SET_TOKEN(token, value, setStatement)
int baseLineOffset(QQuickContext2D::TextBaseLineType value, const QFontMetrics &metrics)
static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens)
static bool areCollinear(const QPointF &a, const QPointF &b, const QPointF &c)
#define CHECK_CONTEXT_SETTER(r)
static bool qSetFontSizeFromToken(QFont &font, QStringView fontSizeToken)
Q_QUICK_PRIVATE_EXPORT QColor qt_color_from_string(const QV4::Value &name)
static int qParseFontSizeFromToken(QStringView fontSizeToken, bool &ok)
void qt_image_boxblur(QImage &image, int radius, bool quality)
static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
static QStringList qExtractFontFamiliesFromString(QStringView fontFamiliesString)
static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionEngine *v4, const QImage &image)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
SSL_CTX int(*) void arg)
#define qPrintable(string)
Definition qstring.h:1391
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
#define DOMEXCEPTION_NOT_SUPPORTED_ERR
#define DOMEXCEPTION_SYNTAX_ERR
#define DOMEXCEPTION_INDEX_SIZE_ERR
#define THROW_DOM(error, string)
#define DOMEXCEPTION_TYPE_MISMATCH_ERR
#define V4_DEFINE_EXTENSION(dataclass, datafunction)
Definition qv4engine_p.h:38
#define V4_NEEDS_DESTROY
#define THROW_TYPE_ERROR()
#define RETURN_UNDEFINED()
#define THROW_GENERIC_ERROR(str)
#define RETURN_RESULT(r)
#define DEFINE_OBJECT_VTABLE(classname)
#define V4_OBJECT2(DataClass, superClass)
QUrl url("example.com")
[constructor-url-reference]
QObject::connect nullptr
ba fill(true)
QRect r1(100, 200, 11, 16)
[0]
QByteArray imageData
[15]
widget render & pixmap
QJSValueList args
QJSEngine engine
[0]
QGraphicsSvgItem * red
\inmodule QtCore \reentrant
Definition qchar.h:17
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static V4_NEEDS_DESTROY QV4::ReturnedValue gradient_proto_addColorStop(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmltype CanvasGradient \inqmlmodule QtQuick
QPainter::CompositionMode globalCompositeOperation
static QV4::ReturnedValue method_get_data(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty object QtQuick::CanvasImageData::data Holds the one-dimensional array containing the dat...
static QV4::ReturnedValue method_get_height(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty int QtQuick::CanvasImageData::height Holds the actual height dimension of the data in th...
static QV4::ReturnedValue method_get_width(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmltype CanvasImageData \inqmlmodule QtQuick
static QV4::ReturnedValue proto_get_length(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmltype CanvasPixelArray \inqmlmodule QtQuick
static QV4::ReturnedValue method_isPointInPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::isPointInPath(real x, real y)
static QV4::ReturnedValue method_measureText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::measureText(text)
static QV4::ReturnedValue method_moveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::moveTo(real x, real y)
static QV4::ReturnedValue method_bezierCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::bezierCurveTo(real cp1x, real cp1y, real cp2x,...
static QV4::ReturnedValue method_getImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod CanvasImageData QtQuick::Context2D::getImageData(real x, real y, real w,...
static QV4::ReturnedValue method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod QtQuick::Context2D::setLineDash(array pattern)
static QV4::ReturnedValue method_quadraticCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::quadraticCurveTo(real cpx, real cpy, real x,...
static QV4::ReturnedValue method_drawImage(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod QtQuick::Context2D::drawImage(variant image, real dx, real dy) Draws the given image on th...
static QV4::ReturnedValue method_scale(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::scale(real x, real y)
static QV4::ReturnedValue method_stroke(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::stroke()
static QV4::ReturnedValue method_closePath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::closePath() Closes the current subpath by drawing a line to the...
static QV4::ReturnedValue method_strokeRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::strokeRect(real x, real y, real w, real h)
static QV4::ReturnedValue method_transform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::transform(real a, real b, real c, real d, real e,...
static QV4::ReturnedValue method_translate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::translate(real x, real y)
static QV4::ReturnedValue method_ellipse(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::ellipse(real x, real y, real w, real h)
static QV4::ReturnedValue method_resetTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::resetTransform()
static QV4::ReturnedValue method_createRadialGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::createRadialGradient(real x0, real y0, real r0,...
static QV4::ReturnedValue method_get_canvas(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty QtQuick::Canvas QtQuick::Context2D::canvas Holds the canvas item that the context paints...
static QV4::ReturnedValue method_clip(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::clip()
static QV4::ReturnedValue method_createLinearGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::createLinearGradient(real x0, real y0, real x1,...
static QV4::ReturnedValue method_reset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::reset() Resets the context state and properties to the default ...
static QV4::ReturnedValue method_fillText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::fillText(text, x, y)
static QV4::ReturnedValue method_arc(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::arc(real x, real y, real radius, real startAngle,...
static QV4::ReturnedValue method_save(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::save() Pushes the current state onto the state stack.
static QV4::ReturnedValue method_drawFocusRing(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_shear(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::shear(real sh, real sv)
static QV4::ReturnedValue method_lineTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::lineTo(real x, real y)
static QV4::Heap::QQuickJSContext2DPrototype * create(QV4::ExecutionEngine *engine)
static QV4::ReturnedValue method_setTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::setTransform(real a, real b, real c, real d,...
static QV4::ReturnedValue method_createConicalGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::createConicalGradient(real x, real y, real angle)
static QV4::ReturnedValue method_strokeText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::strokeText(text, x, y)
static QV4::ReturnedValue method_restore(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::restore() Pops the top state on the stack, restoring the contex...
static QV4::ReturnedValue method_rect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::rect(real x, real y, real w, real h)
static QV4::ReturnedValue method_beginPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::beginPath()
static QV4::ReturnedValue method_rotate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::rotate(real angle) Rotate the canvas around the current origin ...
static QV4::ReturnedValue method_fillRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::fillRect(real x, real y, real w, real h)
static QV4::ReturnedValue method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod array QtQuick::Context2D::getLineDash()
static QV4::ReturnedValue method_arcTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::arcTo(real x1, real y1, real x2, real y2,...
static QV4::ReturnedValue method_fill(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::fill()
static QV4::ReturnedValue method_setCaretSelectionRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_createImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod CanvasImageData QtQuick::Context2D::createImageData(real sw, real sh)
static QV4::ReturnedValue method_createPattern(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod variant QtQuick::Context2D::createPattern(color color, enumeration patternMode) This is an...
static QV4::ReturnedValue method_roundedRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::roundedRect(real x, real y, real w, real h, real xRadius,...
static QV4::ReturnedValue method_caretBlinkRate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_putImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::putImageData(CanvasImageData imageData, real dx,...
static QV4::ReturnedValue method_text(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::text(string text, real x, real y)
static QV4::ReturnedValue method_clearRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlmethod object QtQuick::Context2D::clearRect(real x, real y, real w, real h)
static QV4::ReturnedValue method_set_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::lineJoin Holds the current line join style.
static QV4::ReturnedValue method_get_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::globalCompositeOperation Holds the current the current compos...
static QV4::ReturnedValue method_set_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty enumeration QtQuick::Context2D::fillRule Holds the current fill rule used for filling sh...
static QV4::ReturnedValue method_set_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::lineCap Holds the current line cap style.
static QV4::ReturnedValue method_set_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty real QtQuick::Context2D::lineDashOffset
static QV4::ReturnedValue method_get_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::textAlign
static QV4::ReturnedValue method_set_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty real QtQuick::Context2D::lineWidth Holds the current line width.
static QV4::ReturnedValue method_set_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::font Holds the current font settings.
static QV4::ReturnedValue method_get_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty variant QtQuick::Context2D::fillStyle Holds the current style used for filling shapes.
static QV4::ReturnedValue method_get_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty real QtQuick::Context2D::shadowBlur Holds the current level of blur applied to shadows
static QV4::ReturnedValue method_get_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty qreal QtQuick::Context2D::shadowOffsetY Holds the current shadow offset in the positive ...
static QV4::ReturnedValue method_get_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty real QtQuick::Context2D::miterLimit Holds the current miter limit ratio.
static QV4::ReturnedValue method_set_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static V4_NEEDS_DESTROY QV4::ReturnedValue method_get_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty real QtQuick::Context2D::globalAlpha
static QV4::ReturnedValue method_get_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::shadowColor Holds the current shadow color.
static QV4::ReturnedValue method_set_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_set_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty variant QtQuick::Context2D::strokeStyle Holds the current color or style to use for the ...
static QV4::ReturnedValue method_set_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue method_get_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty string QtQuick::Context2D::textBaseline
static QV4::ReturnedValue method_get_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
\qmlproperty qreal QtQuick::Context2D::shadowOffsetX Holds the current shadow offset in the positive ...
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
MemoryManager * memoryManager
Heap::String * newString(const QString &s=QString())
String * id_length() const
QV4::ReturnedValue fromVariant(const QVariant &)
Heap::Object * newObject()
Heap::String * newIdentifier(const QString &text)
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols=true)
Heap::ArrayObject * newArrayObject(int count=0)
static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
void setContext(QQuickContext2D *context)
Heap::InternalClass * internalClass() const
ExecutionEngine * engine() const
bool hasProperty(PropertyKey id) const
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object)
bool hasException() const
ExecutionEngine * engine
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
static constexpr VTable::Get virtualGet
static constexpr VTable::Put virtualPut
void mark(MarkStack *markStack)
Definition qv4value_p.h:277
bool isString() const
Definition qv4value_p.h:284
int toInt32() const
Definition qv4value_p.h:350
Value()=default
bool toBoolean() const
Definition qv4value_p.h:97
static constexpr Value fromBoolean(bool b)
Definition qv4value_p.h:183
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
static Value fromDouble(double d)
Definition qv4value_p.h:199
double toNumber() const
Definition qv4value_p.h:320
const T * as() const
Definition qv4value_p.h:132
QString toQString() const
Definition qv4value.cpp:158
QString toQStringNoThrow() const
Definition qv4value.cpp:122
bool isObject() const
Definition qv4value_p.h:302
void wrapper()
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent