1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
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 The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QtTest> |
30 | |
31 | #include <qglyphrun.h> |
32 | #include <qpainter.h> |
33 | #include <qtextlayout.h> |
34 | #include <qfontdatabase.h> |
35 | |
36 | // #define DEBUG_SAVE_IMAGE |
37 | |
38 | class tst_QGlyphRun: public QObject |
39 | { |
40 | Q_OBJECT |
41 | |
42 | #if !defined(QT_NO_RAWFONT) |
43 | private slots: |
44 | void initTestCase(); |
45 | void init(); |
46 | void cleanupTestCase(); |
47 | |
48 | void constructionAndDestruction(); |
49 | void copyConstructor(); |
50 | void assignment(); |
51 | void equalsOperator_data(); |
52 | void equalsOperator(); |
53 | void isEmpty(); |
54 | void textLayoutGlyphIndexes(); |
55 | void drawExistingGlyphs(); |
56 | void drawNonExistentGlyphs(); |
57 | void drawMultiScriptText1(); |
58 | void drawMultiScriptText2(); |
59 | void drawStruckOutText(); |
60 | void drawOverlinedText(); |
61 | void drawUnderlinedText(); |
62 | void drawRightToLeft(); |
63 | void detach(); |
64 | void setRawData(); |
65 | void setRawDataAndGetAsVector(); |
66 | void boundingRect(); |
67 | void mixedScripts(); |
68 | void multiLineBoundingRect(); |
69 | void defaultIgnorables(); |
70 | |
71 | private: |
72 | int m_testFontId; |
73 | QFont m_testFont; |
74 | bool m_testFont_ok; |
75 | #endif // QT_NO_RAWFONT |
76 | |
77 | }; |
78 | |
79 | #if !defined(QT_NO_RAWFONT) |
80 | |
81 | Q_DECLARE_METATYPE(QGlyphRun); |
82 | |
83 | void tst_QGlyphRun::initTestCase() |
84 | { |
85 | m_testFont_ok = false; |
86 | |
87 | m_testFontId = QFontDatabase::addApplicationFont(QFINDTESTDATA("test.ttf" )); |
88 | QVERIFY(m_testFontId >= 0); |
89 | |
90 | m_testFont = QFont("QtsSpecialTestFont" ); |
91 | |
92 | QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont" )); |
93 | |
94 | m_testFont_ok = true; |
95 | } |
96 | |
97 | void tst_QGlyphRun::init() |
98 | { |
99 | if (!m_testFont_ok) |
100 | QSKIP("Test font is not working correctly" ); |
101 | } |
102 | |
103 | void tst_QGlyphRun::cleanupTestCase() |
104 | { |
105 | QFontDatabase::removeApplicationFont(id: m_testFontId); |
106 | } |
107 | |
108 | void tst_QGlyphRun::constructionAndDestruction() |
109 | { |
110 | QGlyphRun glyphIndexes; |
111 | } |
112 | |
113 | static QGlyphRun make_dummy_indexes() |
114 | { |
115 | QGlyphRun glyphs; |
116 | |
117 | QVector<quint32> glyphIndexes; |
118 | QVector<QPointF> positions; |
119 | QFont font; |
120 | font.setPointSize(18); |
121 | |
122 | glyphIndexes.append(t: 1); |
123 | glyphIndexes.append(t: 2); |
124 | glyphIndexes.append(t: 3); |
125 | |
126 | positions.append(t: QPointF(1, 2)); |
127 | positions.append(t: QPointF(3, 4)); |
128 | positions.append(t: QPointF(5, 6)); |
129 | |
130 | glyphs.setRawFont(QRawFont::fromFont(font)); |
131 | glyphs.setGlyphIndexes(glyphIndexes); |
132 | glyphs.setPositions(positions); |
133 | |
134 | return glyphs; |
135 | } |
136 | |
137 | void tst_QGlyphRun::copyConstructor() |
138 | { |
139 | QGlyphRun glyphs; |
140 | |
141 | { |
142 | QVector<quint32> glyphIndexes; |
143 | QVector<QPointF> positions; |
144 | QFont font; |
145 | font.setPointSize(18); |
146 | |
147 | glyphIndexes.append(t: 1); |
148 | glyphIndexes.append(t: 2); |
149 | glyphIndexes.append(t: 3); |
150 | |
151 | positions.append(t: QPointF(1, 2)); |
152 | positions.append(t: QPointF(3, 4)); |
153 | positions.append(t: QPointF(5, 6)); |
154 | |
155 | glyphs.setRawFont(QRawFont::fromFont(font)); |
156 | glyphs.setGlyphIndexes(glyphIndexes); |
157 | glyphs.setPositions(positions); |
158 | } |
159 | |
160 | QGlyphRun otherGlyphs(glyphs); |
161 | QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont()); |
162 | QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); |
163 | QCOMPARE(glyphs.positions(), otherGlyphs.positions()); |
164 | } |
165 | |
166 | void tst_QGlyphRun::assignment() |
167 | { |
168 | QGlyphRun glyphs(make_dummy_indexes()); |
169 | |
170 | QGlyphRun otherGlyphs = glyphs; |
171 | QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont()); |
172 | QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); |
173 | QCOMPARE(glyphs.positions(), otherGlyphs.positions()); |
174 | } |
175 | |
176 | void tst_QGlyphRun::equalsOperator_data() |
177 | { |
178 | QTest::addColumn<QGlyphRun>(name: "one" ); |
179 | QTest::addColumn<QGlyphRun>(name: "two" ); |
180 | QTest::addColumn<bool>(name: "equals" ); |
181 | |
182 | QGlyphRun one(make_dummy_indexes()); |
183 | QGlyphRun two(make_dummy_indexes()); |
184 | |
185 | QTest::newRow(dataTag: "Identical" ) << one << two << true; |
186 | |
187 | { |
188 | QGlyphRun busted(two); |
189 | |
190 | QVector<QPointF> positions = busted.positions(); |
191 | positions[2] += QPointF(1, 1); |
192 | busted.setPositions(positions); |
193 | |
194 | |
195 | QTest::newRow(dataTag: "Different positions" ) << one << busted << false; |
196 | } |
197 | |
198 | { |
199 | QGlyphRun busted(two); |
200 | |
201 | QFont font; |
202 | font.setPixelSize(busted.rawFont().pixelSize() * 2); |
203 | busted.setRawFont(QRawFont::fromFont(font)); |
204 | |
205 | QTest::newRow(dataTag: "Different fonts" ) << one << busted << false; |
206 | } |
207 | |
208 | { |
209 | QGlyphRun busted(two); |
210 | |
211 | QVector<quint32> glyphIndexes = busted.glyphIndexes(); |
212 | glyphIndexes[2] += 1; |
213 | busted.setGlyphIndexes(glyphIndexes); |
214 | |
215 | QTest::newRow(dataTag: "Different glyph indexes" ) << one << busted << false; |
216 | } |
217 | |
218 | } |
219 | |
220 | void tst_QGlyphRun::equalsOperator() |
221 | { |
222 | QFETCH(QGlyphRun, one); |
223 | QFETCH(QGlyphRun, two); |
224 | QFETCH(bool, equals); |
225 | |
226 | QCOMPARE(one == two, equals); |
227 | QCOMPARE(one != two, !equals); |
228 | } |
229 | |
230 | void tst_QGlyphRun::isEmpty() |
231 | { |
232 | QGlyphRun glyphs; |
233 | QVERIFY(glyphs.isEmpty()); |
234 | |
235 | glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3); |
236 | QVERIFY(!glyphs.isEmpty()); |
237 | |
238 | glyphs.clear(); |
239 | QVERIFY(glyphs.isEmpty()); |
240 | |
241 | QVector<quint32> glyphIndexes = QVector<quint32>() << 1 << 2 << 3; |
242 | QVector<QPointF> positions = QVector<QPointF>() << QPointF(0, 0) << QPointF(0, 0) << QPointF(0, 0); |
243 | glyphs.setRawData(glyphIndexArray: glyphIndexes.constData(), glyphPositionArray: positions.constData(), size: glyphIndexes.size()); |
244 | QVERIFY(!glyphs.isEmpty()); |
245 | } |
246 | |
247 | void tst_QGlyphRun::textLayoutGlyphIndexes() |
248 | { |
249 | QString s; |
250 | s.append(c: QLatin1Char('A')); |
251 | s.append(c: QChar(0xe000)); |
252 | |
253 | QTextLayout layout(s); |
254 | layout.setFont(m_testFont); |
255 | layout.setCacheEnabled(true); |
256 | layout.beginLayout(); |
257 | layout.createLine(); |
258 | layout.endLayout(); |
259 | |
260 | QList<QGlyphRun> listOfGlyphs = layout.glyphRuns(); |
261 | |
262 | QCOMPARE(listOfGlyphs.size(), 1); |
263 | |
264 | QGlyphRun glyphs = listOfGlyphs.at(i: 0); |
265 | |
266 | QCOMPARE(glyphs.glyphIndexes().size(), 2); |
267 | QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2)); |
268 | QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1)); |
269 | } |
270 | |
271 | void tst_QGlyphRun::drawExistingGlyphs() |
272 | { |
273 | QPixmap textLayoutDraw(1000, 1000); |
274 | QPixmap drawGlyphs(1000, 1000); |
275 | |
276 | textLayoutDraw.fill(fillColor: Qt::white); |
277 | drawGlyphs.fill(fillColor: Qt::white); |
278 | |
279 | QString s; |
280 | s.append(c: QLatin1Char('A')); |
281 | s.append(c: QChar(0xe000)); |
282 | |
283 | QTextLayout layout(s); |
284 | layout.setFont(m_testFont); |
285 | layout.setCacheEnabled(true); |
286 | layout.beginLayout(); |
287 | layout.createLine(); |
288 | layout.endLayout(); |
289 | |
290 | { |
291 | QPainter p(&textLayoutDraw); |
292 | layout.draw(p: &p, pos: QPointF(50, 50)); |
293 | } |
294 | |
295 | QGlyphRun glyphs = layout.glyphRuns().size() > 0 |
296 | ? layout.glyphRuns().at(i: 0) |
297 | : QGlyphRun(); |
298 | |
299 | { |
300 | QPainter p(&drawGlyphs); |
301 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
302 | } |
303 | |
304 | #if defined(DEBUG_SAVE_IMAGE) |
305 | textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png" ); |
306 | drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png" ); |
307 | #endif |
308 | |
309 | QCOMPARE(textLayoutDraw, drawGlyphs); |
310 | } |
311 | |
312 | void tst_QGlyphRun::setRawData() |
313 | { |
314 | QGlyphRun glyphRun; |
315 | glyphRun.setRawFont(QRawFont::fromFont(font: m_testFont)); |
316 | glyphRun.setGlyphIndexes(QVector<quint32>() << 2 << 2 << 2); |
317 | glyphRun.setPositions(QVector<QPointF>() << QPointF(2, 3) << QPointF(20, 3) << QPointF(10, 20)); |
318 | |
319 | QPixmap baseline(100, 50); |
320 | baseline.fill(fillColor: Qt::white); |
321 | { |
322 | QPainter p(&baseline); |
323 | p.drawGlyphRun(position: QPointF(3, 2), glyphRun); |
324 | } |
325 | |
326 | QGlyphRun baselineCopied = glyphRun; |
327 | |
328 | quint32 glyphIndexArray[3] = { 2, 2, 2 }; |
329 | QPointF glyphPositionArray[3] = { QPointF(2, 3), QPointF(20, 3), QPointF(10, 20) }; |
330 | |
331 | glyphRun.setRawData(glyphIndexArray, glyphPositionArray, size: 3); |
332 | |
333 | QPixmap rawDataGlyphs(100, 50); |
334 | rawDataGlyphs.fill(fillColor: Qt::white); |
335 | { |
336 | QPainter p(&rawDataGlyphs); |
337 | p.drawGlyphRun(position: QPointF(3, 2), glyphRun); |
338 | } |
339 | |
340 | quint32 otherGlyphIndexArray[1] = { 2 }; |
341 | QPointF otherGlyphPositionArray[1] = { QPointF(2, 3) }; |
342 | |
343 | glyphRun.setRawData(glyphIndexArray: otherGlyphIndexArray, glyphPositionArray: otherGlyphPositionArray, size: 1); |
344 | |
345 | QPixmap baselineCopiedPixmap(100, 50); |
346 | baselineCopiedPixmap.fill(fillColor: Qt::white); |
347 | { |
348 | QPainter p(&baselineCopiedPixmap); |
349 | p.drawGlyphRun(position: QPointF(3, 2), glyphRun: baselineCopied); |
350 | } |
351 | |
352 | #if defined(DEBUG_SAVE_IMAGE) |
353 | baseline.save("setRawData_baseline.png" ); |
354 | rawDataGlyphs.save("setRawData_rawDataGlyphs.png" ); |
355 | baselineCopiedPixmap.save("setRawData_baselineCopiedPixmap.png" ); |
356 | #endif |
357 | |
358 | QCOMPARE(rawDataGlyphs, baseline); |
359 | QCOMPARE(baselineCopiedPixmap, baseline); |
360 | } |
361 | |
362 | void tst_QGlyphRun::setRawDataAndGetAsVector() |
363 | { |
364 | QVector<quint32> glyphIndexArray; |
365 | glyphIndexArray << 3 << 2 << 1 << 4; |
366 | |
367 | QVector<QPointF> glyphPositionArray; |
368 | glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8); |
369 | |
370 | QGlyphRun glyphRun; |
371 | glyphRun.setRawData(glyphIndexArray: glyphIndexArray.constData(), glyphPositionArray: glyphPositionArray.constData(), size: 4); |
372 | |
373 | QVector<quint32> glyphIndexes = glyphRun.glyphIndexes(); |
374 | QVector<QPointF> glyphPositions = glyphRun.positions(); |
375 | |
376 | QCOMPARE(glyphIndexes.size(), 4); |
377 | QCOMPARE(glyphPositions.size(), 4); |
378 | |
379 | QCOMPARE(glyphIndexes, glyphIndexArray); |
380 | QCOMPARE(glyphPositions, glyphPositionArray); |
381 | |
382 | QGlyphRun otherGlyphRun; |
383 | otherGlyphRun.setGlyphIndexes(glyphIndexArray); |
384 | otherGlyphRun.setPositions(glyphPositionArray); |
385 | |
386 | QCOMPARE(glyphRun, otherGlyphRun); |
387 | } |
388 | |
389 | void tst_QGlyphRun::drawNonExistentGlyphs() |
390 | { |
391 | QVector<quint32> glyphIndexes; |
392 | glyphIndexes.append(t: 4); |
393 | |
394 | QVector<QPointF> glyphPositions; |
395 | glyphPositions.append(t: QPointF(0, 0)); |
396 | |
397 | QGlyphRun glyphs; |
398 | glyphs.setGlyphIndexes(glyphIndexes); |
399 | glyphs.setPositions(glyphPositions); |
400 | glyphs.setRawFont(QRawFont::fromFont(font: m_testFont)); |
401 | |
402 | QPixmap image(1000, 1000); |
403 | image.fill(fillColor: Qt::white); |
404 | |
405 | QPixmap imageBefore = image; |
406 | { |
407 | QPainter p(&image); |
408 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
409 | } |
410 | |
411 | #if defined(DEBUG_SAVE_IMAGE) |
412 | image.save("drawNonExistentGlyphs.png" ); |
413 | #endif |
414 | |
415 | QCOMPARE(image, imageBefore); // Should be unchanged |
416 | } |
417 | |
418 | void tst_QGlyphRun::drawMultiScriptText1() |
419 | { |
420 | QString text; |
421 | text += QChar(0x03D0); // Greek, beta |
422 | |
423 | QTextLayout textLayout(text); |
424 | textLayout.setCacheEnabled(true); |
425 | textLayout.beginLayout(); |
426 | textLayout.createLine(); |
427 | textLayout.endLayout(); |
428 | |
429 | QPixmap textLayoutDraw(1000, 1000); |
430 | textLayoutDraw.fill(fillColor: Qt::white); |
431 | |
432 | QPixmap drawGlyphs(1000, 1000); |
433 | drawGlyphs.fill(fillColor: Qt::white); |
434 | |
435 | QList<QGlyphRun> glyphsList = textLayout.glyphRuns(); |
436 | QCOMPARE(glyphsList.size(), 1); |
437 | |
438 | { |
439 | QPainter p(&textLayoutDraw); |
440 | textLayout.draw(p: &p, pos: QPointF(50, 50)); |
441 | } |
442 | |
443 | { |
444 | QPainter p(&drawGlyphs); |
445 | foreach (QGlyphRun glyphs, glyphsList) |
446 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
447 | } |
448 | |
449 | #if defined(DEBUG_SAVE_IMAGE) |
450 | textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png" ); |
451 | drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png" ); |
452 | #endif |
453 | |
454 | QCOMPARE(drawGlyphs, textLayoutDraw); |
455 | } |
456 | |
457 | |
458 | void tst_QGlyphRun::drawMultiScriptText2() |
459 | { |
460 | QString text; |
461 | text += QChar(0x0621); // Arabic, Hamza |
462 | text += QChar(0x03D0); // Greek, beta |
463 | |
464 | QTextLayout textLayout(text); |
465 | textLayout.setCacheEnabled(true); |
466 | textLayout.beginLayout(); |
467 | textLayout.createLine(); |
468 | textLayout.endLayout(); |
469 | |
470 | QPixmap textLayoutDraw(1000, 1000); |
471 | textLayoutDraw.fill(fillColor: Qt::white); |
472 | |
473 | QPixmap drawGlyphs(1000, 1000); |
474 | drawGlyphs.fill(fillColor: Qt::white); |
475 | |
476 | QList<QGlyphRun> glyphsList = textLayout.glyphRuns(); |
477 | QCOMPARE(glyphsList.size(), 2); |
478 | |
479 | { |
480 | QPainter p(&textLayoutDraw); |
481 | textLayout.draw(p: &p, pos: QPointF(50, 50)); |
482 | } |
483 | |
484 | { |
485 | QPainter p(&drawGlyphs); |
486 | foreach (QGlyphRun glyphs, glyphsList) |
487 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
488 | } |
489 | |
490 | #if defined(DEBUG_SAVE_IMAGE) |
491 | textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png" ); |
492 | drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png" ); |
493 | #endif |
494 | |
495 | QCOMPARE(drawGlyphs, textLayoutDraw); |
496 | } |
497 | |
498 | void tst_QGlyphRun::detach() |
499 | { |
500 | QGlyphRun glyphs; |
501 | |
502 | glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3); |
503 | |
504 | QGlyphRun otherGlyphs; |
505 | otherGlyphs = glyphs; |
506 | |
507 | QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes()); |
508 | |
509 | otherGlyphs.setGlyphIndexes(QVector<quint32>() << 4 << 5 << 6); |
510 | |
511 | QCOMPARE(otherGlyphs.glyphIndexes(), QVector<quint32>() << 4 << 5 << 6); |
512 | QCOMPARE(glyphs.glyphIndexes(), QVector<quint32>() << 1 << 2 << 3); |
513 | } |
514 | |
515 | void tst_QGlyphRun::drawStruckOutText() |
516 | { |
517 | QPixmap textLayoutDraw(1000, 1000); |
518 | QPixmap drawGlyphs(1000, 1000); |
519 | |
520 | textLayoutDraw.fill(fillColor: Qt::white); |
521 | drawGlyphs.fill(fillColor: Qt::white); |
522 | |
523 | QString s = QString::fromLatin1(str: "Foobar" ); |
524 | |
525 | QFont font; |
526 | font.setStrikeOut(true); |
527 | font.setStyleStrategy(QFont::ForceIntegerMetrics); |
528 | |
529 | QTextLayout layout(s); |
530 | layout.setFont(font); |
531 | layout.setCacheEnabled(true); |
532 | layout.beginLayout(); |
533 | layout.createLine(); |
534 | layout.endLayout(); |
535 | |
536 | { |
537 | QPainter p(&textLayoutDraw); |
538 | layout.draw(p: &p, pos: QPointF(50, 50)); |
539 | } |
540 | |
541 | QGlyphRun glyphs = layout.glyphRuns().size() > 0 |
542 | ? layout.glyphRuns().at(i: 0) |
543 | : QGlyphRun(); |
544 | |
545 | { |
546 | QPainter p(&drawGlyphs); |
547 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
548 | } |
549 | |
550 | #if defined(DEBUG_SAVE_IMAGE) |
551 | textLayoutDraw.save("drawStruckOutText_textLayoutDraw.png" ); |
552 | drawGlyphs.save("drawStruckOutText_drawGlyphIndexes.png" ); |
553 | #endif |
554 | |
555 | QCOMPARE(textLayoutDraw, drawGlyphs); |
556 | } |
557 | |
558 | void tst_QGlyphRun::drawOverlinedText() |
559 | { |
560 | QPixmap textLayoutDraw(1000, 1000); |
561 | QPixmap drawGlyphs(1000, 1000); |
562 | |
563 | textLayoutDraw.fill(fillColor: Qt::white); |
564 | drawGlyphs.fill(fillColor: Qt::white); |
565 | |
566 | QString s = QString::fromLatin1(str: "Foobar" ); |
567 | |
568 | QFont font; |
569 | font.setOverline(true); |
570 | font.setStyleStrategy(QFont::ForceIntegerMetrics); |
571 | |
572 | QTextLayout layout(s); |
573 | layout.setFont(font); |
574 | layout.setCacheEnabled(true); |
575 | layout.beginLayout(); |
576 | layout.createLine(); |
577 | layout.endLayout(); |
578 | |
579 | { |
580 | QPainter p(&textLayoutDraw); |
581 | layout.draw(p: &p, pos: QPointF(50, 50)); |
582 | } |
583 | |
584 | QGlyphRun glyphs = layout.glyphRuns().size() > 0 |
585 | ? layout.glyphRuns().at(i: 0) |
586 | : QGlyphRun(); |
587 | |
588 | { |
589 | QPainter p(&drawGlyphs); |
590 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
591 | } |
592 | |
593 | #if defined(DEBUG_SAVE_IMAGE) |
594 | textLayoutDraw.save("drawOverlineText_textLayoutDraw.png" ); |
595 | drawGlyphs.save("drawOverlineText_drawGlyphIndexes.png" ); |
596 | #endif |
597 | |
598 | QCOMPARE(textLayoutDraw, drawGlyphs); |
599 | } |
600 | |
601 | void tst_QGlyphRun::drawUnderlinedText() |
602 | { |
603 | QPixmap textLayoutDraw(1000, 1000); |
604 | QPixmap drawGlyphs(1000, 1000); |
605 | |
606 | textLayoutDraw.fill(fillColor: Qt::white); |
607 | drawGlyphs.fill(fillColor: Qt::white); |
608 | |
609 | QString s = QString::fromLatin1(str: "Foobar" ); |
610 | |
611 | QFont font; |
612 | font.setUnderline(true); |
613 | font.setStyleStrategy(QFont::ForceIntegerMetrics); |
614 | |
615 | QTextLayout layout(s); |
616 | layout.setFont(font); |
617 | layout.setCacheEnabled(true); |
618 | layout.beginLayout(); |
619 | layout.createLine(); |
620 | layout.endLayout(); |
621 | |
622 | { |
623 | QPainter p(&textLayoutDraw); |
624 | layout.draw(p: &p, pos: QPointF(50, 50)); |
625 | } |
626 | |
627 | QGlyphRun glyphs = layout.glyphRuns().size() > 0 |
628 | ? layout.glyphRuns().at(i: 0) |
629 | : QGlyphRun(); |
630 | |
631 | { |
632 | QPainter p(&drawGlyphs); |
633 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
634 | } |
635 | |
636 | #if defined(DEBUG_SAVE_IMAGE) |
637 | textLayoutDraw.save("drawUnderlineText_textLayoutDraw.png" ); |
638 | drawGlyphs.save("drawUnderlineText_drawGlyphIndexes.png" ); |
639 | #endif |
640 | |
641 | QCOMPARE(textLayoutDraw, drawGlyphs); |
642 | } |
643 | |
644 | void tst_QGlyphRun::drawRightToLeft() |
645 | { |
646 | QString s; |
647 | s.append(c: QChar(1575)); |
648 | s.append(c: QChar(1578)); |
649 | |
650 | QPixmap textLayoutDraw(1000, 1000); |
651 | QPixmap drawGlyphs(1000, 1000); |
652 | |
653 | textLayoutDraw.fill(fillColor: Qt::white); |
654 | drawGlyphs.fill(fillColor: Qt::white); |
655 | |
656 | QFont font; |
657 | font.setUnderline(true); |
658 | |
659 | QTextLayout layout(s); |
660 | layout.setFont(font); |
661 | layout.setCacheEnabled(true); |
662 | layout.beginLayout(); |
663 | layout.createLine(); |
664 | layout.endLayout(); |
665 | |
666 | { |
667 | QPainter p(&textLayoutDraw); |
668 | layout.draw(p: &p, pos: QPointF(50, 50)); |
669 | } |
670 | |
671 | QGlyphRun glyphs = layout.glyphRuns().size() > 0 |
672 | ? layout.glyphRuns().at(i: 0) |
673 | : QGlyphRun(); |
674 | |
675 | { |
676 | QPainter p(&drawGlyphs); |
677 | p.drawGlyphRun(position: QPointF(50, 50), glyphRun: glyphs); |
678 | } |
679 | |
680 | #if defined(DEBUG_SAVE_IMAGE) |
681 | textLayoutDraw.save("drawRightToLeft_textLayoutDraw.png" ); |
682 | drawGlyphs.save("drawRightToLeft_drawGlyphIndexes.png" ); |
683 | #endif |
684 | |
685 | QCOMPARE(textLayoutDraw, drawGlyphs); |
686 | |
687 | } |
688 | |
689 | void tst_QGlyphRun::boundingRect() |
690 | { |
691 | QString s(QLatin1String("AbCdE" )); |
692 | |
693 | QRawFont rawFont(QRawFont::fromFont(font: QFont())); |
694 | QVERIFY(rawFont.isValid()); |
695 | QVector<quint32> glyphIndexes = rawFont.glyphIndexesForString(text: s); |
696 | QVector<QPointF> positions = rawFont.advancesForGlyphIndexes(glyphIndexes); |
697 | QCOMPARE(glyphIndexes.size(), s.size()); |
698 | QCOMPARE(positions.size(), glyphIndexes.size()); |
699 | |
700 | QGlyphRun glyphs; |
701 | glyphs.setRawFont(rawFont); |
702 | glyphs.setGlyphIndexes(glyphIndexes); |
703 | glyphs.setPositions(positions); |
704 | |
705 | QRectF boundingRect = glyphs.boundingRect(); |
706 | |
707 | glyphs.clear(); |
708 | glyphs.setRawFont(rawFont); |
709 | glyphs.setRawData(glyphIndexArray: glyphIndexes.constData(), glyphPositionArray: positions.constData(), size: glyphIndexes.size()); |
710 | QCOMPARE(glyphs.boundingRect(), boundingRect); |
711 | |
712 | boundingRect = QRectF(0, 0, 1, 1); |
713 | glyphs.setBoundingRect(boundingRect); |
714 | QCOMPARE(glyphs.boundingRect(), boundingRect); |
715 | } |
716 | |
717 | void tst_QGlyphRun::mixedScripts() |
718 | { |
719 | QString s; |
720 | s += QChar(0x31); // The character '1' |
721 | s += QChar(0xbc14); // Hangul character |
722 | |
723 | QTextLayout layout; |
724 | layout.setFont(m_testFont); |
725 | layout.setText(s); |
726 | layout.beginLayout(); |
727 | layout.createLine(); |
728 | layout.endLayout(); |
729 | |
730 | QList<QGlyphRun> glyphRuns = layout.glyphRuns(); |
731 | #ifdef Q_OS_WINRT |
732 | QEXPECT_FAIL("" , "Hangul character not rendered on winrt" , Continue); |
733 | #endif |
734 | QCOMPARE(glyphRuns.size(), 2); |
735 | } |
736 | |
737 | void tst_QGlyphRun::multiLineBoundingRect() |
738 | { |
739 | QTextLayout layout; |
740 | layout.setText("Foo Bar" ); |
741 | layout.beginLayout(); |
742 | |
743 | QTextLine line = layout.createLine(); |
744 | line.setNumColumns(4); |
745 | line.setPosition(QPointF(0, 0)); |
746 | |
747 | line = layout.createLine(); |
748 | line.setPosition(QPointF(0, 10)); |
749 | |
750 | layout.endLayout(); |
751 | |
752 | QCOMPARE(layout.lineCount(), 2); |
753 | |
754 | QList<QGlyphRun> firstLineGlyphRuns = layout.lineAt(i: 0).glyphRuns(); |
755 | QList<QGlyphRun> allGlyphRuns = layout.glyphRuns(); |
756 | QCOMPARE(firstLineGlyphRuns.size(), 1); |
757 | QCOMPARE(allGlyphRuns.size(), 1); |
758 | |
759 | QGlyphRun firstLineGlyphRun = firstLineGlyphRuns.first(); |
760 | QGlyphRun allGlyphRun = allGlyphRuns.first(); |
761 | |
762 | QVERIFY(firstLineGlyphRun.boundingRect().height() < allGlyphRun.boundingRect().height()); |
763 | } |
764 | |
765 | void tst_QGlyphRun::defaultIgnorables() |
766 | { |
767 | QTextLayout layout; |
768 | layout.setFont(QFont("QtsSpecialTestFont" )); |
769 | layout.setText(QChar(0x200D)); |
770 | layout.beginLayout(); |
771 | layout.createLine(); |
772 | layout.endLayout(); |
773 | |
774 | QList<QGlyphRun> runs = layout.glyphRuns(); |
775 | QCOMPARE(runs.size(), 1); |
776 | QCOMPARE(runs.at(0).glyphIndexes().size(), 1); |
777 | QCOMPARE(runs.at(0).glyphIndexes()[0], 0); |
778 | } |
779 | |
780 | #endif // QT_NO_RAWFONT |
781 | |
782 | QTEST_MAIN(tst_QGlyphRun) |
783 | #include "tst_qglyphrun.moc" |
784 | |
785 | |