From 2a6e105f43885e0901c252bffc77bd1c9db87b67 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 19 Apr 2012 11:08:28 +1000 Subject: Fix bounding rects of text items. Ensure the rectangles are correctly positioned with right and center aligned text, not just sized correctly. Also add padding to the clip rects so the cursor and styled text aren't clipped at the item boundaries. Change-Id: I03ef140589154ebd49b600b0a4c4fbeff845c10f Reviewed-by: Yann Bodson --- tests/auto/quick/qquicktext/tst_qquicktext.cpp | 45 +++++ .../quick/qquicktextedit/tst_qquicktextedit.cpp | 148 ++++++++++++++ .../data/horizontalAlignment_RightToLeft.qml | 2 + .../quick/qquicktextinput/tst_qquicktextinput.cpp | 212 ++++++++++++++++----- 4 files changed, 360 insertions(+), 47 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 297fa0106f..d1899a62b7 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -114,6 +114,7 @@ private slots: void boundingRect_data(); void boundingRect(); + void clipRect(); void lineLaidOut(); void imgTagsBaseUrl_data(); @@ -1802,6 +1803,50 @@ void tst_qquicktext::boundingRect() QVERIFY(text->boundingRect().height() > line.height()); } +void tst_qquicktext::clipRect() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n Text {}", QUrl()); + QScopedPointer object(component.create()); + QQuickText *text = qobject_cast(object.data()); + QVERIFY(text); + + QTextLayout layout; + layout.setFont(text->font()); + + QCOMPARE(text->clipRect().x(), qreal(0)); + QCOMPARE(text->clipRect().y(), qreal(0)); + QCOMPARE(text->clipRect().width(), text->width()); + QCOMPARE(text->clipRect().height(), text->height()); + + text->setText("Hello World"); + + QCOMPARE(text->clipRect().x(), qreal(0)); + QCOMPARE(text->clipRect().y(), qreal(0)); + QCOMPARE(text->clipRect().width(), text->width()); + QCOMPARE(text->clipRect().height(), text->height()); + + // Clip rect follows the item not content dimensions. + text->setWidth(text->width() / 2); + QCOMPARE(text->clipRect().x(), qreal(0)); + QCOMPARE(text->clipRect().y(), qreal(0)); + QCOMPARE(text->clipRect().width(), text->width()); + QCOMPARE(text->clipRect().height(), text->height()); + + text->setHeight(text->height() * 2); + QCOMPARE(text->clipRect().x(), qreal(0)); + QCOMPARE(text->clipRect().y(), qreal(0)); + QCOMPARE(text->clipRect().width(), text->width()); + QCOMPARE(text->clipRect().height(), text->height()); + + // Setting a style adds a small amount of padding to the clip rect. + text->setStyle(QQuickText::Outline); + QCOMPARE(text->clipRect().x(), qreal(-1)); + QCOMPARE(text->clipRect().y(), qreal(0)); + QCOMPARE(text->clipRect().width(), text->width() + 2); + QCOMPARE(text->clipRect().height(), text->height() + 2); +} + void tst_qquicktext::lineLaidOut() { QQuickView *canvas = createView(testFile("lineLayout.qml")); diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 1a5f52f941..9c34a7c8d8 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -152,6 +152,8 @@ private slots: void implicitSize_data(); void implicitSize(); void contentSize(); + void boundingRect(); + void clipRect(); void implicitSizeBinding_data(); void implicitSizeBinding(); @@ -2657,6 +2659,152 @@ void tst_qquicktextedit::implicitSizeBinding() QCOMPARE(textObject->height(), textObject->implicitHeight()); } +void tst_qquicktextedit::clipRect() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n TextEdit {}", QUrl()); + QScopedPointer object(component.create()); + QQuickTextEdit *edit = qobject_cast(object.data()); + QVERIFY(edit); + + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + + QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width()); + QCOMPARE(edit->clipRect().height(), edit->height()); + + edit->setText("Hello World"); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + // XXX: TextEdit allows an extra 3 pixels boundary for the cursor beyond it's width for non + // empty text. TextInput doesn't. + QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + // clip rect shouldn't exceed the size of the item, expect for the cursor width; + edit->setWidth(edit->width() / 2); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + edit->setHeight(edit->height() * 2); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + QQmlComponent cursorComponent(&engine); + cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl()); + + edit->setCursorDelegate(&cursorComponent); + + // If a cursor delegate is used it's size should determine the excess width. + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + // Alignment and wrapping don't affect the clip rect. + edit->setHAlign(QQuickTextEdit::AlignRight); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + edit->setWrapMode(QQuickTextEdit::Wrap); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); + + edit->setVAlign(QQuickTextEdit::AlignBottom); + QCOMPARE(edit->clipRect().x(), qreal(0)); + QCOMPARE(edit->clipRect().y(), qreal(0)); + QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3); + QCOMPARE(edit->clipRect().height(), edit->height()); +} + +void tst_qquicktextedit::boundingRect() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n TextEdit {}", QUrl()); + QScopedPointer object(component.create()); + QQuickTextEdit *edit = qobject_cast(object.data()); + QVERIFY(edit); + + QTextLayout layout; + layout.setFont(edit->font()); + + if (!qmlDisableDistanceField()) { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + QCOMPARE(edit->boundingRect().x(), qreal(0)); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), edit->cursorRectangle().width()); + QCOMPARE(edit->boundingRect().height(), line.height()); + + edit->setText("Hello World"); + + layout.setText(edit->text()); + layout.beginLayout(); + line = layout.createLine(); + layout.endLayout(); + + QCOMPARE(edit->boundingRect().x(), qreal(0)); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->boundingRect().height(), line.height()); + + // the size of the bounding rect shouldn't be bounded by the size of item. + edit->setWidth(edit->width() / 2); + QCOMPARE(edit->boundingRect().x(), qreal(0)); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->boundingRect().height(), line.height()); + + edit->setHeight(edit->height() * 2); + QCOMPARE(edit->boundingRect().x(), qreal(0)); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3); + QCOMPARE(edit->boundingRect().height(), line.height()); + + QQmlComponent cursorComponent(&engine); + cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl()); + + edit->setCursorDelegate(&cursorComponent); + + // Don't include the size of a cursor delegate as it has its own bounding rect. + QCOMPARE(edit->boundingRect().x(), qreal(0)); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth()); + QCOMPARE(edit->boundingRect().height(), line.height()); + + edit->setHAlign(QQuickTextEdit::AlignRight); + QCOMPARE(edit->boundingRect().x(), edit->width() - line.naturalTextWidth()); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth()); + QCOMPARE(edit->boundingRect().height(), line.height()); + + edit->setWrapMode(QQuickTextEdit::Wrap); + QCOMPARE(edit->boundingRect().right(), edit->width()); + QCOMPARE(edit->boundingRect().y(), qreal(0)); + QVERIFY(edit->boundingRect().width() < line.naturalTextWidth()); + QVERIFY(edit->boundingRect().height() > line.height()); + + edit->setVAlign(QQuickTextEdit::AlignBottom); + QCOMPARE(edit->boundingRect().right(), edit->width()); + QCOMPARE(edit->boundingRect().bottom(), edit->height()); + QVERIFY(edit->boundingRect().width() < line.naturalTextWidth()); + QVERIFY(edit->boundingRect().height() > line.height()); +} + void tst_qquicktextedit::preeditCursorRectangle() { QString preeditText = "super"; diff --git a/tests/auto/quick/qquicktextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/quick/qquicktextinput/data/horizontalAlignment_RightToLeft.qml index 5f88025536..d14caea619 100644 --- a/tests/auto/quick/qquicktextinput/data/horizontalAlignment_RightToLeft.qml +++ b/tests/auto/quick/qquicktextinput/data/horizontalAlignment_RightToLeft.qml @@ -19,6 +19,8 @@ Rectangle { anchors.fill: parent text: top.text focus: true + + cursorDelegate: Rectangle { } } } } diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 6f75698c1f..27e557bee5 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -129,6 +129,7 @@ private slots: void horizontalAlignment_RightToLeft(); void verticalAlignment(); + void clipRect(); void boundingRect(); void positionAt(); @@ -1309,43 +1310,41 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() const QString rtlText = textInput->text(); - QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput); - QVERIFY(textInputPrivate != 0); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // implicit alignment should follow the reading direction of RTL text QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // explicitly left aligned textInput->setHAlign(QQuickTextInput::AlignLeft); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); - QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0)); + QCOMPARE(textInput->boundingRect().left(), qreal(0)); // explicitly right aligned textInput->setHAlign(QQuickTextInput::AlignRight); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // explicitly center aligned textInput->setHAlign(QQuickTextInput::AlignHCenter); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignHCenter); - QVERIFY(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll > 0); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll < textInput->width()); + QVERIFY(textInput->boundingRect().left() > 0); + QVERIFY(textInput->boundingRect().right() < textInput->width()); // reseted alignment should go back to following the text reading direction textInput->resetHAlign(); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // mirror the text item QQuickItemPrivate::get(textInput)->setLayoutMirror(true); @@ -1353,21 +1352,21 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() // mirrored implicit alignment should continue to follow the reading direction of the text QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign()); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // explicitly right aligned behaves as left aligned textInput->setHAlign(QQuickTextInput::AlignRight); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignLeft); - QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0)); + QCOMPARE(textInput->boundingRect().left(), qreal(0)); // mirrored explicitly left aligned behaves as right aligned textInput->setHAlign(QQuickTextInput::AlignLeft); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft); QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // disable mirroring QQuickItemPrivate::get(textInput)->setLayoutMirror(false); @@ -1377,7 +1376,7 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() // English text should be implicitly left aligned textInput->setText("Hello world!"); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft); - QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0)); + QCOMPARE(textInput->boundingRect().left(), qreal(0)); canvas.requestActivateWindow(); QTest::qWaitForWindowShown(&canvas); @@ -1400,15 +1399,15 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() platformInputContext.setInputDirection(Qt::LeftToRight); QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft); - QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0)); + QCOMPARE(textInput->boundingRect().left(), qreal(0)); QSignalSpy cursorRectangleSpy(textInput, SIGNAL(cursorRectangleChanged())); platformInputContext.setInputDirection(Qt::RightToLeft); QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft); QCOMPARE(cursorRectangleSpy.count(), 1); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // set input direction while having content platformInputContext.setInputDirection(Qt::LeftToRight); @@ -1417,8 +1416,8 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() QTest::keyClick(&canvas, Qt::Key_Backspace); QVERIFY(textInput->text().isEmpty()); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); // input direction changed while not having focus platformInputContext.setInputDirection(Qt::LeftToRight); @@ -1426,13 +1425,13 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft() platformInputContext.setInputDirection(Qt::RightToLeft); textInput->setFocus(true); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); textInput->setHAlign(QQuickTextInput::AlignRight); QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1); - QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1); + QVERIFY(textInput->boundingRect().right() >= textInput->width() - 1); + QVERIFY(textInput->boundingRect().right() <= textInput->width() + 1); } void tst_qquicktextinput::verticalAlignment() @@ -1442,33 +1441,30 @@ void tst_qquicktextinput::verticalAlignment() QVERIFY(textInput != 0); canvas.show(); - QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput); - QVERIFY(textInputPrivate != 0); - QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignTop); - QVERIFY(textInputPrivate->boundingRect.bottom() - textInputPrivate->vscroll < canvas.height() / 2); + QVERIFY(textInput->boundingRect().bottom() < canvas.height() / 2); QVERIFY(textInput->cursorRectangle().bottom() < canvas.height() / 2); QVERIFY(textInput->positionToRectangle(0).bottom() < canvas.height() / 2); // bottom aligned textInput->setVAlign(QQuickTextInput::AlignBottom); QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignBottom); - QVERIFY(textInputPrivate->boundingRect.top() - textInputPrivate->vscroll > canvas.height() / 2); + QVERIFY(textInput->boundingRect().top() > canvas.height() / 2); QVERIFY(textInput->cursorRectangle().top() > canvas.height() / 2); QVERIFY(textInput->positionToRectangle(0).top() > canvas.height() / 2); // explicitly center aligned textInput->setVAlign(QQuickTextInput::AlignVCenter); QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignVCenter); - QVERIFY(textInputPrivate->boundingRect.top() - textInputPrivate->vscroll < canvas.height() / 2); - QVERIFY(textInputPrivate->boundingRect.bottom() - textInputPrivate->vscroll > canvas.height() / 2); + QVERIFY(textInput->boundingRect().top() < canvas.height() / 2); + QVERIFY(textInput->boundingRect().bottom() > canvas.height() / 2); QVERIFY(textInput->cursorRectangle().top() < canvas.height() / 2); QVERIFY(textInput->cursorRectangle().bottom() > canvas.height() / 2); QVERIFY(textInput->positionToRectangle(0).top() < canvas.height() / 2); QVERIFY(textInput->positionToRectangle(0).bottom() > canvas.height() / 2); } -void tst_qquicktextinput::boundingRect() +void tst_qquicktextinput::clipRect() { QQmlComponent component(&engine); component.setData("import QtQuick 2.0\n TextInput {}", QUrl()); @@ -1476,21 +1472,29 @@ void tst_qquicktextinput::boundingRect() QQuickTextInput *input = qobject_cast(object.data()); QVERIFY(input); - QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width()); - QCOMPARE(input->height(), input->boundingRect().height()); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + input->cursorRectangle().width()); + QCOMPARE(input->clipRect().height(), input->height()); input->setText("Hello World"); - QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width()); - QCOMPARE(input->height(), input->boundingRect().height()); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + input->cursorRectangle().width()); + QCOMPARE(input->clipRect().height(), input->height()); - // bounding rect shouldn't exceed the size of the item, expect for the cursor width; + // clip rect shouldn't exceed the size of the item, expect for the cursor width; input->setWidth(input->width() / 2); - QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width()); - QCOMPARE(input->height(), input->boundingRect().height()); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + input->cursorRectangle().width()); + QCOMPARE(input->clipRect().height(), input->height()); input->setHeight(input->height() * 2); - QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width()); - QCOMPARE(input->height(), input->boundingRect().height()); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + input->cursorRectangle().width()); + QCOMPARE(input->clipRect().height(), input->height()); QQmlComponent cursorComponent(&engine); cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl()); @@ -1498,8 +1502,122 @@ void tst_qquicktextinput::boundingRect() input->setCursorDelegate(&cursorComponent); // If a cursor delegate is used it's size should determine the excess width. - QCOMPARE(input->width() + 8, input->boundingRect().width()); - QCOMPARE(input->height(), input->boundingRect().height()); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + 8); + QCOMPARE(input->clipRect().height(), input->height()); + + // Alignment, auto scroll, wrapping all don't affect the clip rect. + input->setAutoScroll(false); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + 8); + QCOMPARE(input->clipRect().height(), input->height()); + + input->setHAlign(QQuickTextInput::AlignRight); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + 8); + QCOMPARE(input->clipRect().height(), input->height()); + + input->setWrapMode(QQuickTextInput::Wrap); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + 8); + QCOMPARE(input->clipRect().height(), input->height()); + + input->setVAlign(QQuickTextInput::AlignBottom); + QCOMPARE(input->clipRect().x(), qreal(0)); + QCOMPARE(input->clipRect().y(), qreal(0)); + QCOMPARE(input->clipRect().width(), input->width() + 8); + QCOMPARE(input->clipRect().height(), input->height()); +} + +void tst_qquicktextinput::boundingRect() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n TextInput {}", QUrl()); + QScopedPointer object(component.create()); + QQuickTextInput *input = qobject_cast(object.data()); + QVERIFY(input); + + QTextLayout layout; + layout.setFont(input->font()); + + if (!qmlDisableDistanceField()) { + QTextOption option; + option.setUseDesignMetrics(true); + layout.setTextOption(option); + } + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + QCOMPARE(input->boundingRect().x(), qreal(0)); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), input->cursorRectangle().width()); + QCOMPARE(input->boundingRect().height(), line.height()); + + input->setText("Hello World"); + + layout.setText(input->text()); + layout.beginLayout(); + line = layout.createLine(); + layout.endLayout(); + + QCOMPARE(input->boundingRect().x(), qreal(0)); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width()); + QCOMPARE(input->boundingRect().height(), line.height()); + + // the size of the bounding rect shouldn't be bounded by the size of item. + input->setWidth(input->width() / 2); + QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth()); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width()); + QCOMPARE(input->boundingRect().height(), line.height()); + + input->setHeight(input->height() * 2); + QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth()); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width()); + QCOMPARE(input->boundingRect().height(), line.height()); + + QQmlComponent cursorComponent(&engine); + cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl()); + + input->setCursorDelegate(&cursorComponent); + + // Don't include the size of a cursor delegate as it has its own bounding rect. + QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth()); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth()); + QCOMPARE(input->boundingRect().height(), line.height()); + + // Bounding rect left aligned when auto scroll is disabled; + input->setAutoScroll(false); + QCOMPARE(input->boundingRect().x(), qreal(0)); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth()); + QCOMPARE(input->boundingRect().height(), line.height()); + + input->setHAlign(QQuickTextInput::AlignRight); + QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth()); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QCOMPARE(input->boundingRect().width(), line.naturalTextWidth()); + QCOMPARE(input->boundingRect().height(), line.height()); + + input->setWrapMode(QQuickTextInput::Wrap); + QCOMPARE(input->boundingRect().right(), input->width()); + QCOMPARE(input->boundingRect().y(), qreal(0)); + QVERIFY(input->boundingRect().width() < line.naturalTextWidth()); + QVERIFY(input->boundingRect().height() > line.height()); + + input->setVAlign(QQuickTextInput::AlignBottom); + QCOMPARE(input->boundingRect().right(), input->width()); + QCOMPARE(input->boundingRect().bottom(), input->height()); + QVERIFY(input->boundingRect().width() < line.naturalTextWidth()); + QVERIFY(input->boundingRect().height() > line.height()); } void tst_qquicktextinput::positionAt() -- cgit v1.2.3