aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-06-26 18:02:35 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-11 01:46:52 +0200
commitf5cb65b35e076facbce45e896902a34da7036135 (patch)
tree7575065fde2d0c14c379a992bf8b3593e21f4881 /src/quick/util
parent5376906de58e1c25c77b7a61800365b6e542542f (diff)
Fix broken value-type support by allowing property definition
In QtQuick 1.x the "variant" property type was supported, which could be used to allow value type properties to be defined in QML. In QtQuick 2.0, we have deprecated the "variant" property, but its replacement ("var") is not suited for defining lightweight C++ type values (such as QColor, QFont, QRectF, QVector3D etc). This commit allows those QML basic types to be used in QML once more, by supporting them in the property definition syntax. Note that since some value types are provided by QtQuick and others are provided by QtQml, if a client imports only QtQml they can define but not use properties of certain types (eg, font). Task-number: QTBUG-21034 Task-number: QTBUG-18217 Change-Id: Ia951a8522f223408d27293bb96c276281a710277 Reviewed-by: Matthew Vogt <matthew.vogt@nokia.com>
Diffstat (limited to 'src/quick/util')
-rw-r--r--src/quick/util/qquickglobal.cpp608
-rw-r--r--src/quick/util/qquickvaluetypes.cpp14
2 files changed, 539 insertions, 83 deletions
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 99caf218a6..1708cf7331 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -42,6 +42,8 @@
#include <private/qquickvaluetypes_p.h>
#include <private/qquickapplication_p.h>
#include <private/qqmlglobal_p.h>
+#include <private/qv8_p.h>
+#include <private/qv8engine_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/qdesktopservices.h>
@@ -188,6 +190,32 @@ private:
class QQuickValueTypeProvider : public QQmlValueTypeProvider
{
public:
+
+#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+ #define ASSERT_VALID_SIZE(size, min) Q_UNUSED(size)
+#else
+ #define ASSERT_VALID_SIZE(size, min) Q_ASSERT(size >= min)
+#endif
+
+ static QVector2D vector2DFromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 1) {
+ int index = s.indexOf(QLatin1Char(','));
+
+ bool xGood, yGood;
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+
+ if (xGood && yGood) {
+ if (ok) *ok = true;
+ return QVector2D(xCoord, yCoord);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QVector2D();
+ }
+
static QVector3D vector3DFromString(const QString &s, bool *ok)
{
if (s.count(QLatin1Char(',')) == 2) {
@@ -232,67 +260,292 @@ public:
return QVector4D();
}
+ static QQuaternion quaternionFromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 3) {
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ int index3 = s.indexOf(QLatin1Char(','), index2+1);
+
+ bool sGood, xGood, yGood, zGood;
+ qreal sCoord = s.left(index).toDouble(&sGood);
+ qreal xCoord = s.mid(index+1, index2-index-1).toDouble(&xGood);
+ qreal yCoord = s.mid(index2+1, index3-index2-1).toDouble(&yGood);
+ qreal zCoord = s.mid(index3+1).toDouble(&zGood);
+
+ if (sGood && xGood && yGood && zGood) {
+ if (ok) *ok = true;
+ return QQuaternion(sCoord, xCoord, yCoord, zCoord);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QQuaternion();
+ }
+
+ static QMatrix4x4 matrix4x4FromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 15) {
+ qreal matValues[16];
+ bool vOK = true;
+ QString mutableStr = s;
+ for (int i = 0; vOK && i < 16; ++i) {
+ int cidx = mutableStr.indexOf(QLatin1Char(','));
+ matValues[i] = mutableStr.left(cidx).toDouble(&vOK);
+ mutableStr = mutableStr.mid(cidx + 1);
+ }
+
+ if (vOK) {
+ if (ok) *ok = true;
+ return QMatrix4x4(matValues);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QMatrix4x4();
+ }
+
+ static QFont fontFromObject(QQmlV8Handle object, QV8Engine *e, bool *ok)
+ {
+ if (ok) *ok = false;
+ QFont retn;
+ v8::Handle<v8::Object> obj = object.toHandle()->ToObject();
+
+ v8::Handle<v8::Value> vbold = obj->Get(v8::String::New("bold"));
+ v8::Handle<v8::Value> vcap = obj->Get(v8::String::New("capitalization"));
+ v8::Handle<v8::Value> vfam = obj->Get(v8::String::New("family"));
+ v8::Handle<v8::Value> vital = obj->Get(v8::String::New("italic"));
+ v8::Handle<v8::Value> vlspac = obj->Get(v8::String::New("letterSpacing"));
+ v8::Handle<v8::Value> vpixsz = obj->Get(v8::String::New("pixelSize"));
+ v8::Handle<v8::Value> vpntsz = obj->Get(v8::String::New("pointSize"));
+ v8::Handle<v8::Value> vstrk = obj->Get(v8::String::New("strikeout"));
+ v8::Handle<v8::Value> vundl = obj->Get(v8::String::New("underline"));
+ v8::Handle<v8::Value> vweight = obj->Get(v8::String::New("weight"));
+ v8::Handle<v8::Value> vwspac = obj->Get(v8::String::New("wordSpacing"));
+
+ // pull out the values, set ok to true if at least one valid field is given.
+ if (!vbold.IsEmpty() && !vbold->IsNull() && !vbold->IsUndefined() && vbold->IsBoolean()) {
+ retn.setBold(vbold->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vcap.IsEmpty() && !vcap->IsNull() && !vcap->IsUndefined() && vcap->IsInt32()) {
+ retn.setCapitalization(static_cast<QFont::Capitalization>(vcap->Int32Value()));
+ if (ok) *ok = true;
+ }
+ if (!vfam.IsEmpty() && !vfam->IsNull() && !vfam->IsUndefined() && vfam->IsString()) {
+ retn.setFamily(e->toString(vfam->ToString()));
+ if (ok) *ok = true;
+ }
+ if (!vital.IsEmpty() && !vital->IsNull() && !vital->IsUndefined() && vital->IsBoolean()) {
+ retn.setItalic(vital->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vlspac.IsEmpty() && !vlspac->IsNull() && !vlspac->IsUndefined() && vlspac->IsNumber()) {
+ retn.setLetterSpacing(QFont::AbsoluteSpacing, vlspac->NumberValue());
+ if (ok) *ok = true;
+ }
+ if (!vpixsz.IsEmpty() && !vpixsz->IsNull() && !vpixsz->IsUndefined() && vpixsz->IsInt32()) {
+ retn.setPixelSize(vpixsz->Int32Value());
+ if (ok) *ok = true;
+ }
+ if (!vpntsz.IsEmpty() && !vpntsz->IsNull() && !vpntsz->IsUndefined() && vpntsz->IsNumber()) {
+ retn.setPointSize(vpntsz->NumberValue());
+ if (ok) *ok = true;
+ }
+ if (!vstrk.IsEmpty() && !vstrk->IsNull() && !vstrk->IsUndefined() && vstrk->IsBoolean()) {
+ retn.setStrikeOut(vstrk->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vundl.IsEmpty() && !vundl->IsNull() && !vundl->IsUndefined() && vundl->IsBoolean()) {
+ retn.setUnderline(vundl->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vweight.IsEmpty() && !vweight->IsNull() && !vweight->IsUndefined() && vweight->IsInt32()) {
+ retn.setWeight(static_cast<QFont::Weight>(vweight->Int32Value()));
+ if (ok) *ok = true;
+ }
+ if (!vwspac.IsEmpty() && !vwspac->IsNull() && !vwspac->IsUndefined() && vwspac->IsNumber()) {
+ retn.setWordSpacing(vwspac->NumberValue());
+ if (ok) *ok = true;
+ }
+
+ return retn;
+ }
+
+ static QMatrix4x4 matrix4x4FromObject(QQmlV8Handle object, bool *ok)
+ {
+ if (ok) *ok = false;
+ v8::Handle<v8::Object> obj = object.toHandle()->ToObject();
+ if (!obj->IsArray())
+ return QMatrix4x4();
+
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(obj);
+ if (array->Length() != 16)
+ return QMatrix4x4();
+
+ qreal matVals[16];
+ for (uint32_t i = 0; i < 16; ++i) {
+ v8::Handle<v8::Value> v = array->Get(i);
+ if (!v->IsNumber())
+ return QMatrix4x4();
+ matVals[i] = v->NumberValue();
+ }
+
+ if (ok) *ok = true;
+ return QMatrix4x4(matVals);
+ }
+
+ template<typename T>
+ bool typedCreate(QQmlValueType *&v)
+ {
+ v = new T;
+ return true;
+ }
+
bool create(int type, QQmlValueType *&v)
{
switch (type) {
case QMetaType::QColor:
- v = new QQuickColorValueType;
- return true;
+ return typedCreate<QQuickColorValueType>(v);
+ case QMetaType::QFont:
+ return typedCreate<QQuickFontValueType>(v);
case QMetaType::QVector2D:
- v = new QQuickVector2DValueType;
- return true;
+ return typedCreate<QQuickVector2DValueType>(v);
case QMetaType::QVector3D:
- v = new QQuickVector3DValueType;
- return true;
+ return typedCreate<QQuickVector3DValueType>(v);
case QMetaType::QVector4D:
- v = new QQuickVector4DValueType;
- return true;
+ return typedCreate<QQuickVector4DValueType>(v);
case QMetaType::QQuaternion:
- v = new QQuickQuaternionValueType;
- return true;
+ return typedCreate<QQuickQuaternionValueType>(v);
case QMetaType::QMatrix4x4:
- v = new QQuickMatrix4x4ValueType;
- return true;
- case QMetaType::QFont:
- v = new QQuickFontValueType;
- return true;
+ return typedCreate<QQuickMatrix4x4ValueType>(v);
default:
- return false;
+ break;
}
+
+ return false;
}
- bool init(int type, void *data, size_t n)
+ template<typename T>
+ bool typedInit(void *data, size_t dataSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- new (color) QColor();
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ new (t) T();
+ return true;
+ }
+
+ bool init(int type, void *data, size_t dataSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedInit<QColor>(data, dataSize);
+ case QMetaType::QFont:
+ return typedInit<QFont>(data, dataSize);
+ case QMetaType::QVector2D:
+ return typedInit<QVector2D>(data, dataSize);
+ case QMetaType::QVector3D:
+ return typedInit<QVector3D>(data, dataSize);
+ case QMetaType::QVector4D:
+ return typedInit<QVector4D>(data, dataSize);
+ case QMetaType::QQuaternion:
+ return typedInit<QQuaternion>(data, dataSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dataSize >= sizeof(QMatrix4x4))
+ return typedInit<QMatrix4x4>(data, dataSize);
+
+ // special case: init matrix-containing qvariant.
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matvar = reinterpret_cast<QVariant *>(data);
+ new (matvar) QVariant(QMatrix4x4());
return true;
+ }
+ default: break;
}
return false;
}
- bool destroy(int type, void *data, size_t n)
+ template<typename T>
+ bool typedDestroy(void *data, size_t dataSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- color->~QColor();
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ t->~T();
+ return true;
+ }
+
+ bool destroy(int type, void *data, size_t dataSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedDestroy<QColor>(data, dataSize);
+ case QMetaType::QFont:
+ return typedDestroy<QFont>(data, dataSize);
+ case QMetaType::QVector2D:
+ return typedDestroy<QVector2D>(data, dataSize);
+ case QMetaType::QVector3D:
+ return typedDestroy<QVector3D>(data, dataSize);
+ case QMetaType::QVector4D:
+ return typedDestroy<QVector4D>(data, dataSize);
+ case QMetaType::QQuaternion:
+ return typedDestroy<QQuaternion>(data, dataSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dataSize >= sizeof(QMatrix4x4))
+ return typedDestroy<QMatrix4x4>(data, dataSize);
+
+ // special case: destroying matrix-containing qvariant.
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matvar = reinterpret_cast<QVariant *>(data);
+ matvar->~QVariant();
return true;
+ }
+ default: break;
}
return false;
}
- bool copy(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedCopyConstruct(const void *src, void *dst, size_t dstSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- new (dstColor) QColor(*srcColor);
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *destT = reinterpret_cast<T *>(dst);
+ new (destT) T(*srcT);
+ return true;
+ }
+
+ bool copy(int type, const void *src, void *dst, size_t dstSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedCopyConstruct<QColor>(src, dst, dstSize);
+ case QMetaType::QFont:
+ return typedCopyConstruct<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedCopyConstruct<QVector2D>(src, dst, dstSize);
+ case QMetaType::QVector3D:
+ return typedCopyConstruct<QVector3D>(src, dst, dstSize);
+ case QMetaType::QVector4D:
+ return typedCopyConstruct<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedCopyConstruct<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedCopyConstruct<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: copying matrix into variant.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMatrix = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatrixVar = reinterpret_cast<QVariant *>(dst);
+ new (dstMatrixVar) QVariant(*srcMatrix);
return true;
+ }
+ default: break;
}
return false;
@@ -301,6 +554,16 @@ public:
bool create(int type, int argc, const void *argv[], QVariant *v)
{
switch (type) {
+ case QMetaType::QFont: // must specify via js-object.
+ break;
+ case QMetaType::QVector2D:
+ if (argc == 1) {
+ const float *xy = reinterpret_cast<const float*>(argv[0]);
+ QVector2D v2(xy[0], xy[1]);
+ *v = QVariant(v2);
+ return true;
+ }
+ break;
case QMetaType::QVector3D:
if (argc == 1) {
const float *xyz = reinterpret_cast<const float*>(argv[0]);
@@ -317,37 +580,66 @@ public:
return true;
}
break;
+ case QMetaType::QQuaternion:
+ if (argc == 1) {
+ const double *sxyz = reinterpret_cast<const double*>(argv[0]);
+ QQuaternion q(sxyz[0], sxyz[1], sxyz[2], sxyz[3]);
+ *v = QVariant(q);
+ return true;
+ }
+ break;
+ case QMetaType::QMatrix4x4:
+ if (argc == 1) {
+ const float *vals = reinterpret_cast<const float*>(argv[0]);
+ QMatrix4x4 m(vals[0], vals[1], vals[2], vals[3],
+ vals[4], vals[5], vals[6], vals[7],
+ vals[8], vals[9], vals[10], vals[11],
+ vals[12], vals[13], vals[14], vals[15]);
+ *v = QVariant(m);
+ return true;
+ }
+ break;
+ default: break;
}
return false;
}
- bool createFromString(int type, const QString &s, void *data, size_t n)
+ template<typename T>
+ bool createFromStringTyped(void *data, size_t dataSize, T initValue)
+ {
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ new (t) T(initValue);
+ return true;
+ }
+
+ bool createFromString(int type, const QString &s, void *data, size_t dataSize)
{
bool ok = false;
switch (type) {
case QMetaType::QColor:
- {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- new (color) QColor(QQuickColorProvider::QColorFromString(s));
- return true;
- }
+ return createFromStringTyped<QColor>(data, dataSize, QQuickColorProvider::QColorFromString(s));
+ case QMetaType::QVector2D:
+ return createFromStringTyped<QVector2D>(data, dataSize, vector2DFromString(s, &ok));
case QMetaType::QVector3D:
- {
- Q_ASSERT(n >= sizeof(QVector3D));
- QVector3D *v3 = reinterpret_cast<QVector3D *>(data);
- new (v3) QVector3D(vector3DFromString(s, &ok));
- return true;
- }
+ return createFromStringTyped<QVector3D>(data, dataSize, vector3DFromString(s, &ok));
case QMetaType::QVector4D:
+ return createFromStringTyped<QVector4D>(data, dataSize, vector4DFromString(s, &ok));
+ case QMetaType::QQuaternion:
+ return createFromStringTyped<QQuaternion>(data, dataSize, quaternionFromString(s, &ok));
+ case QMetaType::QMatrix4x4:
{
- Q_ASSERT(n >= sizeof(QVector4D));
- QVector4D *v4 = reinterpret_cast<QVector4D *>(data);
- new (v4) QVector4D(vector4DFromString(s, &ok));
+ if (dataSize >= sizeof(QMatrix4x4))
+ return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
+
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matVar = reinterpret_cast<QVariant *>(data);
+ new (matVar) QVariant(matrix4x4FromString(s, &ok));
return true;
}
+ default: break;
}
return false;
@@ -374,6 +666,12 @@ public:
bool ok = false;
+ QVector2D v2 = vector2DFromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(v2);
+ return true;
+ }
+
QVector3D v3 = vector3DFromString(s, &ok);
if (ok) {
*v = QVariant::fromValue(v3);
@@ -386,6 +684,18 @@ public:
return true;
}
+ QQuaternion q = quaternionFromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(q);
+ return true;
+ }
+
+ QMatrix4x4 m = matrix4x4FromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(m);
+ return true;
+ }
+
return false;
}
@@ -400,99 +710,245 @@ public:
*v = QVariant::fromValue(c);
return true;
}
+ case QMetaType::QVector2D:
+ {
+ *v = QVariant::fromValue(vector2DFromString(s, &ok));
+ return true;
+ }
case QMetaType::QVector3D:
+ {
*v = QVariant::fromValue(vector3DFromString(s, &ok));
return true;
+ }
case QMetaType::QVector4D:
+ {
*v = QVariant::fromValue(vector4DFromString(s, &ok));
return true;
+ }
+ case QMetaType::QQuaternion:
+ {
+ *v = QVariant::fromValue(quaternionFromString(s, &ok));
+ return true;
+ }
+ case QMetaType::QMatrix4x4:
+ {
+ *v = QVariant::fromValue(matrix4x4FromString(s, &ok));
+ return true;
+ }
+ default:
+ break;
}
return false;
}
+ bool variantFromJsObject(int type, QQmlV8Handle object, QV8Engine *e, QVariant *v)
+ {
+ // must be called with a valid v8 context.
+ Q_ASSERT(object.toHandle()->IsObject());
+ bool ok = false;
+ switch (type) {
+ case QMetaType::QFont:
+ *v = QVariant::fromValue(fontFromObject(object, e, &ok));
+ break;
+ case QMetaType::QMatrix4x4:
+ *v = QVariant::fromValue(matrix4x4FromObject(object, &ok));
+ default: break;
+ }
+
+ return ok;
+ }
+
template<typename T>
bool typedEqual(const void *lhs, const void *rhs)
{
return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs)));
}
- bool equal(int type, const void *lhs, const void *rhs)
+ bool equal(int type, const void *lhs, const void *rhs, size_t rhsSize)
{
switch (type) {
case QMetaType::QColor:
return typedEqual<QColor>(lhs, rhs);
+ case QMetaType::QFont:
+ return typedEqual<QFont>(lhs, rhs);
+ case QMetaType::QVector2D:
+ return typedEqual<QVector2D>(lhs, rhs);
case QMetaType::QVector3D:
return typedEqual<QVector3D>(lhs, rhs);
case QMetaType::QVector4D:
return typedEqual<QVector4D>(lhs, rhs);
+ case QMetaType::QQuaternion:
+ return typedEqual<QQuaternion>(lhs, rhs);
+ case QMetaType::QMatrix4x4:
+ {
+ if (rhsSize >= sizeof(QMatrix4x4))
+ return typedEqual<QMatrix4x4>(lhs, rhs);
+
+ Q_ASSERT(rhsSize >= sizeof(QVariant));
+ QMatrix4x4 rhsmat = reinterpret_cast<const QVariant *>(rhs)->value<QMatrix4x4>();
+ return typedEqual<QMatrix4x4>(lhs, &rhsmat);
+ }
+ default: break;
}
return false;
}
- bool store(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedStore(const void *src, void *dst, size_t dstSize)
+ {
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *dstT = reinterpret_cast<T *>(dst);
+ new (dstT) T(*srcT);
+ return true;
+ }
+
+ bool store(int type, const void *src, void *dst, size_t dstSize)
{
switch (type) {
case QMetaType::QColor:
{
- Q_ASSERT(n >= sizeof(QColor));
+ Q_ASSERT(dstSize >= sizeof(QColor));
const QRgb *rgb = reinterpret_cast<const QRgb *>(src);
QColor *color = reinterpret_cast<QColor *>(dst);
new (color) QColor(QColor::fromRgba(*rgb));
return true;
}
+ case QMetaType::QFont:
+ return typedStore<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedStore<QVector2D>(src, dst, dstSize);
case QMetaType::QVector3D:
- {
- Q_ASSERT(n >= sizeof(QVector3D));
- const QVector3D *srcVector = reinterpret_cast<const QVector3D *>(src);
- QVector3D *dstVector = reinterpret_cast<QVector3D *>(dst);
- new (dstVector) QVector3D(*srcVector);
- return true;
- }
+ return typedStore<QVector3D>(src, dst, dstSize);
case QMetaType::QVector4D:
+ return typedStore<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedStore<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
{
- Q_ASSERT(n >= sizeof(QVector4D));
- const QVector4D *srcVector = reinterpret_cast<const QVector4D *>(src);
- QVector4D *dstVector = reinterpret_cast<QVector4D *>(dst);
- new (dstVector) QVector4D(*srcVector);
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedStore<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: storing matrix into variant
+ // eg, QVMEMO QVMEVariant data cell is big enough to store
+ // QVariant, but not large enough to store QMatrix4x4.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
+ new (dstMatVar) QVariant(*srcMat);
return true;
}
+ default: break;
}
return false;
}
- bool read(int srcType, const void *src, int dstType, void *dst)
+ template<typename T>
+ bool typedRead(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ {
+ T *dstT = reinterpret_cast<T *>(dst);
+ if (srcType == dstType) {
+ ASSERT_VALID_SIZE(srcSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ *dstT = *srcT;
+ } else {
+ *dstT = T();
+ }
+ return true;
+ }
+
+ bool read(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
{
- if (dstType == QMetaType::QColor) {
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- if (srcType == QMetaType::QColor) {
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- *dstColor = *srcColor;
+ switch (dstType) {
+ case QMetaType::QColor:
+ return typedRead<QColor>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QFont:
+ return typedRead<QFont>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector2D:
+ return typedRead<QVector2D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector3D:
+ return typedRead<QVector3D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector4D:
+ return typedRead<QVector4D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QQuaternion:
+ return typedRead<QQuaternion>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QMatrix4x4:
+ {
+ if (srcSize >= sizeof(QMatrix4x4))
+ return typedRead<QMatrix4x4>(srcType, src, srcSize, dstType, dst);
+
+ // the source data may be stored in a QVariant.
+ QMatrix4x4 *dstMat = reinterpret_cast<QMatrix4x4 *>(dst);
+ if (srcType == dstType) {
+ Q_ASSERT(srcSize >= sizeof(QVariant));
+ const QVariant *srcMatVar = reinterpret_cast<const QVariant *>(src);
+ *dstMat = srcMatVar->value<QMatrix4x4>();
} else {
- *dstColor = QColor();
+ *dstMat = QMatrix4x4();
}
return true;
+ }
+ default: break;
}
return false;
}
- bool write(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedWrite(const void *src, void *dst, size_t dstSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- if (*dstColor != *srcColor) {
- *dstColor = *srcColor;
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *dstT = reinterpret_cast<T *>(dst);
+ if (*dstT != *srcT) {
+ *dstT = *srcT;
+ return true;
+ }
+ return false;
+ }
+
+ bool write(int type, const void *src, void *dst, size_t dstSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedWrite<QColor>(src, dst, dstSize);
+ case QMetaType::QFont:
+ return typedWrite<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedWrite<QVector2D>(src, dst, dstSize);
+ case QMetaType::QVector3D:
+ return typedWrite<QVector3D>(src, dst, dstSize);
+ case QMetaType::QVector4D:
+ return typedWrite<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedWrite<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedWrite<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: storing matrix into variant
+ // eg, QVMEMO QVMEVariant data cell is big enough to store
+ // QVariant, but not large enough to store QMatrix4x4.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
+ QMatrix4x4 dstMatVal = dstMatVar->value<QMatrix4x4>();
+ if (dstMatVal != *srcMat) {
+ *dstMatVar = QVariant(*srcMat);
return true;
}
+ return false;
+ }
+ default: break;
}
return false;
}
+#undef ASSERT_VALID_SIZE
};
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index e3da2658b4..4224847311 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -57,7 +57,7 @@ namespace QQuickValueTypes {
}
QQuickColorValueType::QQuickColorValueType(QObject *parent)
- : QQmlValueTypeBase<QColor>(parent)
+ : QQmlValueTypeBase<QColor>(QMetaType::QColor, parent)
{
}
@@ -109,7 +109,7 @@ void QQuickColorValueType::setA(qreal a)
QQuickVector2DValueType::QQuickVector2DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector2D>(parent)
+ : QQmlValueTypeBase<QVector2D>(QMetaType::QVector2D, parent)
{
}
@@ -140,7 +140,7 @@ void QQuickVector2DValueType::setY(qreal y)
QQuickVector3DValueType::QQuickVector3DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector3D>(parent)
+ : QQmlValueTypeBase<QVector3D>(QMetaType::QVector3D, parent)
{
}
@@ -181,7 +181,7 @@ void QQuickVector3DValueType::setZ(qreal z)
QQuickVector4DValueType::QQuickVector4DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector4D>(parent)
+ : QQmlValueTypeBase<QVector4D>(QMetaType::QVector4D, parent)
{
}
@@ -232,7 +232,7 @@ void QQuickVector4DValueType::setW(qreal w)
QQuickQuaternionValueType::QQuickQuaternionValueType(QObject *parent)
- : QQmlValueTypeBase<QQuaternion>(parent)
+ : QQmlValueTypeBase<QQuaternion>(QMetaType::QQuaternion, parent)
{
}
@@ -283,7 +283,7 @@ void QQuickQuaternionValueType::setZ(qreal z)
QQuickMatrix4x4ValueType::QQuickMatrix4x4ValueType(QObject *parent)
- : QQmlValueTypeBase<QMatrix4x4>(parent)
+ : QQmlValueTypeBase<QMatrix4x4>(QMetaType::QMatrix4x4, parent)
{
}
@@ -298,7 +298,7 @@ QString QQuickMatrix4x4ValueType::toString() const
QQuickFontValueType::QQuickFontValueType(QObject *parent)
- : QQmlValueTypeBase<QFont>(parent),
+ : QQmlValueTypeBase<QFont>(QMetaType::QFont, parent),
pixelSizeSet(false),
pointSizeSet(false)
{