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>
33 return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower);
45 if (fcweight <= FC_WEIGHT_THIN)
47 if (fcweight <= FC_WEIGHT_ULTRALIGHT)
48 return mapToQtWeightForRange(fcweight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT, QFont::Thin, QFont::ExtraLight);
49 if (fcweight <= FC_WEIGHT_LIGHT)
50 return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT, QFont::ExtraLight, QFont::Light);
51 if (fcweight <= FC_WEIGHT_NORMAL)
52 return mapToQtWeightForRange(fcweight, FC_WEIGHT_LIGHT, FC_WEIGHT_NORMAL, QFont::Light, QFont::Normal);
53 if (fcweight <= FC_WEIGHT_MEDIUM)
54 return mapToQtWeightForRange(fcweight, FC_WEIGHT_NORMAL, FC_WEIGHT_MEDIUM, QFont::Normal, QFont::Medium);
55 if (fcweight <= FC_WEIGHT_DEMIBOLD)
56 return mapToQtWeightForRange(fcweight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD, QFont::Medium, QFont::DemiBold);
57 if (fcweight <= FC_WEIGHT_BOLD)
58 return mapToQtWeightForRange(fcweight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD, QFont::DemiBold, QFont::Bold);
59 if (fcweight <= FC_WEIGHT_ULTRABOLD)
60 return mapToQtWeightForRange(fcweight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD, QFont::Bold, QFont::ExtraBold);
61 if (fcweight <= FC_WEIGHT_BLACK)
62 return mapToQtWeightForRange(fcweight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK, QFont::ExtraBold, QFont::Black);
63 if (fcweight <= FC_WEIGHT_ULTRABLACK)
64 return mapToQtWeightForRange(fcweight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK, QFont::Black,
66 return QFONT_WEIGHT_MAX;
73 const int maxStretch = 4000;
77 else if (fcwidth > maxStretch)
78 qtstretch = maxStretch;
262static_assert(
sizeof specialLanguages /
sizeof *specialLanguages == QChar::ScriptCount);
302static_assert(
sizeof languageForWritingSystem /
sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount);
304#if FC_VERSION
>= 20297
308static const char capabilityForWritingSystem[][5] = {
344static_assert(
sizeof(capabilityForWritingSystem) /
sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount);
349 const char *stylehint =
nullptr;
351 case QFont::SansSerif:
352 stylehint =
"sans-serif";
357 case QFont::TypeWriter:
358 case QFont::Monospace:
359 stylehint =
"monospace";
362 stylehint =
"cursive";
365 stylehint =
"fantasy";
375 return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
376 || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
380 QFontDatabasePrivate::ApplicationFont *applicationFont =
nullptr,
381 FT_Face face =
nullptr,
382 QFontconfigDatabase *db =
nullptr)
385 QString familyNameLang;
386 FcChar8 *value =
nullptr;
393 FcChar8 *foundry_value;
394 FcChar8 *style_value;
398 if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
401 familyName = QString::fromUtf8((
const char *)value);
403 if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
404 familyNameLang = QString::fromUtf8((
const char *)value);
406 slant_value = FC_SLANT_ROMAN;
407 weight_value = FC_WEIGHT_REGULAR;
408 spacing_value = FC_PROPORTIONAL;
409 file_value =
nullptr;
414 if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
415 slant_value = FC_SLANT_ROMAN;
416 if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
417 weight_value = FC_WEIGHT_REGULAR;
418 if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
419 width_value = FC_WIDTH_NORMAL;
420 if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
421 spacing_value = FC_PROPORTIONAL;
422 if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
423 file_value =
nullptr;
424 if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
426 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
428 if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
429 foundry_value =
nullptr;
430 if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
431 style_value =
nullptr;
432 if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
435 QSupportedWritingSystems writingSystems;
436 FcLangSet *langset =
nullptr;
437 FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
438 if (res == FcResultMatch) {
439 bool hasLang =
false;
440#if FC_VERSION
>= 20297
441 FcChar8 *cap =
nullptr;
442 FcResult capRes = FcResultNoMatch;
444 for (
int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
447 FcLangResult langRes = FcLangSetHasLang(langset, lang);
448 if (langRes != FcLangDifferentLang) {
449#if FC_VERSION
>= 20297
452 capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap);
453 if (capRes == FcResultMatch && strstr(
reinterpret_cast<
const char *>(cap), capabilityForWritingSystem[j]) ==
nullptr)
457 writingSystems.setSupported(QFontDatabase::WritingSystem(j));
464 writingSystems.setSupported(QFontDatabase::Other);
469 writingSystems.setSupported(QFontDatabase::Other);
472 QString fileName = QString::fromLocal8Bit((
const char *)file_value);
474 QFont::Style style = (slant_value == FC_SLANT_ITALIC)
476 : ((slant_value == FC_SLANT_OBLIQUE)
477 ? QFont::StyleOblique
478 : QFont::StyleNormal);
480 QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
482 double pixel_size = 0;
484 FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
486 bool fixedPitch = spacing_value >= FC_MONO;
488 FcBool colorFont =
false;
490 FcPatternGetBool(pattern, FC_COLOR, 0, &colorFont);
494 QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
495 QString styleName = style_value ? QString::fromUtf8((
const char *) style_value) : QString();
497 if (applicationFont !=
nullptr) {
498 QFontDatabasePrivate::ApplicationFont::Properties properties;
499 properties.familyName = familyName;
500 properties.styleName = styleName;
501 properties.weight = weight;
502 properties.style = style;
503 properties.stretch = stretch;
505 applicationFont->properties.append(properties);
509 FontFile *fontFile =
new FontFile;
510 fontFile->fileName = fileName;
511 fontFile->indexValue = indexValue;
512 QPlatformFontDatabase::registerFont(familyName,
514 QLatin1StringView((
const char *)foundry_value),
526 if (applicationFont !=
nullptr && face !=
nullptr && db !=
nullptr) {
527 db->addNamedInstancesForFace(face,
537 QByteArray((
const char*)file_value),
538 applicationFont->data);
543 for (
int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) {
544 const QString altFamilyName = QString::fromUtf8((
const char *)value);
548 QString altStyleName;
549 if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch)
550 altStyleName = QString::fromUtf8((
const char *)value);
552 altStyleName = styleName;
554 QString altFamilyNameLang;
555 if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch)
556 altFamilyNameLang = QString::fromUtf8((
const char *)value);
558 altFamilyNameLang = familyNameLang;
560 if (familyNameLang == altFamilyNameLang && altStyleName != styleName) {
561 if (applicationFont !=
nullptr) {
562 QFontDatabasePrivate::ApplicationFont::Properties properties;
563 properties.familyName = altFamilyName;
564 properties.styleName = altStyleName;
565 properties.weight = weight;
566 properties.style = style;
567 properties.stretch = stretch;
569 applicationFont->properties.append(properties);
573 FontFile *altFontFile =
new FontFile;
574 altFontFile->fileName = fileName;
575 altFontFile->indexValue = indexValue;
576 QPlatformFontDatabase::registerFont(altFamilyName,
578 QLatin1StringView((
const char *)foundry_value),
591 QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
599 return !qFuzzyCompare(qApp->devicePixelRatio(), qreal(1.0));
602QFontconfigDatabase::~QFontconfigDatabase()
604 FcConfigDestroy(FcConfigGetCurrent());
607void QFontconfigDatabase::populateFontDatabase()
613 FcObjectSet *os = FcObjectSetCreate();
614 FcPattern *pattern = FcPatternCreate();
615 const char *properties [] = {
616 FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
617 FC_SPACING, FC_FILE, FC_INDEX,
618 FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
619 FC_WIDTH, FC_FAMILYLANG,
620#if FC_VERSION
>= 20297
626 (
const char *)
nullptr
628 const char **p = properties;
630 FcObjectSetAdd(os, *p);
636 FcPatternAddBool(pattern, FC_VARIABLE, FcFalse);
639 fonts = FcFontList(
nullptr, pattern, os);
640 FcObjectSetDestroy(os);
641 FcPatternDestroy(pattern);
646 for (
int i = 0; i < fonts->nfont; i++)
647 populateFromPattern(fonts->fonts[i]);
649 FcFontSetDestroy (fonts);
651 struct FcDefaultFont {
656 const FcDefaultFont defaults[] = {
657 {
"Serif",
"serif",
false },
658 {
"Sans Serif",
"sans-serif",
false },
659 {
"Monospace",
"monospace",
true },
660 {
nullptr,
nullptr,
false }
662 const FcDefaultFont *f = defaults;
664 QSupportedWritingSystems ws;
665 ws.setSupported(QFontDatabase::Latin);
668 QString familyQtName = QString::fromLatin1(f->qtname);
669 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
670 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
671 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
684void QFontconfigDatabase::invalidate()
687 FcConfigAppFontClear(
nullptr);
690QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QFontDatabasePrivate::ExtendedScript script)
692 return new QFontEngineMultiFontConfig(fontEngine, script);
696QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match,
bool preferXftConf)
698 switch (hintingPreference) {
699 case QFont::PreferNoHinting:
700 return QFontEngine::HintNone;
701 case QFont::PreferVerticalHinting:
702 return QFontEngine::HintLight;
703 case QFont::PreferFullHinting:
704 return QFontEngine::HintFull;
705 case QFont::PreferDefaultHinting:
710 return QFontEngine::HintNone;
712 void *hintStyleResource =
713 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
714 QGuiApplication::primaryScreen());
715 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
716 if (preferXftConf && xftHintStyle > 0)
717 return QFontEngine::HintStyle(xftHintStyle - 1);
720 if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
721 switch (hint_style) {
723 return QFontEngine::HintNone;
725 return QFontEngine::HintLight;
727 return QFontEngine::HintMedium;
729 return QFontEngine::HintFull;
735 if (xftHintStyle > 0)
736 return QFontEngine::HintStyle(xftHintStyle - 1);
738 return QFontEngine::HintFull;
741QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match,
bool preferXftConf)
743 void *subpixelTypeResource =
744 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
745 QGuiApplication::primaryScreen());
746 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
747 if (preferXftConf && xftSubpixelType > 0)
748 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
750 int subpixel = FC_RGBA_UNKNOWN;
751 if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
753 case FC_RGBA_UNKNOWN:
755 return QFontEngine::Subpixel_None;
757 return QFontEngine::Subpixel_RGB;
759 return QFontEngine::Subpixel_BGR;
761 return QFontEngine::Subpixel_VRGB;
763 return QFontEngine::Subpixel_VBGR;
770 if (xftSubpixelType > 0)
771 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
773 return QFontEngine::Subpixel_None;
777QFontEngine *QFontconfigDatabase::fontEngine(
const QFontDef &f,
void *usrPtr)
782 FontFile *fontfile =
static_cast<FontFile *> (usrPtr);
783 QFontEngine::FaceId fid;
784 fid.filename = QFile::encodeName(fontfile->fileName);
785 fid.index = fontfile->indexValue;
786 fid.instanceIndex = fontfile->instanceIndex;
787 fid.variableAxes = f.variableAxisValues;
790 QFontEngineFT *engine =
new QFontEngineFT(f);
791 engine->face_id = fid;
793 setupFontEngine(engine, f);
795 if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
803QFontEngine *QFontconfigDatabase::fontEngine(
const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
805 QFontEngineFT *engine =
static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference));
806 if (engine ==
nullptr)
809 setupFontEngine(engine, engine->fontDef);
814QStringList QFontconfigDatabase::fallbacksForFamily(
const QString &family,
816 QFont::StyleHint styleHint,
817 QFontDatabasePrivate::ExtendedScript script)
const
819 QStringList fallbackFamilies;
820 FcPattern *pattern = FcPatternCreate();
822 return fallbackFamilies;
825 value.type = FcTypeString;
826 const QByteArray cs = family.toUtf8();
827 value.u.s = (
const FcChar8 *)cs.data();
828 FcPatternAdd(pattern,FC_FAMILY,value,
true);
831 if (script == QFontDatabasePrivate::Script_Emoji) {
832 FcPatternAddBool(pattern, FC_COLOR,
true);
833 value.u.s = (
const FcChar8 *)
"emoji";
834 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
838 int slant_value = FC_SLANT_ROMAN;
839 if (style == QFont::StyleItalic)
840 slant_value = FC_SLANT_ITALIC;
841 else if (style == QFont::StyleOblique)
842 slant_value = FC_SLANT_OBLIQUE;
843 FcPatternAddInteger(pattern, FC_SLANT, slant_value);
845 Q_ASSERT(uint(script) < QFontDatabasePrivate::ScriptCount);
846 if (uint(script) < QChar::ScriptCount && *specialLanguages[script] !=
'\0') {
847 FcLangSet *ls = FcLangSetCreate();
848 FcLangSetAdd(ls, (
const FcChar8*)specialLanguages[script]);
849 FcPatternAddLangSet(pattern, FC_LANG, ls);
850 FcLangSetDestroy(ls);
851 }
else if (!family.isEmpty()) {
857 FcPattern *dummy = FcPatternCreate();
858 FcDefaultSubstitute(dummy);
859 FcChar8 *lang =
nullptr;
860 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
861 if (res == FcResultMatch)
862 FcPatternAddString(pattern, FC_LANG, lang);
863 FcPatternDestroy(dummy);
866 const char *stylehint = getFcFamilyForStyleHint(styleHint);
868 value.u.s = (
const FcChar8 *)stylehint;
869 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
872 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
873 FcDefaultSubstitute(pattern);
875 FcResult result = FcResultMatch;
876 FcFontSet *fontSet = FcFontSort(
nullptr,pattern,FcFalse,
nullptr,&result);
877 FcPatternDestroy(pattern);
880 QDuplicateTracker<QString> duplicates(fontSet->nfont + 1);
881 (
void)duplicates.hasSeen(family.toCaseFolded());
882 for (
int i = 0; i < fontSet->nfont; i++) {
883 FcChar8 *value =
nullptr;
884 if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
887 const QString familyName = QString::fromUtf8((
const char *)value);
888 const QString familyNameCF = familyName.toCaseFolded();
889 if (!duplicates.hasSeen(familyNameCF)) {
890 fallbackFamilies << familyName;
893 FcFontSetDestroy(fontSet);
897 return fallbackFamilies;
900static FcPattern *
queryFont(
const FcChar8 *file,
const QByteArray &data,
int id, FcBlanks *blanks,
int *count, FT_Face *face)
902#if FC_VERSION
< 20402
905 return FcFreeTypeQuery(file, id, blanks, count);
907 if (data.isEmpty()) {
909 return FcFreeTypeQuery(file, id, blanks, count);
912 FT_Library lib = qt_getFreetype();
914 FcPattern *pattern =
nullptr;
916 if (!FT_New_Memory_Face(lib, (
const FT_Byte *)data.constData(), data.size(), id, face)) {
917 *count = (*face)->num_faces;
919 pattern = FcFreeTypeQueryFace(*face, file, id, blanks);
928QStringList QFontconfigDatabase::addApplicationFont(
const QByteArray &fontData,
const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
930 QStringList families;
932 if (applicationFont !=
nullptr)
933 applicationFont->properties.clear();
935 FcFontSet *set = FcConfigGetFonts(
nullptr, FcSetApplication);
937 FcConfigAppFontAddFile(
nullptr, (
const FcChar8 *)
":/non-existent");
938 set = FcConfigGetFonts(
nullptr, FcSetApplication);
944 FcBlanks *blanks = FcConfigGetBlanks(
nullptr);
950 pattern = queryFont((
const FcChar8 *)QFile::encodeName(fileName).constData(),
951 fontData, id, blanks, &count, &face);
955 FcChar8 *fam =
nullptr;
956 if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
957 QString family = QString::fromUtf8(
reinterpret_cast<
const char *>(fam));
960 populateFromPattern(pattern, applicationFont, face,
this);
965 FcFontSetAdd(set, pattern);
968 }
while (id < count);
973QString QFontconfigDatabase::resolveFontFamilyAlias(
const QString &family)
const
975 QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family);
976 if (!resolved.isEmpty() && resolved != family)
978 FcPattern *pattern = FcPatternCreate();
982 if (!family.isEmpty()) {
983 const QByteArray cs = family.toUtf8();
984 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8 *) cs.constData());
986 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
987 FcDefaultSubstitute(pattern);
989 FcChar8 *familyAfterSubstitution =
nullptr;
990 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
991 resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
992 FcPatternDestroy(pattern);
997QFont QFontconfigDatabase::defaultFont()
const
1002 FcPattern *dummy = FcPatternCreate();
1003 FcDefaultSubstitute(dummy);
1004 FcChar8 *lang =
nullptr;
1005 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
1007 FcPattern *pattern = FcPatternCreate();
1008 if (res == FcResultMatch) {
1011 FcPatternAddString(pattern, FC_LANG, lang);
1013 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1014 FcDefaultSubstitute(pattern);
1016 FcChar8 *familyAfterSubstitution =
nullptr;
1017 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
1018 QString resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
1019 FcPatternDestroy(pattern);
1020 FcPatternDestroy(dummy);
1022 return QFont(resolved);
1025void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine,
const QFontDef &fontDef)
const
1027 bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
1028 bool forcedAntialiasSetting = !antialias || isDprScaling();
1030 const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
1031 bool preferXftConf =
false;
1034 const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(
':');
1035 preferXftConf = !(desktopEnv.contains(
"KDE") || desktopEnv.contains(
"LXQT") || desktopEnv.contains(
"UKUI"));
1038 QFontEngine::GlyphFormat format;
1040 FcPattern *pattern = FcPatternCreate();
1041 FcPattern *match =
nullptr;
1044 value.type = FcTypeString;
1045 QByteArray cs = fontDef.families.first().toUtf8();
1046 value.u.s = (
const FcChar8 *)cs.data();
1047 FcPatternAdd(pattern,FC_FAMILY,value,
true);
1049 QFontEngine::FaceId fid = engine->faceId();
1051 if (!fid.filename.isEmpty()) {
1052 value.u.s = (
const FcChar8 *)fid.filename.data();
1053 FcPatternAdd(pattern,FC_FILE,value,
true);
1055 value.type = FcTypeInteger;
1056 value.u.i = fid.index;
1057 FcPatternAdd(pattern,FC_INDEX,value,
true);
1060 if (!qFuzzyIsNull(fontDef.pixelSize))
1061 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
1065 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1066 FcDefaultSubstitute(pattern);
1069 if (!fid.filename.isEmpty()) {
1072 FcFontSet *fcsets[2], *fcfs;
1074 fcsets[0] = FcConfigGetFonts(
nullptr, FcSetSystem);
1075 fcsets[1] = FcConfigGetFonts(
nullptr, FcSetApplication);
1076 for (
int nset = 0; nset < 2; nset++) {
1077 fcfs = fcsets[nset];
1078 if (fcfs ==
nullptr)
1080 for (
int fnum = 0; fnum < fcfs->nfont; fnum++) {
1081 FcPattern *fcpat = fcfs->fonts[fnum];
1088 if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
1092 if (!qFuzzyIsNull(fontDef.pixelSize)) {
1093 if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch &&
1094 fontDef.pixelSize != fcpixelsize)
1098 if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
1099 FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
1100 QByteArray f = QByteArray::fromRawData((
const char *)fcfile,
1101 qstrlen((
const char *)fcfile));
1102 if (f == fid.filename && fcindex == fid.index) {
1104 match = FcFontRenderPrepare(
nullptr, pattern, fcpat);
1115 match = FcFontMatch(
nullptr, pattern, &result);
1117 int xftAntialias = 0;
1118 if (!forcedAntialiasSetting) {
1119 void *antialiasResource =
1120 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"antialiasingEnabled",
1121 QGuiApplication::primaryScreen());
1122 xftAntialias =
int(
reinterpret_cast<qintptr>(antialiasResource));
1123 if ((preferXftConf || !match) && xftAntialias > 0) {
1124 antialias = xftAntialias - 1;
1125 forcedAntialiasSetting =
true;
1129 engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
1132 if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
1133 engine->forceAutoHint = fc_autohint;
1135#if defined(FT_LCD_FILTER_H)
1137 if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
1138 engine->lcdFilterType = lcdFilter;
1141 if (!forcedAntialiasSetting) {
1142 FcBool fc_antialias;
1143 if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
1144 antialias = fc_antialias;
1148 QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
1149 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
1150 subpixelType = subpixelTypeFromMatch(match, preferXftConf);
1151 engine->subpixelType = subpixelType;
1154 FcPatternDestroy(match);
1156 void *hintStyleResource =
1157 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
1158 QGuiApplication::primaryScreen());
1159 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
1160 if (xftHintStyle > 0)
1161 engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
1163 engine->subpixelType = QFontEngine::Subpixel_None;
1164 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
1165 void *subpixelTypeResource =
1166 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
1167 QGuiApplication::primaryScreen());
1168 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
1169 if (xftSubpixelType > 1)
1170 engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
1175 format = (engine->subpixelType == QFontEngine::Subpixel_None)
1176 ? QFontEngine::Format_A8
1177 : QFontEngine::Format_A32;
1179 format = QFontEngine::Format_Mono;
1182 FcPatternDestroy(pattern);
1184 engine->antialias = antialias;
1185 engine->defaultFormat = format;
1186 engine->glyphFormat = format;
1189bool QFontconfigDatabase::supportsVariableApplicationFonts()
const
1191#if (FREETYPE_MAJOR*10000
+ FREETYPE_MINOR*100
+ FREETYPE_PATCH) >= 20900
static int stretchFromFcWidth(int fcwidth)
static QT_BEGIN_NAMESPACE int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper)
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 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)