aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp1
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/doc/src/javascript/functionlist.qdoc21
-rw-r--r--src/qml/jit/qv4assembler.cpp10
-rw-r--r--src/qml/jit/qv4assembler_p.h2
-rw-r--r--src/qml/jsapi/qjsengine.cpp4
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp33
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp23
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h11
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp11
-rw-r--r--src/qml/qml/qqmlcomponent.cpp19
-rw-r--r--src/qml/qml/qqmlcontext.cpp7
-rw-r--r--src/qml/qml/qqmlfile.cpp3
-rw-r--r--src/qml/qml/qqmlmemoryprofiler.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp5
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h16
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp9
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp6
-rw-r--r--src/quick/items/qquickborderimage.cpp88
-rw-r--r--src/quick/items/qquickborderimage_p_p.h11
-rw-r--r--src/quick/items/qquickitem.cpp1
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp197
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h42
-rw-r--r--src/quick/items/qquickspriteengine.cpp2
-rw-r--r--src/quick/items/qquicktextcontrol.cpp19
-rw-r--r--src/quick/items/qquicktextcontrol_p.h1
-rw-r--r--src/quick/items/qquicktextedit.cpp7
-rw-r--r--src/quick/items/qquicktextinput.cpp50
-rw-r--r--src/quick/items/qquicktextinput_p_p.h2
-rw-r--r--src/quick/items/qquickview.cpp3
-rw-r--r--src/quick/items/qquickwindow.cpp4
-rw-r--r--src/quick/items/qquickwindowmodule.cpp10
-rw-r--r--src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp3
-rw-r--r--src/quick/scenegraph/qsgbasicimagenode.cpp495
-rw-r--r--src/quick/scenegraph/qsgbasicimagenode_p.h9
-rw-r--r--src/quickwidgets/qquickwidget.cpp5
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp48
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp15
-rw-r--r--tests/auto/qmldevtools/compile/compile.pro1
-rw-r--r--tests/auto/quick/qquickborderimage/data/mesh.qml22
-rw-r--r--tests/auto/quick/qquickborderimage/data/nonmesh.qml11
-rw-r--r--tests/auto/quick/qquickborderimage/qquickborderimage.pro1
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp17
-rw-r--r--tests/auto/quick/qquickwindow/data/changeVisibilityInCompleted.qml47
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp23
-rw-r--r--tests/auto/quick/scenegraph/scenegraph.pro1
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp42
-rw-r--r--tests/auto/quick/shared/visualtestutil.cpp35
-rw-r--r--tests/auto/quick/shared/visualtestutil.h2
55 files changed, 998 insertions, 418 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 065e91109b..d4757bed39 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -236,7 +236,6 @@ void Document::collectTypeReferences()
// ### FIXME: We could report the more accurate location here by using prop->location, but the old
// compiler can't and the tests expect it to be the object location right now.
QV4::CompiledData::TypeReference &r = typeReferences.add(prop->customTypeNameIndex, obj->location);
- r.needsCreation = true;
r.errorWhenNotFound = true;
}
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 6f0b5f9b32..8990db075d 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -620,8 +620,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
- virtual QV4::ExecutableAllocator::ChunkOfPages *chunkForFunction(int /*functionIndex*/) { return 0; }
-
void markObjects(QV4::ExecutionEngine *e);
protected:
diff --git a/src/qml/doc/src/javascript/functionlist.qdoc b/src/qml/doc/src/javascript/functionlist.qdoc
index 8b9c33f994..b9a25a2440 100644
--- a/src/qml/doc/src/javascript/functionlist.qdoc
+++ b/src/qml/doc/src/javascript/functionlist.qdoc
@@ -231,6 +231,26 @@
\li \l {Number::toLocaleString}{toLocaleString(locale, format, precision)}
\endlist
+ \section2 The Number Object
+
+ \section3 Value Properties
+
+ \list
+ \li NaN
+ \li NEGATIVE_INFINITY
+ \li POSITIVE_INFINITY
+ \li MAX_VALUE
+ \li MIN_VALUE
+ \li EPSILON // ECMAScript 6: Added in Qt 5.8
+ \endlist
+
+ \section3 Function Properties
+
+ \list
+ \li isFinite(x) // ECMAScript 6: Added in Qt 5.8
+ \li isNaN(x) // ECMAScript 6: Added in Qt 5.8
+ \endlist
+
\section1 The Math Object
\section2 Value Properties
@@ -264,6 +284,7 @@
\li pow(x, y)
\li random()
\li round(x)
+ \li sign(x) // ECMAScript 6: Added in Qt 5.8
\li sin(x)
\li sqrt(x)
\li tan(x)
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 3da1aaa010..7d0d93b63a 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -79,16 +79,6 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
}
}
-QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
-{
- if (functionIndex < 0 || functionIndex >= codeRefs.count())
- return 0;
- JSC::ExecutableMemoryHandle *handle = codeRefs[functionIndex].executableMemory();
- if (!handle)
- return 0;
- return handle->chunk();
-}
-
const Assembler::VoidType Assembler::Void;
Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 6c7d27b2f4..9a681bc9ba 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -83,8 +83,6 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
virtual void linkBackendToEngine(QV4::ExecutionEngine *engine);
- virtual QV4::ExecutableAllocator::ChunkOfPages *chunkForFunction(int functionIndex);
-
// Coderef + execution engine
QVector<JSC::MacroAssemblerCodeRef> codeRefs;
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 4241213c09..424d5548a1 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -255,10 +255,8 @@ QT_BEGIN_NAMESPACE
\l{ECMA-262}, Section 15.1.
*/
QJSEngine::QJSEngine()
- : QObject(*new QJSEnginePrivate, 0)
- , d(new QV8Engine(this))
+ : QJSEngine(nullptr)
{
- QJSEnginePrivate::addToDebugServer(this);
}
/*!
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index e00a3445da..ea7a3b06ce 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -71,7 +71,6 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
ReturnedValue evalCall(CallData *callData, bool directCall) const;
- using Object::construct;
static ReturnedValue call(const Managed *that, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 4a304b6138..5528409b40 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -80,22 +80,24 @@ Heap::MathObject::MathObject()
m->defineDefaultProperty(QStringLiteral("pow"), QV4::MathObject::method_pow, 2);
m->defineDefaultProperty(QStringLiteral("random"), QV4::MathObject::method_random, 0);
m->defineDefaultProperty(QStringLiteral("round"), QV4::MathObject::method_round, 1);
+ m->defineDefaultProperty(QStringLiteral("sign"), QV4::MathObject::method_sign, 1);
m->defineDefaultProperty(QStringLiteral("sin"), QV4::MathObject::method_sin, 1);
m->defineDefaultProperty(QStringLiteral("sqrt"), QV4::MathObject::method_sqrt, 1);
m->defineDefaultProperty(QStringLiteral("tan"), QV4::MathObject::method_tan, 1);
}
-/* copies the sign from y to x and returns the result */
-static double copySign(double x, double y)
+#ifdef Q_OS_ANDROID
+// C++11's std::copysign is missing in the std namespace, so get it from the root namespace (math.h)
+static Q_ALWAYS_INLINE double copySign(double x, double y)
{
- uchar *xch = (uchar *)&x;
- uchar *ych = (uchar *)&y;
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- xch[0] = (xch[0] & 0x7f) | (ych[0] & 0x80);
- else
- xch[7] = (xch[7] & 0x7f) | (ych[7] & 0x80);
- return x;
+ return ::copysign(x, y);
+}
+#else // Ok, we have a proper C++11 standard library
+static Q_ALWAYS_INLINE double copySign(double x, double y)
+{
+ return std::copysign(x, y);
}
+#endif
ReturnedValue MathObject::method_abs(CallContext *context)
{
@@ -299,6 +301,19 @@ ReturnedValue MathObject::method_round(CallContext *context)
return Encode(v);
}
+ReturnedValue MathObject::method_sign(CallContext *context)
+{
+ double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+
+ if (std::isnan(v))
+ return Encode(qt_qnan());
+
+ if (qIsNull(v))
+ return v;
+
+ return Encode(std::signbit(v) ? -1 : 1);
+}
+
ReturnedValue MathObject::method_sin(CallContext *context)
{
double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 2b842a312f..01e778d9ec 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -84,6 +84,7 @@ struct MathObject: Object
static ReturnedValue method_pow(CallContext *context);
static ReturnedValue method_random(CallContext *context);
static ReturnedValue method_round(CallContext *context);
+ static ReturnedValue method_sign(CallContext *context);
static ReturnedValue method_sin(CallContext *context);
static ReturnedValue method_sqrt(CallContext *context);
static ReturnedValue method_tan(CallContext *context);
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index ab3e03b183..f6b3e9a2b3 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -45,6 +45,7 @@
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
#include <cassert>
+#include <limits>
using namespace QV4;
@@ -99,12 +100,16 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
ctor->defineReadonlyProperty(QStringLiteral("POSITIVE_INFINITY"), Primitive::fromDouble(qInf()));
ctor->defineReadonlyProperty(QStringLiteral("MAX_VALUE"), Primitive::fromDouble(1.7976931348623158e+308));
+ ctor->defineReadonlyProperty(QStringLiteral("EPSILON"), Primitive::fromDouble(std::numeric_limits<double>::epsilon()));
QT_WARNING_PUSH
QT_WARNING_DISABLE_INTEL(239)
ctor->defineReadonlyProperty(QStringLiteral("MIN_VALUE"), Primitive::fromDouble(5e-324));
QT_WARNING_POP
+ ctor->defineDefaultProperty(QStringLiteral("isFinite"), method_isFinite, 1);
+ ctor->defineDefaultProperty(QStringLiteral("isNaN"), method_isNaN, 1);
+
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
@@ -134,6 +139,24 @@ inline double thisNumber(ExecutionContext *ctx)
return n->value();
}
+ReturnedValue NumberPrototype::method_isFinite(CallContext *ctx)
+{
+ if (!ctx->argc())
+ return Encode(false);
+
+ double v = ctx->args()[0].toNumber();
+ return Encode(!std::isnan(v) && !qt_is_inf(v));
+}
+
+ReturnedValue NumberPrototype::method_isNaN(CallContext *ctx)
+{
+ if (!ctx->argc())
+ return Encode(false);
+
+ double v = ctx->args()[0].toNumber();
+ return Encode(std::isnan(v));
+}
+
ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index ca6f686304..bbe22af4bb 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -87,6 +87,8 @@ struct NumberPrototype: NumberObject
{
void init(ExecutionEngine *engine, Object *ctor);
+ static ReturnedValue method_isFinite(CallContext *ctx);
+ static ReturnedValue method_isNaN(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_toLocaleString(CallContext *ctx);
static ReturnedValue method_valueOf(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index bf153223a0..ded2b541dc 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -39,6 +39,17 @@
#ifndef QV4RUNTIMEAPI_P_H
#define QV4RUNTIMEAPI_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qv4global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 57cdd3f47f..8c342e0592 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -211,11 +211,8 @@ QQmlApplicationEngine::QQmlApplicationEngine(QObject *parent)
This is provided as a convenience, and is the same as using the empty constructor and calling load afterwards.
*/
QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent)
- : QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
+ : QQmlApplicationEngine(parent)
{
- Q_D(QQmlApplicationEngine);
- d->init();
- QJSEnginePrivate::addToDebugServer(this);
load(url);
}
@@ -228,12 +225,8 @@ QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent)
This is provided as a convenience, and is the same as using the empty constructor and calling load afterwards.
*/
QQmlApplicationEngine::QQmlApplicationEngine(const QString &filePath, QObject *parent)
- : QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
+ : QQmlApplicationEngine(QUrl::fromLocalFile(filePath), parent)
{
- Q_D(QQmlApplicationEngine);
- d->init();
- QJSEnginePrivate::addToDebugServer(this);
- load(QUrl::fromLocalFile(filePath));
}
/*!
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index fbd2d13e40..61a4b701c0 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -511,11 +511,8 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent)
\sa loadUrl()
*/
QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *parent)
-: QObject(*(new QQmlComponentPrivate), parent)
+ : QQmlComponent(engine, url, QQmlComponent::PreferSynchronous, parent)
{
- Q_D(QQmlComponent);
- d->engine = engine;
- d->loadUrl(url);
}
/*!
@@ -530,10 +527,9 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *paren
*/
QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, CompilationMode mode,
QObject *parent)
-: QObject(*(new QQmlComponentPrivate), parent)
+ : QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->engine = engine;
d->loadUrl(url, mode);
}
@@ -545,11 +541,8 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, CompilationMod
*/
QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
QObject *parent)
-: QObject(*(new QQmlComponentPrivate), parent)
+ : QQmlComponent(engine, fileName, QQmlComponent::PreferSynchronous, parent)
{
- Q_D(QQmlComponent);
- d->engine = engine;
- d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
}
/*!
@@ -561,10 +554,9 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
*/
QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
CompilationMode mode, QObject *parent)
-: QObject(*(new QQmlComponentPrivate), parent)
+ : QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->engine = engine;
d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)), mode);
}
@@ -572,10 +564,9 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
\internal
*/
QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start, QObject *parent)
- : QObject(*(new QQmlComponentPrivate), parent)
+ : QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->engine = engine;
d->cc = cc;
cc->addref();
d->start = start;
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 65a337f4e5..af06405376 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -516,12 +516,7 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int ind
QQmlContextData::QQmlContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
- isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- publicContext(0), activeVMEData(0),
- contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
- componentAttached(0)
+ : QQmlContextData(nullptr)
{
}
diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
index 8ce0cc2026..7a441dd9ff 100644
--- a/src/qml/qml/qqmlfile.cpp
+++ b/src/qml/qml/qqmlfile.cpp
@@ -227,9 +227,8 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QUrl &url)
}
QQmlFile::QQmlFile(QQmlEngine *e, const QString &url)
-: d(new QQmlFilePrivate)
+ : QQmlFile(e, QUrl(url))
{
- load(e, url);
}
QQmlFile::~QQmlFile()
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/qml/qqmlmemoryprofiler.cpp
index d9e121bb1b..60f6d96eaf 100644
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ b/src/qml/qml/qqmlmemoryprofiler.cpp
@@ -97,12 +97,9 @@ static bool openLibrary()
return state == Loaded;
}
-QQmlMemoryScope::QQmlMemoryScope(const QUrl &url) : pushed(false)
+QQmlMemoryScope::QQmlMemoryScope(const QUrl &url)
+ : QQmlMemoryScope(url.path().toUtf8().constData())
{
- if (openLibrary() && memprofile_is_enabled()) {
- memprofile_push_location(url.path().toUtf8().constData(), 0);
- pushed = true;
- }
}
QQmlMemoryScope::QQmlMemoryScope(const char *string) : pushed(false)
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 0522aa93ee..4ac13d1cb4 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -249,11 +249,8 @@ QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
Creates a new QQmlPropertyCache of \a metaObject.
*/
QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject)
- : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+ : QQmlPropertyCache(e)
{
- Q_ASSERT(engine);
Q_ASSERT(metaObject);
update(metaObject);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 4fb84198d9..b2171dd86b 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -496,6 +496,14 @@ int QQmlPropertyRawData::encodedIndex() const
return isValueTypeVirtual()?QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeCoreIndex):coreIndex;
}
+inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
+{
+ if (p && p->notFullyResolved())
+ resolve(p);
+
+ return p;
+}
+
inline QQmlPropertyData *QQmlPropertyCache::property(int index) const
{
if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count()))
@@ -556,14 +564,6 @@ int QQmlPropertyCache::signalOffset() const
return signalHandlerIndexCacheStart;
}
-inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
-{
- if (p && p->notFullyResolved())
- resolve(p);
-
- return p;
-}
-
QQmlMetaObject::QQmlMetaObject()
{
}
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 28bbaf0e92..44fd47244d 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -523,7 +523,7 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
QVariantList variantList = customCurveVariant;
if ((variantList.count() % 6) == 0) {
bool allRealsOk = true;
- QList<qreal> reals;
+ QVector<qreal> reals;
const int variantListCount = variantList.count();
reals.reserve(variantListCount);
for (int i = 0; i < variantListCount; i++) {
@@ -557,9 +557,10 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant)
QVariantList QQmlEasingValueType::bezierCurve() const
{
QVariantList rv;
- QVector<QPointF> points = v.toCubicSpline();
- for (int ii = 0; ii < points.count(); ++ii)
- rv << QVariant(points.at(ii).x()) << QVariant(points.at(ii).y());
+ const QVector<QPointF> points = v.toCubicSpline();
+ rv.reserve(points.size() * 2);
+ for (const auto &point : points)
+ rv << QVariant(point.x()) << QVariant(point.y());
return rv;
}
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index cd80cba855..6e5fa516db 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -235,10 +235,8 @@ void QQmlDelegateModelPrivate::init()
}
QQmlDelegateModel::QQmlDelegateModel()
-: QQmlInstanceModel(*(new QQmlDelegateModelPrivate(0)))
+ : QQmlDelegateModel(nullptr, nullptr)
{
- Q_D(QQmlDelegateModel);
- d->init();
}
QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent)
@@ -2357,7 +2355,7 @@ QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
QQmlDelegateModelGroup::QQmlDelegateModelGroup(
const QString &name, QQmlDelegateModel *model, int index, QObject *parent)
- : QObject(*new QQmlDelegateModelGroupPrivate, parent)
+ : QQmlDelegateModelGroup(parent)
{
Q_D(QQmlDelegateModelGroup);
d->name = name;
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 5f8dd7b989..b3a35e6219 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -574,6 +574,52 @@ void QQuickBorderImage::doUpdate()
update();
}
+void QQuickBorderImagePrivate::calculateRects(const QQuickScaleGrid *border,
+ const QSize &sourceSize,
+ const QSizeF &targetSize,
+ int horizontalTileMode,
+ int verticalTileMode,
+ qreal devicePixelRatio,
+ QRectF *targetRect,
+ QRectF *innerTargetRect,
+ QRectF *innerSourceRect,
+ QRectF *subSourceRect)
+{
+ *innerSourceRect = QRectF(0, 0, 1, 1);
+ *targetRect = QRectF(0, 0, targetSize.width(), targetSize.height());
+ *innerTargetRect = *targetRect;
+
+ if (border) {
+ *innerSourceRect = QRectF(border->left() * devicePixelRatio / qreal(sourceSize.width()),
+ border->top() * devicePixelRatio / qreal(sourceSize.height()),
+ qMax<qreal>(0, sourceSize.width() - (border->right() + border->left()) * devicePixelRatio) / sourceSize.width(),
+ qMax<qreal>(0, sourceSize.height() - (border->bottom() + border->top()) * devicePixelRatio) / sourceSize.height());
+ *innerTargetRect = QRectF(border->left(),
+ border->top(),
+ qMax<qreal>(0, targetSize.width() - (border->right() + border->left())),
+ qMax<qreal>(0, targetSize.height() - (border->bottom() + border->top())));
+ }
+
+ qreal hTiles = 1;
+ qreal vTiles = 1;
+ const QSizeF innerTargetSize = innerTargetRect->size() * devicePixelRatio;
+ if (innerSourceRect->width() != 0
+ && horizontalTileMode != QQuickBorderImage::Stretch) {
+ hTiles = innerTargetSize.width() / qreal(innerSourceRect->width() * sourceSize.width());
+ if (horizontalTileMode == QQuickBorderImage::Round)
+ hTiles = qCeil(hTiles);
+ }
+ if (innerSourceRect->height() != 0
+ && verticalTileMode != QQuickBorderImage::Stretch) {
+ vTiles = innerTargetSize.height() / qreal(innerSourceRect->height() * sourceSize.height());
+ if (verticalTileMode == QQuickBorderImage::Round)
+ vTiles = qCeil(vTiles);
+ }
+
+ *subSourceRect = QRectF(0, 0, hTiles, vTiles);
+}
+
+
QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickBorderImage);
@@ -598,45 +644,25 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
node->setTexture(texture);
// Don't implicitly create the scalegrid in the rendering thread...
- QRectF innerSourceRect(0, 0, 1, 1);
- QRectF targetRect(0, 0, width(), height());
- QRectF innerTargetRect = targetRect;
- if (d->border) {
- const QQuickScaleGrid *border = d->getScaleGrid();
- innerSourceRect = QRectF(border->left() * d->devicePixelRatio / qreal(d->pix.width()),
- border->top() * d->devicePixelRatio / qreal(d->pix.height()),
- qMax<qreal>(0, d->pix.width() - (border->right() + border->left()) * d->devicePixelRatio) / d->pix.width(),
- qMax<qreal>(0, d->pix.height() - (border->bottom() + border->top()) * d->devicePixelRatio) / d->pix.height());
- innerTargetRect = QRectF(border->left(),
- border->top(),
- qMax<qreal>(0, width() - (border->right() + border->left())),
- qMax<qreal>(0, height() - (border->bottom() + border->top())));
- }
- qreal hTiles = 1;
- qreal vTiles = 1;
- const QSizeF innerTargetSize = innerTargetRect.size() * d->devicePixelRatio;
- if (innerSourceRect.width() != 0
- && d->horizontalTileMode != QQuickBorderImage::Stretch) {
- hTiles = innerTargetSize.width() / qreal(innerSourceRect.width() * d->pix.width());
- if (d->horizontalTileMode == QQuickBorderImage::Round)
- hTiles = qCeil(hTiles);
- }
- if (innerSourceRect.height() != 0
- && d->verticalTileMode != QQuickBorderImage::Stretch) {
- vTiles = innerTargetSize.height() / qreal(innerSourceRect.height() * d->pix.height());
- if (d->verticalTileMode == QQuickBorderImage::Round)
- vTiles = qCeil(vTiles);
- }
+ QRectF targetRect;
+ QRectF innerTargetRect;
+ QRectF innerSourceRect;
+ QRectF subSourceRect;
+ d->calculateRects(d->border,
+ QSize(d->pix.width(), d->pix.height()), QSizeF(width(), height()),
+ d->horizontalTileMode, d->verticalTileMode, d->devicePixelRatio,
+ &targetRect, &innerTargetRect,
+ &innerSourceRect, &subSourceRect);
node->setTargetRect(targetRect);
node->setInnerSourceRect(innerSourceRect);
node->setInnerTargetRect(innerTargetRect);
- node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
+ node->setSubSourceRect(subSourceRect);
node->setMirror(d->mirror);
node->setMipmapFiltering(QSGTexture::None);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) {
+ if (innerSourceRect == QRectF(0, 0, 1, 1) && (subSourceRect.width() > 1 || subSourceRect.height() > 1)) {
node->setHorizontalWrapMode(QSGTexture::Repeat);
node->setVerticalWrapMode(QSGTexture::Repeat);
} else {
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 1dc530e34e..56fbbab049 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -91,6 +91,17 @@ public:
return border;
}
+ static void calculateRects(const QQuickScaleGrid *border,
+ const QSize &sourceSize,
+ const QSizeF &targetSize,
+ int horizontalTileMode,
+ int verticalTileMode,
+ qreal devicePixelRatio,
+ QRectF *targetRect,
+ QRectF *innerTargetRect,
+ QRectF *innerSourceRect,
+ QRectF *subSourceRect);
+
QQuickScaleGrid *border;
QUrl sciurl;
QQuickBorderImage::TileMode horizontalTileMode;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index ea2cb5aa5f..1100b12cbc 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -4152,6 +4152,7 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
v = (bool)(flags() & ItemAcceptsInputMethod);
break;
case Qt::ImHints:
+ case Qt::ImAnchorRectangle:
case Qt::ImCursorRectangle:
case Qt::ImFont:
case Qt::ImCursorPosition:
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 5f5809b6f2..fb5bc3683f 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -297,6 +297,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickShaderEffect, 2>(uri, 2, 8, "ShaderEffect");
qmlRegisterUncreatableType<QQuickRendererInfo>(uri, 2, 8,"RendererInfo", QQuickRendererInfo::tr("RendererInfo is only available via attached properties"));
+ qmlRegisterType<QQuickBorderImageMesh>("QtQuick", 2, 8, "BorderImageMesh");
}
static void initResources()
diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp
index d7765cdc69..f5cc19c877 100644
--- a/src/quick/items/qquickshadereffectmesh.cpp
+++ b/src/quick/items/qquickshadereffectmesh.cpp
@@ -39,6 +39,10 @@
#include "qquickshadereffectmesh_p.h"
#include <QtQuick/qsggeometry.h>
+#include "qquickshadereffect_p.h"
+#include "qquickscalegrid_p_p.h"
+#include "qquickborderimage_p_p.h"
+#include <QtQuick/private/qsgbasicimagenode_p.h>
QT_BEGIN_NAMESPACE
@@ -239,4 +243,197 @@ QSize QQuickGridMesh::resolution() const
return m_resolution;
}
+/*!
+ \qmltype BorderImageMesh
+ \instantiates QQuickBorderImageMesh
+ \inqmlmodule QtQuick
+ \since 5.8
+ \ingroup qtquick-effects
+ \brief Defines a mesh with vertices arranged like those of a BorderImage.
+
+ BorderImageMesh provides BorderImage-like capabilities to a ShaderEffect
+ without the need for a potentially costly ShaderEffectSource.
+
+ The following are functionally equivalent:
+ \qml
+ BorderImage {
+ id: borderImage
+ border {
+ left: 10
+ right: 10
+ top: 10
+ bottom: 10
+ }
+ source: "myImage.png"
+ visible: false
+ }
+ ShaderEffectSource {
+ id: effectSource
+ sourceItem: borderImage
+ visible: false
+ }
+ ShaderEffect {
+ property var source: effectSource
+ ...
+ }
+ \endqml
+
+ \qml
+ Image {
+ id: image
+ source: "myImage.png"
+ visible: false
+ }
+ ShaderEffect {
+ property var source: image
+ mesh: BorderImageMesh {
+ border {
+ left: 10
+ right: 10
+ top: 10
+ bottom: 10
+ }
+ size: image.sourceSize
+ }
+ ...
+ }
+ \endqml
+
+ But the BorderImageMesh version can typically be better optimized.
+*/
+QQuickBorderImageMesh::QQuickBorderImageMesh(QObject *parent)
+ : QQuickShaderEffectMesh(parent), m_border(new QQuickScaleGrid(this)),
+ m_horizontalTileMode(QQuickBorderImageMesh::Stretch),
+ m_verticalTileMode(QQuickBorderImageMesh::Stretch)
+{
+}
+
+bool QQuickBorderImageMesh::validateAttributes(const QVector<QByteArray> &attributes, int *posIndex)
+{
+ Q_UNUSED(attributes);
+ Q_UNUSED(posIndex);
+ return true;
+}
+
+QSGGeometry *QQuickBorderImageMesh::updateGeometry(QSGGeometry *geometry, int attrCount, int posIndex,
+ const QRectF &srcRect, const QRectF &rect)
+{
+ Q_UNUSED(attrCount);
+ Q_UNUSED(posIndex);
+
+ QRectF innerSourceRect;
+ QRectF targetRect;
+ QRectF innerTargetRect;
+ QRectF subSourceRect;
+
+ QQuickBorderImagePrivate::calculateRects(m_border, m_size, rect.size(), m_horizontalTileMode, m_verticalTileMode,
+ 1, &targetRect, &innerTargetRect, &innerSourceRect, &subSourceRect);
+
+ QRectF sourceRect = srcRect;
+ QRectF modifiedInnerSourceRect(sourceRect.x() + innerSourceRect.x() * sourceRect.width(),
+ sourceRect.y() + innerSourceRect.y() * sourceRect.height(),
+ innerSourceRect.width() * sourceRect.width(),
+ innerSourceRect.height() * sourceRect.height());
+
+ geometry = QSGBasicImageNode::updateGeometry(targetRect, innerTargetRect, sourceRect,
+ modifiedInnerSourceRect, subSourceRect, geometry);
+
+ return geometry;
+}
+
+/*!
+ \qmlpropertygroup QtQuick::BorderImageMesh::border
+ \qmlproperty int QtQuick::BorderImageMesh::border.left
+ \qmlproperty int QtQuick::BorderImageMesh::border.right
+ \qmlproperty int QtQuick::BorderImageMesh::border.top
+ \qmlproperty int QtQuick::BorderImageMesh::border.bottom
+
+ The 4 border lines (2 horizontal and 2 vertical) break the image into 9 sections,
+ as shown below:
+
+ \image declarative-scalegrid.png
+
+ Each border line (left, right, top, and bottom) specifies an offset in pixels
+ from the respective edge of the mesh. By default, each border line has
+ a value of 0.
+
+ For example, the following definition sets the bottom line 10 pixels up from
+ the bottom of the mesh:
+
+ \qml
+ BorderImageMesh {
+ border.bottom: 10
+ // ...
+ }
+ \endqml
+*/
+QQuickScaleGrid *QQuickBorderImageMesh::border()
+{
+ return m_border;
+}
+
+/*!
+ \qmlproperty size QtQuick::BorderImageMesh::size
+
+ The base size of the mesh. This generally corresponds to the \l {Image::}{sourceSize}
+ of the image being used by the ShaderEffect.
+*/
+QSize QQuickBorderImageMesh::size() const
+{
+ return m_size;
+}
+
+void QQuickBorderImageMesh::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+ m_size = size;
+ Q_EMIT sizeChanged();
+ Q_EMIT geometryChanged();
+}
+
+/*!
+ \qmlproperty enumeration QtQuick::BorderImageMesh::horizontalTileMode
+ \qmlproperty enumeration QtQuick::BorderImageMesh::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of an image.
+
+ \list
+ \li BorderImage.Stretch - Scales the image to fit to the available area.
+ \li BorderImage.Repeat - Tile the image until there is no more space. May crop the last image.
+ \li BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+
+ The default tile mode for each property is BorderImage.Stretch.
+*/
+
+QQuickBorderImageMesh::TileMode QQuickBorderImageMesh::horizontalTileMode() const
+{
+ return m_horizontalTileMode;
+}
+
+void QQuickBorderImageMesh::setHorizontalTileMode(TileMode t)
+{
+ if (t == m_horizontalTileMode)
+ return;
+ m_horizontalTileMode = t;
+ Q_EMIT horizontalTileModeChanged();
+ Q_EMIT geometryChanged();
+}
+
+QQuickBorderImageMesh::TileMode QQuickBorderImageMesh::verticalTileMode() const
+{
+ return m_verticalTileMode;
+}
+
+void QQuickBorderImageMesh::setVerticalTileMode(TileMode t)
+{
+ if (t == m_verticalTileMode)
+ return;
+
+ m_verticalTileMode = t;
+ Q_EMIT verticalTileModeChanged();
+ Q_EMIT geometryChanged();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index b6894dc2ec..c5f1d19866 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -107,6 +107,48 @@ private:
QString m_log;
};
+class QQuickScaleGrid;
+class QQuickBorderImageMesh : public QQuickShaderEffectMesh
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+public:
+ QQuickBorderImageMesh(QObject *parent = 0);
+
+ bool validateAttributes(const QVector<QByteArray> &attributes, int *posIndex) override;
+ QSGGeometry *updateGeometry(QSGGeometry *geometry, int attrCount, int posIndex,
+ const QRectF &srcRect, const QRectF &rect) override;
+
+ QQuickScaleGrid *border();
+
+ enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+ Q_ENUM(TileMode)
+
+ QSize size() const;
+ void setSize(const QSize &size);
+
+ TileMode horizontalTileMode() const;
+ void setHorizontalTileMode(TileMode);
+
+ TileMode verticalTileMode() const;
+ void setVerticalTileMode(TileMode);
+
+Q_SIGNALS:
+ void sizeChanged();
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+
+private:
+ QQuickScaleGrid *m_border;
+ QSize m_size;
+ TileMode m_horizontalTileMode;
+ TileMode m_verticalTileMode;
+};
+
inline QColor qt_premultiply_color(const QColor &c)
{
return QColor::fromRgbF(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 025d5b7b6e..c82966cf6b 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -111,7 +111,7 @@ QQuickSpriteEngine::QQuickSpriteEngine(QObject *parent)
}
QQuickSpriteEngine::QQuickSpriteEngine(QList<QQuickSprite*> sprites, QObject *parent)
- : QQuickStochasticEngine(parent), m_startedImageAssembly(false), m_loaded(false)
+ : QQuickSpriteEngine(parent)
{
foreach (QQuickSprite* sprite, sprites)
m_states << (QQuickStochasticState*)sprite;
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 127b51948a..8b6cc221d5 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -1399,10 +1399,16 @@ QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVar
switch (property) {
case Qt::ImCursorRectangle:
return cursorRect();
+ case Qt::ImAnchorRectangle:
+ return anchorRect();
case Qt::ImFont:
return QVariant(d->cursor.charFormat().font());
- case Qt::ImCursorPosition:
+ case Qt::ImCursorPosition: {
+ const QPointF pt = argument.toPointF();
+ if (!pt.isNull())
+ return QVariant(d->doc->documentLayout()->hitTest(pt, Qt::FuzzyHit) - block.position());
return QVariant(d->cursor.position() - block.position());
+ }
case Qt::ImSurroundingText:
return QVariant(block.text());
case Qt::ImCurrentSelection:
@@ -1527,6 +1533,17 @@ void QQuickTextControl::setCursorVisible(bool visible)
&& (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
}
+QRectF QQuickTextControl::anchorRect() const
+{
+ Q_D(const QQuickTextControl);
+ QRectF rect;
+ QTextCursor cursor = d->cursor;
+ if (!cursor.isNull()) {
+ rect = d->rectForPosition(cursor.anchor());
+ }
+ return rect;
+}
+
QRectF QQuickTextControl::cursorRect(const QTextCursor &cursor) const
{
Q_D(const QQuickTextControl);
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index cee9cff064..602e457cb8 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -98,6 +98,7 @@ public:
void setOverwriteMode(bool overwrite);
bool cursorVisible() const;
void setCursorVisible(bool visible);
+ QRectF anchorRect() const;
QRectF cursorRect(const QTextCursor &cursor) const;
QRectF cursorRect() const;
QRectF selectionRect(const QTextCursor &cursor) const;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index a44f549b37..8bb788d008 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -541,7 +541,7 @@ void QQuickTextEdit::setFont(const QFont &font)
updateSize();
updateWholeDocument();
#ifndef QT_NO_IM
- updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
+ updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorRectangle | Qt::ImFont);
#endif
}
emit fontChanged(d->sourceFont);
@@ -1729,6 +1729,7 @@ void QQuickTextEdit::select(int start, int end)
// QTBUG-11100
updateSelection();
+ updateInputMethod();
}
/*!
@@ -1901,7 +1902,11 @@ QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVarian
v = (int)d->effectiveInputMethodHints();
break;
default:
+ if (property == Qt::ImCursorPosition && !argument.isNull())
+ argument = QVariant(argument.toPointF() - QPointF(d->xoff, d->yoff));
v = d->control->inputMethodQuery(property, argument);
+ if (property == Qt::ImCursorRectangle || property == Qt::ImAnchorRectangle)
+ v = QVariant(v.toRectF().translated(d->xoff, d->yoff));
break;
}
return v;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 8bf854aac2..f361d46424 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -401,7 +401,7 @@ void QQuickTextInput::setFont(const QFont &font)
d->updateLayout();
updateCursorRectangle();
#ifndef QT_NO_IM
- updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
+ updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont | Qt::ImAnchorRectangle);
#endif
}
emit fontChanged(d->sourceFont);
@@ -1044,6 +1044,36 @@ void QQuickTextInput::q_validatorChanged()
}
#endif // QT_NO_VALIDATOR
+QRectF QQuickTextInputPrivate::anchorRectangle() const
+{
+ QRectF rect;
+ int a;
+ // Unfortunately we cannot use selectionStart() and selectionEnd()
+ // since they always assume that the selectionStart is logically before selectionEnd.
+ // To rely on that would cause havoc if the user was interactively moving the end selection
+ // handle to become before the start selection
+ if (m_selstart == m_selend)
+ // This is to handle the case when there is "no selection" while moving the handle onto the
+ // same position as the other handle (in which case it would hide the selection handles)
+ a = m_cursor;
+ else
+ a = m_selstart == m_cursor ? m_selend : m_selstart;
+ if (a >= 0) {
+#ifndef QT_NO_IM
+ a += m_preeditCursor;
+#endif
+ if (m_echoMode == QQuickTextInput::NoEcho)
+ a = 0;
+ QTextLine l = m_textLayout.lineForTextPosition(a);
+ if (l.isValid()) {
+ qreal x = l.cursorToX(a) - hscroll;
+ qreal y = l.y() - vscroll;
+ rect.setRect(x, y, 1, l.height());
+ }
+ }
+ return rect;
+}
+
void QQuickTextInputPrivate::checkIsValid()
{
Q_Q(QQuickTextInput);
@@ -1889,10 +1919,16 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVaria
return QVariant((int) d->effectiveInputMethodHints());
case Qt::ImCursorRectangle:
return cursorRectangle();
+ case Qt::ImAnchorRectangle:
+ return d->anchorRectangle();
case Qt::ImFont:
return font();
- case Qt::ImCursorPosition:
+ case Qt::ImCursorPosition: {
+ const QPointF pt = argument.toPointF();
+ if (!pt.isNull())
+ return QVariant(d->positionAt(pt));
return QVariant(d->m_cursor);
+ }
case Qt::ImSurroundingText:
if (d->m_echoMode == PasswordEchoOnEdit && !d->m_passwordEchoEditing) {
return QVariant(displayText());
@@ -2689,7 +2725,7 @@ void QQuickTextInput::updateCursorRectangle(bool scroll)
d->cursorItem->setHeight(r.height());
}
#ifndef QT_NO_IM
- updateInputMethod(Qt::ImCursorRectangle);
+ updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorRectangle);
#endif
}
@@ -3223,8 +3259,8 @@ void QQuickTextInputPrivate::setSelection(int start, int length)
emit q->selectionChanged();
emitCursorPositionChanged();
#ifndef QT_NO_IM
- q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
- | Qt::ImCursorPosition | Qt::ImCurrentSelection);
+ q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorRectangle | Qt::ImCursorPosition | Qt::ImAnchorPosition
+ | Qt::ImCurrentSelection);
#endif
}
@@ -3422,8 +3458,8 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (selectionChange) {
emit q->selectionChanged();
- q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
- | Qt::ImCursorPosition | Qt::ImCurrentSelection);
+ q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorRectangle
+ | Qt::ImCurrentSelection);
}
}
#endif // QT_NO_IM
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index d5a138945d..e6bd29bf67 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -342,6 +342,8 @@ public:
int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
+ QRectF anchorRectangle() const;
+
int positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const;
int positionAt(const QPointF &point, QTextLine::CursorPosition position = QTextLine::CursorBetweenCharacters) const {
return positionAt(point.x(), point.y(), position);
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 3ce96b673d..1101b88992 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -194,9 +194,8 @@ QQuickView::QQuickView(QWindow *parent)
*/
QQuickView::QQuickView(const QUrl &source, QWindow *parent)
-: QQuickWindow(*(new QQuickViewPrivate), parent)
+ : QQuickView(parent)
{
- d_func()->init();
setSource(source);
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index fda01a72f2..2d38314a0a 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1148,10 +1148,8 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
Constructs a window for displaying a QML scene with parent window \a parent.
*/
QQuickWindow::QQuickWindow(QWindow *parent)
- : QWindow(*(new QQuickWindowPrivate), parent)
+ : QQuickWindow(*new QQuickWindowPrivate, parent)
{
- Q_D(QQuickWindow);
- d->init(this);
}
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 124df8f676..c624d162a9 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -77,18 +77,16 @@ QQuickWindowQmlImpl::QQuickWindowQmlImpl(QWindow *parent)
void QQuickWindowQmlImpl::setVisible(bool visible)
{
Q_D(QQuickWindowQmlImpl);
- if (!d->complete)
- d->visible = visible;
- else if (!transientParent() || transientParent()->isVisible())
+ d->visible = visible;
+ if (d->complete && (!transientParent() || transientParent()->isVisible()))
QQuickWindow::setVisible(visible);
}
void QQuickWindowQmlImpl::setVisibility(Visibility visibility)
{
Q_D(QQuickWindowQmlImpl);
- if (!d->complete)
- d->visibility = visibility;
- else
+ d->visibility = visibility;
+ if (d->complete)
QQuickWindow::setVisibility(visibility);
}
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index 97d7e69407..3a35632d5c 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -89,9 +89,6 @@ void Tokenizer::initialize(const char *input)
identifier = input;
}
-#define foo
-
-
Tokenizer::Token Tokenizer::next()
{
while (*pos != 0) {
diff --git a/src/quick/scenegraph/qsgbasicimagenode.cpp b/src/quick/scenegraph/qsgbasicimagenode.cpp
index 0d33e2e24a..36a43b754a 100644
--- a/src/quick/scenegraph/qsgbasicimagenode.cpp
+++ b/src/quick/scenegraph/qsgbasicimagenode.cpp
@@ -200,6 +200,264 @@ static inline void appendQuad(quint16 **indices, quint16 topLeft, quint16 topRig
*(*indices)++ = topLeft;
}
+QSGGeometry *QSGBasicImageNode::updateGeometry(const QRectF &targetRect,
+ const QRectF &innerTargetRect,
+ const QRectF &sourceRect,
+ const QRectF &innerSourceRect,
+ const QRectF &subSourceRect,
+ QSGGeometry *geometry,
+ bool mirror,
+ bool antialiasing)
+{
+ int floorLeft = qFloor(subSourceRect.left());
+ int ceilRight = qCeil(subSourceRect.right());
+ int floorTop = qFloor(subSourceRect.top());
+ int ceilBottom = qCeil(subSourceRect.bottom());
+ int hTiles = ceilRight - floorLeft;
+ int vTiles = ceilBottom - floorTop;
+
+ int hCells = hTiles;
+ int vCells = vTiles;
+ if (innerTargetRect.width() == 0)
+ hCells = 0;
+ if (innerTargetRect.left() != targetRect.left())
+ ++hCells;
+ if (innerTargetRect.right() != targetRect.right())
+ ++hCells;
+ if (innerTargetRect.height() == 0)
+ vCells = 0;
+ if (innerTargetRect.top() != targetRect.top())
+ ++vCells;
+ if (innerTargetRect.bottom() != targetRect.bottom())
+ ++vCells;
+ QVarLengthArray<X, 32> xData(2 * hCells);
+ QVarLengthArray<Y, 32> yData(2 * vCells);
+ X *xs = xData.data();
+ Y *ys = yData.data();
+
+ if (innerTargetRect.left() != targetRect.left()) {
+ xs[0].x = targetRect.left();
+ xs[0].tx = sourceRect.left();
+ xs[1].x = innerTargetRect.left();
+ xs[1].tx = innerSourceRect.left();
+ xs += 2;
+ }
+ if (innerTargetRect.width() != 0) {
+ xs[0].x = innerTargetRect.left();
+ xs[0].tx = innerSourceRect.x() + (subSourceRect.left() - floorLeft) * innerSourceRect.width();
+ ++xs;
+ float b = innerTargetRect.width() / subSourceRect.width();
+ float a = innerTargetRect.x() - subSourceRect.x() * b;
+ for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
+ xs[0].x = xs[1].x = a + b * i;
+ xs[0].tx = innerSourceRect.right();
+ xs[1].tx = innerSourceRect.left();
+ xs += 2;
+ }
+ xs[0].x = innerTargetRect.right();
+ xs[0].tx = innerSourceRect.x() + (subSourceRect.right() - ceilRight + 1) * innerSourceRect.width();
+ ++xs;
+ }
+ if (innerTargetRect.right() != targetRect.right()) {
+ xs[0].x = innerTargetRect.right();
+ xs[0].tx = innerSourceRect.right();
+ xs[1].x = targetRect.right();
+ xs[1].tx = sourceRect.right();
+ xs += 2;
+ }
+ Q_ASSERT(xs == xData.data() + xData.size());
+ if (mirror) {
+ float leftPlusRight = targetRect.left() + targetRect.right();
+ int count = xData.size();
+ xs = xData.data();
+ for (int i = 0; i < count >> 1; ++i)
+ qSwap(xs[i], xs[count - 1 - i]);
+ for (int i = 0; i < count; ++i)
+ xs[i].x = leftPlusRight - xs[i].x;
+ }
+
+ if (innerTargetRect.top() != targetRect.top()) {
+ ys[0].y = targetRect.top();
+ ys[0].ty = sourceRect.top();
+ ys[1].y = innerTargetRect.top();
+ ys[1].ty = innerSourceRect.top();
+ ys += 2;
+ }
+ if (innerTargetRect.height() != 0) {
+ ys[0].y = innerTargetRect.top();
+ ys[0].ty = innerSourceRect.y() + (subSourceRect.top() - floorTop) * innerSourceRect.height();
+ ++ys;
+ float b = innerTargetRect.height() / subSourceRect.height();
+ float a = innerTargetRect.y() - subSourceRect.y() * b;
+ for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
+ ys[0].y = ys[1].y = a + b * i;
+ ys[0].ty = innerSourceRect.bottom();
+ ys[1].ty = innerSourceRect.top();
+ ys += 2;
+ }
+ ys[0].y = innerTargetRect.bottom();
+ ys[0].ty = innerSourceRect.y() + (subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height();
+ ++ys;
+ }
+ if (innerTargetRect.bottom() != targetRect.bottom()) {
+ ys[0].y = innerTargetRect.bottom();
+ ys[0].ty = innerSourceRect.bottom();
+ ys[1].y = targetRect.bottom();
+ ys[1].ty = sourceRect.bottom();
+ ys += 2;
+ }
+ Q_ASSERT(ys == yData.data() + yData.size());
+
+ if (antialiasing) {
+ QSGGeometry *g = geometry;
+ Q_ASSERT(g);
+
+ g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4,
+ hCells * vCells * 6 + (hCells + vCells) * 12);
+ g->setDrawingMode(GL_TRIANGLES);
+ SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
+ memset(vertices, 0, g->vertexCount() * g->sizeOfVertex());
+ quint16 *indices = g->indexDataAsUShort();
+
+ // The deltas are how much the fuzziness can reach into the image.
+ // Only the border vertices are moved by the vertex shader, so the fuzziness
+ // can't reach further into the image than the closest interior vertices.
+ float leftDx = xData.at(1).x - xData.at(0).x;
+ float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x;
+ float topDy = yData.at(1).y - yData.at(0).y;
+ float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y;
+
+ float leftDu = xData.at(1).tx - xData.at(0).tx;
+ float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx;
+ float topDv = yData.at(1).ty - yData.at(0).ty;
+ float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty;
+
+ if (hCells == 1) {
+ leftDx = rightDx *= 0.5f;
+ leftDu = rightDu *= 0.5f;
+ }
+ if (vCells == 1) {
+ topDy = bottomDy *= 0.5f;
+ topDv = bottomDv *= 0.5f;
+ }
+
+ // This delta is how much the fuzziness can reach out from the image.
+ float delta = float(qAbs(targetRect.width()) < qAbs(targetRect.height())
+ ? targetRect.width() : targetRect.height()) * 0.5f;
+
+ quint16 index = 0;
+ ys = yData.data();
+ for (int j = 0; j < vCells; ++j, ys += 2) {
+ xs = xData.data();
+ bool isTop = j == 0;
+ bool isBottom = j == vCells - 1;
+ for (int i = 0; i < hCells; ++i, xs += 2) {
+ bool isLeft = i == 0;
+ bool isRight = i == hCells - 1;
+
+ SmoothVertex *v = vertices + index;
+
+ quint16 topLeft = index;
+ for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) {
+ v->x = xs[0].x;
+ v->u = xs[0].tx;
+ v->y = ys[0].y;
+ v->v = ys[0].ty;
+ }
+
+ quint16 topRight = index;
+ for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) {
+ v->x = xs[1].x;
+ v->u = xs[1].tx;
+ v->y = ys[0].y;
+ v->v = ys[0].ty;
+ }
+
+ quint16 bottomLeft = index;
+ for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) {
+ v->x = xs[0].x;
+ v->u = xs[0].tx;
+ v->y = ys[1].y;
+ v->v = ys[1].ty;
+ }
+
+ quint16 bottomRight = index;
+ for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) {
+ v->x = xs[1].x;
+ v->u = xs[1].tx;
+ v->y = ys[1].y;
+ v->v = ys[1].ty;
+ }
+
+ appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight);
+
+ if (isTop) {
+ vertices[topLeft].dy = vertices[topRight].dy = topDy;
+ vertices[topLeft].dv = vertices[topRight].dv = topDv;
+ vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
+ appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
+ }
+
+ if (isBottom) {
+ vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
+ vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
+ vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
+ appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
+ }
+
+ if (isLeft) {
+ vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
+ vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
+ vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
+ appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
+ }
+
+ if (isRight) {
+ vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
+ vertices[topRight].du = vertices[bottomRight].du = -rightDu;
+ vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
+ appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
+ }
+ }
+ }
+
+ Q_ASSERT(index == g->vertexCount());
+ Q_ASSERT(indices - g->indexCount() == g->indexData());
+ } else {
+ if (!geometry) {
+ geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(),
+ hCells * vCells * 4, hCells * vCells * 6,
+ GL_UNSIGNED_SHORT);
+ } else {
+ geometry->allocate(hCells * vCells * 4, hCells * vCells * 6);
+ }
+ geometry->setDrawingMode(GL_TRIANGLES);
+ QSGGeometry::TexturedPoint2D *vertices = geometry->vertexDataAsTexturedPoint2D();
+ ys = yData.data();
+ for (int j = 0; j < vCells; ++j, ys += 2) {
+ xs = xData.data();
+ for (int i = 0; i < hCells; ++i, xs += 2) {
+ vertices[0].x = vertices[2].x = xs[0].x;
+ vertices[0].tx = vertices[2].tx = xs[0].tx;
+ vertices[1].x = vertices[3].x = xs[1].x;
+ vertices[1].tx = vertices[3].tx = xs[1].tx;
+
+ vertices[0].y = vertices[1].y = ys[0].y;
+ vertices[0].ty = vertices[1].ty = ys[0].ty;
+ vertices[2].y = vertices[3].y = ys[1].y;
+ vertices[2].ty = vertices[3].ty = ys[1].ty;
+
+ vertices += 4;
+ }
+ }
+
+ quint16 *indices = geometry->indexDataAsUShort();
+ for (int i = 0; i < 4 * vCells * hCells; i += 4)
+ appendQuad(&indices, i, i + 1, i + 2, i + 3);
+ }
+ return geometry;
+}
+
void QSGBasicImageNode::updateGeometry()
{
Q_ASSERT(!m_targetRect.isEmpty());
@@ -288,239 +546,10 @@ void QSGBasicImageNode::updateGeometry()
QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr);
}
} else {
- int hCells = hTiles;
- int vCells = vTiles;
- if (m_innerTargetRect.width() == 0)
- hCells = 0;
- if (m_innerTargetRect.left() != m_targetRect.left())
- ++hCells;
- if (m_innerTargetRect.right() != m_targetRect.right())
- ++hCells;
- if (m_innerTargetRect.height() == 0)
- vCells = 0;
- if (m_innerTargetRect.top() != m_targetRect.top())
- ++vCells;
- if (m_innerTargetRect.bottom() != m_targetRect.bottom())
- ++vCells;
- QVarLengthArray<X, 32> xData(2 * hCells);
- QVarLengthArray<Y, 32> yData(2 * vCells);
- X *xs = xData.data();
- Y *ys = yData.data();
-
- if (m_innerTargetRect.left() != m_targetRect.left()) {
- xs[0].x = m_targetRect.left();
- xs[0].tx = sourceRect.left();
- xs[1].x = m_innerTargetRect.left();
- xs[1].tx = innerSourceRect.left();
- xs += 2;
- }
- if (m_innerTargetRect.width() != 0) {
- xs[0].x = m_innerTargetRect.left();
- xs[0].tx = innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width();
- ++xs;
- float b = m_innerTargetRect.width() / m_subSourceRect.width();
- float a = m_innerTargetRect.x() - m_subSourceRect.x() * b;
- for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
- xs[0].x = xs[1].x = a + b * i;
- xs[0].tx = innerSourceRect.right();
- xs[1].tx = innerSourceRect.left();
- xs += 2;
- }
- xs[0].x = m_innerTargetRect.right();
- xs[0].tx = innerSourceRect.x() + (m_subSourceRect.right() - ceilRight + 1) * innerSourceRect.width();
- ++xs;
- }
- if (m_innerTargetRect.right() != m_targetRect.right()) {
- xs[0].x = m_innerTargetRect.right();
- xs[0].tx = innerSourceRect.right();
- xs[1].x = m_targetRect.right();
- xs[1].tx = sourceRect.right();
- xs += 2;
- }
- Q_ASSERT(xs == xData.data() + xData.size());
- if (m_mirror) {
- float leftPlusRight = m_targetRect.left() + m_targetRect.right();
- int count = xData.size();
- xs = xData.data();
- for (int i = 0; i < count >> 1; ++i)
- qSwap(xs[i], xs[count - 1 - i]);
- for (int i = 0; i < count; ++i)
- xs[i].x = leftPlusRight - xs[i].x;
- }
-
- if (m_innerTargetRect.top() != m_targetRect.top()) {
- ys[0].y = m_targetRect.top();
- ys[0].ty = sourceRect.top();
- ys[1].y = m_innerTargetRect.top();
- ys[1].ty = innerSourceRect.top();
- ys += 2;
- }
- if (m_innerTargetRect.height() != 0) {
- ys[0].y = m_innerTargetRect.top();
- ys[0].ty = innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height();
- ++ys;
- float b = m_innerTargetRect.height() / m_subSourceRect.height();
- float a = m_innerTargetRect.y() - m_subSourceRect.y() * b;
- for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
- ys[0].y = ys[1].y = a + b * i;
- ys[0].ty = innerSourceRect.bottom();
- ys[1].ty = innerSourceRect.top();
- ys += 2;
- }
- ys[0].y = m_innerTargetRect.bottom();
- ys[0].ty = innerSourceRect.y() + (m_subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height();
- ++ys;
- }
- if (m_innerTargetRect.bottom() != m_targetRect.bottom()) {
- ys[0].y = m_innerTargetRect.bottom();
- ys[0].ty = innerSourceRect.bottom();
- ys[1].y = m_targetRect.bottom();
- ys[1].ty = sourceRect.bottom();
- ys += 2;
- }
- Q_ASSERT(ys == yData.data() + yData.size());
-
- if (m_antialiasing) {
- QSGGeometry *g = geometry();
- Q_ASSERT(g != &m_geometry);
-
- g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4,
- hCells * vCells * 6 + (hCells + vCells) * 12);
- g->setDrawingMode(QSGGeometry::DrawTriangles);
- SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
- memset(vertices, 0, g->vertexCount() * g->sizeOfVertex());
- quint16 *indices = g->indexDataAsUShort();
-
- // The deltas are how much the fuzziness can reach into the image.
- // Only the border vertices are moved by the vertex shader, so the fuzziness
- // can't reach further into the image than the closest interior vertices.
- float leftDx = xData.at(1).x - xData.at(0).x;
- float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x;
- float topDy = yData.at(1).y - yData.at(0).y;
- float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y;
-
- float leftDu = xData.at(1).tx - xData.at(0).tx;
- float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx;
- float topDv = yData.at(1).ty - yData.at(0).ty;
- float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty;
-
- if (hCells == 1) {
- leftDx = rightDx *= 0.5f;
- leftDu = rightDu *= 0.5f;
- }
- if (vCells == 1) {
- topDy = bottomDy *= 0.5f;
- topDv = bottomDv *= 0.5f;
- }
-
- // This delta is how much the fuzziness can reach out from the image.
- float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
- ? m_targetRect.width() : m_targetRect.height()) * 0.5f;
-
- quint16 index = 0;
- ys = yData.data();
- for (int j = 0; j < vCells; ++j, ys += 2) {
- xs = xData.data();
- bool isTop = j == 0;
- bool isBottom = j == vCells - 1;
- for (int i = 0; i < hCells; ++i, xs += 2) {
- bool isLeft = i == 0;
- bool isRight = i == hCells - 1;
-
- SmoothVertex *v = vertices + index;
-
- quint16 topLeft = index;
- for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) {
- v->x = xs[0].x;
- v->u = xs[0].tx;
- v->y = ys[0].y;
- v->v = ys[0].ty;
- }
-
- quint16 topRight = index;
- for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) {
- v->x = xs[1].x;
- v->u = xs[1].tx;
- v->y = ys[0].y;
- v->v = ys[0].ty;
- }
-
- quint16 bottomLeft = index;
- for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) {
- v->x = xs[0].x;
- v->u = xs[0].tx;
- v->y = ys[1].y;
- v->v = ys[1].ty;
- }
-
- quint16 bottomRight = index;
- for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) {
- v->x = xs[1].x;
- v->u = xs[1].tx;
- v->y = ys[1].y;
- v->v = ys[1].ty;
- }
-
- appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight);
-
- if (isTop) {
- vertices[topLeft].dy = vertices[topRight].dy = topDy;
- vertices[topLeft].dv = vertices[topRight].dv = topDv;
- vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
- appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
- }
-
- if (isBottom) {
- vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
- vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
- vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
- appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
- }
-
- if (isLeft) {
- vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
- vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
- vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
- appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
- }
-
- if (isRight) {
- vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
- vertices[topRight].du = vertices[bottomRight].du = -rightDu;
- vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
- appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
- }
- }
- }
-
- Q_ASSERT(index == g->vertexCount());
- Q_ASSERT(indices - g->indexCount() == g->indexData());
- } else {
- m_geometry.allocate(hCells * vCells * 4, hCells * vCells * 6);
- m_geometry.setDrawingMode(QSGGeometry::DrawTriangles);
- QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D();
- ys = yData.data();
- for (int j = 0; j < vCells; ++j, ys += 2) {
- xs = xData.data();
- for (int i = 0; i < hCells; ++i, xs += 2) {
- vertices[0].x = vertices[2].x = xs[0].x;
- vertices[0].tx = vertices[2].tx = xs[0].tx;
- vertices[1].x = vertices[3].x = xs[1].x;
- vertices[1].tx = vertices[3].tx = xs[1].tx;
-
- vertices[0].y = vertices[1].y = ys[0].y;
- vertices[0].ty = vertices[1].ty = ys[0].ty;
- vertices[2].y = vertices[3].y = ys[1].y;
- vertices[2].ty = vertices[3].ty = ys[1].ty;
-
- vertices += 4;
- }
- }
-
- quint16 *indices = m_geometry.indexDataAsUShort();
- for (int i = 0; i < 4 * vCells * hCells; i += 4)
- appendQuad(&indices, i, i + 1, i + 2, i + 3);
- }
+ QSGGeometry *g = m_antialiasing ? geometry() : &m_geometry;
+ updateGeometry(m_targetRect, m_innerTargetRect,
+ sourceRect, innerSourceRect, m_subSourceRect,
+ g, m_mirror, m_antialiasing);
}
}
markDirty(DirtyGeometry);
diff --git a/src/quick/scenegraph/qsgbasicimagenode_p.h b/src/quick/scenegraph/qsgbasicimagenode_p.h
index 288b6c23f0..4a96e1a9f6 100644
--- a/src/quick/scenegraph/qsgbasicimagenode_p.h
+++ b/src/quick/scenegraph/qsgbasicimagenode_p.h
@@ -70,6 +70,15 @@ public:
void update() override;
void preprocess() override;
+ static QSGGeometry *updateGeometry(const QRectF &targetRect,
+ const QRectF &innerTargetRect,
+ const QRectF &sourceRect,
+ const QRectF &innerSourceRect,
+ const QRectF &subSourceRect,
+ QSGGeometry *geometry,
+ bool mirror = false,
+ bool antialiasing = false);
+
protected:
virtual void updateMaterialAntialiasing() = 0;
virtual void setMaterialTexture(QSGTexture *texture) = 0;
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index b4efe2faea..b6431666bf 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -433,11 +433,8 @@ QQuickWidget::QQuickWidget(QWidget *parent)
*/
QQuickWidget::QQuickWidget(const QUrl &source, QWidget *parent)
-: QWidget(*(new QQuickWidgetPrivate), parent, 0)
+ : QQuickWidget(parent)
{
- setMouseTracking(true);
- setFocusPolicy(Qt::StrongFocus);
- d_func()->init();
setSource(source);
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index c535258c19..adf944c7e1 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1024,11 +1024,14 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("Math.pow") << QString("Math.pow") << QString("pow");
QTest::newRow("Math.random") << QString("Math.random") << QString("random");
QTest::newRow("Math.round") << QString("Math.round") << QString("round");
+ QTest::newRow("Math.sign") << QString("Math.sign") << QString("sign");
QTest::newRow("Math.sin") << QString("Math.sin") << QString("sin");
QTest::newRow("Math.sqrt") << QString("Math.sqrt") << QString("sqrt");
QTest::newRow("Math.tan") << QString("Math.tan") << QString("tan");
QTest::newRow("Number") << QString("Number") << QString("Number");
+ QTest::newRow("Number.isFinite") << QString("Number.isFinite") << QString("isFinite");
+ QTest::newRow("Number.isNaN") << QString("Number.isNaN") << QString("isNaN");
QTest::newRow("Number.prototype.toString") << QString("Number.prototype.toString") << QString("toString");
QTest::newRow("Number.prototype.toLocaleString") << QString("Number.prototype.toLocaleString") << QString("toLocaleString");
QTest::newRow("Number.prototype.valueOf") << QString("Number.prototype.valueOf") << QString("valueOf");
@@ -1920,6 +1923,7 @@ void tst_QJSEngine::jsNumberClass()
QVERIFY(ctor.property("NaN").isNumber());
QVERIFY(ctor.property("NEGATIVE_INFINITY").isNumber());
QVERIFY(ctor.property("POSITIVE_INFINITY").isNumber());
+ QVERIFY(ctor.property("EPSILON").isNumber());
}
QCOMPARE(proto.toNumber(), qreal(0));
QVERIFY(proto.property("constructor").strictlyEquals(ctor));
@@ -1958,6 +1962,50 @@ void tst_QJSEngine::jsNumberClass()
QCOMPARE(ret.toNumber(), qreal(456));
}
+ QVERIFY(ctor.property("isFinite").isCallable());
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite()");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(NaN)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(Infinity)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(-Infinity)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(123)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), true);
+ }
+
+ QVERIFY(ctor.property("isNaN").isCallable());
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN()");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN(NaN)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), true);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN(123)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+
QVERIFY(proto.property("toString").isCallable());
{
QJSValue ret = eng.evaluate("new Number(123).toString()");
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt
deleted file mode 100644
index 32d2ed857e..0000000000
--- a/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt
+++ /dev/null
@@ -1 +0,0 @@
-4:1:Composite Singleton Type SingletonType is not creatable.
diff --git a/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml b/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml
new file mode 100644
index 0000000000..8369ab1eea
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import Test 1.0
+
+QtObject {
+ property MyUncreateableBaseClass someProperty;
+}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index dd7410dfd3..1ac1661ea8 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -188,6 +188,8 @@ private slots:
void subclassedUncreateableRevision_data();
void subclassedUncreateableRevision();
+ void uncreatableTypesAsProperties();
+
void propertyInit();
void remoteLoadCrash();
void signalWithDefaultArg();
@@ -3158,6 +3160,14 @@ void tst_qqmllanguage::subclassedUncreateableRevision()
delete obj;
}
+void tst_qqmllanguage::uncreatableTypesAsProperties()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("uncreatableTypeAsProperty.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
+
void tst_qqmllanguage::initTestCase()
{
QQmlDataTest::initTestCase();
@@ -3863,12 +3873,11 @@ void tst_qqmllanguage::compositeSingletonInstantiateError()
VERIFY_ERRORS("singletonTest9.error.txt");
}
-// Having a composite singleton type as dynamic property type fails
-// (like C++ singleton)
+// Having a composite singleton type as dynamic property type is allowed
void tst_qqmllanguage::compositeSingletonDynamicPropertyError()
{
QQmlComponent component(&engine, testFile("singletonTest10.qml"));
- VERIFY_ERRORS("singletonTest10.error.txt");
+ VERIFY_ERRORS(0);
}
// Having a composite singleton type as dynamic signal parameter succeeds
diff --git a/tests/auto/qmldevtools/compile/compile.pro b/tests/auto/qmldevtools/compile/compile.pro
index 186ef71e8d..71d91c107d 100644
--- a/tests/auto/qmldevtools/compile/compile.pro
+++ b/tests/auto/qmldevtools/compile/compile.pro
@@ -12,3 +12,4 @@ macx:CONFIG -= app_bundle
SOURCES += tst_compile.cpp
+load(qt_common)
diff --git a/tests/auto/quick/qquickborderimage/data/mesh.qml b/tests/auto/quick/qquickborderimage/data/mesh.qml
new file mode 100644
index 0000000000..203bf25867
--- /dev/null
+++ b/tests/auto/quick/qquickborderimage/data/mesh.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.8
+
+Item {
+ width: 300
+ height: 300
+ Image {
+ id: image
+ source: "colors.png"
+ visible: false
+ }
+ ShaderEffect {
+ anchors.fill: parent
+ property variant source: image
+ mesh: BorderImageMesh {
+ border.left: 30
+ border.right: 30
+ border.top: 30
+ border.bottom: 30
+ size: image.sourceSize
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickborderimage/data/nonmesh.qml b/tests/auto/quick/qquickborderimage/data/nonmesh.qml
new file mode 100644
index 0000000000..7a1830a942
--- /dev/null
+++ b/tests/auto/quick/qquickborderimage/data/nonmesh.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.8
+
+BorderImage {
+ width: 300
+ height: 300
+ source: "colors.png"
+ border.left: 30
+ border.right: 30
+ border.top: 30
+ border.bottom: 30
+}
diff --git a/tests/auto/quick/qquickborderimage/qquickborderimage.pro b/tests/auto/quick/qquickborderimage/qquickborderimage.pro
index 3e16063559..ba6c01737a 100644
--- a/tests/auto/quick/qquickborderimage/qquickborderimage.pro
+++ b/tests/auto/quick/qquickborderimage/qquickborderimage.pro
@@ -7,6 +7,7 @@ SOURCES += tst_qquickborderimage.cpp \
../../shared/testhttpserver.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index c11ae1e8c9..e1435e739f 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -44,6 +44,7 @@
#include "../../shared/testhttpserver.h"
#include "../../shared/util.h"
+#include "../shared/visualtestutil.h"
Q_DECLARE_METATYPE(QQuickImageBase::Status)
@@ -75,6 +76,7 @@ private slots:
void statusChanges_data();
void sourceSizeChanges();
void progressAndStatusChanges();
+ void borderImageMesh();
private:
QQmlEngine engine;
@@ -575,6 +577,21 @@ void tst_qquickborderimage::progressAndStatusChanges()
delete obj;
}
+void tst_qquickborderimage::borderImageMesh()
+{
+ QQuickView *window = new QQuickView;
+
+ window->setSource(testFileUrl("nonmesh.qml"));
+ window->show();
+ QTest::qWaitForWindowExposed(window);
+ QImage nonmesh = window->grabWindow();
+
+ window->setSource(testFileUrl("mesh.qml"));
+ QImage mesh = window->grabWindow();
+
+ QVERIFY(QQuickVisualTestUtil::compareImages(mesh, nonmesh));
+}
+
QTEST_MAIN(tst_qquickborderimage)
#include "tst_qquickborderimage.moc"
diff --git a/tests/auto/quick/qquickwindow/data/changeVisibilityInCompleted.qml b/tests/auto/quick/qquickwindow/data/changeVisibilityInCompleted.qml
new file mode 100644
index 0000000000..48c4d1d69f
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/changeVisibilityInCompleted.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.0
+import QtQuick.Window 2.1
+
+Window {
+ width: 200
+ height: 200
+
+ property var winVisible: subwin1
+ property var winVisibility: subwin2
+
+ Rectangle {
+ anchors.fill: parent
+ color:"green"
+ }
+
+ Window {
+ id: subwin1
+ width: 200
+ height: 200
+
+ visible: false
+
+ Rectangle {
+ anchors.fill: parent
+ color:"red"
+ }
+ Component.onCompleted: {
+ subwin1.visible = true
+ }
+ }
+ Window {
+ id: subwin2
+ width: 200
+ height: 200
+
+ visible: true
+ visibility: Window.Maximized
+
+ Rectangle {
+ anchors.fill: parent
+ color:"blue"
+ }
+ Component.onCompleted: {
+ subwin2.visibility = Window.Windowed
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 0e4ad86260..ff996e5362 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -348,6 +348,7 @@ private slots:
void crashWhenHoverItemDeleted();
void unloadSubWindow();
+ void changeVisibilityInCompleted();
void qobjectEventFilter_touch();
void qobjectEventFilter_key();
@@ -1865,6 +1866,28 @@ void tst_qquickwindow::unloadSubWindow()
QTRY_VERIFY(transient.isNull() || !transient->isVisible());
}
+// QTBUG-52573
+void tst_qquickwindow::changeVisibilityInCompleted()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("changeVisibilityInCompleted.qml"));
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(component.create()));
+ QVERIFY(!window.isNull());
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QTest::qWaitForWindowExposed(window.data());
+ QPointer<QQuickWindow> winVisible;
+ QTRY_VERIFY(winVisible = window->property("winVisible").value<QQuickWindow*>());
+ QPointer<QQuickWindow> winVisibility;
+ QTRY_VERIFY(winVisibility = window->property("winVisibility").value<QQuickWindow*>());
+ QTest::qWaitForWindowExposed(winVisible);
+ QTest::qWaitForWindowExposed(winVisibility);
+
+ QVERIFY(winVisible->isVisible());
+ QCOMPARE(winVisibility->visibility(), QWindow::Windowed);
+}
+
// QTBUG-32004
void tst_qquickwindow::qobjectEventFilter_touch()
{
diff --git a/tests/auto/quick/scenegraph/scenegraph.pro b/tests/auto/quick/scenegraph/scenegraph.pro
index 320228bd08..40ff7750cc 100644
--- a/tests/auto/quick/scenegraph/scenegraph.pro
+++ b/tests/auto/quick/scenegraph/scenegraph.pro
@@ -3,6 +3,7 @@ TARGET = tst_scenegraph
SOURCES += tst_scenegraph.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
macx:CONFIG -= app_bundle
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 6f00d5f9f2..91c872a36a 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -44,6 +44,10 @@
#include <private/qsgcontext_p.h>
#include <private/qsgrenderloop_p.h>
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickVisualTestUtil;
+
class PerPixelRect : public QQuickItem
{
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
@@ -194,44 +198,6 @@ bool containsSomethingOtherThanWhite(const QImage &image)
return false;
}
-// When running on native Nvidia graphics cards on linux, the
-// distance field glyph pixels have a measurable, but not visible
-// pixel error. Use a custom compare function to avoid
-//
-// This was GT-216 with the ubuntu "nvidia-319" driver package.
-// llvmpipe does not show the same issue.
-//
-bool compareImages(const QImage &ia, const QImage &ib)
-{
- if (ia.size() != ib.size())
- qDebug() << "images are of different size" << ia.size() << ib.size();
- Q_ASSERT(ia.size() == ib.size());
- Q_ASSERT(ia.format() == ib.format());
-
- int w = ia.width();
- int h = ia.height();
- const int tolerance = 5;
- for (int y=0; y<h; ++y) {
- const uint *as= (const uint *) ia.constScanLine(y);
- const uint *bs= (const uint *) ib.constScanLine(y);
- for (int x=0; x<w; ++x) {
- uint a = as[x];
- uint b = bs[x];
-
- // No tolerance for error in the alpha.
- if ((a & 0xff000000) != (b & 0xff000000))
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- }
- }
- return true;
-}
-
void tst_SceneGraph::manyWindows_data()
{
QTest::addColumn<QString>("file");
diff --git a/tests/auto/quick/shared/visualtestutil.cpp b/tests/auto/quick/shared/visualtestutil.cpp
index 3e18c83ee2..eabfe5368b 100644
--- a/tests/auto/quick/shared/visualtestutil.cpp
+++ b/tests/auto/quick/shared/visualtestutil.cpp
@@ -61,3 +61,38 @@ void QQuickVisualTestUtil::dumpTree(QQuickItem *parent, int depth)
}
}
+// A custom compare function to avoid issues such as:
+// When running on native Nvidia graphics cards on linux, the
+// distance field glyph pixels have a measurable, but not visible
+// pixel error. This was GT-216 with the ubuntu "nvidia-319" driver package.
+// llvmpipe does not show the same issue.
+bool QQuickVisualTestUtil::compareImages(const QImage &ia, const QImage &ib)
+{
+ if (ia.size() != ib.size())
+ qDebug() << "images are of different size" << ia.size() << ib.size();
+ Q_ASSERT(ia.size() == ib.size());
+ Q_ASSERT(ia.format() == ib.format());
+
+ int w = ia.width();
+ int h = ia.height();
+ const int tolerance = 5;
+ for (int y=0; y<h; ++y) {
+ const uint *as= (const uint *) ia.constScanLine(y);
+ const uint *bs= (const uint *) ib.constScanLine(y);
+ for (int x=0; x<w; ++x) {
+ uint a = as[x];
+ uint b = bs[x];
+
+ // No tolerance for error in the alpha.
+ if ((a & 0xff000000) != (b & 0xff000000))
+ return false;
+ if (qAbs(qRed(a) - qRed(b)) > tolerance)
+ return false;
+ if (qAbs(qRed(a) - qRed(b)) > tolerance)
+ return false;
+ if (qAbs(qRed(a) - qRed(b)) > tolerance)
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/tests/auto/quick/shared/visualtestutil.h b/tests/auto/quick/shared/visualtestutil.h
index 2b377a4bab..2daf86cd83 100644
--- a/tests/auto/quick/shared/visualtestutil.h
+++ b/tests/auto/quick/shared/visualtestutil.h
@@ -96,6 +96,8 @@ namespace QQuickVisualTestUtil
items << qobject_cast<QQuickItem*>(findItem<T>(parent, objectName, indexes[i]));
return items;
}
+
+ bool compareImages(const QImage &ia, const QImage &ib);
}
#define QQUICK_VERIFY_POLISH(item) \