Add QColor support to v4.
authorMichael Brasser <michael.brasser@nokia.com>
Tue, 28 Feb 2012 06:32:45 +0000 (16:32 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 2 Mar 2012 06:22:53 +0000 (07:22 +0100)
Change-Id: I033e92007f894d45695ea48d7f954d534a2fadee
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
Reviewed-by: Matthew Vogt <matthew.vogt@nokia.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
src/declarative/qml/v4/qv4bindings.cpp
src/declarative/qml/v4/qv4compiler.cpp
src/declarative/qml/v4/qv4instruction.cpp
src/declarative/qml/v4/qv4instruction_p.h
src/declarative/qml/v4/qv4ir.cpp
src/declarative/qml/v4/qv4ir_p.h
src/declarative/qml/v4/qv4irbuilder.cpp
src/declarative/qml/v4/qv4program_p.h
tests/auto/declarative/v4/data/colorType.qml [new file with mode: 0644]
tests/auto/declarative/v4/tst_v4.cpp

index 319dbf5..ecd18cd 100644 (file)
@@ -50,6 +50,7 @@
 #include <private/qdeclarativeprofilerservice_p.h>
 #include <private/qdeclarativemetatype_p.h>
 #include <private/qdeclarativetrace_p.h>
+#include <private/qdeclarativestringconverters_p.h>
 
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include <QtCore/qnumeric.h>
@@ -86,9 +87,11 @@ struct Register {
     QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
     QString *getstringptr() { return (QString *)typeDataPtr(); }
     QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
+    QColor *getcolorptr() { return (QColor *)typeDataPtr(); }
     const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
     const QString *getstringptr() const { return (QString *)typeDataPtr(); }
     const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+    const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); }
 
     void *typeDataPtr() { return (void *)&data; }
     void *typeMemory() { return (void *)data; }
@@ -112,6 +115,7 @@ struct Register {
     inline void cleanup();
     inline void cleanupString();
     inline void cleanupUrl();
+    inline void cleanupColor();
     inline void cleanupVariant();
 
     inline void copy(const Register &other);
@@ -135,6 +139,8 @@ void Register::cleanup()
             getstringptr()->~QString();
         } else if (dataType == QUrlType) {
             geturlptr()->~QUrl();
+        } else if (dataType == QColorType) {
+            getcolorptr()->~QColor();
         } else if (dataType == QVariantType) {
             getvariantptr()->~QVariant();
         }
@@ -154,6 +160,12 @@ void Register::cleanupUrl()
     setUndefined();
 }
 
+void Register::cleanupColor()
+{
+    getcolorptr()->~QColor();
+    setUndefined();
+}
+
 void Register::cleanupVariant()
 {
     getvariantptr()->~QVariant();
@@ -168,6 +180,8 @@ void Register::copy(const Register &other)
             new (getstringptr()) QString(*other.getstringptr());
         else if (other.dataType == QUrlType)
             new (geturlptr()) QUrl(*other.geturlptr());
+        else if (other.dataType == QColorType)
+            new (getcolorptr()) QColor(*other.getcolorptr());
         else if (other.dataType == QVariantType)
             new (getvariantptr()) QVariant(*other.getvariantptr());
     } 
@@ -181,6 +195,8 @@ void Register::init(Type type)
             new (getstringptr()) QString();
         else if (dataType == QUrlType)
             new (geturlptr()) QUrl();
+        else if (dataType == QColorType)
+            new (getcolorptr()) QColor();
         else if (dataType == QVariantType)
             new (getvariantptr()) QVariant();
     }
@@ -663,6 +679,11 @@ inline quint32 QV4Bindings::toUint32(qreal n)
     MARK_REGISTER(reg); \
 }
 
+#define COLOR_REGISTER(reg) { \
+    registers[(reg)].settype(QColorType); \
+    MARK_REGISTER(reg); \
+}
+
 #define VARIANT_REGISTER(reg) { \
     registers[(reg)].settype(QVariantType); \
     MARK_REGISTER(reg); \
