diff options
Diffstat (limited to 'tests/auto/declarative/qsgtext')
22 files changed, 1558 insertions, 0 deletions
diff --git a/tests/auto/declarative/qsgtext/data/alignments.qml b/tests/auto/declarative/qsgtext/data/alignments.qml new file mode 100644 index 0000000000..9798d9c736 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 + +Rectangle { + id: top + width: 70; height: 70; + + property alias horizontalAlignment: t.horizontalAlignment + property alias verticalAlignment: t.verticalAlignment + property alias wrapMode: t.wrapMode + property alias running: timer.running + property string txt: "Test" + + Rectangle { + anchors.centerIn: parent + width: 40 + height: 40 + color: "green" + + Text { + id: t + + anchors.fill: parent + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignBottom + wrapMode: Text.WordWrap + text: top.txt + } + Timer { + id: timer + + interval: 1 + running: true + repeat: true + onTriggered: { + top.txt = top.txt + "<br>more " + top.txt.length; + if (top.txt.length > 50) + running = false + } + } + } +} diff --git a/tests/auto/declarative/qsgtext/data/alignments_cb.png b/tests/auto/declarative/qsgtext/data/alignments_cb.png Binary files differnew file mode 100644 index 0000000000..cf6199a418 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_cb.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_cc.png b/tests/auto/declarative/qsgtext/data/alignments_cc.png Binary files differnew file mode 100644 index 0000000000..f81ccb4238 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_cc.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_ct.png b/tests/auto/declarative/qsgtext/data/alignments_ct.png Binary files differnew file mode 100644 index 0000000000..9ba64125d5 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_ct.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_lb.png b/tests/auto/declarative/qsgtext/data/alignments_lb.png Binary files differnew file mode 100644 index 0000000000..1b50a81f3d --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_lb.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_lc.png b/tests/auto/declarative/qsgtext/data/alignments_lc.png Binary files differnew file mode 100644 index 0000000000..f041b868f8 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_lc.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_lt.png b/tests/auto/declarative/qsgtext/data/alignments_lt.png Binary files differnew file mode 100644 index 0000000000..c75e0d158e --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_lt.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_rb.png b/tests/auto/declarative/qsgtext/data/alignments_rb.png Binary files differnew file mode 100644 index 0000000000..b06a5da715 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_rb.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_rc.png b/tests/auto/declarative/qsgtext/data/alignments_rc.png Binary files differnew file mode 100644 index 0000000000..e468857cd0 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_rc.png diff --git a/tests/auto/declarative/qsgtext/data/alignments_rt.png b/tests/auto/declarative/qsgtext/data/alignments_rt.png Binary files differnew file mode 100644 index 0000000000..576715ffce --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/alignments_rt.png diff --git a/tests/auto/declarative/qsgtext/data/embeddedImagesLocal.qml b/tests/auto/declarative/qsgtext/data/embeddedImagesLocal.qml new file mode 100644 index 0000000000..d71e9bb5bf --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/embeddedImagesLocal.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Text { + text: "<img src='http/exists.png'>" +} diff --git a/tests/auto/declarative/qsgtext/data/embeddedImagesLocalError.qml b/tests/auto/declarative/qsgtext/data/embeddedImagesLocalError.qml new file mode 100644 index 0000000000..e6719481db --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/embeddedImagesLocalError.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Text { + text: "<img src='http/notexists.png'>" +} diff --git a/tests/auto/declarative/qsgtext/data/embeddedImagesRemote.qml b/tests/auto/declarative/qsgtext/data/embeddedImagesRemote.qml new file mode 100644 index 0000000000..e524d028b5 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/embeddedImagesRemote.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Text { + text: "<img src='http://127.0.0.1:14453/exists.png'>" +} diff --git a/tests/auto/declarative/qsgtext/data/embeddedImagesRemoteError.qml b/tests/auto/declarative/qsgtext/data/embeddedImagesRemoteError.qml new file mode 100644 index 0000000000..f541e0e497 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/embeddedImagesRemoteError.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Text { + text: "<img src='http://127.0.0.1:14453/notexists.png'>" +} diff --git a/tests/auto/declarative/qsgtext/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qsgtext/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000000..5ba4d35684 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 180 + height: 20 + color: "green" + + Text { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qsgtext/data/http/exists.png b/tests/auto/declarative/qsgtext/data/http/exists.png Binary files differnew file mode 100644 index 0000000000..399bd0b1d9 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/http/exists.png diff --git a/tests/auto/declarative/qsgtext/data/lineCount.qml b/tests/auto/declarative/qsgtext/data/lineCount.qml new file mode 100644 index 0000000000..b672863684 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/lineCount.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + maximumLineCount: undefined + text: "Testing that maximumLines, visibleLines, and totalLines works properly in the autotests. The quick brown fox jumped over the lazy anything with the letter 'g'." + } +} diff --git a/tests/auto/declarative/qsgtext/data/lineHeight.qml b/tests/auto/declarative/qsgtext/data/lineHeight.qml new file mode 100644 index 0000000000..c1f337aa05 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/lineHeight.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + font.pixelSize: 13 + text: "Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum." + } +} diff --git a/tests/auto/declarative/qsgtext/data/qtbug_14734.qml b/tests/auto/declarative/qsgtext/data/qtbug_14734.qml new file mode 100644 index 0000000000..e71a798421 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/qtbug_14734.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Rectangle { + width: 640 + height: 480 + + Text { + text: "Ã " + } +} diff --git a/tests/auto/declarative/qsgtext/data/rotated.qml b/tests/auto/declarative/qsgtext/data/rotated.qml new file mode 100644 index 0000000000..fecf64b249 --- /dev/null +++ b/tests/auto/declarative/qsgtext/data/rotated.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 + +Rectangle { + width : 200 + height : 100 + + Text { + objectName: "text" + x: 20 + y: 20 + height : 20 + width : 80 + text : "Something" + rotation : 30 + transformOrigin : Item.TopLeft + } +} + diff --git a/tests/auto/declarative/qsgtext/qsgtext.pro b/tests/auto/declarative/qsgtext/qsgtext.pro new file mode 100644 index 0000000000..99aac1982f --- /dev/null +++ b/tests/auto/declarative/qsgtext/qsgtext.pro @@ -0,0 +1,24 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +QT += network +macx:CONFIG -= app_bundle + +SOURCES += tst_qsgtext.cpp + +INCLUDEPATH += ../shared/ +HEADERS += ../shared/testhttpserver.h +SOURCES += ../shared/testhttpserver.cpp + +symbian: { + importFiles.files = data + importFiles.path = . + DEPLOYMENT += importFiles +} else { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +CONFIG += parallel_test + +QT += core-private gui-private declarative-private +QT += script-private +QT += opengl-private diff --git a/tests/auto/declarative/qsgtext/tst_qsgtext.cpp b/tests/auto/declarative/qsgtext/tst_qsgtext.cpp new file mode 100644 index 0000000000..27db79b640 --- /dev/null +++ b/tests/auto/declarative/qsgtext/tst_qsgtext.cpp @@ -0,0 +1,1392 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qtest.h> +#include <QTextDocument> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativecomponent.h> +#include <private/qsgtext_p.h> +#include <private/qsgtext_p_p.h> +#include <private/qdeclarativevaluetype_p.h> +#include <QFontMetrics> +#include <QGraphicsSceneMouseEvent> +#include <qmath.h> +#include <QSGView> +#include <private/qapplication_p.h> +#include <limits.h> + +#include "../../../shared/util.h" +#include "testhttpserver.h" +#include <QtOpenGL/QGLShaderProgram> + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +class tst_qsgtext : public QObject + +{ + Q_OBJECT +public: + tst_qsgtext(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void text(); + void width(); + void wrap(); + void elide(); + void textFormat(); + + void alignments_data(); + void alignments(); + + void embeddedImages_data(); + void embeddedImages(); + + void lineCount(); + void lineHeight(); + + // ### these tests may be trivial + void horizontalAlignment(); + void horizontalAlignment_RightToLeft(); + void verticalAlignment(); + void font(); + void style(); + void color(); + void smooth(); + + // QDeclarativeFontValueType + void weight(); + void underline(); + void overline(); + void strikeout(); + void capitalization(); + void letterSpacing(); + void wordSpacing(); + + void clickLink(); + + void QTBUG_12291(); + void implicitSize_data(); + void implicitSize(); + + void qtbug_14734(); +private: + QStringList standard; + QStringList richText; + + QStringList horizontalAlignmentmentStrings; + QStringList verticalAlignmentmentStrings; + + QList<Qt::Alignment> verticalAlignmentments; + QList<Qt::Alignment> horizontalAlignmentments; + + QStringList styleStrings; + QList<QSGText::TextStyle> styles; + + QStringList colorStrings; + + QDeclarativeEngine engine; + + QSGView *createView(const QString &filename); +}; +void tst_qsgtext::initTestCase() +{ + QSGView canvas; + if (!QGLShaderProgram::hasOpenGLShaderPrograms(canvas.context())) + QSKIP("Text item needs OpenGL 2.0", SkipAll); +} + +void tst_qsgtext::cleanupTestCase() +{ + +} +tst_qsgtext::tst_qsgtext() +{ + standard << "the quick brown fox jumped over the lazy dog" + << "the quick brown fox\n jumped over the lazy dog"; + + richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>" + << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>"; + + horizontalAlignmentmentStrings << "AlignLeft" + << "AlignRight" + << "AlignHCenter"; + + verticalAlignmentmentStrings << "AlignTop" + << "AlignBottom" + << "AlignVCenter"; + + horizontalAlignmentments << Qt::AlignLeft + << Qt::AlignRight + << Qt::AlignHCenter; + + verticalAlignmentments << Qt::AlignTop + << Qt::AlignBottom + << Qt::AlignVCenter; + + styleStrings << "Normal" + << "Outline" + << "Raised" + << "Sunken"; + + styles << QSGText::Normal + << QSGText::Outline + << QSGText::Raised + << QSGText::Sunken; + + colorStrings << "aliceblue" + << "antiquewhite" + << "aqua" + << "darkkhaki" + << "darkolivegreen" + << "dimgray" + << "palevioletred" + << "lightsteelblue" + << "#000000" + << "#AAAAAA" + << "#FFFFFF" + << "#2AC05F"; + // + // need a different test to do alpha channel test + // << "#AA0011DD" + // << "#00F16B11"; + // +} + +QSGView *tst_qsgtext::createView(const QString &filename) +{ + QSGView *canvas = new QSGView(0); + + canvas->setSource(QUrl::fromLocalFile(filename)); + return canvas; +} + +void tst_qsgtext::text() +{ + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->text(), QString("")); + QVERIFY(textObject->width() == 0); + + delete textObject; + } + + for (int i = 0; i < standard.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->text(), standard.at(i)); + QVERIFY(textObject->width() > 0); + + delete textObject; + } + + for (int i = 0; i < richText.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QString expected = richText.at(i); + QCOMPARE(textObject->text(), expected.replace("\\\"", "\"")); + QVERIFY(textObject->width() > 0); + + delete textObject; + } +} + +void tst_qsgtext::width() +{ + // uses Font metrics to find the width for standard and document to find the width for rich + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), 0.); + + delete textObject; + } + + for (int i = 0; i < standard.size(); i++) + { + QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test + + QFont f; + QFontMetricsF fm(f); + qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width(); + metricWidth = qCeil(metricWidth); + + QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QVERIFY(textObject->boundingRect().width() > 0); + QCOMPARE(textObject->width(), qreal(metricWidth)); + QVERIFY(textObject->textFormat() == QSGText::AutoText); // setting text doesn't change format + + delete textObject; + } + + for (int i = 0; i < richText.size(); i++) + { + QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test + + QTextDocument document; + document.setHtml(richText.at(i)); + document.setDocumentMargin(0); + + int documentWidth = document.idealWidth(); + + QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), qreal(documentWidth)); + QVERIFY(textObject->textFormat() == QSGText::AutoText); // setting text doesn't change format + + delete textObject; + } +} + +void tst_qsgtext::wrap() +{ + int textHeight = 0; + // for specified width and wrap set true + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + textHeight = textObject->height(); + + QVERIFY(textObject != 0); + QVERIFY(textObject->wrapMode() == QSGText::WordWrap); + QCOMPARE(textObject->width(), 300.); + + delete textObject; + } + + for (int i = 0; i < standard.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), 30.); + QVERIFY(textObject->height() > textHeight); + + int oldHeight = textObject->height(); + textObject->setWidth(100); + QVERIFY(textObject->height() < oldHeight); + + delete textObject; + } + + for (int i = 0; i < richText.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), 30.); + QVERIFY(textObject->height() > textHeight); + + qreal oldHeight = textObject->height(); + textObject->setWidth(100); + QVERIFY(textObject->height() < oldHeight); + + delete textObject; + } + + // richtext again with a fixed height + for (int i = 0; i < richText.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), 30.); + QVERIFY(textObject->implicitHeight() > textHeight); + + qreal oldHeight = textObject->implicitHeight(); + textObject->setWidth(100); + QVERIFY(textObject->implicitHeight() < oldHeight); + + delete textObject; + } +} + +void tst_qsgtext::elide() +{ + for (QSGText::TextElideMode m = QSGText::ElideLeft; m<=QSGText::ElideNone; m=QSGText::TextElideMode(int(m)+1)) { + const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"}; + QString elide = "elide: Text." + QString(elidename[int(m)]) + ";"; + + // XXX Poor coverage. + + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->elideMode(), m); + QCOMPARE(textObject->width(), 100.); + + delete textObject; + } + + for (int i = 0; i < standard.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->elideMode(), m); + QCOMPARE(textObject->width(), 100.); + + delete textObject; + } + + // richtext - does nothing + for (int i = 0; i < richText.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->elideMode(), m); + QCOMPARE(textObject->width(), 100.); + + delete textObject; + } + } +} + +void tst_qsgtext::textFormat() +{ + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QVERIFY(textObject->textFormat() == QSGText::RichText); + + delete textObject; + } + { + QDeclarativeComponent textComponent(&engine); + textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QVERIFY(textObject->textFormat() == QSGText::PlainText); + + delete textObject; + } +} + + +void tst_qsgtext::alignments_data() +{ + QTest::addColumn<int>("hAlign"); + QTest::addColumn<int>("vAlign"); + QTest::addColumn<QString>("expectfile"); + + QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << SRCDIR "/data/alignments_lt.png"; + QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << SRCDIR "/data/alignments_rt.png"; + QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << SRCDIR "/data/alignments_ct.png"; + + QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_lb.png"; + QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_rb.png"; + QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_cb.png"; + + QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_lc.png"; + QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_rc.png"; + QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_cc.png"; +} + + +void tst_qsgtext::alignments() +{ + QSKIP("Text alignment pixmap comparison tests will not work with scenegraph", SkipAll); + + QFETCH(int, hAlign); + QFETCH(int, vAlign); + QFETCH(QString, expectfile); + +#ifdef Q_WS_X11 + // Font-specific, but not likely platform-specific, so only test on one platform + QFont fn; + fn.setRawName("-misc-fixed-medium-r-*-*-8-*-*-*-*-*-*-*"); + QApplication::setFont(fn); +#endif + + QSGView *canvas = createView(SRCDIR "/data/alignments.qml"); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QObject *ob = canvas->rootObject(); + QVERIFY(ob != 0); + ob->setProperty("horizontalAlignment",hAlign); + ob->setProperty("verticalAlignment",vAlign); + QTRY_COMPARE(ob->property("running").toBool(),false); + QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32); + actual.fill(qRgb(255,255,255)); + QPainter p(&actual); + canvas->render(&p); + + QImage expect(expectfile); + +#ifdef Q_WS_X11 + // Font-specific, but not likely platform-specific, so only test on one platform + if (QApplicationPrivate::graphics_system_name == "raster" || QApplicationPrivate::graphics_system_name == "") { + QCOMPARE(actual,expect); + } +#endif + + delete canvas; +} + +//the alignment tests may be trivial o.oa +void tst_qsgtext::horizontalAlignment() +{ + //test one align each, and then test if two align fails. + + for (int i = 0; i < standard.size(); i++) + { + for (int j=0; j < horizontalAlignmentmentStrings.size(); j++) + { + QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j)); + + delete textObject; + } + } + + for (int i = 0; i < richText.size(); i++) + { + for (int j=0; j < horizontalAlignmentmentStrings.size(); j++) + { + QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j)); + + delete textObject; + } + } + +} + +void tst_qsgtext::horizontalAlignment_RightToLeft() +{ + QSGView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QSGText *text = canvas->rootObject()->findChild<QSGText*>("text"); + QVERIFY(text != 0); + canvas->show(); + + QSGTextPrivate *textPrivate = QSGTextPrivate::get(text); + QVERIFY(textPrivate != 0); + + // implicit alignment should follow the reading direction of RTL text + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // explicitly left aligned text + text->setHAlign(QSGText::AlignLeft); + QCOMPARE(text->hAlign(), QSGText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + + // explicitly right aligned text + text->setHAlign(QSGText::AlignRight); + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // change to rich text + QString textString = text->text(); + text->setText(QString("<i>") + textString + QString("</i>")); + text->setTextFormat(QSGText::RichText); + text->resetHAlign(); + + // implicitly aligned rich text should follow the reading direction of text + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft); + + // explicitly left aligned rich text + text->setHAlign(QSGText::AlignLeft); + QCOMPARE(text->hAlign(), QSGText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight); + + // explicitly right aligned rich text + text->setHAlign(QSGText::AlignRight); + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft); + + text->setText(textString); + text->setTextFormat(QSGText::PlainText); + + // explicitly center aligned + text->setHAlign(QSGText::AlignHCenter); + QCOMPARE(text->hAlign(), QSGText::AlignHCenter); + QCOMPARE(text->effectiveHAlign(), text->hAlign()); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2); + + // reseted alignment should go back to following the text reading direction + text->resetHAlign(); + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // mirror the text item + QSGItemPrivate::get(text)->setLayoutMirror(true); + + // mirrored implicit alignment should continue to follow the reading direction of the text + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), QSGText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // mirrored explicitly right aligned behaves as left aligned + text->setHAlign(QSGText::AlignRight); + QCOMPARE(text->hAlign(), QSGText::AlignRight); + QCOMPARE(text->effectiveHAlign(), QSGText::AlignLeft); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + + // mirrored explicitly left aligned behaves as right aligned + text->setHAlign(QSGText::AlignLeft); + QCOMPARE(text->hAlign(), QSGText::AlignLeft); + QCOMPARE(text->effectiveHAlign(), QSGText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2); + + // disable mirroring + QSGItemPrivate::get(text)->setLayoutMirror(false); + text->resetHAlign(); + + // English text should be implicitly left aligned + text->setText("Hello world!"); + QCOMPARE(text->hAlign(), QSGText::AlignLeft); + QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2); + +#ifndef Q_OS_MAC // QTBUG-18040 + // empty text with implicit alignment follows the system locale-based + // keyboard input direction from QApplication::keyboardInputDirection + text->setText(""); + QCOMPARE(text->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QSGText::AlignLeft : QSGText::AlignRight); + text->setHAlign(QSGText::AlignRight); + QCOMPARE(text->hAlign(), QSGText::AlignRight); +#endif + + delete canvas; + +#ifndef Q_OS_MAC // QTBUG-18040 + // alignment of Text with no text set to it + QString componentStr = "import QtQuick 2.0\nText {}"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ? + QSGText::AlignLeft : QSGText::AlignRight); + delete textObject; +#endif +} + +void tst_qsgtext::verticalAlignment() +{ + //test one align each, and then test if two align fails. + + for (int i = 0; i < standard.size(); i++) + { + for (int j=0; j < verticalAlignmentmentStrings.size(); j++) + { + QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j)); + + delete textObject; + } + } + + for (int i = 0; i < richText.size(); i++) + { + for (int j=0; j < verticalAlignmentmentStrings.size(); j++) + { + QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j)); + + delete textObject; + } + } + +} + +void tst_qsgtext::font() +{ + //test size, then bold, then italic, then family + { + QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().pointSize(), 40); + QCOMPARE(textObject->font().bold(), false); + QCOMPARE(textObject->font().italic(), false); + + delete textObject; + } + + { + QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().pixelSize(), 40); + QCOMPARE(textObject->font().bold(), false); + QCOMPARE(textObject->font().italic(), false); + + delete textObject; + } + + { + QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().bold(), true); + QCOMPARE(textObject->font().italic(), false); + + delete textObject; + } + + { + QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().italic(), true); + QCOMPARE(textObject->font().bold(), false); + + delete textObject; + } + + { + QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().family(), QString("Helvetica")); + QCOMPARE(textObject->font().bold(), false); + QCOMPARE(textObject->font().italic(), false); + + delete textObject; + } + + { + QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->font().family(), QString("")); + + delete textObject; + } +} + +void tst_qsgtext::style() +{ + //test style + for (int i = 0; i < styles.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE((int)textObject->style(), (int)styles.at(i)); + QCOMPARE(textObject->styleColor(), QColor("white")); + + delete textObject; + } + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QRectF brPre = textObject->boundingRect(); + textObject->setStyle(QSGText::Outline); + QRectF brPost = textObject->boundingRect(); + + QVERIFY(brPre.width() < brPost.width()); + QVERIFY(brPre.height() < brPost.height()); + + delete textObject; +} + +void tst_qsgtext::color() +{ + //test style + for (int i = 0; i < colorStrings.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->color(), QColor(colorStrings.at(i))); + QCOMPARE(textObject->styleColor(), QColor()); + + delete textObject; + } + + for (int i = 0; i < colorStrings.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i))); + // default color to black? + QCOMPARE(textObject->color(), QColor("black")); + + delete textObject; + } + + for (int i = 0; i < colorStrings.size(); i++) + { + for (int j = 0; j < colorStrings.size(); j++) + { + QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->color(), QColor(colorStrings.at(i))); + QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j))); + + delete textObject; + } + } + { + QString colorStr = "#AA001234"; + QColor testColor("#001234"); + testColor.setAlpha(170); + + QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QCOMPARE(textObject->color(), testColor); + + delete textObject; + } +} + +void tst_qsgtext::smooth() +{ + for (int i = 0; i < standard.size(); i++) + { + { + QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + QCOMPARE(textObject->smooth(), true); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + QCOMPARE(textObject->smooth(), false); + + delete textObject; + } + } + for (int i = 0; i < richText.size(); i++) + { + { + QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + QCOMPARE(textObject->smooth(), true); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + QCOMPARE(textObject->smooth(), false); + + delete textObject; + } + } +} + +void tst_qsgtext::weight() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Normal); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Bold); + + delete textObject; + } +} + +void tst_qsgtext::underline() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().underline(), false); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { font.underline: true; text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().underline(), true); + + delete textObject; + } +} + +void tst_qsgtext::overline() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().overline(), false); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { font.overline: true; text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().overline(), true); + + delete textObject; + } +} + +void tst_qsgtext::strikeout() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().strikeOut(), false); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { font.strikeout: true; text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().strikeOut(), true); + + delete textObject; + } +} + +void tst_qsgtext::capitalization() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::MixedCase); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllUppercase); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllLowercase); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::SmallCaps); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::Capitalize); + + delete textObject; + } +} + +void tst_qsgtext::letterSpacing() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().letterSpacing(), 0.0); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().letterSpacing(), -2.); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().letterSpacing(), 3.); + + delete textObject; + } +} + +void tst_qsgtext::wordSpacing() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().wordSpacing(), 0.0); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().wordSpacing(), -50.); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->font().wordSpacing(), 200.); + + delete textObject; + } +} + +void tst_qsgtext::QTBUG_12291() +{ + QSGView *canvas = createView(SRCDIR "/data/rotated.qml"); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QObject *ob = canvas->rootObject(); + QVERIFY(ob != 0); + + QSGText *text = ob->findChild<QSGText*>("text"); + QVERIFY(text); + QVERIFY(text->boundingRect().isValid()); + + delete canvas; +} + +class EventSender : public QSGItem +{ +public: + void sendEvent(QEvent *event) { + if (event->type() == QEvent::GraphicsSceneMousePress) + mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event)); + else if (event->type() == QEvent::GraphicsSceneMouseRelease) + mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event)); + else + qWarning() << "Trying to send unsupported event type"; + } +}; + +class LinkTest : public QObject +{ + Q_OBJECT +public: + LinkTest() {} + + QString link; + +public slots: + void linkClicked(QString l) { link = l; } +}; + +void tst_qsgtext::clickLink() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + + LinkTest test; + QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString))); + + { + QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress); + me.setPos(QPointF(textObject->x()/2, textObject->y()/2)); + me.setButton(Qt::LeftButton); + static_cast<EventSender*>(static_cast<QSGItem*>(textObject))->sendEvent(&me); + } + + { + QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMouseRelease); + me.setPos(QPointF(textObject->x()/2, textObject->y()/2)); + me.setButton(Qt::LeftButton); + static_cast<EventSender*>(static_cast<QSGItem*>(textObject))->sendEvent(&me); + } + + QCOMPARE(test.link, QLatin1String("http://qt.nokia.com")); + + delete textObject; + } +} + +void tst_qsgtext::embeddedImages_data() +{ + QTest::addColumn<QUrl>("qmlfile"); + QTest::addColumn<QString>("error"); + QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocal.qml") << ""; + QTest::newRow("local-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocalError.qml") + << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/http/notexists.png").toString(); + QTest::newRow("remote") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemote.qml") << ""; + QTest::newRow("remote-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemoteError.qml") + << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found"; +} + +void tst_qsgtext::embeddedImages() +{ + // Tests QTBUG-9900 + + QFETCH(QUrl, qmlfile); + QFETCH(QString, error); + + TestHTTPServer server(14453); + server.serveDirectory(SRCDIR "/data/http"); + + if (!error.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, error.toLatin1()); + + QDeclarativeComponent textComponent(&engine, qmlfile); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject != 0); + + QTRY_COMPARE(textObject->resourcesLoading(), 0); + + QPixmap pm(SRCDIR "/data/http/exists.png"); + if (error.isEmpty()) { + QCOMPARE(textObject->width(), double(pm.width())); + QCOMPARE(textObject->height(), double(pm.height())); + } else { + QVERIFY(16 != pm.width()); // check test is effective + QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon + QCOMPARE(textObject->height(), 16.0); + } + + delete textObject; +} + +void tst_qsgtext::lineCount() +{ + QSGView *canvas = createView(SRCDIR "/data/lineCount.qml"); + + QSGText *myText = canvas->rootObject()->findChild<QSGText*>("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineCount() > 1); + QVERIFY(!myText->truncated()); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); + + myText->resetMaximumLineCount(); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + QCOMPARE(myText->truncated(), false); + + myText->setElideMode(QSGText::ElideRight); + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); + + delete canvas; +} + +void tst_qsgtext::lineHeight() +{ + QSGView *canvas = createView(SRCDIR "/data/lineHeight.qml"); + + QSGText *myText = canvas->rootObject()->findChild<QSGText*>("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineHeight() == 1); + QVERIFY(myText->lineHeightMode() == QSGText::ProportionalHeight); + + qreal h = myText->height(); + myText->setLineHeight(1.5); + QVERIFY(myText->height() == h * 1.5); + + myText->setLineHeightMode(QSGText::FixedHeight); + myText->setLineHeight(20); + QCOMPARE(myText->height(), myText->lineCount() * 20.0); + + myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum."); + myText->setLineHeightMode(QSGText::ProportionalHeight); + myText->setLineHeight(1.0); + + qreal h2 = myText->height(); + myText->setLineHeight(2.0); + QVERIFY(myText->height() == h2 * 2.0); + + myText->setLineHeightMode(QSGText::FixedHeight); + myText->setLineHeight(10); + QCOMPARE(myText->height(), myText->lineCount() * 10.0); + + delete canvas; +} + +void tst_qsgtext::implicitSize_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.Wrap"; +} + +void tst_qsgtext::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QSGText *textObject = qobject_cast<QSGText*>(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + delete textObject; +} + +void tst_qsgtext::qtbug_14734() +{ + QSGView *canvas = createView(SRCDIR "/data/qtbug_14734.qml"); + QVERIFY(canvas); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + delete canvas; +} + +QTEST_MAIN(tst_qsgtext) + +#include "tst_qsgtext.moc" |