Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 plugins of the Qt Toolkit. | - | ||||||||||||
7 | ** | - | ||||||||||||
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 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 Lesser General Public License Usage | - | ||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||
24 | ** | - | ||||||||||||
25 | ** GNU General Public License Usage | - | ||||||||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||
35 | ** | - | ||||||||||||
36 | ** $QT_END_LICENSE$ | - | ||||||||||||
37 | ** | - | ||||||||||||
38 | ****************************************************************************/ | - | ||||||||||||
39 | - | |||||||||||||
40 | #include "qfontconfigdatabase_p.h" | - | ||||||||||||
41 | #include "qfontenginemultifontconfig_p.h" | - | ||||||||||||
42 | - | |||||||||||||
43 | #include <QtCore/QList> | - | ||||||||||||
44 | #include <QtCore/QElapsedTimer> | - | ||||||||||||
45 | #include <QtCore/QFile> | - | ||||||||||||
46 | - | |||||||||||||
47 | #include <qpa/qplatformnativeinterface.h> | - | ||||||||||||
48 | #include <qpa/qplatformscreen.h> | - | ||||||||||||
49 | #include <qpa/qplatformintegration.h> | - | ||||||||||||
50 | #include <qpa/qplatformservices.h> | - | ||||||||||||
51 | - | |||||||||||||
52 | #include <QtGui/private/qfontengine_ft_p.h> | - | ||||||||||||
53 | #include <QtGui/private/qguiapplication_p.h> | - | ||||||||||||
54 | #include <QtGui/private/qhighdpiscaling_p.h> | - | ||||||||||||
55 | - | |||||||||||||
56 | #include <QtGui/qguiapplication.h> | - | ||||||||||||
57 | - | |||||||||||||
58 | #include <fontconfig/fontconfig.h> | - | ||||||||||||
59 | #if FC_VERSION >= 20402 | - | ||||||||||||
60 | #include <fontconfig/fcfreetype.h> | - | ||||||||||||
61 | #endif | - | ||||||||||||
62 | - | |||||||||||||
63 | QT_BEGIN_NAMESPACE | - | ||||||||||||
64 | - | |||||||||||||
65 | static const int maxWeight = 99; | - | ||||||||||||
66 | - | |||||||||||||
67 | static inline int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper) | - | ||||||||||||
68 | { | - | ||||||||||||
69 | return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower); | - | ||||||||||||
70 | } | - | ||||||||||||
71 | - | |||||||||||||
72 | static inline int weightFromFcWeight(int fcweight) | - | ||||||||||||
73 | { | - | ||||||||||||
74 | // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from | - | ||||||||||||
75 | // 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from | - | ||||||||||||
76 | // Font Config values to Qt would give surprising results. So, we do a piecewise linear | - | ||||||||||||
77 | // mapping. This ensures that where there is a corresponding enum on both sides (for example | - | ||||||||||||
78 | // FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map | - | ||||||||||||
79 | // to intermediate Qt weights. | - | ||||||||||||
80 | - | |||||||||||||
81 | if (fcweight <= FC_WEIGHT_THIN) | - | ||||||||||||
82 | return QFont::Thin; | - | ||||||||||||
83 | if (fcweight <= FC_WEIGHT_ULTRALIGHT) | - | ||||||||||||
84 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT, QFont::Thin, QFont::ExtraLight); | - | ||||||||||||
85 | if (fcweight <= FC_WEIGHT_LIGHT) | - | ||||||||||||
86 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT, QFont::ExtraLight, QFont::Light); | - | ||||||||||||
87 | if (fcweight <= FC_WEIGHT_NORMAL) | - | ||||||||||||
88 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_LIGHT, FC_WEIGHT_NORMAL, QFont::Light, QFont::Normal); | - | ||||||||||||
89 | if (fcweight <= FC_WEIGHT_MEDIUM) | - | ||||||||||||
90 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_NORMAL, FC_WEIGHT_MEDIUM, QFont::Normal, QFont::Medium); | - | ||||||||||||
91 | if (fcweight <= FC_WEIGHT_DEMIBOLD) | - | ||||||||||||
92 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD, QFont::Medium, QFont::DemiBold); | - | ||||||||||||
93 | if (fcweight <= FC_WEIGHT_BOLD) | - | ||||||||||||
94 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD, QFont::DemiBold, QFont::Bold); | - | ||||||||||||
95 | if (fcweight <= FC_WEIGHT_ULTRABOLD) | - | ||||||||||||
96 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD, QFont::Bold, QFont::ExtraBold); | - | ||||||||||||
97 | if (fcweight <= FC_WEIGHT_BLACK) | - | ||||||||||||
98 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK, QFont::ExtraBold, QFont::Black); | - | ||||||||||||
99 | if (fcweight <= FC_WEIGHT_ULTRABLACK) | - | ||||||||||||
100 | return mapToQtWeightForRange(fcweight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK, QFont::Black, maxWeight); | - | ||||||||||||
101 | return maxWeight; | - | ||||||||||||
102 | } | - | ||||||||||||
103 | - | |||||||||||||
104 | static inline int stretchFromFcWidth(int fcwidth) | - | ||||||||||||
105 | { | - | ||||||||||||
106 | // Font Config enums for width match pretty closely with those used by Qt so just use | - | ||||||||||||
107 | // Font Config values directly while enforcing the same limits imposed by QFont. | - | ||||||||||||
108 | const int maxStretch = 4000; | - | ||||||||||||
109 | int qtstretch; | - | ||||||||||||
110 | if (fcwidth < 1) | - | ||||||||||||
111 | qtstretch = 1; | - | ||||||||||||
112 | else if (fcwidth > maxStretch) | - | ||||||||||||
113 | qtstretch = maxStretch; | - | ||||||||||||
114 | else | - | ||||||||||||
115 | qtstretch = fcwidth; | - | ||||||||||||
116 | - | |||||||||||||
117 | return qtstretch; | - | ||||||||||||
118 | } | - | ||||||||||||
119 | - | |||||||||||||
120 | static const char specialLanguages[][6] = { | - | ||||||||||||
121 | "", // Unknown | - | ||||||||||||
122 | "", // Inherited | - | ||||||||||||
123 | "", // Common | - | ||||||||||||
124 | "en", // Latin | - | ||||||||||||
125 | "el", // Greek | - | ||||||||||||
126 | "ru", // Cyrillic | - | ||||||||||||
127 | "hy", // Armenian | - | ||||||||||||
128 | "he", // Hebrew | - | ||||||||||||
129 | "ar", // Arabic | - | ||||||||||||
130 | "syr", // Syriac | - | ||||||||||||
131 | "dv", // Thaana | - | ||||||||||||
132 | "hi", // Devanagari | - | ||||||||||||
133 | "bn", // Bengali | - | ||||||||||||
134 | "pa", // Gurmukhi | - | ||||||||||||
135 | "gu", // Gujarati | - | ||||||||||||
136 | "or", // Oriya | - | ||||||||||||
137 | "ta", // Tamil | - | ||||||||||||
138 | "te", // Telugu | - | ||||||||||||
139 | "kn", // Kannada | - | ||||||||||||
140 | "ml", // Malayalam | - | ||||||||||||
141 | "si", // Sinhala | - | ||||||||||||
142 | "th", // Thai | - | ||||||||||||
143 | "lo", // Lao | - | ||||||||||||
144 | "bo", // Tibetan | - | ||||||||||||
145 | "my", // Myanmar | - | ||||||||||||
146 | "ka", // Georgian | - | ||||||||||||
147 | "ko", // Hangul | - | ||||||||||||
148 | "am", // Ethiopic | - | ||||||||||||
149 | "chr", // Cherokee | - | ||||||||||||
150 | "cr", // CanadianAboriginal | - | ||||||||||||
151 | "sga", // Ogham | - | ||||||||||||
152 | "non", // Runic | - | ||||||||||||
153 | "km", // Khmer | - | ||||||||||||
154 | "mn", // Mongolian | - | ||||||||||||
155 | "ja", // Hiragana | - | ||||||||||||
156 | "ja", // Katakana | - | ||||||||||||
157 | "zh-TW", // Bopomofo | - | ||||||||||||
158 | "", // Han | - | ||||||||||||
159 | "ii", // Yi | - | ||||||||||||
160 | "ett", // OldItalic | - | ||||||||||||
161 | "got", // Gothic | - | ||||||||||||
162 | "en", // Deseret | - | ||||||||||||
163 | "fil", // Tagalog | - | ||||||||||||
164 | "hnn", // Hanunoo | - | ||||||||||||
165 | "bku", // Buhid | - | ||||||||||||
166 | "tbw", // Tagbanwa | - | ||||||||||||
167 | "cop", // Coptic | - | ||||||||||||
168 | "lif", // Limbu | - | ||||||||||||
169 | "tdd", // TaiLe | - | ||||||||||||
170 | "grc", // LinearB | - | ||||||||||||
171 | "uga", // Ugaritic | - | ||||||||||||
172 | "en", // Shavian | - | ||||||||||||
173 | "so", // Osmanya | - | ||||||||||||
174 | "grc", // Cypriot | - | ||||||||||||
175 | "", // Braille | - | ||||||||||||
176 | "bug", // Buginese | - | ||||||||||||
177 | "khb", // NewTaiLue | - | ||||||||||||
178 | "cu", // Glagolitic | - | ||||||||||||
179 | "shi", // Tifinagh | - | ||||||||||||
180 | "syl", // SylotiNagri | - | ||||||||||||
181 | "peo", // OldPersian | - | ||||||||||||
182 | "pra", // Kharoshthi | - | ||||||||||||
183 | "ban", // Balinese | - | ||||||||||||
184 | "akk", // Cuneiform | - | ||||||||||||
185 | "phn", // Phoenician | - | ||||||||||||
186 | "lzh", // PhagsPa | - | ||||||||||||
187 | "man", // Nko | - | ||||||||||||
188 | "su", // Sundanese | - | ||||||||||||
189 | "lep", // Lepcha | - | ||||||||||||
190 | "sat", // OlChiki | - | ||||||||||||
191 | "vai", // Vai | - | ||||||||||||
192 | "saz", // Saurashtra | - | ||||||||||||
193 | "eky", // KayahLi | - | ||||||||||||
194 | "rej", // Rejang | - | ||||||||||||
195 | "xlc", // Lycian | - | ||||||||||||
196 | "xcr", // Carian | - | ||||||||||||
197 | "xld", // Lydian | - | ||||||||||||
198 | "cjm", // Cham | - | ||||||||||||
199 | "nod", // TaiTham | - | ||||||||||||
200 | "blt", // TaiViet | - | ||||||||||||
201 | "ae", // Avestan | - | ||||||||||||
202 | "egy", // EgyptianHieroglyphs | - | ||||||||||||
203 | "smp", // Samaritan | - | ||||||||||||
204 | "lis", // Lisu | - | ||||||||||||
205 | "bax", // Bamum | - | ||||||||||||
206 | "jv", // Javanese | - | ||||||||||||
207 | "mni", // MeeteiMayek | - | ||||||||||||
208 | "arc", // ImperialAramaic | - | ||||||||||||
209 | "xsa", // OldSouthArabian | - | ||||||||||||
210 | "xpr", // InscriptionalParthian | - | ||||||||||||
211 | "pal", // InscriptionalPahlavi | - | ||||||||||||
212 | "otk", // OldTurkic | - | ||||||||||||
213 | "bh", // Kaithi | - | ||||||||||||
214 | "bbc", // Batak | - | ||||||||||||
215 | "pra", // Brahmi | - | ||||||||||||
216 | "myz", // Mandaic | - | ||||||||||||
217 | "ccp", // Chakma | - | ||||||||||||
218 | "xmr", // MeroiticCursive | - | ||||||||||||
219 | "xmr", // MeroiticHieroglyphs | - | ||||||||||||
220 | "hmd", // Miao | - | ||||||||||||
221 | "sa", // Sharada | - | ||||||||||||
222 | "srb", // SoraSompeng | - | ||||||||||||
223 | "doi", // Takri | - | ||||||||||||
224 | "lez", // CaucasianAlbanian | - | ||||||||||||
225 | "bsq", // BassaVah | - | ||||||||||||
226 | "fr", // Duployan | - | ||||||||||||
227 | "sq", // Elbasan | - | ||||||||||||
228 | "sa", // Grantha | - | ||||||||||||
229 | "hnj", // PahawhHmong | - | ||||||||||||
230 | "sd", // Khojki | - | ||||||||||||
231 | "lab", // LinearA | - | ||||||||||||
232 | "hi", // Mahajani | - | ||||||||||||
233 | "xmn", // Manichaean | - | ||||||||||||
234 | "men", // MendeKikakui | - | ||||||||||||
235 | "mr", // Modi | - | ||||||||||||
236 | "mru", // Mro | - | ||||||||||||
237 | "xna", // OldNorthArabian | - | ||||||||||||
238 | "arc", // Nabataean | - | ||||||||||||
239 | "arc", // Palmyrene | - | ||||||||||||
240 | "ctd", // PauCinHau | - | ||||||||||||
241 | "kv", // OldPermic | - | ||||||||||||
242 | "pal", // PsalterPahlavi | - | ||||||||||||
243 | "sa", // Siddham | - | ||||||||||||
244 | "sd", // Khudawadi | - | ||||||||||||
245 | "mai", // Tirhuta | - | ||||||||||||
246 | "hoc", // WarangCiti | - | ||||||||||||
247 | "", // Ahom | - | ||||||||||||
248 | "", // AnatolianHieroglyphs | - | ||||||||||||
249 | "", // Hatran | - | ||||||||||||
250 | "", // Multani | - | ||||||||||||
251 | "", // OldHungarian | - | ||||||||||||
252 | "" // SignWriting | - | ||||||||||||
253 | }; | - | ||||||||||||
254 | Q_STATIC_ASSERT(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount); | - | ||||||||||||
255 | - | |||||||||||||
256 | // this could become a list of all languages used for each writing | - | ||||||||||||
257 | // system, instead of using the single most common language. | - | ||||||||||||
258 | static const char languageForWritingSystem[][6] = { | - | ||||||||||||
259 | "", // Any | - | ||||||||||||
260 | "en", // Latin | - | ||||||||||||
261 | "el", // Greek | - | ||||||||||||
262 | "ru", // Cyrillic | - | ||||||||||||
263 | "hy", // Armenian | - | ||||||||||||
264 | "he", // Hebrew | - | ||||||||||||
265 | "ar", // Arabic | - | ||||||||||||
266 | "syr", // Syriac | - | ||||||||||||
267 | "div", // Thaana | - | ||||||||||||
268 | "hi", // Devanagari | - | ||||||||||||
269 | "bn", // Bengali | - | ||||||||||||
270 | "pa", // Gurmukhi | - | ||||||||||||
271 | "gu", // Gujarati | - | ||||||||||||
272 | "or", // Oriya | - | ||||||||||||
273 | "ta", // Tamil | - | ||||||||||||
274 | "te", // Telugu | - | ||||||||||||
275 | "kn", // Kannada | - | ||||||||||||
276 | "ml", // Malayalam | - | ||||||||||||
277 | "si", // Sinhala | - | ||||||||||||
278 | "th", // Thai | - | ||||||||||||
279 | "lo", // Lao | - | ||||||||||||
280 | "bo", // Tibetan | - | ||||||||||||
281 | "my", // Myanmar | - | ||||||||||||
282 | "ka", // Georgian | - | ||||||||||||
283 | "km", // Khmer | - | ||||||||||||
284 | "zh-cn", // SimplifiedChinese | - | ||||||||||||
285 | "zh-tw", // TraditionalChinese | - | ||||||||||||
286 | "ja", // Japanese | - | ||||||||||||
287 | "ko", // Korean | - | ||||||||||||
288 | "vi", // Vietnamese | - | ||||||||||||
289 | "", // Symbol | - | ||||||||||||
290 | "sga", // Ogham | - | ||||||||||||
291 | "non", // Runic | - | ||||||||||||
292 | "man" // N'Ko | - | ||||||||||||
293 | }; | - | ||||||||||||
294 | Q_STATIC_ASSERT(sizeof languageForWritingSystem / sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount); | - | ||||||||||||
295 | - | |||||||||||||
296 | #if FC_VERSION >= 20297 | - | ||||||||||||
297 | // Newer FontConfig let's us sort out fonts that report certain scripts support, | - | ||||||||||||
298 | // but no open type tables for handling them correctly. | - | ||||||||||||
299 | // Check the reported script presence in the FC_CAPABILITY's "otlayout:" section. | - | ||||||||||||
300 | static const char capabilityForWritingSystem[][5] = { | - | ||||||||||||
301 | "", // Any | - | ||||||||||||
302 | "", // Latin | - | ||||||||||||
303 | "", // Greek | - | ||||||||||||
304 | "", // Cyrillic | - | ||||||||||||
305 | "", // Armenian | - | ||||||||||||
306 | "", // Hebrew | - | ||||||||||||
307 | "", // Arabic | - | ||||||||||||
308 | "syrc", // Syriac | - | ||||||||||||
309 | "thaa", // Thaana | - | ||||||||||||
310 | "deva", // Devanagari | - | ||||||||||||
311 | "beng", // Bengali | - | ||||||||||||
312 | "guru", // Gurmukhi | - | ||||||||||||
313 | "gujr", // Gujarati | - | ||||||||||||
314 | "orya", // Oriya | - | ||||||||||||
315 | "taml", // Tamil | - | ||||||||||||
316 | "telu", // Telugu | - | ||||||||||||
317 | "knda", // Kannada | - | ||||||||||||
318 | "mlym", // Malayalam | - | ||||||||||||
319 | "sinh", // Sinhala | - | ||||||||||||
320 | "", // Thai | - | ||||||||||||
321 | "", // Lao | - | ||||||||||||
322 | "tibt", // Tibetan | - | ||||||||||||
323 | "mymr", // Myanmar | - | ||||||||||||
324 | "", // Georgian | - | ||||||||||||
325 | "khmr", // Khmer | - | ||||||||||||
326 | "", // SimplifiedChinese | - | ||||||||||||
327 | "", // TraditionalChinese | - | ||||||||||||
328 | "", // Japanese | - | ||||||||||||
329 | "", // Korean | - | ||||||||||||
330 | "", // Vietnamese | - | ||||||||||||
331 | "", // Symbol | - | ||||||||||||
332 | "", // Ogham | - | ||||||||||||
333 | "", // Runic | - | ||||||||||||
334 | "nko " // N'Ko | - | ||||||||||||
335 | }; | - | ||||||||||||
336 | Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount); | - | ||||||||||||
337 | #endif | - | ||||||||||||
338 | - | |||||||||||||
339 | static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) | - | ||||||||||||
340 | { | - | ||||||||||||
341 | const char *stylehint = 0; | - | ||||||||||||
342 | switch (style) { | - | ||||||||||||
343 | case QFont::SansSerif: | - | ||||||||||||
344 | stylehint = "sans-serif"; | - | ||||||||||||
345 | break; | - | ||||||||||||
346 | case QFont::Serif: | - | ||||||||||||
347 | stylehint = "serif"; | - | ||||||||||||
348 | break; | - | ||||||||||||
349 | case QFont::TypeWriter: | - | ||||||||||||
350 | case QFont::Monospace: | - | ||||||||||||
351 | stylehint = "monospace"; | - | ||||||||||||
352 | break; | - | ||||||||||||
353 | case QFont::Cursive: | - | ||||||||||||
354 | stylehint = "cursive"; | - | ||||||||||||
355 | break; | - | ||||||||||||
356 | case QFont::Fantasy: | - | ||||||||||||
357 | stylehint = "fantasy"; | - | ||||||||||||
358 | break; | - | ||||||||||||
359 | default: | - | ||||||||||||
360 | break; | - | ||||||||||||
361 | } | - | ||||||||||||
362 | return stylehint; | - | ||||||||||||
363 | } | - | ||||||||||||
364 | - | |||||||||||||
365 | static inline bool requiresOpenType(int writingSystem) | - | ||||||||||||
366 | { | - | ||||||||||||
367 | return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) | - | ||||||||||||
368 | || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); | - | ||||||||||||
369 | } | - | ||||||||||||
370 | - | |||||||||||||
371 | static void populateFromPattern(FcPattern *pattern) | - | ||||||||||||
372 | { | - | ||||||||||||
373 | QString familyName; | - | ||||||||||||
374 | QString familyNameLang; | - | ||||||||||||
375 | FcChar8 *value = 0; | - | ||||||||||||
376 | int weight_value; | - | ||||||||||||
377 | int slant_value; | - | ||||||||||||
378 | int spacing_value; | - | ||||||||||||
379 | int width_value; | - | ||||||||||||
380 | FcChar8 *file_value; | - | ||||||||||||
381 | int indexValue; | - | ||||||||||||
382 | FcChar8 *foundry_value; | - | ||||||||||||
383 | FcChar8 *style_value; | - | ||||||||||||
384 | FcBool scalable; | - | ||||||||||||
385 | FcBool antialias; | - | ||||||||||||
386 | - | |||||||||||||
387 | if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
| 0-20694 | ||||||||||||
388 | return; never executed: return; | 0 | ||||||||||||
389 | - | |||||||||||||
390 | familyName = QString::fromUtf8((const char *)value); | - | ||||||||||||
391 | - | |||||||||||||
392 | if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
| 7654-13040 | ||||||||||||
393 | familyNameLang executed 13040 times by 123 tests: = QString::fromUtf8((const char *)value);familyNameLang = QString::fromUtf8((const char *)value); Executed by:
executed 13040 times by 123 tests: familyNameLang = QString::fromUtf8((const char *)value); Executed by:
| 13040 | ||||||||||||
394 | - | |||||||||||||
395 | slant_value = FC_SLANT_ROMAN; | - | ||||||||||||
396 | weight_value = FC_WEIGHT_REGULAR; | - | ||||||||||||
397 | spacing_value = FC_PROPORTIONAL; | - | ||||||||||||
398 | file_value = 0; | - | ||||||||||||
399 | indexValue = 0; | - | ||||||||||||
400 | scalable = FcTrue; | - | ||||||||||||
401 | - | |||||||||||||
402 | - | |||||||||||||
403 | if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
| 0-20694 | ||||||||||||
404 | slant_value = FC_SLANT_ROMAN; never executed: slant_value = 0; | 0 | ||||||||||||
405 | if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
| 0-20694 | ||||||||||||
406 | weight_value = FC_WEIGHT_REGULAR; never executed: weight_value = 80; | 0 | ||||||||||||
407 | if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
| 0-20694 | ||||||||||||
408 | width_value = FC_WIDTH_NORMAL; never executed: width_value = 100; | 0 | ||||||||||||
409 | if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
| 3036-17658 | ||||||||||||
410 | spacing_value = FC_PROPORTIONAL; executed 17658 times by 123 tests: spacing_value = 0; Executed by:
| 17658 | ||||||||||||
411 | if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
| 0-20694 | ||||||||||||
412 | file_value = 0; never executed: file_value = 0; | 0 | ||||||||||||
413 | if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
| 0-20694 | ||||||||||||
414 | indexValue = 0; never executed: indexValue = 0; | 0 | ||||||||||||
415 | if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
| 0-20694 | ||||||||||||
416 | scalable = FcTrue; never executed: scalable = 1; | 0 | ||||||||||||
417 | if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
| 0-20694 | ||||||||||||
418 | foundry_value = 0; never executed: foundry_value = 0; | 0 | ||||||||||||
419 | if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
| 0-20694 | ||||||||||||
420 | style_value = 0; never executed: style_value = 0; | 0 | ||||||||||||
421 | if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
| 0-20694 | ||||||||||||
422 | antialias = true; executed 20694 times by 123 tests: antialias = true; Executed by:
| 20694 | ||||||||||||
423 | - | |||||||||||||
424 | QSupportedWritingSystems writingSystems; | - | ||||||||||||
425 | FcLangSet *langset = 0; | - | ||||||||||||
426 | FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); | - | ||||||||||||
427 | if (res == FcResultMatch) {
| 0-20694 | ||||||||||||
428 | bool hasLang = false; | - | ||||||||||||
429 | #if FC_VERSION >= 20297 | - | ||||||||||||
430 | FcChar8 *cap = Q_NULLPTR; | - | ||||||||||||
431 | FcResult capRes = FcResultNoMatch; | - | ||||||||||||
432 | #endif | - | ||||||||||||
433 | for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
| 20694-682902 | ||||||||||||
434 | const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; | - | ||||||||||||
435 | if (lang) {
| 0-682902 | ||||||||||||
436 | FcLangResult langRes = FcLangSetHasLang(langset, lang); | - | ||||||||||||
437 | if (langRes != FcLangDifferentLang) {
| 61268-621634 | ||||||||||||
438 | #if FC_VERSION >= 20297 | - | ||||||||||||
439 | if (*capabilityForWritingSystem[j] && requiresOpenType(j)) {
| 0-60378 | ||||||||||||
440 | if (cap == Q_NULLPTR)
| 0-890 | ||||||||||||
441 | capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); executed 890 times by 123 tests: capRes = FcPatternGetString(pattern, "capability", 0, &cap); Executed by:
| 890 | ||||||||||||
442 | if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0)
| 0-890 | ||||||||||||
443 | continue; executed 890 times by 123 tests: continue; Executed by:
| 890 | ||||||||||||
444 | } never executed: end of block | 0 | ||||||||||||
445 | #endif | - | ||||||||||||
446 | writingSystems.setSupported(QFontDatabase::WritingSystem(j)); | - | ||||||||||||
447 | hasLang = true; | - | ||||||||||||
448 | } executed 60378 times by 123 tests: end of block Executed by:
| 60378 | ||||||||||||
449 | } executed 682012 times by 123 tests: end of block Executed by:
| 682012 | ||||||||||||
450 | } executed 682012 times by 123 tests: end of block Executed by:
| 682012 | ||||||||||||
451 | if (!hasLang)
| 900-19794 | ||||||||||||
452 | // none of our known languages, add it to the other set | - | ||||||||||||
453 | writingSystems.setSupported(QFontDatabase::Other); executed 900 times by 123 tests: writingSystems.setSupported(QFontDatabase::Other); Executed by:
| 900 | ||||||||||||
454 | } else { executed 20694 times by 123 tests: end of block Executed by:
| 20694 | ||||||||||||
455 | // we set Other to supported for symbol fonts. It makes no | - | ||||||||||||
456 | // sense to merge these with other ones, as they are | - | ||||||||||||
457 | // special in a way. | - | ||||||||||||
458 | writingSystems.setSupported(QFontDatabase::Other); | - | ||||||||||||
459 | } never executed: end of block | 0 | ||||||||||||
460 | - | |||||||||||||
461 | FontFile *fontFile = new FontFile; | - | ||||||||||||
462 | fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); | - | ||||||||||||
463 | fontFile->indexValue = indexValue; | - | ||||||||||||
464 | - | |||||||||||||
465 | QFont::Style style = (slant_value == FC_SLANT_ITALIC)
| 6586-14108 | ||||||||||||
466 | ? QFont::StyleItalic | - | ||||||||||||
467 | : ((slant_value == FC_SLANT_OBLIQUE)
| 1780-12328 | ||||||||||||
468 | ? QFont::StyleOblique | - | ||||||||||||
469 | : QFont::StyleNormal); | - | ||||||||||||
470 | // Note: weight should really be an int but registerFont incorrectly uses an enum | - | ||||||||||||
471 | QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); | - | ||||||||||||
472 | - | |||||||||||||
473 | double pixel_size = 0; | - | ||||||||||||
474 | if (!scalable)
| 0-20694 | ||||||||||||
475 | FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); never executed: FcPatternGetDouble (pattern, "pixelsize", 0, &pixel_size); | 0 | ||||||||||||
476 | - | |||||||||||||
477 | bool fixedPitch = spacing_value >= FC_MONO; | - | ||||||||||||
478 | // Note: stretch should really be an int but registerFont incorrectly uses an enum | - | ||||||||||||
479 | QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); | - | ||||||||||||
480 | QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString();
| 0-20694 | ||||||||||||
481 | QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); | - | ||||||||||||
482 | // qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; | - | ||||||||||||
483 | - | |||||||||||||
484 | for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) QPlatformFontDatabase{
| 1602-20694 | ||||||||||||
485 | const QString altFamilyName = QString::registerAliasToFontFamilyfromUtf8((const char *)value); | - | ||||||||||||
486 | // Extra family names can be aliases or subfamilies. | - | ||||||||||||
487 | // If it is a subfamily, register it as a separate font, so only members of the subfamily are | - | ||||||||||||
488 | // matched when the subfamily is requested. | - | ||||||||||||
489 | QString altStyleName; | - | ||||||||||||
490 | if
| 178-1424 | ||||||||||||
491 | altStyleName = executed 1424 times by 123 tests: QString::fromUtf8((const char *)value)););altStyleName = QString::fromUtf8((const char *)value); Executed by:
executed 1424 times by 123 tests: altStyleName = QString::fromUtf8((const char *)value); Executed by:
| 1424 | ||||||||||||
492 | else | - | ||||||||||||
493 | altStyleName = styleName; executed 178 times by 123 tests: altStyleName = styleName; Executed by:
| 178 | ||||||||||||
494 | - | |||||||||||||
495 | QString altFamilyNameLang; | - | ||||||||||||
496 | if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch)
| 0-1602 | ||||||||||||
497 | altFamilyNameLang = QString::fromUtf8((const char *)value); executed 1602 times by 123 tests: altFamilyNameLang = QString::fromUtf8((const char *)value); Executed by:
| 1602 | ||||||||||||
498 | else | - | ||||||||||||
499 | altFamilyNameLang = familyNameLang; never executed: altFamilyNameLang = familyNameLang; | 0 | ||||||||||||
500 | - | |||||||||||||
501 | if (familyNameLang == altFamilyNameLang && altStyleName != styleName) {
| 0-1602 | ||||||||||||
502 | FontFile *altFontFile = new FontFile(*fontFile); | - | ||||||||||||
503 | QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile); | - | ||||||||||||
504 | } else { executed 1424 times by 123 tests: end of block Executed by:
| 1424 | ||||||||||||
505 | QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName); | - | ||||||||||||
506 | } executed 178 times by 123 tests: end of block Executed by:
| 178 | ||||||||||||
507 | } | - | ||||||||||||
508 | - | |||||||||||||
509 | } executed 20694 times by 123 tests: end of block Executed by:
| 20694 | ||||||||||||
510 | - | |||||||||||||
511 | void QFontconfigDatabase::populateFontDatabase() | - | ||||||||||||
512 | { | - | ||||||||||||
513 | FcInitReinitialize(); | - | ||||||||||||
514 | FcFontSet *fonts; | - | ||||||||||||
515 | - | |||||||||||||
516 | { | - | ||||||||||||
517 | FcObjectSet *os = FcObjectSetCreate(); | - | ||||||||||||
518 | FcPattern *pattern = FcPatternCreate(); | - | ||||||||||||
519 | const char *properties [] = { | - | ||||||||||||
520 | FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, | - | ||||||||||||
521 | FC_SPACING, FC_FILE, FC_INDEX, | - | ||||||||||||
522 | FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, | - | ||||||||||||
523 | FC_WIDTH, FC_FAMILYLANG, | - | ||||||||||||
524 | #if FC_VERSION >= 20297 | - | ||||||||||||
525 | FC_CAPABILITY, | - | ||||||||||||
526 | #endif | - | ||||||||||||
527 | (const char *)0 | - | ||||||||||||
528 | }; | - | ||||||||||||
529 | const char **p = properties; | - | ||||||||||||
530 | while (*p) {
| 178-2670 | ||||||||||||
531 | FcObjectSetAdd(os, *p); | - | ||||||||||||
532 | ++p; | - | ||||||||||||
533 | } executed 2670 times by 123 tests: end of block Executed by:
| 2670 | ||||||||||||
534 | fonts = FcFontList(0, pattern, os); | - | ||||||||||||
535 | FcObjectSetDestroy(os); | - | ||||||||||||
536 | FcPatternDestroy(pattern); | - | ||||||||||||
537 | } | - | ||||||||||||
538 | - | |||||||||||||
539 | for (int i = 0; i < fonts->nfont; i++)
| 178-20648 | ||||||||||||
540 | populateFromPattern(fonts->fonts[i]); executed 20648 times by 123 tests: populateFromPattern(fonts->fonts[i]); Executed by:
| 20648 | ||||||||||||
541 | - | |||||||||||||
542 | FcFontSetDestroy (fonts); | - | ||||||||||||
543 | - | |||||||||||||
544 | struct FcDefaultFont { | - | ||||||||||||
545 | const char *qtname; | - | ||||||||||||
546 | const char *rawname; | - | ||||||||||||
547 | bool fixed; | - | ||||||||||||
548 | }; | - | ||||||||||||
549 | const FcDefaultFont defaults[] = { | - | ||||||||||||
550 | { "Serif", "serif", false }, | - | ||||||||||||
551 | { "Sans Serif", "sans-serif", false }, | - | ||||||||||||
552 | { "Monospace", "monospace", true }, | - | ||||||||||||
553 | { 0, 0, false } | - | ||||||||||||
554 | }; | - | ||||||||||||
555 | const FcDefaultFont *f = defaults; | - | ||||||||||||
556 | // aliases only make sense for 'common', not for any of the specials | - | ||||||||||||
557 | QSupportedWritingSystems ws; | - | ||||||||||||
558 | ws.setSupported(QFontDatabase::Latin); | - | ||||||||||||
559 | - | |||||||||||||
560 | while (f->qtname) {
| 178-534 | ||||||||||||
561 | QString familyQtName = QString::fromLatin1(f->qtname); | - | ||||||||||||
562 | registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,0); | - | ||||||||||||
563 | registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,0); | - | ||||||||||||
564 | registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,0); | - | ||||||||||||
565 | ++f; | - | ||||||||||||
566 | } executed 534 times by 123 tests: end of block Executed by:
| 534 | ||||||||||||
567 | - | |||||||||||||
568 | //Lighthouse has very lazy population of the font db. We want it to be initialized when | - | ||||||||||||
569 | //QApplication is constructed, so that the population procedure can do something like this to | - | ||||||||||||
570 | //set the default font | - | ||||||||||||
571 | // const FcDefaultFont *s = defaults; | - | ||||||||||||
572 | // QFont font("Sans Serif"); | - | ||||||||||||
573 | // font.setPointSize(9); | - | ||||||||||||
574 | // QApplication::setFont(font); | - | ||||||||||||
575 | } executed 178 times by 123 tests: end of block Executed by:
| 178 | ||||||||||||
576 | - | |||||||||||||
577 | QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) | - | ||||||||||||
578 | { | - | ||||||||||||
579 | return new QFontEngineMultiFontConfig(fontEngine, script); | - | ||||||||||||
580 | } | - | ||||||||||||
581 | - | |||||||||||||
582 | namespace { | - | ||||||||||||
583 | QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf) | - | ||||||||||||
584 | { | - | ||||||||||||
585 | switch (hintingPreference) { | - | ||||||||||||
586 | case QFont::PreferNoHinting: | - | ||||||||||||
587 | return QFontEngine::HintNone; | - | ||||||||||||
588 | case QFont::PreferVerticalHinting: | - | ||||||||||||
589 | return QFontEngine::HintLight; | - | ||||||||||||
590 | case QFont::PreferFullHinting: | - | ||||||||||||
591 | return QFontEngine::HintFull; | - | ||||||||||||
592 | case QFont::PreferDefaultHinting: | - | ||||||||||||
593 | break; | - | ||||||||||||
594 | } | - | ||||||||||||
595 | - | |||||||||||||
596 | if (QHighDpiScaling::isActive()) | - | ||||||||||||
597 | return QFontEngine::HintNone; | - | ||||||||||||
598 | - | |||||||||||||
599 | int hint_style = 0; | - | ||||||||||||
600 | if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) { | - | ||||||||||||
601 | switch (hint_style) { | - | ||||||||||||
602 | case FC_HINT_NONE: | - | ||||||||||||
603 | return QFontEngine::HintNone; | - | ||||||||||||
604 | case FC_HINT_SLIGHT: | - | ||||||||||||
605 | return QFontEngine::HintLight; | - | ||||||||||||
606 | case FC_HINT_MEDIUM: | - | ||||||||||||
607 | return QFontEngine::HintMedium; | - | ||||||||||||
608 | case FC_HINT_FULL: | - | ||||||||||||
609 | return QFontEngine::HintFull; | - | ||||||||||||
610 | default: | - | ||||||||||||
611 | Q_UNREACHABLE(); | - | ||||||||||||
612 | break; | - | ||||||||||||
613 | } | - | ||||||||||||
614 | } | - | ||||||||||||
615 | - | |||||||||||||
616 | if (useXftConf) { | - | ||||||||||||
617 | void *hintStyleResource = | - | ||||||||||||
618 | QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", | - | ||||||||||||
619 | QGuiApplication::primaryScreen()); | - | ||||||||||||
620 | int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource)); | - | ||||||||||||
621 | if (hintStyle > 0) | - | ||||||||||||
622 | return QFontEngine::HintStyle(hintStyle - 1); | - | ||||||||||||
623 | } | - | ||||||||||||
624 | - | |||||||||||||
625 | return QFontEngine::HintFull; | - | ||||||||||||
626 | } | - | ||||||||||||
627 | - | |||||||||||||
628 | QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf) | - | ||||||||||||
629 | { | - | ||||||||||||
630 | int subpixel = FC_RGBA_UNKNOWN; | - | ||||||||||||
631 | if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) { | - | ||||||||||||
632 | switch (subpixel) { | - | ||||||||||||
633 | case FC_RGBA_UNKNOWN: | - | ||||||||||||
634 | case FC_RGBA_NONE: | - | ||||||||||||
635 | return QFontEngine::Subpixel_None; | - | ||||||||||||
636 | case FC_RGBA_RGB: | - | ||||||||||||
637 | return QFontEngine::Subpixel_RGB; | - | ||||||||||||
638 | case FC_RGBA_BGR: | - | ||||||||||||
639 | return QFontEngine::Subpixel_BGR; | - | ||||||||||||
640 | case FC_RGBA_VRGB: | - | ||||||||||||
641 | return QFontEngine::Subpixel_VRGB; | - | ||||||||||||
642 | case FC_RGBA_VBGR: | - | ||||||||||||
643 | return QFontEngine::Subpixel_VBGR; | - | ||||||||||||
644 | default: | - | ||||||||||||
645 | Q_UNREACHABLE(); | - | ||||||||||||
646 | break; | - | ||||||||||||
647 | } | - | ||||||||||||
648 | } | - | ||||||||||||
649 | - | |||||||||||||
650 | if (useXftConf) { | - | ||||||||||||
651 | void *subpixelTypeResource = | - | ||||||||||||
652 | QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype", | - | ||||||||||||
653 | QGuiApplication::primaryScreen()); | - | ||||||||||||
654 | int subpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource)); | - | ||||||||||||
655 | if (subpixelType > 0) | - | ||||||||||||
656 | return QFontEngine::SubpixelAntialiasingType(subpixelType - 1); | - | ||||||||||||
657 | } | - | ||||||||||||
658 | - | |||||||||||||
659 | return QFontEngine::Subpixel_None; | - | ||||||||||||
660 | } | - | ||||||||||||
661 | } // namespace | - | ||||||||||||
662 | - | |||||||||||||
663 | QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) | - | ||||||||||||
664 | { | - | ||||||||||||
665 | if (!usrPtr) | - | ||||||||||||
666 | return 0; | - | ||||||||||||
667 | - | |||||||||||||
668 | FontFile *fontfile = static_cast<FontFile *> (usrPtr); | - | ||||||||||||
669 | QFontEngine::FaceId fid; | - | ||||||||||||
670 | fid.filename = QFile::encodeName(fontfile->fileName); | - | ||||||||||||
671 | fid.index = fontfile->indexValue; | - | ||||||||||||
672 | - | |||||||||||||
673 | QFontEngineFT *engine = new QFontEngineFT(f); | - | ||||||||||||
674 | engine->face_id = fid; | - | ||||||||||||
675 | - | |||||||||||||
676 | setupFontEngine(engine, f); | - | ||||||||||||
677 | - | |||||||||||||
678 | if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) { | - | ||||||||||||
679 | delete engine; | - | ||||||||||||
680 | engine = 0; | - | ||||||||||||
681 | } | - | ||||||||||||
682 | - | |||||||||||||
683 | return engine; | - | ||||||||||||
684 | } | - | ||||||||||||
685 | - | |||||||||||||
686 | QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) | - | ||||||||||||
687 | { | - | ||||||||||||
688 | QFontEngineFT *engine = static_cast<QFontEngineFT*>(QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); | - | ||||||||||||
689 | if (engine == 0) | - | ||||||||||||
690 | return 0; | - | ||||||||||||
691 | - | |||||||||||||
692 | setupFontEngine(engine, engine->fontDef); | - | ||||||||||||
693 | - | |||||||||||||
694 | return engine; | - | ||||||||||||
695 | } | - | ||||||||||||
696 | - | |||||||||||||
697 | QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const | - | ||||||||||||
698 | { | - | ||||||||||||
699 | QStringList fallbackFamilies; | - | ||||||||||||
700 | FcPattern *pattern = FcPatternCreate(); | - | ||||||||||||
701 | if (!pattern) | - | ||||||||||||
702 | return fallbackFamilies; | - | ||||||||||||
703 | - | |||||||||||||
704 | FcValue value; | - | ||||||||||||
705 | value.type = FcTypeString; | - | ||||||||||||
706 | QByteArray cs = family.toUtf8(); | - | ||||||||||||
707 | value.u.s = (const FcChar8 *)cs.data(); | - | ||||||||||||
708 | FcPatternAdd(pattern,FC_FAMILY,value,true); | - | ||||||||||||
709 | - | |||||||||||||
710 | int slant_value = FC_SLANT_ROMAN; | - | ||||||||||||
711 | if (style == QFont::StyleItalic) | - | ||||||||||||
712 | slant_value = FC_SLANT_ITALIC; | - | ||||||||||||
713 | else if (style == QFont::StyleOblique) | - | ||||||||||||
714 | slant_value = FC_SLANT_OBLIQUE; | - | ||||||||||||
715 | FcPatternAddInteger(pattern, FC_SLANT, slant_value); | - | ||||||||||||
716 | - | |||||||||||||
717 | Q_ASSERT(uint(script) < QChar::ScriptCount); | - | ||||||||||||
718 | if (*specialLanguages[script] != '\0') { | - | ||||||||||||
719 | FcLangSet *ls = FcLangSetCreate(); | - | ||||||||||||
720 | FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); | - | ||||||||||||
721 | FcPatternAddLangSet(pattern, FC_LANG, ls); | - | ||||||||||||
722 | FcLangSetDestroy(ls); | - | ||||||||||||
723 | } else if (!family.isEmpty()) { | - | ||||||||||||
724 | // If script is Common or Han, then it may include languages like CJK, | - | ||||||||||||
725 | // we should attach system default language set to the pattern | - | ||||||||||||
726 | // to obtain correct font fallback list (i.e. if LANG=zh_CN | - | ||||||||||||
727 | // then we normally want to use a Chinese font for CJK text; | - | ||||||||||||
728 | // while a Japanese font should be used for that if LANG=ja) | - | ||||||||||||
729 | FcPattern *dummy = FcPatternCreate(); | - | ||||||||||||
730 | FcDefaultSubstitute(dummy); | - | ||||||||||||
731 | FcChar8 *lang = 0; | - | ||||||||||||
732 | FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); | - | ||||||||||||
733 | if (res == FcResultMatch) | - | ||||||||||||
734 | FcPatternAddString(pattern, FC_LANG, lang); | - | ||||||||||||
735 | FcPatternDestroy(dummy); | - | ||||||||||||
736 | } | - | ||||||||||||
737 | - | |||||||||||||
738 | const char *stylehint = getFcFamilyForStyleHint(styleHint); | - | ||||||||||||
739 | if (stylehint) { | - | ||||||||||||
740 | value.u.s = (const FcChar8 *)stylehint; | - | ||||||||||||
741 | FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); | - | ||||||||||||
742 | } | - | ||||||||||||
743 | - | |||||||||||||
744 | FcConfigSubstitute(0, pattern, FcMatchPattern); | - | ||||||||||||
745 | FcDefaultSubstitute(pattern); | - | ||||||||||||
746 | - | |||||||||||||
747 | FcResult result = FcResultMatch; | - | ||||||||||||
748 | FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); | - | ||||||||||||
749 | FcPatternDestroy(pattern); | - | ||||||||||||
750 | - | |||||||||||||
751 | if (fontSet) { | - | ||||||||||||
752 | QSet<QString> duplicates; | - | ||||||||||||
753 | duplicates.reserve(fontSet->nfont + 1); | - | ||||||||||||
754 | duplicates.insert(family.toCaseFolded()); | - | ||||||||||||
755 | for (int i = 0; i < fontSet->nfont; i++) { | - | ||||||||||||
756 | FcChar8 *value = 0; | - | ||||||||||||
757 | if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) | - | ||||||||||||
758 | continue; | - | ||||||||||||
759 | // capitalize(value); | - | ||||||||||||
760 | const QString familyName = QString::fromUtf8((const char *)value); | - | ||||||||||||
761 | const QString familyNameCF = familyName.toCaseFolded(); | - | ||||||||||||
762 | if (!duplicates.contains(familyNameCF)) { | - | ||||||||||||
763 | fallbackFamilies << familyName; | - | ||||||||||||
764 | duplicates.insert(familyNameCF); | - | ||||||||||||
765 | } | - | ||||||||||||
766 | } | - | ||||||||||||
767 | FcFontSetDestroy(fontSet); | - | ||||||||||||
768 | } | - | ||||||||||||
769 | // qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies; | - | ||||||||||||
770 | - | |||||||||||||
771 | return fallbackFamilies; | - | ||||||||||||
772 | } | - | ||||||||||||
773 | - | |||||||||||||
774 | static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count) | - | ||||||||||||
775 | { | - | ||||||||||||
776 | #if FC_VERSION < 20402 | - | ||||||||||||
777 | Q_UNUSED(data) | - | ||||||||||||
778 | return FcFreeTypeQuery(file, id, blanks, count); | - | ||||||||||||
779 | #else | - | ||||||||||||
780 | if (data.isEmpty()) | - | ||||||||||||
781 | return FcFreeTypeQuery(file, id, blanks, count); | - | ||||||||||||
782 | - | |||||||||||||
783 | FT_Library lib = qt_getFreetype(); | - | ||||||||||||
784 | - | |||||||||||||
785 | FcPattern *pattern = 0; | - | ||||||||||||
786 | - | |||||||||||||
787 | FT_Face face; | - | ||||||||||||
788 | if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { | - | ||||||||||||
789 | *count = face->num_faces; | - | ||||||||||||
790 | - | |||||||||||||
791 | pattern = FcFreeTypeQueryFace(face, file, id, blanks); | - | ||||||||||||
792 | - | |||||||||||||
793 | FT_Done_Face(face); | - | ||||||||||||
794 | } | - | ||||||||||||
795 | - | |||||||||||||
796 | return pattern; | - | ||||||||||||
797 | #endif | - | ||||||||||||
798 | } | - | ||||||||||||
799 | - | |||||||||||||
800 | QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) | - | ||||||||||||
801 | { | - | ||||||||||||
802 | QStringList families; | - | ||||||||||||
803 | - | |||||||||||||
804 | FcFontSet *set = FcConfigGetFonts(0, FcSetApplication); | - | ||||||||||||
805 | if (!set) { | - | ||||||||||||
806 | FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent"); | - | ||||||||||||
807 | set = FcConfigGetFonts(0, FcSetApplication); // try again | - | ||||||||||||
808 | if (!set) | - | ||||||||||||
809 | return families; | - | ||||||||||||
810 | } | - | ||||||||||||
811 | - | |||||||||||||
812 | int id = 0; | - | ||||||||||||
813 | FcBlanks *blanks = FcConfigGetBlanks(0); | - | ||||||||||||
814 | int count = 0; | - | ||||||||||||
815 | - | |||||||||||||
816 | FcPattern *pattern; | - | ||||||||||||
817 | do { | - | ||||||||||||
818 | pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(), | - | ||||||||||||
819 | fontData, id, blanks, &count); | - | ||||||||||||
820 | if (!pattern) | - | ||||||||||||
821 | return families; | - | ||||||||||||
822 | - | |||||||||||||
823 | FcChar8 *fam = 0; | - | ||||||||||||
824 | if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { | - | ||||||||||||
825 | QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); | - | ||||||||||||
826 | families << family; | - | ||||||||||||
827 | } | - | ||||||||||||
828 | populateFromPattern(pattern); | - | ||||||||||||
829 | - | |||||||||||||
830 | FcFontSetAdd(set, pattern); | - | ||||||||||||
831 | - | |||||||||||||
832 | ++id; | - | ||||||||||||
833 | } while (id < count); | - | ||||||||||||
834 | - | |||||||||||||
835 | return families; | - | ||||||||||||
836 | } | - | ||||||||||||
837 | - | |||||||||||||
838 | QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const | - | ||||||||||||
839 | { | - | ||||||||||||
840 | QString resolved = QBasicFontDatabase::resolveFontFamilyAlias(family); | - | ||||||||||||
841 | if (!resolved.isEmpty() && resolved != family) | - | ||||||||||||
842 | return resolved; | - | ||||||||||||
843 | FcPattern *pattern = FcPatternCreate(); | - | ||||||||||||
844 | if (!pattern) | - | ||||||||||||
845 | return family; | - | ||||||||||||
846 | - | |||||||||||||
847 | if (!family.isEmpty()) { | - | ||||||||||||
848 | QByteArray cs = family.toUtf8(); | - | ||||||||||||
849 | FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData()); | - | ||||||||||||
850 | } | - | ||||||||||||
851 | FcConfigSubstitute(0, pattern, FcMatchPattern); | - | ||||||||||||
852 | FcDefaultSubstitute(pattern); | - | ||||||||||||
853 | - | |||||||||||||
854 | FcChar8 *familyAfterSubstitution = 0; | - | ||||||||||||
855 | FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); | - | ||||||||||||
856 | resolved = QString::fromUtf8((const char *) familyAfterSubstitution); | - | ||||||||||||
857 | FcPatternDestroy(pattern); | - | ||||||||||||
858 | - | |||||||||||||
859 | return resolved; | - | ||||||||||||
860 | } | - | ||||||||||||
861 | - | |||||||||||||
862 | QFont QFontconfigDatabase::defaultFont() const | - | ||||||||||||
863 | { | - | ||||||||||||
864 | // Hack to get system default language until FcGetDefaultLangs() | - | ||||||||||||
865 | // is exported (https://bugs.freedesktop.org/show_bug.cgi?id=32853) | - | ||||||||||||
866 | // or https://bugs.freedesktop.org/show_bug.cgi?id=35482 is fixed | - | ||||||||||||
867 | FcPattern *dummy = FcPatternCreate(); | - | ||||||||||||
868 | FcDefaultSubstitute(dummy); | - | ||||||||||||
869 | FcChar8 *lang = 0; | - | ||||||||||||
870 | FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); | - | ||||||||||||
871 | - | |||||||||||||
872 | FcPattern *pattern = FcPatternCreate(); | - | ||||||||||||
873 | if (res == FcResultMatch) { | - | ||||||||||||
874 | // Make defaultFont pattern matching locale language aware, because | - | ||||||||||||
875 | // certain FC_LANG based custom rules may happen in FcConfigSubstitute() | - | ||||||||||||
876 | FcPatternAddString(pattern, FC_LANG, lang); | - | ||||||||||||
877 | } | - | ||||||||||||
878 | FcConfigSubstitute(0, pattern, FcMatchPattern); | - | ||||||||||||
879 | FcDefaultSubstitute(pattern); | - | ||||||||||||
880 | - | |||||||||||||
881 | FcChar8 *familyAfterSubstitution = 0; | - | ||||||||||||
882 | FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); | - | ||||||||||||
883 | QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); | - | ||||||||||||
884 | FcPatternDestroy(pattern); | - | ||||||||||||
885 | FcPatternDestroy(dummy); | - | ||||||||||||
886 | - | |||||||||||||
887 | return QFont(resolved); | - | ||||||||||||
888 | } | - | ||||||||||||
889 | - | |||||||||||||
890 | void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const | - | ||||||||||||
891 | { | - | ||||||||||||
892 | bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); | - | ||||||||||||
893 | bool forcedAntialiasSetting = !antialias; | - | ||||||||||||
894 | - | |||||||||||||
895 | const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); | - | ||||||||||||
896 | bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")); | - | ||||||||||||
897 | if (useXftConf && !forcedAntialiasSetting) { | - | ||||||||||||
898 | void *antialiasResource = | - | ||||||||||||
899 | QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", | - | ||||||||||||
900 | QGuiApplication::primaryScreen()); | - | ||||||||||||
901 | int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource)); | - | ||||||||||||
902 | if (antialiasingEnabled > 0) | - | ||||||||||||
903 | antialias = antialiasingEnabled - 1; | - | ||||||||||||
904 | } | - | ||||||||||||
905 | - | |||||||||||||
906 | QFontEngine::GlyphFormat format; | - | ||||||||||||
907 | // try and get the pattern | - | ||||||||||||
908 | FcPattern *pattern = FcPatternCreate(); | - | ||||||||||||
909 | - | |||||||||||||
910 | FcValue value; | - | ||||||||||||
911 | value.type = FcTypeString; | - | ||||||||||||
912 | QByteArray cs = fontDef.family.toUtf8(); | - | ||||||||||||
913 | value.u.s = (const FcChar8 *)cs.data(); | - | ||||||||||||
914 | FcPatternAdd(pattern,FC_FAMILY,value,true); | - | ||||||||||||
915 | - | |||||||||||||
916 | QFontEngine::FaceId fid = engine->faceId(); | - | ||||||||||||
917 | - | |||||||||||||
918 | if (!fid.filename.isEmpty()) { | - | ||||||||||||
919 | value.u.s = (const FcChar8 *)fid.filename.data(); | - | ||||||||||||
920 | FcPatternAdd(pattern,FC_FILE,value,true); | - | ||||||||||||
921 | - | |||||||||||||
922 | value.type = FcTypeInteger; | - | ||||||||||||
923 | value.u.i = fid.index; | - | ||||||||||||
924 | FcPatternAdd(pattern,FC_INDEX,value,true); | - | ||||||||||||
925 | } | - | ||||||||||||
926 | - | |||||||||||||
927 | if (fontDef.pixelSize > 0.1) | - | ||||||||||||
928 | FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); | - | ||||||||||||
929 | - | |||||||||||||
930 | FcResult result; | - | ||||||||||||
931 | - | |||||||||||||
932 | FcConfigSubstitute(0, pattern, FcMatchPattern); | - | ||||||||||||
933 | FcDefaultSubstitute(pattern); | - | ||||||||||||
934 | - | |||||||||||||
935 | FcPattern *match = FcFontMatch(0, pattern, &result); | - | ||||||||||||
936 | if (match) { | - | ||||||||||||
937 | engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); | - | ||||||||||||
938 | - | |||||||||||||
939 | FcBool fc_autohint; | - | ||||||||||||
940 | if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) | - | ||||||||||||
941 | engine->forceAutoHint = fc_autohint; | - | ||||||||||||
942 | - | |||||||||||||
943 | #if defined(FT_LCD_FILTER_H) | - | ||||||||||||
944 | int lcdFilter; | - | ||||||||||||
945 | if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch) | - | ||||||||||||
946 | engine->lcdFilterType = lcdFilter; | - | ||||||||||||
947 | #endif | - | ||||||||||||
948 | - | |||||||||||||
949 | if (!forcedAntialiasSetting) { | - | ||||||||||||
950 | FcBool fc_antialias; | - | ||||||||||||
951 | if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch) | - | ||||||||||||
952 | antialias = fc_antialias; | - | ||||||||||||
953 | } | - | ||||||||||||
954 | - | |||||||||||||
955 | if (antialias) { | - | ||||||||||||
956 | QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; | - | ||||||||||||
957 | if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) | - | ||||||||||||
958 | subpixelType = subpixelTypeFromMatch(match, useXftConf); | - | ||||||||||||
959 | engine->subpixelType = subpixelType; | - | ||||||||||||
960 | - | |||||||||||||
961 | format = (subpixelType == QFontEngine::Subpixel_None) | - | ||||||||||||
962 | ? QFontEngine::Format_A8 | - | ||||||||||||
963 | : QFontEngine::Format_A32; | - | ||||||||||||
964 | } else | - | ||||||||||||
965 | format = QFontEngine::Format_Mono; | - | ||||||||||||
966 | - | |||||||||||||
967 | FcPatternDestroy(match); | - | ||||||||||||
968 | } else | - | ||||||||||||
969 | format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono; | - | ||||||||||||
970 | - | |||||||||||||
971 | FcPatternDestroy(pattern); | - | ||||||||||||
972 | - | |||||||||||||
973 | engine->antialias = antialias; | - | ||||||||||||
974 | engine->defaultFormat = format; | - | ||||||||||||
975 | engine->glyphFormat = format; | - | ||||||||||||
976 | } | - | ||||||||||||
977 | - | |||||||||||||
978 | QT_END_NAMESPACE | - | ||||||||||||
Source code | Switch to Preprocessed file |