From 1d48b9ea56e42b2cf963090078ee2162bde23a25 Mon Sep 17 00:00:00 2001 From: Janne Koskinen Date: Wed, 30 Oct 2013 12:08:36 +0200 Subject: Fixed rounding errors in QtQuick1 to int conversions qRound introduced errors when qreal is single precision. Added double signature for qround so that string and int don't lose precision in conversion. Task-number: QTBUG-33625 Change-Id: I58582f57d5cd68fcad3fe9efb5fea5935f61b9e3 Reviewed-by: Olivier Goffart Reviewed-by: Thiago Macieira --- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 9 +++++++-- src/declarative/qml/qdeclarativestringconverters.cpp | 10 ++++++++-- .../qdeclarativevaluetypes/data/qtbug-33625.qml | 12 ++++++++++++ .../qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativevaluetypes/data/qtbug-33625.qml diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 99d34b4..8cfdad2 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -328,7 +328,12 @@ void QDeclarativeObjectScriptClass::setProperty(Object *object, { return setProperty(toQObject(object), name, value, context()); } - +namespace { +int qRoundDouble(double d) +{ + return d >= double(0.0) ? int(d + double(0.5)) : int(d - int(d-1) + double(0.5)) + int(d-1); +} +} void QDeclarativeObjectScriptClass::setProperty(QObject *obj, const Identifier &name, const QScriptValue &value, @@ -405,7 +410,7 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, } else { //### expand optimization for other known types if (lastData->propType == QMetaType::Int && value.isNumber()) { - int rawValue = qRound(value.toNumber()); + int rawValue = qRoundDouble(value.toNumber()); int status = -1; int flags = 0; void *a[] = { (void *)&rawValue, 0, &status, &flags }; diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index bb5eacb..738619d 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -97,13 +97,19 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) return QVariant(s); } +namespace { +int qRoundDouble(double d) +{ + return d >= double(0.0) ? int(d + double(0.5)) : int(d - int(d-1) + double(0.5)) + int(d-1); +} +} QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int preferredType, bool *ok) { switch (preferredType) { case QMetaType::Int: - return QVariant(int(qRound(s.toDouble(ok)))); + return QVariant(int(qRoundDouble(s.toDouble(ok)))); case QMetaType::UInt: - return QVariant(uint(qRound(s.toDouble(ok)))); + return QVariant(uint(qRoundDouble(s.toDouble(ok)))); case QMetaType::QColor: return QVariant::fromValue(colorFromString(s, ok)); #ifndef QT_NO_DATESTRING diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/qtbug-33625.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/qtbug-33625.qml new file mode 100644 index 0000000..977028f --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/qtbug-33625.qml @@ -0,0 +1,12 @@ +import QtQuick 1.0 +Item { + property string stringtest: "16777237" + property int stringint: stringtest + + property int inttest: 16777237 + property int intint: 0 + + Component.onCompleted: { + intint = inttest; + } +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index 87a60e3..a21ffc6 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -96,6 +96,7 @@ private slots: void returnValues(); void varAssignment(); void bindingsSpliceCorrectly(); + void qtbug_33625(); private: QDeclarativeEngine engine; @@ -1012,6 +1013,19 @@ void tst_qdeclarativevaluetypes::bindingsSpliceCorrectly() } } +//qreal as float should not limit int to single precision. +void tst_qdeclarativevaluetypes::qtbug_33625() +{ + QDeclarativeComponent component(&engine, TEST_FILE("qtbug-33625.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("intint").toInt(), 16777237); + QCOMPARE(object->property("stringint").toInt(), 16777237); + + delete object; +} + QTEST_MAIN(tst_qdeclarativevaluetypes) #include "tst_qdeclarativevaluetypes.moc" -- cgit v0.12