| 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 blockExecuted by:
| 60378 | ||||||||||||
| 449 | } executed 682012 times by 123 tests: end of blockExecuted by:
| 682012 | ||||||||||||
| 450 | } executed 682012 times by 123 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 1424 | ||||||||||||
| 505 | QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName); | - | ||||||||||||
| 506 | } executed 178 times by 123 tests: end of blockExecuted by:
| 178 | ||||||||||||
| 507 | } | - | ||||||||||||
| 508 | - | |||||||||||||
| 509 | } executed 20694 times by 123 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 |