1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
44 #include <qglyphrun.h>
46 #include <qtextlayout.h>
47 #include <qfontdatabase.h>
49 // #define DEBUG_SAVE_IMAGE
51 class tst_QGlyphRun: public QObject
55 #if !defined(QT_NO_RAWFONT)
59 void cleanupTestCase();
61 void constructionAndDestruction();
62 void copyConstructor();
64 void equalsOperator_data();
65 void equalsOperator();
66 void textLayoutGlyphIndexes();
67 void drawExistingGlyphs();
68 void drawNonExistentGlyphs();
69 void drawMultiScriptText1();
70 void drawMultiScriptText2();
71 void drawStruckOutText();
72 void drawOverlinedText();
73 void drawUnderlinedText();
74 void drawRightToLeft();
77 void setRawDataAndGetAsVector();
83 #endif // QT_NO_RAWFONT
87 #if !defined(QT_NO_RAWFONT)
89 Q_DECLARE_METATYPE(QGlyphRun);
91 void tst_QGlyphRun::initTestCase()
93 m_testFont_ok = false;
95 m_testFontId = QFontDatabase::addApplicationFont(SRCDIR "test.ttf");
96 QVERIFY(m_testFontId >= 0);
98 m_testFont = QFont("QtsSpecialTestFont");
100 QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont"));
102 m_testFont_ok = true;
105 void tst_QGlyphRun::init()
108 QSKIP("Test font is not working correctly");
111 void tst_QGlyphRun::cleanupTestCase()
113 QFontDatabase::removeApplicationFont(m_testFontId);
116 void tst_QGlyphRun::constructionAndDestruction()
118 QGlyphRun glyphIndexes;
121 static QGlyphRun make_dummy_indexes()
125 QVector<quint32> glyphIndexes;
126 QVector<QPointF> positions;
128 font.setPointSize(18);
130 glyphIndexes.append(1);
131 glyphIndexes.append(2);
132 glyphIndexes.append(3);
134 positions.append(QPointF(1, 2));
135 positions.append(QPointF(3, 4));
136 positions.append(QPointF(5, 6));
138 glyphs.setRawFont(QRawFont::fromFont(font));
139 glyphs.setGlyphIndexes(glyphIndexes);
140 glyphs.setPositions(positions);
145 void tst_QGlyphRun::copyConstructor()
150 QVector<quint32> glyphIndexes;
151 QVector<QPointF> positions;
153 font.setPointSize(18);
155 glyphIndexes.append(1);
156 glyphIndexes.append(2);
157 glyphIndexes.append(3);
159 positions.append(QPointF(1, 2));
160 positions.append(QPointF(3, 4));
161 positions.append(QPointF(5, 6));
163 glyphs.setRawFont(QRawFont::fromFont(font));
164 glyphs.setGlyphIndexes(glyphIndexes);
165 glyphs.setPositions(positions);
168 QGlyphRun otherGlyphs(glyphs);
169 QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
170 QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
171 QCOMPARE(glyphs.positions(), otherGlyphs.positions());
174 void tst_QGlyphRun::assignment()
176 QGlyphRun glyphs(make_dummy_indexes());
178 QGlyphRun otherGlyphs = glyphs;
179 QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
180 QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
181 QCOMPARE(glyphs.positions(), otherGlyphs.positions());
184 void tst_QGlyphRun::equalsOperator_data()
186 QTest::addColumn<QGlyphRun>("one");
187 QTest::addColumn<QGlyphRun>("two");
188 QTest::addColumn<bool>("equals");
190 QGlyphRun one(make_dummy_indexes());
191 QGlyphRun two(make_dummy_indexes());
193 QTest::newRow("Identical") << one << two << true;
196 QGlyphRun busted(two);
198 QVector<QPointF> positions = busted.positions();
199 positions[2] += QPointF(1, 1);
200 busted.setPositions(positions);
203 QTest::newRow("Different positions") << one << busted << false;
207 QGlyphRun busted(two);
210 font.setPixelSize(busted.rawFont().pixelSize() * 2);
211 busted.setRawFont(QRawFont::fromFont(font));
213 QTest::newRow("Different fonts") << one << busted << false;
217 QGlyphRun busted(two);
219 QVector<quint32> glyphIndexes = busted.glyphIndexes();
220 glyphIndexes[2] += 1;
221 busted.setGlyphIndexes(glyphIndexes);
223 QTest::newRow("Different glyph indexes") << one << busted << false;
228 void tst_QGlyphRun::equalsOperator()
230 QFETCH(QGlyphRun, one);
231 QFETCH(QGlyphRun, two);
232 QFETCH(bool, equals);
234 QCOMPARE(one == two, equals);
235 QCOMPARE(one != two, !equals);
239 void tst_QGlyphRun::textLayoutGlyphIndexes()
242 s.append(QLatin1Char('A'));
243 s.append(QChar(0xe000));
245 QTextLayout layout(s);
246 layout.setFont(m_testFont);
247 layout.setCacheEnabled(true);
248 layout.beginLayout();
252 QList<QGlyphRun> listOfGlyphs = layout.glyphRuns();
254 QCOMPARE(listOfGlyphs.size(), 1);
256 QGlyphRun glyphs = listOfGlyphs.at(0);
258 QCOMPARE(glyphs.glyphIndexes().size(), 2);
259 QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2));
260 QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1));
263 void tst_QGlyphRun::drawExistingGlyphs()
265 QPixmap textLayoutDraw(1000, 1000);
266 QPixmap drawGlyphs(1000, 1000);
268 textLayoutDraw.fill(Qt::white);
269 drawGlyphs.fill(Qt::white);
272 s.append(QLatin1Char('A'));
273 s.append(QChar(0xe000));
275 QTextLayout layout(s);
276 layout.setFont(m_testFont);
277 layout.setCacheEnabled(true);
278 layout.beginLayout();
283 QPainter p(&textLayoutDraw);
284 layout.draw(&p, QPointF(50, 50));
287 QGlyphRun glyphs = layout.glyphRuns().size() > 0
288 ? layout.glyphRuns().at(0)
292 QPainter p(&drawGlyphs);
293 p.drawGlyphRun(QPointF(50, 50), glyphs);
296 #if defined(DEBUG_SAVE_IMAGE)
297 textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png");
298 drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png");
301 QCOMPARE(textLayoutDraw, drawGlyphs);
304 void tst_QGlyphRun::setRawData()
307 glyphRun.setRawFont(QRawFont::fromFont(m_testFont));
308 glyphRun.setGlyphIndexes(QVector<quint32>() << 2 << 2 << 2);
309 glyphRun.setPositions(QVector<QPointF>() << QPointF(2, 3) << QPointF(20, 3) << QPointF(10, 20));
311 QPixmap baseline(100, 50);
312 baseline.fill(Qt::white);
314 QPainter p(&baseline);
315 p.drawGlyphRun(QPointF(3, 2), glyphRun);
318 QGlyphRun baselineCopied = glyphRun;
320 quint32 glyphIndexArray[3] = { 2, 2, 2 };
321 QPointF glyphPositionArray[3] = { QPointF(2, 3), QPointF(20, 3), QPointF(10, 20) };
323 glyphRun.setRawData(glyphIndexArray, glyphPositionArray, 3);
325 QPixmap rawDataGlyphs(100, 50);
326 rawDataGlyphs.fill(Qt::white);
328 QPainter p(&rawDataGlyphs);
329 p.drawGlyphRun(QPointF(3, 2), glyphRun);
332 quint32 otherGlyphIndexArray[1] = { 2 };
333 QPointF otherGlyphPositionArray[1] = { QPointF(2, 3) };
335 glyphRun.setRawData(otherGlyphIndexArray, otherGlyphPositionArray, 1);
337 QPixmap baselineCopiedPixmap(100, 50);
338 baselineCopiedPixmap.fill(Qt::white);
340 QPainter p(&baselineCopiedPixmap);
341 p.drawGlyphRun(QPointF(3, 2), baselineCopied);
344 #if defined(DEBUG_SAVE_IMAGE)
345 baseline.save("setRawData_baseline.png");
346 rawDataGlyphs.save("setRawData_rawDataGlyphs.png");
347 baselineCopiedPixmap.save("setRawData_baselineCopiedPixmap.png");
350 QCOMPARE(rawDataGlyphs, baseline);
351 QCOMPARE(baselineCopiedPixmap, baseline);
354 void tst_QGlyphRun::setRawDataAndGetAsVector()
356 QVector<quint32> glyphIndexArray;
357 glyphIndexArray << 3 << 2 << 1 << 4;
359 QVector<QPointF> glyphPositionArray;
360 glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8);
363 glyphRun.setRawData(glyphIndexArray.constData(), glyphPositionArray.constData(), 4);
365 QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
366 QVector<QPointF> glyphPositions = glyphRun.positions();
368 QCOMPARE(glyphIndexes.size(), 4);
369 QCOMPARE(glyphPositions.size(), 4);
371 QCOMPARE(glyphIndexes, glyphIndexArray);
372 QCOMPARE(glyphPositions, glyphPositionArray);
374 QGlyphRun otherGlyphRun;
375 otherGlyphRun.setGlyphIndexes(glyphIndexArray);
376 otherGlyphRun.setPositions(glyphPositionArray);
378 QCOMPARE(glyphRun, otherGlyphRun);
381 void tst_QGlyphRun::drawNonExistentGlyphs()
383 QVector<quint32> glyphIndexes;
384 glyphIndexes.append(3);
386 QVector<QPointF> glyphPositions;
387 glyphPositions.append(QPointF(0, 0));
390 glyphs.setGlyphIndexes(glyphIndexes);
391 glyphs.setPositions(glyphPositions);
392 glyphs.setRawFont(QRawFont::fromFont(m_testFont));
394 QPixmap image(1000, 1000);
395 image.fill(Qt::white);
397 QPixmap imageBefore = image;
400 p.drawGlyphRun(QPointF(50, 50), glyphs);
403 #if defined(DEBUG_SAVE_IMAGE)
404 image.save("drawNonExistentGlyphs.png");
407 QCOMPARE(image, imageBefore); // Should be unchanged
410 void tst_QGlyphRun::drawMultiScriptText1()
413 text += QChar(0x03D0); // Greek, beta
415 QTextLayout textLayout(text);
416 textLayout.setCacheEnabled(true);
417 textLayout.beginLayout();
418 textLayout.createLine();
419 textLayout.endLayout();
421 QPixmap textLayoutDraw(1000, 1000);
422 textLayoutDraw.fill(Qt::white);
424 QPixmap drawGlyphs(1000, 1000);
425 drawGlyphs.fill(Qt::white);
427 QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
428 QCOMPARE(glyphsList.size(), 1);
431 QPainter p(&textLayoutDraw);
432 textLayout.draw(&p, QPointF(50, 50));
436 QPainter p(&drawGlyphs);
437 foreach (QGlyphRun glyphs, glyphsList)
438 p.drawGlyphRun(QPointF(50, 50), glyphs);
441 #if defined(DEBUG_SAVE_IMAGE)
442 textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png");
443 drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png");
446 QCOMPARE(drawGlyphs, textLayoutDraw);
450 void tst_QGlyphRun::drawMultiScriptText2()
453 text += QChar(0x0621); // Arabic, Hamza
454 text += QChar(0x03D0); // Greek, beta
456 QTextLayout textLayout(text);
457 textLayout.setCacheEnabled(true);
458 textLayout.beginLayout();
459 textLayout.createLine();
460 textLayout.endLayout();
462 QPixmap textLayoutDraw(1000, 1000);
463 textLayoutDraw.fill(Qt::white);
465 QPixmap drawGlyphs(1000, 1000);
466 drawGlyphs.fill(Qt::white);
468 QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
469 QCOMPARE(glyphsList.size(), 2);
472 QPainter p(&textLayoutDraw);
473 textLayout.draw(&p, QPointF(50, 50));
477 QPainter p(&drawGlyphs);
478 foreach (QGlyphRun glyphs, glyphsList)
479 p.drawGlyphRun(QPointF(50, 50), glyphs);
482 #if defined(DEBUG_SAVE_IMAGE)
483 textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png");
484 drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png");
487 QCOMPARE(drawGlyphs, textLayoutDraw);
490 void tst_QGlyphRun::detach()
494 glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3);
496 QGlyphRun otherGlyphs;
497 otherGlyphs = glyphs;
499 QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes());
501 otherGlyphs.setGlyphIndexes(QVector<quint32>() << 4 << 5 << 6);
503 QCOMPARE(otherGlyphs.glyphIndexes(), QVector<quint32>() << 4 << 5 << 6);
504 QCOMPARE(glyphs.glyphIndexes(), QVector<quint32>() << 1 << 2 << 3);
507 void tst_QGlyphRun::drawStruckOutText()
509 QPixmap textLayoutDraw(1000, 1000);
510 QPixmap drawGlyphs(1000, 1000);
512 textLayoutDraw.fill(Qt::white);
513 drawGlyphs.fill(Qt::white);
515 QString s = QString::fromLatin1("Foobar");
518 font.setStrikeOut(true);
520 QTextLayout layout(s);
521 layout.setFont(font);
522 layout.setCacheEnabled(true);
523 layout.beginLayout();
528 QPainter p(&textLayoutDraw);
529 layout.draw(&p, QPointF(50, 50));
532 QGlyphRun glyphs = layout.glyphRuns().size() > 0
533 ? layout.glyphRuns().at(0)
537 QPainter p(&drawGlyphs);
538 p.drawGlyphRun(QPointF(50, 50), glyphs);
541 #if defined(DEBUG_SAVE_IMAGE)
542 textLayoutDraw.save("drawStruckOutText_textLayoutDraw.png");
543 drawGlyphs.save("drawStruckOutText_drawGlyphIndexes.png");
546 QCOMPARE(textLayoutDraw, drawGlyphs);
549 void tst_QGlyphRun::drawOverlinedText()
551 QPixmap textLayoutDraw(1000, 1000);
552 QPixmap drawGlyphs(1000, 1000);
554 textLayoutDraw.fill(Qt::white);
555 drawGlyphs.fill(Qt::white);
557 QString s = QString::fromLatin1("Foobar");
560 font.setOverline(true);
562 QTextLayout layout(s);
563 layout.setFont(font);
564 layout.setCacheEnabled(true);
565 layout.beginLayout();
570 QPainter p(&textLayoutDraw);
571 layout.draw(&p, QPointF(50, 50));
574 QGlyphRun glyphs = layout.glyphRuns().size() > 0
575 ? layout.glyphRuns().at(0)
579 QPainter p(&drawGlyphs);
580 p.drawGlyphRun(QPointF(50, 50), glyphs);
583 #if defined(DEBUG_SAVE_IMAGE)
584 textLayoutDraw.save("drawOverlineText_textLayoutDraw.png");
585 drawGlyphs.save("drawOverlineText_drawGlyphIndexes.png");
588 QCOMPARE(textLayoutDraw, drawGlyphs);
591 void tst_QGlyphRun::drawUnderlinedText()
593 QPixmap textLayoutDraw(1000, 1000);
594 QPixmap drawGlyphs(1000, 1000);
596 textLayoutDraw.fill(Qt::white);
597 drawGlyphs.fill(Qt::white);
599 QString s = QString::fromLatin1("Foobar");
602 font.setUnderline(true);
604 QTextLayout layout(s);
605 layout.setFont(font);
606 layout.setCacheEnabled(true);
607 layout.beginLayout();
612 QPainter p(&textLayoutDraw);
613 layout.draw(&p, QPointF(50, 50));
616 QGlyphRun glyphs = layout.glyphRuns().size() > 0
617 ? layout.glyphRuns().at(0)
621 QPainter p(&drawGlyphs);
622 p.drawGlyphRun(QPointF(50, 50), glyphs);
625 #if defined(DEBUG_SAVE_IMAGE)
626 textLayoutDraw.save("drawUnderlineText_textLayoutDraw.png");
627 drawGlyphs.save("drawUnderlineText_drawGlyphIndexes.png");
630 QCOMPARE(textLayoutDraw, drawGlyphs);
633 void tst_QGlyphRun::drawRightToLeft()
636 s.append(QChar(1575));
637 s.append(QChar(1578));
639 QPixmap textLayoutDraw(1000, 1000);
640 QPixmap drawGlyphs(1000, 1000);
642 textLayoutDraw.fill(Qt::white);
643 drawGlyphs.fill(Qt::white);
646 font.setUnderline(true);
648 QTextLayout layout(s);
649 layout.setFont(font);
650 layout.setCacheEnabled(true);
651 layout.beginLayout();
656 QPainter p(&textLayoutDraw);
657 layout.draw(&p, QPointF(50, 50));
660 QGlyphRun glyphs = layout.glyphRuns().size() > 0
661 ? layout.glyphRuns().at(0)
665 QPainter p(&drawGlyphs);
666 p.drawGlyphRun(QPointF(50, 50), glyphs);
669 #if defined(DEBUG_SAVE_IMAGE)
670 textLayoutDraw.save("drawRightToLeft_textLayoutDraw.png");
671 drawGlyphs.save("drawRightToLeft_drawGlyphIndexes.png");
674 QCOMPARE(textLayoutDraw, drawGlyphs);
678 #endif // QT_NO_RAWFONT
680 QTEST_MAIN(tst_QGlyphRun)
681 #include "tst_qglyphrun.moc"