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:
718 void *hintStyleResource =
719 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
720 QGuiApplication::primaryScreen());
721 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
722 if (preferXftConf && xftHintStyle > 0)
723 return QFontEngine::HintStyle(xftHintStyle - 1);
726 if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
727 switch (hint_style) {
729 return QFontEngine::HintNone;
731 return QFontEngine::HintLight;
733 return QFontEngine::HintMedium;
735 return QFontEngine::HintFull;
741 if (xftHintStyle > 0)
742 return QFontEngine::HintStyle(xftHintStyle - 1);
744 return QFontEngine::HintFull;
747QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match,
bool preferXftConf)
749 void *subpixelTypeResource =
750 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
751 QGuiApplication::primaryScreen());
752 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
753 if (preferXftConf && xftSubpixelType > 0)
754 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
756 int subpixel = FC_RGBA_UNKNOWN;
757 if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
759 case FC_RGBA_UNKNOWN:
761 return QFontEngine::Subpixel_None;
763 return QFontEngine::Subpixel_RGB;
765 return QFontEngine::Subpixel_BGR;
767 return QFontEngine::Subpixel_VRGB;
769 return QFontEngine::Subpixel_VBGR;
776 if (xftSubpixelType > 0)
777 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
779 return QFontEngine::Subpixel_None;
783QFontEngine *QFontconfigDatabase::fontEngine(
const QFontDef &f,
void *usrPtr)
788 FontFile *fontfile =
static_cast<FontFile *> (usrPtr);
789 QFontEngine::FaceId fid;
790 fid.filename = QFile::encodeName(fontfile->fileName);
791 fid.index = fontfile->indexValue;
792 fid.instanceIndex = fontfile->instanceIndex;
793 fid.variableAxes = f.variableAxisValues;
796 QFontEngineFT *engine =
new QFontEngineFT(f);
797 engine->face_id = fid;
799 setupFontEngine(engine, f);
801 if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
809QFontEngine *QFontconfigDatabase::fontEngine(
const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
811 QFontEngineFT *engine =
static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference));
812 if (engine ==
nullptr)
815 setupFontEngine(engine, engine->fontDef);
820QStringList QFontconfigDatabase::fallbacksForFamily(
const QString &family,
822 QFont::StyleHint styleHint,
823 QFontDatabasePrivate::ExtendedScript script)
const
825 QStringList fallbackFamilies;
826 FcPattern *pattern = FcPatternCreate();
828 return fallbackFamilies;
831 value.type = FcTypeString;
832 const QByteArray cs = family.toUtf8();
833 value.u.s = (
const FcChar8 *)cs.data();
834 FcPatternAdd(pattern,FC_FAMILY,value,
true);
837 if (script == QFontDatabasePrivate::Script_Emoji) {
838 FcPatternAddBool(pattern, FC_COLOR,
true);
839 value.u.s = (
const FcChar8 *)
"emoji";
840 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
844 int slant_value = FC_SLANT_ROMAN;
845 if (style == QFont::StyleItalic)
846 slant_value = FC_SLANT_ITALIC;
847 else if (style == QFont::StyleOblique)
848 slant_value = FC_SLANT_OBLIQUE;
849 FcPatternAddInteger(pattern, FC_SLANT, slant_value);
851 Q_ASSERT(uint(script) < QFontDatabasePrivate::ScriptCount);
852 if (uint(script) < QChar::ScriptCount && *specialLanguages[script] !=
'\0') {
853 FcLangSet *ls = FcLangSetCreate();
854 FcLangSetAdd(ls, (
const FcChar8*)specialLanguages[script]);
855 FcPatternAddLangSet(pattern, FC_LANG, ls);
856 FcLangSetDestroy(ls);
857 }
else if (!family.isEmpty()) {
863 FcPattern *dummy = FcPatternCreate();
864 FcDefaultSubstitute(dummy);
865 FcChar8 *lang =
nullptr;
866 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
867 if (res == FcResultMatch)
868 FcPatternAddString(pattern, FC_LANG, lang);
869 FcPatternDestroy(dummy);
872 const char *stylehint = getFcFamilyForStyleHint(styleHint);
874 value.u.s = (
const FcChar8 *)stylehint;
875 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
878 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
879 FcDefaultSubstitute(pattern);
881 FcResult result = FcResultMatch;
882 FcFontSet *fontSet = FcFontSort(
nullptr,pattern,FcFalse,
nullptr,&result);
883 FcPatternDestroy(pattern);
886 QDuplicateTracker<QString> duplicates(fontSet->nfont + 1);
887 (
void)duplicates.hasSeen(family.toCaseFolded());
888 for (
int i = 0; i < fontSet->nfont; i++) {
889 FcChar8 *value =
nullptr;
890 if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
893 const QString familyName = QString::fromUtf8((
const char *)value);
894 const QString familyNameCF = familyName.toCaseFolded();
895 if (!duplicates.hasSeen(familyNameCF)) {
896 fallbackFamilies << familyName;
899 FcFontSetDestroy(fontSet);
903 return fallbackFamilies;
906static FcPattern *
queryFont(
const FcChar8 *file,
const QByteArray &data,
int id, FcBlanks *blanks,
int *count, FT_Face *face)
908#if FC_VERSION
< 20402
911 return FcFreeTypeQuery(file, id, blanks, count);
913 if (data.isEmpty()) {
915 return FcFreeTypeQuery(file, id, blanks, count);
918 FT_Library lib = qt_getFreetype();
920 FcPattern *pattern =
nullptr;
922 if (!FT_New_Memory_Face(lib, (
const FT_Byte *)data.constData(), data.size(), id, face)) {
923 *count = (*face)->num_faces;
925 pattern = FcFreeTypeQueryFace(*face, file, id, blanks);
934QStringList QFontconfigDatabase::addApplicationFont(
const QByteArray &fontData,
const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
936 QStringList families;
938 if (applicationFont !=
nullptr)
939 applicationFont->properties.clear();
941 FcFontSet *set = FcConfigGetFonts(
nullptr, FcSetApplication);
943 FcConfigAppFontAddFile(
nullptr, (
const FcChar8 *)
":/non-existent");
944 set = FcConfigGetFonts(
nullptr, FcSetApplication);
950 FcBlanks *blanks = FcConfigGetBlanks(
nullptr);
956 pattern = queryFont((
const FcChar8 *)QFile::encodeName(fileName).constData(),
957 fontData, id, blanks, &count, &face);
961 FcChar8 *fam =
nullptr;
962 if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
963 QString family = QString::fromUtf8(
reinterpret_cast<
const char *>(fam));
966 populateFromPattern(pattern, applicationFont, face,
this);
971 FcFontSetAdd(set, pattern);
974 }
while (id < count);
979QString QFontconfigDatabase::resolveFontFamilyAlias(
const QString &family)
const
981 QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family);
982 if (!resolved.isEmpty() && resolved != family)
984 FcPattern *pattern = FcPatternCreate();
988 if (!family.isEmpty()) {
989 const QByteArray cs = family.toUtf8();
990 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8 *) cs.constData());
992 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
993 FcDefaultSubstitute(pattern);
995 FcChar8 *familyAfterSubstitution =
nullptr;
996 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
997 resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
998 FcPatternDestroy(pattern);
1003QFont QFontconfigDatabase::defaultFont()
const
1008 FcPattern *dummy = FcPatternCreate();
1009 FcDefaultSubstitute(dummy);
1010 FcChar8 *lang =
nullptr;
1011 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
1013 FcPattern *pattern = FcPatternCreate();
1014 if (res == FcResultMatch) {
1017 FcPatternAddString(pattern, FC_LANG, lang);
1019 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1020 FcDefaultSubstitute(pattern);
1022 FcChar8 *familyAfterSubstitution =
nullptr;
1023 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
1024 QString resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
1025 FcPatternDestroy(pattern);
1026 FcPatternDestroy(dummy);
1028 return QFont(resolved);
1031void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine,
const QFontDef &fontDef)
const
1033 bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
1034 bool forcedAntialiasSetting = !antialias || isDprScaling();
1036 const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
1037 bool preferXftConf =
false;
1040 const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(
':');
1041 preferXftConf = !(desktopEnv.contains(
"KDE") || desktopEnv.contains(
"LXQT") || desktopEnv.contains(
"UKUI"));
1044 QFontEngine::GlyphFormat format;
1046 FcPattern *pattern = FcPatternCreate();
1047 FcPattern *match =
nullptr;
1050 value.type = FcTypeString;
1051 QByteArray cs = fontDef.family().toUtf8();
1052 value.u.s = (
const FcChar8 *)cs.data();
1053 FcPatternAdd(pattern,FC_FAMILY,value,
true);
1055 QFontEngine::FaceId fid = engine->faceId();
1057 if (!fid.filename.isEmpty()) {
1058 value.u.s = (
const FcChar8 *)fid.filename.data();
1059 FcPatternAdd(pattern,FC_FILE,value,
true);
1061 value.type = FcTypeInteger;
1062 value.u.i = fid.index;
1063 FcPatternAdd(pattern,FC_INDEX,value,
true);
1066 if (!qFuzzyIsNull(fontDef.pixelSize))
1067 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
1071 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1072 FcDefaultSubstitute(pattern);
1075 if (!fid.filename.isEmpty()) {
1078 FcFontSet *fcsets[2], *fcfs;
1080 fcsets[0] = FcConfigGetFonts(
nullptr, FcSetSystem);
1081 fcsets[1] = FcConfigGetFonts(
nullptr, FcSetApplication);
1082 for (
int nset = 0; nset < 2; nset++) {
1083 fcfs = fcsets[nset];
1084 if (fcfs ==
nullptr)
1086 for (
int fnum = 0; fnum < fcfs->nfont; fnum++) {
1087 FcPattern *fcpat = fcfs->fonts[fnum];
1094 if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
1098 if (!qFuzzyIsNull(fontDef.pixelSize)) {
1099 if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch &&
1100 fontDef.pixelSize != fcpixelsize)
1104 if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
1105 FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
1106 QByteArray f = QByteArray::fromRawData((
const char *)fcfile,
1107 qstrlen((
const char *)fcfile));
1108 if (f == fid.filename && fcindex == fid.index) {
1110 match = FcFontRenderPrepare(
nullptr, pattern, fcpat);
1121 match = FcFontMatch(
nullptr, pattern, &result);
1123 int xftAntialias = 0;
1124 if (!forcedAntialiasSetting) {
1125 void *antialiasResource =
1126 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"antialiasingEnabled",
1127 QGuiApplication::primaryScreen());
1128 xftAntialias =
int(
reinterpret_cast<qintptr>(antialiasResource));
1129 if ((preferXftConf || !match) && xftAntialias > 0) {
1130 antialias = xftAntialias - 1;
1131 forcedAntialiasSetting =
true;
1135 engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
1138 if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
1139 engine->forceAutoHint = fc_autohint;
1141#if defined(FT_LCD_FILTER_H)
1143 if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
1144 engine->lcdFilterType = lcdFilter;
1147 if (!forcedAntialiasSetting) {
1148 FcBool fc_antialias;
1149 if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
1150 antialias = fc_antialias;
1154 QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
1155 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
1156 subpixelType = subpixelTypeFromMatch(match, preferXftConf);
1157 engine->subpixelType = subpixelType;
1160 FcPatternDestroy(match);
1162 void *hintStyleResource =
1163 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
1164 QGuiApplication::primaryScreen());
1165 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
1166 if (xftHintStyle > 0)
1167 engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
1169 engine->subpixelType = QFontEngine::Subpixel_None;
1170 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
1171 void *subpixelTypeResource =
1172 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
1173 QGuiApplication::primaryScreen());
1174 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
1175 if (xftSubpixelType > 1)
1176 engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
1181 format = (engine->subpixelType == QFontEngine::Subpixel_None)
1182 ? QFontEngine::Format_A8
1183 : QFontEngine::Format_A32;
1185 format = QFontEngine::Format_Mono;
1188 FcPatternDestroy(pattern);
1190 engine->antialias = antialias;
1191 engine->defaultFormat = format;
1192 engine->glyphFormat = format;
1195 if (isDprScaling() && fontDef.hintingPreference == QFont::PreferDefaultHinting) {
1196 static const bool disabled =
1197 qEnvironmentVariableIntValue(
"QT_DISABLE_DPR_FONT_HINTING") > 0;
1198 if (disabled || !engine->setVerticalHintingOnly())
1199 engine->setDefaultHintStyle(QFontEngine::HintNone);
1203bool QFontconfigDatabase::supportsVariableApplicationFonts()
const
1205#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)