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 | #include <QtGui/QFontDatabase> |
31 | |
32 | #include <qrawfont.h> |
33 | #include <private/qrawfont_p.h> |
34 | |
35 | class tst_QRawFont: public QObject |
36 | { |
37 | Q_OBJECT |
38 | #if !defined(QT_NO_RAWFONT) |
39 | private slots: |
40 | void init(); |
41 | void initTestCase(); |
42 | |
43 | void invalidRawFont(); |
44 | |
45 | void explicitRawFontNotLoadedInDatabase_data(); |
46 | void explicitRawFontNotLoadedInDatabase(); |
47 | |
48 | void explicitRawFontNotAvailableInSystem_data(); |
49 | void explicitRawFontNotAvailableInSystem(); |
50 | |
51 | void correctFontData_data(); |
52 | void correctFontData(); |
53 | |
54 | void glyphIndices(); |
55 | |
56 | void advances_data(); |
57 | void advances(); |
58 | |
59 | void textLayout(); |
60 | |
61 | void fontTable_data(); |
62 | void fontTable(); |
63 | |
64 | void supportedWritingSystems_data(); |
65 | void supportedWritingSystems(); |
66 | |
67 | void supportsCharacter_data(); |
68 | void supportsCharacter(); |
69 | |
70 | void supportsUcs4Character_data(); |
71 | void supportsUcs4Character(); |
72 | |
73 | void fromFont_data(); |
74 | void fromFont(); |
75 | |
76 | void copyConstructor_data(); |
77 | void copyConstructor(); |
78 | |
79 | void detach_data(); |
80 | void detach(); |
81 | |
82 | void unsupportedWritingSystem_data(); |
83 | void unsupportedWritingSystem(); |
84 | |
85 | void rawFontSetPixelSize_data(); |
86 | void rawFontSetPixelSize(); |
87 | |
88 | void multipleRawFontsFromData(); |
89 | |
90 | void rawFontFromInvalidData(); |
91 | |
92 | void kernedAdvances(); |
93 | |
94 | void fallbackFontsOrder(); |
95 | |
96 | void qtbug65923_partal_clone_data(); |
97 | void qtbug65923_partal_clone(); |
98 | |
99 | private: |
100 | QString testFont; |
101 | QString testFontBoldItalic; |
102 | QString testFontOs2V1; |
103 | #endif // QT_NO_RAWFONT |
104 | }; |
105 | |
106 | #if !defined(QT_NO_RAWFONT) |
107 | Q_DECLARE_METATYPE(QFont::HintingPreference) |
108 | Q_DECLARE_METATYPE(QFont::Style) |
109 | Q_DECLARE_METATYPE(QFont::Weight) |
110 | Q_DECLARE_METATYPE(QFontDatabase::WritingSystem) |
111 | |
112 | void tst_QRawFont::init() |
113 | { |
114 | } |
115 | |
116 | void tst_QRawFont::initTestCase() |
117 | { |
118 | testFont = QFINDTESTDATA("testfont.ttf" ); |
119 | testFontBoldItalic = QFINDTESTDATA("testfont_bold_italic.ttf" ); |
120 | testFontOs2V1 = QFINDTESTDATA("testfont_os2_v1.ttf" ); |
121 | if (testFont.isEmpty() || testFontBoldItalic.isEmpty()) |
122 | QFAIL("qrawfont unittest font files not found!" ); |
123 | |
124 | QFontDatabase database; |
125 | if (database.families().count() == 0) |
126 | QSKIP("No fonts available!!!" ); |
127 | } |
128 | |
129 | void tst_QRawFont::invalidRawFont() |
130 | { |
131 | QRawFont font; |
132 | QVERIFY(!font.isValid()); |
133 | QCOMPARE(font.pixelSize(), 0.0); |
134 | QVERIFY(font.familyName().isEmpty()); |
135 | QCOMPARE(font.style(), QFont::StyleNormal); |
136 | QCOMPARE(font.weight(), -1); |
137 | QCOMPARE(font.ascent(), 0.0); |
138 | QCOMPARE(font.descent(), 0.0); |
139 | QVERIFY(font.glyphIndexesForString(QLatin1String("Test" )).isEmpty()); |
140 | } |
141 | |
142 | void tst_QRawFont::explicitRawFontNotLoadedInDatabase_data() |
143 | { |
144 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
145 | |
146 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
147 | QTest::newRow(dataTag: "No hinting" ) << QFont::PreferNoHinting; |
148 | QTest::newRow(dataTag: "Vertical hinting" ) << QFont::PreferVerticalHinting; |
149 | QTest::newRow(dataTag: "Full hinting" ) << QFont::PreferFullHinting; |
150 | } |
151 | |
152 | void tst_QRawFont::explicitRawFontNotLoadedInDatabase() |
153 | { |
154 | QFETCH(QFont::HintingPreference, hintingPreference); |
155 | |
156 | QRawFont font(testFont, 10, hintingPreference); |
157 | QVERIFY(font.isValid()); |
158 | |
159 | QVERIFY(!QFontDatabase().families().contains(font.familyName())); |
160 | } |
161 | |
162 | void tst_QRawFont::explicitRawFontNotAvailableInSystem_data() |
163 | { |
164 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
165 | |
166 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
167 | QTest::newRow(dataTag: "No hinting" ) << QFont::PreferNoHinting; |
168 | QTest::newRow(dataTag: "Vertical hinting" ) << QFont::PreferVerticalHinting; |
169 | QTest::newRow(dataTag: "Full hinting" ) << QFont::PreferFullHinting; |
170 | } |
171 | |
172 | void tst_QRawFont::explicitRawFontNotAvailableInSystem() |
173 | { |
174 | QFETCH(QFont::HintingPreference, hintingPreference); |
175 | |
176 | QRawFont rawfont(testFont, 10, hintingPreference); |
177 | |
178 | { |
179 | QFont font(rawfont.familyName(), 10); |
180 | |
181 | QVERIFY(!font.exactMatch()); |
182 | QVERIFY(font.family() != QFontInfo(font).family()); |
183 | } |
184 | } |
185 | |
186 | void tst_QRawFont::correctFontData_data() |
187 | { |
188 | QTest::addColumn<QString>(name: "fileName" ); |
189 | QTest::addColumn<QString>(name: "expectedFamilyName" ); |
190 | QTest::addColumn<QFont::Style>(name: "style" ); |
191 | QTest::addColumn<QFont::Weight>(name: "weight" ); |
192 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
193 | QTest::addColumn<qreal>(name: "unitsPerEm" ); |
194 | QTest::addColumn<qreal>(name: "pixelSize" ); |
195 | QTest::addColumn<int>(name: "capHeight" ); |
196 | |
197 | int hintingPreferences[] = { |
198 | int(QFont::PreferDefaultHinting), |
199 | int(QFont::PreferNoHinting), |
200 | int(QFont::PreferVerticalHinting), |
201 | int(QFont::PreferFullHinting), |
202 | -1 |
203 | }; |
204 | int *hintingPreference = hintingPreferences; |
205 | |
206 | while (*hintingPreference >= 0) { |
207 | QString fileName = testFont; |
208 | QString title = fileName |
209 | + QLatin1String(": hintingPreference=" ) |
210 | + QString::number(*hintingPreference); |
211 | |
212 | QTest::newRow(qPrintable(title)) |
213 | << fileName |
214 | << QString::fromLatin1(str: "QtBidiTestFont" ) |
215 | << QFont::StyleNormal |
216 | << QFont::Normal |
217 | << QFont::HintingPreference(*hintingPreference) |
218 | << qreal(1000.0) |
219 | << qreal(10.0) |
220 | << 7; |
221 | |
222 | fileName = testFontBoldItalic; |
223 | title = fileName |
224 | + QLatin1String(": hintingPreference=" ) |
225 | + QString::number(*hintingPreference); |
226 | |
227 | QTest::newRow(qPrintable(title)) |
228 | << fileName |
229 | << QString::fromLatin1(str: "QtBidiTestFont" ) |
230 | << QFont::StyleItalic |
231 | << QFont::Bold |
232 | << QFont::HintingPreference(*hintingPreference) |
233 | << qreal(1000.0) |
234 | << qreal(10.0) |
235 | << 7; |
236 | |
237 | fileName = testFontOs2V1; |
238 | title = fileName |
239 | + QLatin1String(": hintingPreference=" ) |
240 | + QString::number(*hintingPreference); |
241 | |
242 | QTest::newRow(qPrintable(title)) |
243 | << fileName |
244 | << QString::fromLatin1(str: "QtBidiTestFont" ) |
245 | << QFont::StyleNormal |
246 | << QFont::Normal |
247 | << QFont::HintingPreference(*hintingPreference) |
248 | << qreal(1000.0) |
249 | << qreal(10.0) |
250 | << 7; |
251 | |
252 | ++hintingPreference; |
253 | } |
254 | } |
255 | |
256 | void tst_QRawFont::correctFontData() |
257 | { |
258 | QFETCH(QString, fileName); |
259 | QFETCH(QString, expectedFamilyName); |
260 | QFETCH(QFont::Style, style); |
261 | QFETCH(QFont::Weight, weight); |
262 | QFETCH(QFont::HintingPreference, hintingPreference); |
263 | QFETCH(qreal, unitsPerEm); |
264 | QFETCH(qreal, pixelSize); |
265 | QFETCH(int, capHeight); |
266 | |
267 | QRawFont font(fileName, 10, hintingPreference); |
268 | QVERIFY(font.isValid()); |
269 | |
270 | QCOMPARE(font.familyName(), expectedFamilyName); |
271 | QCOMPARE(font.style(), style); |
272 | QCOMPARE(font.weight(), int(weight)); |
273 | QCOMPARE(font.hintingPreference(), hintingPreference); |
274 | QCOMPARE(font.unitsPerEm(), unitsPerEm); |
275 | QCOMPARE(font.pixelSize(), pixelSize); |
276 | |
277 | // Some platforms return the actual fractional height of the |
278 | // H character when the value is missing from the OS/2 table, |
279 | // so we ceil it off to match (any touched pixel counts). |
280 | QCOMPARE(qCeil(font.capHeight()), capHeight); |
281 | } |
282 | |
283 | void tst_QRawFont::glyphIndices() |
284 | { |
285 | QRawFont font(testFont, 10); |
286 | QVERIFY(font.isValid()); |
287 | |
288 | QVector<quint32> glyphIndices = font.glyphIndexesForString(text: QLatin1String("Foobar" )); |
289 | QVector<quint32> expectedGlyphIndices; |
290 | expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; |
291 | |
292 | QCOMPARE(glyphIndices, expectedGlyphIndices); |
293 | |
294 | glyphIndices = font.glyphIndexesForString(text: QString()); |
295 | QVERIFY(glyphIndices.isEmpty()); |
296 | |
297 | QString str(QLatin1String("Foobar" )); |
298 | int numGlyphs = str.size(); |
299 | glyphIndices.resize(size: numGlyphs); |
300 | |
301 | QVERIFY(!font.glyphIndexesForChars(str.constData(), 0, glyphIndices.data(), &numGlyphs)); |
302 | QCOMPARE(numGlyphs, 0); |
303 | |
304 | QVERIFY(!font.glyphIndexesForChars(str.constData(), str.size(), glyphIndices.data(), &numGlyphs)); |
305 | QCOMPARE(numGlyphs, str.size()); |
306 | |
307 | QVERIFY(font.glyphIndexesForChars(str.constData(), str.size(), glyphIndices.data(), &numGlyphs)); |
308 | QCOMPARE(numGlyphs, str.size()); |
309 | |
310 | QCOMPARE(glyphIndices, expectedGlyphIndices); |
311 | } |
312 | |
313 | void tst_QRawFont::advances_data() |
314 | { |
315 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
316 | |
317 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
318 | QTest::newRow(dataTag: "No hinting" ) << QFont::PreferNoHinting; |
319 | QTest::newRow(dataTag: "Vertical hinting" ) << QFont::PreferVerticalHinting; |
320 | QTest::newRow(dataTag: "Full hinting" ) << QFont::PreferFullHinting; |
321 | } |
322 | |
323 | void tst_QRawFont::advances() |
324 | { |
325 | QFETCH(QFont::HintingPreference, hintingPreference); |
326 | |
327 | QRawFont font(testFont, 10, hintingPreference); |
328 | QVERIFY(font.isValid()); |
329 | |
330 | QRawFontPrivate *font_d = QRawFontPrivate::get(font); |
331 | QVERIFY(font_d->fontEngine != 0); |
332 | |
333 | QVector<quint32> glyphIndices; |
334 | glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar" |
335 | |
336 | bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions(); |
337 | QVector<QPointF> advances = font.advancesForGlyphIndexes(glyphIndexes: glyphIndices); |
338 | |
339 | bool mayDiffer = font_d->fontEngine->type() == QFontEngine::Freetype |
340 | && (hintingPreference == QFont::PreferFullHinting |
341 | || hintingPreference == QFont::PreferDefaultHinting); |
342 | |
343 | for (int i = 0; i < glyphIndices.size(); ++i) { |
344 | if ((i == 0 || i == 5) && mayDiffer) { |
345 | QVERIFY2(qRound(advances.at(i).x()) == 8 |
346 | || qRound(advances.at(i).x()) == 9, |
347 | qPrintable(QStringLiteral("%1 != %2 && %1 != %3" ) |
348 | .arg(qRound(advances.at(i).x())) |
349 | .arg(8) |
350 | .arg(9))); |
351 | } else { |
352 | QCOMPARE(qRound(advances.at(i).x()), 8); |
353 | } |
354 | |
355 | if (supportsSubPixelPositions) |
356 | QVERIFY(advances.at(i).x() > 8.0); |
357 | |
358 | QVERIFY(qFuzzyIsNull(advances.at(i).y())); |
359 | } |
360 | |
361 | advances = font.advancesForGlyphIndexes(glyphIndexes: QVector<quint32>()); |
362 | QVERIFY(advances.isEmpty()); |
363 | |
364 | int numGlyphs = glyphIndices.size(); |
365 | advances.resize(size: numGlyphs); |
366 | |
367 | QVERIFY(!font.advancesForGlyphIndexes(glyphIndices.constData(), advances.data(), 0)); |
368 | |
369 | QVERIFY(font.advancesForGlyphIndexes(glyphIndices.constData(), advances.data(), numGlyphs)); |
370 | |
371 | for (int i = 0; i < glyphIndices.size(); ++i) { |
372 | if ((i == 0 || i == 5) && mayDiffer) { |
373 | QVERIFY2(qRound(advances.at(i).x()) == 8 |
374 | || qRound(advances.at(i).x()) == 9, |
375 | qPrintable(QStringLiteral("%1 != %2 && %1 != %3" ) |
376 | .arg(qRound(advances.at(i).x())) |
377 | .arg(8) |
378 | .arg(9))); |
379 | } else { |
380 | QCOMPARE(qRound(advances.at(i).x()), 8); |
381 | } |
382 | |
383 | if (supportsSubPixelPositions) |
384 | QVERIFY(advances.at(i).x() > 8.0); |
385 | |
386 | QVERIFY(qFuzzyIsNull(advances.at(i).y())); |
387 | } |
388 | } |
389 | |
390 | void tst_QRawFont::textLayout() |
391 | { |
392 | QFontDatabase fontDatabase; |
393 | int id = fontDatabase.addApplicationFont(fileName: testFont); |
394 | QVERIFY(id >= 0); |
395 | |
396 | QString familyName = QString::fromLatin1(str: "QtBidiTestFont" ); |
397 | QFont font(familyName); |
398 | font.setPixelSize(18.0); |
399 | QCOMPARE(QFontInfo(font).family(), familyName); |
400 | |
401 | QTextLayout layout(QLatin1String("Foobar" )); |
402 | layout.setFont(font); |
403 | layout.setCacheEnabled(true); |
404 | layout.beginLayout(); |
405 | layout.createLine(); |
406 | layout.endLayout(); |
407 | |
408 | QList<QGlyphRun> glyphRuns = layout.glyphRuns(); |
409 | QCOMPARE(glyphRuns.size(), 1); |
410 | |
411 | QGlyphRun glyphs = glyphRuns.at(i: 0); |
412 | |
413 | QRawFont rawFont = glyphs.rawFont(); |
414 | QVERIFY(rawFont.isValid()); |
415 | QCOMPARE(rawFont.familyName(), familyName); |
416 | QCOMPARE(rawFont.pixelSize(), 18.0); |
417 | |
418 | QVector<quint32> expectedGlyphIndices; |
419 | expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; |
420 | |
421 | QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices); |
422 | |
423 | QVERIFY(fontDatabase.removeApplicationFont(id)); |
424 | } |
425 | |
426 | void tst_QRawFont::fontTable_data() |
427 | { |
428 | QTest::addColumn<QByteArray>(name: "tagName" ); |
429 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
430 | QTest::addColumn<int>(name: "offset" ); |
431 | QTest::addColumn<quint32>(name: "expectedValue" ); |
432 | |
433 | QTest::newRow(dataTag: "Head table, magic number, default hinting" ) |
434 | << QByteArray("head" ) |
435 | << QFont::PreferDefaultHinting |
436 | << 12 |
437 | << (QSysInfo::ByteOrder == QSysInfo::BigEndian |
438 | ? 0x5F0F3CF5 |
439 | : 0xF53C0F5F); |
440 | |
441 | QTest::newRow(dataTag: "Head table, magic number, no hinting" ) |
442 | << QByteArray("head" ) |
443 | << QFont::PreferNoHinting |
444 | << 12 |
445 | << (QSysInfo::ByteOrder == QSysInfo::BigEndian |
446 | ? 0x5F0F3CF5 |
447 | : 0xF53C0F5F); |
448 | |
449 | QTest::newRow(dataTag: "Head table, magic number, vertical hinting" ) |
450 | << QByteArray("head" ) |
451 | << QFont::PreferVerticalHinting |
452 | << 12 |
453 | << (QSysInfo::ByteOrder == QSysInfo::BigEndian |
454 | ? 0x5F0F3CF5 |
455 | : 0xF53C0F5F); |
456 | |
457 | QTest::newRow(dataTag: "Head table, magic number, full hinting" ) |
458 | << QByteArray("head" ) |
459 | << QFont::PreferFullHinting |
460 | << 12 |
461 | << (QSysInfo::ByteOrder == QSysInfo::BigEndian |
462 | ? 0x5F0F3CF5 |
463 | : 0xF53C0F5F); |
464 | } |
465 | |
466 | void tst_QRawFont::fontTable() |
467 | { |
468 | QFETCH(QByteArray, tagName); |
469 | QFETCH(QFont::HintingPreference, hintingPreference); |
470 | QFETCH(int, offset); |
471 | QFETCH(quint32, expectedValue); |
472 | |
473 | QRawFont font(testFont, 10, hintingPreference); |
474 | QVERIFY(font.isValid()); |
475 | |
476 | QByteArray table = font.fontTable(tagName); |
477 | QVERIFY(!table.isEmpty()); |
478 | |
479 | const quint32 *value = reinterpret_cast<const quint32 *>(table.constData() + offset); |
480 | QCOMPARE(*value, expectedValue); |
481 | } |
482 | |
483 | typedef QList<QFontDatabase::WritingSystem> WritingSystemList; |
484 | Q_DECLARE_METATYPE(WritingSystemList) |
485 | |
486 | void tst_QRawFont::supportedWritingSystems_data() |
487 | { |
488 | QTest::addColumn<QString>(name: "fileName" ); |
489 | QTest::addColumn<WritingSystemList>(name: "writingSystems" ); |
490 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
491 | |
492 | for (int hintingPreference=QFont::PreferDefaultHinting; |
493 | hintingPreference<=QFont::PreferFullHinting; |
494 | ++hintingPreference) { |
495 | |
496 | QTest::newRow(qPrintable(QString::fromLatin1("testfont.ttf, hintingPreference=%1" ) |
497 | .arg(hintingPreference))) |
498 | << testFont |
499 | << (QList<QFontDatabase::WritingSystem>() |
500 | << QFontDatabase::Latin |
501 | << QFontDatabase::Hebrew |
502 | << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin |
503 | << QFont::HintingPreference(hintingPreference); |
504 | |
505 | QTest::newRow(qPrintable(QString::fromLatin1("testfont_bold_italic.ttf, hintingPreference=%1" ) |
506 | .arg(hintingPreference))) |
507 | << testFontBoldItalic |
508 | << (QList<QFontDatabase::WritingSystem>() |
509 | << QFontDatabase::Latin |
510 | << QFontDatabase::Hebrew |
511 | << QFontDatabase::Devanagari |
512 | << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin |
513 | << QFont::HintingPreference(hintingPreference); |
514 | } |
515 | } |
516 | |
517 | void tst_QRawFont::supportedWritingSystems() |
518 | { |
519 | QFETCH(QString, fileName); |
520 | QFETCH(WritingSystemList, writingSystems); |
521 | QFETCH(QFont::HintingPreference, hintingPreference); |
522 | |
523 | QRawFont font(fileName, 10, hintingPreference); |
524 | QVERIFY(font.isValid()); |
525 | |
526 | WritingSystemList actualWritingSystems = font.supportedWritingSystems(); |
527 | QCOMPARE(actualWritingSystems.size(), writingSystems.size()); |
528 | |
529 | foreach (QFontDatabase::WritingSystem writingSystem, writingSystems) |
530 | QVERIFY(actualWritingSystems.contains(writingSystem)); |
531 | } |
532 | |
533 | void tst_QRawFont::supportsCharacter_data() |
534 | { |
535 | QTest::addColumn<QString>(name: "fileName" ); |
536 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
537 | QTest::addColumn<QChar>(name: "character" ); |
538 | QTest::addColumn<bool>(name: "shouldBeSupported" ); |
539 | |
540 | const char *fileNames[2] = { |
541 | "testfont.ttf" , |
542 | "testfont_bold_italic.ttf" |
543 | }; |
544 | |
545 | for (int hintingPreference=QFont::PreferDefaultHinting; |
546 | hintingPreference<=QFont::PreferFullHinting; |
547 | ++hintingPreference) { |
548 | |
549 | for (int i=0; i<2; ++i) { |
550 | QString fileName = QFINDTESTDATA(fileNames[i]); |
551 | |
552 | // Latin text |
553 | for (char ch='!'; ch<='~'; ++ch) { |
554 | QString title = QString::fromLatin1(str: "%1, character=0x%2, hintingPreference=%3" ) |
555 | .arg(a: fileName).arg(a: QString::number(ch, base: 16)).arg(a: hintingPreference); |
556 | |
557 | QTest::newRow(qPrintable(title)) |
558 | << fileName |
559 | << QFont::HintingPreference(hintingPreference) |
560 | << QChar::fromLatin1(c: ch) |
561 | << true; |
562 | } |
563 | |
564 | // Hebrew text |
565 | for (quint16 ch=0x05D0; ch<=0x05EA; ++ch) { |
566 | QString title = QString::fromLatin1(str: "%1, character=0x%2, hintingPreference=%3" ) |
567 | .arg(a: fileName).arg(a: QString::number(ch, base: 16)).arg(a: hintingPreference); |
568 | |
569 | QTest::newRow(qPrintable(title)) |
570 | << fileName |
571 | << QFont::HintingPreference(hintingPreference) |
572 | << QChar(ch) |
573 | << true; |
574 | } |
575 | |
576 | QTest::newRow(qPrintable(QString::fromLatin1("Missing character, %1, hintingPreference=%2" ) |
577 | .arg(fileName).arg(hintingPreference))) |
578 | << fileName |
579 | << QFont::HintingPreference(hintingPreference) |
580 | << QChar(0xD8) |
581 | << false; |
582 | } |
583 | } |
584 | } |
585 | |
586 | void tst_QRawFont::supportsCharacter() |
587 | { |
588 | QFETCH(QString, fileName); |
589 | QFETCH(QFont::HintingPreference, hintingPreference); |
590 | QFETCH(QChar, character); |
591 | QFETCH(bool, shouldBeSupported); |
592 | |
593 | QRawFont font(fileName, 10, hintingPreference); |
594 | QVERIFY(font.isValid()); |
595 | |
596 | QCOMPARE(font.supportsCharacter(character), shouldBeSupported); |
597 | } |
598 | |
599 | void tst_QRawFont::supportsUcs4Character_data() |
600 | { |
601 | QTest::addColumn<QString>(name: "fileName" ); |
602 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
603 | QTest::addColumn<quint32>(name: "ucs4" ); |
604 | QTest::addColumn<bool>(name: "shouldBeSupported" ); |
605 | |
606 | // Gothic text |
607 | for (int hintingPreference=QFont::PreferDefaultHinting; |
608 | hintingPreference<=QFont::PreferFullHinting; |
609 | ++hintingPreference) { |
610 | for (quint32 ch=0x10330; ch<=0x1034A; ++ch) { |
611 | { |
612 | QString fileName = testFont; |
613 | QString title = QString::fromLatin1(str: "%1, character=0x%2, hintingPreference=%3" ) |
614 | .arg(a: fileName).arg(a: QString::number(ch, base: 16)).arg(a: hintingPreference); |
615 | |
616 | QTest::newRow(qPrintable(title)) |
617 | << fileName |
618 | << QFont::HintingPreference(hintingPreference) |
619 | << ch |
620 | << true; |
621 | } |
622 | |
623 | { |
624 | QString fileName = testFontBoldItalic; |
625 | QString title = QString::fromLatin1(str: "%1, character=0x%2, hintingPreference=%3" ) |
626 | .arg(a: fileName).arg(a: QString::number(ch, base: 16)).arg(a: hintingPreference); |
627 | |
628 | QTest::newRow(qPrintable(title)) |
629 | << fileName |
630 | << QFont::HintingPreference(hintingPreference) |
631 | << ch |
632 | << false; |
633 | } |
634 | } |
635 | } |
636 | } |
637 | |
638 | void tst_QRawFont::supportsUcs4Character() |
639 | { |
640 | QFETCH(QString, fileName); |
641 | QFETCH(QFont::HintingPreference, hintingPreference); |
642 | QFETCH(quint32, ucs4); |
643 | QFETCH(bool, shouldBeSupported); |
644 | |
645 | QRawFont font(fileName, 10, hintingPreference); |
646 | QVERIFY(font.isValid()); |
647 | |
648 | QCOMPARE(font.supportsCharacter(ucs4), shouldBeSupported); |
649 | } |
650 | |
651 | void tst_QRawFont::fromFont_data() |
652 | { |
653 | QTest::addColumn<QString>(name: "fileName" ); |
654 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
655 | QTest::addColumn<QString>(name: "familyName" ); |
656 | QTest::addColumn<QFontDatabase::WritingSystem>(name: "writingSystem" ); |
657 | QTest::addColumn<QFont::StyleStrategy>(name: "styleStrategy" ); |
658 | |
659 | for (int i=QFont::PreferDefaultHinting; i<=QFont::PreferFullHinting; ++i) { |
660 | QString titleBase = QString::fromLatin1(str: "%2, hintingPreference=%1, writingSystem=%3" ) |
661 | .arg(a: i); |
662 | { |
663 | QString fileName = testFont; |
664 | QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any; |
665 | |
666 | QString title = titleBase.arg(a: fileName).arg(a: writingSystem); |
667 | QTest::newRow(qPrintable(title)) |
668 | << fileName |
669 | << QFont::HintingPreference(i) |
670 | << "QtBidiTestFont" |
671 | << writingSystem |
672 | << QFont::PreferDefault; |
673 | } |
674 | |
675 | { |
676 | QString fileName = testFont; |
677 | QFontDatabase::WritingSystem writingSystem = QFontDatabase::Hebrew; |
678 | |
679 | QString title = titleBase.arg(a: fileName).arg(a: writingSystem); |
680 | QTest::newRow(qPrintable(title)) |
681 | << fileName |
682 | << QFont::HintingPreference(i) |
683 | << "QtBidiTestFont" |
684 | << writingSystem |
685 | << QFont::PreferDefault; |
686 | } |
687 | |
688 | { |
689 | QString fileName = testFont; |
690 | QFontDatabase::WritingSystem writingSystem = QFontDatabase::Latin; |
691 | |
692 | QString title = titleBase.arg(a: fileName).arg(a: writingSystem); |
693 | QTest::newRow(qPrintable(title)) |
694 | << fileName |
695 | << QFont::HintingPreference(i) |
696 | << "QtBidiTestFont" |
697 | << writingSystem |
698 | << QFont::PreferDefault; |
699 | } |
700 | } |
701 | |
702 | { |
703 | QString fileName = testFont; |
704 | QFontDatabase::WritingSystem writingSystem = QFontDatabase::Arabic; |
705 | |
706 | QString title = QStringLiteral("No font merging + unsupported script" ); |
707 | QTest::newRow(qPrintable(title)) |
708 | << fileName |
709 | << QFont::PreferDefaultHinting |
710 | << "QtBidiTestFont" |
711 | << writingSystem |
712 | << QFont::NoFontMerging; |
713 | } |
714 | |
715 | } |
716 | |
717 | void tst_QRawFont::fromFont() |
718 | { |
719 | QFETCH(QString, fileName); |
720 | QFETCH(QFont::HintingPreference, hintingPreference); |
721 | QFETCH(QString, familyName); |
722 | QFETCH(QFontDatabase::WritingSystem, writingSystem); |
723 | QFETCH(QFont::StyleStrategy, styleStrategy); |
724 | |
725 | QFontDatabase fontDatabase; |
726 | int id = fontDatabase.addApplicationFont(fileName); |
727 | QVERIFY(id >= 0); |
728 | |
729 | QFont font(familyName); |
730 | font.setHintingPreference(hintingPreference); |
731 | font.setPixelSize(26.0); |
732 | if (styleStrategy != QFont::PreferDefault) |
733 | font.setStyleStrategy(styleStrategy); |
734 | |
735 | QRawFont rawFont = QRawFont::fromFont(font, writingSystem); |
736 | QVERIFY(rawFont.isValid()); |
737 | |
738 | QCOMPARE(rawFont.familyName(), familyName); |
739 | QCOMPARE(rawFont.pixelSize(), 26.0); |
740 | |
741 | QVERIFY(fontDatabase.removeApplicationFont(id)); |
742 | } |
743 | |
744 | void tst_QRawFont::copyConstructor_data() |
745 | { |
746 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
747 | |
748 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
749 | QTest::newRow(dataTag: "No hinting preference" ) << QFont::PreferNoHinting; |
750 | QTest::newRow(dataTag: "Vertical hinting preference" ) << QFont::PreferVerticalHinting; |
751 | QTest::newRow(dataTag: "Full hinting preference" ) << QFont::PreferFullHinting; |
752 | } |
753 | |
754 | void tst_QRawFont::copyConstructor() |
755 | { |
756 | QFETCH(QFont::HintingPreference, hintingPreference); |
757 | |
758 | { |
759 | QString rawFontFamilyName; |
760 | qreal rawFontPixelSize; |
761 | qreal rawFontAscent; |
762 | qreal rawFontDescent; |
763 | int rawFontTableSize; |
764 | |
765 | QRawFont outerRawFont; |
766 | { |
767 | QRawFont rawFont(testFont, 11, hintingPreference); |
768 | QVERIFY(rawFont.isValid()); |
769 | |
770 | rawFontFamilyName = rawFont.familyName(); |
771 | rawFontPixelSize = rawFont.pixelSize(); |
772 | rawFontAscent = rawFont.ascent(); |
773 | rawFontDescent = rawFont.descent(); |
774 | rawFontTableSize = rawFont.fontTable(tagName: "glyf" ).size(); |
775 | QVERIFY(rawFontTableSize > 0); |
776 | |
777 | { |
778 | QRawFont otherRawFont(rawFont); |
779 | QVERIFY(otherRawFont.isValid()); |
780 | QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); |
781 | QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); |
782 | QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); |
783 | QCOMPARE(otherRawFont.ascent(), rawFontAscent); |
784 | QCOMPARE(otherRawFont.descent(), rawFontDescent); |
785 | QCOMPARE(otherRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
786 | } |
787 | |
788 | { |
789 | QRawFont otherRawFont = rawFont; |
790 | QVERIFY(otherRawFont.isValid()); |
791 | QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); |
792 | QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); |
793 | QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); |
794 | QCOMPARE(otherRawFont.ascent(), rawFontAscent); |
795 | QCOMPARE(otherRawFont.descent(), rawFontDescent); |
796 | QCOMPARE(otherRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
797 | } |
798 | |
799 | outerRawFont = rawFont; |
800 | } |
801 | |
802 | QVERIFY(outerRawFont.isValid()); |
803 | QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize); |
804 | QCOMPARE(outerRawFont.familyName(), rawFontFamilyName); |
805 | QCOMPARE(outerRawFont.hintingPreference(), hintingPreference); |
806 | QCOMPARE(outerRawFont.ascent(), rawFontAscent); |
807 | QCOMPARE(outerRawFont.descent(), rawFontDescent); |
808 | QCOMPARE(outerRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
809 | } |
810 | } |
811 | |
812 | void tst_QRawFont::detach_data() |
813 | { |
814 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
815 | |
816 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
817 | QTest::newRow(dataTag: "No hinting preference" ) << QFont::PreferNoHinting; |
818 | QTest::newRow(dataTag: "Vertical hinting preference" ) << QFont::PreferVerticalHinting; |
819 | QTest::newRow(dataTag: "Full hinting preference" ) << QFont::PreferFullHinting; |
820 | } |
821 | |
822 | void tst_QRawFont::detach() |
823 | { |
824 | QFETCH(QFont::HintingPreference, hintingPreference); |
825 | |
826 | { |
827 | QString rawFontFamilyName; |
828 | qreal rawFontPixelSize; |
829 | qreal rawFontAscent; |
830 | qreal rawFontDescent; |
831 | int rawFontTableSize; |
832 | |
833 | QRawFont outerRawFont; |
834 | { |
835 | QRawFont rawFont(testFont, 11, hintingPreference); |
836 | QVERIFY(rawFont.isValid()); |
837 | |
838 | rawFontFamilyName = rawFont.familyName(); |
839 | rawFontPixelSize = rawFont.pixelSize(); |
840 | rawFontAscent = rawFont.ascent(); |
841 | rawFontDescent = rawFont.descent(); |
842 | rawFontTableSize = rawFont.fontTable(tagName: "glyf" ).size(); |
843 | QVERIFY(rawFontTableSize > 0); |
844 | |
845 | { |
846 | QRawFont otherRawFont(rawFont); |
847 | |
848 | otherRawFont.loadFromFile(fileName: testFont, pixelSize: rawFontPixelSize, hintingPreference); |
849 | |
850 | QVERIFY(otherRawFont.isValid()); |
851 | QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); |
852 | QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); |
853 | QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); |
854 | QCOMPARE(otherRawFont.ascent(), rawFontAscent); |
855 | QCOMPARE(otherRawFont.descent(), rawFontDescent); |
856 | QCOMPARE(otherRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
857 | } |
858 | |
859 | { |
860 | QRawFont otherRawFont = rawFont; |
861 | |
862 | otherRawFont.loadFromFile(fileName: testFont, pixelSize: rawFontPixelSize, hintingPreference); |
863 | |
864 | QVERIFY(otherRawFont.isValid()); |
865 | QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); |
866 | QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); |
867 | QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); |
868 | QCOMPARE(otherRawFont.ascent(), rawFontAscent); |
869 | QCOMPARE(otherRawFont.descent(), rawFontDescent); |
870 | QCOMPARE(otherRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
871 | } |
872 | |
873 | outerRawFont = rawFont; |
874 | |
875 | rawFont.loadFromFile(fileName: testFont, pixelSize: rawFontPixelSize, hintingPreference); |
876 | } |
877 | |
878 | QVERIFY(outerRawFont.isValid()); |
879 | QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize); |
880 | QCOMPARE(outerRawFont.familyName(), rawFontFamilyName); |
881 | QCOMPARE(outerRawFont.hintingPreference(), hintingPreference); |
882 | QCOMPARE(outerRawFont.ascent(), rawFontAscent); |
883 | QCOMPARE(outerRawFont.descent(), rawFontDescent); |
884 | QCOMPARE(outerRawFont.fontTable("glyf" ).size(), rawFontTableSize); |
885 | } |
886 | } |
887 | |
888 | void tst_QRawFont::unsupportedWritingSystem_data() |
889 | { |
890 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
891 | |
892 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
893 | QTest::newRow(dataTag: "No hinting preference" ) << QFont::PreferNoHinting; |
894 | QTest::newRow(dataTag: "Vertical hinting preference" ) << QFont::PreferVerticalHinting; |
895 | QTest::newRow(dataTag: "Full hinting preference" ) << QFont::PreferFullHinting; |
896 | } |
897 | |
898 | void tst_QRawFont::unsupportedWritingSystem() |
899 | { |
900 | QFETCH(QFont::HintingPreference, hintingPreference); |
901 | |
902 | QFontDatabase fontDatabase; |
903 | int id = fontDatabase.addApplicationFont(fileName: testFont); |
904 | |
905 | QFont font("QtBidiTestFont" ); |
906 | font.setHintingPreference(hintingPreference); |
907 | font.setPixelSize(12.0); |
908 | |
909 | QRawFont rawFont = QRawFont::fromFont(font, writingSystem: QFontDatabase::Any); |
910 | QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont" )); |
911 | QCOMPARE(rawFont.pixelSize(), 12.0); |
912 | |
913 | rawFont = QRawFont::fromFont(font, writingSystem: QFontDatabase::Hebrew); |
914 | QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont" )); |
915 | QCOMPARE(rawFont.pixelSize(), 12.0); |
916 | |
917 | QString arabicText = QFontDatabase::writingSystemSample(writingSystem: QFontDatabase::Arabic).simplified().remove(c: QLatin1Char(' ')); |
918 | |
919 | QTextLayout layout; |
920 | layout.setFont(font); |
921 | layout.setText(arabicText); |
922 | layout.setCacheEnabled(true); |
923 | layout.beginLayout(); |
924 | layout.createLine(); |
925 | layout.endLayout(); |
926 | |
927 | QList<QGlyphRun> glyphRuns = layout.glyphRuns(); |
928 | QCOMPARE(glyphRuns.size(), 1); |
929 | |
930 | QGlyphRun glyphs = glyphRuns.at(i: 0); |
931 | QRawFont layoutFont = glyphs.rawFont(); |
932 | QVERIFY(layoutFont.familyName() != QString::fromLatin1("QtBidiTestFont" )); |
933 | QCOMPARE(layoutFont.pixelSize(), 12.0); |
934 | |
935 | rawFont = QRawFont::fromFont(font, writingSystem: QFontDatabase::Arabic); |
936 | QCOMPARE(rawFont.familyName(), layoutFont.familyName()); |
937 | QCOMPARE(rawFont.pixelSize(), 12.0); |
938 | |
939 | fontDatabase.removeApplicationFont(id); |
940 | } |
941 | |
942 | void tst_QRawFont::rawFontSetPixelSize_data() |
943 | { |
944 | QTest::addColumn<QFont::HintingPreference>(name: "hintingPreference" ); |
945 | |
946 | QTest::newRow(dataTag: "Default hinting preference" ) << QFont::PreferDefaultHinting; |
947 | QTest::newRow(dataTag: "No hinting preference" ) << QFont::PreferNoHinting; |
948 | QTest::newRow(dataTag: "Vertical hinting preference" ) << QFont::PreferVerticalHinting; |
949 | QTest::newRow(dataTag: "Full hinting preference" ) << QFont::PreferFullHinting; |
950 | } |
951 | |
952 | void tst_QRawFont::rawFontSetPixelSize() |
953 | { |
954 | QFETCH(QFont::HintingPreference, hintingPreference); |
955 | |
956 | QTextLayout layout("Foobar" ); |
957 | |
958 | QFont font = layout.font(); |
959 | font.setHintingPreference(hintingPreference); |
960 | font.setPixelSize(12); |
961 | layout.setFont(font); |
962 | |
963 | layout.setCacheEnabled(true); |
964 | layout.beginLayout(); |
965 | layout.createLine(); |
966 | layout.endLayout(); |
967 | |
968 | QGlyphRun glyphs = layout.glyphRuns().at(i: 0); |
969 | QRawFont rawFont = glyphs.rawFont(); |
970 | QCOMPARE(rawFont.pixelSize(), 12.0); |
971 | |
972 | rawFont.setPixelSize(24); |
973 | QCOMPARE(rawFont.pixelSize(), 24.0); |
974 | } |
975 | |
976 | void tst_QRawFont::multipleRawFontsFromData() |
977 | { |
978 | QFile file(testFont); |
979 | QRawFont testFont; |
980 | if (file.open(flags: QIODevice::ReadOnly)) { |
981 | testFont.loadFromData(fontData: file.readAll(), pixelSize: 11, hintingPreference: QFont::PreferDefaultHinting); |
982 | file.close(); |
983 | } |
984 | file.setFileName(testFontBoldItalic); |
985 | QRawFont testFontBoldItalic; |
986 | if (file.open(flags: QIODevice::ReadOnly)) |
987 | testFontBoldItalic.loadFromData(fontData: file.readAll(), pixelSize: 11, hintingPreference: QFont::PreferDefaultHinting); |
988 | |
989 | QVERIFY(testFont.familyName() != (testFontBoldItalic.familyName()) |
990 | || testFont.style() != (testFontBoldItalic.style())); |
991 | } |
992 | |
993 | void tst_QRawFont::rawFontFromInvalidData() |
994 | { |
995 | QByteArray invalidData("foobar" ); |
996 | QRawFont font; |
997 | font.loadFromData(fontData: invalidData, pixelSize: 10, hintingPreference: QFont::PreferDefaultHinting); |
998 | |
999 | QVERIFY(!font.isValid()); |
1000 | |
1001 | invalidData.fill(c: char(255), size: 1024); |
1002 | font.loadFromData(fontData: invalidData, pixelSize: 10, hintingPreference: QFont::PreferDefaultHinting); |
1003 | |
1004 | QVERIFY(!font.isValid()); |
1005 | } |
1006 | |
1007 | #define FUZZY_LTEQ(X, Y) (X < Y || qFuzzyCompare(X, Y)) |
1008 | |
1009 | void tst_QRawFont::kernedAdvances() |
1010 | { |
1011 | const int emSquareSize = 1000; |
1012 | const qreal pixelSize = 16.0; |
1013 | const int underScoreAW = 500; |
1014 | const int underscoreTwoKerning = -500; |
1015 | const qreal errorMargin = 1.0 / 16.0; // Fixed point error margin |
1016 | |
1017 | QRawFont font(testFont, pixelSize); |
1018 | QVERIFY(font.isValid()); |
1019 | |
1020 | QVector<quint32> glyphIndexes = font.glyphIndexesForString(QStringLiteral("__" )); |
1021 | QCOMPARE(glyphIndexes.size(), 2); |
1022 | |
1023 | QVector<QPointF> advances = font.advancesForGlyphIndexes(glyphIndexes, layoutFlags: QRawFont::KernedAdvances); |
1024 | QCOMPARE(advances.size(), 2); |
1025 | |
1026 | qreal expectedAdvanceWidth = pixelSize * underScoreAW / emSquareSize; |
1027 | QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin)); |
1028 | |
1029 | glyphIndexes = font.glyphIndexesForString(QStringLiteral("_2" )); |
1030 | QCOMPARE(glyphIndexes.size(), 2); |
1031 | |
1032 | advances = font.advancesForGlyphIndexes(glyphIndexes, layoutFlags: QRawFont::KernedAdvances); |
1033 | QCOMPARE(advances.size(), 2); |
1034 | |
1035 | expectedAdvanceWidth = pixelSize * (underScoreAW + underscoreTwoKerning) / emSquareSize; |
1036 | QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin)); |
1037 | } |
1038 | |
1039 | void tst_QRawFont::fallbackFontsOrder() |
1040 | { |
1041 | QFontDatabase fontDatabase; |
1042 | int id = fontDatabase.addApplicationFont(fileName: testFont); |
1043 | |
1044 | QFont font("QtBidiTestFont" ); |
1045 | font.setPixelSize(12.0); |
1046 | |
1047 | QString arabicText = QFontDatabase::writingSystemSample(writingSystem: QFontDatabase::Arabic); |
1048 | |
1049 | // If this fails, then the writing system sample has changed and we need to create |
1050 | // a new text containing both a space and Arabic characters. |
1051 | QVERIFY(arabicText.contains(QLatin1Char(' '))); |
1052 | |
1053 | QTextLayout layout; |
1054 | layout.setFont(font); |
1055 | layout.setText(arabicText); |
1056 | layout.setCacheEnabled(true); |
1057 | layout.beginLayout(); |
1058 | layout.createLine(); |
1059 | layout.endLayout(); |
1060 | |
1061 | QList<QGlyphRun> glyphRuns = layout.glyphRuns(); |
1062 | |
1063 | #ifdef Q_OS_ANDROID |
1064 | QEXPECT_FAIL("" , "QTBUG-69217" , Continue); |
1065 | #endif |
1066 | // Since QtBidiTestFont does not support Arabic nor the space, both should map to |
1067 | // the same font. If this fails, it is an indication that the list of fallbacks fonts |
1068 | // is not sorted by writing system support. |
1069 | QCOMPARE(glyphRuns.size(), 1); |
1070 | |
1071 | fontDatabase.removeApplicationFont(id); |
1072 | } |
1073 | |
1074 | void tst_QRawFont::qtbug65923_partal_clone_data() |
1075 | { |
1076 | QTest::addColumn<bool>(name: "shouldClone" ); |
1077 | |
1078 | QTest::newRow(dataTag: "Without cloning font engine" ) << false; |
1079 | QTest::newRow(dataTag: "Cloning font engine" ) << true; |
1080 | } |
1081 | |
1082 | void tst_QRawFont::qtbug65923_partal_clone() |
1083 | { |
1084 | QFile file(testFont); |
1085 | file.open(flags: QIODevice::ReadOnly); |
1086 | QByteArray fontData = file.readAll(); |
1087 | |
1088 | QRawFont outerFont; |
1089 | |
1090 | { |
1091 | QRawFont innerFont(fontData, 16, QFont::PreferDefaultHinting); |
1092 | |
1093 | QFETCH(bool, shouldClone); |
1094 | if (shouldClone) { |
1095 | // This will trigger QFontEngine::cloneWithSize |
1096 | innerFont.setPixelSize(innerFont.pixelSize() + 1); |
1097 | } |
1098 | |
1099 | outerFont = innerFont; |
1100 | } |
1101 | |
1102 | // This will detach if data is shared with the raw font. If the raw font has |
1103 | // a naked reference to the data, without informing Qt of it via the ref count |
1104 | // of the byte array, this will result in clearing 'live' data. |
1105 | fontData.fill(c: '\0'); |
1106 | |
1107 | QVERIFY(!outerFont.boundingRect(42).isEmpty()); |
1108 | } |
1109 | |
1110 | #endif // QT_NO_RAWFONT |
1111 | |
1112 | QTEST_MAIN(tst_QRawFont) |
1113 | #include "tst_qrawfont.moc" |
1114 | |
1115 | |