@@ -1023,6 +1044,27 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QString tmp(*src.getstringptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupString();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            QColor *colorPtr = output.getcolorptr();
+            new (colorPtr) QColor(QDeclarativeStringConverters::colorFromString(tmp));
+
+            COLOR_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -1060,6 +1102,40 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertUrlToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            // for compatibility with color behavior in v8, always true
+            output.setbool(true);
+        }
+    }
+    QML_V4_END_INSTR(ConvertColorToBool, unaryop)
+
+    QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QColor tmp(*src.getcolorptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupColor();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            // to maintain behaviour with QtQuick 1.0, we just output normal toString() value.
+            new (output.getstringptr()) QString(QVariant(tmp).toString());
+            STRING_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertColorToString, unaryop)
+
     QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
index 29023ae..0a0269d 100644 (file)
@@ -344,6 +344,9 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
         case QMetaType::QUrl:
             regType = QUrlType;
             break;
+        case QMetaType::QColor:
+            regType = QColorType;
+            break;
 
         default:
             if (propTy == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
@@ -581,6 +584,12 @@ void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg)
         gen(i);
         } return;
 
+    case IR::ColorType: {
+        Instr::ConvertColorToBool i;
+        i.output = i.src = reg;
+        gen(i);
+        } return;
+
     default:
         discard();
         break;
@@ -880,6 +889,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
             case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
             case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
             case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
+            case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
             default: break;
             } // switch
         } else if (targetTy == IR::IntType) {
@@ -908,6 +918,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
             case IR::IntType:  opcode = V4Instr::ConvertIntToString; break;
             case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
             case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break;
+            case IR::ColorType: opcode = V4Instr::ConvertColorToString; break;
             default: break;
             } // switch
         } else if (targetTy == IR::UrlType) {
@@ -920,11 +931,17 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
             case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break;
             case IR::IntType:  gen(V4Instr::ConvertIntToString,  convToString); sourceTy = IR::StringType; break;
             case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break;
+            case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break;
             default: break;
             } // switch
 
             if (sourceTy == IR::StringType)
                 opcode = V4Instr::ConvertStringToUrl;
