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 <private/qquickvaluetypes_p.h>
5
6#include <qtquickglobal.h>
7#include <private/qqmlvaluetype_p.h>
8#include <private/qqmlstringconverters_p.h>
9#include <private/qcolorspace_p.h>
10#include <private/qfont_p.h>
11
12QT_BEGIN_NAMESPACE
13
14QQuickColorValueType::QQuickColorValueType(const QString &string)
15 : QColor(QColor::fromString(name: string))
16{
17}
18
19QVariant QQuickColorValueType::create(const QJSValue &params)
20{
21 return params.isString() ? QColor::fromString(name: params.toString()) : QVariant();
22}
23
24QString QQuickColorValueType::toString() const
25{
26 return QColor::name(format: QColor::alpha() != 255 ? QColor::HexArgb : QColor::HexRgb);
27}
28
29QColor QQuickColorValueType::lighter(qreal factor) const
30{
31 return QColor::lighter(f: int(qRound(d: factor*100.)));
32}
33
34QColor QQuickColorValueType::darker(qreal factor) const
35{
36 return QColor::darker(f: int(qRound(d: factor*100.)));
37}
38
39QColor QQuickColorValueType::alpha(qreal value) const
40{
41 QColor color = *this;
42 color.setAlphaF(value);
43 return color;
44}
45
46QColor QQuickColorValueType::tint(const QColor &tintColor) const
47{
48 int tintAlpha = tintColor.alpha();
49 if (tintAlpha == 0xFF)
50 return tintColor;
51 else if (tintAlpha == 0x00)
52 return *this;
53
54 // tint the base color and return the final color
55 const QColor baseColor = QColor::toRgb();
56 const qreal a = tintColor.alphaF();
57 const qreal inv_a = 1.0 - a;
58
59 const qreal r = tintColor.redF() * a + baseColor.redF() * inv_a;
60 const qreal g = tintColor.greenF() * a + baseColor.greenF() * inv_a;
61 const qreal b = tintColor.blueF() * a + baseColor.blueF() * inv_a;
62
63 return QColor::fromRgbF(r, g, b, a: a + inv_a * baseColor.alphaF());
64}
65
66qreal QQuickColorValueType::r() const
67{
68 return QColor::redF();
69}
70
71qreal QQuickColorValueType::g() const
72{
73 return QColor::greenF();
74}
75
76qreal QQuickColorValueType::b() const
77{
78 return QColor::blueF();
79}
80
81qreal QQuickColorValueType::a() const
82{
83 return QColor::alphaF();
84}
85
86qreal QQuickColorValueType::hsvHue() const
87{
88 return QColor::hsvHueF();
89}
90
91qreal QQuickColorValueType::hsvSaturation() const
92{
93 return QColor::hsvSaturationF();
94}
95
96qreal QQuickColorValueType::hsvValue() const
97{
98 return QColor::valueF();
99}
100
101qreal QQuickColorValueType::hslHue() const
102{
103 return QColor::hslHueF();
104}
105
106qreal QQuickColorValueType::hslSaturation() const
107{
108 return QColor::hslSaturationF();
109}
110
111qreal QQuickColorValueType::hslLightness() const
112{
113 return QColor::lightnessF();
114}
115
116bool QQuickColorValueType::isValid() const
117{
118 return QColor::isValid();
119}
120
121void QQuickColorValueType::setR(qreal r)
122{
123 QColor::setRedF(r);
124}
125
126void QQuickColorValueType::setG(qreal g)
127{
128 QColor::setGreenF(g);
129}
130
131void QQuickColorValueType::setB(qreal b)
132{
133 QColor::setBlueF(b);
134}
135
136void QQuickColorValueType::setA(qreal a)
137{
138 QColor::setAlphaF(a);
139}
140
141void QQuickColorValueType::setHsvHue(qreal hsvHue)
142{
143 float hue, saturation, value, alpha;
144 QColor::getHsvF(h: &hue, s: &saturation, v: &value, a: &alpha);
145 QColor::setHsvF(h: hsvHue, s: saturation, v: value, a: alpha);
146}
147
148void QQuickColorValueType::setHsvSaturation(qreal hsvSaturation)
149{
150 float hue, saturation, value, alpha;
151 QColor::getHsvF(h: &hue, s: &saturation, v: &value, a: &alpha);
152 QColor::setHsvF(h: hue, s: hsvSaturation, v: value, a: alpha);
153}
154
155void QQuickColorValueType::setHsvValue(qreal hsvValue)
156{
157 float hue, saturation, value, alpha;
158 QColor::getHsvF(h: &hue, s: &saturation, v: &value, a: &alpha);
159 QColor::setHsvF(h: hue, s: saturation, v: hsvValue, a: alpha);
160}
161
162void QQuickColorValueType::setHslHue(qreal hslHue)
163{
164 float hue, saturation, lightness, alpha;
165 QColor::getHslF(h: &hue, s: &saturation, l: &lightness, a: &alpha);
166 QColor::setHslF(h: hslHue, s: saturation, l: lightness, a: alpha);
167}
168
169void QQuickColorValueType::setHslSaturation(qreal hslSaturation)
170{
171 float hue, saturation, lightness, alpha;
172 QColor::getHslF(h: &hue, s: &saturation, l: &lightness, a: &alpha);
173 QColor::setHslF(h: hue, s: hslSaturation, l: lightness, a: alpha);
174}
175
176void QQuickColorValueType::setHslLightness(qreal hslLightness)
177{
178 float hue, saturation, lightness, alpha;
179 QColor::getHslF(h: &hue, s: &saturation, l: &lightness, a: &alpha);
180 QColor::setHslF(h: hue, s: saturation, l: hslLightness, a: alpha);
181}
182
183QVariant QQuickVector2DValueType::create(const QJSValue &params)
184{
185 if (params.isString())
186 return QQmlStringConverters::valueTypeFromNumberString<QVector2D, 2, u','>(s: params.toString());
187 if (params.isArray())
188 return QVector2D(params.property(arrayIndex: 0).toNumber(), params.property(arrayIndex: 1).toNumber());
189 return QVariant();
190}
191
192QString QQuickVector2DValueType::toString() const
193{
194 return QString::fromLatin1(ba: "QVector2D(%1, %2)").arg(a: QVector2D::x()).arg(a: QVector2D::y());
195}
196
197qreal QQuickVector2DValueType::x() const
198{
199 return QVector2D::x();
200}
201
202qreal QQuickVector2DValueType::y() const
203{
204 return QVector2D::y();
205}
206
207void QQuickVector2DValueType::setX(qreal x)
208{
209 QVector2D::setX(x);
210}
211
212void QQuickVector2DValueType::setY(qreal y)
213{
214 QVector2D::setY(y);
215}
216
217qreal QQuickVector2DValueType::dotProduct(const QVector2D &vec) const
218{
219 return QVector2D::dotProduct(v1: *this, v2: vec);
220}
221
222QVector2D QQuickVector2DValueType::times(const QVector2D &vec) const
223{
224 return *this * vec;
225}
226
227QVector2D QQuickVector2DValueType::times(qreal scalar) const
228{
229 return *this * scalar;
230}
231
232QVector2D QQuickVector2DValueType::plus(const QVector2D &vec) const
233{
234 return *this + vec;
235}
236
237QVector2D QQuickVector2DValueType::minus(const QVector2D &vec) const
238{
239 return *this - vec;
240}
241
242QVector2D QQuickVector2DValueType::normalized() const
243{
244 return QVector2D::normalized();
245}
246
247qreal QQuickVector2DValueType::length() const
248{
249 return QVector2D::length();
250}
251
252QVector3D QQuickVector2DValueType::toVector3d() const
253{
254 return QVector2D::toVector3D();
255}
256
257QVector4D QQuickVector2DValueType::toVector4d() const
258{
259 return QVector2D::toVector4D();
260}
261
262bool QQuickVector2DValueType::fuzzyEquals(const QVector2D &vec, qreal epsilon) const
263{
264 qreal absEps = qAbs(t: epsilon);
265 if (qAbs(t: QVector2D::x() - vec.x()) > absEps)
266 return false;
267 if (qAbs(t: QVector2D::y() - vec.y()) > absEps)
268 return false;
269 return true;
270}
271
272bool QQuickVector2DValueType::fuzzyEquals(const QVector2D &vec) const
273{
274 return qFuzzyCompare(v1: *this, v2: vec);
275}
276
277QVariant QQuickVector3DValueType::create(const QJSValue &params)
278{
279 if (params.isString()) {
280 return QQmlStringConverters::valueTypeFromNumberString<QVector3D, 3, u',', u','>(
281 s: params.toString());
282 }
283
284 if (params.isArray()) {
285 return QVector3D(params.property(arrayIndex: 0).toNumber(), params.property(arrayIndex: 1).toNumber(),
286 params.property(arrayIndex: 2).toNumber());
287 }
288 return QVariant();
289}
290
291QString QQuickVector3DValueType::toString() const
292{
293 return QString::fromLatin1(ba: "QVector3D(%1, %2, %3)")
294 .arg(a: QVector3D::x()).arg(a: QVector3D::y()).arg(a: QVector3D::z());
295}
296
297qreal QQuickVector3DValueType::x() const
298{
299 return QVector3D::x();
300}
301
302qreal QQuickVector3DValueType::y() const
303{
304 return QVector3D::y();
305}
306
307qreal QQuickVector3DValueType::z() const
308{
309 return QVector3D::z();
310}
311
312void QQuickVector3DValueType::setX(qreal x)
313{
314 QVector3D::setX(x);
315}
316
317void QQuickVector3DValueType::setY(qreal y)
318{
319 QVector3D::setY(y);
320}
321
322void QQuickVector3DValueType::setZ(qreal z)
323{
324 QVector3D::setZ(z);
325}
326
327QVector3D QQuickVector3DValueType::crossProduct(const QVector3D &vec) const
328{
329 return QVector3D::crossProduct(v1: *this, v2: vec);
330}
331
332qreal QQuickVector3DValueType::dotProduct(const QVector3D &vec) const
333{
334 return QVector3D::dotProduct(v1: *this, v2: vec);
335}
336
337QVector3D QQuickVector3DValueType::times(const QMatrix4x4 &m) const
338{
339 return (QVector4D(*this, 1) * m).toVector3DAffine();
340}
341
342QVector3D QQuickVector3DValueType::times(const QVector3D &vec) const
343{
344 return *this * vec;
345}
346
347QVector3D QQuickVector3DValueType::times(qreal scalar) const
348{
349 return *this * scalar;
350}
351
352QVector3D QQuickVector3DValueType::plus(const QVector3D &vec) const
353{
354 return *this + vec;
355}
356
357QVector3D QQuickVector3DValueType::minus(const QVector3D &vec) const
358{
359 return *this - vec;
360}
361
362QVector3D QQuickVector3DValueType::normalized() const
363{
364 return QVector3D::normalized();
365}
366
367qreal QQuickVector3DValueType::length() const
368{
369 return QVector3D::length();
370}
371
372QVector2D QQuickVector3DValueType::toVector2d() const
373{
374 return QVector3D::toVector2D();
375}
376
377QVector4D QQuickVector3DValueType::toVector4d() const
378{
379 return QVector3D::toVector4D();
380}
381
382bool QQuickVector3DValueType::fuzzyEquals(const QVector3D &vec, qreal epsilon) const
383{
384 qreal absEps = qAbs(t: epsilon);
385 if (qAbs(t: QVector3D::x() - vec.x()) > absEps)
386 return false;
387 if (qAbs(t: QVector3D::y() - vec.y()) > absEps)
388 return false;
389 if (qAbs(t: QVector3D::z() - vec.z()) > absEps)
390 return false;
391 return true;
392}
393
394bool QQuickVector3DValueType::fuzzyEquals(const QVector3D &vec) const
395{
396 return qFuzzyCompare(v1: *this, v2: vec);
397}
398
399QVariant QQuickVector4DValueType::create(const QJSValue &params)
400{
401 if (params.isString()) {
402 return QQmlStringConverters::valueTypeFromNumberString<QVector4D, 4, u',', u',', u','>(
403 s: params.toString());
404 }
405
406 if (params.isArray()) {
407 return QVector4D(params.property(arrayIndex: 0).toNumber(), params.property(arrayIndex: 1).toNumber(),
408 params.property(arrayIndex: 2).toNumber(), params.property(arrayIndex: 3).toNumber());
409 }
410
411 return QVariant();
412}
413
414QString QQuickVector4DValueType::toString() const
415{
416 return QString::fromLatin1(ba: "QVector4D(%1, %2, %3, %4)")
417 .arg(a: QVector4D::x()).arg(a: QVector4D::y()).arg(a: QVector4D::z()).arg(a: QVector4D::w());
418}
419
420qreal QQuickVector4DValueType::x() const
421{
422 return QVector4D::x();
423}
424
425qreal QQuickVector4DValueType::y() const
426{
427 return QVector4D::y();
428}
429
430qreal QQuickVector4DValueType::z() const
431{
432 return QVector4D::z();
433}
434
435qreal QQuickVector4DValueType::w() const
436{
437 return QVector4D::w();
438}
439
440void QQuickVector4DValueType::setX(qreal x)
441{
442 QVector4D::setX(x);
443}
444
445void QQuickVector4DValueType::setY(qreal y)
446{
447 QVector4D::setY(y);
448}
449
450void QQuickVector4DValueType::setZ(qreal z)
451{
452 QVector4D::setZ(z);
453}
454
455void QQuickVector4DValueType::setW(qreal w)
456{
457 QVector4D::setW(w);
458}
459
460qreal QQuickVector4DValueType::dotProduct(const QVector4D &vec) const
461{
462 return QVector4D::dotProduct(v1: *this, v2: vec);
463}
464
465QVector4D QQuickVector4DValueType::times(const QVector4D &vec) const
466{
467 return *this * vec;
468}
469
470QVector4D QQuickVector4DValueType::times(const QMatrix4x4 &m) const
471{
472 return *this * m;
473}
474
475QVector4D QQuickVector4DValueType::times(qreal scalar) const
476{
477 return *this * scalar;
478}
479
480QVector4D QQuickVector4DValueType::plus(const QVector4D &vec) const
481{
482 return *this + vec;
483}
484
485QVector4D QQuickVector4DValueType::minus(const QVector4D &vec) const
486{
487 return *this - vec;
488}
489
490QVector4D QQuickVector4DValueType::normalized() const
491{
492 return QVector4D::normalized();
493}
494
495qreal QQuickVector4DValueType::length() const
496{
497 return QVector4D::length();
498}
499
500QVector2D QQuickVector4DValueType::toVector2d() const
501{
502 return QVector4D::toVector2D();
503}
504
505QVector3D QQuickVector4DValueType::toVector3d() const
506{
507 return QVector4D::toVector3D();
508}
509
510bool QQuickVector4DValueType::fuzzyEquals(const QVector4D &vec, qreal epsilon) const
511{
512 qreal absEps = qAbs(t: epsilon);
513 if (qAbs(t: QVector4D::x() - vec.x()) > absEps)
514 return false;
515 if (qAbs(t: QVector4D::y() - vec.y()) > absEps)
516 return false;
517 if (qAbs(t: QVector4D::z() - vec.z()) > absEps)
518 return false;
519 if (qAbs(t: QVector4D::w() - vec.w()) > absEps)
520 return false;
521 return true;
522}
523
524bool QQuickVector4DValueType::fuzzyEquals(const QVector4D &vec) const
525{
526 return qFuzzyCompare(v1: *this, v2: vec);
527}
528
529QVariant QQuickQuaternionValueType::create(const QJSValue &params)
530{
531 if (params.isString()) {
532 return QQmlStringConverters::valueTypeFromNumberString<QQuaternion, 4, u',', u',', u','>(
533 s: params.toString());
534 }
535
536 if (params.isArray()) {
537 return QQuaternion(params.property(arrayIndex: 0).toNumber(), params.property(arrayIndex: 1).toNumber(),
538 params.property(arrayIndex: 2).toNumber(), params.property(arrayIndex: 3).toNumber());
539 }
540
541 return QVariant();
542}
543
544QString QQuickQuaternionValueType::toString() const
545{
546 return QString::fromLatin1(ba: "QQuaternion(%1, %2, %3, %4)")
547 .arg(a: QQuaternion::scalar())
548 .arg(a: QQuaternion::x())
549 .arg(a: QQuaternion::y())
550 .arg(a: QQuaternion::z());
551}
552
553qreal QQuickQuaternionValueType::scalar() const
554{
555 return QQuaternion::scalar();
556}
557
558qreal QQuickQuaternionValueType::x() const
559{
560 return QQuaternion::x();
561}
562
563qreal QQuickQuaternionValueType::y() const
564{
565 return QQuaternion::y();
566}
567
568qreal QQuickQuaternionValueType::z() const
569{
570 return QQuaternion::z();
571}
572
573void QQuickQuaternionValueType::setScalar(qreal scalar)
574{
575 QQuaternion::setScalar(scalar);
576}
577
578void QQuickQuaternionValueType::setX(qreal x)
579{
580 QQuaternion::setX(x);
581}
582
583void QQuickQuaternionValueType::setY(qreal y)
584{
585 QQuaternion::setY(y);
586}
587
588void QQuickQuaternionValueType::setZ(qreal z)
589{
590 QQuaternion::setZ(z);
591}
592
593qreal QQuickQuaternionValueType::dotProduct(const QQuaternion &q) const
594{
595 return QQuaternion::dotProduct(q1: *this, q2: q);
596}
597
598QQuaternion QQuickQuaternionValueType::times(const QQuaternion &q) const
599{
600 return *this * q;
601}
602
603QVector3D QQuickQuaternionValueType::times(const QVector3D &vec) const
604{
605 return *this * vec;
606}
607
608QQuaternion QQuickQuaternionValueType::times(qreal factor) const
609{
610 return *this * factor;
611}
612
613QQuaternion QQuickQuaternionValueType::plus(const QQuaternion &q) const
614{
615 return *this + q;
616}
617
618QQuaternion QQuickQuaternionValueType::minus(const QQuaternion &q) const
619{
620 return *this - q;
621}
622
623QQuaternion QQuickQuaternionValueType::normalized() const
624{
625 return QQuaternion::normalized();
626}
627
628QQuaternion QQuickQuaternionValueType::inverted() const
629{
630 return QQuaternion::inverted();
631}
632
633QQuaternion QQuickQuaternionValueType::conjugated() const
634{
635 return QQuaternion::conjugated();
636}
637
638qreal QQuickQuaternionValueType::length() const
639{
640 return QQuaternion::length();
641}
642
643QVector3D QQuickQuaternionValueType::toEulerAngles() const
644{
645 return QQuaternion::toEulerAngles();
646}
647
648QVector4D QQuickQuaternionValueType::toVector4d() const
649{
650 return QQuaternion::toVector4D();
651}
652
653bool QQuickQuaternionValueType::fuzzyEquals(const QQuaternion &q, qreal epsilon) const
654{
655 qreal absEps = qAbs(t: epsilon);
656 if (qAbs(t: QQuaternion::scalar() - q.scalar()) > absEps)
657 return false;
658 if (qAbs(t: QQuaternion::x() - q.x()) > absEps)
659 return false;
660 if (qAbs(t: QQuaternion::y() - q.y()) > absEps)
661 return false;
662 if (qAbs(t: QQuaternion::z() - q.z()) > absEps)
663 return false;
664 return true;
665}
666
667bool QQuickQuaternionValueType::fuzzyEquals(const QQuaternion &q) const
668{
669 return qFuzzyCompare(q1: *this, q2: q);
670}
671
672QVariant QQuickMatrix4x4ValueType::create(const QJSValue &params)
673{
674 if (params.isNull() || params.isUndefined())
675 return QMatrix4x4();
676
677 if (params.isString()) {
678 return QQmlStringConverters::valueTypeFromNumberString<QMatrix4x4, 16, u',', u',', u',',
679 u',', u',', u',', u',', u',', u',',
680 u',', u',', u',', u',', u',', u','>(
681 s: params.toString());
682 }
683
684 if (params.isArray() && params.property(QStringLiteral("length")).toInt() == 16) {
685 return QMatrix4x4(params.property(arrayIndex: 0).toNumber(),
686 params.property(arrayIndex: 1).toNumber(),
687 params.property(arrayIndex: 2).toNumber(),
688 params.property(arrayIndex: 3).toNumber(),
689 params.property(arrayIndex: 4).toNumber(),
690 params.property(arrayIndex: 5).toNumber(),
691 params.property(arrayIndex: 6).toNumber(),
692 params.property(arrayIndex: 7).toNumber(),
693 params.property(arrayIndex: 8).toNumber(),
694 params.property(arrayIndex: 9).toNumber(),
695 params.property(arrayIndex: 10).toNumber(),
696 params.property(arrayIndex: 11).toNumber(),
697 params.property(arrayIndex: 12).toNumber(),
698 params.property(arrayIndex: 13).toNumber(),
699 params.property(arrayIndex: 14).toNumber(),
700 params.property(arrayIndex: 15).toNumber());
701 }
702
703 return QVariant();
704}
705
706QMatrix4x4 QQuickMatrix4x4ValueType::times(const QMatrix4x4 &m) const
707{
708 return *this * m;
709}
710
711QVector4D QQuickMatrix4x4ValueType::times(const QVector4D &vec) const
712{
713 return *this * vec;
714}
715
716QVector3D QQuickMatrix4x4ValueType::times(const QVector3D &vec) const
717{
718 return QMatrix4x4::map(point: vec);
719}
720
721QMatrix4x4 QQuickMatrix4x4ValueType::times(qreal factor) const
722{
723 return *this * factor;
724}
725
726QMatrix4x4 QQuickMatrix4x4ValueType::plus(const QMatrix4x4 &m) const
727{
728 return *this + m;
729}
730
731QMatrix4x4 QQuickMatrix4x4ValueType::minus(const QMatrix4x4 &m) const
732{
733 return *this - m;
734}
735
736QVector4D QQuickMatrix4x4ValueType::row(int n) const
737{
738 return QMatrix4x4::row(index: n);
739}
740
741QVector4D QQuickMatrix4x4ValueType::column(int m) const
742{
743 return QMatrix4x4::column(index: m);
744}
745
746qreal QQuickMatrix4x4ValueType::determinant() const
747{
748 return QMatrix4x4::determinant();
749}
750
751QMatrix4x4 QQuickMatrix4x4ValueType::inverted() const
752{
753 return QMatrix4x4::inverted();
754}
755
756QMatrix4x4 QQuickMatrix4x4ValueType::transposed() const
757{
758 return QMatrix4x4::transposed();
759}
760
761QPointF QQuickMatrix4x4ValueType::map(const QPointF p) const
762{
763 return QMatrix4x4::map(point: p);
764}
765
766QRectF QQuickMatrix4x4ValueType::mapRect(const QRectF r) const
767{
768 return QMatrix4x4::mapRect(rect: r);
769}
770
771bool QQuickMatrix4x4ValueType::fuzzyEquals(const QMatrix4x4 &m, qreal epsilon) const
772{
773 qreal absEps = qAbs(t: epsilon);
774 for (int i = 0; i < 4; ++i) {
775 for (int j = 0; j < 4; ++j) {
776 if (qAbs(t: (*this)(i,j) - m(i,j)) > absEps) {
777 return false;
778 }
779 }
780 }
781 return true;
782}
783
784bool QQuickMatrix4x4ValueType::fuzzyEquals(const QMatrix4x4 &m) const
785{
786 return qFuzzyCompare(m1: *this, m2: m);
787}
788
789/*!
790 \qmltype PlanarTransform
791 \inqmlmodule QtQuick
792 \since 6.8
793
794 \brief Provides utility functions for matrix4x4 when used for 2D transforms.
795
796 The \c PlanarTransform is a global object with utility functions.
797
798 It is not instantiable; to use it, call the members of the global \c PlanarTransform object
799 directly. For example:
800
801 \qml
802 Item {
803 transform: Matrix4x4 { matrix: PlanarTransform.fromAffineMatrix(1, 0, 0.36, 1, -36, 0) }
804 }
805 \endqml
806*/
807
808QQuickPlanarTransform::QQuickPlanarTransform(QObject *parent)
809 : QObject(parent)
810{
811}
812
813/*!
814 \qmlmethod matrix4x4 PlanarTransform::identity()
815
816 Returns a matrix4x4 for the identity transform.
817
818 This is equivalent to \l Qt::matrix4x4().
819*/
820
821QMatrix4x4 QQuickPlanarTransform::identity()
822{
823 return QMatrix4x4();
824}
825
826/*!
827 \qmlmethod matrix4x4 PlanarTransform::fromAffineMatrix(real scaleX, real shearY,
828 real shearX, real scaleY,
829 real translateX, real translateY)
830
831 Returns a matrix4x4 for an affine (non-projecting) 2D transform with the specified values.
832
833 This method and its argument order correspond to SVG's \c matrix() function and the
834 six-argument QTransform constructor. The result is this 4x4 matrix:
835
836 \table
837 \row \li \a scaleX \li \a shearX \li 0 \li \a translateX
838 \row \li \a shearY \li \a scaleY \li 0 \li \a translateY
839 \row \li 0 \li 0 \li 1 \li 0
840 \row \li 0 \li 0 \li 0 \li 1
841 \endtable
842*/
843
844QMatrix4x4 QQuickPlanarTransform::fromAffineMatrix(float scaleX, float shearY,
845 float shearX, float scaleY,
846 float translateX, float translateY)
847{
848 return QMatrix4x4(scaleX, shearX, 0, translateX,
849 shearY, scaleY, 0, translateY,
850 0, 0, 1, 0,
851 0, 0, 0, 1);
852}
853
854/*!
855 \qmlmethod matrix4x4 PlanarTransform::fromTranslate(real translateX, real translateY)
856
857 Returns a matrix4x4 for a 2D transform that translates by \a translateX horizontally and
858 \a translateY vertically.
859*/
860QMatrix4x4 QQuickPlanarTransform::fromTranslate(float translateX, float translateY)
861{
862 QMatrix4x4 xf;
863 xf.translate(x: translateX, y: translateY);
864 return xf;
865}
866
867/*!
868 \qmlmethod matrix4x4 PlanarTransform::fromScale(real scaleX, real scaleY, real originX, real originY)
869
870 Returns a matrix4x4 for a 2D transform that scales by \a scaleX horizontally and \a scaleY
871 vertically, centered at the point (\a originX, \a originY).
872
873 \a originX and \a originY are optional and default to (0, 0).
874*/
875QMatrix4x4 QQuickPlanarTransform::fromScale(float scaleX, float scaleY, float originX, float originY)
876{
877 QMatrix4x4 xf;
878 xf.translate(x: originX, y: originY);
879 xf.scale(x: scaleX, y: scaleY);
880 xf.translate(x: -originX, y: -originY);
881 return xf;
882}
883
884/*!
885 \qmlmethod matrix4x4 PlanarTransform::fromRotate(real angle, real originX, real originY)
886
887 Returns a matrix4x4 for a 2D transform that rotates by \a angle degrees around the point (\a
888 originX, \a originY).
889
890 \a originX and \a originY are optional and default to (0, 0).
891*/
892QMatrix4x4 QQuickPlanarTransform::fromRotate(float angle, float originX, float originY)
893{
894 QMatrix4x4 xf;
895 xf.translate(x: originX, y: originY);
896 xf.rotate(angle, x: 0, y: 0, z: 1);
897 xf.translate(x: -originX, y: -originY);
898 return xf;
899}
900
901/*!
902 \qmlmethod matrix4x4 PlanarTransform::fromShear(float shearX, float shearY, float originX, float originY)
903
904 Returns a matrix4x4 for a 2D transform that shears by \a shearX horizontally and \a shearY
905 vertically, centered at the point (\a originX, \a originY).
906
907 \a originX and \a originY are optional and default to (0, 0).
908*/
909QMatrix4x4 QQuickPlanarTransform::fromShear(float shearX, float shearY, float originX, float originY)
910{
911 QMatrix4x4 xf;
912 xf.translate(x: originX, y: originY);
913 xf *= QMatrix4x4(1, shearX, 0, 0, shearY, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
914 xf.translate(x: -originX, y: -originY);
915 return xf;
916}
917
918template<typename T>
919void setFontProperty(QFont &font, void (QFont::*setter)(T value), QString name,
920 const QJSValue &params, bool *ok)
921{
922 const QJSValue value = params.property(name);
923
924 if constexpr (std::is_same_v<T, bool>) {
925 if (value.isBool()) {
926 (font.*setter)(value.toBool());
927 *ok = true;
928 }
929 } else if constexpr (std::is_same_v<
930 typename std::remove_cv<typename std::remove_reference<T>::type>::type,
931 QString>) {
932 if (value.isString()) {
933 (font.*setter)(value.toString());
934 *ok = true;
935 }
936 } else if constexpr (std::is_integral_v<T> || std::is_enum_v<T>) {
937 if (value.isNumber()) {
938 (font.*setter)(T(value.toInt()));
939 *ok = true;
940 }
941 } else if constexpr (std::is_floating_point_v<T>) {
942 if (value.isNumber()) {
943 (font.*setter)(value.toNumber());
944 *ok = true;
945 }
946 }
947}
948
949QVariant QQuickFontValueType::create(const QJSValue &params)
950{
951 if (!params.isObject())
952 return QVariant();
953
954 bool ok = false;
955 QFont ret;
956
957 setFontProperty(font&: ret, setter: &QFont::setBold, QStringLiteral("bold"), params, ok: &ok);
958 setFontProperty(font&: ret, setter: &QFont::setCapitalization, QStringLiteral("capitalization"), params, ok: &ok);
959 setFontProperty(font&: ret, setter: &QFont::setFamily, QStringLiteral("family"), params, ok: &ok);
960 setFontProperty(font&: ret, setter: &QFont::setItalic, QStringLiteral("italic"), params, ok: &ok);
961 setFontProperty(font&: ret, setter: &QFont::setPixelSize, QStringLiteral("pixelSize"), params, ok: &ok);
962 setFontProperty(font&: ret, setter: &QFont::setPointSize, QStringLiteral("pointSize"), params, ok: &ok);
963 setFontProperty(font&: ret, setter: &QFont::setStrikeOut, QStringLiteral("strikeout"), params, ok: &ok);
964 setFontProperty(font&: ret, setter: &QFont::setStyleName, QStringLiteral("styleName"), params, ok: &ok);
965 setFontProperty(font&: ret, setter: &QFont::setUnderline, QStringLiteral("underline"), params, ok: &ok);
966 setFontProperty(font&: ret, setter: &QFont::setWeight, QStringLiteral("weight"), params, ok: &ok);
967 setFontProperty(font&: ret, setter: &QFont::setWordSpacing, QStringLiteral("wordSpacing"), params, ok: &ok);
968 setFontProperty(font&: ret, setter: &QFont::setHintingPreference, QStringLiteral("hintingPreference"), params, ok: &ok);
969 setFontProperty(font&: ret, setter: &QFont::setKerning, QStringLiteral("kerning"), params, ok: &ok);
970
971 {
972 const QJSValue vlspac = params.property(QStringLiteral("letterSpacing"));
973 if (vlspac.isNumber()) {
974 ret.setLetterSpacing(type: QFont::AbsoluteSpacing, spacing: vlspac.toNumber());
975 ok = true;
976 }
977 }
978
979 {
980 const QJSValue vshaping = params.property(QStringLiteral("preferShaping"));
981 if (vshaping.isBool()) {
982 const bool enable = vshaping.toBool();
983 const QFont::StyleStrategy strategy = ret.styleStrategy();
984 if (enable)
985 ret.setStyleStrategy(QFont::StyleStrategy(strategy & ~QFont::PreferNoShaping));
986 else
987 ret.setStyleStrategy(QFont::StyleStrategy(strategy | QFont::PreferNoShaping));
988 ok = true;
989 }
990 }
991
992 {
993 const QJSValue typoMetrics = params.property(QStringLiteral("preferTypoLineMetrics"));
994 if (typoMetrics.isBool()) {
995 const bool enable = typoMetrics.toBool();
996 const QFont::StyleStrategy strategy = ret.styleStrategy();
997 if (enable)
998 ret.setStyleStrategy(QFont::StyleStrategy(strategy & ~QFont::PreferTypoLineMetrics));
999 else
1000 ret.setStyleStrategy(QFont::StyleStrategy(strategy | QFont::PreferTypoLineMetrics));
1001 ok = true;
1002 }
1003 }
1004
1005 {
1006 const QJSValue ctxFontMerging = params.property(QStringLiteral("contextFontMerging"));
1007 if (ctxFontMerging.isBool()) {
1008 const bool enable = ctxFontMerging.toBool();
1009 const QFont::StyleStrategy strategy = ret.styleStrategy();
1010 if (enable)
1011 ret.setStyleStrategy(QFont::StyleStrategy(strategy | QFont::ContextFontMerging));
1012 else
1013 ret.setStyleStrategy(QFont::StyleStrategy(strategy & ~QFont::ContextFontMerging));
1014 ok = true;
1015 }
1016 }
1017
1018 {
1019 const QJSValue variableAxes = params.property(QStringLiteral("variableAxes"));
1020 if (variableAxes.isObject()) {
1021 QVariantMap variantMap = variableAxes.toVariant().toMap();
1022 for (auto [variableAxisName, variableAxisValue] : variantMap.asKeyValueRange()) {
1023 const auto maybeTag = QFont::Tag::fromString(view: variableAxisName);
1024 if (!maybeTag) {
1025 qWarning() << "Invalid variable axis" << variableAxisName << "ignored";
1026 continue;
1027 }
1028
1029 bool valueOk;
1030 float value = variableAxisValue.toFloat(ok: &valueOk);
1031 if (!valueOk) {
1032 qWarning() << "Variable axis" << variableAxisName << "value" << variableAxisValue << "is not a floating point value.";
1033 continue;
1034 }
1035
1036 ret.setVariableAxis(tag: *maybeTag, value);
1037 ok = true;
1038 }
1039 }
1040 }
1041
1042 {
1043 const QJSValue features = params.property(QStringLiteral("features"));
1044 if (features.isObject()) {
1045 QVariantMap variantMap = features.toVariant().toMap();
1046 for (auto [featureName, featureValue] : variantMap.asKeyValueRange()) {
1047 const auto maybeTag = QFont::Tag::fromString(view: featureName);
1048 if (!maybeTag) {
1049 qWarning() << "Invalid font feature" << featureName << "ignored";
1050 continue;
1051 }
1052
1053 bool valueOk;
1054 quint32 value = featureValue.toUInt(ok: &valueOk);
1055 if (!valueOk) {
1056 qWarning() << "Font feature" << featureName << "value" << featureValue << "is not an integer.";
1057 continue;
1058 }
1059
1060 ret.setFeature(tag: *maybeTag, value);
1061 ok = true;
1062 }
1063 }
1064 }
1065
1066 return ok ? ret : QVariant();
1067}
1068
1069QString QQuickFontValueType::toString() const
1070{
1071 return QLatin1String("QFont(%1)").arg(args: QFont::toString());
1072}
1073
1074QString QQuickFontValueType::family() const
1075{
1076 return QFont::family();
1077}
1078
1079void QQuickFontValueType::setFamily(const QString &family)
1080{
1081 QFont::setFamily(family);
1082}
1083
1084QString QQuickFontValueType::styleName() const
1085{
1086 return QFont::styleName();
1087}
1088
1089void QQuickFontValueType::setStyleName(const QString &style)
1090{
1091 QFont::setStyleName(style);
1092}
1093
1094bool QQuickFontValueType::bold() const
1095{
1096 return QFont::bold();
1097}
1098
1099void QQuickFontValueType::setBold(bool b)
1100{
1101 QFont::setBold(b);
1102}
1103
1104int QQuickFontValueType::weight() const
1105{
1106 return QFont::weight();
1107}
1108
1109void QQuickFontValueType::setWeight(int w)
1110{
1111 QFont::setWeight(QFont::Weight(w));
1112}
1113
1114bool QQuickFontValueType::italic() const
1115{
1116 return QFont::italic();
1117}
1118
1119void QQuickFontValueType::setItalic(bool b)
1120{
1121 QFont::setItalic(b);
1122}
1123
1124bool QQuickFontValueType::underline() const
1125{
1126 return QFont::underline();
1127}
1128
1129void QQuickFontValueType::setUnderline(bool b)
1130{
1131 QFont::setUnderline(b);
1132}
1133
1134bool QQuickFontValueType::overline() const
1135{
1136 return QFont::overline();
1137}
1138
1139void QQuickFontValueType::setOverline(bool b)
1140{
1141 QFont::setOverline(b);
1142}
1143
1144bool QQuickFontValueType::strikeout() const
1145{
1146 return QFont::strikeOut();
1147}
1148
1149void QQuickFontValueType::setStrikeout(bool b)
1150{
1151 QFont::setStrikeOut(b);
1152}
1153
1154qreal QQuickFontValueType::pointSize() const
1155{
1156 if (QFont::pointSizeF() == -1) {
1157 return QFont::pixelSize() * qreal(72.) / qreal(qt_defaultDpi());
1158 }
1159 return QFont::pointSizeF();
1160}
1161
1162void QQuickFontValueType::setPointSize(qreal size)
1163{
1164 if ((QFont::resolveMask() & QFont::SizeResolved) && QFont::pixelSize() != -1) {
1165 qWarning() << "Both point size and pixel size set. Using pixel size.";
1166 return;
1167 }
1168
1169 if (size >= 0.0) {
1170 QFont::setPointSizeF(size);
1171 }
1172}
1173
1174int QQuickFontValueType::pixelSize() const
1175{
1176 if (QFont::pixelSize() == -1) {
1177 return (QFont::pointSizeF() * qt_defaultDpi()) / qreal(72.);
1178 }
1179 return QFont::pixelSize();
1180}
1181
1182void QQuickFontValueType::setPixelSize(int size)
1183{
1184 if (size >0) {
1185 if ((QFont::resolveMask() & QFont::SizeResolved) && QFont::pointSizeF() != -1)
1186 qWarning() << "Both point size and pixel size set. Using pixel size.";
1187 QFont::setPixelSize(size);
1188 }
1189}
1190
1191QQuickFontEnums::Capitalization QQuickFontValueType::capitalization() const
1192{
1193 return (QQuickFontEnums::Capitalization)QFont::capitalization();
1194}
1195
1196void QQuickFontValueType::setCapitalization(QQuickFontEnums::Capitalization c)
1197{
1198 QFont::setCapitalization((QFont::Capitalization)c);
1199}
1200
1201qreal QQuickFontValueType::letterSpacing() const
1202{
1203 return QFont::letterSpacing();
1204}
1205
1206void QQuickFontValueType::setLetterSpacing(qreal size)
1207{
1208 QFont::setLetterSpacing(type: QFont::AbsoluteSpacing, spacing: size);
1209}
1210
1211qreal QQuickFontValueType::wordSpacing() const
1212{
1213 return QFont::wordSpacing();
1214}
1215
1216void QQuickFontValueType::setWordSpacing(qreal size)
1217{
1218 QFont::setWordSpacing(size);
1219}
1220
1221QQuickFontEnums::HintingPreference QQuickFontValueType::hintingPreference() const
1222{
1223 return QQuickFontEnums::HintingPreference(QFont::hintingPreference());
1224}
1225
1226void QQuickFontValueType::setHintingPreference(QQuickFontEnums::HintingPreference hintingPreference)
1227{
1228 QFont::setHintingPreference(QFont::HintingPreference(hintingPreference));
1229}
1230
1231bool QQuickFontValueType::kerning() const
1232{
1233 return QFont::kerning();
1234}
1235
1236void QQuickFontValueType::setKerning(bool b)
1237{
1238 QFont::setKerning(b);
1239}
1240
1241bool QQuickFontValueType::preferShaping() const
1242{
1243 return (QFont::styleStrategy() & QFont::PreferNoShaping) == 0;
1244}
1245
1246void QQuickFontValueType::setPreferShaping(bool enable)
1247{
1248 if (enable) {
1249 QFont::setStyleStrategy(
1250 static_cast<QFont::StyleStrategy>(QFont::styleStrategy() & ~QFont::PreferNoShaping));
1251 } else {
1252 QFont::setStyleStrategy(
1253 static_cast<QFont::StyleStrategy>(QFont::styleStrategy() | QFont::PreferNoShaping));
1254 }
1255}
1256
1257void QQuickFontValueType::setVariableAxes(const QVariantMap &variableAxes)
1258{
1259 QFont::clearVariableAxes();
1260 for (auto [variableAxisName, variableAxisValue] : variableAxes.asKeyValueRange()) {
1261 const auto maybeTag = QFont::Tag::fromString(view: variableAxisName);
1262 if (!maybeTag) {
1263 qWarning() << "Invalid variable axis" << variableAxisName << "ignored";
1264 continue;
1265 }
1266
1267 bool ok;
1268 float value = variableAxisValue.toFloat(ok: &ok);
1269 if (!ok) {
1270 qWarning() << "Variable axis" << variableAxisName << "value" << variableAxisValue
1271 << "is not a floating point value.";
1272 continue;
1273 }
1274
1275 QFont::setVariableAxis(tag: *maybeTag, value);
1276 }
1277}
1278
1279QVariantMap QQuickFontValueType::variableAxes() const
1280{
1281 QVariantMap ret;
1282 for (const auto &tag : QFont::variableAxisTags())
1283 ret.insert(key: QString::fromUtf8(ba: tag.toString()), value: QFont::variableAxisValue(tag));
1284
1285 return ret;
1286}
1287
1288void QQuickFontValueType::setFeatures(const QVariantMap &features)
1289{
1290 QFont::clearFeatures();
1291 for (auto [featureName, featureValue] : features.asKeyValueRange()) {
1292 const auto maybeTag = QFont::Tag::fromString(view: featureName);
1293 if (!maybeTag) {
1294 qWarning() << "Invalid font feature" << featureName << "ignored";
1295 continue;
1296 }
1297
1298 bool ok;
1299 quint32 value = featureValue.toUInt(ok: &ok);
1300 if (!ok) {
1301 qWarning() << "Font feature" << featureName << "value" << featureValue << "is not an integer.";
1302 continue;
1303 }
1304
1305 QFont::setFeature(tag: *maybeTag, value);
1306 }
1307}
1308
1309QVariantMap QQuickFontValueType::features() const
1310{
1311 QVariantMap ret;
1312 for (const auto &tag : QFont::featureTags())
1313 ret.insert(key: QString::fromUtf8(ba: tag.toString()), value: QFont::featureValue(tag));
1314
1315 return ret;
1316}
1317
1318bool QQuickFontValueType::contextFontMerging() const
1319{
1320 return (QFont::styleStrategy() & QFont::ContextFontMerging) != 0;
1321}
1322
1323void QQuickFontValueType::setContextFontMerging(bool enable)
1324{
1325 if (enable) {
1326 QFont::setStyleStrategy(
1327 static_cast<QFont::StyleStrategy>(
1328 QFont::styleStrategy() | QFont::ContextFontMerging));
1329 } else {
1330 QFont::setStyleStrategy(
1331 static_cast<QFont::StyleStrategy>(
1332 QFont::styleStrategy() & ~QFont::ContextFontMerging));
1333 }
1334}
1335
1336bool QQuickFontValueType::preferTypoLineMetrics() const
1337{
1338 return (QFont::styleStrategy() & QFont::PreferTypoLineMetrics) != 0;
1339}
1340
1341void QQuickFontValueType::setPreferTypoLineMetrics(bool enable)
1342{
1343 if (enable) {
1344 QFont::setStyleStrategy(
1345 static_cast<QFont::StyleStrategy>(
1346 QFont::styleStrategy() | QFont::PreferTypoLineMetrics));
1347 } else {
1348 QFont::setStyleStrategy(
1349 static_cast<QFont::StyleStrategy>(
1350 QFont::styleStrategy() & ~QFont::PreferTypoLineMetrics));
1351 }
1352}
1353
1354QVariant QQuickColorSpaceValueType::create(const QJSValue &params)
1355{
1356 if (!params.isObject())
1357 return QVariant();
1358
1359
1360 const QJSValue vName = params.property(QStringLiteral("namedColorSpace"));
1361 if (vName.isNumber())
1362 return QColorSpace((QColorSpace::NamedColorSpace)vName.toInt());
1363
1364 const QJSValue vPri = params.property(QStringLiteral("primaries"));
1365 const QJSValue vTra = params.property(QStringLiteral("transferFunction"));
1366 if (!vPri.isNumber() || !vTra.isNumber())
1367 return QVariant();
1368
1369 QColorSpace::Primaries pri = static_cast<QColorSpace::Primaries>(vPri.toInt());
1370 QColorSpace::TransferFunction tra = static_cast<QColorSpace::TransferFunction>(vTra.toInt());
1371 float gamma = 0.0f;
1372 if (tra == QColorSpace::TransferFunction::Gamma) {
1373 const QJSValue vGam = params.property(QStringLiteral("gamma"));
1374 if (!vGam.isNumber())
1375 return QVariant();
1376 gamma = vGam.toNumber();
1377 }
1378
1379 return QColorSpace(pri, tra, gamma);
1380}
1381
1382QQuickColorSpaceEnums::NamedColorSpace QQuickColorSpaceValueType::namedColorSpace() const noexcept
1383{
1384 if (const auto *p = QColorSpacePrivate::get(colorSpace: *this))
1385 return (QQuickColorSpaceEnums::NamedColorSpace)p->namedColorSpace;
1386 return QQuickColorSpaceEnums::Unknown;
1387}
1388void QQuickColorSpaceValueType::setNamedColorSpace(
1389 QQuickColorSpaceEnums::NamedColorSpace namedColorSpace)
1390{
1391 *this = { (QColorSpace::NamedColorSpace)namedColorSpace };
1392}
1393
1394QQuickColorSpaceEnums::Primaries QQuickColorSpaceValueType::primaries() const noexcept
1395{
1396 return (QQuickColorSpaceEnums::Primaries)QColorSpace::primaries();
1397}
1398
1399void QQuickColorSpaceValueType::setPrimaries(QQuickColorSpaceEnums::Primaries primariesId)
1400{
1401 QColorSpace::setPrimaries((QColorSpace::Primaries)primariesId);
1402}
1403
1404QQuickColorSpaceEnums::TransferFunction QQuickColorSpaceValueType::transferFunction() const noexcept
1405{
1406 return (QQuickColorSpaceEnums::TransferFunction)QColorSpace::transferFunction();
1407}
1408
1409void QQuickColorSpaceValueType::setTransferFunction(
1410 QQuickColorSpaceEnums::TransferFunction transferFunction)
1411{
1412 QColorSpace::setTransferFunction(
1413 transferFunction: (QColorSpace::TransferFunction)transferFunction, gamma: QColorSpace::gamma());
1414}
1415
1416float QQuickColorSpaceValueType::gamma() const noexcept
1417{
1418 return QColorSpace::gamma();
1419}
1420
1421void QQuickColorSpaceValueType::setGamma(float gamma)
1422{
1423 QColorSpace::setTransferFunction(transferFunction: QColorSpace::transferFunction(), gamma);
1424}
1425
1426QT_END_NAMESPACE
1427
1428#include "moc_qquickvaluetypes_p.cpp"
1429

source code of qtdeclarative/src/quick/util/qquickvaluetypes.cpp