tests/auto/qtextlayout/tst_qtextlayout.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 /*
       
    44     !!!!!! Warning !!!!!
       
    45     Please don't save this file in emacs. It contains utf8 text sequences emacs will
       
    46     silently convert to a series of question marks.
       
    47  */
       
    48 #include <QtTest/QtTest>
       
    49 
       
    50 
       
    51 
       
    52 #include <private/qtextengine_p.h>
       
    53 #include <qtextlayout.h>
       
    54 
       
    55 #include <qdebug.h>
       
    56 
       
    57 
       
    58 #define TESTFONT_SIZE 12
       
    59 
       
    60 //TESTED_CLASS=
       
    61 //TESTED_FILES=
       
    62 
       
    63 class tst_QTextLayout : public QObject
       
    64 {
       
    65     Q_OBJECT
       
    66 
       
    67 public:
       
    68     tst_QTextLayout();
       
    69     virtual ~tst_QTextLayout();
       
    70 
       
    71 
       
    72 public slots:
       
    73     void init();
       
    74     void cleanup();
       
    75 private slots:
       
    76     void getSetCheck();
       
    77     void lineBreaking();
       
    78     void simpleBoundingRect();
       
    79     void threeLineBoundingRect();
       
    80     void boundingRectWithLongLineAndNoWrap();
       
    81     void forcedBreaks();
       
    82     void breakAny();
       
    83     void noWrap();
       
    84     void cursorToXForInlineObjects();
       
    85     void cursorToXForSetColumns();
       
    86     void defaultWordSeparators_data();
       
    87     void defaultWordSeparators();
       
    88     void cursorMovementInsideSpaces();
       
    89     void charWordStopOnLineSeparator();
       
    90     void xToCursorAtEndOfLine();
       
    91     void boundingRectTopLeft();
       
    92     void charStopForSurrogatePairs();
       
    93     void tabStops();
       
    94     void integerOverflow();
       
    95     void testDefaultTabs();
       
    96     void testTabs();
       
    97     void testMultilineTab();
       
    98     void testRightTab();
       
    99     void testTabsInAlignedParag();
       
   100     void testCenteredTab();
       
   101     void testDelimiterTab();
       
   102     void testMultiTab();
       
   103     void testTabDPIScale();
       
   104     void tabsForRtl();
       
   105     void tabHeight();
       
   106     void capitalization_allUpperCase();
       
   107     void capitalization_allLowerCase();
       
   108     void capitalization_smallCaps();
       
   109     void capitalization_capitalize();
       
   110     void longText();
       
   111     void widthOfTabs();
       
   112     void columnWrapWithTabs();
       
   113 
       
   114     // QTextLine stuff
       
   115     void setNumColumnsWrapAtWordBoundaryOrAnywhere();
       
   116     void setNumColumnsWordWrap();
       
   117     void smallTextLengthNoWrap();
       
   118     void smallTextLengthWordWrap();
       
   119     void smallTextLengthWrapAtWordBoundaryOrAnywhere();
       
   120     void testLineBreakingAllSpaces();
       
   121 
       
   122 
       
   123 private:
       
   124     QFont testFont;
       
   125 };
       
   126 
       
   127 // Testing get/set functions
       
   128 void tst_QTextLayout::getSetCheck()
       
   129 {
       
   130     QString str("Bogus text");
       
   131     QTextLayout layout(str, testFont);
       
   132     layout.beginLayout();
       
   133     QTextEngine *engine = layout.engine();
       
   134     QTextInlineObject obj1(0, engine);
       
   135     // qreal QTextInlineObject::width()
       
   136     // void QTextInlineObject::setWidth(qreal)
       
   137     obj1.setWidth(0.0);
       
   138     QCOMPARE(0.0, obj1.width());
       
   139     obj1.setWidth(1.2);
       
   140     QVERIFY(1.0 < obj1.width());
       
   141 
       
   142     // qreal QTextInlineObject::ascent()
       
   143     // void QTextInlineObject::setAscent(qreal)
       
   144     obj1.setAscent(0.0);
       
   145     QCOMPARE(0.0, obj1.ascent());
       
   146     obj1.setAscent(1.2);
       
   147     QVERIFY(1.0 < obj1.ascent());
       
   148 
       
   149     // qreal QTextInlineObject::descent()
       
   150     // void QTextInlineObject::setDescent(qreal)
       
   151     obj1.setDescent(0.0);
       
   152     QCOMPARE(0.0, obj1.descent());
       
   153     obj1.setDescent(1.2);
       
   154     QVERIFY(1.0 < obj1.descent());
       
   155 
       
   156     QTextLayout obj2;
       
   157     // bool QTextLayout::cacheEnabled()
       
   158     // void QTextLayout::setCacheEnabled(bool)
       
   159     obj2.setCacheEnabled(false);
       
   160     QCOMPARE(false, obj2.cacheEnabled());
       
   161     obj2.setCacheEnabled(true);
       
   162     QCOMPARE(true, obj2.cacheEnabled());
       
   163 }
       
   164 
       
   165 QT_BEGIN_NAMESPACE
       
   166 extern void qt_setQtEnableTestFont(bool value);
       
   167 QT_END_NAMESPACE
       
   168 
       
   169 tst_QTextLayout::tst_QTextLayout()
       
   170 {
       
   171     qt_setQtEnableTestFont(true);
       
   172 }
       
   173 
       
   174 tst_QTextLayout::~tst_QTextLayout()
       
   175 {
       
   176 }
       
   177 
       
   178 void tst_QTextLayout::init()
       
   179 {
       
   180     testFont = QFont();
       
   181     testFont.setFamily("__Qt__Box__Engine__");
       
   182     testFont.setPixelSize(TESTFONT_SIZE);
       
   183     testFont.setWeight(QFont::Normal);
       
   184     QCOMPARE(QFontMetrics(testFont).width('a'), testFont.pixelSize());
       
   185 }
       
   186 
       
   187 void tst_QTextLayout::cleanup()
       
   188 {
       
   189     testFont = QFont();
       
   190 }
       
   191 
       
   192 
       
   193 void tst_QTextLayout::lineBreaking()
       
   194 {
       
   195 #if defined(Q_WS_X11)
       
   196     struct Breaks {
       
   197 	const char *utf8;
       
   198 	uchar breaks[32];
       
   199     };
       
   200     Breaks brks[] = {
       
   201 	{ "11", { false, 0xff } },
       
   202 	{ "aa", { false, 0xff } },
       
   203 	{ "++", { false, 0xff } },
       
   204 	{ "--", { false, 0xff } },
       
   205 	{ "((", { false, 0xff } },
       
   206 	{ "))", { false, 0xff } },
       
   207 	{ "..", { false, 0xff } },
       
   208 	{ "\"\"", { false, 0xff } },
       
   209 	{ "$$", { false, 0xff } },
       
   210 	{ "!!", { false, 0xff } },
       
   211 	{ "??", { false, 0xff } },
       
   212 	{ ",,", { false, 0xff } },
       
   213 
       
   214 	{ ")()", { true, false, 0xff } },
       
   215 	{ "?!?", { false, false, 0xff } },
       
   216 	{ ".,.", { false, false, 0xff } },
       
   217 	{ "+-+", { false, false, 0xff } },
       
   218 	{ "+=+", { false, false, 0xff } },
       
   219 	{ "+(+", { false, false, 0xff } },
       
   220 	{ "+)+", { false, false, 0xff } },
       
   221 
       
   222 	{ "a b", { false, true, 0xff } },
       
   223 	{ "a(b", { false, false, 0xff } },
       
   224 	{ "a)b", { false, false, 0xff } },
       
   225 	{ "a-b", { false, true, 0xff } },
       
   226 	{ "a.b", { false, false, 0xff } },
       
   227 	{ "a+b", { false, false, 0xff } },
       
   228 	{ "a?b", { false, false, 0xff } },
       
   229 	{ "a!b", { false, false, 0xff } },
       
   230 	{ "a$b", { false, false, 0xff } },
       
   231 	{ "a,b", { false, false, 0xff } },
       
   232 	{ "a/b", { false, false, 0xff } },
       
   233 	{ "1/2", { false, false, 0xff } },
       
   234 	{ "./.", { false, false, 0xff } },
       
   235 	{ ",/,", { false, false, 0xff } },
       
   236 	{ "!/!", { false, false, 0xff } },
       
   237 	{ "\\/\\", { false, false, 0xff } },
       
   238 	{ "1 2", { false, true, 0xff } },
       
   239 	{ "1(2", { false, false, 0xff } },
       
   240 	{ "1)2", { false, false, 0xff } },
       
   241 	{ "1-2", { false, false, 0xff } },
       
   242 	{ "1.2", { false, false, 0xff } },
       
   243 	{ "1+2", { false, false, 0xff } },
       
   244 	{ "1?2", { false, true, 0xff } },
       
   245 	{ "1!2", { false, true, 0xff } },
       
   246 	{ "1$2", { false, false, 0xff } },
       
   247 	{ "1,2", { false, false, 0xff } },
       
   248 	{ "1/2", { false, false, 0xff } },
       
   249 	{ "\330\260\331\216\331\204\331\220\331\203\331\216", { false, false, false, false, false, 0xff } },
       
   250 	{ "\330\247\331\204\331\205 \330\247\331\204\331\205", { false, false, false, true, false, false, 0xff } },
       
   251 	{ "1#2", { false, false, 0xff } },
       
   252 	{ "!#!", { false, false, 0xff } },
       
   253 	{ 0, {} }
       
   254     };
       
   255     Breaks *b = brks;
       
   256     while (b->utf8) {
       
   257         QString str = QString::fromUtf8(b->utf8);
       
   258         QTextEngine engine(str, QFont());
       
   259         const HB_CharAttributes *attrs = engine.attributes();
       
   260         int i;
       
   261         for (i = 0; i < (int)str.length() - 1; ++i) {
       
   262             QVERIFY(b->breaks[i] != 0xff);
       
   263             if ( (attrs[i].lineBreakType != HB_NoBreak) != (bool)b->breaks[i] ) {
       
   264                 qDebug("test case \"%s\" failed at char %d; break type: %d", b->utf8, i, attrs[i].lineBreakType);
       
   265                 QCOMPARE( (attrs[i].lineBreakType != HB_NoBreak), (bool)b->breaks[i] );
       
   266             }
       
   267         }
       
   268         QVERIFY(attrs[i].lineBreakType == HB_ForcedBreak);
       
   269         QCOMPARE(b->breaks[i], (uchar)0xff);
       
   270         ++b;
       
   271     }
       
   272 #else
       
   273     QSKIP("This test can not be run on non-X11 platforms", SkipAll);
       
   274 #endif
       
   275 }
       
   276 
       
   277 void tst_QTextLayout::simpleBoundingRect()
       
   278 {
       
   279     /* just check if boundingRect() gives sane values. The text is not broken. */
       
   280 
       
   281     QString hello("hello world");
       
   282 
       
   283     const int width = hello.length() * testFont.pixelSize();
       
   284 
       
   285     QTextLayout layout(hello, testFont);
       
   286     layout.beginLayout();
       
   287 
       
   288     QTextLine line = layout.createLine();
       
   289     line.setLineWidth(width);
       
   290     QCOMPARE(line.textLength(), hello.length());
       
   291     QCOMPARE(layout.boundingRect(), QRectF(0, 0, width, QFontMetrics(testFont).height()));
       
   292 }
       
   293 
       
   294 void tst_QTextLayout::threeLineBoundingRect()
       
   295 {
       
   296 #if defined(Q_WS_MAC)
       
   297     QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
       
   298 #endif
       
   299     /* stricter check. break text into three lines */
       
   300 
       
   301     QString firstWord("hello");
       
   302     QString secondWord("world");
       
   303     QString thirdWord("test");
       
   304     QString text(firstWord + ' ' + secondWord + ' ' + thirdWord);
       
   305 
       
   306     const int firstLineWidth = firstWord.length() * testFont.pixelSize();
       
   307     const int secondLineWidth = secondWord.length() * testFont.pixelSize();
       
   308     const int thirdLineWidth = thirdWord.length() * testFont.pixelSize();
       
   309 
       
   310     const int longestLine = qMax(firstLineWidth, qMax(secondLineWidth, thirdLineWidth));
       
   311 
       
   312     QTextLayout layout(text, testFont);
       
   313     layout.beginLayout();
       
   314 
       
   315     int pos = 0;
       
   316     int y = 0;
       
   317     QTextLine line = layout.createLine();
       
   318     line.setLineWidth(firstLineWidth);
       
   319     line.setPosition(QPoint(0, y));
       
   320     QCOMPARE(line.textStart(), pos);
       
   321     // + 1 for trailing space
       
   322     QCOMPARE(line.textLength(), firstWord.length() + 1);
       
   323     QCOMPARE(qRound(line.naturalTextWidth()), firstLineWidth);
       
   324 
       
   325     pos += line.textLength();
       
   326     y += qRound(line.ascent() + line.descent());
       
   327 
       
   328     line = layout.createLine();
       
   329     line.setLineWidth(secondLineWidth);
       
   330     line.setPosition(QPoint(0, y));
       
   331     // + 1 for trailing space
       
   332     QCOMPARE(line.textStart(), pos);
       
   333     QCOMPARE(line.textLength(), secondWord.length() + 1);
       
   334     QCOMPARE(qRound(line.naturalTextWidth()), secondLineWidth);
       
   335 
       
   336     pos += line.textLength();
       
   337     y += qRound(line.ascent() + line.descent());
       
   338 
       
   339     line = layout.createLine();
       
   340     line.setLineWidth(secondLineWidth);
       
   341     line.setPosition(QPoint(0, y));
       
   342     // no trailing space here!
       
   343     QCOMPARE(line.textStart(), pos);
       
   344     QCOMPARE(line.textLength(), thirdWord.length());
       
   345     QCOMPARE(qRound(line.naturalTextWidth()), thirdLineWidth);
       
   346     y += qRound(line.ascent() + line.descent());
       
   347 
       
   348     QCOMPARE(layout.boundingRect(), QRectF(0, 0, longestLine, y + 1));
       
   349 }
       
   350 
       
   351 void tst_QTextLayout::boundingRectWithLongLineAndNoWrap()
       
   352 {
       
   353     QString longString("thisisaverylongstringthatcannotbewrappedatallitjustgoesonandonlikeonebigword");
       
   354 
       
   355     const int width = longString.length() * testFont.pixelSize() / 20; // very small widthx
       
   356 
       
   357     QTextLayout layout(longString, testFont);
       
   358     layout.beginLayout();
       
   359     QTextLine line = layout.createLine();
       
   360     line.setLineWidth(width);
       
   361 
       
   362     QVERIFY(layout.boundingRect().width() >= line.width());
       
   363     QCOMPARE(layout.boundingRect().width(), line.naturalTextWidth());
       
   364 }
       
   365 
       
   366 void tst_QTextLayout::forcedBreaks()
       
   367 {
       
   368     QString text = "A\n\nB\nC";
       
   369     text.replace('\n', QChar::LineSeparator);
       
   370 
       
   371     QTextLayout layout(text, testFont);
       
   372 
       
   373     layout.beginLayout();
       
   374 
       
   375     int pos = 0;
       
   376 
       
   377     QTextLine line = layout.createLine();
       
   378     line.setLineWidth(0x10000);
       
   379     QCOMPARE(line.textStart(), pos);
       
   380     QCOMPARE(line.textLength(),2);
       
   381     QCOMPARE(qRound(line.naturalTextWidth()),testFont.pixelSize());
       
   382     QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
       
   383     QCOMPARE(line.xToCursor(0), line.textStart());
       
   384     pos += line.textLength();
       
   385 
       
   386     line = layout.createLine();
       
   387     line.setLineWidth(0x10000);
       
   388     QCOMPARE(line.textStart(),pos);
       
   389     QCOMPARE(line.textLength(),1);
       
   390     QCOMPARE(qRound(line.naturalTextWidth()), 0);
       
   391     QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
       
   392     QCOMPARE(line.xToCursor(0), line.textStart());
       
   393     pos += line.textLength();
       
   394 
       
   395     line = layout.createLine();
       
   396     line.setLineWidth(0x10000);
       
   397     QCOMPARE(line.textStart(),pos);
       
   398     QCOMPARE(line.textLength(),2);
       
   399     QCOMPARE(qRound(line.naturalTextWidth()),testFont.pixelSize());
       
   400     QCOMPARE(qRound(line.height()), testFont.pixelSize() + 1); // + 1 baseline
       
   401     QCOMPARE(line.xToCursor(0), line.textStart());
       
   402     pos += line.textLength();
       
   403 
       
   404     line = layout.createLine();
       
   405     line.setLineWidth(0x10000);
       
   406     QCOMPARE(line.textStart(),pos);
       
   407     QCOMPARE(line.textLength(),1);
       
   408     QCOMPARE(qRound(line.naturalTextWidth()), testFont.pixelSize());
       
   409     QCOMPARE((int) line.height(), testFont.pixelSize() + 1); // + 1 baseline
       
   410     QCOMPARE(line.xToCursor(0), line.textStart());
       
   411 }
       
   412 
       
   413 void tst_QTextLayout::breakAny()
       
   414 {
       
   415 #if defined(Q_WS_MAC)
       
   416     QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
       
   417 #endif
       
   418     QString text = "ABCD";
       
   419 
       
   420     QTextLayout layout(text, testFont);
       
   421     QTextLine line;
       
   422 
       
   423     QTextOption opt;
       
   424     opt.setWrapMode(QTextOption::WrapAnywhere);
       
   425     layout.setTextOption(opt);
       
   426     layout.beginLayout();
       
   427 
       
   428     line = layout.createLine();
       
   429     line.setLineWidth(testFont.pixelSize() * 2);
       
   430     QCOMPARE(line.textStart(), 0);
       
   431     QCOMPARE(line.textLength(), 2);
       
   432 
       
   433     line = layout.createLine();
       
   434     line.setLineWidth(testFont.pixelSize() * 2);
       
   435     QCOMPARE(line.textStart(), 2);
       
   436     QCOMPARE(line.textLength(), 2);
       
   437 
       
   438     line = layout.createLine();
       
   439     QVERIFY(!line.isValid());
       
   440 
       
   441     layout.endLayout();
       
   442 
       
   443     text = "ABCD EFGH";
       
   444     layout.setText(text);
       
   445     layout.beginLayout();
       
   446 
       
   447     line = layout.createLine();
       
   448     line.setLineWidth(testFont.pixelSize() * 7);
       
   449     QCOMPARE(line.textStart(), 0);
       
   450     QCOMPARE(line.textLength(), 7);
       
   451 
       
   452     layout.endLayout();
       
   453 }
       
   454 
       
   455 void tst_QTextLayout::noWrap()
       
   456 {
       
   457 #if defined(Q_WS_MAC)
       
   458     QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
       
   459 #endif
       
   460     QString text = "AB CD";
       
   461 
       
   462     QTextLayout layout(text, testFont);
       
   463     QTextLine line;
       
   464 
       
   465     QTextOption opt;
       
   466     opt.setWrapMode(QTextOption::NoWrap);
       
   467     layout.setTextOption(opt);
       
   468     layout.beginLayout();
       
   469 
       
   470     line = layout.createLine();
       
   471     line.setLineWidth(testFont.pixelSize() * 2);
       
   472     QCOMPARE(line.textStart(), 0);
       
   473     QCOMPARE(line.textLength(), 5);
       
   474 
       
   475     line = layout.createLine();
       
   476     QVERIFY(!line.isValid());
       
   477 
       
   478     layout.endLayout();
       
   479 }
       
   480 
       
   481 void tst_QTextLayout::cursorToXForInlineObjects()
       
   482 {
       
   483     QChar ch(QChar::ObjectReplacementCharacter);
       
   484     QString text(ch);
       
   485     QTextLayout layout(text, testFont);
       
   486     layout.beginLayout();
       
   487 
       
   488     QTextEngine *engine = layout.engine();
       
   489     const int item = engine->findItem(0);
       
   490     engine->layoutData->items[item].width = 32;
       
   491 
       
   492     QTextLine line = layout.createLine();
       
   493     line.setLineWidth(0x10000);
       
   494 
       
   495     QCOMPARE(line.cursorToX(0), qreal(0));
       
   496     QCOMPARE(line.cursorToX(1), qreal(32));
       
   497 }
       
   498 
       
   499 void tst_QTextLayout::cursorToXForSetColumns()
       
   500 {
       
   501     QTextLayout lay("abc", testFont);
       
   502     QTextOption o = lay.textOption();
       
   503     o.setWrapMode(QTextOption::WrapAnywhere);
       
   504 
       
   505     // enable/disable this line for full effect ;)
       
   506     o.setAlignment(Qt::AlignHCenter);
       
   507 
       
   508     lay.setTextOption(o);
       
   509     lay.beginLayout();
       
   510     QTextLine line = lay.createLine();
       
   511     line.setNumColumns(1);
       
   512     lay.endLayout();
       
   513     QCOMPARE(line.cursorToX(0), 0.);
       
   514     QCOMPARE(line.cursorToX(1), (qreal) TESTFONT_SIZE);
       
   515 }
       
   516 
       
   517 void tst_QTextLayout::defaultWordSeparators_data()
       
   518 {
       
   519     QTest::addColumn<QString>("text");
       
   520     QTest::addColumn<int>("startPos");
       
   521     QTest::addColumn<int>("endPos");
       
   522 
       
   523     QString separators(".,:;-<>[](){}=/+%&^*");
       
   524     separators += QLatin1String("!?");
       
   525     for (int i = 0; i < separators.count(); ++i) {
       
   526         QTest::newRow(QString::number(i).toAscii().data())
       
   527             << QString::fromLatin1("abcd") + separators.at(i) + QString::fromLatin1("efgh")
       
   528             <<  0 << 4;
       
   529     }
       
   530 
       
   531     QTest::newRow("nbsp")
       
   532             << QString::fromLatin1("abcd") + QString(QChar::Nbsp) + QString::fromLatin1("efgh")
       
   533             << 0 << 5;
       
   534 
       
   535     QTest::newRow("tab")
       
   536         << QString::fromLatin1("abcd") + QString::fromLatin1("\t") + QString::fromLatin1("efgh")
       
   537             << 0 << 5;
       
   538 
       
   539     QTest::newRow("lineseparator")
       
   540             << QString::fromLatin1("abcd") + QString(QChar::LineSeparator) + QString::fromLatin1("efgh")
       
   541             << 0 << 5;
       
   542 }
       
   543 
       
   544 void tst_QTextLayout::defaultWordSeparators()
       
   545 {
       
   546     QFETCH(QString, text);
       
   547     QFETCH(int, startPos);
       
   548     QFETCH(int, endPos);
       
   549     QTextLayout layout(text, testFont);
       
   550 
       
   551     QCOMPARE(layout.nextCursorPosition(startPos, QTextLayout::SkipWords), endPos);
       
   552     QCOMPARE(layout.previousCursorPosition(endPos, QTextLayout::SkipWords), startPos);
       
   553 }
       
   554 
       
   555 void tst_QTextLayout::cursorMovementInsideSpaces()
       
   556 {
       
   557     QTextLayout layout("ABC            DEF", testFont);
       
   558 
       
   559     QCOMPARE(layout.previousCursorPosition(6, QTextLayout::SkipWords), 0);
       
   560     QCOMPARE(layout.nextCursorPosition(6, QTextLayout::SkipWords), 15);
       
   561 }
       
   562 
       
   563 void tst_QTextLayout::charWordStopOnLineSeparator()
       
   564 {
       
   565     const QChar lineSeparator(QChar::LineSeparator);
       
   566     QString txt;
       
   567     txt.append(lineSeparator);
       
   568     txt.append(lineSeparator);
       
   569     QTextLayout layout(txt, testFont);
       
   570     QTextEngine *engine = layout.engine();
       
   571     const HB_CharAttributes *attrs = engine->attributes();
       
   572     QVERIFY(attrs);
       
   573     QVERIFY(attrs[1].charStop);
       
   574 }
       
   575 
       
   576 void tst_QTextLayout::xToCursorAtEndOfLine()
       
   577 {
       
   578 #if defined(Q_WS_MAC)
       
   579     QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
       
   580 #endif
       
   581     QString text = "FirstLine SecondLine";
       
   582     text.replace('\n', QChar::LineSeparator);
       
   583 
       
   584     const qreal firstLineWidth = QString("FirstLine").length() * testFont.pixelSize();
       
   585 
       
   586     QTextLayout layout(text, testFont);
       
   587 
       
   588     layout.beginLayout();
       
   589     QTextLine line = layout.createLine();
       
   590     QVERIFY(line.isValid());
       
   591     line.setLineWidth(firstLineWidth);
       
   592     QVERIFY(layout.createLine().isValid());
       
   593     QVERIFY(!layout.createLine().isValid());
       
   594     layout.endLayout();
       
   595 
       
   596     line = layout.lineAt(0);
       
   597     QCOMPARE(line.xToCursor(100000), 9);
       
   598     line = layout.lineAt(1);
       
   599     QCOMPARE(line.xToCursor(100000), 20);
       
   600 }
       
   601 
       
   602 void tst_QTextLayout::boundingRectTopLeft()
       
   603 {
       
   604     QString text = "FirstLine\nSecondLine";
       
   605     text.replace('\n', QChar::LineSeparator);
       
   606 
       
   607     QTextLayout layout(text, testFont);
       
   608 
       
   609     layout.beginLayout();
       
   610     QTextLine firstLine = layout.createLine();
       
   611     QVERIFY(firstLine.isValid());
       
   612     firstLine.setPosition(QPointF(10, 10));
       
   613     QTextLine secondLine = layout.createLine();
       
   614     QVERIFY(secondLine.isValid());
       
   615     secondLine.setPosition(QPointF(20, 20));
       
   616     layout.endLayout();
       
   617 
       
   618     QCOMPARE(layout.boundingRect().topLeft(), firstLine.position());
       
   619 }
       
   620 
       
   621 void tst_QTextLayout::charStopForSurrogatePairs()
       
   622 {
       
   623     QString txt;
       
   624     txt.append("a");
       
   625     txt.append(0xd87e);
       
   626     txt.append(0xdc25);
       
   627     txt.append("b");
       
   628     QTextLayout layout(txt, testFont);
       
   629     QTextEngine *engine = layout.engine();
       
   630     const HB_CharAttributes *attrs = engine->attributes();
       
   631     QVERIFY(attrs);
       
   632     QVERIFY(attrs[0].charStop);
       
   633     QVERIFY(attrs[1].charStop);
       
   634     QVERIFY(!attrs[2].charStop);
       
   635     QVERIFY(attrs[3].charStop);
       
   636 }
       
   637 
       
   638 void tst_QTextLayout::tabStops()
       
   639 {
       
   640 #if defined(Q_WS_MAC)
       
   641     QSKIP("QTestFontEngine on the mac does not support logclusters at the moment", SkipAll);
       
   642 #endif
       
   643     QString txt("Hello there\tworld");
       
   644     QTextLayout layout(txt, testFont);
       
   645     layout.beginLayout();
       
   646     QTextLine line = layout.createLine();
       
   647 
       
   648     QVERIFY(line.isValid());
       
   649     line.setNumColumns(11);
       
   650     QCOMPARE(line.textLength(), TESTFONT_SIZE);
       
   651 
       
   652     line = layout.createLine();
       
   653     QVERIFY(line.isValid());
       
   654     line.setNumColumns(5);
       
   655     QCOMPARE(line.textLength(), 5);
       
   656 
       
   657     layout.endLayout();
       
   658 }
       
   659 
       
   660 void tst_QTextLayout::integerOverflow()
       
   661 {
       
   662     QString txt("Hello world... ");
       
   663 
       
   664     for (int i = 0; i < 8; ++i)
       
   665         txt += txt;
       
   666 
       
   667     QTextLayout layout(txt, testFont);
       
   668     layout.beginLayout();
       
   669     QTextLine line = layout.createLine();
       
   670 
       
   671     QVERIFY(line.isValid());
       
   672     line.setLineWidth(INT_MAX);
       
   673     QCOMPARE(line.textLength(), txt.length());
       
   674 
       
   675     QVERIFY(!layout.createLine().isValid());
       
   676 
       
   677     layout.endLayout();
       
   678 }
       
   679 
       
   680 void tst_QTextLayout::setNumColumnsWrapAtWordBoundaryOrAnywhere()
       
   681 {
       
   682     QString txt("This is a small test text");
       
   683     QTextLayout layout(txt, testFont);
       
   684     QTextOption option = layout.textOption();
       
   685     option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
       
   686     layout.setTextOption(option);
       
   687 
       
   688     layout.beginLayout();
       
   689     QTextLine line1 = layout.createLine();
       
   690     QVERIFY(line1.isValid());
       
   691     line1.setNumColumns(1);
       
   692 
       
   693     // qDebug() << line1.naturalTextWidth();
       
   694     QCOMPARE(line1.textLength(), 1);
       
   695     QVERIFY(line1.naturalTextWidth() == testFont.pixelSize()); // contains only one character
       
   696 
       
   697     QTextLine line2 = layout.createLine();
       
   698     QVERIFY(line2.isValid());
       
   699 
       
   700     layout.endLayout();
       
   701 }
       
   702 
       
   703 void tst_QTextLayout::setNumColumnsWordWrap()
       
   704 {
       
   705     QString txt("This is a small test text");
       
   706     QTextLayout layout(txt, testFont);
       
   707     QTextOption option = layout.textOption();
       
   708     option.setWrapMode(QTextOption::WordWrap);
       
   709     layout.setTextOption(option);
       
   710 
       
   711     layout.beginLayout();
       
   712     QTextLine line1 = layout.createLine();
       
   713     QVERIFY(line1.isValid());
       
   714     line1.setNumColumns(1);
       
   715 
       
   716     // qDebug() << line1.naturalTextWidth();
       
   717     QCOMPARE(line1.textLength(), 5);
       
   718     QVERIFY(line1.naturalTextWidth() > 20.0); // contains the whole first word.
       
   719 
       
   720     QTextLine line2 = layout.createLine();
       
   721     QVERIFY(line2.isValid());
       
   722 
       
   723     layout.endLayout();
       
   724 }
       
   725 
       
   726 void tst_QTextLayout::smallTextLengthNoWrap()
       
   727 {
       
   728     QString txt("This is a small test text");
       
   729     QTextLayout layout(txt, testFont);
       
   730     QTextOption option = layout.textOption();
       
   731     option.setWrapMode(QTextOption::NoWrap);
       
   732     layout.setTextOption(option);
       
   733 
       
   734     /// NoWrap
       
   735     layout.beginLayout();
       
   736     QTextLine line1 = layout.createLine();
       
   737     QVERIFY(line1.isValid());
       
   738     line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
       
   739 
       
   740     QCOMPARE(line1.width(), 5.0);
       
   741     QVERIFY(line1.naturalTextWidth() > 70); // contains all the text.
       
   742 
       
   743     QTextLine line2 = layout.createLine();
       
   744     QVERIFY(! line2.isValid());
       
   745 
       
   746     layout.endLayout();
       
   747 }
       
   748 
       
   749 void tst_QTextLayout::smallTextLengthWordWrap()
       
   750 {
       
   751     QString txt("This is a small test text");
       
   752     QTextLayout layout(txt, testFont);
       
   753     QTextOption option = layout.textOption();
       
   754     option.setWrapMode(QTextOption::WordWrap);
       
   755     layout.setTextOption(option);
       
   756 
       
   757     /// WordWrap
       
   758     layout.beginLayout();
       
   759     QTextLine line1 = layout.createLine();
       
   760     QVERIFY(line1.isValid());
       
   761     line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
       
   762 
       
   763     QCOMPARE(line1.width(), 5.0);
       
   764     QVERIFY(line1.naturalTextWidth() > 20.0); // contains the whole first word.
       
   765     QCOMPARE(line1.textLength(), 5);
       
   766 
       
   767     QTextLine line2 = layout.createLine();
       
   768     QVERIFY(line2.isValid());
       
   769 
       
   770     layout.endLayout();
       
   771 }
       
   772 
       
   773 void tst_QTextLayout::smallTextLengthWrapAtWordBoundaryOrAnywhere()
       
   774 {
       
   775     QString txt("This is a small test text");
       
   776     QTextLayout layout(txt, testFont);
       
   777     QTextOption option = layout.textOption();
       
   778     option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
       
   779     layout.setTextOption(option);
       
   780 
       
   781     layout.beginLayout();
       
   782     QTextLine line1 = layout.createLine();
       
   783     QVERIFY(line1.isValid());
       
   784     line1.setLineWidth(5); // most certainly too short for the word 'This' to fit.
       
   785 
       
   786     QCOMPARE(line1.width(), 5.0);
       
   787     // qDebug() << line1.naturalTextWidth();
       
   788     QCOMPARE(line1.textLength(), 1);
       
   789     QVERIFY(line1.naturalTextWidth() == testFont.pixelSize()); // contains just the characters that fit.
       
   790 
       
   791     QTextLine line2 = layout.createLine();
       
   792     QVERIFY(line2.isValid());
       
   793 
       
   794     layout.endLayout();
       
   795 }
       
   796 
       
   797 void tst_QTextLayout::testDefaultTabs()
       
   798 {
       
   799     QTextLayout layout("Foo\tBar\ta slightly longer text\tend.", testFont);
       
   800     layout.beginLayout();
       
   801     QTextLine line = layout.createLine();
       
   802     line.setLineWidth(1000);
       
   803     layout.endLayout();
       
   804 
       
   805     //qDebug() << "After the tab: " << line.cursorToX(4);
       
   806     QCOMPARE(line.cursorToX(4), 80.); // default tab is 80
       
   807     QCOMPARE(line.cursorToX(8), 160.);
       
   808     QCOMPARE(line.cursorToX(31), 480.);
       
   809 
       
   810     QTextOption option = layout.textOption();
       
   811     option.setTabStop(90);
       
   812     layout.setTextOption(option);
       
   813     layout.beginLayout();
       
   814     line = layout.createLine();
       
   815     line.setLineWidth(1000);
       
   816     layout.endLayout();
       
   817 
       
   818     QCOMPARE(line.cursorToX(4), 90.);
       
   819     QCOMPARE(line.cursorToX(8), 180.);
       
   820     QCOMPARE(line.cursorToX(31), 450.);
       
   821 
       
   822     QList<QTextOption::Tab> tabs;
       
   823     QTextOption::Tab tab;
       
   824     tab.position = 110; // set one tab to 110, but since the rest is unset they will be at the normal interval again.
       
   825     tabs.append(tab);
       
   826     option.setTabs(tabs);
       
   827     layout.setTextOption(option);
       
   828     layout.beginLayout();
       
   829     line = layout.createLine();
       
   830     line.setLineWidth(1000);
       
   831     layout.endLayout();
       
   832 
       
   833     QCOMPARE(line.cursorToX(4), 110.);
       
   834     QCOMPARE(line.cursorToX(8), 180.);
       
   835     QCOMPARE(line.cursorToX(31), 450.);
       
   836 }
       
   837 
       
   838 void tst_QTextLayout::testTabs()
       
   839 {
       
   840     QTextLayout layout("Foo\tBar.", testFont);
       
   841     QTextOption option = layout.textOption();
       
   842     option.setTabStop(150);
       
   843     layout.setTextOption(option);
       
   844 
       
   845     layout.beginLayout();
       
   846     QTextLine line = layout.createLine();
       
   847     line.setLineWidth(200.);
       
   848     layout.endLayout();
       
   849 
       
   850     QVERIFY(line.naturalTextWidth() > 150);
       
   851     QCOMPARE(line.cursorToX(4), 150.);
       
   852 }
       
   853 
       
   854 void tst_QTextLayout::testMultilineTab()
       
   855 {
       
   856     QTextLayout layout("Lorem ipsum dolor sit\tBar.", testFont);
       
   857     // test if this works on the second line.
       
   858     layout.beginLayout();
       
   859     QTextLine line = layout.createLine();
       
   860     line.setLineWidth(220.); // moves 'sit' to next line.
       
   861     line = layout.createLine();
       
   862     line.setLineWidth(220.);
       
   863     layout.endLayout();
       
   864 
       
   865     QCOMPARE(line.cursorToX(22), 80.);
       
   866 }
       
   867 
       
   868 void tst_QTextLayout::testMultiTab()
       
   869 {
       
   870     QTextLayout layout("Foo\t\t\tBar.", testFont);
       
   871     layout.beginLayout();
       
   872     QTextLine line = layout.createLine();
       
   873     line.setLineWidth(1000.);
       
   874     layout.endLayout();
       
   875 
       
   876     QCOMPARE(line.cursorToX(6), 80. * 3);
       
   877 }
       
   878 
       
   879 void tst_QTextLayout::testTabsInAlignedParag()
       
   880 {
       
   881     QTextLayout layout("Foo\tsome more words", testFont);
       
   882     QTextOption option = layout.textOption();
       
   883     // right
       
   884     option.setAlignment(Qt::AlignRight);
       
   885     layout.setTextOption(option);
       
   886 
       
   887     layout.beginLayout();
       
   888     QTextLine line = layout.createLine();
       
   889     line.setLineWidth(300.);
       
   890     layout.endLayout();
       
   891 
       
   892     const qreal textWidth = 80 + 15 * TESTFONT_SIZE; // 15 chars right of the tab
       
   893     QCOMPARE(line.naturalTextWidth(), textWidth);
       
   894     QCOMPARE(line.cursorToX(0), 300. - textWidth);
       
   895 
       
   896     // centered
       
   897     option.setAlignment(Qt::AlignCenter);
       
   898     layout.setTextOption(option);
       
   899 
       
   900     layout.beginLayout();
       
   901     line = layout.createLine();
       
   902     line.setLineWidth(300.);
       
   903     layout.endLayout();
       
   904 
       
   905     QCOMPARE(line.naturalTextWidth(), textWidth);
       
   906     QCOMPARE(line.cursorToX(0), (300. - textWidth) / 2.);
       
   907 
       
   908     // justified
       
   909     option.setAlignment(Qt::AlignJustify);
       
   910     layout.setTextOption(option);
       
   911 
       
   912     layout.beginLayout();
       
   913     line = layout.createLine();
       
   914     line.setLineWidth(textWidth - 10); // make the last word slip to the next line so justification actually happens.
       
   915     layout.endLayout();
       
   916 
       
   917     QCOMPARE(line.cursorToX(0), 0.);
       
   918     QCOMPARE(line.cursorToX(4), 80.);
       
   919 
       
   920     //QTextLayout layout2("Foo\tUt wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis", testFont); // means it will be more then one line long.
       
   921 }
       
   922 
       
   923 void tst_QTextLayout::testRightTab()
       
   924 {
       
   925     QTextLayout layout("Foo\tLorem ipsum te sit\tBar baz\tText\tEnd", testFont);
       
   926     /*                     ^ a                 ^ b      ^ c   ^ d
       
   927      a = 4, b = 22, c = 30, d = 35 (position)
       
   928 
       
   929      I expect the output to be:
       
   930         Foo Lorem ipsum te
       
   931         sit      Bar Baz
       
   932         Text         End
       
   933 
       
   934      a) tab replaced with a single space due to the text not fitting before the tab.
       
   935      b) tab takes space so the text until the 3th tab fits to the tab pos.
       
   936      c) tab is after last tab (both auto and defined) and thus moves text to start of next line.
       
   937      d) tab takes space so text until enter fits to tab pos.
       
   938     */
       
   939 
       
   940     QTextOption option = layout.textOption();
       
   941     QList<QTextOption::Tab> tabs;
       
   942     QTextOption::Tab tab;
       
   943     tab.type = QTextOption::RightTab;
       
   944     tab.position = 190; // which means only 15(.8) chars of our test font fit left of it.
       
   945     tabs.append(tab);
       
   946     option.setTabs(tabs);
       
   947     layout.setTextOption(option);
       
   948 
       
   949     layout.beginLayout();
       
   950     QTextLine line1 = layout.createLine();
       
   951     line1.setLineWidth(220.);
       
   952     // qDebug() << "=====line 2";
       
   953     QTextLine line2 = layout.createLine();
       
   954     QVERIFY(line2.isValid());
       
   955     line2.setLineWidth(220.);
       
   956     // qDebug() << "=====line 3";
       
   957     QTextLine line3 = layout.createLine();
       
   958     QVERIFY(line3.isValid());
       
   959     line3.setLineWidth(220.);
       
   960     // qDebug() << "=====line 4";
       
   961     QTextLine line4 = layout.createLine();
       
   962     QVERIFY(! line4.isValid());
       
   963     layout.endLayout();
       
   964     // qDebug() << "--------";
       
   965 
       
   966     QCOMPARE(line1.cursorToX(4), 3. * TESTFONT_SIZE ); // a
       
   967     QCOMPARE(line1.textLength(), 19);
       
   968     QCOMPARE(line2.cursorToX(23), 190. - 7. * TESTFONT_SIZE); // b
       
   969     QCOMPARE(line2.textLength(), 12);
       
   970     QCOMPARE(line3.cursorToX(31), 0.); // c
       
   971     QCOMPARE(line3.cursorToX(36), 190 - 3. * TESTFONT_SIZE); // d
       
   972 }
       
   973 
       
   974 void tst_QTextLayout::testCenteredTab()
       
   975 {
       
   976     QTextLayout layout("Foo\tBar", testFont);
       
   977     // test if centering the tab works.  We expect the center of 'Bar.' to be at the tab point.
       
   978     QTextOption option = layout.textOption();
       
   979     QList<QTextOption::Tab> tabs;
       
   980     QTextOption::Tab tab;
       
   981     tab.type = QTextOption::CenterTab;
       
   982     tab.position = 150;
       
   983     tabs.append(tab);
       
   984     option.setTabs(tabs);
       
   985     layout.setTextOption(option);
       
   986 
       
   987     layout.beginLayout();
       
   988     QTextLine line = layout.createLine();
       
   989     line.setLineWidth(200.);
       
   990     layout.endLayout();
       
   991 
       
   992     const qreal wordLength = 3 * TESTFONT_SIZE; // the length of 'Bar'
       
   993     QCOMPARE(line.cursorToX(4), 150 - wordLength / 2.);
       
   994 }
       
   995 
       
   996 void tst_QTextLayout::testDelimiterTab()
       
   997 {
       
   998     QTextLayout layout("Foo\tBar. Barrabas", testFont);
       
   999     // try the different delimiter characters to see if the alignment works there.
       
  1000     QTextOption option = layout.textOption();
       
  1001     QList<QTextOption::Tab> tabs;
       
  1002     QTextOption::Tab tab;
       
  1003     tab.type = QTextOption::DelimiterTab;
       
  1004     tab.delimiter = QChar('.');
       
  1005     tab.position = 100;
       
  1006     tabs.append(tab);
       
  1007     option.setTabs(tabs);
       
  1008     layout.setTextOption(option);
       
  1009 
       
  1010     layout.beginLayout();
       
  1011     QTextLine line = layout.createLine();
       
  1012     line.setLineWidth(200.);
       
  1013     layout.endLayout();
       
  1014 
       
  1015     const qreal distanceBeforeTab = 3.5 * TESTFONT_SIZE; // the length of 'bar' and half the width of the dot.
       
  1016     QCOMPARE(line.cursorToX(4), 100 - distanceBeforeTab);
       
  1017 }
       
  1018 
       
  1019 void tst_QTextLayout::testLineBreakingAllSpaces()
       
  1020 {
       
  1021     QTextLayout layout("                    123", testFont); // thats 20 spaces
       
  1022     const qreal firstLineWidth = 17 * TESTFONT_SIZE;
       
  1023     layout.beginLayout();
       
  1024     QTextLine line1 = layout.createLine();
       
  1025     line1.setLineWidth(firstLineWidth);
       
  1026     QTextLine line2 = layout.createLine();
       
  1027     line2.setLineWidth(1000); // the rest
       
  1028     layout.endLayout();
       
  1029     QCOMPARE(line1.width(), firstLineWidth);
       
  1030     QCOMPARE(line1.naturalTextWidth(), 0.); // spaces don't take space
       
  1031     QCOMPARE(line1.textLength(), 20);
       
  1032     QCOMPARE(line2.textLength(), 3);
       
  1033     QCOMPARE(line2.naturalTextWidth(), 3. * TESTFONT_SIZE);
       
  1034 }
       
  1035 
       
  1036 void tst_QTextLayout::tabsForRtl()
       
  1037 {
       
  1038     QString word(QChar(0x5e9)); // a hebrew character
       
  1039     word = word + word + word;  // 3 hebrew characters ;)
       
  1040 
       
  1041     QTextLayout layout(word +'\t'+ word +'\t'+ word +'\t'+ word, testFont);
       
  1042 //QTextLayout layout(word +' '+ word +' '+ word +' '+ word, testFont);// tester ;)
       
  1043     /*                             ^ a         ^ b         ^ c
       
  1044      a = 4, b = 8, c = 12, d = 16 (position)
       
  1045 
       
  1046      a) Left tab in RTL is a righ tab; so a is at width - 80
       
  1047      b) Like a
       
  1048      c) right tab on RTL is a left tab; so its at width - 240
       
  1049      d) center tab is still a centered tab.
       
  1050     */
       
  1051 
       
  1052     QTextOption option = layout.textOption();
       
  1053     QList<QTextOption::Tab> tabs;
       
  1054     QTextOption::Tab tab;
       
  1055     tab.position = 80;
       
  1056     tabs.append(tab);
       
  1057     tab.position = 160;
       
  1058     tabs.append(tab);
       
  1059     tab.position = 240;
       
  1060     tab.type = QTextOption::RightTab;
       
  1061     tabs.append(tab);
       
  1062     option.setTabs(tabs);
       
  1063     option.setTextDirection(Qt::RightToLeft);
       
  1064     option.setAlignment(Qt::AlignRight);
       
  1065     layout.setTextOption(option);
       
  1066 
       
  1067     layout.beginLayout();
       
  1068     QTextLine line = layout.createLine();
       
  1069     const qreal WIDTH = 400.;
       
  1070     line.setLineWidth(WIDTH);
       
  1071     layout.endLayout();
       
  1072 
       
  1073 //qDebug() << "layout ended --------------";
       
  1074 
       
  1075     QCOMPARE(line.cursorToX(0), WIDTH);
       
  1076     QCOMPARE(line.cursorToX(1), WIDTH - TESTFONT_SIZE); // check its right-aligned
       
  1077     QCOMPARE(line.cursorToX(4), WIDTH - 80 + 3 * TESTFONT_SIZE);
       
  1078     QCOMPARE(line.cursorToX(8), WIDTH - 160 + 3 * TESTFONT_SIZE);
       
  1079     QCOMPARE(line.cursorToX(12), WIDTH - 240);
       
  1080 }
       
  1081 
       
  1082 QT_BEGIN_NAMESPACE
       
  1083 extern int qt_defaultDpiY();
       
  1084 QT_END_NAMESPACE
       
  1085 
       
  1086 void tst_QTextLayout::testTabDPIScale()
       
  1087 {
       
  1088     class MyPaintDevice : public QPaintDevice {
       
  1089         QPaintEngine *paintEngine () const { return 0; }
       
  1090         int metric (QPaintDevice::PaintDeviceMetric metric) const {
       
  1091             switch(metric) {
       
  1092             case QPaintDevice::PdmWidth:
       
  1093             case QPaintDevice::PdmHeight:
       
  1094             case QPaintDevice::PdmWidthMM:
       
  1095             case QPaintDevice::PdmHeightMM:
       
  1096             case QPaintDevice::PdmNumColors:
       
  1097                 return INT_MAX;
       
  1098             case QPaintDevice::PdmDepth:
       
  1099                 return 32;
       
  1100             case QPaintDevice::PdmDpiX:
       
  1101             case QPaintDevice::PdmDpiY:
       
  1102             case QPaintDevice::PdmPhysicalDpiX:
       
  1103             case QPaintDevice::PdmPhysicalDpiY:
       
  1104                 return 72;
       
  1105             }
       
  1106             return 0;
       
  1107         }
       
  1108     };
       
  1109 
       
  1110     MyPaintDevice pd;
       
  1111 
       
  1112     QTextLayout layout("text1\ttext2\ttext3\tend", testFont, &pd);
       
  1113 
       
  1114     QTextOption option = layout.textOption();
       
  1115     QList<QTextOption::Tab> tabs;
       
  1116     QTextOption::Tab tab;
       
  1117     tab.position = 200;
       
  1118     tabs.append(tab);
       
  1119 
       
  1120     tab.position = 400;
       
  1121     tab.type = QTextOption::RightTab;
       
  1122     tabs.append(tab);
       
  1123 
       
  1124     tab.position = 600;
       
  1125     tab.type = QTextOption::CenterTab;
       
  1126     tabs.append(tab);
       
  1127     option.setTabs(tabs);
       
  1128     layout.setTextOption(option);
       
  1129 
       
  1130     layout.beginLayout();
       
  1131     QTextLine line = layout.createLine();
       
  1132     line.setLineWidth(1500.);
       
  1133     layout.endLayout();
       
  1134     QCOMPARE(line.cursorToX(0), 0.);
       
  1135     QCOMPARE(line.cursorToX(1), (double) TESTFONT_SIZE); // check that the font does not resize
       
  1136     qreal scale = 72 / (qreal) qt_defaultDpiY();
       
  1137     // lets do the transformation of deminishing resolution that QFixed has as effect.
       
  1138     int fixedScale = (int)( scale * qreal(64)); // into a QFixed
       
  1139     scale = ((qreal)fixedScale)/(qreal)64;      // and out of a QFixed
       
  1140 
       
  1141     QCOMPARE(line.cursorToX(6),  tabs.at(0).position * scale);
       
  1142     QCOMPARE(line.cursorToX(12), tabs.at(1).position * scale - TESTFONT_SIZE * 5);
       
  1143     QCOMPARE(line.cursorToX(18), tabs.at(2).position * scale - TESTFONT_SIZE * 3 / 2.0);
       
  1144 }
       
  1145 
       
  1146 void tst_QTextLayout::tabHeight()
       
  1147 {
       
  1148     QTextLayout layout("\t", testFont);
       
  1149     layout.beginLayout();
       
  1150     QTextLine line = layout.createLine();
       
  1151     layout.endLayout();
       
  1152 
       
  1153     QCOMPARE(qRound(line.ascent()), QFontMetrics(testFont).ascent());
       
  1154     QCOMPARE(qRound(line.descent()), QFontMetrics(testFont).descent());
       
  1155 }
       
  1156 
       
  1157 void tst_QTextLayout::capitalization_allUpperCase()
       
  1158 {
       
  1159     QFont font(testFont);
       
  1160     font.setCapitalization(QFont::AllUppercase);
       
  1161     QTextLayout layout("Test", font);
       
  1162     layout.beginLayout();
       
  1163     QTextLine line = layout.createLine();
       
  1164     layout.endLayout();
       
  1165 
       
  1166     QTextEngine *engine = layout.engine();
       
  1167     engine->itemize();
       
  1168     QCOMPARE(engine->layoutData->items.count(), 1);
       
  1169     QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Uppercase);
       
  1170 }
       
  1171 
       
  1172 void tst_QTextLayout::capitalization_allLowerCase()
       
  1173 {
       
  1174     QFont font(testFont);
       
  1175     font.setCapitalization(QFont::AllLowercase);
       
  1176     QTextLayout layout("Test", font);
       
  1177     layout.beginLayout();
       
  1178     QTextLine line = layout.createLine();
       
  1179     layout.endLayout();
       
  1180 
       
  1181     QTextEngine *engine = layout.engine();
       
  1182     engine->itemize();
       
  1183     QCOMPARE(engine->layoutData->items.count(), 1);
       
  1184     QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Lowercase);
       
  1185 }
       
  1186 
       
  1187 void tst_QTextLayout::capitalization_smallCaps()
       
  1188 {
       
  1189     QFont font(testFont);
       
  1190     font.setCapitalization(QFont::SmallCaps);
       
  1191     QTextLayout layout("Test", font);
       
  1192     layout.beginLayout();
       
  1193     QTextLine line = layout.createLine();
       
  1194     layout.endLayout();
       
  1195 
       
  1196     QTextEngine *engine = layout.engine();
       
  1197     engine->itemize();
       
  1198     QCOMPARE(engine->layoutData->items.count(), 2);
       
  1199     QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::None);
       
  1200     QVERIFY(engine->layoutData->items.at(1).analysis.flags == QScriptAnalysis::SmallCaps);
       
  1201 }
       
  1202 
       
  1203 void tst_QTextLayout::capitalization_capitalize()
       
  1204 {
       
  1205     QFont font(testFont);
       
  1206     font.setCapitalization(QFont::Capitalize);
       
  1207     QTextLayout layout("hello\tworld", font);
       
  1208     layout.beginLayout();
       
  1209     QTextLine line = layout.createLine();
       
  1210     layout.endLayout();
       
  1211 
       
  1212     QTextEngine *engine = layout.engine();
       
  1213     engine->itemize();
       
  1214     QCOMPARE(engine->layoutData->items.count(), 5);
       
  1215     QVERIFY(engine->layoutData->items.at(0).analysis.flags == QScriptAnalysis::Uppercase);
       
  1216     QVERIFY(engine->layoutData->items.at(1).analysis.flags == QScriptAnalysis::None);
       
  1217     QVERIFY(engine->layoutData->items.at(2).analysis.flags == QScriptAnalysis::Tab);
       
  1218     QVERIFY(engine->layoutData->items.at(3).analysis.flags == QScriptAnalysis::Uppercase);
       
  1219     QVERIFY(engine->layoutData->items.at(4).analysis.flags == QScriptAnalysis::None);
       
  1220 }
       
  1221 
       
  1222 void tst_QTextLayout::longText()
       
  1223 {
       
  1224     QString longText(128000, 'a');
       
  1225 
       
  1226     {
       
  1227         QTextLayout layout(longText, testFont);
       
  1228         layout.beginLayout();
       
  1229         QTextLine line = layout.createLine();
       
  1230         layout.endLayout();
       
  1231         QVERIFY(line.isValid());
       
  1232         QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
       
  1233     }
       
  1234 
       
  1235     for (int cap = QFont::MixedCase; cap < QFont::Capitalize + 1; ++cap) {
       
  1236         QFont f(testFont);
       
  1237         f.setCapitalization(QFont::Capitalization(cap));
       
  1238         QTextLayout layout(longText, f);
       
  1239         layout.beginLayout();
       
  1240         QTextLine line = layout.createLine();
       
  1241         layout.endLayout();
       
  1242         QVERIFY(line.isValid());
       
  1243         QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
       
  1244     }
       
  1245 
       
  1246     {
       
  1247         QTextLayout layout(longText, testFont);
       
  1248         layout.setFlags(Qt::TextForceLeftToRight);
       
  1249         layout.beginLayout();
       
  1250         QTextLine line = layout.createLine();
       
  1251         layout.endLayout();
       
  1252         QVERIFY(line.isValid());
       
  1253         QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
       
  1254     }
       
  1255 
       
  1256     {
       
  1257         QTextLayout layout(longText, testFont);
       
  1258         layout.setFlags(Qt::TextForceRightToLeft);
       
  1259         layout.beginLayout();
       
  1260         QTextLine line = layout.createLine();
       
  1261         layout.endLayout();
       
  1262         QVERIFY(line.isValid());
       
  1263         QVERIFY(line.cursorToX(line.textLength() - 1) > 0);
       
  1264     }
       
  1265 }
       
  1266 
       
  1267 void tst_QTextLayout::widthOfTabs()
       
  1268 {
       
  1269     QTextEngine engine("ddd\t\t", testFont);
       
  1270     engine.ignoreBidi = true;
       
  1271     engine.itemize();
       
  1272     QCOMPARE(qRound(engine.width(0, 5)), qRound(engine.boundingBox(0, 5).width));
       
  1273 }
       
  1274 
       
  1275 void tst_QTextLayout::columnWrapWithTabs()
       
  1276 {
       
  1277     QTextLayout textLayout;
       
  1278     {
       
  1279         QTextOption textOption;
       
  1280         textOption.setWrapMode(QTextOption::WordWrap);
       
  1281         textLayout.setTextOption(textOption);
       
  1282     }
       
  1283 
       
  1284     // Make sure string with spaces does not break
       
  1285     {
       
  1286         QString text = "Foo bar foo bar foo bar";
       
  1287         textLayout.setText(text);
       
  1288 
       
  1289         textLayout.beginLayout();
       
  1290         QTextLine line = textLayout.createLine();
       
  1291         line.setNumColumns(30);
       
  1292         QCOMPARE(line.textLength(), text.length());
       
  1293         textLayout.endLayout();
       
  1294     }
       
  1295 
       
  1296     // Make sure string with tabs breaks
       
  1297     {
       
  1298         QString text = "Foo\tbar\tfoo\tbar\tfoo\tbar";
       
  1299         textLayout.setText(text);
       
  1300         textLayout.beginLayout();
       
  1301         QTextLine line = textLayout.createLine();
       
  1302         line.setNumColumns(30);
       
  1303         QVERIFY(line.textLength() < text.length());
       
  1304         textLayout.endLayout();
       
  1305     }
       
  1306 
       
  1307 }
       
  1308 
       
  1309 
       
  1310 QTEST_MAIN(tst_QTextLayout)
       
  1311 #include "tst_qtextlayout.moc"