+        } else if (targetTy == IR::ColorType) {
+            switch (sourceTy) {
+            case IR::StringType: opcode = V4Instr::ConvertStringToColor; break;
+            default: break;
+            } // switch
         }
         if (opcode != V4Instr::Noop) {
             V4Instr conv;
@@ -989,6 +1006,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
         case IR::UrlType:
             test.regType = QMetaType::QUrl;
             break;
+        case IR::ColorType:
+            test.regType = QMetaType::QColor;
+            break;
         case IR::SGAnchorLineType:
             test.regType = QDeclarativeMetaType::QQuickAnchorLineMetaTypeId();
             break;
index d470b5b..e9213f5 100644 (file)
@@ -171,12 +171,21 @@ void Bytecode::dump(const V4Instr *i, int address) const
     case V4Instr::ConvertStringToUrl:
         INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertStringToColor:
+        INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertUrlToBool:
         INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
     case V4Instr::ConvertUrlToString:
         INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertColorToBool:
+        INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
+    case V4Instr::ConvertColorToString:
+        INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ResolveUrl:
         INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
index 477a085..d243d3f 100644 (file)
@@ -92,8 +92,11 @@ QT_BEGIN_NAMESPACE
     F(ConvertStringToInt, unaryop) \
     F(ConvertStringToReal, unaryop) \
     F(ConvertStringToUrl, unaryop) \
+    F(ConvertStringToColor, unaryop) \
     F(ConvertUrlToBool, unaryop) \
     F(ConvertUrlToString, unaryop) \
+    F(ConvertColorToBool, unaryop) \
+    F(ConvertColorToString, unaryop) \
     F(ResolveUrl, unaryop) \
     F(MathSinReal, unaryop) \
     F(MathCosReal, unaryop) \
index 149479d..6a30e93 100644 (file)
@@ -59,6 +59,7 @@ inline const char *typeName(Type t)
     case VoidType: return "void";
     case StringType: return "string";
     case UrlType: return "url";
+    case ColorType: return "color";
     case SGAnchorLineType: return "SGAnchorLine";
     case AttachType: return "AttachType";
     case ObjectType: return "object";
@@ -77,7 +78,7 @@ inline bool isNumberType(IR::Type ty)
 
 inline bool isStringType(IR::Type ty)
 {
-    return ty == IR::StringType || ty == IR::UrlType;
+    return ty == IR::StringType || ty == IR::UrlType || ty == IR::ColorType;
 }
 
 IR::Type maxType(IR::Type left, IR::Type right)
index 746995e..f6aae06 100644 (file)
@@ -142,6 +142,7 @@ enum Type {
     VoidType,
     StringType,
     UrlType,
+    ColorType,
     SGAnchorLineType,
     AttachType,
     ObjectType,
index 522bc01..e9f02b0 100644 (file)
@@ -69,6 +69,9 @@ static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine,
     case QMetaType::QUrl:
         return IR::UrlType;
 
+    case QMetaType::QColor:
+        return IR::ColorType;
+
     default:
         if (t == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
             return IR::SGAnchorLineType;
index 1f37786..6792ccb 100644 (file)
@@ -96,6 +96,7 @@ enum QDeclarativeRegisterType {
     QStringType = FirstCleanupType,
     QUrlType,
     QVariantType,
+    QColorType
 };
 
 const char *QV4Program::data() const 
diff --git a/tests/auto/declarative/v4/data/colorType.qml b/tests/auto/declarative/v4/data/colorType.qml
new file mode 100644 (file)
index 0000000..f6a98a4
--- /dev/null
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+QtObject {
+    property bool useMyColor: true
+    property color myColor: "red"
+    property color myOtherColor: "green"
+
+    property color test1: useMyColor ? myColor : myOtherColor
+    property color test2: useMyColor ? "red" : "green"
+    property color test3: useMyColor ? myColor : "green"
+
+    property bool test4: !myColor ? false : true
+
+    property bool test5: myColor != "red"
+    property bool test6: myColor == "#ff0000"
+    property bool test7: myColor != "#00ff00"
+}
+
index 927dc0f..99e3f32 100644 (file)
@@ -45,6 +45,7 @@
 #include <QtDeclarative/qdeclarativeengine.h>
 #include <QtDeclarative/qdeclarativecomponent.h>
 #include <QtCore/qdebug.h>
+#include <QtGui/qcolor.h>
 
 #include <private/qv4compiler_p.h>
 
@@ -73,6 +74,7 @@ private slots:
     void stringComparison();
     void unaryMinus();
     void unaryPlus();
+    void colorType();
 
 private:
     QDeclarativeEngine engine;
@@ -348,6 +350,22 @@ void tst_v4::unaryPlus()
     delete o;
 }
 
+void tst_v4::colorType()
+{
+    QDeclarativeComponent component(&engine, testFileUrl("colorType.qml"));
+
+    QObject *o = component.create();
+    QVERIFY(o != 0);
+    QCOMPARE(o->property("test1").value<QColor>(), QColor("red"));
+    QCOMPARE(o->property("test2").value<QColor>(), QColor("red"));
+    QCOMPARE(o->property("test3").value<QColor>(), QColor("red"));
+    QCOMPARE(o->property("test4").toBool(), true);
+    QCOMPARE(o->property("test5").toBool(), true);
+    QCOMPARE(o->property("test6").toBool(), true);
+    QCOMPARE(o->property("test7").toBool(), true);
+    delete o;
+}
+
 QTEST_MAIN(tst_v4)
 
 #include "tst_v4.moc"