Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qfontdatabase.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfontdatabase.h"
5#include "qfontdatabase_p.h"
6#include "qloggingcategory.h"
7#include "qalgorithms.h"
8#include "qguiapplication.h"
9#include "qvarlengtharray.h" // here or earlier - workaround for VC++6
10#include "qthread.h"
11#include "qmutex.h"
12#include "qfile.h"
13#include "qfileinfo.h"
14#include "qfontengine_p.h"
15#include <qpa/qplatformintegration.h>
16
17#include <QtGui/private/qguiapplication_p.h>
18#include <qpa/qplatformfontdatabase.h>
19#include <qpa/qplatformtheme.h>
20
21#include <QtCore/qcache.h>
22#include <QtCore/qmath.h>
23
24#include <stdlib.h>
25#include <algorithm>
26
27#include <qtgui_tracepoints_p.h>
28
29#ifdef Q_OS_WIN
30#include <QtGui/private/qwindowsfontdatabasebase_p.h>
31#endif
32
34
35using namespace Qt::StringLiterals;
36
37Q_LOGGING_CATEGORY(lcFontDb, "qt.text.font.db")
38Q_LOGGING_CATEGORY(lcFontMatch, "qt.text.font.match")
39
40#define SMOOTH_SCALABLE 0xffff
41
42#if defined(QT_BUILD_INTERNAL)
43bool qt_enable_test_font = false;
44
45Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value)
46{
47 qt_enable_test_font = value;
48}
49#endif
50
51Q_TRACE_POINT(qtgui, QFontDatabase_loadEngine, const QString &families, int pointSize);
52Q_TRACE_POINT(qtgui, QFontDatabasePrivate_addAppFont, const QString &fileName);
53Q_TRACE_POINT(qtgui, QFontDatabase_addApplicationFont, const QString &fileName);
54Q_TRACE_POINT(qtgui, QFontDatabase_load, const QString &family, int pointSize);
55
56static int getFontWeight(const QString &weightString)
57{
58 QString s = weightString.toLower();
59
60 // Order here is important. We want to match the common cases first, but we
61 // must also take care to acknowledge the cost of our tests.
62 //
63 // As a result, we test in two orders; the order of commonness, and the
64 // order of "expense".
65 //
66 // A simple string test is the cheapest, so let's do that first.
67 // Test in decreasing order of commonness
68 if (s == "normal"_L1 || s == "regular"_L1)
69 return QFont::Normal;
70 if (s == "bold"_L1)
71 return QFont::Bold;
72 if (s == "semibold"_L1 || s == "semi bold"_L1 || s == "demibold"_L1 || s == "demi bold"_L1)
73 return QFont::DemiBold;
74 if (s == "medium"_L1)
75 return QFont::Medium;
76 if (s == "black"_L1)
77 return QFont::Black;
78 if (s == "light"_L1)
79 return QFont::Light;
80 if (s == "thin"_L1)
81 return QFont::Thin;
82 const QStringView s2 = QStringView{s}.mid(2);
83 if (s.startsWith("ex"_L1) || s.startsWith("ul"_L1)) {
84 if (s2 == "tralight"_L1 || s == "tra light"_L1)
85 return QFont::ExtraLight;
86 if (s2 == "trabold"_L1 || s2 == "tra bold"_L1)
87 return QFont::ExtraBold;
88 }
89
90 // Next up, let's see if contains() matches: slightly more expensive, but
91 // still fast enough.
92 if (s.contains("bold"_L1)) {
93 if (s.contains("demi"_L1))
94 return QFont::DemiBold;
95 return QFont::Bold;
96 }
97 if (s.contains("thin"_L1))
98 return QFont::Thin;
99 if (s.contains("light"_L1))
100 return QFont::Light;
101 if (s.contains("black"_L1))
102 return QFont::Black;
103
104 // Now, we perform string translations & comparisons with those.
105 // These are (very) slow compared to simple string ops, so we do these last.
106 // As using translated values for such things is not very common, this should
107 // not be too bad.
108 if (s.compare(QCoreApplication::translate("QFontDatabase", "Normal", "The Normal or Regular font weight"), Qt::CaseInsensitive) == 0)
109 return QFont::Normal;
110 const QString translatedBold = QCoreApplication::translate("QFontDatabase", "Bold").toLower();
111 if (s == translatedBold)
112 return QFont::Bold;
113 if (s.compare(QCoreApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
114 return QFont::DemiBold;
115 if (s.compare(QCoreApplication::translate("QFontDatabase", "Medium", "The Medium font weight"), Qt::CaseInsensitive) == 0)
116 return QFont::Medium;
117 if (s.compare(QCoreApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
118 return QFont::Black;
119 const QString translatedLight = QCoreApplication::translate("QFontDatabase", "Light").toLower();
120 if (s == translatedLight)
121 return QFont::Light;
122 if (s.compare(QCoreApplication::translate("QFontDatabase", "Thin"), Qt::CaseInsensitive) == 0)
123 return QFont::Thin;
124 if (s.compare(QCoreApplication::translate("QFontDatabase", "Extra Light"), Qt::CaseInsensitive) == 0)
125 return QFont::ExtraLight;
126 if (s.compare(QCoreApplication::translate("QFontDatabase", "Extra Bold"), Qt::CaseInsensitive) == 0)
127 return QFont::ExtraBold;
128
129 // And now the contains() checks for the translated strings.
130 //: The word for "Extra" as in "Extra Bold, Extra Thin" used as a pattern for string searches
131 const QString translatedExtra = QCoreApplication::translate("QFontDatabase", "Extra").toLower();
132 if (s.contains(translatedBold)) {
133 //: The word for "Demi" as in "Demi Bold" used as a pattern for string searches
134 QString translatedDemi = QCoreApplication::translate("QFontDatabase", "Demi").toLower();
135 if (s .contains(translatedDemi))
136 return QFont::DemiBold;
137 if (s.contains(translatedExtra))
138 return QFont::ExtraBold;
139 return QFont::Bold;
140 }
141
142 if (s.contains(translatedLight)) {
143 if (s.contains(translatedExtra))
144 return QFont::ExtraLight;
145 return QFont::Light;
146 }
147 return QFont::Normal;
148}
149
150
152 : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
153{
154 weight = getFontWeight(styleString);
155
156 if (!styleString.isEmpty()) {
157 // First the straightforward no-translation checks, these are fast.
158 if (styleString.contains("Italic"_L1))
160 else if (styleString.contains("Oblique"_L1))
162
163 // Then the translation checks. These aren't as fast.
164 else if (styleString.contains(QCoreApplication::translate("QFontDatabase", "Italic")))
166 else if (styleString.contains(QCoreApplication::translate("QFontDatabase", "Oblique")))
168 }
169}
170
172{
173 for (int i = 0; i < count; i++) {
174 if (pixelSizes[i].pixelSize == size)
175 return pixelSizes + i;
176 }
177 if (!add)
178 return nullptr;
179
180 if (!pixelSizes) {
181 // Most style have only one font size, we avoid waisting memory
182 QtFontSize *newPixelSizes = (QtFontSize *)malloc(sizeof(QtFontSize));
183 Q_CHECK_PTR(newPixelSizes);
184 pixelSizes = newPixelSizes;
185 } else if (!(count % 8) || count == 1) {
186 QtFontSize *newPixelSizes = (QtFontSize *)
187 realloc(pixelSizes,
188 (((count+8) >> 3) << 3) * sizeof(QtFontSize));
189 Q_CHECK_PTR(newPixelSizes);
190 pixelSizes = newPixelSizes;
191 }
193 pixelSizes[count].handle = nullptr;
194 return pixelSizes + (count++);
195}
196
198{
199 int pos = 0;
200 for (; pos < count; pos++) {
201 bool hasStyleName = !styleName.isEmpty(); // search styleName first if available
202 if (hasStyleName && !styles[pos]->styleName.isEmpty()) {
203 if (styles[pos]->styleName == styleName)
204 return styles[pos];
205 } else {
206 if (styles[pos]->key == key)
207 return styles[pos];
208 }
209 }
210 if (!create)
211 return nullptr;
212
213// qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
214 if (!(count % 8)) {
215 QtFontStyle **newStyles = (QtFontStyle **)
216 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
217 Q_CHECK_PTR(newStyles);
218 styles = newStyles;
219 }
220
221 QtFontStyle *style = new QtFontStyle(key);
222 style->styleName = styleName;
223 styles[pos] = style;
224 count++;
225 return styles[pos];
226}
227
229{
230 if (f.isNull() && count == 1)
231 return foundries[0];
232
233 for (int i = 0; i < count; i++) {
234 if (foundries[i]->name.compare(f, Qt::CaseInsensitive) == 0)
235 return foundries[i];
236 }
237 if (!create)
238 return nullptr;
239
240 if (!(count % 8)) {
241 QtFontFoundry **newFoundries = (QtFontFoundry **)
242 realloc(foundries,
243 (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
244 Q_CHECK_PTR(newFoundries);
245 foundries = newFoundries;
246 }
247
248 foundries[count] = new QtFontFoundry(f);
249 return foundries[count++];
250}
251
252static inline bool equalsCaseInsensitive(const QString &a, const QString &b)
253{
254 return a.size() == b.size() && a.compare(b, Qt::CaseInsensitive) == 0;
255}
256
257bool QtFontFamily::matchesFamilyName(const QString &familyName) const
258{
259 return equalsCaseInsensitive(name, familyName) || aliases.contains(familyName, Qt::CaseInsensitive);
260}
261
263{
264 if (populated)
265 return true;
266
268 return populated;
269}
270
272{
273 while (count--)
274 delete families[count];
275 ::free(families);
276 families = nullptr;
277 count = 0;
278
279 for (auto &font : applicationFonts)
280 font.properties.clear(); // Unpopulate
281
282 populated = false;
283 // don't clear the memory fonts!
284}
285
287{
288 qCDebug(lcFontDb) << "Invalidating font database";
289
291
292 fallbacksCache.clear();
293 clearFamilies();
295 emit qGuiApp->fontDatabaseChanged();
296}
297
299{
300 QtFontFamily *fam = nullptr;
301
302 int low = 0;
303 int high = count;
304 int pos = count / 2;
305 int res = 1;
306 if (count) {
307 while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) {
308 if (res > 0)
309 high = pos;
310 else
311 low = pos;
312 pos = (high + low) / 2;
313 }
314 if (!res)
315 fam = families[pos];
316 }
317
318 if (!fam && (flags & EnsureCreated)) {
319 if (res < 0)
320 pos++;
321
322 // qDebug() << "adding family " << f.toLatin1() << " at " << pos << " total=" << count;
323 if (!(count % 8)) {
324 QtFontFamily **newFamilies = (QtFontFamily **)
325 realloc(families,
326 (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
327 Q_CHECK_PTR(newFamilies);
328 families = newFamilies;
329 }
330
331 QtFontFamily *family = new QtFontFamily(f);
332 memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
333 families[pos] = family;
334 count++;
335
336 fam = families[pos];
337 }
338
339 if (fam && (flags & EnsurePopulated)) {
340 if (!fam->ensurePopulated())
341 return nullptr;
342 }
343
344 return fam;
345}
346
347
348
349static const int scriptForWritingSystem[] = {
351 QChar::Script_Latin, // Latin
352 QChar::Script_Greek, // Greek
353 QChar::Script_Cyrillic, // Cyrillic
354 QChar::Script_Armenian, // Armenian
355 QChar::Script_Hebrew, // Hebrew
356 QChar::Script_Arabic, // Arabic
357 QChar::Script_Syriac, // Syriac
358 QChar::Script_Thaana, // Thaana
359 QChar::Script_Devanagari, // Devanagari
360 QChar::Script_Bengali, // Bengali
361 QChar::Script_Gurmukhi, // Gurmukhi
362 QChar::Script_Gujarati, // Gujarati
363 QChar::Script_Oriya, // Oriya
364 QChar::Script_Tamil, // Tamil
365 QChar::Script_Telugu, // Telugu
366 QChar::Script_Kannada, // Kannada
367 QChar::Script_Malayalam, // Malayalam
368 QChar::Script_Sinhala, // Sinhala
369 QChar::Script_Thai, // Thai
370 QChar::Script_Lao, // Lao
371 QChar::Script_Tibetan, // Tibetan
372 QChar::Script_Myanmar, // Myanmar
373 QChar::Script_Georgian, // Georgian
374 QChar::Script_Khmer, // Khmer
375 QChar::Script_Han, // SimplifiedChinese
376 QChar::Script_Han, // TraditionalChinese
377 QChar::Script_Han, // Japanese
378 QChar::Script_Hangul, // Korean
379 QChar::Script_Latin, // Vietnamese
380 QChar::Script_Common, // Symbol
381 QChar::Script_Ogham, // Ogham
382 QChar::Script_Runic, // Runic
383 QChar::Script_Nko // Nko
384};
385
387
389{
390 return scriptForWritingSystem[writingSystem];
391}
392
393
400static bool familySupportsWritingSystem(QtFontFamily *family, size_t writingSystem)
401{
402 Q_ASSERT(family != nullptr);
403 Q_ASSERT(writingSystem != QFontDatabase::Any && writingSystem < QFontDatabase::WritingSystemsCount);
404
405 size_t ws = writingSystem;
406 do {
407 if ((family->writingSystems[ws] & QtFontFamily::Supported) != 0)
408 return true;
409 } while (writingSystem >= QFontDatabase::SimplifiedChinese && writingSystem <= QFontDatabase::Japanese && ++ws <= QFontDatabase::Japanese);
410
411 return false;
412}
413
415{
418 script) - scriptForWritingSystem);
419}
420
430static void parseFontName(const QString &name, QString &foundry, QString &family)
431{
432 int i = name.indexOf(u'[');
433 int li = name.lastIndexOf(u']');
434 if (i >= 0 && li >= 0 && i < li) {
435 foundry = name.mid(i + 1, li - i - 1);
436 if (i > 0 && name[i - 1] == u' ')
437 i--;
438 family = name.left(i);
439 } else {
440 foundry.clear();
441 family = name;
442 }
443
444 // capitalize the family/foundry names
445 bool space = true;
446 QChar *s = family.data();
447 int len = family.size();
448 while(len--) {
449 if (space) *s = s->toUpper();
450 space = s->isSpace();
451 ++s;
452 }
453
454 space = true;
455 s = foundry.data();
456 len = foundry.size();
457 while(len--) {
458 if (space) *s = s->toUpper();
459 space = s->isSpace();
460 ++s;
461 }
462}
463
464
466{
467 inline QtFontDesc() : family(nullptr), foundry(nullptr), style(nullptr), size(nullptr) {}
472};
473
474static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi)
475{
476 QString family;
477 family = desc.family->name;
478 if (! desc.foundry->name.isEmpty() && desc.family->count > 1)
479 family += " ["_L1 + desc.foundry->name + u']';
480 fontDef->families = QStringList(family);
481
482 if (desc.style->smoothScalable
484 || (desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch))) {
485 fontDef->pixelSize = request.pixelSize;
486 } else {
487 fontDef->pixelSize = desc.size->pixelSize;
488 }
489 fontDef->pointSize = request.pointSize;
490
491 fontDef->styleHint = request.styleHint;
492 fontDef->styleStrategy = request.styleStrategy;
493
494 if (!multi)
495 fontDef->weight = desc.style->key.weight;
496 if (!multi)
497 fontDef->style = desc.style->key.style;
498 fontDef->fixedPitch = desc.family->fixedPitch;
499 fontDef->ignorePitch = false;
500}
501
503{
504 // list of families to try
505 QStringList family_list;
506
507 family_list << req.families;
508 // append the substitute list for each family in family_list
509 for (int i = 0, size = family_list.size(); i < size; ++i)
510 family_list += QFont::substitutes(family_list.at(i));
511
512 return family_list;
513}
514
515Q_GLOBAL_STATIC(QRecursiveMutex, fontDatabaseMutex)
516
517// used in qguiapplication.cpp
519{
521 db->fallbacksCache.clear();
522 db->clearFamilies();
523}
524
525// used in qfont.cpp
527{
528 return fontDatabaseMutex();
529}
530
532{
533 static QFontDatabasePrivate instance;
534 return &instance;
535}
536
537void qt_registerFont(const QString &familyName, const QString &stylename,
538 const QString &foundryname, int weight,
539 QFont::Style style, int stretch, bool antialiased,
540 bool scalable, int pixelSize, bool fixedPitch,
541 const QSupportedWritingSystems &writingSystems, void *handle)
542{
544 qCDebug(lcFontDb) << "Adding font: familyName" << familyName << "stylename" << stylename << "weight" << weight
545 << "style" << style << "pixelSize" << pixelSize << "antialiased" << antialiased << "fixed" << fixedPitch;
546 QtFontStyle::Key styleKey;
547 styleKey.style = style;
548 styleKey.weight = weight;
549 styleKey.stretch = stretch;
550 QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated);
551 f->fixedPitch = fixedPitch;
552
553 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
554 if (writingSystems.supported(QFontDatabase::WritingSystem(i)))
555 f->writingSystems[i] = QtFontFamily::Supported;
556 }
557
558 QtFontFoundry *foundry = f->foundry(foundryname, true);
559 QtFontStyle *fontStyle = foundry->style(styleKey, stylename, true);
560 fontStyle->smoothScalable = scalable;
561 fontStyle->antialiased = antialiased;
563 if (size->handle) {
565 if (integration)
566 integration->fontDatabase()->releaseHandle(size->handle);
567 }
568 size->handle = handle;
569 f->populated = true;
570}
571
572void qt_registerFontFamily(const QString &familyName)
573{
574 qCDebug(lcFontDb) << "Registering family" << familyName;
575
576 // Create uninitialized/unpopulated family
578}
579
580void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
581{
582 if (alias.isEmpty())
583 return;
584
585 qCDebug(lcFontDb) << "Registering alias" << alias << "to family" << familyName;
586
588 QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily);
589 if (!f)
590 return;
591
592 if (f->aliases.contains(alias, Qt::CaseInsensitive))
593 return;
594
595 f->aliases.push_back(alias);
596}
597
599{
600 if (!alias.isEmpty()) {
601 const auto *d = QFontDatabasePrivate::instance();
602 for (int i = 0; i < d->count; ++i)
603 if (d->families[i]->matchesFamilyName(alias))
604 return d->families[i]->name;
605 }
606 return alias;
607}
608
609bool qt_isFontFamilyPopulated(const QString &familyName)
610{
612 QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily);
613 return f != nullptr && f->populated;
614}
615
624{
625 Q_UNUSED(family);
626 Q_UNUSED(styleHint);
627
628 QStringList preferredFallbacks;
629 QStringList otherFallbacks;
630
631 auto writingSystem = qt_writing_system_for_script(script);
632 if (writingSystem >= QFontDatabase::WritingSystemsCount)
633 writingSystem = QFontDatabase::Any;
634
636 for (int i = 0; i < db->count; ++i) {
637 QtFontFamily *f = db->families[i];
638
639 f->ensurePopulated();
640
641 if (writingSystem != QFontDatabase::Any && !familySupportsWritingSystem(f, writingSystem))
642 continue;
643
644 for (int j = 0; j < f->count; ++j) {
645 QtFontFoundry *foundry = f->foundries[j];
646
647 for (int k = 0; k < foundry->count; ++k) {
648 QString name = foundry->name.isEmpty()
649 ? f->name
650 : f->name + " ["_L1 + foundry->name + u']';
651 if (style == foundry->styles[k]->key.style)
652 preferredFallbacks.append(name);
653 else
654 otherFallbacks.append(name);
655 }
656 }
657 }
658
659 return preferredFallbacks + otherFallbacks;
660}
661
663{
664 QMutexLocker locker(fontDatabaseMutex());
666
667 const QtFontFallbacksCacheKey cacheKey = { family, style, styleHint, script };
668
669 if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
670 return *fallbacks;
671
672 // make sure that the db has all fallback families
673 QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
674
675 QStringList::iterator i;
676 for (i = retList.begin(); i != retList.end(); ++i) {
677 bool contains = false;
678 for (int j = 0; j < db->count; j++) {
679 if (db->families[j]->matchesFamilyName(*i)) {
680 contains = true;
681 break;
682 }
683 }
684 if (!contains) {
685 i = retList.erase(i);
686 --i;
687 }
688 }
689
690 db->fallbacksCache.insert(cacheKey, new QStringList(retList));
691
692 return retList;
693}
694
696{
697 QMutexLocker locker(fontDatabaseMutex());
698 return fallbacksForFamily(family, style, styleHint, script);
699}
700
701QFontEngine *QFontDatabasePrivate::loadSingleEngine(int script,
702 const QFontDef &request,
703 QtFontFamily *family, QtFontFoundry *foundry,
704 QtFontStyle *style, QtFontSize *size)
705{
706 Q_UNUSED(foundry);
707
708 Q_ASSERT(size);
710 int pixelSize = size->pixelSize;
712 || pfdb->fontsAlwaysScalable()) {
713 pixelSize = request.pixelSize;
714 }
715
716 QFontDef def = request;
717 def.pixelSize = pixelSize;
718
719 QFontCache *fontCache = QFontCache::instance();
720
721 QFontCache::Key key(def,script);
722 QFontEngine *engine = fontCache->findEngine(key);
723 if (!engine) {
724 const bool cacheForCommonScript = script != QChar::Script_Common
726
727 if (Q_LIKELY(cacheForCommonScript)) {
728 // fast path: check if engine was loaded for another script
729 key.script = QChar::Script_Common;
730 engine = fontCache->findEngine(key);
731 key.script = script;
732 if (engine) {
733 // Also check for OpenType tables when using complex scripts
734 if (Q_UNLIKELY(!engine->supportsScript(QChar::Script(script)))) {
735 qWarning(" OpenType support missing for \"%s\", script %d",
736 qPrintable(def.families.first()), script);
737 return nullptr;
738 }
739
740 engine->isSmoothlyScalable = style->smoothScalable;
741 fontCache->insertEngine(key, engine);
742 return engine;
743 }
744 }
745
746 // To avoid synthesized stretch we need a matching stretch to be 100 after this point.
747 // If stretch didn't match exactly we need to calculate the new stretch factor.
748 // This only done if not matched by styleName.
749 if (style->key.stretch != 0 && request.stretch != 0
750 && (request.styleName.isEmpty() || request.styleName != style->styleName)) {
751 def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch;
752 } else if (request.stretch == QFont::AnyStretch) {
753 def.stretch = 100;
754 }
755
756 engine = pfdb->fontEngine(def, size->handle);
757 if (engine) {
758 // Also check for OpenType tables when using complex scripts
759 if (!engine->supportsScript(QChar::Script(script))) {
760 qWarning(" OpenType support missing for \"%s\", script %d",
761 +qPrintable(def.families.first()), script);
762 if (engine->ref.loadRelaxed() == 0)
763 delete engine;
764 return nullptr;
765 }
766
767 engine->isSmoothlyScalable = style->smoothScalable;
768 fontCache->insertEngine(key, engine);
769
770 if (Q_LIKELY(cacheForCommonScript && !engine->symbol)) {
771 // cache engine for Common script as well
772 key.script = QChar::Script_Common;
773 if (!fontCache->findEngine(key))
774 fontCache->insertEngine(key, engine);
775 }
776 }
777 }
778 return engine;
779}
780
781QFontEngine *QFontDatabasePrivate::loadEngine(int script, const QFontDef &request,
782 QtFontFamily *family, QtFontFoundry *foundry,
783 QtFontStyle *style, QtFontSize *size)
784{
785 QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
786
787 if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
788 Q_TRACE(QFontDatabase_loadEngine, request.families.join(QLatin1Char(';')), request.pointSize);
789
791 QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
792 if (!request.fallBackFamilies.isEmpty()) {
793 QStringList fallbacks = request.fallBackFamilies;
794
795 QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
796 if (styleHint == QFont::AnyStyle && request.fixedPitch)
797 styleHint = QFont::TypeWriter;
798
799 fallbacks += fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script));
800
801 pfMultiEngine->setFallbackFamiliesList(fallbacks);
802 }
803 engine = pfMultiEngine;
804
805 // Cache Multi font engine as well in case we got the single
806 // font engine when we are actually looking for a Multi one
807 QFontCache::Key key(request, script, 1);
809 }
810
811 return engine;
812}
813
815{
816 while (count) {
817 // bitfield count-- in while condition does not work correctly in mwccsym2
818 count--;
820 if (integration)
822 }
823
824 free(pixelSizes);
825}
826
827static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
828 const QString &styleName = QString())
829{
830 int best = 0;
831 int dist = 0xffff;
832
833 for ( int i = 0; i < foundry->count; i++ ) {
834 QtFontStyle *style = foundry->styles[i];
835
836 if (!styleName.isEmpty() && styleName == style->styleName) {
837 dist = 0;
838 best = i;
839 break;
840 }
841
842 int d = qAbs( (int(styleKey.weight) - int(style->key.weight)) / 10 );
843
844 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
845 d += qAbs( styleKey.stretch - style->key.stretch );
846 }
847
848 if (styleKey.style != style->key.style) {
849 if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
850 // one is italic, the other oblique
851 d += 0x0001;
852 else
853 d += 0x1000;
854 }
855
856 if ( d < dist ) {
857 best = i;
858 dist = d;
859 }
860 }
861
862 qCDebug(lcFontMatch, " best style has distance 0x%x", dist );
863 return foundry->styles[best];
864}
865
866
867unsigned int QFontDatabasePrivate::bestFoundry(int script, unsigned int score, int styleStrategy,
868 const QtFontFamily *family, const QString &foundry_name,
869 QtFontStyle::Key styleKey, int pixelSize, char pitch,
871{
872 Q_UNUSED(script);
873 Q_UNUSED(pitch);
874
875 desc->foundry = nullptr;
876 desc->style = nullptr;
877 desc->size = nullptr;
878
879
880 qCDebug(lcFontMatch, " REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
881
882 for (int x = 0; x < family->count; ++x) {
883 QtFontFoundry *foundry = family->foundries[x];
884 if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
885 continue;
886
887 qCDebug(lcFontMatch, " looking for matching style in foundry '%s' %d",
888 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
889
890 QtFontStyle *style = bestStyle(foundry, styleKey, styleName);
891
892 if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
893 qCDebug(lcFontMatch, " ForceOutline set, but not smoothly scalable");
894 continue;
895 }
896
897 int px = -1;
898 QtFontSize *size = nullptr;
899
900 // 1. see if we have an exact matching size
901 if (!(styleStrategy & QFont::ForceOutline)) {
902 size = style->pixelSize(pixelSize);
903 if (size) {
904 qCDebug(lcFontMatch, " found exact size match (%d pixels)", size->pixelSize);
905 px = size->pixelSize;
906 }
907 }
908
909 // 2. see if we have a smoothly scalable font
910 if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
912 if (size) {
913 qCDebug(lcFontMatch, " found smoothly scalable font (%d pixels)", pixelSize);
914 px = pixelSize;
915 }
916 }
917
918 // 3. see if we have a bitmap scalable font
919 if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
920 size = style->pixelSize(0);
921 if (size) {
922 qCDebug(lcFontMatch, " found bitmap scalable font (%d pixels)", pixelSize);
923 px = pixelSize;
924 }
925 }
926
927
928 // 4. find closest size match
929 if (! size) {
930 unsigned int distance = ~0u;
931 for (int x = 0; x < style->count; ++x) {
932
933 unsigned int d;
934 if (style->pixelSizes[x].pixelSize < pixelSize) {
935 // penalize sizes that are smaller than the
936 // requested size, due to truncation from floating
937 // point to integer conversions
938 d = pixelSize - style->pixelSizes[x].pixelSize + 1;
939 } else {
940 d = style->pixelSizes[x].pixelSize - pixelSize;
941 }
942
943 if (d < distance) {
944 distance = d;
945 size = style->pixelSizes + x;
946 qCDebug(lcFontMatch, " best size so far: %3d (%d)", size->pixelSize, pixelSize);
947 }
948 }
949
950 if (!size) {
951 qCDebug(lcFontMatch, " no size supports the script we want");
952 continue;
953 }
954
955 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
956 (distance * 10 / pixelSize) >= 2) {
957 // the closest size is not close enough, go ahead and
958 // use a bitmap scaled font
959 size = style->pixelSize(0);
960 px = pixelSize;
961 } else {
962 px = size->pixelSize;
963 }
964 }
965
966
967 unsigned int this_score = 0x0000;
968 enum {
969 PitchMismatch = 0x4000,
970 StyleMismatch = 0x2000,
971 BitmapScaledPenalty = 0x1000
972 };
973 if (pitch != '*') {
974 if ((pitch == 'm' && !family->fixedPitch)
975 || (pitch == 'p' && family->fixedPitch))
976 this_score += PitchMismatch;
977 }
978 if (styleKey != style->key)
979 this_score += StyleMismatch;
980 if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
981 this_score += BitmapScaledPenalty;
982 if (px != pixelSize) // close, but not exact, size match
983 this_score += qAbs(px - pixelSize);
984
985 if (this_score < score) {
986 qCDebug(lcFontMatch, " found a match: score %x best score so far %x",
987 this_score, score);
988
989 score = this_score;
990 desc->foundry = foundry;
991 desc->style = style;
992 desc->size = size;
993 } else {
994 qCDebug(lcFontMatch, " score %x no better than best %x", this_score, score);
995 }
996 }
997
998 return score;
999}
1000
1001static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
1002{
1003 if (familyName.isEmpty())
1004 return true;
1005 return f->matchesFamilyName(familyName);
1006}
1007
1013int QFontDatabasePrivate::match(int script, const QFontDef &request, const QString &family_name,
1014 const QString &foundry_name, QtFontDesc *desc, const QList<int> &blacklistedFamilies,
1015 unsigned int *resultingScore)
1016{
1017 int result = -1;
1018
1019 QtFontStyle::Key styleKey;
1020 styleKey.style = request.style;
1021 styleKey.weight = request.weight;
1022 // Prefer a stretch closest to 100.
1023 styleKey.stretch = request.stretch ? request.stretch : 100;
1024 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1025
1026
1027 qCDebug(lcFontMatch, "QFontDatabasePrivate::match\n"
1028 " request:\n"
1029 " family: %s [%s], script: %d\n"
1030 " styleName: %s\n"
1031 " weight: %d, style: %d\n"
1032 " stretch: %d\n"
1033 " pixelSize: %g\n"
1034 " pitch: %c",
1035 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1036 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), script,
1037 request.styleName.isEmpty() ? "-- any --" : request.styleName.toLatin1().constData(),
1038 request.weight, request.style, request.stretch, request.pixelSize, pitch);
1039
1040 desc->family = nullptr;
1041 desc->foundry = nullptr;
1042 desc->style = nullptr;
1043 desc->size = nullptr;
1044
1045 unsigned int score = ~0u;
1046
1047 QMutexLocker locker(fontDatabaseMutex());
1049
1050 auto writingSystem = qt_writing_system_for_script(script);
1051 if (writingSystem >= QFontDatabase::WritingSystemsCount)
1052 writingSystem = QFontDatabase::Any;
1053
1055 for (int x = 0; x < db->count; ++x) {
1056 if (blacklistedFamilies.contains(x))
1057 continue;
1058 QtFontDesc test;
1059 test.family = db->families[x];
1060
1061 if (!matchFamilyName(family_name, test.family))
1062 continue;
1063 if (!test.family->ensurePopulated())
1064 continue;
1065
1066 // Check if family is supported in the script we want
1067 if (writingSystem != QFontDatabase::Any && !familySupportsWritingSystem(test.family, writingSystem))
1068 continue;
1069
1070 // as we know the script is supported, we can be sure
1071 // to find a matching font here.
1072 unsigned int newscore =
1073 bestFoundry(script, score, request.styleStrategy,
1074 test.family, foundry_name, styleKey, request.pixelSize, pitch,
1075 &test, request.styleName);
1076 if (test.foundry == nullptr && !foundry_name.isEmpty()) {
1077 // the specific foundry was not found, so look for
1078 // any foundry matching our requirements
1079 newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1080 QString(), styleKey, request.pixelSize,
1081 pitch, &test, request.styleName);
1082 }
1083
1084 if (newscore < score) {
1085 result = x;
1086 score = newscore;
1087 *desc = test;
1088 }
1089 if (newscore < 10) // xlfd instead of FT... just accept it
1090 break;
1091 }
1092
1093 if (resultingScore != nullptr)
1094 *resultingScore = score;
1095
1096 return result;
1097}
1098
1100{
1102 if (weight > QFont::Normal) {
1103 if (weight >= QFont::Black)
1104 result = QCoreApplication::translate("QFontDatabase", "Black");
1105 else if (weight >= QFont::ExtraBold)
1106 result = QCoreApplication::translate("QFontDatabase", "Extra Bold");
1107 else if (weight >= QFont::Bold)
1108 result = QCoreApplication::translate("QFontDatabase", "Bold");
1109 else if (weight >= QFont::DemiBold)
1110 result = QCoreApplication::translate("QFontDatabase", "Demi Bold");
1111 else if (weight >= QFont::Medium)
1112 result = QCoreApplication::translate("QFontDatabase", "Medium", "The Medium font weight");
1113 } else {
1114 if (weight <= QFont::Thin)
1115 result = QCoreApplication::translate("QFontDatabase", "Thin");
1116 else if (weight <= QFont::ExtraLight)
1117 result = QCoreApplication::translate("QFontDatabase", "Extra Light");
1118 else if (weight <= QFont::Light)
1119 result = QCoreApplication::translate("QFontDatabase", "Light");
1120 }
1121
1122 if (style == QFont::StyleItalic)
1123 result += u' ' + QCoreApplication::translate("QFontDatabase", "Italic");
1124 else if (style == QFont::StyleOblique)
1125 result += u' ' + QCoreApplication::translate("QFontDatabase", "Oblique");
1126
1127 if (result.isEmpty())
1128 result = QCoreApplication::translate("QFontDatabase", "Normal", "The Normal or Regular font weight");
1129
1130 return result.simplified();
1131}
1132
1139{
1141 : font.styleName();
1142}
1143
1150{
1151 return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style())
1152 : fontInfo.styleName();
1153}
1154
1155
1324{
1326 if (!d->populated) {
1327 // The font database may have been partially populated, but to ensure
1328 // we can answer queries for any platform- or user-provided family we
1329 // need to fully populate it now.
1330 qCDebug(lcFontDb) << "Populating font database";
1331
1332 if (Q_UNLIKELY(qGuiApp == nullptr || QGuiApplicationPrivate::platformIntegration() == nullptr))
1333 qFatal("QFontDatabase: Must construct a QGuiApplication before accessing QFontDatabase");
1334
1335 auto *platformFontDatabase = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
1336 platformFontDatabase->populateFontDatabase();
1337
1338 for (int i = 0; i < d->applicationFonts.size(); i++) {
1339 auto *font = &d->applicationFonts[i];
1340 if (!font->isNull() && !font->isPopulated())
1341 platformFontDatabase->addApplicationFont(font->data, font->fileName, font);
1342 }
1343
1344 // Note: Both application fonts and platform fonts may be added
1345 // after this initial population, so the only thing we are tracking
1346 // is whether we've done our part in ensuring a filled font database.
1347 d->populated = true;
1348 }
1349 return d;
1350}
1351
1360{
1361 QMutexLocker locker(fontDatabaseMutex());
1363
1364 quint64 writingSystemsFound = 0;
1365 static_assert(WritingSystemsCount < 64);
1366
1367 for (int i = 0; i < d->count; ++i) {
1368 QtFontFamily *family = d->families[i];
1369 if (!family->ensurePopulated())
1370 continue;
1371
1372 if (family->count == 0)
1373 continue;
1374 for (uint x = Latin; x < uint(WritingSystemsCount); ++x) {
1376 writingSystemsFound |= quint64(1) << x;
1377 }
1378 }
1379
1380 // mutex protection no longer needed - just working on local data now:
1381 locker.unlock();
1382
1384 list.reserve(qPopulationCount(writingSystemsFound));
1385 for (uint x = Latin ; x < uint(WritingSystemsCount); ++x) {
1386 if (writingSystemsFound & (quint64(1) << x))
1388 }
1389 return list;
1390}
1391
1392
1400{
1401 QString familyName, foundryName;
1402 parseFontName(family, foundryName, familyName);
1403
1404 QMutexLocker locker(fontDatabaseMutex());
1406
1408 QtFontFamily *f = d->family(familyName);
1409 if (!f || f->count == 0)
1410 return list;
1411
1412 for (int x = Latin; x < WritingSystemsCount; ++x) {
1413 const WritingSystem writingSystem = WritingSystem(x);
1414 if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1415 list.append(writingSystem);
1416 }
1417 return list;
1418}
1419
1420
1432{
1433 QMutexLocker locker(fontDatabaseMutex());
1435
1436 QStringList flist;
1437 for (int i = 0; i < d->count; i++) {
1438 QtFontFamily *f = d->families[i];
1439 if (f->populated && f->count == 0)
1440 continue;
1441 if (writingSystem != Any) {
1442 if (!f->ensurePopulated())
1443 continue;
1444 if (f->writingSystems[writingSystem] != QtFontFamily::Supported)
1445 continue;
1446 }
1447 if (!f->populated || f->count == 1) {
1448 flist.append(f->name);
1449 } else {
1450 for (int j = 0; j < f->count; j++) {
1451 QString str = f->name;
1452 QString foundry = f->foundries[j]->name;
1453 if (!foundry.isEmpty()) {
1454 str += " ["_L1;
1455 str += foundry;
1456 str += u']';
1457 }
1458 flist.append(str);
1459 }
1460 }
1461 }
1462 return flist;
1463}
1464
1473{
1474 QString familyName, foundryName;
1475 parseFontName(family, foundryName, familyName);
1476
1477 QMutexLocker locker(fontDatabaseMutex());
1479
1480 QStringList l;
1481 QtFontFamily *f = d->family(familyName);
1482 if (!f)
1483 return l;
1484
1485 QtFontFoundry allStyles(foundryName);
1486 for (int j = 0; j < f->count; j++) {
1487 QtFontFoundry *foundry = f->foundries[j];
1488 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1489 for (int k = 0; k < foundry->count; k++) {
1490 QtFontStyle::Key ke(foundry->styles[k]->key);
1491 ke.stretch = 0;
1492 allStyles.style(ke, foundry->styles[k]->styleName, true);
1493 }
1494 }
1495 }
1496
1497 l.reserve(allStyles.count);
1498 for (int i = 0; i < allStyles.count; i++) {
1499 l.append(allStyles.styles[i]->styleName.isEmpty() ?
1500 styleStringHelper(allStyles.styles[i]->key.weight,
1501 (QFont::Style)allStyles.styles[i]->key.style) :
1502 allStyles.styles[i]->styleName);
1503 }
1504 return l;
1505}
1506
1513 const QString &style)
1514{
1515 Q_UNUSED(style);
1516
1517 QString familyName, foundryName;
1518 parseFontName(family, foundryName, familyName);
1519
1520 QMutexLocker locker(fontDatabaseMutex());
1522
1523 QtFontFamily *f = d->family(familyName);
1524 return (f && f->fixedPitch);
1525}
1526
1538 const QString &style)
1539{
1540 bool bitmapScalable = false;
1541 QString familyName, foundryName;
1542 parseFontName(family, foundryName, familyName);
1543
1544 QMutexLocker locker(fontDatabaseMutex());
1546
1547 QtFontFamily *f = d->family(familyName);
1548 if (!f) return bitmapScalable;
1549
1550 QtFontStyle::Key styleKey(style);
1551 for (int j = 0; j < f->count; j++) {
1552 QtFontFoundry *foundry = f->foundries[j];
1553 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1554 for (int k = 0; k < foundry->count; k++)
1555 if ((style.isEmpty() ||
1556 foundry->styles[k]->styleName == style ||
1557 foundry->styles[k]->key == styleKey)
1558 && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1559 bitmapScalable = true;
1560 goto end;
1561 }
1562 }
1563 }
1564 end:
1565 return bitmapScalable;
1566}
1567
1568
1577bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style)
1578{
1579 bool smoothScalable = false;
1580 QString familyName, foundryName;
1581 parseFontName(family, foundryName, familyName);
1582
1583 QMutexLocker locker(fontDatabaseMutex());
1585
1586 QtFontFamily *f = d->family(familyName);
1587 if (!f) {
1588 for (int i = 0; i < d->count; i++) {
1589 if (d->families[i]->matchesFamilyName(familyName)) {
1590 f = d->families[i];
1591 if (f->ensurePopulated())
1592 break;
1593 }
1594 }
1595 }
1596 if (!f) return smoothScalable;
1597
1598 const QtFontStyle::Key styleKey(style);
1599 for (int j = 0; j < f->count; j++) {
1600 QtFontFoundry *foundry = f->foundries[j];
1601 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1602 for (int k = 0; k < foundry->count; k++) {
1603 const QtFontStyle *fontStyle = foundry->styles[k];
1605 fontStyle->smoothScalable
1606 && ((style.isEmpty()
1607 || fontStyle->styleName == style
1608 || fontStyle->key == styleKey)
1609 || (fontStyle->styleName.isEmpty()
1610 && style == styleStringHelper(fontStyle->key.weight,
1611 QFont::Style(fontStyle->key.style))));
1612 if (smoothScalable)
1613 goto end;
1614 }
1615 }
1616 }
1617 end:
1618 return smoothScalable;
1619}
1620
1628 const QString &style)
1629{
1630 QMutexLocker locker(fontDatabaseMutex());
1631 if (isSmoothlyScalable(family, style))
1632 return true;
1633 return isBitmapScalable(family, style);
1634}
1635
1636
1644 const QString &styleName)
1645{
1646 if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
1647 return standardSizes();
1648
1649 bool smoothScalable = false;
1650 QString familyName, foundryName;
1651 parseFontName(family, foundryName, familyName);
1652
1653 QMutexLocker locker(fontDatabaseMutex());
1655
1657
1658 QtFontFamily *fam = d->family(familyName);
1659 if (!fam) return sizes;
1660
1661
1662 const int dpi = qt_defaultDpiY(); // embedded
1663
1664 QtFontStyle::Key styleKey(styleName);
1665 for (int j = 0; j < fam->count; j++) {
1666 QtFontFoundry *foundry = fam->foundries[j];
1667 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1668 QtFontStyle *style = foundry->style(styleKey, styleName);
1669 if (!style) continue;
1670
1671 if (style->smoothScalable) {
1672 smoothScalable = true;
1673 goto end;
1674 }
1675 for (int l = 0; l < style->count; l++) {
1676 const QtFontSize *size = style->pixelSizes + l;
1677
1678 if (size->pixelSize != 0 && size->pixelSize != SMOOTH_SCALABLE) {
1679 const int pointSize = qRound(size->pixelSize * 72.0 / dpi);
1680 if (! sizes.contains(pointSize))
1681 sizes.append(pointSize);
1682 }
1683 }
1684 }
1685 }
1686 end:
1687 if (smoothScalable)
1688 return standardSizes();
1689
1690 std::sort(sizes.begin(), sizes.end());
1691 return sizes;
1692}
1693
1700QFont QFontDatabase::font(const QString &family, const QString &style,
1701 int pointSize)
1702{
1703 QString familyName, foundryName;
1704 parseFontName(family, foundryName, familyName);
1705 QMutexLocker locker(fontDatabaseMutex());
1707
1708 QtFontFoundry allStyles(foundryName);
1709 QtFontFamily *f = d->family(familyName);
1710 if (!f) return QGuiApplication::font();
1711
1712 for (int j = 0; j < f->count; j++) {
1713 QtFontFoundry *foundry = f->foundries[j];
1714 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1715 for (int k = 0; k < foundry->count; k++)
1716 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1717 }
1718 }
1719
1720 QtFontStyle::Key styleKey(style);
1721 QtFontStyle *s = bestStyle(&allStyles, styleKey, style);
1722
1723 if (!s) // no styles found?
1724 return QGuiApplication::font();
1725
1726 QFont fnt(QStringList{family}, pointSize, s->key.weight);
1727 fnt.setStyle((QFont::Style)s->key.style);
1728 if (!s->styleName.isEmpty())
1729 fnt.setStyleName(s->styleName);
1730 return fnt;
1731}
1732
1733
1743 const QString &styleName)
1744{
1745 if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
1746 return standardSizes();
1747
1748 bool smoothScalable = false;
1749 QString familyName, foundryName;
1750 parseFontName(family, foundryName, familyName);
1751
1752 QMutexLocker locker(fontDatabaseMutex());
1754
1756
1757 QtFontFamily *fam = d->family(familyName);
1758 if (!fam)
1759 return sizes;
1760
1761 const int dpi = qt_defaultDpiY(); // embedded
1762
1763 QtFontStyle::Key styleKey(styleName);
1764 for (int j = 0; j < fam->count; j++) {
1765 QtFontFoundry *foundry = fam->foundries[j];
1766 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1767 QtFontStyle *style = foundry->style(styleKey, styleName);
1768 if (!style) continue;
1769
1770 if (style->smoothScalable) {
1771 smoothScalable = true;
1772 goto end;
1773 }
1774 for (int l = 0; l < style->count; l++) {
1775 const QtFontSize *size = style->pixelSizes + l;
1776
1777 if (size->pixelSize != 0 && size->pixelSize != SMOOTH_SCALABLE) {
1778 const int pointSize = qRound(size->pixelSize * 72.0 / dpi);
1779 if (! sizes.contains(pointSize))
1780 sizes.append(pointSize);
1781 }
1782 }
1783 }
1784 }
1785 end:
1786 if (smoothScalable)
1788
1789 std::sort(sizes.begin(), sizes.end());
1790 return sizes;
1791}
1792
1793
1800{
1802}
1803
1804
1811bool QFontDatabase::italic(const QString &family, const QString &style)
1812{
1813 QString familyName, foundryName;
1814 parseFontName(family, foundryName, familyName);
1815
1816 QMutexLocker locker(fontDatabaseMutex());
1818
1819 QtFontFoundry allStyles(foundryName);
1820 QtFontFamily *f = d->family(familyName);
1821 if (!f) return false;
1822
1823 for (int j = 0; j < f->count; j++) {
1824 QtFontFoundry *foundry = f->foundries[j];
1825 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1826 for (int k = 0; k < foundry->count; k++)
1827 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1828 }
1829 }
1830
1831 QtFontStyle::Key styleKey(style);
1832 QtFontStyle *s = allStyles.style(styleKey, style);
1833 return s && s->key.style == QFont::StyleItalic;
1834}
1835
1836
1843bool QFontDatabase::bold(const QString &family,
1844 const QString &style)
1845{
1846 QString familyName, foundryName;
1847 parseFontName(family, foundryName, familyName);
1848
1849 QMutexLocker locker(fontDatabaseMutex());
1851
1852 QtFontFoundry allStyles(foundryName);
1853 QtFontFamily *f = d->family(familyName);
1854 if (!f) return false;
1855
1856 for (int j = 0; j < f->count; j++) {
1857 QtFontFoundry *foundry = f->foundries[j];
1858 if (foundryName.isEmpty() ||
1859 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1860 for (int k = 0; k < foundry->count; k++)
1861 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1862 }
1863 }
1864
1865 QtFontStyle::Key styleKey(style);
1866 QtFontStyle *s = allStyles.style(styleKey, style);
1867 return s && s->key.weight >= QFont::Bold;
1868}
1869
1870
1879 const QString &style)
1880{
1881 QString familyName, foundryName;
1882 parseFontName(family, foundryName, familyName);
1883
1884 QMutexLocker locker(fontDatabaseMutex());
1886
1887 QtFontFoundry allStyles(foundryName);
1888 QtFontFamily *f = d->family(familyName);
1889 if (!f) return -1;
1890
1891 for (int j = 0; j < f->count; j++) {
1892 QtFontFoundry *foundry = f->foundries[j];
1893 if (foundryName.isEmpty() ||
1894 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1895 for (int k = 0; k < foundry->count; k++)
1896 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1897 }
1898 }
1899
1900 QtFontStyle::Key styleKey(style);
1901 QtFontStyle *s = allStyles.style(styleKey, style);
1902 return s ? s->key.weight : -1;
1903}
1904
1905
1908{
1909 QString parsedFamily, foundry;
1910 parseFontName(family, foundry, parsedFamily);
1911 const QString familyAlias = QFontDatabasePrivate::resolveFontFamilyAlias(parsedFamily);
1912
1913 QMutexLocker locker(fontDatabaseMutex());
1915
1916 for (int i = 0; i < d->count; i++) {
1917 QtFontFamily *f = d->families[i];
1918 if (f->populated && f->count == 0)
1919 continue;
1920 if (familyAlias.compare(f->name, Qt::CaseInsensitive) == 0)
1921 return true;
1922 }
1923
1924 return false;
1925}
1926
1927
1941{
1943}
1944
1945
1951{
1952 const char *name = nullptr;
1953 switch (writingSystem) {
1954 case Any:
1955 name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
1956 break;
1957 case Latin:
1958 name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
1959 break;
1960 case Greek:
1961 name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
1962 break;
1963 case Cyrillic:
1964 name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
1965 break;
1966 case Armenian:
1967 name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
1968 break;
1969 case Hebrew:
1970 name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
1971 break;
1972 case Arabic:
1973 name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
1974 break;
1975 case Syriac:
1976 name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
1977 break;
1978 case Thaana:
1979 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
1980 break;
1981 case Devanagari:
1982 name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
1983 break;
1984 case Bengali:
1985 name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
1986 break;
1987 case Gurmukhi:
1988 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
1989 break;
1990 case Gujarati:
1991 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
1992 break;
1993 case Oriya:
1994 name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
1995 break;
1996 case Tamil:
1997 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
1998 break;
1999 case Telugu:
2000 name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
2001 break;
2002 case Kannada:
2003 name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
2004 break;
2005 case Malayalam:
2006 name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
2007 break;
2008 case Sinhala:
2009 name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
2010 break;
2011 case Thai:
2012 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
2013 break;
2014 case Lao:
2015 name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
2016 break;
2017 case Tibetan:
2018 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
2019 break;
2020 case Myanmar:
2021 name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
2022 break;
2023 case Georgian:
2024 name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
2025 break;
2026 case Khmer:
2027 name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
2028 break;
2029 case SimplifiedChinese:
2030 name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
2031 break;
2032 case TraditionalChinese:
2033 name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
2034 break;
2035 case Japanese:
2036 name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
2037 break;
2038 case Korean:
2039 name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
2040 break;
2041 case Vietnamese:
2042 name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
2043 break;
2044 case Symbol:
2045 name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
2046 break;
2047 case Ogham:
2048 name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
2049 break;
2050 case Runic:
2051 name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
2052 break;
2053 case Nko:
2054 name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko");
2055 break;
2056 default:
2057 Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
2058 break;
2059 }
2060 return QCoreApplication::translate("QFontDatabase", name);
2061}
2062
2067{
2068 return [&]() -> QStringView {
2069 switch (writingSystem) {
2070 case QFontDatabase::Any:
2072 // show only ascii characters
2073 return u"AaBbzZ";
2075 // This is cheating... we only show latin-1 characters so that we don't
2076 // end up loading lots of fonts - at least on X11...
2077 return u"Aa\x00C3\x00E1Zz";
2079 return u"\x0393\x03B1\x03A9\x03C9";
2081 return u"\x0414\x0434\x0436\x044f";
2083 return u"\x053f\x054f\x056f\x057f";
2085 return u"\x05D0\x05D1\x05D2\x05D3";
2087 return u"\x0623\x0628\x062C\x062F\x064A\x0629\x0020\x0639\x0631\x0628\x064A\x0629";
2089 return u"\x0715\x0725\x0716\x0726";
2091 return u"\x0784\x0794\x078c\x078d";
2093 return u"\x0905\x0915\x0925\x0935";
2095 return u"\x0986\x0996\x09a6\x09b6";
2097 return u"\x0a05\x0a15\x0a25\x0a35";
2099 return u"\x0a85\x0a95\x0aa5\x0ab5";
2101 return u"\x0b06\x0b16\x0b2b\x0b36";
2103 return u"\x0b89\x0b99\x0ba9\x0bb9";
2105 return u"\x0c05\x0c15\x0c25\x0c35";
2107 return u"\x0c85\x0c95\x0ca5\x0cb5";
2109 return u"\x0d05\x0d15\x0d25\x0d35";
2111 return u"\x0d90\x0da0\x0db0\x0dc0";
2113 return u"\x0e02\x0e12\x0e22\x0e32";
2114 case QFontDatabase::Lao:
2115 return u"\x0e8d\x0e9d\x0ead\x0ebd";
2117 return u"\x0f00\x0f01\x0f02\x0f03";
2119 return u"\x1000\x1001\x1002\x1003";
2121 return u"\x10a0\x10b0\x10c0\x10d0";
2123 return u"\x1780\x1790\x17b0\x17c0";
2125 return u"\x4e2d\x6587\x8303\x4f8b";
2127 return u"\x4e2d\x6587\x7bc4\x4f8b";
2129 return u"\x30b5\x30f3\x30d7\x30eb\x3067\x3059";
2131 return u"\xac00\xac11\xac1a\xac2f";
2133 return u"\x1ED7\x1ED9\x1ED1\x1ED3";
2135 return u"\x1681\x1682\x1683\x1684";
2137 return u"\x16a0\x16a1\x16a2\x16a3";
2138 case QFontDatabase::Nko:
2139 return u"\x7ca\x7cb\x7cc\x7cd";
2140 default:
2141 return nullptr;
2142 }
2143 }().toString();
2144}
2145
2147{
2148 QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2149}
2150
2151// used from qfontengine_ft.cpp
2153{
2154 QMutexLocker locker(fontDatabaseMutex());
2156}
2157
2159{
2161 font.data = fontData;
2162 font.fileName = fileName;
2163
2164 Q_TRACE(QFontDatabasePrivate_addAppFont, fileName);
2165
2166 int i;
2167 for (i = 0; i < applicationFonts.size(); ++i)
2168 if (applicationFonts.at(i).isNull())
2169 break;
2170 if (i >= applicationFonts.size()) {
2171 applicationFonts.append(ApplicationFont());
2172 i = applicationFonts.size() - 1;
2173 }
2174
2175 if (font.fileName.isEmpty() && !fontData.isEmpty())
2176 font.fileName = ":qmemoryfonts/"_L1 + QString::number(i);
2177
2178 auto *platformFontDatabase = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
2179 platformFontDatabase->addApplicationFont(font.data, font.fileName, &font);
2180 if (font.properties.isEmpty())
2181 return -1;
2182
2183 applicationFonts[i] = font;
2184
2185 // The font cache may have cached lookups for the font that was now
2186 // loaded, so it has to be flushed.
2188
2189 emit qApp->fontDatabaseChanged();
2190
2191 return i;
2192}
2193
2195{
2196 for (int i = 0; i < applicationFonts.size(); ++i)
2197 if (applicationFonts.at(i).fileName == fileName)
2198 return true;
2199 return false;
2200}
2201
2211
2216
2220{
2222 if (!QFileInfo(fileName).isNativePath()) {
2223 QFile f(fileName);
2224 if (!f.open(QIODevice::ReadOnly))
2225 return -1;
2226
2227 Q_TRACE(QFontDatabase_addApplicationFont, fileName);
2228
2229 data = f.readAll();
2230 }
2231 QMutexLocker locker(fontDatabaseMutex());
2233}
2234
2248{
2249 QMutexLocker locker(fontDatabaseMutex());
2250 return QFontDatabasePrivate::instance()->addAppFont(fontData, QString() /* fileName */);
2251}
2252
2262{
2263 QMutexLocker locker(fontDatabaseMutex());
2265
2267 ret.reserve(d->applicationFonts.value(id).properties.size());
2268
2269 for (const auto &properties : d->applicationFonts.value(id).properties)
2270 ret.append(properties.familyName);
2271
2272 return ret;
2273}
2274
2285{
2286 const QFont *font = nullptr;
2288 switch (type) {
2289 case GeneralFont:
2290 font = theme->font(QPlatformTheme::SystemFont);
2291 break;
2292 case FixedFont:
2293 font = theme->font(QPlatformTheme::FixedFont);
2294 break;
2295 case TitleFont:
2296 font = theme->font(QPlatformTheme::TitleBarFont);
2297 break;
2298 case SmallestReadableFont:
2299 font = theme->font(QPlatformTheme::MiniFont);
2300 break;
2301 }
2302 }
2303
2304 if (font)
2305 return *font;
2307 return integration->fontDatabase()->defaultFont();
2308 else
2309 return QFont();
2310}
2311
2324{
2325 QMutexLocker locker(fontDatabaseMutex());
2326
2328 if (handle < 0 || handle >= db->applicationFonts.size())
2329 return false;
2330
2331 db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
2332
2333 db->invalidate();
2334 return true;
2335}
2336
2350{
2351 QMutexLocker locker(fontDatabaseMutex());
2352
2354 if (!db || db->applicationFonts.isEmpty())
2355 return false;
2356
2357 db->applicationFonts.clear();
2358 db->invalidate();
2359 return true;
2360}
2361
2366 int script,
2367 bool preferScriptOverFamily)
2368{
2369 QMutexLocker locker(fontDatabaseMutex());
2370 ensureFontDatabase();
2371
2373
2374#ifdef Q_OS_WIN
2375 const QFontDef request = static_cast<QWindowsFontDatabaseBase *>(
2377 ->sanitizeRequest(req);
2378#else
2379 const QFontDef &request = req;
2380#endif
2381
2382#if defined(QT_BUILD_INTERNAL)
2383 // For testing purpose only, emulates an exact-matching monospace font
2384 if (qt_enable_test_font && request.families.first() == "__Qt__Box__Engine__"_L1) {
2385 engine = new QTestFontEngine(request.pixelSize);
2386 engine->fontDef = request;
2387 return engine;
2388 }
2389#endif
2390
2391 QFontCache *fontCache = QFontCache::instance();
2392
2393 // Until we specifically asked not to, try looking for Multi font engine
2394 // first, the last '1' indicates that we want Multi font engine instead
2395 // of single ones
2396 bool multi = !(request.styleStrategy & QFont::NoFontMerging);
2397 QFontCache::Key key(request, script, multi ? 1 : 0);
2398 engine = fontCache->findEngine(key);
2399 if (engine) {
2400 qCDebug(lcFontMatch, "Cache hit level 1");
2401 return engine;
2402 }
2403
2404 if (request.pixelSize > 0xffff) {
2405 // Stop absurd requests reaching the engines; pixel size is assumed to fit ushort
2406 qCDebug(lcFontMatch, "Rejecting request for pixel size %g2, returning box engine", double(request.pixelSize));
2407 return new QFontEngineBox(32); // not request.pixelSize, to avoid overflow/DOS
2408 }
2409
2410 QString family_name, foundry_name;
2411 const QString requestFamily = request.families.at(0);
2412 parseFontName(requestFamily, foundry_name, family_name);
2414 QList<int> blackListed;
2415 unsigned int score = UINT_MAX;
2416 int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed, &score);
2418 // We populated family aliases (e.g. localized families), so try again
2419 index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
2420 }
2421
2422 // If we do not find a match and NoFontMerging is set, use the requested font even if it does
2423 // not support the script.
2424 //
2425 // (we do this at the end to prefer foundries that support the script if they exist)
2426 if (index < 0 && !multi && !preferScriptOverFamily)
2427 index = match(QChar::Script_Common, request, family_name, foundry_name, &desc, blackListed);
2428
2429 if (index >= 0) {
2430 QFontDef fontDef = request;
2431 // Don't pass empty family names to the platform font database, since it will then invoke its own matching
2432 // and we will be out of sync with the matched font.
2433 if (fontDef.families.isEmpty())
2434 fontDef.families = QStringList(desc.family->name);
2435
2436 engine = loadEngine(script, fontDef, desc.family, desc.foundry, desc.style, desc.size);
2437
2438 if (engine)
2439 initFontDef(desc, request, &engine->fontDef, multi);
2440 else
2441 blackListed.append(index);
2442 } else {
2443 qCDebug(lcFontMatch, " NO MATCH FOUND\n");
2444 }
2445
2446 if (!engine) {
2447 if (!requestFamily.isEmpty()) {
2448 QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
2449 if (styleHint == QFont::AnyStyle && request.fixedPitch)
2450 styleHint = QFont::TypeWriter;
2451
2452 QStringList fallbacks = request.fallBackFamilies
2453 + fallbacksForFamily(requestFamily,
2454 QFont::Style(request.style),
2455 styleHint,
2456 QChar::Script(script));
2457 if (script > QChar::Script_Common)
2458 fallbacks += QString(); // Find the first font matching the specified script.
2459
2460 for (int i = 0; !engine && i < fallbacks.size(); i++) {
2461 QFontDef def = request;
2462 def.families = QStringList(fallbacks.at(i));
2463 QFontCache::Key key(def, script, multi ? 1 : 0);
2464 engine = fontCache->findEngine(key);
2465 if (!engine) {
2467 do {
2468 index = match(multi ? QChar::Script_Common : script, def, def.families.first(), ""_L1, &desc, blackListed);
2469 if (index >= 0) {
2470 QFontDef loadDef = def;
2471 if (loadDef.families.isEmpty())
2472 loadDef.families = QStringList(desc.family->name);
2473 engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
2474 if (engine)
2475 initFontDef(desc, loadDef, &engine->fontDef, multi);
2476 else
2477 blackListed.append(index);
2478 }
2479 } while (index >= 0 && !engine);
2480 }
2481 }
2482 }
2483
2484 if (!engine)
2485 engine = new QFontEngineBox(request.pixelSize);
2486
2487 qCDebug(lcFontMatch, "returning box engine");
2488 }
2489
2490 return engine;
2491}
2492
2494{
2495 QFontDef req = d->request;
2496
2497 if (req.pixelSize == -1) {
2498 req.pixelSize = std::floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
2499 req.pixelSize = qRound(req.pixelSize);
2500 }
2501 if (req.pointSize < 0)
2502 req.pointSize = req.pixelSize*72.0/d->dpi;
2503
2504 // respect the fallback families that might be passed through the request
2505 const QStringList fallBackFamilies = familyList(req);
2506
2507 if (!d->engineData) {
2508 QFontCache *fontCache = QFontCache::instance();
2509 // look for the requested font in the engine data cache
2510 // note: fallBackFamilies are not respected in the EngineData cache key;
2511 // join them with the primary selection family to avoid cache misses
2512 if (!d->request.families.isEmpty())
2513 req.families = fallBackFamilies;
2514
2515 d->engineData = fontCache->findEngineData(req);
2516 if (!d->engineData) {
2517 // create a new one
2518 d->engineData = new QFontEngineData;
2519 fontCache->insertEngineData(req, d->engineData);
2520 }
2521 d->engineData->ref.ref();
2522 }
2523
2524 // the cached engineData could have already loaded the engine we want
2525 if (d->engineData->engines[script])
2526 return;
2527
2528 QFontEngine *fe = nullptr;
2529
2530 Q_TRACE(QFontDatabase_load, req.families.join(QLatin1Char(';')), req.pointSize);
2531
2532 req.fallBackFamilies = fallBackFamilies;
2533 if (!req.fallBackFamilies.isEmpty())
2534 req.families = QStringList(req.fallBackFamilies.takeFirst());
2535
2536 // list of families to try
2537 QStringList family_list;
2538
2539 if (!req.families.isEmpty()) {
2540 // Add primary selection
2541 family_list << req.families.at(0);
2542
2543 // add the default family
2544 auto families = QGuiApplication::font().families();
2545 if (!families.isEmpty()) {
2546 QString defaultFamily = families.first();
2547 if (! family_list.contains(defaultFamily))
2548 family_list << defaultFamily;
2549 }
2550
2551 }
2552
2553 // null family means find the first font matching the specified script
2554 family_list << QString();
2555
2556 QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
2557 for (; !fe && it != end; ++it) {
2558 req.families = QStringList(*it);
2559
2560 fe = QFontDatabasePrivate::findFont(req, script);
2561 if (fe) {
2562 if (fe->type() == QFontEngine::Box && !req.families.at(0).isEmpty()) {
2563 if (fe->ref.loadRelaxed() == 0)
2564 delete fe;
2565 fe = nullptr;
2566 } else {
2567 if (d->dpi > 0)
2568 fe->fontDef.pointSize = qreal(double((fe->fontDef.pixelSize * 72) / d->dpi));
2569 }
2570 }
2571
2572 // No need to check requested fallback families again
2573 req.fallBackFamilies.clear();
2574 }
2575
2576 Q_ASSERT(fe);
2577 if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
2578 for (int i = 0; i < QChar::ScriptCount; ++i) {
2579 if (!d->engineData->engines[i]) {
2580 d->engineData->engines[i] = fe;
2581 fe->ref.ref();
2582 }
2583 }
2584 } else {
2585 d->engineData->engines[script] = fe;
2586 fe->ref.ref();
2587 }
2588}
2589
2591{
2593}
2594
2596{
2597 size_t writingSystem = qt_writing_system_for_script(script);
2598 if (writingSystem == QFontDatabase::Any
2599 || writingSystem >= QFontDatabase::WritingSystemsCount) {
2600 return families;
2601 }
2602
2604 QMultiMap<uint, QString> supported;
2605 for (int i = 0; i < families.size(); ++i) {
2606 const QString &family = families.at(i);
2607
2608 QtFontFamily *testFamily = nullptr;
2609 for (int x = 0; x < db->count; ++x) {
2610 if (Q_UNLIKELY(matchFamilyName(family, db->families[x]))) {
2611 testFamily = db->families[x];
2612 if (testFamily->ensurePopulated())
2613 break;
2614 }
2615 }
2616
2617 uint order = i;
2618 if (testFamily == nullptr
2619 || !familySupportsWritingSystem(testFamily, writingSystem)) {
2620 order |= 1u << 31;
2621 }
2622
2623 supported.insert(order, family);
2624 }
2625
2626 return supported.values();
2627}
2628
2630
2631#include "moc_qfontdatabase.cpp"
2632
bool ref() noexcept
T loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
\inmodule QtCore
Definition qchar.h:48
Script
Definition qchar.h:144
@ Script_Tamil
Definition qchar.h:162
@ Script_Thai
Definition qchar.h:167
@ Script_Armenian
Definition qchar.h:152
@ Script_Gurmukhi
Definition qchar.h:159
@ ScriptCount
Definition qchar.h:341
@ Script_Arabic
Definition qchar.h:154
@ Script_Gujarati
Definition qchar.h:160
@ Script_Cyrillic
Definition qchar.h:151
@ Script_Hebrew
Definition qchar.h:153
@ Script_Ogham
Definition qchar.h:176
@ Script_Han
Definition qchar.h:183
@ Script_Telugu
Definition qchar.h:163
@ Script_Oriya
Definition qchar.h:161
@ Script_Kannada
Definition qchar.h:164
@ Script_Devanagari
Definition qchar.h:157
@ Script_Georgian
Definition qchar.h:171
@ Script_Runic
Definition qchar.h:177
@ Script_Myanmar
Definition qchar.h:170
@ Script_Common
Definition qchar.h:147
@ Script_Hangul
Definition qchar.h:172
@ Script_Greek
Definition qchar.h:150
@ Script_Malayalam
Definition qchar.h:165
@ Script_Bengali
Definition qchar.h:158
@ Script_Tibetan
Definition qchar.h:169
@ Script_Lao
Definition qchar.h:168
@ Script_Khmer
Definition qchar.h:178
@ Script_Thaana
Definition qchar.h:156
@ Script_Nko
Definition qchar.h:218
@ Script_Syriac
Definition qchar.h:155
@ Script_Latin
Definition qchar.h:149
@ Script_Sinhala
Definition qchar.h:166
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
\inmodule QtCore
Definition qfile.h:93
void insertEngineData(const QFontDef &def, QFontEngineData *engineData)
Definition qfont.cpp:3159
void clear()
Definition qfont.cpp:3089
QFontEngine * findEngine(const Key &key)
Definition qfont.cpp:3180
QFontEngineData * findEngineData(const QFontDef &def) const
Definition qfont.cpp:3149
static QFontCache * instance()
Definition qfont.cpp:3052
void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti=false)
Definition qfont.cpp:3207
QList< ApplicationFont > applicationFonts
bool isApplicationFont(const QString &fileName)
static void parseFontName(const QString &name, QString &foundry, QString &family)
static void load(const QFontPrivate *d, int script)
static QFontDatabasePrivate * ensureFontDatabase()
static QFontDatabasePrivate * instance()
static QFontEngine * findFont(const QFontDef &request, int script, bool preferScriptOverFamily=false)
static QString resolveFontFamilyAlias(const QString &family)
QtFontFamily * family(const QString &f, FamilyRequestFlags flags=EnsurePopulated)
int addAppFont(const QByteArray &fontData, const QString &fileName)
static QList< int > standardSizes()
Returns a list of standard font sizes.
SystemFont
\value GeneralFont The default system font.
static int addApplicationFontFromData(const QByteArray &fontData)
static QString writingSystemName(WritingSystem writingSystem)
Returns the names the writingSystem (e.g.
static bool bold(const QString &family, const QString &style)
Returns true if the font that has family family and style style is bold; otherwise returns false.
WritingSystem
\value Any \value Latin \value Greek \value Cyrillic \value Armenian \value Hebrew \value Arabic \val...
static bool isSmoothlyScalable(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is smoothly scalable; otherwise retur...
static int addApplicationFont(const QString &fileName)
static bool isPrivateFamily(const QString &family)
static QString styleString(const QFont &font)
Returns a string that describes the style of the font.
static bool italic(const QString &family, const QString &style)
Returns true if the font that has family family and style style is italic; otherwise returns false.
static QFont font(const QString &family, const QString &style, int pointSize)
Returns a QFont object that has family family, style style and point size pointSize.
static QString writingSystemSample(WritingSystem writingSystem)
Returns a string with sample characters from writingSystem.
static bool removeApplicationFont(int id)
static bool isScalable(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is scalable; otherwise returns false.
static QStringList families(WritingSystem writingSystem=Any)
Returns a sorted list of the available font families which support the writingSystem.
static bool isBitmapScalable(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is a scalable bitmap font; otherwise ...
static bool hasFamily(const QString &family)
static QList< int > smoothSizes(const QString &family, const QString &style)
Returns the point sizes of a font that has family family and style styleName that will look attractiv...
static QList< WritingSystem > writingSystems()
Returns a sorted list of the available writing systems.
static QList< int > pointSizes(const QString &family, const QString &style=QString())
Returns a list of the point sizes available for the font that has family family and style styleName.
static QFont systemFont(SystemFont type)
static QStringList applicationFontFamilies(int id)
static QStringList styles(const QString &family)
Returns a list of the styles available for the font family family.
static bool removeAllApplicationFonts()
static bool isFixedPitch(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is fixed pitch; otherwise returns fal...
static int weight(const QString &family, const QString &style)
Returns the weight of the font that has family family and style style.
void setFallbackFamiliesList(const QStringList &fallbackFamilies)
QFontDef fontDef
Type type() const
QAtomicInt ref
\reentrant
Definition qfontinfo.h:14
QString styleName() const
Definition qfont.cpp:2823
QFont::Style style() const
Returns the style value of the matched window system font.
Definition qfont.cpp:2883
int weight() const
Returns the weight of the matched window system font.
Definition qfont.cpp:2917
\reentrant
Definition qfont.h:20
static QStringList substitutes(const QString &)
Returns a list of family names to be used whenever familyName is specified.
Definition qfont.cpp:1919
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:23
@ AnyStyle
Definition qfont.h:29
@ TypeWriter
Definition qfont.h:26
void setStyle(Style style)
Sets the style of the font to style.
Definition qfont.cpp:1101
QString styleName() const
Definition qfont.cpp:828
QStringList families() const
Definition qfont.cpp:2469
Weight weight() const
Returns the weight of the font, using the same scale as the \l{QFont::Weight} enumeration.
Definition qfont.cpp:1118
@ AnyStretch
Definition qfont.h:81
Style style() const
Returns the style of the font.
Definition qfont.cpp:1090
@ PreferQuality
Definition qfont.h:43
@ PreferBitmap
Definition qfont.h:38
@ ForceOutline
Definition qfont.h:41
@ PreferMatch
Definition qfont.h:42
@ NoFontMerging
Definition qfont.h:48
@ DemiBold
Definition qfont.h:66
@ Thin
Definition qfont.h:61
@ ExtraBold
Definition qfont.h:68
@ Black
Definition qfont.h:69
@ Bold
Definition qfont.h:67
@ ExtraLight
Definition qfont.h:62
@ Normal
Definition qfont.h:64
@ Light
Definition qfont.h:63
@ Medium
Definition qfont.h:65
Style
This enum describes the different styles of glyphs that are used to display text.
Definition qfont.h:73
@ StyleItalic
Definition qfont.h:75
@ StyleNormal
Definition qfont.h:74
@ StyleOblique
Definition qfont.h:76
static QPlatformIntegration * platformIntegration()
static QPlatformTheme * platformTheme()
static QFont font()
Returns the default application font.
Definition qlist.h:74
void push_back(parameter_type t)
Definition qlist.h:672
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
const_iterator ConstIterator
Definition qlist.h:251
iterator insert(const Key &key, const T &value)
Definition qmap.h:1425
QList< T > values() const
Definition qmap.h:1078
\inmodule QtCore
Definition qmutex.h:317
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:323
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font=nullptr)
Adds an application font described by the font contained supplied fontData or using the font containe...
virtual bool populateFamilyAliases(const QString &missingFamily)
virtual QFontEngine * fontEngine(const QFontDef &fontDef, void *handle)
Returns the font engine that can be used to render the font described by the font definition,...
virtual bool fontsAlwaysScalable() const
Return true if all fonts are considered scalable when using this font database.
virtual void releaseHandle(void *handle)
Releases the specified font handle.
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
Returns a list of alternative fonts for the specified family and style and script using the styleHint...
virtual void populateFamily(const QString &familyName)
This function is called whenever a lazily populated family, populated through registerFontFamily(),...
virtual QFontEngineMulti * fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
Returns a multi font engine in the specified script to encapsulate fontEngine with the option to fall...
virtual bool isPrivateFontFamily(const QString &family) const
Returns true if the font family is private.
virtual QString resolveFontFamilyAlias(const QString &family) const
Resolve alias to actual font family names.
virtual void invalidate()
This function is called whenever the font database is invalidated.
virtual QList< int > standardSizes() const
Return list of standard font sizes when using this font database.
virtual void populateFontDatabase()
This function is called once at startup by Qt's internal font database.
The QPlatformIntegration class is the entry for WindowSystem specific functionality.
virtual QPlatformFontDatabase * fontDatabase() const
Accessor for the platform integration's fontdatabase.
The QPlatformTheme class allows customizing the UI based on themes.
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
QString first(qsizetype n) const
Definition qstring.h:337
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
QString toLower() const &
Definition qstring.h:368
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
The QSupportedWritingSystems class is used when registering fonts with the internal Qt fontdatabase.
bool supported(QFontDatabase::WritingSystem) const
Returns true if the writing system specified by writingSystem is supported; otherwise returns false.
QString str
[2]
QString text
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ CaseInsensitive
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#define qApp
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
QRecursiveMutex * qt_fontdatabase_mutex()
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
Q_GUI_EXPORT int qt_defaultDpiY()
Definition qfont.cpp:122
static bool familySupportsWritingSystem(QtFontFamily *family, size_t writingSystem)
static bool equalsCaseInsensitive(const QString &a, const QString &b)
static void parseFontName(const QString &name, QString &foundry, QString &family)
bool qt_isFontFamilyPopulated(const QString &familyName)
void qt_registerFont(const QString &familyName, const QString &stylename, const QString &foundryname, int weight, QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *handle)
#define SMOOTH_SCALABLE
static QString styleStringHelper(int weight, QFont::Style style)
static const int scriptForWritingSystem[]
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families)
static int getFontWeight(const QString &weightString)
static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int script)
static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi)
static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
Q_GUI_EXPORT int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem)
void qt_registerFontFamily(const QString &familyName)
void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
QString qt_resolveFontFamilyAlias(const QString &alias)
static QStringList familyList(const QFontDef &req)
static QtFontStyle * bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey, const QString &styleName=QString())
QByteArray qt_fontdata_from_index(int)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
void qt_cleanupFontDatabase()
#define qGuiApp
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
return ret
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLsizei GLsizei GLfloat distance
GLenum type
GLbitfield flags
GLenum const void GLbitfield fontStyle
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLenum GLsizeiptr const void * fontData
GLuint res
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLenum GLsizei len
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfixed GLfixed GLint GLint order
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define qPrintable(string)
Definition qstring.h:1391
#define s2
#define Q_AUTOTEST_EXPORT
#define emit
#define Q_UNUSED(x)
#define Q_TRACE(x,...)
Definition qtrace_p.h:144
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
@ desc
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define QT_TRANSLATE_NOOP(scope, x)
unsigned long long quint64
Definition qtypes.h:56
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
QT_END_NAMESPACE typedef QT_PREPEND_NAMESPACE(quintptr) WId
QList< int > list
[14]
Q_CHECK_PTR(a=new int[80])
std::uniform_real_distribution dist(1, 2.5)
[2]
QObject::connect nullptr
QMimeDatabase db
[0]
QNetworkRequest request(url)
view create()
char * toString(const MyType &t)
[31]
QJSEngine engine
[0]
uint stretch
Definition qfont_p.h:64
uint style
Definition qfont_p.h:65
uint styleStrategy
Definition qfont_p.h:63
QStringList fallBackFamilies
Definition qfont_p.h:57
uint fixedPitch
Definition qfont_p.h:70
qreal pixelSize
Definition qfont_p.h:60
uint ignorePitch
Definition qfont_p.h:71
uint weight
Definition qfont_p.h:69
QStringList families
Definition qfont_p.h:54
uint styleHint
Definition qfont_p.h:68
qreal pointSize
Definition qfont_p.h:59
\inmodule QtCore \reentrant
Definition qchar.h:17
bool contains(const AT &t) const noexcept
Definition qlist.h:44
QtFontFoundry * foundry
QtFontFamily * family
QtFontStyle * style
QtFontSize * size
QtFontFoundry ** foundries
unsigned char writingSystems[QFontDatabase::WritingSystemsCount]
bool matchesFamilyName(const QString &familyName) const
QtFontFoundry * foundry(const QString &f, bool=false)
QtFontStyle * style(const QtFontStyle::Key &, const QString &=QString(), bool=false)
QtFontStyle ** styles
unsigned short pixelSize
QtFontSize * pixelSizes
QtFontSize * pixelSize(unsigned short size, bool=false)
signed int count