diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2011-06-01 09:45:55 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-08-19 15:15:56 +0200 |
commit | 1cc58fdf174656a52603af00cb40478066c5abd4 (patch) | |
tree | 432054d60316a981b17655dc888805e4e5434966 /tests | |
parent | 7059861a8b8d48b5187eb46a2678f306ba288320 (diff) |
Make QSGTextNode back-end for QML's TextInput and TextEdit
Use the general QSGTextNode class as back-end for all text
elements in QML to make all text elements look the same and
use the same text rasterization back-end. This requires a
few rewrites in the text node to support e.g. selections.
Crashes seen with threaded renderer in TextEdit and TextInput on
Mac are also fixed by this.
Reviewed-by: Jiang Jiang
Task-number: QTBUG-18019, QTBUG-20017
Change-Id: I4207faf180c83422e5f8b726741321af395bd724
Reviewed-on: http://codereview.qt.nokia.com/2865
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Diffstat (limited to 'tests')
4 files changed, 185 insertions, 15 deletions
diff --git a/tests/auto/declarative/qsgtext/tst_qsgtext.cpp b/tests/auto/declarative/qsgtext/tst_qsgtext.cpp index 48d679bfa7..747ea51f41 100644 --- a/tests/auto/declarative/qsgtext/tst_qsgtext.cpp +++ b/tests/auto/declarative/qsgtext/tst_qsgtext.cpp @@ -45,6 +45,7 @@ #include <private/qsgtext_p.h> #include <private/qsgtext_p_p.h> #include <private/qdeclarativevaluetype_p.h> +#include <private/qsgdistancefieldglyphcache_p.h> #include <QFontMetrics> #include <QGraphicsSceneMouseEvent> #include <qmath.h> @@ -61,6 +62,8 @@ #define SRCDIR "." #endif +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) + class tst_qsgtext : public QObject { @@ -261,14 +264,42 @@ void tst_qsgtext::width() delete textObject; } + bool requiresUnhintedMetrics = !qmlDisableDistanceField(); + 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); + qreal metricWidth = 0.0; + + if (requiresUnhintedMetrics) { + QString s = standard.at(i); + s.replace(QLatin1Char('\n'), QChar::LineSeparator); + + QTextLayout layout(s); + layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic); + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + + layout.endLayout(); + + metricWidth = qCeil(layout.boundingRect().width()); + } else { + 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); diff --git a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp index 3492ac2138..2a94e20d3f 100644 --- a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp +++ b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp @@ -51,6 +51,7 @@ #include <QtDeclarative/qdeclarativecomponent.h> #include <private/qsgtextedit_p.h> #include <private/qsgtextedit_p_p.h> +#include <private/qsgdistancefieldglyphcache_p.h> #include <QFontMetrics> #include <QSGView> #include <QDir> @@ -72,6 +73,7 @@ #endif Q_DECLARE_METATYPE(QSGTextEdit::SelectionMode) +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { @@ -280,12 +282,40 @@ void tst_qsgtextedit::width() QCOMPARE(textEditObject->width(), 0.0); } + bool requiresUnhintedMetrics = !qmlDisableDistanceField(); + for (int i = 0; i < standard.size(); i++) { QFont f; - QFontMetricsF fm(f); - qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width(); - metricWidth = ceil(metricWidth); + qreal metricWidth = 0.0; + + if (requiresUnhintedMetrics) { + QString s = standard.at(i); + s.replace(QLatin1Char('\n'), QChar::LineSeparator); + + QTextLayout layout(s); + layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic); + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + + layout.endLayout(); + + metricWidth = ceil(layout.boundingRect().width()); + } else { + QFontMetricsF fm(f); + metricWidth = fm.size(Qt::TextExpandTabs | Qt::TextShowMnemonic, standard.at(i)).width(); + metricWidth = ceil(metricWidth); + } QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }"; QDeclarativeComponent texteditComponent(&engine); @@ -301,6 +331,8 @@ void tst_qsgtextedit::width() QTextDocument document; document.setHtml(richText.at(i)); document.setDocumentMargin(0); + if (requiresUnhintedMetrics) + document.setUseDesignMetrics(true); int documentWidth = ceil(document.idealWidth()); @@ -455,7 +487,6 @@ void tst_qsgtextedit::hAlign() void tst_qsgtextedit::hAlign_RightToLeft() { - QSKIP("QTBUG-20017", SkipAll); QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/horizontalAlignment_RightToLeft.qml")); QSGTextEdit *textEdit = canvas.rootObject()->findChild<QSGTextEdit*>("text"); QVERIFY(textEdit != 0); @@ -1471,7 +1502,28 @@ void tst_qsgtextedit::positionAt() const int y1 = fm.height() * 3 / 2; int pos = texteditObject->positionAt(texteditObject->width()/2, y0); - int diff = abs(int(fm.width(texteditObject->text().left(pos))-texteditObject->width()/2)); + int width = 0; + if (!qmlDisableDistanceField()) { + QTextLayout layout(texteditObject->text().left(pos)); + + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + width = ceil(line.horizontalAdvance()); + + } else { + width = fm.width(texteditObject->text().left(pos)); + } + + + int diff = abs(int(width-texteditObject->width()/2)); // some tollerance for different fonts. #ifdef Q_OS_LINUX diff --git a/tests/auto/declarative/qsgtextinput/data/positionAt.qml b/tests/auto/declarative/qsgtextinput/data/positionAt.qml index 7611376e13..1840462c87 100644 --- a/tests/auto/declarative/qsgtextinput/data/positionAt.qml +++ b/tests/auto/declarative/qsgtextinput/data/positionAt.qml @@ -4,5 +4,5 @@ TextInput{ focus: true objectName: "myInput" width: 50 - text: "This is a long piece of text" + text: "AAAAAAAAAAAAAAAAAAAAAAAAAAAA" } diff --git a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp index 93e8ad21fd..744717cd80 100644 --- a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp +++ b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp @@ -51,7 +51,9 @@ #include <QStyle> #include <QInputContext> #include <private/qapplication_p.h> +#include <private/qsgdistancefieldglyphcache_p.h> #include <QtOpenGL/QGLShaderProgram> +#include <math.h> #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -59,6 +61,7 @@ #endif Q_DECLARE_METATYPE(QSGTextInput::SelectionMode) +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { @@ -221,11 +224,38 @@ void tst_qsgtextinput::width() delete textinputObject; } + bool requiresUnhintedMetrics = !qmlDisableDistanceField(); + for (int i = 0; i < standard.size(); i++) { QFont f; - QFontMetricsF fm(f); - qreal metricWidth = fm.width(standard.at(i)); + qreal metricWidth = 0.0; + if (requiresUnhintedMetrics) { + QString s = standard.at(i); + s.replace(QLatin1Char('\n'), QChar::LineSeparator); + + QTextLayout layout(s); + layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic); + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + + layout.endLayout(); + + metricWidth = ceil(layout.boundingRect().width()); + } else { + QFontMetricsF fm(f); + metricWidth = fm.width(standard.at(i)); + } QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }"; QDeclarativeComponent textinputComponent(&engine); @@ -1048,7 +1078,6 @@ void tst_qsgtextinput::horizontalAlignment() void tst_qsgtextinput::horizontalAlignment_RightToLeft() { - QSKIP("QTBUG-20017", SkipAll); QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/horizontalAlignment_RightToLeft.qml")); QSGTextInput *textInput = canvas.rootObject()->findChild<QSGTextInput*>("text"); QVERIFY(textInput != 0); @@ -1161,7 +1190,45 @@ void tst_qsgtextinput::positionAt() QFontMetrics fm(textinputObject->font()); int pos = textinputObject->positionAt(textinputObject->width()/2); - int diff = abs(int(fm.width(textinputObject->text()) - (fm.width(textinputObject->text().left(pos))+textinputObject->width()/2))); + int textWidth = 0; + int textLeftWidth = 0; + if (!qmlDisableDistanceField()) { + { + QTextLayout layout(textinputObject->text().left(pos)); + + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + textLeftWidth = ceil(line.horizontalAdvance()); + } + { + QTextLayout layout(textinputObject->text()); + + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + textWidth = ceil(line.horizontalAdvance()); + } + } else { + textWidth = fm.width(textinputObject->text()); + textLeftWidth = fm.width(textinputObject->text().left(pos)); + } + + int diff = abs(textWidth - (textLeftWidth+textinputObject->width()/2)); // some tollerance for different fonts. #ifdef Q_OS_LINUX @@ -1177,7 +1244,28 @@ void tst_qsgtextinput::positionAt() // Check without autoscroll... textinputObject->setAutoScroll(false); pos = textinputObject->positionAt(textinputObject->width()/2); - diff = abs(int(fm.width(textinputObject->text().left(pos))-textinputObject->width()/2)); + + if (!qmlDisableDistanceField()) { + { + QTextLayout layout(textinputObject->text().left(pos)); + + { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + textLeftWidth = ceil(line.horizontalAdvance()); + } + } else { + textLeftWidth = fm.width(textinputObject->text().left(pos)); + } + + diff = abs(int(textLeftWidth-textinputObject->width()/2)); // some tollerance for different fonts. #ifdef Q_OS_LINUX @@ -1442,7 +1530,6 @@ void tst_qsgtextinput::navigation() void tst_qsgtextinput::navigation_RTL() { - QSKIP("QTBUG-20017", SkipAll); QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/navigation.qml")); canvas.show(); canvas.setFocus(); |