aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util/qquickvaluetypes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/util/qquickvaluetypes.cpp')
-rw-r--r--src/quick/util/qquickvaluetypes.cpp256
1 files changed, 209 insertions, 47 deletions
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index a5a9424597..888a9e9ce5 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -5,6 +5,7 @@
#include <qtquickglobal.h>
#include <private/qqmlvaluetype_p.h>
+#include <private/qqmlstringconverters_p.h>
#include <private/qcolorspace_p.h>
#include <private/qfont_p.h>
@@ -162,48 +163,10 @@ void QQuickColorValueType::setHslLightness(qreal hslLightness)
v.setHslF(hue, saturation, hslLightness, alpha);
}
-template<typename T, int NumParams>
-QVariant createValueTypeFromNumberString(const QString &s)
-{
- Q_STATIC_ASSERT_X(NumParams == 2 || NumParams == 3 || NumParams == 4 || NumParams == 16,
- "Unsupported number of params; add an additional case below if necessary.");
-
- if (s.count(u',') != NumParams - 1)
- return QVariant();
-
- QVarLengthArray<float, NumParams> parameters;
- bool ok = true;
- for (qsizetype prev = 0, next = s.indexOf(u','), length = s.size(); ok && prev < length;) {
- parameters.append(s.mid(prev, next - prev).toFloat(&ok));
- prev = next + 1;
- next = (parameters.size() == NumParams - 1) ? length : s.indexOf(u',', prev);
- }
-
- if (!ok)
- return QVariant();
-
- if constexpr (NumParams == 2) {
- return T(parameters[0], parameters[1]);
- } else if constexpr (NumParams == 3) {
- return T(parameters[0], parameters[1], parameters[2]);
- } else if constexpr (NumParams == 4) {
- return T(parameters[0], parameters[1], parameters[2], parameters[3]);
- } else if constexpr (NumParams == 16) {
- return T(parameters[0], parameters[1], parameters[2], parameters[3],
- parameters[4], parameters[5], parameters[6], parameters[7],
- parameters[8], parameters[9], parameters[10], parameters[11],
- parameters[12], parameters[13], parameters[14], parameters[15]);
- } else {
- Q_UNREACHABLE();
- }
-
- return QVariant();
-}
-
QVariant QQuickVector2DValueType::create(const QJSValue &params)
{
if (params.isString())
- return createValueTypeFromNumberString<QVector2D, 2>(params.toString());
+ return QQmlStringConverters::valueTypeFromNumberString<QVector2D, 2, u','>(params.toString());
if (params.isArray())
return QVector2D(params.property(0).toNumber(), params.property(1).toNumber());
return QVariant();
@@ -296,8 +259,10 @@ bool QQuickVector2DValueType::fuzzyEquals(const QVector2D &vec) const
QVariant QQuickVector3DValueType::create(const QJSValue &params)
{
- if (params.isString())
- return createValueTypeFromNumberString<QVector3D, 3>(params.toString());
+ if (params.isString()) {
+ return QQmlStringConverters::valueTypeFromNumberString<QVector3D, 3, u',', u','>(
+ params.toString());
+ }
if (params.isArray()) {
return QVector3D(params.property(0).toNumber(), params.property(1).toNumber(),
@@ -415,8 +380,10 @@ bool QQuickVector3DValueType::fuzzyEquals(const QVector3D &vec) const
QVariant QQuickVector4DValueType::create(const QJSValue &params)
{
- if (params.isString())
- return createValueTypeFromNumberString<QVector4D, 4>(params.toString());
+ if (params.isString()) {
+ return QQmlStringConverters::valueTypeFromNumberString<QVector4D, 4, u',', u',', u','>(
+ params.toString());
+ }
if (params.isArray()) {
return QVector4D(params.property(0).toNumber(), params.property(1).toNumber(),
@@ -542,8 +509,10 @@ bool QQuickVector4DValueType::fuzzyEquals(const QVector4D &vec) const
QVariant QQuickQuaternionValueType::create(const QJSValue &params)
{
- if (params.isString())
- return createValueTypeFromNumberString<QQuaternion, 4>(params.toString());
+ if (params.isString()) {
+ return QQmlStringConverters::valueTypeFromNumberString<QQuaternion, 4, u',', u',', u','>(
+ params.toString());
+ }
if (params.isArray()) {
return QQuaternion(params.property(0).toNumber(), params.property(1).toNumber(),
@@ -682,8 +651,12 @@ QVariant QQuickMatrix4x4ValueType::create(const QJSValue &params)
if (params.isNull() || params.isUndefined())
return QMatrix4x4();
- if (params.isString())
- return createValueTypeFromNumberString<QMatrix4x4, 16>(params.toString());
+ if (params.isString()) {
+ return QQmlStringConverters::valueTypeFromNumberString<QMatrix4x4, 16, u',', u',', u',',
+ u',', u',', u',', u',', u',', u',',
+ u',', u',', u',', u',', u',', u','>(
+ params.toString());
+ }
if (params.isArray() && params.property(QStringLiteral("length")).toInt() == 16) {
return QMatrix4x4(params.property(0).toNumber(),
@@ -790,6 +763,122 @@ bool QQuickMatrix4x4ValueType::fuzzyEquals(const QMatrix4x4 &m) const
return qFuzzyCompare(v, m);
}
+/*!
+ \qmltype PlanarTransform
+ \inqmlmodule QtQuick
+ \since 6.8
+
+ \brief Provides utility functions for matrix4x4 when used for 2D transforms.
+
+ The \c PlanarTransform is a global object with utility functions.
+
+ It is not instantiable; to use it, call the members of the global \c PlanarTransform object
+ directly. For example:
+
+ \qml
+ Item {
+ transform: Matrix4x4 { matrix: PlanarTransform.fromAffineMatrix(1, 0, 0.36, 1, -36, 0) }
+ }
+ \endqml
+*/
+
+QQuickPlanarTransform::QQuickPlanarTransform(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \qmlmethod matrix4x4 PlanarTransform::fromAffineMatrix(real scaleX, real shearY,
+ real shearX, real scaleY,
+ real translateX, real translateY)
+
+ Returns a matrix4x4 for an affine (non-projecting) 2D transform with the specified values.
+
+ This method and its argument order correspond to SVG's \c matrix() function and the
+ six-argument QTransform constructor. The result is this 4x4 matrix:
+
+ \table
+ \row \li \a scaleX \li \a shearX \li 0 \li \a translateX
+ \row \li \a shearY \li \a scaleY \li 0 \li \a translateY
+ \row \li 0 \li 0 \li 1 \li 0
+ \row \li 0 \li 0 \li 0 \li 1
+ \endtable
+*/
+
+QMatrix4x4 QQuickPlanarTransform::fromAffineMatrix(float scaleX, float shearY,
+ float shearX, float scaleY,
+ float translateX, float translateY)
+{
+ return QMatrix4x4(scaleX, shearX, 0, translateX,
+ shearY, scaleY, 0, translateY,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+}
+
+/*!
+ \qmlmethod matrix4x4 PlanarTransform::fromTranslate(real translateX, real translateY)
+
+ Returns a matrix4x4 for a 2D transform that translates by \a translateX horizontally and
+ \a translateY vertically.
+*/
+QMatrix4x4 QQuickPlanarTransform::fromTranslate(float translateX, float translateY)
+{
+ QMatrix4x4 xf;
+ xf.translate(translateX, translateY);
+ return xf;
+}
+
+/*!
+ \qmlmethod matrix4x4 PlanarTransform::fromScale(real scaleX, real scaleY, real originX, real originY)
+
+ Returns a matrix4x4 for a 2D transform that scales by \a scaleX horizontally and \a scaleY
+ vertically, centered at the point (\a originX, \a originY).
+
+ \a originX and \a originY are optional and default to (0, 0).
+*/
+QMatrix4x4 QQuickPlanarTransform::fromScale(float scaleX, float scaleY, float originX, float originY)
+{
+ QMatrix4x4 xf;
+ xf.translate(originX, originY);
+ xf.scale(scaleX, scaleY);
+ xf.translate(-originX, -originY);
+ return xf;
+}
+
+/*!
+ \qmlmethod matrix4x4 PlanarTransform::fromRotate(real angle, real originX, real originY)
+
+ Returns a matrix4x4 for a 2D transform that rotates by \a angle degrees around the point (\a
+ originX, \a originY).
+
+ \a originX and \a originY are optional and default to (0, 0).
+*/
+QMatrix4x4 QQuickPlanarTransform::fromRotate(float angle, float originX, float originY)
+{
+ QMatrix4x4 xf;
+ xf.translate(originX, originY);
+ xf.rotate(angle, 0, 0, 1);
+ xf.translate(-originX, -originY);
+ return xf;
+}
+
+/*!
+ \qmlmethod matrix4x4 PlanarTransform::fromShear(float shearX, float shearY, float originX, float originY)
+
+ Returns a matrix4x4 for a 2D transform that shears by \a shearX horizontally and \a shearY
+ vertically, centered at the point (\a originX, \a originY).
+
+ \a originX and \a originY are optional and default to (0, 0).
+*/
+QMatrix4x4 QQuickPlanarTransform::fromShear(float shearX, float shearY, float originX, float originY)
+{
+ QMatrix4x4 xf;
+ xf.translate(originX, originY);
+ xf *= QMatrix4x4(1, shearX, 0, 0, shearY, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+ xf.translate(-originX, -originY);
+ return xf;
+}
+
template<typename T>
void setFontProperty(QFont &font, void (QFont::*setter)(T value), QString name,
const QJSValue &params, bool *ok)
@@ -1047,6 +1136,79 @@ void QQuickFontValueType::setPreferShaping(bool enable)
v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() | QFont::PreferNoShaping));
}
+void QQuickFontValueType::setVariableAxes(const QVariantMap &variableAxes)
+{
+ v.clearVariableAxes();
+ for (auto [variableAxisName, variableAxisValue] : variableAxes.asKeyValueRange()) {
+ const auto maybeTag = QFont::Tag::fromString(variableAxisName);
+ if (!maybeTag) {
+ qWarning() << "Invalid variable axis" << variableAxisName << "ignored";
+ continue;
+ }
+
+ bool ok;
+ float value = variableAxisValue.toFloat(&ok);
+ if (!ok) {
+ qWarning() << "Variable axis" << variableAxisName << "value" << variableAxisValue << "is not a floating point value.";
+ continue;
+ }
+
+ v.setVariableAxis(*maybeTag, value);
+ }
+}
+
+QVariantMap QQuickFontValueType::variableAxes() const
+{
+ QVariantMap ret;
+ for (const auto &tag : v.variableAxisTags())
+ ret.insert(QString::fromUtf8(tag.toString()), v.variableAxisValue(tag));
+
+ return ret;
+}
+
+void QQuickFontValueType::setFeatures(const QVariantMap &features)
+{
+ v.clearFeatures();
+ for (auto [featureName, featureValue] : features.asKeyValueRange()) {
+ const auto maybeTag = QFont::Tag::fromString(featureName);
+ if (!maybeTag) {
+ qWarning() << "Invalid font feature" << featureName << "ignored";
+ continue;
+ }
+
+ bool ok;
+ quint32 value = featureValue.toUInt(&ok);
+ if (!ok) {
+ qWarning() << "Font feature" << featureName << "value" << featureValue << "is not an integer.";
+ continue;
+ }
+
+ v.setFeature(*maybeTag, value);
+ }
+}
+
+QVariantMap QQuickFontValueType::features() const
+{
+ QVariantMap ret;
+ for (const auto &tag : v.featureTags())
+ ret.insert(QString::fromUtf8(tag.toString()), v.featureValue(tag));
+
+ return ret;
+}
+
+bool QQuickFontValueType::contextFontMerging() const
+{
+ return (v.styleStrategy() & QFont::ContextFontMerging) != 0;
+}
+
+void QQuickFontValueType::setContextFontMerging(bool enable)
+{
+ if (enable)
+ v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() | QFont::ContextFontMerging));
+ else
+ v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() & ~QFont::ContextFontMerging));
+}
+
QVariant QQuickColorSpaceValueType::create(const QJSValue &params)
{
if (!params.isObject())