Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 <QtCore/qpointer.h>
48
49#include <cmath>
50#if defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
51#include <ctype.h>
52#endif
53
94#define CHECK_CONTEXT(r) if (!r || !r->d()->context() || !r->d()->context()->bufferValid()) \
95 THROW_GENERIC_ERROR("Not a Context2D object");
96
97#define CHECK_CONTEXT_SETTER(r) if (!r || !r->d()->context() || !r->d()->context()->bufferValid()) \
98 THROW_GENERIC_ERROR("Not a Context2D object");
99#define qClamp(val, min, max) qMin(qMax(val, min), max)
100#define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9))
102{
103 QByteArray str = name.toQString().toUtf8();
104
105 char *p = str.data();
106 int len = str.size();
107 //rgb/hsl color string has at least 7 characters
108 if (!p || len > 255 || len <= 7)
109 return QColor::fromString(p);
110 else {
111 bool isRgb(false), isHsl(false), hasAlpha(false);
112 Q_UNUSED(isHsl);
113
114 while (isspace(*p)) p++;
115 if (strncmp(p, "rgb", 3) == 0)
116 isRgb = true;
117 else if (strncmp(p, "hsl", 3) == 0)
118 isHsl = true;
119 else
120 return QColor::fromString(p);
121
122 p+=3; //skip "rgb" or "hsl"
123 hasAlpha = (*p == 'a') ? true : false;
124
125 ++p; //skip "("
126
127 if (hasAlpha) ++p; //skip "a"
128
129 int rh, gs, bl, alpha = 255;
130
131 //red
132 while (isspace(*p)) p++;
133 rh = strtol(p, &p, 10);
134 if (*p == '%') {
135 rh = qRound(rh/100.0 * 255);
136 ++p;
137 }
138 if (*p++ != ',') return QColor();
139
140 //green
141 while (isspace(*p)) p++;
142 gs = strtol(p, &p, 10);
143 if (*p == '%') {
144 gs = qRound(gs/100.0 * 255);
145 ++p;
146 }
147 if (*p++ != ',') return QColor();
148
149 //blue
150 while (isspace(*p)) p++;
151 bl = strtol(p, &p, 10);
152 if (*p == '%') {
153 bl = qRound(bl/100.0 * 255);
154 ++p;
155 }
156
157 if (hasAlpha) {
158 if (*p++!= ',') return QColor();
159 while (isspace(*p)) p++;
160 bool ok = false;
161 alpha = qRound(qstrtod(p, const_cast<const char **>(&p), &ok) * 255);
162 }
163
164 if (*p != ')') return QColor();
165 if (isRgb)
166 return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
167 else if (isHsl)
168 return QColor::fromHsl(qClamp(rh, 0, 359), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
169 }
170 return QColor();
171}
172
173static int qParseFontSizeFromToken(QStringView fontSizeToken, bool &ok)
174{
175 ok = false;
176 float size = fontSizeToken.trimmed().toFloat(&ok);
177 if (ok) {
178 return int(size);
179 }
180 qWarning().nospace() << "Context2D: A font size of " << fontSizeToken << " is invalid.";
181 return 0;
182}
183
184/*
185 Attempts to set the font size of \a font to \a fontSizeToken, returning
186 \c true if successful. If the font size is invalid, \c false is returned
187 and a warning is printed.
188*/
189static bool qSetFontSizeFromToken(QFont &font, QStringView fontSizeToken)
190{
191 const QStringView trimmedToken = fontSizeToken.trimmed();
192 const QStringView unitStr = trimmedToken.right(2);
193 const QStringView value = trimmedToken.left(trimmedToken.size() - 2);
194 bool ok = false;
195 int size = 0;
196 if (unitStr == QLatin1String("px")) {
198 if (ok) {
200 return true;
201 }
202 } else if (unitStr == QLatin1String("pt")) {
204 if (ok) {
206 return true;
207 }
208 } else {
209 qWarning().nospace() << "Context2D: Invalid font size unit in font string.";
210 }
211 return false;
212}
213
214/*
215 Returns a list of all of the families in \a fontFamiliesString, where
216 each family is separated by spaces. Families with spaces in their name
217 must be quoted.
218*/
220{
221 QStringList extractedFamilies;
222 int quoteIndex = -1;
223 QString currentFamily;
224 for (int index = 0; index < fontFamiliesString.size(); ++index) {
225 const QChar ch = fontFamiliesString.at(index);
226 if (ch == u'"' || ch == u'\'') {
227 if (quoteIndex == -1) {
228 quoteIndex = index;
229 } else {
230 if (ch == fontFamiliesString.at(quoteIndex)) {
231 // Found the matching quote. +1/-1 because we don't want the quote as part of the name.
232 const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1).toString();
233 extractedFamilies.push_back(family);
234 currentFamily.clear();
235 quoteIndex = -1;
236 } else {
237 qWarning().nospace() << "Context2D: Mismatched quote in font string.";
238 return QStringList();
239 }
240 }
241 } else if (ch == u' ' && quoteIndex == -1) {
242 // This is a space that's not within quotes...
243 if (!currentFamily.isEmpty()) {
244 // and there is a current family; consider it the end of the current family.
245 extractedFamilies.push_back(currentFamily);
246 currentFamily.clear();
247 } // else: ignore the space
248 } else {
249 currentFamily.push_back(ch);
250 }
251 }
252 if (!currentFamily.isEmpty()) {
253 if (quoteIndex == -1) {
254 // This is the end of the string, so add this family to our list.
255 extractedFamilies.push_back(currentFamily);
256 } else {
257 qWarning().nospace() << "Context2D: Unclosed quote in font string.";
258 return QStringList();
259 }
260 }
261 if (extractedFamilies.isEmpty()) {
262 qWarning().nospace() << "Context2D: Missing or misplaced font family in font string"
263 << " (it must come after the font size).";
264 }
265 return extractedFamilies;
266}
267
268/*
269 Tries to set a family on \a font using the families provided in \a fontFamilyTokens.
270
271 The list is ordered by preference, with the first family having the highest preference.
272 If the first family is invalid, the next family in the list is evaluated.
273 This process is repeated until a valid font is found (at which point the function
274 will return \c true and the family set on \a font) or there are no more
275 families left, at which point a warning is printed and \c false is returned.
276*/
277static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens)
278{
279 for (const QString &fontFamilyToken : fontFamilyTokens) {
280 if (QFontDatabase::hasFamily(fontFamilyToken)) {
281 font.setFamily(fontFamilyToken);
282 return true;
283 } else {
284 // Can't find a family matching this name; if it's a generic family,
285 // try searching for the default family for it by using style hints.
286 int styleHint = -1;
287 if (fontFamilyToken.compare(QLatin1String("serif")) == 0) {
288 styleHint = QFont::Serif;
289 } else if (fontFamilyToken.compare(QLatin1String("sans-serif")) == 0) {
290 styleHint = QFont::SansSerif;
291 } else if (fontFamilyToken.compare(QLatin1String("cursive")) == 0) {
292 styleHint = QFont::Cursive;
293 } else if (fontFamilyToken.compare(QLatin1String("monospace")) == 0) {
294 styleHint = QFont::Monospace;
295 } else if (fontFamilyToken.compare(QLatin1String("fantasy")) == 0) {
296 styleHint = QFont::Fantasy;
297 }
298 if (styleHint != -1) {
299 QFont tmp;
300 tmp.setStyleHint(static_cast<QFont::StyleHint>(styleHint));
302 return true;
303 }
304 }
305 }
306 qWarning("Context2D: The font families specified are invalid: %s", qPrintable(fontFamilyTokens.join(QString()).trimmed()));
307 return false;
308}
309
311{
312 NoTokens = 0x00,
313 FontStyle = 0x01,
315 FontWeight = 0x04
317
318#define Q_TRY_SET_TOKEN(token, value, setStatement) \
319if (!(usedTokens & token)) { \
320 usedTokens |= token; \
321 setStatement; \
322} else { \
323 qWarning().nospace() << "Context2D: Duplicate token " << QLatin1String(value) << " found in font string."; \
324 return currentFont; \
325}
326
327/*
328 Parses a font string based on the CSS shorthand font property.
329
330 See: http://www.w3.org/TR/css3-fonts/#font-prop
331*/
332static QFont qt_font_from_string(const QString& fontString, const QFont &currentFont) {
333 if (fontString.isEmpty()) {
334 qWarning().nospace() << "Context2D: Font string is empty.";
335 return currentFont;
336 }
337
338 // We know that font-size must be specified and it must be before font-family
339 // (which could potentially have "px" or "pt" in its name), so extract it now.
340 int fontSizeEnd = fontString.indexOf(QLatin1String("px"));
341 if (fontSizeEnd == -1)
342 fontSizeEnd = fontString.indexOf(QLatin1String("pt"));
343 if (fontSizeEnd == -1) {
344 qWarning().nospace() << "Context2D: Invalid font size unit in font string.";
345 return currentFont;
346 }
347
348 int fontSizeStart = fontString.lastIndexOf(u' ', fontSizeEnd);
349 if (fontSizeStart == -1) {
350 // The font size might be the first token in the font string, which is OK.
351 // Regardless, we'll find out if the font is invalid with qSetFontSizeFromToken().
352 fontSizeStart = 0;
353 } else {
354 // Don't want to take the leading space.
355 ++fontSizeStart;
356 }
357
358 // + 2 for the unit, +1 for the space that we require.
359 fontSizeEnd += 3;
360
361 QFont newFont;
362 if (!qSetFontSizeFromToken(newFont, QStringView{fontString}.mid(fontSizeStart, fontSizeEnd - fontSizeStart)))
363 return currentFont;
364
365 // We don't want to parse the size twice, so remove it now.
366 QString remainingFontString = fontString;
367 remainingFontString.remove(fontSizeStart, fontSizeEnd - fontSizeStart);
368 QStringView remainingFontStringRef(remainingFontString);
369
370 // Next, we have to take any font families out, as QString::split() will ruin quoted family names.
371 const QStringView fontFamiliesString = remainingFontStringRef.mid(fontSizeStart);
372 remainingFontStringRef.truncate(fontSizeStart);
373 QStringList fontFamilies = qExtractFontFamiliesFromString(fontFamiliesString);
374 if (fontFamilies.isEmpty()) {
375 return currentFont;
376 }
377 if (!qSetFontFamilyFromTokens(newFont, fontFamilies))
378 return currentFont;
379
380 // Now that we've removed the messy parts, we can split the font string on spaces.
381 const QStringView trimmedTokensStr = remainingFontStringRef.trimmed();
382 if (trimmedTokensStr.isEmpty()) {
383 // No optional properties.
384 return newFont;
385 }
386 const auto tokens = trimmedTokensStr.split(QLatin1Char(' '));
387
388 int usedTokens = NoTokens;
389 // Optional properties can be in any order, but font-size and font-family must be last.
390 for (const QStringView &token : tokens) {
391 if (token.compare(QLatin1String("normal")) == 0) {
392 if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
393 // Could be font-style, font-variant or font-weight.
394 if (!(usedTokens & FontStyle)) {
395 // QFont::StyleNormal is the default for QFont::style.
396 usedTokens = usedTokens | FontStyle;
397 } else if (!(usedTokens & FontVariant)) {
398 // QFont::MixedCase is the default for QFont::capitalization.
399 usedTokens |= FontVariant;
400 } else if (!(usedTokens & FontWeight)) {
401 // QFont::Normal is the default for QFont::weight.
402 usedTokens |= FontWeight;
403 }
404 } else {
405 qWarning().nospace() << "Context2D: Duplicate token \"normal\" found in font string.";
406 return currentFont;
407 }
408 } else if (token.compare(QLatin1String("bold")) == 0) {
409 Q_TRY_SET_TOKEN(FontWeight, "bold", newFont.setBold(true))
410 } else if (token.compare(QLatin1String("italic")) == 0) {
411 Q_TRY_SET_TOKEN(FontStyle, "italic", newFont.setStyle(QFont::StyleItalic))
412 } else if (token.compare(QLatin1String("oblique")) == 0) {
413 Q_TRY_SET_TOKEN(FontStyle, "oblique", newFont.setStyle(QFont::StyleOblique))
414 } else if (token.compare(QLatin1String("small-caps")) == 0) {
415 Q_TRY_SET_TOKEN(FontVariant, "small-caps", newFont.setCapitalization(QFont::SmallCaps))
416 } else {
417 bool conversionOk = false;
418 int weight = token.toInt(&conversionOk);
419 if (conversionOk) {
420 Q_TRY_SET_TOKEN(FontWeight, "<font-weight>",
421 newFont.setWeight(QFont::Weight(weight)))
422 } else {
423 // The token is invalid or in the wrong place/order in the font string.
424 qWarning().nospace() << "Context2D: Invalid or misplaced token " << token
425 << " found in font string.";
426 return currentFont;
427 }
428 }
429 }
430 return newFont;
431}
432
443
445
446namespace QV4 {
447namespace Heap {
448
450 void init()
451 {
452 Object::init();
453 m_context = nullptr;
454 }
455
456 void destroy()
457 {
458 delete m_context;
459 Object::destroy();
460 }
461
462 QQuickContext2D *context() { return m_context ? *m_context : nullptr; }
464 {
465 if (m_context)
466 *m_context = context;
467 else
468 m_context = new QPointer<QQuickContext2D>(context);
469 }
470
471private:
472 QPointer<QQuickContext2D>* m_context;
473};
474
476 void init() { Object::init(); }
477};
478
480 void init()
481 {
482 brush = new QBrush;
483 patternRepeatX = false;
484 patternRepeatY = false;
485 }
486 void destroy() {
487 delete brush;
488 Object::destroy();
489 }
490
494};
495
497 void init();
498 void destroy() {
499 delete image;
500 Object::destroy();
501 }
502
504};
505
507 void init();
508
509 static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
510 static_cast<QQuickJSContext2DImageData *>(that)->pixelData.mark(markStack);
511 Object::markObjects(that, markStack);
512 }
513
515};
516
517}
518}
519
521{
524
525 static QV4::ReturnedValue method_get_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
526 static QV4::ReturnedValue method_set_globalAlpha(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
527 static QV4::ReturnedValue method_get_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
528 static QV4::ReturnedValue method_set_globalCompositeOperation(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
529 static QV4::ReturnedValue method_get_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
530 static QV4::ReturnedValue method_set_fillStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
531 static QV4::ReturnedValue method_get_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
532 static QV4::ReturnedValue method_set_fillRule(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
533 static QV4::ReturnedValue method_get_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
534 static QV4::ReturnedValue method_set_strokeStyle(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
535
536 static QV4::ReturnedValue method_get_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
537 static QV4::ReturnedValue method_set_lineCap(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
538 static QV4::ReturnedValue method_get_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
539 static QV4::ReturnedValue method_set_lineJoin(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
540 static QV4::ReturnedValue method_get_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
541 static QV4::ReturnedValue method_set_lineWidth(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
542 static QV4::ReturnedValue method_get_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
543 static QV4::ReturnedValue method_set_miterLimit(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
544 static QV4::ReturnedValue method_set_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
545 static QV4::ReturnedValue method_get_lineDashOffset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
546
547 static QV4::ReturnedValue method_get_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
548 static QV4::ReturnedValue method_set_shadowBlur(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
549 static QV4::ReturnedValue method_get_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
550 static QV4::ReturnedValue method_set_shadowColor(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
551 static QV4::ReturnedValue method_get_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
552 static QV4::ReturnedValue method_set_shadowOffsetX(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
553 static QV4::ReturnedValue method_get_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
554 static QV4::ReturnedValue method_set_shadowOffsetY(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
555
556 // should these two be on the proto?
557#if QT_CONFIG(quick_path)
558 static QV4::ReturnedValue method_get_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
559 static QV4::ReturnedValue method_set_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
560#endif
561 static QV4::ReturnedValue method_get_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
562 static QV4::ReturnedValue method_set_font(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
563 static QV4::ReturnedValue method_get_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
564 static QV4::ReturnedValue method_set_textAlign(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
565 static QV4::ReturnedValue method_get_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
566 static QV4::ReturnedValue method_set_textBaseline(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
567};
568
570
571
573{
575public:
577 {
578 QV4::Scope scope(engine);
580
581 o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
582 o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
583 o->defineDefaultProperty(QStringLiteral("moveTo"), method_moveTo, 0);
584 o->defineDefaultProperty(QStringLiteral("lineTo"), method_lineTo, 0);
585 o->defineDefaultProperty(QStringLiteral("caretBlinkRate"), method_caretBlinkRate, 0);
586 o->defineDefaultProperty(QStringLiteral("clip"), method_clip, 0);
587 o->defineDefaultProperty(QStringLiteral("setTransform"), method_setTransform, 0);
588 o->defineDefaultProperty(QStringLiteral("text"), method_text, 0);
589 o->defineDefaultProperty(QStringLiteral("roundedRect"), method_roundedRect, 0);
590 o->defineDefaultProperty(QStringLiteral("createPattern"), method_createPattern, 0);
591 o->defineDefaultProperty(QStringLiteral("stroke"), method_stroke, 0);
592 o->defineDefaultProperty(QStringLiteral("arc"), method_arc, 0);
593 o->defineDefaultProperty(QStringLiteral("createImageData"), method_createImageData, 0);
594 o->defineDefaultProperty(QStringLiteral("measureText"), method_measureText, 0);
595 o->defineDefaultProperty(QStringLiteral("ellipse"), method_ellipse, 0);
596 o->defineDefaultProperty(QStringLiteral("fill"), method_fill, 0);
597 o->defineDefaultProperty(QStringLiteral("save"), method_save, 0);
598 o->defineDefaultProperty(QStringLiteral("scale"), method_scale, 0);
599 o->defineDefaultProperty(QStringLiteral("drawImage"), method_drawImage, 0);
600 o->defineDefaultProperty(QStringLiteral("transform"), method_transform, 0);
601 o->defineDefaultProperty(QStringLiteral("fillText"), method_fillText, 0);
602 o->defineDefaultProperty(QStringLiteral("strokeText"), method_strokeText, 0);
603 o->defineDefaultProperty(QStringLiteral("translate"), method_translate, 0);
604 o->defineDefaultProperty(QStringLiteral("createRadialGradient"), method_createRadialGradient, 0);
605 o->defineDefaultProperty(QStringLiteral("shear"), method_shear, 0);
606 o->defineDefaultProperty(QStringLiteral("isPointInPath"), method_isPointInPath, 0);
607 o->defineDefaultProperty(QStringLiteral("bezierCurveTo"), method_bezierCurveTo, 0);
608 o->defineDefaultProperty(QStringLiteral("resetTransform"), method_resetTransform, 0);
609 o->defineDefaultProperty(QStringLiteral("arcTo"), method_arcTo, 0);
610 o->defineDefaultProperty(QStringLiteral("fillRect"), method_fillRect, 0);
611 o->defineDefaultProperty(QStringLiteral("createConicalGradient"), method_createConicalGradient, 0);
612 o->defineDefaultProperty(QStringLiteral("drawFocusRing"), method_drawFocusRing, 0);
613 o->defineDefaultProperty(QStringLiteral("beginPath"), method_beginPath, 0);
614 o->defineDefaultProperty(QStringLiteral("clearRect"), method_clearRect, 0);
615 o->defineDefaultProperty(QStringLiteral("rect"), method_rect, 0);
616 o->defineDefaultProperty(QStringLiteral("reset"), method_reset, 0);
617 o->defineDefaultProperty(QStringLiteral("rotate"), method_rotate, 0);
618 o->defineDefaultProperty(QStringLiteral("setCaretSelectionRect"), method_setCaretSelectionRect, 0);
619 o->defineDefaultProperty(QStringLiteral("putImageData"), method_putImageData, 0);
620 o->defineDefaultProperty(QStringLiteral("getImageData"), method_getImageData, 0);
621 o->defineDefaultProperty(QStringLiteral("createLinearGradient"), method_createLinearGradient, 0);
622 o->defineDefaultProperty(QStringLiteral("strokeRect"), method_strokeRect, 0);
623 o->defineDefaultProperty(QStringLiteral("closePath"), method_closePath, 0);
624 o->defineDefaultProperty(QStringLiteral("setLineDash"), method_setLineDash, 0);
625 o->defineDefaultProperty(QStringLiteral("getLineDash"), method_getLineDash, 0);
626 o->defineAccessorProperty(QStringLiteral("canvas"), QQuickJSContext2DPrototype::method_get_canvas, nullptr);
627
628 return o->d();
629 }
630
631 static QV4::ReturnedValue method_get_canvas(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
632 static QV4::ReturnedValue method_restore(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
633 static QV4::ReturnedValue method_reset(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
634 static QV4::ReturnedValue method_save(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
635 static QV4::ReturnedValue method_rotate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
636 static QV4::ReturnedValue method_scale(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
637 static QV4::ReturnedValue method_translate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
638 static QV4::ReturnedValue method_setTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
639 static QV4::ReturnedValue method_transform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
640 static QV4::ReturnedValue method_resetTransform(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
641 static QV4::ReturnedValue method_shear(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
642 static QV4::ReturnedValue method_createLinearGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
643 static QV4::ReturnedValue method_createRadialGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
644 static QV4::ReturnedValue method_createConicalGradient(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
645 static QV4::ReturnedValue method_createPattern(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
646 static QV4::ReturnedValue method_clearRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
647 static QV4::ReturnedValue method_fillRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
648 static QV4::ReturnedValue method_strokeRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
649 static QV4::ReturnedValue method_arc(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
650 static QV4::ReturnedValue method_arcTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
651 static QV4::ReturnedValue method_beginPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
652 static QV4::ReturnedValue method_bezierCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
653 static QV4::ReturnedValue method_clip(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
654 static QV4::ReturnedValue method_closePath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
655 static QV4::ReturnedValue method_fill(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
656 static QV4::ReturnedValue method_lineTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
657 static QV4::ReturnedValue method_moveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
658 static QV4::ReturnedValue method_quadraticCurveTo(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
659 static QV4::ReturnedValue method_rect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
660 static QV4::ReturnedValue method_roundedRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
661 static QV4::ReturnedValue method_ellipse(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
662 static QV4::ReturnedValue method_text(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
663 static QV4::ReturnedValue method_stroke(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
664 static QV4::ReturnedValue method_isPointInPath(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
665 static QV4::ReturnedValue method_drawFocusRing(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
666 static QV4::ReturnedValue method_setCaretSelectionRect(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
667 static QV4::ReturnedValue method_caretBlinkRate(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
668 static QV4::ReturnedValue method_fillText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
669 static QV4::ReturnedValue method_strokeText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
670 static QV4::ReturnedValue method_measureText(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
671 static QV4::ReturnedValue method_drawImage(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
672 static QV4::ReturnedValue method_createImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
673 static QV4::ReturnedValue method_getImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
674 static QV4::ReturnedValue method_putImageData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
675 static QV4::ReturnedValue method_setLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
676 static QV4::ReturnedValue method_getLineDash(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
677
678};
679
681
682
690
691
692
694
695QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
696{
697 // weights 3x3 => delta 1
698 int delta = radius ? radius : qFloor(qSqrt(weights.size()) / qreal(2));
699 int filterDim = 2 * delta + 1;
700
701 QImage dst = QImage(src.size(), src.format());
702
703 int w = src.width();
704 int h = src.height();
705
706 const QRgb *sr = (const QRgb *)(src.constBits());
707 int srcStride = src.bytesPerLine() / 4;
708
709 QRgb *dr = (QRgb*)dst.bits();
710 int dstStride = dst.bytesPerLine() / 4;
711
712 for (int y = 0; y < h; ++y) {
713 for (int x = 0; x < w; ++x) {
714 int red = 0;
715 int green = 0;
716 int blue = 0;
717 int alpha = 0;
718
719 qreal redF = 0;
720 qreal greenF = 0;
721 qreal blueF = 0;
722 qreal alphaF = 0;
723
724 int sy = y;
725 int sx = x;
726
727 for (int cy = 0; cy < filterDim; ++cy) {
728 int scy = sy + cy - delta;
729
730 if (scy < 0 || scy >= h)
731 continue;
732
733 const QRgb *sry = sr + scy * srcStride;
734
735 for (int cx = 0; cx < filterDim; ++cx) {
736 int scx = sx + cx - delta;
737
738 if (scx < 0 || scx >= w)
739 continue;
740
741 const QRgb col = sry[scx];
742
743 if (radius) {
744 red += qRed(col);
745 green += qGreen(col);
746 blue += qBlue(col);
747 alpha += qAlpha(col);
748 } else {
749 qreal wt = weights[cy * filterDim + cx];
750
751 redF += qRed(col) * wt;
752 greenF += qGreen(col) * wt;
753 blueF += qBlue(col) * wt;
754 alphaF += qAlpha(col) * wt;
755 }
756 }
757 }
758
759 if (radius)
760 dr[x] = qRgba(qRound(red * weights[0]), qRound(green * weights[0]), qRound(blue * weights[0]), qRound(alpha * weights[0]));
761 else
762 dr[x] = qRgba(qRound(redF), qRound(greenF), qRound(blueF), qRound(alphaF));
763 }
764
765 dr += dstStride;
766 }
767
768 return dst;
769}
770
771void qt_image_boxblur(QImage& image, int radius, bool quality)
772{
773 int passes = quality? 3: 1;
774 int filterSize = 2 * radius + 1;
775 for (int i = 0; i < passes; ++i)
776 image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0 / (filterSize * filterSize), radius);
777}
778
780{
781 if (compositeOperator == QLatin1String("source-over")) {
783 } else if (compositeOperator == QLatin1String("source-out")) {
785 } else if (compositeOperator == QLatin1String("source-in")) {
787 } else if (compositeOperator == QLatin1String("source-atop")) {
789 } else if (compositeOperator == QLatin1String("destination-atop")) {
791 } else if (compositeOperator == QLatin1String("destination-in")) {
793 } else if (compositeOperator == QLatin1String("destination-out")) {
795 } else if (compositeOperator == QLatin1String("destination-over")) {
797 } else if (compositeOperator == QLatin1String("lighter")) {
799 } else if (compositeOperator == QLatin1String("copy")) {
801 } else if (compositeOperator == QLatin1String("xor")) {
803 } else if (compositeOperator == QLatin1String("qt-clear")) {
805 } else if (compositeOperator == QLatin1String("qt-destination")) {
807 } else if (compositeOperator == QLatin1String("qt-multiply")) {
809 } else if (compositeOperator == QLatin1String("qt-screen")) {
811 } else if (compositeOperator == QLatin1String("qt-overlay")) {
813 } else if (compositeOperator == QLatin1String("qt-darken")) {
815 } else if (compositeOperator == QLatin1String("qt-lighten")) {
817 } else if (compositeOperator == QLatin1String("qt-color-dodge")) {
819 } else if (compositeOperator == QLatin1String("qt-color-burn")) {
821 } else if (compositeOperator == QLatin1String("qt-hard-light")) {
823 } else if (compositeOperator == QLatin1String("qt-soft-light")) {
825 } else if (compositeOperator == QLatin1String("qt-difference")) {
827 } else if (compositeOperator == QLatin1String("qt-exclusion")) {
829 }
831}
832
834{
835 switch (op) {
837 return QStringLiteral("source-over");
839 return QStringLiteral("destination-over");
841 return QStringLiteral("qt-clear");
843 return QStringLiteral("copy");
845 return QStringLiteral("qt-destination");
847 return QStringLiteral("source-in");
849 return QStringLiteral("destination-in");
851 return QStringLiteral("source-out");
853 return QStringLiteral("destination-out");
855 return QStringLiteral("source-atop");
857 return QStringLiteral("destination-atop");
859 return QStringLiteral("xor");
861 return QStringLiteral("lighter");
863 return QStringLiteral("qt-multiply");
865 return QStringLiteral("qt-screen");
867 return QStringLiteral("qt-overlay");
869 return QStringLiteral("qt-darken");
871 return QStringLiteral("lighter");
873 return QStringLiteral("qt-color-dodge");
875 return QStringLiteral("qt-color-burn");
877 return QStringLiteral("qt-hard-light");
879 return QStringLiteral("qt-soft-light");
881 return QStringLiteral("qt-difference");
883 return QStringLiteral("qt-exclusion");
884 default:
885 break;
886 }
887 return QString();
888}
889
891{
894
895 static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty);
896 static bool virtualPut(QV4::Managed *m, QV4::PropertyKey id, const QV4::Value &value, Value *receiver);
897
898 static QV4::ReturnedValue proto_get_length(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
899};
900
902{
903 Object::init();
904 image = new QImage;
906 QV4::ScopedObject o(scope, this);
907 o->setArrayType(QV4::Heap::ArrayData::Custom);
908}
909
911
913{
915
916 static QV4::ReturnedValue method_get_width(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
917 static QV4::ReturnedValue method_get_height(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
918 static QV4::ReturnedValue method_get_data(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
919
920};
921
923{
924 Object::init();
925 pixelData = QV4::Value::undefinedValue();
926
927 QV4::Scope scope(internalClass->engine);
928 QV4::ScopedObject o(scope, this);
929
930 o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, nullptr);
931 o->defineAccessorProperty(QStringLiteral("height"), ::QQuickJSContext2DImageData::method_get_height, nullptr);
932 o->defineAccessorProperty(QStringLiteral("data"), ::QQuickJSContext2DImageData::method_get_data, nullptr);
933}
934
936
938{
939 QV4::Scope scope(v4);
940 QQuickContext2DEngineData *ed = engineData(scope.engine);
942 QV4::ScopedObject p(scope, ed->pixelArrayProto.value());
943 pixelData->setPrototypeOf(p);
944
945 if (image.isNull()) {
946 *pixelData->d()->image = QImage(qRound(w), qRound(h), QImage::Format_ARGB32);
947 pixelData->d()->image->fill(0x00000000);
948 } else {
949 // After qtbase 88e56d0932a3615231adf40d5ae033e742d72c33, the image size can be off by one.
950 Q_ASSERT(qAbs(image.width() - qRound(w * image.devicePixelRatio())) <= 1 && qAbs(image.height() - qRound(h * image.devicePixelRatio())) <= 1);
951 *pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? std::move(image) : std::move(image).convertToFormat(QImage::Format_ARGB32);
952 }
953
955 imageData->d()->pixelData = pixelData.asReturnedValue();
956 return imageData.asReturnedValue();
957}
958
959//static script functions
960
968{
969 QV4::Scope scope(b);
972
973 RETURN_RESULT(QV4::QObjectWrapper::wrap(scope.engine, r->d()->context()->canvas()));
974}
975
983{
984 QV4::Scope scope(b);
987
988 r->d()->context()->popState();
989 RETURN_RESULT(thisObject->asReturnedValue());
990}
991
997{
998 QV4::Scope scope(b);
1001
1002 r->d()->context()->reset();
1003
1004 RETURN_RESULT(thisObject->asReturnedValue());
1005}
1006
1038{
1039 QV4::Scope scope(b);
1042
1043 r->d()->context()->pushState();
1044
1045 RETURN_RESULT(*thisObject);
1046}
1047
1048// transformations
1067{
1068 QV4::Scope scope(b);
1071
1072 if (argc >= 1)
1073 r->d()->context()->rotate(argv[0].toNumber());
1074 RETURN_RESULT(*thisObject);
1075}
1076
1095{
1096 QV4::Scope scope(b);
1099
1100
1101 if (argc >= 2)
1102 r->d()->context()->scale(argv[0].toNumber(), argv[1].toNumber());
1103 RETURN_RESULT(*thisObject);
1104
1105}
1106
1144{
1145 QV4::Scope scope(b);
1148
1149
1150 if (argc >= 6)
1151 r->d()->context()->setTransform( argv[0].toNumber()
1152 , argv[1].toNumber()
1153 , argv[2].toNumber()
1154 , argv[3].toNumber()
1155 , argv[4].toNumber()
1156 , argv[5].toNumber());
1157
1158 RETURN_RESULT(*thisObject);
1159
1160}
1161
1177{
1178 QV4::Scope scope(b);
1181
1182 if (argc >= 6)
1183 r->d()->context()->transform( argv[0].toNumber()
1184 , argv[1].toNumber()
1185 , argv[2].toNumber()
1186 , argv[3].toNumber()
1187 , argv[4].toNumber()
1188 , argv[5].toNumber());
1189
1190 RETURN_RESULT(*thisObject);
1191
1192}
1193
1204{
1205 QV4::Scope scope(b);
1208
1209 if (argc >= 2)
1210 r->d()->context()->translate(argv[0].toNumber(), argv[1].toNumber());
1211 RETURN_RESULT(*thisObject);
1212
1213}
1214
1215
1225{
1226 QV4::Scope scope(b);
1229
1230 r->d()->context()->setTransform(1, 0, 0, 1, 0, 0);
1231
1232 RETURN_RESULT(*thisObject);
1233
1234}
1235
1236
1244{
1245 QV4::Scope scope(b);
1248
1249 if (argc >= 2)
1250 r->d()->context()->shear(argv[0].toNumber(), argv[1].toNumber());
1251
1252 RETURN_RESULT(*thisObject);
1253
1254}
1255// compositing
1256
1265{
1266 QV4::Scope scope(b);
1269
1270 RETURN_RESULT(QV4::Encode(r->d()->context()->state.globalAlpha));
1271}
1272
1274{
1275 QV4::Scope scope(b);
1278
1279 double globalAlpha = argc ? argv[0].toNumber() : qt_qnan();
1280
1281
1282 if (!qt_is_finite(globalAlpha))
1284
1285 if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context()->state.globalAlpha != globalAlpha) {
1286 r->d()->context()->state.globalAlpha = globalAlpha;
1287 r->d()->context()->buffer()->setGlobalAlpha(r->d()->context()->state.globalAlpha);
1288 }
1290}
1291
1371{
1372 QV4::Scope scope(b);
1375
1376 RETURN_RESULT(scope.engine->newString(qt_composite_mode_to_string(r->d()->context()->state.globalCompositeOperation)));
1377}
1378
1380{
1381 QV4::Scope scope(b);
1384
1385 if (!argc)
1387
1388 QString mode = argv[0].toQString();
1390 if (cm == QPainter::CompositionMode_SourceOver && mode != QLatin1String("source-over"))
1392
1393 if (cm != r->d()->context()->state.globalCompositeOperation) {
1394 r->d()->context()->state.globalCompositeOperation = cm;
1395 r->d()->context()->buffer()->setGlobalCompositeOperation(cm);
1396 }
1397
1399}
1400
1401// colors and styles
1425{
1426 QV4::Scope scope(b);
1429
1430 const QColor color = r->d()->context()->state.fillStyle.color().toRgb();
1431 if (color.isValid()) {
1432 if (color.alpha() == 255)
1433 RETURN_RESULT(scope.engine->newString(color.name()));
1434 QString alphaString = QString::number(color.alphaF(), 'f');
1435 while (alphaString.endsWith(QLatin1Char('0')))
1436 alphaString.chop(1);
1437 if (alphaString.endsWith(QLatin1Char('.')))
1438 alphaString += QLatin1Char('0');
1439 QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString);
1441 }
1442 RETURN_RESULT(r->d()->context()->m_fillStyle.value());
1443}
1444
1446{
1447 QV4::Scope scope(b);
1450
1451 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1452
1453 if (value->as<Object>()) {
1454 QColor color = QV4::ExecutionEngine::toVariant(value, QMetaType::fromType<QColor>()).value<QColor>();
1455 if (color.isValid()) {
1456 r->d()->context()->state.fillStyle = color;
1457 r->d()->context()->buffer()->setFillStyle(color);
1458 r->d()->context()->m_fillStyle.set(scope.engine, value);
1459 } else {
1461 if (style && *style->d()->brush != r->d()->context()->state.fillStyle) {
1462 r->d()->context()->state.fillStyle = *style->d()->brush;
1463 r->d()->context()->buffer()->setFillStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
1464 r->d()->context()->m_fillStyle.set(scope.engine, value);
1465 r->d()->context()->state.fillPatternRepeatX = style->d()->patternRepeatX;
1466 r->d()->context()->state.fillPatternRepeatY = style->d()->patternRepeatY;
1467 }
1468 }
1469 } else if (value->isString()) {
1471 if (color.isValid() && r->d()->context()->state.fillStyle != QBrush(color)) {
1472 r->d()->context()->state.fillStyle = QBrush(color);
1473 r->d()->context()->buffer()->setFillStyle(r->d()->context()->state.fillStyle);
1474 r->d()->context()->m_fillStyle.set(scope.engine, value);
1475 }
1476 }
1478}
1479
1493{
1494 QV4::Scope scope(b);
1497
1498 RETURN_RESULT(scope.engine->fromVariant(r->d()->context()->state.fillRule));
1499}
1500
1502{
1503 QV4::Scope scope(b);
1506
1507 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1508
1509 if ((value->isString() && value->toQString() == QLatin1String("WindingFill"))
1510 || (value->isInt32() && value->integerValue() == Qt::WindingFill)) {
1511 r->d()->context()->state.fillRule = Qt::WindingFill;
1512 } else if ((value->isString() && value->toQStringNoThrow() == QLatin1String("OddEvenFill"))
1513 || (value->isInt32() && value->integerValue() == Qt::OddEvenFill)) {
1514 r->d()->context()->state.fillRule = Qt::OddEvenFill;
1515 } else {
1516 //error
1517 }
1518 r->d()->context()->m_path.setFillRule(r->d()->context()->state.fillRule);
1520}
1535{
1536 QV4::Scope scope(b);
1539
1540 const QColor color = r->d()->context()->state.strokeStyle.color().toRgb();
1541 if (color.isValid()) {
1542 if (color.alpha() == 255)
1543 RETURN_RESULT(scope.engine->newString(color.name()));
1544 QString alphaString = QString::number(color.alphaF(), 'f');
1545 while (alphaString.endsWith(QLatin1Char('0')))
1546 alphaString.chop(1);
1547 if (alphaString.endsWith(QLatin1Char('.')))
1548 alphaString += QLatin1Char('0');
1549 QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString);
1551 }
1552 RETURN_RESULT(r->d()->context()->m_strokeStyle.value());
1553}
1554
1556{
1557 QV4::Scope scope(b);
1560
1561 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
1562
1563 if (value->as<Object>()) {
1564 QColor color = QV4::ExecutionEngine::toVariant(value, QMetaType::fromType<QColor>()).value<QColor>();
1565 if (color.isValid()) {
1566 r->d()->context()->state.strokeStyle = color;
1567 r->d()->context()->buffer()->setStrokeStyle(color);
1568 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1569 } else {
1571 if (style && *style->d()->brush != r->d()->context()->state.strokeStyle) {
1572 r->d()->context()->state.strokeStyle = *style->d()->brush;
1573 r->d()->context()->buffer()->setStrokeStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
1574 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1575 r->d()->context()->state.strokePatternRepeatX = style->d()->patternRepeatX;
1576 r->d()->context()->state.strokePatternRepeatY = style->d()->patternRepeatY;
1577 } else if (!style && r->d()->context()->state.strokeStyle != QBrush(QColor())) {
1578 // If there is no style object, then ensure that the strokeStyle is at least
1579 // QColor in case it was previously set
1580 r->d()->context()->state.strokeStyle = QBrush(QColor());
1581 r->d()->context()->buffer()->setStrokeStyle(r->d()->context()->state.strokeStyle);
1582 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1583 }
1584 }
1585 } else if (value->isString()) {
1587 if (color.isValid() && r->d()->context()->state.strokeStyle != QBrush(color)) {
1588 r->d()->context()->state.strokeStyle = QBrush(color);
1589 r->d()->context()->buffer()->setStrokeStyle(r->d()->context()->state.strokeStyle);
1590 r->d()->context()->m_strokeStyle.set(scope.engine, value);
1591 }
1592 }
1594}
1595
1614{
1615 QV4::Scope scope(b);
1618
1619 if (argc >= 4) {
1620 qreal x0 = argv[0].toNumber();
1621 qreal y0 = argv[1].toNumber();
1622 qreal x1 = argv[2].toNumber();
1623 qreal y1 = argv[3].toNumber();
1624
1625 if (!qt_is_finite(x0)
1626 || !qt_is_finite(y0)
1627 || !qt_is_finite(x1)
1628 || !qt_is_finite(y1)) {
1629 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
1630 }
1631 QQuickContext2DEngineData *ed = engineData(scope.engine);
1632
1634 QV4::ScopedObject p(scope, ed->gradientProto.value());
1635 gradient->setPrototypeOf(p);
1636 *gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
1637 RETURN_RESULT(*gradient);
1638 }
1639
1640 RETURN_RESULT(*thisObject);
1641
1642}
1643
1661{
1662 QV4::Scope scope(b);
1665
1666 if (argc >= 6) {
1667 qreal x0 = argv[0].toNumber();
1668 qreal y0 = argv[1].toNumber();
1669 qreal r0 = argv[2].toNumber();
1670 qreal x1 = argv[3].toNumber();
1671 qreal y1 = argv[4].toNumber();
1672 qreal r1 = argv[5].toNumber();
1673
1674 if (!qt_is_finite(x0)
1675 || !qt_is_finite(y0)
1676 || !qt_is_finite(x1)
1677 || !qt_is_finite(r0)
1678 || !qt_is_finite(r1)
1679 || !qt_is_finite(y1)) {
1680 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
1681 }
1682
1683 if (r0 < 0 || r1 < 0)
1684 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
1685
1686 QQuickContext2DEngineData *ed = engineData(scope.engine);
1687
1689 QV4::ScopedObject p(scope, ed->gradientProto.value());
1690 gradient->setPrototypeOf(p);
1691 *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0);
1692 RETURN_RESULT(*gradient);
1693 }
1694
1695 RETURN_RESULT(*thisObject);
1696
1697}
1698
1715{
1716 QV4::Scope scope(b);
1719
1720 if (argc >= 3) {
1721 qreal x = argv[0].toNumber();
1722 qreal y = argv[1].toNumber();
1724 if (!qt_is_finite(x) || !qt_is_finite(y)) {
1725 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
1726 }
1727
1728 if (!qt_is_finite(angle)) {
1729 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
1730 }
1731
1732 QQuickContext2DEngineData *ed = engineData(scope.engine);
1733
1735 QV4::ScopedObject p(scope, ed->gradientProto.value());
1736 gradient->setPrototypeOf(p);
1737 *gradient->d()->brush = QConicalGradient(x, y, angle);
1738 RETURN_RESULT(*gradient);
1739 }
1740
1741 RETURN_RESULT(*thisObject);
1742
1743}
1789{
1790 QV4::Scope scope(b);
1791 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1793
1794 if (argc >= 2) {
1796
1798 argv[0], QMetaType::fromType<QColor>()).value<QColor>();
1799 if (color.isValid()) {
1800 int patternMode = argv[1].toInt32();
1802 if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) {
1803 style = static_cast<Qt::BrushStyle>(patternMode);
1804 }
1805 *pattern->d()->brush = QBrush(color, style);
1806 } else {
1807 QImage patternTexture;
1808
1809 if (const QV4::Object *o = argv[0].as<Object>()) {
1810 QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data")));
1811 QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s));
1812 if (!!pixelData) {
1813 patternTexture = *pixelData->d()->image;
1814 }
1815 } else {
1816 patternTexture = r->d()->context()->createPixmap(QUrl(argv[0].toQStringNoThrow()))->image();
1817 }
1818
1819 if (!patternTexture.isNull()) {
1820 pattern->d()->brush->setTextureImage(patternTexture);
1821
1822 QString repetition = argv[1].toQStringNoThrow();
1823 if (repetition == QLatin1String("repeat") || repetition.isEmpty()) {
1824 pattern->d()->patternRepeatX = true;
1825 pattern->d()->patternRepeatY = true;
1826 } else if (repetition == QLatin1String("repeat-x")) {
1827 pattern->d()->patternRepeatX = true;
1828 pattern->d()->patternRepeatY = false;
1829 } else if (repetition == QLatin1String("repeat-y")) {
1830 pattern->d()->patternRepeatX = false;
1831 pattern->d()->patternRepeatY = true;
1832 } else if (repetition == QLatin1String("no-repeat")) {
1833 pattern->d()->patternRepeatX = false;
1834 pattern->d()->patternRepeatY = false;
1835 } else {
1836 //TODO: exception: SYNTAX_ERR
1837 }
1838
1839 }
1840 }
1841
1843
1844 }
1846}
1847
1848// line styles
1868{
1869 QV4::Scope scope(b);
1870 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1872
1873 switch (r->d()->context()->state.lineCap) {
1874 case Qt::RoundCap:
1875 RETURN_RESULT(scope.engine->newString(QStringLiteral("round")));
1876 case Qt::SquareCap:
1877 RETURN_RESULT(scope.engine->newString(QStringLiteral("square")));
1878 case Qt::FlatCap:
1879 default:
1880 break;
1881 }
1883}
1884
1886{
1887 if (!argc)
1888 return QV4::Encode::undefined();
1889
1890 QV4::Scope scope(b);
1891 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1893
1894 QString lineCap = argv[0].toQString();
1896 if (lineCap == QLatin1String("round"))
1897 cap = Qt::RoundCap;
1898 else if (lineCap == QLatin1String("butt"))
1899 cap = Qt::FlatCap;
1900 else if (lineCap == QLatin1String("square"))
1902 else
1904
1905 if (cap != r->d()->context()->state.lineCap) {
1906 r->d()->context()->state.lineCap = cap;
1907 r->d()->context()->buffer()->setLineCap(cap);
1908 }
1910}
1911
1929{
1930 QV4::Scope scope(b);
1931 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1933
1934 switch (r->d()->context()->state.lineJoin) {
1935 case Qt::RoundJoin:
1936 RETURN_RESULT(scope.engine->newString(QStringLiteral("round")));
1937 case Qt::BevelJoin:
1938 RETURN_RESULT(scope.engine->newString(QStringLiteral("bevel")));
1939 case Qt::MiterJoin:
1940 default:
1941 break;
1942 }
1943 RETURN_RESULT(scope.engine->newString(QStringLiteral("miter")));
1944}
1945
1947{
1948 QV4::Scope scope(b);
1949 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1951
1952 if (!argc)
1954
1955 QString lineJoin = argv[0].toQString();
1956 Qt::PenJoinStyle join;
1957 if (lineJoin == QLatin1String("round"))
1958 join = Qt::RoundJoin;
1959 else if (lineJoin == QLatin1String("bevel"))
1960 join = Qt::BevelJoin;
1961 else if (lineJoin == QLatin1String("miter"))
1962 join = Qt::SvgMiterJoin;
1963 else
1965
1966 if (join != r->d()->context()->state.lineJoin) {
1967 r->d()->context()->state.lineJoin = join;
1968 r->d()->context()->buffer()->setLineJoin(join);
1969 }
1971}
1972
1978{
1979 QV4::Scope scope(b);
1980 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1982
1983 RETURN_RESULT(QV4::Encode(r->d()->context()->state.lineWidth));
1984}
1985
1987{
1988 QV4::Scope scope(b);
1989 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
1991
1992 qreal w = argc ? argv[0].toNumber() : -1;
1993
1994 if (w > 0 && qt_is_finite(w) && w != r->d()->context()->state.lineWidth) {
1995 r->d()->context()->state.lineWidth = w;
1996 r->d()->context()->buffer()->setLineWidth(w);
1997 }
1999}
2000
2007{
2008 QV4::Scope scope(b);
2009 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2011
2012 RETURN_RESULT(QV4::Encode(r->d()->context()->state.miterLimit));
2013}
2014
2016{
2017 QV4::Scope scope(b);
2018 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2020
2021 qreal ml = argc ? argv[0].toNumber() : -1;
2022
2023 if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context()->state.miterLimit) {
2024 r->d()->context()->state.miterLimit = ml;
2025 r->d()->context()->buffer()->setMiterLimit(ml);
2026 }
2028}
2029
2038{
2039 QV4::Scope scope(b);
2040 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2042
2043 const QVector<qreal> pattern = r->d()->context()->state.lineDash;
2045 array->arrayReserve(pattern.size());
2046 for (int i = 0; i < pattern.size(); i++)
2048
2049 array->setArrayLengthUnchecked(pattern.size());
2050
2052}
2053
2079{
2080 QV4::Scope scope(b);
2081 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2083
2084 if (!argc)
2086
2087 QV4::ScopedArrayObject array(scope, argv[0]);
2088 if (!array)
2090
2091 QV4::ScopedValue v(scope);
2092 const uint arrayLength = array->getLength();
2093 QVector<qreal> dashes;
2094 dashes.reserve(arrayLength);
2095 for (uint i = 0; i < arrayLength; ++i) {
2096 v = array->get(i);
2097 const double number = v->toNumber();
2098
2099 if (!qt_is_finite(number) || (number < 0))
2101
2102 dashes.append(v->toNumber());
2103 }
2104 if (dashes.size() % 2 != 0) {
2105 dashes += dashes;
2106 }
2107
2108 r->d()->context()->state.lineDash = dashes;
2109 r->d()->context()->buffer()->setLineDash(dashes);
2110
2112}
2113
2124{
2125 QV4::Scope scope(b);
2126 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2128
2129 RETURN_RESULT(QV4::Encode(r->d()->context()->state.lineDashOffset));
2130}
2131
2133{
2134 QV4::Scope scope(b);
2135 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2137
2138 const qreal offset = argc ? argv[0].toNumber() : -1;
2139
2140 if (qt_is_finite(offset) && offset != r->d()->context()->state.lineDashOffset) {
2141 r->d()->context()->state.lineDashOffset = offset;
2142 r->d()->context()->buffer()->setLineDashOffset(offset);
2143 }
2145}
2146
2147
2148// shadows
2154{
2155 QV4::Scope scope(b);
2156 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2158
2159 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowBlur));
2160}
2161
2163{
2164 QV4::Scope scope(b);
2165 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2167
2168 qreal blur = argc ? argv[0].toNumber() : -1;
2169
2170 if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context()->state.shadowBlur) {
2171 r->d()->context()->state.shadowBlur = blur;
2172 r->d()->context()->buffer()->setShadowBlur(blur);
2173 }
2175}
2176
2182{
2183 QV4::Scope scope(b);
2184 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2186
2187 RETURN_RESULT(scope.engine->newString(r->d()->context()->state.shadowColor.name()));
2188}
2189
2191{
2192 QV4::Scope scope(b);
2193 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2195
2196 QColor color;
2197 if (argc)
2198 color = qt_color_from_string(argv[0]);
2199
2200 if (color.isValid() && color != r->d()->context()->state.shadowColor) {
2201 r->d()->context()->state.shadowColor = color;
2202 r->d()->context()->buffer()->setShadowColor(color);
2203 }
2205}
2206
2207
2215{
2216 QV4::Scope scope(b);
2217 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2219
2220 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowOffsetX));
2221}
2222
2224{
2225 QV4::Scope scope(b);
2226 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2228
2229 qreal offsetX = argc ? argv[0].toNumber() : qt_qnan();
2230 if (qt_is_finite(offsetX) && offsetX != r->d()->context()->state.shadowOffsetX) {
2231 r->d()->context()->state.shadowOffsetX = offsetX;
2232 r->d()->context()->buffer()->setShadowOffsetX(offsetX);
2233 }
2235}
2243{
2244 QV4::Scope scope(b);
2245 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2247
2248 RETURN_RESULT(QV4::Encode(r->d()->context()->state.shadowOffsetY));
2249}
2250
2252{
2253 QV4::Scope scope(b);
2254 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2256
2257 qreal offsetY = argc ? argv[0].toNumber() : qt_qnan();
2258 if (qt_is_finite(offsetY) && offsetY != r->d()->context()->state.shadowOffsetY) {
2259 r->d()->context()->state.shadowOffsetY = offsetY;
2260 r->d()->context()->buffer()->setShadowOffsetY(offsetY);
2261 }
2263}
2264
2265#if QT_CONFIG(quick_path)
2266QV4::ReturnedValue QQuickJSContext2D::method_get_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
2267{
2268 QV4::Scope scope(b);
2269 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2271
2272 RETURN_RESULT(r->d()->context()->m_v4path.value());
2273}
2274
2275QV4::ReturnedValue QQuickJSContext2D::method_set_path(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
2276{
2277 QV4::Scope scope(b);
2278 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2280
2281 QV4::ScopedValue value(scope, argc ? argv[0] : QV4::Value::undefinedValue());
2282 r->d()->context()->beginPath();
2283 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, value);
2284 if (!!qobjectWrapper) {
2285 if (QQuickPath *path = qobject_cast<QQuickPath*>(qobjectWrapper->object()))
2286 r->d()->context()->m_path = path->path();
2287 } else {
2288 QString path =value->toQStringNoThrow();
2289 QQuickSvgParser::parsePathDataFast(path, r->d()->context()->m_path);
2290 }
2291 r->d()->context()->m_v4path.set(scope.engine, value);
2293}
2294#endif // QT_CONFIG(quick_path)
2295
2296//rects
2304{
2305 QV4::Scope scope(b);
2306 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2308
2309
2310 if (argc >= 4)
2311 r->d()->context()->clearRect(argv[0].toNumber(),
2312 argv[1].toNumber(),
2313 argv[2].toNumber(),
2314 argv[3].toNumber());
2315
2316 RETURN_RESULT(*thisObject);
2317
2318}
2327{
2328 QV4::Scope scope(b);
2329 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2331
2332 if (argc >= 4)
2333 r->d()->context()->fillRect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2334 RETURN_RESULT(*thisObject);
2335
2336}
2337
2347{
2348 QV4::Scope scope(b);
2349 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2351
2352 if (argc >= 4)
2353 r->d()->context()->strokeRect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2354
2355 RETURN_RESULT(*thisObject);
2356
2357}
2358
2359// Complex shapes (paths) API
2381{
2382 QV4::Scope scope(b);
2383 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2385
2386 if (argc >= 5) {
2387 bool antiClockwise = false;
2388
2389 if (argc == 6)
2390 antiClockwise = argv[5].toBoolean();
2391
2392 qreal radius = argv[2].toNumber();
2393
2394 if (qt_is_finite(radius) && radius < 0)
2395 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
2396
2397 r->d()->context()->arc(argv[0].toNumber(),
2398 argv[1].toNumber(),
2399 radius,
2400 argv[3].toNumber(),
2401 argv[4].toNumber(),
2402 antiClockwise);
2403 }
2404
2405 RETURN_RESULT(*thisObject);
2406
2407}
2408
2433{
2434 QV4::Scope scope(b);
2435 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2437
2438 if (argc >= 5) {
2439 qreal radius = argv[4].toNumber();
2440
2441 if (qt_is_finite(radius) && radius < 0)
2442 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
2443
2444 r->d()->context()->arcTo(argv[0].toNumber(),
2445 argv[1].toNumber(),
2446 argv[2].toNumber(),
2447 argv[3].toNumber(),
2448 radius);
2449 }
2450
2451 RETURN_RESULT(*thisObject);
2452
2453}
2454
2461{
2462 QV4::Scope scope(b);
2463 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2465
2466 r->d()->context()->beginPath();
2467
2468 RETURN_RESULT(*thisObject);
2469
2470}
2471
2495{
2496 QV4::Scope scope(b);
2497 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2499
2500 if (argc >= 6) {
2501 qreal cp1x = argv[0].toNumber();
2502 qreal cp1y = argv[1].toNumber();
2503 qreal cp2x = argv[2].toNumber();
2504 qreal cp2y = argv[3].toNumber();
2505 qreal x = argv[4].toNumber();
2506 qreal y = argv[5].toNumber();
2507
2508 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))
2510
2511 r->d()->context()->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
2512 }
2513 RETURN_RESULT(*thisObject);
2514}
2515
2541{
2542 QV4::Scope scope(b);
2543 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2545
2546 r->d()->context()->clip();
2547 RETURN_RESULT(*thisObject);
2548}
2549
2558{
2559 QV4::Scope scope(b);
2560 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2562
2563 r->d()->context()->closePath();
2564
2565 RETURN_RESULT(*thisObject);
2566}
2567
2578{
2579 QV4::Scope scope(b);
2580 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2582 r->d()->context()->fill();
2583 RETURN_RESULT(*thisObject);
2584}
2585
2592{
2593 QV4::Scope scope(b);
2594 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2596
2597 if (argc >= 2) {
2598 qreal x = argv[0].toNumber();
2599 qreal y = argv[1].toNumber();
2600
2601 if (!qt_is_finite(x) || !qt_is_finite(y))
2603
2604 r->d()->context()->lineTo(x, y);
2605 }
2606
2607 RETURN_RESULT(*thisObject);
2608}
2609
2616{
2617 QV4::Scope scope(b);
2618 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2620
2621 if (argc >= 2) {
2622 qreal x = argv[0].toNumber();
2623 qreal y = argv[1].toNumber();
2624
2625 if (!qt_is_finite(x) || !qt_is_finite(y))
2627 r->d()->context()->moveTo(x, y);
2628 }
2629
2630 RETURN_RESULT(*thisObject);
2631}
2632
2642{
2643 QV4::Scope scope(b);
2644 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2646
2647 if (argc >= 4) {
2648 qreal cpx = argv[0].toNumber();
2649 qreal cpy = argv[1].toNumber();
2650 qreal x = argv[2].toNumber();
2651 qreal y = argv[3].toNumber();
2652
2653 if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y))
2655
2656 r->d()->context()->quadraticCurveTo(cpx, cpy, x, y);
2657 }
2658
2659 RETURN_RESULT(*thisObject);
2660}
2661
2669{
2670 QV4::Scope scope(b);
2671 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2673
2674 if (argc >= 4)
2675 r->d()->context()->rect(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2676 RETURN_RESULT(*thisObject);
2677
2678}
2679
2688{
2689 QV4::Scope scope(b);
2690 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2692
2693 if (argc >= 6)
2694 r->d()->context()->roundedRect(argv[0].toNumber()
2695 , argv[1].toNumber()
2696 , argv[2].toNumber()
2697 , argv[3].toNumber()
2698 , argv[4].toNumber()
2699 , argv[5].toNumber());
2700 RETURN_RESULT(*thisObject);
2701
2702}
2703
2715{
2716 QV4::Scope scope(b);
2717 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2719
2720 if (argc >= 4)
2721 r->d()->context()->ellipse(argv[0].toNumber(), argv[1].toNumber(), argv[2].toNumber(), argv[3].toNumber());
2722
2723 RETURN_RESULT(*thisObject);
2724
2725}
2726
2737{
2738 QV4::Scope scope(b);
2739 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2741
2742 if (argc >= 3) {
2743 qreal x = argv[1].toNumber();
2744 qreal y = argv[2].toNumber();
2745
2746 if (!qt_is_finite(x) || !qt_is_finite(y))
2748 r->d()->context()->text(argv[0].toQStringNoThrow(), x, y);
2749 }
2750
2751 RETURN_RESULT(*thisObject);
2752}
2753
2762{
2763 QV4::Scope scope(b);
2764 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2766
2767 r->d()->context()->stroke();
2768 RETURN_RESULT(*thisObject);
2769
2770}
2771
2780{
2781 QV4::Scope scope(b);
2782 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2784
2785 bool pointInPath = false;
2786 if (argc >= 2)
2787 pointInPath = r->d()->context()->isPointInPath(argv[0].toNumber(), argv[1].toNumber());
2789}
2790
2792{
2793 QV4::Scope scope(b);
2794 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
2795}
2796
2798{
2799 QV4::Scope scope(b);
2800 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
2801}
2802
2804{
2805 QV4::Scope scope(b);
2806 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
2807}
2808
2833{
2834 QV4::Scope scope(b);
2835 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2837
2838 RETURN_RESULT(scope.engine->newString(r->d()->context()->state.font.toString()));
2839}
2840
2842{
2843 QV4::Scope scope(b);
2844 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2846
2847 QV4::ScopedString s(scope, argc ? argv[0] : QV4::Value::undefinedValue(), QV4::ScopedString::Convert);
2848 if (scope.hasException())
2850 QFont font = qt_font_from_string(s->toQString(), r->d()->context()->state.font);
2851 if (font != r->d()->context()->state.font) {
2852 r->d()->context()->state.font = font;
2853 }
2855}
2856
2873{
2874 QV4::Scope scope(b);
2875 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2877
2878 switch (r->d()->context()->state.textAlign) {
2884 RETURN_RESULT(scope.engine->newString(QStringLiteral("right")));
2886 RETURN_RESULT(scope.engine->newString(QStringLiteral("center")));
2888 default:
2889 break;
2890 }
2891 RETURN_RESULT(scope.engine->newString(QStringLiteral("start")));
2892}
2893
2895{
2896 QV4::Scope scope(b);
2897 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2899
2900 QV4::ScopedString s(scope, argc ? argv[0] : QV4::Value::undefinedValue(), QV4::ScopedString::Convert);
2901 if (scope.hasException())
2903 QString textAlign = s->toQString();
2904
2906 if (textAlign == QLatin1String("start"))
2908 else if (textAlign == QLatin1String("end"))
2910 else if (textAlign == QLatin1String("left"))
2912 else if (textAlign == QLatin1String("right"))
2914 else if (textAlign == QLatin1String("center"))
2916 else
2918
2919 if (ta != r->d()->context()->state.textAlign)
2920 r->d()->context()->state.textAlign = ta;
2921
2923}
2924
2940{
2941 QV4::Scope scope(b);
2942 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2944
2945 switch (r->d()->context()->state.textBaseline) {
2947 RETURN_RESULT(scope.engine->newString(QStringLiteral("hanging")));
2951 RETURN_RESULT(scope.engine->newString(QStringLiteral("bottom")));
2953 RETURN_RESULT(scope.engine->newString(QStringLiteral("middle")));
2955 default:
2956 break;
2957 }
2958 RETURN_RESULT(scope.engine->newString(QStringLiteral("alphabetic")));
2959}
2960
2962{
2963 QV4::Scope scope(b);
2964 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
2966 QV4::ScopedString s(scope, argc ? argv[0] : QV4::Value::undefinedValue(), QV4::ScopedString::Convert);
2967 if (scope.hasException())
2969 QString textBaseline = s->toQString();
2970
2972 if (textBaseline == QLatin1String("alphabetic"))
2974 else if (textBaseline == QLatin1String("hanging"))
2976 else if (textBaseline == QLatin1String("top"))
2978 else if (textBaseline == QLatin1String("bottom"))
2980 else if (textBaseline == QLatin1String("middle"))
2982 else
2984
2985 if (tb != r->d()->context()->state.textBaseline)
2986 r->d()->context()->state.textBaseline = tb;
2987
2989}
2990
3002{
3003 QV4::Scope scope(b);
3004 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3006
3007 if (argc >= 3) {
3008 qreal x = argv[1].toNumber();
3009 qreal y = argv[2].toNumber();
3010 if (!qt_is_finite(x) || !qt_is_finite(y))
3012 QPainterPath textPath = r->d()->context()->createTextGlyphs(x, y, argv[0].toQStringNoThrow());
3013 r->d()->context()->buffer()->fill(textPath);
3014 }
3015
3016 RETURN_RESULT(*thisObject);
3017}
3029{
3030 QV4::Scope scope(b);
3031 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3033
3034 if (argc >= 3)
3035 r->d()->context()->drawText(argv[0].toQStringNoThrow(), argv[1].toNumber(), argv[2].toNumber(), false);
3036
3037 RETURN_RESULT(*thisObject);
3038}
3039
3048{
3049 QV4::Scope scope(b);
3050 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3052
3053 if (argc >= 1) {
3054 QFontMetrics fm(r->d()->context()->state.font);
3055 uint width = fm.horizontalAdvance(argv[0].toQStringNoThrow());
3056 QV4::ScopedObject tm(scope, scope.engine->newObject());
3057 tm->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("width"))).getPointer(),
3059 RETURN_RESULT(*tm);
3060 }
3062}
3063
3064// drawing images
3124{
3125 QV4::Scope scope(b);
3126 QV4::Scoped<QQuickJSContext2D> r(scope, *thisObject);
3128
3129 qreal sx, sy, sw, sh, dx, dy, dw, dh;
3130
3131 if (!argc)
3133
3134 //FIXME:This function should be moved to QQuickContext2D::drawImage(...)
3135 if (!r->d()->context()->state.invertibleCTM)
3137
3138 QQmlRefPointer<QQuickCanvasPixmap> pixmap;
3139
3140 QV4::ScopedValue arg(scope, argv[0]);
3141 if (arg->isString()) {
3142 QUrl url(arg->toQString());
3143 if (!url.isValid())
3144 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3145
3146 pixmap = r->d()->context()->createPixmap(url);
3147 } else if (arg->isObject()) {
3148 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, arg);
3149 if (!!qobjectWrapper) {
3150 if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
3151 pixmap = r->d()->context()->createPixmap(imageItem->source());
3152 } else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
3153 QImage img = canvas->toImage();
3154 if (!img.isNull())
3155 pixmap.adopt(new QQuickCanvasPixmap(img));
3156 } else {
3157 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3158 }
3159 } else {
3161 if (!!imageData) {
3163 if (pix && !pix->d()->image->isNull()) {
3164 pixmap.adopt(new QQuickCanvasPixmap(*pix->d()->image));
3165 } else {
3166 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3167 }
3168 } else {
3169 QUrl url(arg->toQStringNoThrow());
3170 if (url.isValid())
3171 pixmap = r->d()->context()->createPixmap(url);
3172 else
3173 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3174 }
3175 }
3176 } else {
3177 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
3178 }
3179
3180 if (pixmap.isNull() || !pixmap->isValid())
3182
3183 if (argc >= 9) {
3184 sx = argv[1].toNumber();
3185 sy = argv[2].toNumber();
3186 sw = argv[3].toNumber();
3187 sh = argv[4].toNumber();
3188 dx = argv[5].toNumber();
3189 dy = argv[6].toNumber();
3190 dw = argv[7].toNumber();
3191 dh = argv[8].toNumber();
3192 } else if (argc >= 5) {
3193 sx = 0;
3194 sy = 0;
3195 sw = pixmap->width();
3196 sh = pixmap->height();
3197 dx = argv[1].toNumber();
3198 dy = argv[2].toNumber();
3199 dw = argv[3].toNumber();
3200 dh = argv[4].toNumber();
3201 } else if (argc >= 3) {
3202 dx = argv[1].toNumber();
3203 dy = argv[2].toNumber();
3204 sx = 0;
3205 sy = 0;
3206 sw = pixmap->width();
3207 sh = pixmap->height();
3208 dw = sw;
3209 dh = sh;
3210 } else {
3212 }
3213
3214 if (!qt_is_finite(sx)
3215 || !qt_is_finite(sy)
3216 || !qt_is_finite(sw)
3217 || !qt_is_finite(sh)
3218 || !qt_is_finite(dx)
3219 || !qt_is_finite(dy)
3220 || !qt_is_finite(dw)
3221 || !qt_is_finite(dh))
3223
3224 if (sx < 0
3225 || sy < 0
3226 || sw == 0
3227 || sh == 0
3228 || sx + sw > pixmap->width()
3229 || sy + sh > pixmap->height()
3230 || sx + sw < 0 || sy + sh < 0) {
3231 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
3232 }
3233
3234 r->d()->context()->buffer()->drawPixmap(pixmap, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh));
3235
3236 RETURN_RESULT(*thisObject);
3237}
3238
3239// pixel manipulation
3264{
3265 QV4::Scope scope(b);
3267 if (!imageData)
3270 int width = r ? r->d()->image->width() : 0;
3272}
3273
3279{
3280 QV4::Scope scope(b);
3282 if (!imageData)
3285 int height = r ? r->d()->image->height() : 0;
3287}
3288
3294{
3295 QV4::Scope scope(b);
3297 if (!imageData)
3299 RETURN_RESULT(imageData->d()->pixelData);
3300}
3301
3321{
3322 QV4::Scope scope(b);
3324 if (!r || r->d()->image->isNull())
3326
3327 RETURN_RESULT(QV4::Encode(r->d()->image->width() * r->d()->image->height() * 4));
3328}
3329
3331{
3332 if (!id.isArrayIndex())
3333 return QV4::Object::virtualGet(m, id, receiver, hasProperty);
3334
3335 uint index = id.asArrayIndex();
3337 QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine();
3338 QV4::Scope scope(v4);
3340
3341 if (index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4)) {
3342 if (hasProperty)
3343 *hasProperty = true;
3344 const quint32 w = r->d()->image->width();
3345 const quint32 row = (index / 4) / w;
3346 const quint32 col = (index / 4) % w;
3347 const QRgb* pixel = reinterpret_cast<const QRgb*>(r->d()->image->constScanLine(row));
3348 pixel += col;
3349 switch (index % 4) {
3350 case 0:
3351 return QV4::Encode(qRed(*pixel));
3352 case 1:
3353 return QV4::Encode(qGreen(*pixel));
3354 case 2:
3355 return QV4::Encode(qBlue(*pixel));
3356 case 3:
3357 return QV4::Encode(qAlpha(*pixel));
3358 }
3359 }
3360
3361 if (hasProperty)
3362 *hasProperty = false;
3363 return QV4::Encode::undefined();
3364}
3365
3367{
3368 if (!id.isArrayIndex())
3369 return Object::virtualPut(m, id, value, receiver);
3370
3373 QV4::Scope scope(v4);
3374 if (scope.hasException())
3375 return false;
3376
3377 uint index = id.asArrayIndex();
3379
3380 const int v = value.toInt32();
3381 if (r && index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4) && v >= 0 && v <= 255) {
3382 const quint32 w = r->d()->image->width();
3383 const quint32 row = (index / 4) / w;
3384 const quint32 col = (index / 4) % w;
3385
3386 QRgb* pixel = reinterpret_cast<QRgb*>(r->d()->image->scanLine(row));
3387 pixel += col;
3388 switch (index % 4) {
3389 case 0:
3390 *pixel = qRgba(v, qGreen(*pixel), qBlue(*pixel), qAlpha(*pixel));
3391 break;
3392 case 1:
3393 *pixel = qRgba(qRed(*pixel), v, qBlue(*pixel), qAlpha(*pixel));
3394 break;
3395 case 2:
3396 *pixel = qRgba(qRed(*pixel), qGreen(*pixel), v, qAlpha(*pixel));
3397 break;
3398 case 3:
3399 *pixel = qRgba(qRed(*pixel), qGreen(*pixel), qBlue(*pixel), v);
3400 break;
3401 }
3402 return true;
3403 }
3404
3405 return false;
3406}
3429{
3430 QV4::Scope scope(b);
3433
3434 if (argc == 1) {
3435 QV4::ScopedValue arg0(scope, argv[0]);
3436 QV4::Scoped<QQuickJSContext2DImageData> imgData(scope, arg0);
3437 if (!!imgData) {
3438 QV4::Scoped<QQuickJSContext2DPixelData> pa(scope, imgData->d()->pixelData.as<QQuickJSContext2DPixelData>());
3439 if (pa) {
3440 qreal w = pa->d()->image->width();
3441 qreal h = pa->d()->image->height();
3443 }
3444 } else if (arg0->isString()) {
3445 QImage image = r->d()->context()->createPixmap(QUrl(arg0->toQStringNoThrow()))->image();
3446 RETURN_RESULT(qt_create_image_data(image.width(), image.height(), scope.engine, std::move(image)));
3447 }
3448 } else if (argc == 2) {
3449 qreal w = argv[0].toNumber();
3450 qreal h = argv[1].toNumber();
3451
3452 if (!qt_is_finite(w) || !qt_is_finite(h))
3453 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
3454
3455 if (w > 0 && h > 0)
3457 else
3458 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments");
3459 }
3461}
3462
3470{
3471 QV4::Scope scope(b);
3474
3475 if (argc >= 4) {
3476 qreal x = argv[0].toNumber();
3477 qreal y = argv[1].toNumber();
3478 qreal w = argv[2].toNumber();
3479 qreal h = argv[3].toNumber();
3480 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3481 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
3482
3483 if (w <= 0 || h <= 0)
3484 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments");
3485
3486 QImage image = r->d()->context()->canvas()->toImage(QRectF(x, y, w, h));
3487 RETURN_RESULT(qt_create_image_data(w, h, scope.engine, std::move(image)));
3488 }
3490}
3491
3502{
3503 QV4::Scope scope(b);
3506 if (argc < 7)
3508
3509 QV4::ScopedValue arg0(scope, argv[0]);
3510 if (!arg0->isObject())
3511 THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch");
3512
3513 qreal dx = argv[1].toNumber();
3514 qreal dy = argv[2].toNumber();
3515 qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
3516
3517 if (!qt_is_finite(dx) || !qt_is_finite(dy))
3518 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
3519
3521 if (!imageData)
3523
3524 QV4::Scoped<QQuickJSContext2DPixelData> pixelArray(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
3525 if (pixelArray) {
3526 w = pixelArray->d()->image->width();
3527 h = pixelArray->d()->image->height();
3528
3529 if (argc == 7) {
3530 dirtyX = argv[3].toNumber();
3531 dirtyY = argv[4].toNumber();
3532 dirtyWidth = argv[5].toNumber();
3533 dirtyHeight = argv[6].toNumber();
3534
3535 if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight))
3536 THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
3537
3538
3539 if (dirtyWidth < 0) {
3540 dirtyX = dirtyX+dirtyWidth;
3541 dirtyWidth = -dirtyWidth;
3542 }
3543
3544 if (dirtyHeight < 0) {
3545 dirtyY = dirtyY+dirtyHeight;
3546 dirtyHeight = -dirtyHeight;
3547 }
3548
3549 if (dirtyX < 0) {
3550 dirtyWidth = dirtyWidth+dirtyX;
3551 dirtyX = 0;
3552 }
3553
3554 if (dirtyY < 0) {
3555 dirtyHeight = dirtyHeight+dirtyY;
3556 dirtyY = 0;
3557 }
3558
3559 if (dirtyX+dirtyWidth > w) {
3560 dirtyWidth = w - dirtyX;
3561 }
3562
3563 if (dirtyY+dirtyHeight > h) {
3564 dirtyHeight = h - dirtyY;
3565 }
3566
3567 if (dirtyWidth <=0 || dirtyHeight <= 0)
3569 } else {
3570 dirtyX = 0;
3571 dirtyY = 0;
3572 dirtyWidth = w;
3573 dirtyHeight = h;
3574 }
3575
3576 QImage image = pixelArray->d()->image->copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
3577 r->d()->context()->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight));
3578 }
3579
3580 RETURN_RESULT(*thisObject);
3581}
3582
3606{
3607 QV4::Scope scope(b);
3608 QV4::Scoped<QQuickContext2DStyle> style(scope, thisObject->as<QQuickContext2DStyle>());
3609 if (!style)
3610 THROW_GENERIC_ERROR("Not a CanvasGradient object");
3611
3612 if (argc == 2) {
3613
3614 if (!style->d()->brush->gradient())
3615 THROW_GENERIC_ERROR("Not a valid CanvasGradient object, can't get the gradient information");
3616 QGradient gradient = *(style->d()->brush->gradient());
3617 qreal pos = argv[0].toNumber();
3618 QColor color;
3619
3620 if (argv[1].as<Object>()) {
3622 argv[1], QMetaType::fromType<QColor>()).value<QColor>();
3623 } else {
3624 color = qt_color_from_string(argv[1]);
3625 }
3626 if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) {
3627 THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
3628 }
3629
3630 if (color.isValid()) {
3631 gradient.setColorAt(pos, color);
3632 } else {
3633 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string");
3634 }
3635 *style->d()->brush = gradient;
3636 }
3637
3638 return thisObject->asReturnedValue();
3639}
3640
3642{
3643 if (!state.invertibleCTM)
3644 return;
3645
3646 if (!qt_is_finite(x) || !qt_is_finite(y))
3647 return;
3648
3649 QTransform newTransform = state.matrix;
3650 newTransform.scale(x, y);
3651
3652 if (!newTransform.isInvertible()) {
3653 state.invertibleCTM = false;
3654 return;
3655 }
3656
3657 state.matrix = newTransform;
3658 buffer()->updateMatrix(state.matrix);
3659 m_path = QTransform().scale(1.0 / x, 1.0 / y).map(m_path);
3660}
3661
3663{
3664 if (!state.invertibleCTM)
3665 return;
3666
3667 if (!qt_is_finite(angle))
3668 return;
3669
3670 QTransform newTransform =state.matrix;
3671 newTransform.rotate(qRadiansToDegrees(angle));
3672
3673 if (!newTransform.isInvertible()) {
3674 state.invertibleCTM = false;
3675 return;
3676 }
3677
3678 state.matrix = newTransform;
3679 buffer()->updateMatrix(state.matrix);
3680 m_path = QTransform().rotate(-qRadiansToDegrees(angle)).map(m_path);
3681}
3682
3684{
3685 if (!state.invertibleCTM)
3686 return;
3687
3688 if (!qt_is_finite(h) || !qt_is_finite(v))
3689 return ;
3690
3691 QTransform newTransform = state.matrix;
3692 newTransform.shear(h, v);
3693
3694 if (!newTransform.isInvertible()) {
3695 state.invertibleCTM = false;
3696 return;
3697 }
3698
3699 state.matrix = newTransform;
3700 buffer()->updateMatrix(state.matrix);
3701 m_path = QTransform().shear(-h, -v).map(m_path);
3702}
3703
3705{
3706 if (!state.invertibleCTM)
3707 return;
3708
3709 if (!qt_is_finite(x) || !qt_is_finite(y))
3710 return ;
3711
3712 QTransform newTransform = state.matrix;
3713 newTransform.translate(x, y);
3714
3715 if (!newTransform.isInvertible()) {
3716 state.invertibleCTM = false;
3717 return;
3718 }
3719
3720 state.matrix = newTransform;
3721 buffer()->updateMatrix(state.matrix);
3722 m_path = QTransform().translate(-x, -y).map(m_path);
3723}
3724
3726{
3727 if (!state.invertibleCTM)
3728 return;
3729
3731 return;
3732
3733 QTransform transform(a, b, c, d, e, f);
3734 QTransform newTransform = state.matrix * transform;
3735
3736 if (!newTransform.isInvertible()) {
3737 state.invertibleCTM = false;
3738 return;
3739 }
3740 state.matrix = newTransform;
3741 buffer()->updateMatrix(state.matrix);
3742 m_path = transform.inverted().map(m_path);
3743}
3744
3746{
3748 return;
3749
3750 QTransform ctm = state.matrix;
3751 if (!ctm.isInvertible())
3752 return;
3753
3754 state.matrix = ctm.inverted() * state.matrix;
3755 m_path = ctm.map(m_path);
3756 state.invertibleCTM = true;
3757 transform(a, b, c, d, e, f);
3758}
3759
3761{
3762 if (!state.invertibleCTM)
3763 return;
3764
3765 if (!m_path.elementCount())
3766 return;
3767
3768 m_path.setFillRule(state.fillRule);
3769 buffer()->fill(m_path);
3770}
3771
3773{
3774 if (!state.invertibleCTM)
3775 return;
3776
3777 QPainterPath clipPath = m_path;
3778 clipPath.closeSubpath();
3779 if (state.clip) {
3780 state.clipPath = clipPath.intersected(state.clipPath);
3781 } else {
3782 state.clip = true;
3783 state.clipPath = clipPath;
3784 }
3785 buffer()->clip(state.clip, state.clipPath);
3786}
3787
3789{
3790 if (!state.invertibleCTM)
3791 return;
3792
3793 if (!m_path.elementCount())
3794 return;
3795
3796 buffer()->stroke(m_path);
3797}
3798
3800{
3801 if (!state.invertibleCTM)
3802 return;
3803
3804 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3805 return;
3806
3807 buffer()->fillRect(QRectF(x, y, w, h));
3808}
3809
3811{
3812 if (!state.invertibleCTM)
3813 return;
3814
3815 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3816 return;
3817
3818 buffer()->strokeRect(QRectF(x, y, w, h));
3819}
3820
3822{
3823 if (!state.invertibleCTM)
3824 return;
3825
3826 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3827 return;
3828
3829 buffer()->clearRect(QRectF(x, y, w, h));
3830}
3831
3833{
3834 if (!state.invertibleCTM)
3835 return;
3836
3837 if (!qt_is_finite(x) || !qt_is_finite(y))
3838 return;
3839
3840 QPainterPath textPath = createTextGlyphs(x, y, text);
3841 if (fill)
3842 buffer()->fill(textPath);
3843 else
3844 buffer()->stroke(textPath);
3845}
3846
3847
3849{
3850 if (!m_path.elementCount())
3851 return;
3852 m_path = QPainterPath();
3853}
3854
3856{
3857 if (!m_path.elementCount())
3858 return;
3859
3860 QRectF boundRect = m_path.boundingRect();
3861 if (boundRect.width() || boundRect.height())
3862 m_path.closeSubpath();
3863 //FIXME:QPainterPath set the current point to (0,0) after close subpath
3864 //should be the first point of the previous subpath
3865}
3866
3868{
3869 if (!state.invertibleCTM)
3870 return;
3871
3872 //FIXME: moveTo should not close the previous subpath
3873 m_path.moveTo(QPointF(x, y));
3874}
3875
3877{
3878 if (!state.invertibleCTM)
3879 return;
3880
3881 QPointF pt(x, y);
3882
3883 if (!m_path.elementCount())
3884 m_path.moveTo(pt);
3885 else if (m_path.currentPosition() != pt)
3886 m_path.lineTo(pt);
3887}
3888
3890 qreal x, qreal y)
3891{
3892 if (!state.invertibleCTM)
3893 return;
3894
3895 if (!m_path.elementCount())
3896 m_path.moveTo(QPointF(cpx, cpy));
3897
3898 QPointF pt(x, y);
3899 if (m_path.currentPosition() != pt)
3900 m_path.quadTo(QPointF(cpx, cpy), pt);
3901}
3902
3904 qreal cp2x, qreal cp2y,
3905 qreal x, qreal y)
3906{
3907 if (!state.invertibleCTM)
3908 return;
3909
3910 if (!m_path.elementCount())
3911 m_path.moveTo(QPointF(cp1x, cp1y));
3912
3913 QPointF pt(x, y);
3914 if (m_path.currentPosition() != pt)
3915 m_path.cubicTo(QPointF(cp1x, cp1y), QPointF(cp2x, cp2y), pt);
3916}
3917
3919{
3920 QPointF p0(m_path.currentPosition());
3921
3922 QPointF p1p0((p0.x() - p1.x()), (p0.y() - p1.y()));
3923 QPointF p1p2((p2.x() - p1.x()), (p2.y() - p1.y()));
3924 qreal p1p0_length = std::hypot(p1p0.x(), p1p0.y());
3925 qreal p1p2_length = std::hypot(p1p2.x(), p1p2.y());
3926
3927 qreal cos_phi = QPointF::dotProduct(p1p0, p1p2) / (p1p0_length * p1p2_length);
3928
3929 // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8)
3930 // We could have used areCollinear() here, but since we're reusing
3931 // the variables computed above later on we keep this logic.
3932 if (qFuzzyCompare(std::abs(cos_phi), 1.0)) {
3933 m_path.lineTo(p1);
3934 return;
3935 }
3936
3937 qreal tangent = radius / std::tan(std::acos(cos_phi) / 2);
3938 qreal factor_p1p0 = tangent / p1p0_length;
3939 QPointF t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));
3940
3941 QPointF orth_p1p0(p1p0.y(), -p1p0.x());
3942 qreal orth_p1p0_length = std::hypot(orth_p1p0.x(), orth_p1p0.y());
3943 qreal factor_ra = radius / orth_p1p0_length;
3944
3945 // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
3946 qreal cos_alpha = QPointF::dotProduct(orth_p1p0, p1p2) / (orth_p1p0_length * p1p2_length);
3947 if (cos_alpha < 0.f)
3948 orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
3949
3950 QPointF p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));
3951
3952 // calculate angles for addArc
3953 orth_p1p0 = QPointF(-orth_p1p0.x(), -orth_p1p0.y());
3954 qreal sa = std::atan2(orth_p1p0.y(), orth_p1p0.x());
3955
3956 // anticlockwise logic
3957 bool anticlockwise = false;
3958
3959 qreal factor_p1p2 = tangent / p1p2_length;
3960 QPointF t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
3961 QPointF orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y()));
3962 qreal ea = std::atan2(orth_p1p2.y(), orth_p1p2.x());
3963 if ((sa > ea) && ((sa - ea) < M_PI))
3964 anticlockwise = true;
3965 if ((sa < ea) && ((ea - sa) > M_PI))
3966 anticlockwise = true;
3967
3968 arc(p.x(), p.y(), radius, sa, ea, anticlockwise);
3969}
3970
3972 qreal x2, qreal y2,
3973 qreal radius)
3974{
3975 if (!state.invertibleCTM)
3976 return;
3977
3978 if (!qt_is_finite(x1) || !qt_is_finite(y1) || !qt_is_finite(x2) || !qt_is_finite(y2) || !qt_is_finite(radius))
3979 return;
3980
3981 QPointF st(x1, y1);
3982 QPointF end(x2, y2);
3983
3984 if (!m_path.elementCount())
3985 m_path.moveTo(st);
3986 else if (st == m_path.currentPosition() || st == end || !radius)
3987 lineTo(x1, y1);
3988 else
3989 addArcTo(st, end, radius);
3990 }
3991
3993{
3994 if (!state.invertibleCTM)
3995 return;
3996 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
3997 return;
3998
3999 if (!w && !h) {
4000 m_path.moveTo(x, y);
4001 return;
4002 }
4003 m_path.addRect(x, y, w, h);
4004}
4005
4007 qreal w, qreal h,
4008 qreal xr, qreal yr)
4009{
4010 if (!state.invertibleCTM)
4011 return;
4012
4013 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))
4014 return;
4015
4016 if (!w && !h) {
4017 m_path.moveTo(x, y);
4018 return;
4019 }
4020 m_path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
4021}
4022
4024 qreal w, qreal h)
4025{
4026 if (!state.invertibleCTM)
4027 return;
4028
4029 if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
4030 return;
4031
4032 if (!w && !h) {
4033 m_path.moveTo(x, y);
4034 return;
4035 }
4036
4037 m_path.addEllipse(x, y, w, h);
4038}
4039
4041{
4042 if (!state.invertibleCTM)
4043 return;
4044
4046 path.addText(x, y, state.font, str);
4047 m_path.addPath(path);
4048}
4049
4050void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear, bool antiClockWise)
4051{
4052 if (!state.invertibleCTM)
4053 return;
4054
4055 if (!qt_is_finite(xc) || !qt_is_finite(yc) || !qt_is_finite(sar) || !qt_is_finite(ear) || !qt_is_finite(radius))
4056 return;
4057
4058 if (sar == ear)
4059 return;
4060
4061
4062 //### HACK
4063
4064 // In Qt we don't switch the coordinate system for degrees
4065 // and still use the 0,0 as bottom left for degrees so we need
4066 // to switch
4067 sar = -sar;
4068 ear = -ear;
4069 antiClockWise = !antiClockWise;
4070 //end hack
4071
4072 float sa = qRadiansToDegrees(sar);
4073 float ea = qRadiansToDegrees(ear);
4074
4075 double span = 0;
4076
4077 double xs = xc - radius;
4078 double ys = yc - radius;
4079 double width = radius*2;
4080 double height = radius*2;
4081 if ((!antiClockWise && (ea - sa >= 360)) || (antiClockWise && (sa - ea >= 360)))
4082 // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the
4083 // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole
4084 // circumference of this circle.
4085 span = 360;
4086 else {
4087 if (!antiClockWise && (ea < sa)) {
4088 span += 360;
4089 } else if (antiClockWise && (sa < ea)) {
4090 span -= 360;
4091 }
4092 //### this is also due to switched coordinate system
4093 // we would end up with a 0 span instead of 360
4094 if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) &&
4095 qFuzzyCompare(qAbs(span), 360))) {
4096 span += ea - sa;
4097 }
4098 }
4099
4100 // If the path is empty, move to where the arc will start to avoid painting a line from (0,0)
4101 if (!m_path.elementCount())
4102 m_path.arcMoveTo(xs, ys, width, height, sa);
4103 else if (!radius) {
4104 m_path.lineTo(xc, yc);
4105 return;
4106 }
4107
4108 m_path.arcTo(xs, ys, width, height, sa, span);
4109}
4110
4112{
4113 int offset = 0;
4114 switch (value) {
4117 break;
4119 offset = (metrics.ascent() >> 1) + metrics.height() - metrics.ascent();
4120 break;
4122 offset = metrics.ascent();
4123 break;
4125 offset = metrics.height();
4126 break;
4127 }
4128 return offset;
4129}
4130
4132{
4133 int offset = 0;
4136 else if (value == QQuickContext2D::End)
4138 switch (value) {
4140 offset = metrics.horizontalAdvance(text) / 2;
4141 break;
4143 offset = metrics.horizontalAdvance(text);
4144 break;
4146 default:
4147 break;
4148 }
4149 return offset;
4150}
4151
4153{
4154 m_grabbedImage = grab;
4155 m_grabbed = true;
4156}
4157
4158QQmlRefPointer<QQuickCanvasPixmap> QQuickContext2D::createPixmap(const QUrl& url, QSizeF sourceSize)
4159{
4160 return m_canvas->loadedPixmap(url, sourceSize);
4161}
4162
4164{
4165 const QFontMetrics metrics(state.font);
4166 int yoffset = baseLineOffset(static_cast<QQuickContext2D::TextBaseLineType>(state.textBaseline), metrics);
4168
4169 QPainterPath textPath;
4170
4171 textPath.addText(x - xoffset, y - yoffset+metrics.ascent(), state.font, text);
4172 return textPath;
4173}
4174
4175
4176static inline bool areCollinear(const QPointF& a, const QPointF& b, const QPointF& c)
4177{
4178 // Solved from comparing the slopes of a to b and b to c: (ay-by)/(ax-bx) == (cy-by)/(cx-bx)
4179 return qFuzzyCompare((c.y() - b.y()) * (a.x() - b.x()), (a.y() - b.y()) * (c.x() - b.x()));
4180}
4181
4182static inline bool withinRange(qreal p, qreal a, qreal b)
4183{
4184 return (p >= a && p <= b) || (p >= b && p <= a);
4185}
4186
4188{
4189 if (!state.invertibleCTM)
4190 return false;
4191
4192 if (!m_path.elementCount())
4193 return false;
4194
4195 if (!qt_is_finite(x) || !qt_is_finite(y))
4196 return false;
4197
4198 QPointF point(x, y);
4199 QTransform ctm = state.matrix;
4200 QPointF p = ctm.inverted().map(point);
4201 if (!qt_is_finite(p.x()) || !qt_is_finite(p.y()))
4202 return false;
4203
4204 const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule);
4205
4206 bool contains = m_path.contains(p);
4207
4208 if (!contains) {
4209 // check whether the point is on the border
4210 QPolygonF border = m_path.toFillPolygon();
4211
4212 QPointF p1 = border.at(0);
4213 QPointF p2;
4214
4215 for (int i = 1; i < border.size(); ++i) {
4216 p2 = border.at(i);
4217 if (areCollinear(p, p1, p2)
4218 // Once we know that the points are collinear we
4219 // only need to check one of the coordinates
4220 && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ?
4221 withinRange(p.x(), p1.x(), p2.x()) :
4222 withinRange(p.y(), p1.y(), p2.y()))) {
4223 return true;
4224 }
4225 p1 = p2;
4226 }
4227 }
4228 return contains;
4229}
4230
4232
4234 : QQuickCanvasContext(parent)
4235 , m_buffer(new QQuickContext2DCommandBuffer)
4236 , m_v4engine(nullptr)
4237 , m_surface(nullptr)
4238 , m_thread(nullptr)
4239 , m_grabbed(false)
4240{
4241}
4242
4244{
4245 mutex.lock();
4246 m_texture->setItem(nullptr);
4247 delete m_buffer;
4249
4250 mutex.unlock();
4251}
4252
4257
4259{
4260 return QStringList() << QStringLiteral("2d");
4261}
4262
4264{
4265 Q_UNUSED(args);
4266
4267 m_canvas = canvasItem;
4268 m_renderTarget = canvasItem->renderTarget();
4269 m_renderStrategy = canvasItem->renderStrategy();
4270
4271 // Disable threaded background rendering if the platform has issues with it
4276 }
4277
4278 // Disable framebuffer object based rendering always in Qt 6. It
4279 // is not implemented in the new RHI-based graphics stack, but the
4280 // enum value is still present. Switch to Image instead.
4283
4285
4286 m_texture->setItem(canvasItem);
4287 m_texture->setCanvasWindow(canvasItem->canvasWindow().toRect());
4288 m_texture->setTileSize(canvasItem->tileSize());
4289 m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
4290 m_texture->setSmooth(canvasItem->smooth());
4291 m_texture->setAntialiasing(canvasItem->antialiasing());
4294
4295 QThread *renderThread = m_thread;
4297 renderThread = QQuickContext2DRenderThread::instance(qmlEngine(canvasItem));
4298 if (renderThread && renderThread != QThread::currentThread())
4299 m_texture->moveToThread(renderThread);
4301
4302 reset();
4303}
4304
4305void QQuickContext2D::prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing)
4306{
4308 m_texture->canvasChanged(canvasSize, tileSize, canvasWindow, dirtyRect, smooth, antialiasing);
4309 } else {
4311 tileSize,
4312 canvasWindow,
4313 dirtyRect,
4314 smooth,
4315 antialiasing);
4317 }
4318}
4319
4330
4335
4337{
4339 flush();
4340 m_texture->grabImage(bounds);
4342 qWarning() << "Pixel readback is not supported in Cooperative mode, please try Threaded or Immediate mode";
4343 return QImage();
4344 } else {
4345 flush();
4348 "grabImage",
4350 Q_ARG(QRectF, bounds));
4351 }
4354 m_grabbed = false;
4355 return img;
4356}
4357
4358
4360{
4361 QV4::Scope scope(v4);
4362
4376#if QT_CONFIG(quick_path)
4377 proto->defineAccessorProperty(QStringLiteral("path"), QQuickJSContext2D::method_get_path, QQuickJSContext2D::method_set_path);
4378#endif
4384 contextPrototype = proto;
4385
4386 proto = scope.engine->newObject();
4388 gradientProto = proto;
4389
4390 proto = scope.engine->newObject();
4392 pixelArrayProto = proto;
4393}
4394
4398
4400{
4401 if (m_stateStack.isEmpty())
4402 return;
4403
4405
4406 if (state.matrix != newState.matrix)
4407 buffer()->updateMatrix(newState.matrix);
4408
4409 if (newState.globalAlpha != state.globalAlpha)
4410 buffer()->setGlobalAlpha(newState.globalAlpha);
4411
4412 if (newState.globalCompositeOperation != state.globalCompositeOperation)
4413 buffer()->setGlobalCompositeOperation(newState.globalCompositeOperation);
4414
4415 if (newState.fillStyle != state.fillStyle)
4416 buffer()->setFillStyle(newState.fillStyle);
4417
4418 if (newState.strokeStyle != state.strokeStyle)
4419 buffer()->setStrokeStyle(newState.strokeStyle);
4420
4421 if (newState.lineWidth != state.lineWidth)
4422 buffer()->setLineWidth(newState.lineWidth);
4423
4424 if (newState.lineCap != state.lineCap)
4425 buffer()->setLineCap(newState.lineCap);
4426
4427 if (newState.lineJoin != state.lineJoin)
4428 buffer()->setLineJoin(newState.lineJoin);
4429
4430 if (newState.miterLimit != state.miterLimit)
4431 buffer()->setMiterLimit(newState.miterLimit);
4432
4433 if (newState.clip != state.clip || newState.clipPath != state.clipPath)
4434 buffer()->clip(newState.clip, newState.clipPath);
4435
4436 if (newState.shadowBlur != state.shadowBlur)
4437 buffer()->setShadowBlur(newState.shadowBlur);
4438
4439 if (newState.shadowColor != state.shadowColor)
4440 buffer()->setShadowColor(newState.shadowColor);
4441
4442 if (newState.shadowOffsetX != state.shadowOffsetX)
4443 buffer()->setShadowOffsetX(newState.shadowOffsetX);
4444
4445 if (newState.shadowOffsetY != state.shadowOffsetY)
4446 buffer()->setShadowOffsetY(newState.shadowOffsetY);
4447
4448 if (newState.lineDash != state.lineDash)
4449 buffer()->setLineDash(newState.lineDash);
4450
4452 state = newState;
4454}
4459
4461{
4463
4464 m_path = QPainterPath();
4465
4466 newState.clipPath.setFillRule(Qt::WindingFill);
4467
4470 popState();
4472}
4473
4478
4480{
4481 if (m_v4engine != engine) {
4483
4484 if (m_v4engine == nullptr)
4485 return;
4486
4487 QQuickContext2DEngineData *ed = engineData(engine);
4488 QV4::Scope scope(engine);
4489 QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocate<QQuickJSContext2D>());
4490 QV4::ScopedObject p(scope, ed->contextPrototype.value());
4491 wrapper->setPrototypeOf(p);
4492 wrapper->d()->setContext(this);
4494 }
4495}
4496
4498
4499#include "moc_qquickcontext2d_p.cpp"
Definition main.cpp:8
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QColor toRgb() const noexcept
Create and returns an RGB QColor based on this color.
Definition qcolor.cpp:2035
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
\reentrant
Definition qfont.h:22
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:25
@ Monospace
Definition qfont.h:33
@ Serif
Definition qfont.h:27
@ Cursive
Definition qfont.h:32
@ Fantasy
Definition qfont.h:34
@ SansSerif
Definition qfont.h:26
void setPointSize(int)
Sets the point size to pointSize.
Definition qfont.cpp:985
@ SmallCaps
Definition qfont.h:101
void setFamily(const QString &)
Sets the family name of the font.
Definition qfont.cpp:835
QString defaultFamily() const
Returns the family name that corresponds to the current style hint.
Definition qfont.cpp:2680
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1049
void setStyleHint(StyleHint, StyleStrategy=PreferDefault)
Sets the style hint and strategy to hint and strategy, respectively.
Definition qfont.cpp:1505
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:63
@ StyleItalic
Definition qfont.h:78
@ StyleOblique
Definition qfont.h:79
\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
@ Format_ARGB32
Definition qimage.h:47
constexpr bool isEmpty() const noexcept
\inmodule QtGui
Definition qbrush.h:394
bool isEmpty() const noexcept
Definition qlist.h:401
void clear()
Definition qlist.h:434
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
Definition qobject.cpp:1643
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
\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:456
\inmodule QtCore\reentrant
Definition qpoint.h:217
static constexpr qreal dotProduct(const QPointF &p1, const QPointF &p2)
Definition qpoint.h:242
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
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:75
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr void moveTo(qreal x, qreal y) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:750
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:208
\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:78
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:8249
constexpr QStringView right(qsizetype n) const noexcept
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:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.h:957
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
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:8084
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:3466
QByteArray toUtf8() const &
Definition qstring.h:634
static QThread * currentThread()
Definition qthread.cpp:1039
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.
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:1882
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:298
ReturnedValue value() const
QString str
[2]
QPixmap p2
QPixmap p1
[0]
QString text
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.
quint64 ReturnedValue
Scoped< String > ScopedString
@ 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
QList< QString > QStringList
Constructs a string list that contains the given string, str.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:289
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
double qstrtod(const char *s00, char const **se, bool *ok)
#define qWarning
Definition qlogging.h:166
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:100
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
Definition qnumeric_p.h:117
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
#define SIGNAL(a)
Definition qobjectdefs.h:53
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
GLuint color
[2]
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
GLdouble s
[6]
Definition qopenglext.h:235
GLbyte GLbyte blue
Definition qopenglext.h:385
const GLubyte * c
GLfixed GLfixed GLfixed y2
GLint void * img
Definition qopenglext.h:233
GLenum array
GLfixed GLfixed x2
GLsizei const GLchar *const * path
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void GLsizei void void * span
GLfloat GLfloat p
[1]
GLenum GLsizei len
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:80
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)
Q_QUICK_EXPORT QColor qt_color_from_string(const QV4::Value &name)
#define CHECK_CONTEXT_SETTER(r)
static bool qSetFontSizeFromToken(QFont &font, QStringView fontSizeToken)
static int qParseFontSizeFromToken(QStringView fontSizeToken, bool &ok)
static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionEngine *v4, QImage &&image)
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)
#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:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
#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:18
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
String * id_length() const
QV4::ReturnedValue fromVariant(const QVariant &)
Heap::Object * newObject()
Heap::String * newString(char16_t c)
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
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
void defineAccessorProperty(const QString &name, VTable::Call getter, VTable::Call setter)
bool hasProperty(PropertyKey id) const
bool put(StringOrSymbol *name, const Value &v, Value *receiver=nullptr)
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
int toInt32() const
Definition qv4value_p.h:353
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:323
const T * as() const
Definition qv4value_p.h:132
QString toQString() const
Definition qv4value.cpp:158
QString toQStringNoThrow() const
Definition qv4value.cpp:122
void wrapper()