7#include <QtGui/private/qfontengine_ft_p.h>
10#include <QtCore/QElapsedTimer>
11#include <QtCore/QFile>
13#include <qpa/qplatformnativeinterface.h>
14#include <qpa/qplatformscreen.h>
15#include <qpa/qplatformintegration.h>
16#include <qpa/qplatformservices.h>
18#include <QtGui/private/qguiapplication_p.h>
20#include <QtGui/qguiapplication.h>
22#include <QtCore/private/qduplicatetracker_p.h>
24#include <fontconfig/fontconfig.h>
25#if FC_VERSION
>= 20402
26#include <fontconfig/fcfreetype.h>
31using namespace Qt::StringLiterals;
35 return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower);
47 if (fcweight <= FC_WEIGHT_THIN)
49 if (fcweight <= FC_WEIGHT_ULTRALIGHT)
50 return mapToQtWeightForRange(fcweight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT, QFont::Thin, QFont::ExtraLight);
51 if (fcweight <= FC_WEIGHT_LIGHT)
52 return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT, QFont::ExtraLight, QFont::Light);
53 if (fcweight <= FC_WEIGHT_NORMAL)
54 return mapToQtWeightForRange(fcweight, FC_WEIGHT_LIGHT, FC_WEIGHT_NORMAL, QFont::Light, QFont::Normal);
55 if (fcweight <= FC_WEIGHT_MEDIUM)
56 return mapToQtWeightForRange(fcweight, FC_WEIGHT_NORMAL, FC_WEIGHT_MEDIUM, QFont::Normal, QFont::Medium);
57 if (fcweight <= FC_WEIGHT_DEMIBOLD)
58 return mapToQtWeightForRange(fcweight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD, QFont::Medium, QFont::DemiBold);
59 if (fcweight <= FC_WEIGHT_BOLD)
60 return mapToQtWeightForRange(fcweight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD, QFont::DemiBold, QFont::Bold);
61 if (fcweight <= FC_WEIGHT_ULTRABOLD)
62 return mapToQtWeightForRange(fcweight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD, QFont::Bold, QFont::ExtraBold);
63 if (fcweight <= FC_WEIGHT_BLACK)
64 return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK, QFont::ExtraBold, QFont::Black);
65 if (fcweight <= FC_WEIGHT_ULTRABLACK)
66 return mapToQtWeightForRange(fcweight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK, QFont::Black,
68 return QFONT_WEIGHT_MAX;
75 const int maxStretch = 4000;
79 else if (fcwidth > maxStretch)
80 qtstretch = maxStretch;
264static_assert(
sizeof specialLanguages /
sizeof *specialLanguages == QChar::ScriptCount);
304static_assert(
sizeof languageForWritingSystem /
sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount);
306#if FC_VERSION
>= 20297
310static const char capabilityForWritingSystem[][5] = {
346static_assert(
sizeof(capabilityForWritingSystem) /
sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount);
351 const char *stylehint =
nullptr;
353 case QFont::SansSerif:
354 stylehint =
"sans-serif";
359 case QFont::TypeWriter:
360 case QFont::Monospace:
361 stylehint =
"monospace";
364 stylehint =
"cursive";
367 stylehint =
"fantasy";
377 return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
378 || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
382 QFontDatabasePrivate::ApplicationFont *applicationFont =
nullptr,
383 FT_Face face =
nullptr,
384 QFontconfigDatabase *db =
nullptr)
387 QString familyNameLang;
388 FcChar8 *value =
nullptr;
395 FcChar8 *foundry_value;
396 FcChar8 *style_value;
400 if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
403 familyName = QString::fromUtf8((
const char *)value);
405 if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
406 familyNameLang = QString::fromUtf8((
const char *)value);
408 slant_value = FC_SLANT_ROMAN;
409 weight_value = FC_WEIGHT_REGULAR;
410 spacing_value = FC_PROPORTIONAL;
411 file_value =
nullptr;
416 if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
417 slant_value = FC_SLANT_ROMAN;
418 if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
419 weight_value = FC_WEIGHT_REGULAR;
420 if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
421 width_value = FC_WIDTH_NORMAL;
422 if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
423 spacing_value = FC_PROPORTIONAL;
424 if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
425 file_value =
nullptr;
426 if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
428 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
430 if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
431 foundry_value =
nullptr;
432 if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
433 style_value =
nullptr;
434 if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
437 QSupportedWritingSystems writingSystems;
438 FcLangSet *langset =
nullptr;
439 FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
440 if (res == FcResultMatch) {
441 bool hasLang =
false;
442#if FC_VERSION
>= 20297
443 FcChar8 *cap =
nullptr;
444 FcResult capRes = FcResultNoMatch;
446 for (
int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
449 FcLangResult langRes = FcLangSetHasLang(langset, lang);
450 if (langRes != FcLangDifferentLang) {
451#if FC_VERSION
>= 20297
454 capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap);
455 if (capRes == FcResultMatch && strstr(
reinterpret_cast<
const char *>(cap), capabilityForWritingSystem[j]) ==
nullptr)
459 writingSystems.setSupported(QFontDatabase::WritingSystem(j));
466 writingSystems.setSupported(QFontDatabase::Other);
471 writingSystems.setSupported(QFontDatabase::Other);
474 QString fileName = QString::fromLocal8Bit((
const char *)file_value);
480 if (fileName.startsWith(
"/:/"_L1))
481 fileName = fileName.mid(1);
483 QFont::Style style = (slant_value == FC_SLANT_ITALIC)
485 : ((slant_value == FC_SLANT_OBLIQUE)
486 ? QFont::StyleOblique
487 : QFont::StyleNormal);
489 QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
491 double pixel_size = 0;
493 FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
495 bool fixedPitch = spacing_value >= FC_MONO;
497 FcBool colorFont =
false;
499 FcPatternGetBool(pattern, FC_COLOR, 0, &colorFont);
503 QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
504 QString styleName = style_value ? QString::fromUtf8((
const char *) style_value) : QString();
506 if (applicationFont !=
nullptr) {
507 QFontDatabasePrivate::ApplicationFont::Properties properties;
508 properties.familyName = familyName;
509 properties.styleName = styleName;
510 properties.weight = weight;
511 properties.style = style;
512 properties.stretch = stretch;
514 applicationFont->properties.append(properties);
518 FontFile *fontFile =
new FontFile;
519 fontFile->fileName = fileName;
520 fontFile->indexValue = indexValue;
521 QPlatformFontDatabase::registerFont(familyName,
523 QLatin1StringView((
const char *)foundry_value),
535 if (applicationFont !=
nullptr && face !=
nullptr && db !=
nullptr) {
536 db->addNamedInstancesForFace(face,
546 QByteArray((
const char*)file_value),
547 applicationFont->data);
552 for (
int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) {
553 const QString altFamilyName = QString::fromUtf8((
const char *)value);
557 QString altStyleName;
558 if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch)
559 altStyleName = QString::fromUtf8((
const char *)value);
561 altStyleName = styleName;
563 QString altFamilyNameLang;
564 if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch)
565 altFamilyNameLang = QString::fromUtf8((
const char *)value);
567 altFamilyNameLang = familyNameLang;
569 if (familyNameLang == altFamilyNameLang && altStyleName != styleName) {
570 if (applicationFont !=
nullptr) {
571 QFontDatabasePrivate::ApplicationFont::Properties properties;
572 properties.familyName = altFamilyName;
573 properties.styleName = altStyleName;
574 properties.weight = weight;
575 properties.style = style;
576 properties.stretch = stretch;
578 applicationFont->properties.append(properties);
582 FontFile *altFontFile =
new FontFile;
583 altFontFile->fileName = fileName;
584 altFontFile->indexValue = indexValue;
585 QPlatformFontDatabase::registerFont(altFamilyName,
587 QLatin1StringView((
const char *)foundry_value),
600 QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
608 return !qFuzzyCompare(qApp->devicePixelRatio(), qreal(1.0));
611QFontconfigDatabase::~QFontconfigDatabase()
613 FcConfigDestroy(FcConfigGetCurrent());
616void QFontconfigDatabase::populateFontDatabase()
622 FcObjectSet *os = FcObjectSetCreate();
623 FcPattern *pattern = FcPatternCreate();
624 const char *properties [] = {
625 FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
626 FC_SPACING, FC_FILE, FC_INDEX,
627 FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
628 FC_WIDTH, FC_FAMILYLANG,
629#if FC_VERSION
>= 20297
635 (
const char *)
nullptr
637 const char **p = properties;
639 FcObjectSetAdd(os, *p);
645 FcPatternAddBool(pattern, FC_VARIABLE, FcFalse);
648 fonts = FcFontList(
nullptr, pattern, os);
649 FcObjectSetDestroy(os);
650 FcPatternDestroy(pattern);
655 for (
int i = 0; i < fonts->nfont; i++)
656 populateFromPattern(fonts->fonts[i]);
658 FcFontSetDestroy (fonts);
660 struct FcDefaultFont {
665 const FcDefaultFont defaults[] = {
666 {
"Serif",
"serif",
false },
667 {
"Sans Serif",
"sans-serif",
false },
668 {
"Monospace",
"monospace",
true },
669 {
nullptr,
nullptr,
false }
671 const FcDefaultFont *f = defaults;
673 QSupportedWritingSystems ws;
674 ws.setSupported(QFontDatabase::Latin);
677 QString familyQtName = QString::fromLatin1(f->qtname);
678 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
679 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
680 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
693void QFontconfigDatabase::invalidate()
696 FcConfigAppFontClear(
nullptr);
699QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QFontDatabasePrivate::ExtendedScript script)
701 return new QFontEngineMultiFontConfig(fontEngine, script);
705QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match,
bool preferXftConf)
707 switch (hintingPreference) {
708 case QFont::PreferNoHinting:
709 return QFontEngine::HintNone;
710 case QFont::PreferVerticalHinting:
711 return QFontEngine::HintLight;
712 case QFont::PreferFullHinting:
713 return QFontEngine::HintFull;
714 case QFont::PreferDefaultHinting:
719 return QFontEngine::HintNone;
721 void *hintStyleResource =
722 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
723 QGuiApplication::primaryScreen());
724 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
725 if (preferXftConf && xftHintStyle > 0)
726 return QFontEngine::HintStyle(xftHintStyle - 1);
729 if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
730 switch (hint_style) {
732 return QFontEngine::HintNone;
734 return QFontEngine::HintLight;
736 return QFontEngine::HintMedium;
738 return QFontEngine::HintFull;
744 if (xftHintStyle > 0)
745 return QFontEngine::HintStyle(xftHintStyle - 1);
747 return QFontEngine::HintFull;
750QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match,
bool preferXftConf)
752 void *subpixelTypeResource =
753 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
754 QGuiApplication::primaryScreen());
755 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
756 if (preferXftConf && xftSubpixelType > 0)
757 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
759 int subpixel = FC_RGBA_UNKNOWN;
760 if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
762 case FC_RGBA_UNKNOWN:
764 return QFontEngine::Subpixel_None;
766 return QFontEngine::Subpixel_RGB;
768 return QFontEngine::Subpixel_BGR;
770 return QFontEngine::Subpixel_VRGB;
772 return QFontEngine::Subpixel_VBGR;
779 if (xftSubpixelType > 0)
780 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
782 return QFontEngine::Subpixel_None;
786QFontEngine *QFontconfigDatabase::fontEngine(
const QFontDef &f,
void *usrPtr)
791 FontFile *fontfile =
static_cast<FontFile *> (usrPtr);
792 QFontEngine::FaceId fid;
793 fid.filename = QFile::encodeName(fontfile->fileName);
794 fid.index = fontfile->indexValue;
795 fid.instanceIndex = fontfile->instanceIndex;
796 fid.variableAxes = f.variableAxisValues;
799 QFontEngineFT *engine =
new QFontEngineFT(f);
800 engine->face_id = fid;
802 setupFontEngine(engine, f);
804 if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
812QFontEngine *QFontconfigDatabase::fontEngine(
const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
814 QFontEngineFT *engine =
static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference));
815 if (engine ==
nullptr)
818 setupFontEngine(engine, engine->fontDef);
823QStringList QFontconfigDatabase::fallbacksForFamily(
const QString &family,
825 QFont::StyleHint styleHint,
826 QFontDatabasePrivate::ExtendedScript script)
const
828 QStringList fallbackFamilies;
829 FcPattern *pattern = FcPatternCreate();
831 return fallbackFamilies;
834 value.type = FcTypeString;
835 const QByteArray cs = family.toUtf8();
836 value.u.s = (
const FcChar8 *)cs.data();
837 FcPatternAdd(pattern,FC_FAMILY,value,
true);
840 if (script == QFontDatabasePrivate::Script_Emoji) {
841 FcPatternAddBool(pattern, FC_COLOR,
true);
842 value.u.s = (
const FcChar8 *)
"emoji";
843 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
847 int slant_value = FC_SLANT_ROMAN;
848 if (style == QFont::StyleItalic)
849 slant_value = FC_SLANT_ITALIC;
850 else if (style == QFont::StyleOblique)
851 slant_value = FC_SLANT_OBLIQUE;
852 FcPatternAddInteger(pattern, FC_SLANT, slant_value);
854 Q_ASSERT(uint(script) < QFontDatabasePrivate::ScriptCount);
855 if (uint(script) < QChar::ScriptCount && *specialLanguages[script] !=
'\0') {
856 FcLangSet *ls = FcLangSetCreate();
857 FcLangSetAdd(ls, (
const FcChar8*)specialLanguages[script]);
858 FcPatternAddLangSet(pattern, FC_LANG, ls);
859 FcLangSetDestroy(ls);
860 }
else if (!family.isEmpty()) {
866 FcPattern *dummy = FcPatternCreate();
867 FcDefaultSubstitute(dummy);
868 FcChar8 *lang =
nullptr;
869 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
870 if (res == FcResultMatch)
871 FcPatternAddString(pattern, FC_LANG, lang);
872 FcPatternDestroy(dummy);
875 const char *stylehint = getFcFamilyForStyleHint(styleHint);
877 value.u.s = (
const FcChar8 *)stylehint;
878 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
881 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
882 FcDefaultSubstitute(pattern);
884 FcResult result = FcResultMatch;
885 FcFontSet *fontSet = FcFontSort(
nullptr,pattern,FcFalse,
nullptr,&result);
886 FcPatternDestroy(pattern);
889 QDuplicateTracker<QString> duplicates(fontSet->nfont + 1);
890 (
void)duplicates.hasSeen(family.toCaseFolded());
891 for (
int i = 0; i < fontSet->nfont; i++) {
892 FcChar8 *value =
nullptr;
893 if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
896 const QString familyName = QString::fromUtf8((
const char *)value);
897 const QString familyNameCF = familyName.toCaseFolded();
898 if (!duplicates.hasSeen(familyNameCF)) {
899 fallbackFamilies << familyName;
902 FcFontSetDestroy(fontSet);
906 return fallbackFamilies;
909static FcPattern *
queryFont(
const FcChar8 *file,
const QByteArray &data,
int id, FcBlanks *blanks,
int *count, FT_Face *face)
911#if FC_VERSION
< 20402
914 return FcFreeTypeQuery(file, id, blanks, count);
916 if (data.isEmpty()) {
918 return FcFreeTypeQuery(file, id, blanks, count);
921 FT_Library lib = qt_getFreetype();
923 FcPattern *pattern =
nullptr;
925 if (!FT_New_Memory_Face(lib, (
const FT_Byte *)data.constData(), data.size(), id, face)) {
926 *count = (*face)->num_faces;
928 pattern = FcFreeTypeQueryFace(*face, file, id, blanks);
937QStringList QFontconfigDatabase::addApplicationFont(
const QByteArray &fontData,
const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
939 QStringList families;
941 if (applicationFont !=
nullptr)
942 applicationFont->properties.clear();
944 FcFontSet *set = FcConfigGetFonts(
nullptr, FcSetApplication);
946 FcConfigAppFontAddFile(
nullptr, (
const FcChar8 *)
":/non-existent");
947 set = FcConfigGetFonts(
nullptr, FcSetApplication);
953 FcBlanks *blanks = FcConfigGetBlanks(
nullptr);
959 pattern = queryFont((
const FcChar8 *)QFile::encodeName(fileName).constData(),
960 fontData, id, blanks, &count, &face);
964 FcChar8 *fam =
nullptr;
965 if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
966 QString family = QString::fromUtf8(
reinterpret_cast<
const char *>(fam));
969 populateFromPattern(pattern, applicationFont, face,
this);
974 FcFontSetAdd(set, pattern);
977 }
while (id < count);
982QString QFontconfigDatabase::resolveFontFamilyAlias(
const QString &family)
const
984 QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family);
985 if (!resolved.isEmpty() && resolved != family)
987 FcPattern *pattern = FcPatternCreate();
991 if (!family.isEmpty()) {
992 const QByteArray cs = family.toUtf8();
993 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8 *) cs.constData());
995 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
996 FcDefaultSubstitute(pattern);
998 FcChar8 *familyAfterSubstitution =
nullptr;
999 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
1000 resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
1001 FcPatternDestroy(pattern);
1006QFont QFontconfigDatabase::defaultFont()
const
1011 FcPattern *dummy = FcPatternCreate();
1012 FcDefaultSubstitute(dummy);
1013 FcChar8 *lang =
nullptr;
1014 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
1016 FcPattern *pattern = FcPatternCreate();
1017 if (res == FcResultMatch) {
1020 FcPatternAddString(pattern, FC_LANG, lang);
1022 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1023 FcDefaultSubstitute(pattern);
1025 FcChar8 *familyAfterSubstitution =
nullptr;
1026 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
1027 QString resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
1028 FcPatternDestroy(pattern);
1029 FcPatternDestroy(dummy);
1031 return QFont(resolved);
1034void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine,
const QFontDef &fontDef)
const
1036 bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
1037 bool forcedAntialiasSetting = !antialias || isDprScaling();
1039 const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
1040 bool preferXftConf =
false;
1043 const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(
':');
1044 preferXftConf = !(desktopEnv.contains(
"KDE") || desktopEnv.contains(
"LXQT") || desktopEnv.contains(
"UKUI"));
1047 QFontEngine::GlyphFormat format;
1049 FcPattern *pattern = FcPatternCreate();
1050 FcPattern *match =
nullptr;
1053 value.type = FcTypeString;
1054 QByteArray cs = fontDef.families.first().toUtf8();
1055 value.u.s = (
const FcChar8 *)cs.data();
1056 FcPatternAdd(pattern,FC_FAMILY,value,
true);
1058 QFontEngine::FaceId fid = engine->faceId();
1060 if (!fid.filename.isEmpty()) {
1061 value.u.s = (
const FcChar8 *)fid.filename.data();
1062 FcPatternAdd(pattern,FC_FILE,value,
true);
1064 value.type = FcTypeInteger;
1065 value.u.i = fid.index;
1066 FcPatternAdd(pattern,FC_INDEX,value,
true);
1069 if (!qFuzzyIsNull(fontDef.pixelSize))
1070 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
1074 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1075 FcDefaultSubstitute(pattern);
1078 if (!fid.filename.isEmpty()) {
1081 FcFontSet *fcsets[2], *fcfs;
1083 fcsets[0] = FcConfigGetFonts(
nullptr, FcSetSystem);
1084 fcsets[1] = FcConfigGetFonts(
nullptr, FcSetApplication);
1085 for (
int nset = 0; nset < 2; nset++) {
1086 fcfs = fcsets[nset];
1087 if (fcfs ==
nullptr)
1089 for (
int fnum = 0; fnum < fcfs->nfont; fnum++) {
1090 FcPattern *fcpat = fcfs->fonts[fnum];
1097 if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
1101 if (!qFuzzyIsNull(fontDef.pixelSize)) {
1102 if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch &&
1103 fontDef.pixelSize != fcpixelsize)
1107 if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
1108 FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
1109 QByteArray f = QByteArray::fromRawData((
const char *)fcfile,
1110 qstrlen((
const char *)fcfile));
1111 if (f == fid.filename && fcindex == fid.index) {
1113 match = FcFontRenderPrepare(
nullptr, pattern, fcpat);
1124 match = FcFontMatch(
nullptr, pattern, &result);
1126 int xftAntialias = 0;
1127 if (!forcedAntialiasSetting) {
1128 void *antialiasResource =
1129 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"antialiasingEnabled",
1130 QGuiApplication::primaryScreen());
1131 xftAntialias =
int(
reinterpret_cast<qintptr>(antialiasResource));
1132 if ((preferXftConf || !match) && xftAntialias > 0) {
1133 antialias = xftAntialias - 1;
1134 forcedAntialiasSetting =
true;
1138 engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
1141 if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
1142 engine->forceAutoHint = fc_autohint;
1144#if defined(FT_LCD_FILTER_H)
1146 if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
1147 engine->lcdFilterType = lcdFilter;
1150 if (!forcedAntialiasSetting) {
1151 FcBool fc_antialias;
1152 if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
1153 antialias = fc_antialias;
1157 QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
1158 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
1159 subpixelType = subpixelTypeFromMatch(match, preferXftConf);
1160 engine->subpixelType = subpixelType;
1163 FcPatternDestroy(match);
1165 void *hintStyleResource =
1166 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
1167 QGuiApplication::primaryScreen());
1168 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
1169 if (xftHintStyle > 0)
1170 engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
1172 engine->subpixelType = QFontEngine::Subpixel_None;
1173 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
1174 void *subpixelTypeResource =
1175 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
1176 QGuiApplication::primaryScreen());
1177 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
1178 if (xftSubpixelType > 1)
1179 engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
1184 format = (engine->subpixelType == QFontEngine::Subpixel_None)
1185 ? QFontEngine::Format_A8
1186 : QFontEngine::Format_A32;
1188 format = QFontEngine::Format_Mono;
1191 FcPatternDestroy(pattern);
1193 engine->antialias = antialias;
1194 engine->defaultFormat = format;
1195 engine->glyphFormat = format;
1198bool QFontconfigDatabase::supportsVariableApplicationFonts()
const
1200#if (FREETYPE_MAJOR*10000
+ FREETYPE_MINOR*100
+ FREETYPE_PATCH) >= 20900
static int stretchFromFcWidth(int fcwidth)
static FcPattern * queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count, FT_Face *face)
static int weightFromFcWeight(int fcweight)
static const char languageForWritingSystem[][6]
static int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper)
static const char specialLanguages[][6]
static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::ApplicationFont *applicationFont=nullptr, FT_Face face=nullptr, QFontconfigDatabase *db=nullptr)
static bool isDprScaling()
static bool requiresOpenType(int writingSystem)
static const char * getFcFamilyForStyleHint(const QFont::StyleHint style)