QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QSGImage);
- //XXX Support mirror property
if (!d->pix.texture() || width() <= 0 || height() <= 0) {
delete oldNode;
sourceRect.width() / d->pix.width(),
sourceRect.height() / d->pix.height());
+ if (d->mirror) {
+ qreal oldLeft = nsrect.left();
+ nsrect.setLeft(nsrect.right());
+ nsrect.setRight(oldLeft);
+ }
+
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
QMLRenderer::QMLRenderer(QSGContext *context)
: QSGRenderer(context)
+ , m_opaqueNodes(64)
+ , m_transparentNodes(64)
+ , m_tempNodes(64)
, m_rebuild_lists(false)
, m_needs_sorting(false)
, m_sort_front_to_back(false)
m_currentMatrix = 0;
if (m_rebuild_lists) {
- m_opaqueNodes.clear();
- m_transparentNodes.clear();
+ m_opaqueNodes.reset();
+ m_transparentNodes.reset();
m_currentRenderOrder = 1;
buildLists(rootNode());
m_rebuild_lists = false;
if (m_needs_sorting) {
- qSort(m_opaqueNodes.begin(), m_opaqueNodes.end(),
- m_sort_front_to_back
- ? nodeLessThanWithRenderOrder
- : nodeLessThan);
+ if (!m_opaqueNodes.isEmpty()) {
+ qSort(&m_opaqueNodes.first(), &m_opaqueNodes.first() + m_opaqueNodes.size(),
+ m_sort_front_to_back
+ ? nodeLessThanWithRenderOrder
+ : nodeLessThan);
+ }
m_needs_sorting = false;
}
if ((m->flags() & QSGMaterial::Blending) || opacity < 1) {
#endif
geomNode->setRenderOrder(m_currentRenderOrder - 1);
- m_transparentNodes.append(geomNode);
+ m_transparentNodes.add(geomNode);
} else {
geomNode->setRenderOrder(m_currentRenderOrder);
- m_opaqueNodes.append(geomNode);
+ m_opaqueNodes.add(geomNode);
m_currentRenderOrder += 2;
}
}
endIndices[i] = m_transparentNodes.size();
}
- Heap<Foo, 16> heap;
- m_tempNodes.clear();
int childNodeCount = m_transparentNodes.size() - baseCount;
- while (childNodeCount) {
- for (int i = 0; i < count; ++i) {
- if (beginIndices[i] != endIndices[i])
- heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
- }
- while (!heap.isEmpty()) {
- Foo foo = heap.pop();
- m_tempNodes.append(foo.second);
- --childNodeCount;
- int i = foo.first;
- if (beginIndices[i] != endIndices[i] && !nodeLessThan(m_transparentNodes.at(beginIndices[i]), foo.second))
- heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
+ if (childNodeCount) {
+ Heap<Foo, 16> heap;
+ m_tempNodes.reset();
+ m_tempNodes.reserve(childNodeCount);
+ while (childNodeCount) {
+ for (int i = 0; i < count; ++i) {
+ if (beginIndices[i] != endIndices[i])
+ heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
+ }
+ while (!heap.isEmpty()) {
+ Foo foo = heap.pop();
+ m_tempNodes.add(foo.second);
+ --childNodeCount;
+ int i = foo.first;
+ if (beginIndices[i] != endIndices[i] && !nodeLessThan(m_transparentNodes.at(beginIndices[i]), foo.second))
+ heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
+ }
}
- }
- Q_ASSERT(m_tempNodes.size() == m_transparentNodes.size() - baseCount);
+ Q_ASSERT(m_tempNodes.size() == m_transparentNodes.size() - baseCount);
- m_transparentNodes.resize(baseCount);
- m_transparentNodes << m_tempNodes;
+ qMemCopy(&m_transparentNodes.at(baseCount), &m_tempNodes.at(0), m_tempNodes.size() * sizeof(QSGGeometryNode *));
+ }
} else {
for (int i = 0; i < count; ++i)
buildLists(node->childAtIndex(i));
}
}
-void QMLRenderer::renderNodes(const QVector<QSGGeometryNode *> &list)
+void QMLRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
{
const float scale = 1.0f / m_currentRenderOrder;
- int count = list.count();
+ int count = list.size();
int currentRenderOrder = 0x80000000;
//int clipChangeCount = 0;
#include "qsgrenderer_p.h"
+#include <QtGui/private/qdatabuffer_p.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
private:
void buildLists(QSGNode *node);
- void renderNodes(const QVector <QSGGeometryNode *> &list);
+ void renderNodes(const QDataBuffer<QSGGeometryNode *> &list);
const QSGClipNode *m_currentClip;
QSGMaterial *m_currentMaterial;
QSGMaterialShader *m_currentProgram;
const QMatrix4x4 *m_currentMatrix;
QMatrix4x4 m_renderOrderMatrix;
- QVector<QSGGeometryNode *> m_opaqueNodes;
- QVector<QSGGeometryNode *> m_transparentNodes;
- QVector<QSGGeometryNode *> m_tempNodes;
+ QDataBuffer<QSGGeometryNode *> m_opaqueNodes;
+ QDataBuffer<QSGGeometryNode *> m_transparentNodes;
+ QDataBuffer<QSGGeometryNode *> m_tempNodes;
bool m_rebuild_lists;
bool m_needs_sorting;
QSGNode::QSGNode()
: m_parent(0)
+ , m_type(BasicNodeType)
, m_nodeFlags(OwnedByParent)
, m_flags(0)
{
+ init();
+}
+
+QSGNode::QSGNode(NodeType type)
+ : m_parent(0)
+ , m_type(type)
+ , m_nodeFlags(OwnedByParent)
+ , m_flags(0)
+{
+ init();
+}
+
+void QSGNode::init()
+{
#ifndef QT_NO_DEBUG
++qt_node_count;
static bool atexit_registered = false;
atexit_registered = true;
}
#endif
-
}
QSGNode::~QSGNode()
/*!
Creates a new basic geometry node.
*/
-QSGBasicGeometryNode::QSGBasicGeometryNode()
- : m_geometry(0)
+QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
+ : QSGNode(type)
+ , m_geometry(0)
, m_matrix(0)
, m_clip_list(0)
{
*/
QSGGeometryNode::QSGGeometryNode()
- : m_render_order(0)
+ : QSGBasicGeometryNode(GeometryNodeType)
+ , m_render_order(0)
, m_material(0)
, m_opaque_material(0)
, m_opacity(1)
*/
QSGClipNode::QSGClipNode()
+ : QSGBasicGeometryNode(ClipNodeType)
{
}
*/
QSGTransformNode::QSGTransformNode()
+ : QSGNode(TransformNodeType)
{
}
Creates a new root node.
*/
+QSGRootNode::QSGRootNode()
+ : QSGNode(RootNodeType)
+{
+}
/*!
The default opacity of nodes is 1.
*/
QSGOpacityNode::QSGOpacityNode()
- : m_opacity(1)
+ : QSGNode(OpacityNodeType)
+ , m_opacity(1)
, m_combined_opacity(1)
{
}
int childCount() const { return m_children.size(); }
QSGNode *childAtIndex(int i) const { return m_children.at(i); }
- virtual NodeType type() const { return BasicNodeType; }
+ inline NodeType type() const { return m_type; }
void clearDirty() { m_flags = 0; }
void markDirty(DirtyFlags flags);
#endif
protected:
+ QSGNode(NodeType type);
+
// When a node is destroyed, it will detach from the scene graph and the renderer will be
// notified about the change. If the node is detached in the base node's destructor, the
- // renderer can't check what type the node originally was because the node's type() method is
- // virtual and will return the base node type. The renderer might therefore react incorrectly
- // to the change. There are a few of ways I can think of to solve the problem:
- // - The renderer must take into account that the notify method might be called from a node's
- // destructor.
- // - The node can have a type property that is set in the constructor.
- // - All the node destructors must call a common destroy method.
- // I choose the third option since that will allow the renderer to treat the nodes as their
- // proper types.
+ // renderer can't safely cast the node to its original type, since at this point it has been
+ // partly destroyed already. To solve this problem, all the node destructors must call a common
+ // destroy method.
void destroy();
private:
+ void init();
+
QSGNode *m_parent;
+ NodeType m_type;
QList<QSGNode *> m_children;
Flags m_nodeFlags;
// void setUsagePattern(UsagePattern pattern);
// UsagePattern usagePattern() const { return m_pattern; }
- QSGBasicGeometryNode();
~QSGBasicGeometryNode();
void setGeometry(QSGGeometry *geometry);
const QMatrix4x4 *matrix() const { return m_matrix; }
const QSGClipNode *clipList() const { return m_clip_list; }
+protected:
+ QSGBasicGeometryNode(NodeType type);
+
private:
friend class QSGNodeUpdater;
QSGGeometry *m_geometry;
QSGMaterial *activeMaterial() const;
- virtual NodeType type() const { return GeometryNodeType; }
-
void setRenderOrder(int order);
int renderOrder() const { return m_render_order; }
QSGClipNode();
~QSGClipNode();
- virtual NodeType type() const { return ClipNodeType; }
-
void setIsRectangular(bool rectHint);
bool isRectangular() const { return m_is_rectangular; }
QSGTransformNode();
~QSGTransformNode();
- virtual NodeType type() const { return TransformNodeType; }
-
void setMatrix(const QMatrix4x4 &matrix);
const QMatrix4x4 &matrix() const { return m_matrix; }
class Q_DECLARATIVE_EXPORT QSGRootNode : public QSGNode
{
public:
+ QSGRootNode();
~QSGRootNode();
- NodeType type() const { return RootNodeType; }
private:
void notifyNodeChange(QSGNode *node, DirtyFlags flags);
void setCombinedOpacity(qreal opacity);
qreal combinedOpacity() const { return m_combined_opacity; }
- virtual QSGNode::NodeType type() const { return OpacityNodeType; }
-
bool isSubtreeBlocked() const;
-
private:
qreal m_opacity;
qreal m_combined_opacity;
return;
QSize ts = texture->textureSize();
- QRectF sourceRect(0, ts.height(), ts.width(), -ts.height());
+ QRectF sourceRect(0, 0, ts.width(), ts.height());
QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect));
}
+++ /dev/null
-CONFIG += testcase
-
-!symbian {
- INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtQuickTest
-} else {
- load(data_caging_paths)
-
- INCLUDEPATH+=$$MW_LAYER_PUBLIC_EXPORT_PATH(QtQuickTest)
-}
-
-QT += declarative
-
-win32:CONFIG(debug, debug|release) {
- LIBS += -lQtQuickTest$${QT_LIBINFIX}d
-} else {
- LIBS += -lQtQuickTest$${QT_LIBINFIX}
-}
-
-# If the .pro file specified an IMPORTPATH, then add that to
-# the command-line when the test is run.
-!isEmpty(IMPORTPATH) {
- load(testcase)
- for(import, IMPORTPATH): check.commands += -import \"$$import\"
-}
-DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$OUT_PWD\\\"\"
// set handler
//
rootObject = findRootObject();
- QCOMPARE(rootObject.children().size(), 4); // Rectangle, Text, MouseArea, QDeclarativeComponentAttached
+ QCOMPARE(rootObject.children().size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement
QDeclarativeDebugObjectReference mouseAreaObject = rootObject.children().at(2);
QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(mouseAreaObject, this);
waitForQuery(q_obj);
--- /dev/null
+-1:-1:module "" plugin "AType" not found
--- /dev/null
+1:12:unexpected token
+1:-1:expected '.'
+2:17:unexpected token
void versionNotInstalled();
void versionNotInstalled_data();
void implicitQmldir();
+ void implicitQmldir_data();
};
#ifdef Q_OS_SYMBIAN
QVERIFY(!component.isError()); \
QVERIFY(component.errors().isEmpty()); \
} else { \
- QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
+ QString verify_errors_file_name = QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("data") + QDir::separator() + QLatin1String(errorfile); \
+ QFile file(verify_errors_file_name); \
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
QByteArray data = file.readAll(); \
file.close(); \
error.description().toUtf8(); \
actual << errorStr; \
} \
- if (qgetenv("DEBUG") != "" && expected != actual) \
- qWarning() << "Expected:" << expected << "Actual:" << actual; \
+ if (qgetenv("DEBUG") != "" && expected != actual) { \
+ qWarning() << "Expected:" << expected << "Actual:" << actual; \
+ } \
if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
- QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
+ QFile file(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("data") + QDir::separator() + QLatin1String(errorfile)); \
QVERIFY(file.open(QIODevice::WriteOnly)); \
for (int ii = 0; ii < actual.count(); ++ii) { \
file.write(actual.at(ii)); file.write("\n"); \
// test that errors are reporting correctly for plugin loading and qmldir parsing
+void tst_qdeclarativemoduleplugin::implicitQmldir_data()
+{
+ QTest::addColumn<QString>("directory");
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+
+ // parsing qmldir succeeds, but plugin specified in the qmldir file doesn't exist
+ QTest::newRow("implicitQmldir") << "implicit1" << "temptest.qml" << "implicitQmldir.errors.txt";
+
+ // parsing qmldir fails due to syntax errors, etc.
+ QTest::newRow("implicitQmldir2") << "implicit2" << "temptest2.qml" << "implicitQmldir.2.errors.txt";
+}
void tst_qdeclarativemoduleplugin::implicitQmldir()
{
- QDeclarativeEngine engine;
+ QFETCH(QString, directory);
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
- QObject *obj = 0;
- QList<QDeclarativeError> errors;
- QString qmldirUrl;
- QStringList expectedErrors;
+ QString importPath = QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("data") + QDir::separator() + directory;
+ QString fileName = QLatin1String("data") + QDir::separator() + directory + QDir::separator() + file;
+ QString errorFileName = directory + QDir::separator() + errorFile;
+ QUrl testFileUrl = TEST_FILE(fileName);
- // parsing qmldir succeeds, but plugin specified in the qmldir file doesn't exist
- QDeclarativeComponent c(&engine, TEST_FILE("data/implicit1/temptest.qml"));
- qmldirUrl = TEST_FILE("data/implicit1/qmldir").toString();
- errors = c.errors();
- QString moduleName = TEST_FILE("data/implicit1").toString().remove(0,7).replace(QLatin1String("/"), QLatin1String("."));
- expectedErrors << QString(QLatin1String(": module \"") + moduleName + QLatin1String("\" plugin \"AType\" not found"));
- QVERIFY(errors.size() == expectedErrors.size());
- for (int i = 0; i < errors.size(); ++i) {
- QString msg = qmldirUrl + expectedErrors.at(i);
- QCOMPARE(errors.at(i).toString(), msg); // ensure that the expected message matches the real message.
- }
- QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
- obj = c.create();
- QVERIFY(!obj);
- delete obj;
+ QDeclarativeEngine engine;
+ engine.addImportPath(importPath);
- // parsing qmldir fails due to syntax errors etc.
- QDeclarativeComponent c2(&engine, TEST_FILE("data/implicit2/temptest2.qml"));
- qmldirUrl = TEST_FILE("data/implicit2/qmldir").toString();
- errors = c2.errors();
- expectedErrors = QStringList();
- expectedErrors << QLatin1String(":1:12: unexpected token");
- expectedErrors << QLatin1String(":1: expected '.'");
- expectedErrors << QLatin1String(":2:17: unexpected token");
- QVERIFY(errors.size() == expectedErrors.size());
- for (int i = 0; i < errors.size(); ++i) {
- QString msg = qmldirUrl + expectedErrors.at(i);
- QCOMPARE(errors.at(i).toString(), msg); // ensure that the expected message matches the real message.
- }
+ QDeclarativeComponent component(&engine, testFileUrl);
+ QList<QDeclarativeError> errors = component.errors();
+ VERIFY_ERRORS(errorFileName.toLatin1().constData());
QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
- obj = c2.create();
+ QObject *obj = component.create();
QVERIFY(!obj);
delete obj;
}
import QtQuick 2.0
-Image {
- source: "heart200.png"
+Rectangle {
+ width: 300
+ height: 250
+ Image {
+ objectName: "image"
+ anchors.fill: parent
+ source: "heart200.png"
+ }
}
qreal height = 250;
QSGView *canvas = new QSGView;
- canvas->show();
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirror.qml"));
- QSGImage *obj = qobject_cast<QSGImage*>(canvas->rootObject());
+ QSGImage *obj = canvas->rootObject()->findChild<QSGImage*>("image");
QVERIFY(obj != 0);
- obj->setProperty("width", width);
- obj->setProperty("height", height);
obj->setFillMode((QSGImage::FillMode)fillMode);
obj->setProperty("mirror", true);
+ canvas->show();
+
QPixmap screenshot = canvas->renderPixmap();
QPixmap srcPixmap;