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;
258static_assert(
sizeof specialLanguages /
sizeof *specialLanguages == QChar::ScriptCount);
298static_assert(
sizeof languageForWritingSystem /
sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount);
300#if FC_VERSION
>= 20297
304static const char capabilityForWritingSystem[][5] = {
340static_assert(
sizeof(capabilityForWritingSystem) /
sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount);
345 const char *stylehint =
nullptr;
347 case QFont::SansSerif:
348 stylehint =
"sans-serif";
353 case QFont::TypeWriter:
354 case QFont::Monospace:
355 stylehint =
"monospace";
358 stylehint =
"cursive";
361 stylehint =
"fantasy";
371 return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
372 || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
376 QFontDatabasePrivate::ApplicationFont *applicationFont =
nullptr,
377 FT_Face face =
nullptr,
378 QFontconfigDatabase *db =
nullptr)
381 QString familyNameLang;
382 FcChar8 *value =
nullptr;
389 FcChar8 *foundry_value;
390 FcChar8 *style_value;
394 if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
397 familyName = QString::fromUtf8((
const char *)value);
399 if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
400 familyNameLang = QString::fromUtf8((
const char *)value);
402 slant_value = FC_SLANT_ROMAN;
403 weight_value = FC_WEIGHT_REGULAR;
404 spacing_value = FC_PROPORTIONAL;
405 file_value =
nullptr;
410 if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
411 slant_value = FC_SLANT_ROMAN;
412 if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
413 weight_value = FC_WEIGHT_REGULAR;
414 if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
415 width_value = FC_WIDTH_NORMAL;
416 if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
417 spacing_value = FC_PROPORTIONAL;
418 if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
419 file_value =
nullptr;
420 if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
422 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
424 if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
425 foundry_value =
nullptr;
426 if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
427 style_value =
nullptr;
428 if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
431 QSupportedWritingSystems writingSystems;
432 FcLangSet *langset =
nullptr;
433 FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset);
434 if (res == FcResultMatch) {
435 bool hasLang =
false;
436#if FC_VERSION
>= 20297
437 FcChar8 *cap =
nullptr;
438 FcResult capRes = FcResultNoMatch;
440 for (
int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) {
443 FcLangResult langRes = FcLangSetHasLang(langset, lang);
444 if (langRes != FcLangDifferentLang) {
445#if FC_VERSION
>= 20297
448 capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap);
449 if (capRes == FcResultMatch && strstr(
reinterpret_cast<
const char *>(cap), capabilityForWritingSystem[j]) ==
nullptr)
453 writingSystems.setSupported(QFontDatabase::WritingSystem(j));
460 writingSystems.setSupported(QFontDatabase::Other);
465 writingSystems.setSupported(QFontDatabase::Other);
468 QString fileName = QString::fromLocal8Bit((
const char *)file_value);
470 QFont::Style style = (slant_value == FC_SLANT_ITALIC)
472 : ((slant_value == FC_SLANT_OBLIQUE)
473 ? QFont::StyleOblique
474 : QFont::StyleNormal);
476 QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value));
478 double pixel_size = 0;
480 FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size);
482 bool fixedPitch = spacing_value >= FC_MONO;
484 FcBool colorFont =
false;
486 FcPatternGetBool(pattern, FC_COLOR, 0, &colorFont);
490 QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value));
491 QString styleName = style_value ? QString::fromUtf8((
const char *) style_value) : QString();
493 if (applicationFont !=
nullptr) {
494 QFontDatabasePrivate::ApplicationFont::Properties properties;
495 properties.familyName = familyName;
496 properties.styleName = styleName;
497 properties.weight = weight;
498 properties.style = style;
499 properties.stretch = stretch;
501 applicationFont->properties.append(properties);
505 FontFile *fontFile =
new FontFile;
506 fontFile->fileName = fileName;
507 fontFile->indexValue = indexValue;
508 QPlatformFontDatabase::registerFont(familyName,
510 QLatin1StringView((
const char *)foundry_value),
522 if (applicationFont !=
nullptr && face !=
nullptr && db !=
nullptr) {
523 db->addNamedInstancesForFace(face,
533 QByteArray((
const char*)file_value),
534 applicationFont->data);
539 for (
int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) {
540 const QString altFamilyName = QString::fromUtf8((
const char *)value);
544 QString altStyleName;
545 if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch)
546 altStyleName = QString::fromUtf8((
const char *)value);
548 altStyleName = styleName;
550 QString altFamilyNameLang;
551 if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch)
552 altFamilyNameLang = QString::fromUtf8((
const char *)value);
554 altFamilyNameLang = familyNameLang;
556 if (familyNameLang == altFamilyNameLang && altStyleName != styleName) {
557 if (applicationFont !=
nullptr) {
558 QFontDatabasePrivate::ApplicationFont::Properties properties;
559 properties.familyName = altFamilyName;
560 properties.styleName = altStyleName;
561 properties.weight = weight;
562 properties.style = style;
563 properties.stretch = stretch;
565 applicationFont->properties.append(properties);
569 FontFile *altFontFile =
new FontFile;
570 altFontFile->fileName = fileName;
571 altFontFile->indexValue = indexValue;
572 QPlatformFontDatabase::registerFont(altFamilyName,
574 QLatin1StringView((
const char *)foundry_value),
587 QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
595 return !qFuzzyCompare(qApp->devicePixelRatio(), qreal(1.0));
598QFontconfigDatabase::~QFontconfigDatabase()
600 FcConfigDestroy(FcConfigGetCurrent());
603void QFontconfigDatabase::populateFontDatabase()
609 FcObjectSet *os = FcObjectSetCreate();
610 FcPattern *pattern = FcPatternCreate();
611 const char *properties [] = {
612 FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
613 FC_SPACING, FC_FILE, FC_INDEX,
614 FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
615 FC_WIDTH, FC_FAMILYLANG,
616#if FC_VERSION
>= 20297
622 (
const char *)
nullptr
624 const char **p = properties;
626 FcObjectSetAdd(os, *p);
632 FcPatternAddBool(pattern, FC_VARIABLE, FcFalse);
635 fonts = FcFontList(
nullptr, pattern, os);
636 FcObjectSetDestroy(os);
637 FcPatternDestroy(pattern);
642 for (
int i = 0; i < fonts->nfont; i++)
643 populateFromPattern(fonts->fonts[i]);
645 FcFontSetDestroy (fonts);
647 struct FcDefaultFont {
652 const FcDefaultFont defaults[] = {
653 {
"Serif",
"serif",
false },
654 {
"Sans Serif",
"sans-serif",
false },
655 {
"Monospace",
"monospace",
true },
656 {
nullptr,
nullptr,
false }
658 const FcDefaultFont *f = defaults;
660 QSupportedWritingSystems ws;
661 ws.setSupported(QFontDatabase::Latin);
664 QString familyQtName = QString::fromLatin1(f->qtname);
665 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
666 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
667 registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,
true,
true,0,f->fixed,
false,ws,
nullptr);
680void QFontconfigDatabase::invalidate()
683 FcConfigAppFontClear(
nullptr);
686QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QFontDatabasePrivate::ExtendedScript script)
688 return new QFontEngineMultiFontConfig(fontEngine, script);
692QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match,
bool preferXftConf)
694 switch (hintingPreference) {
695 case QFont::PreferNoHinting:
696 return QFontEngine::HintNone;
697 case QFont::PreferVerticalHinting:
698 return QFontEngine::HintLight;
699 case QFont::PreferFullHinting:
700 return QFontEngine::HintFull;
701 case QFont::PreferDefaultHinting:
706 return QFontEngine::HintNone;
708 void *hintStyleResource =
709 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
710 QGuiApplication::primaryScreen());
711 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
712 if (preferXftConf && xftHintStyle > 0)
713 return QFontEngine::HintStyle(xftHintStyle - 1);
716 if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
717 switch (hint_style) {
719 return QFontEngine::HintNone;
721 return QFontEngine::HintLight;
723 return QFontEngine::HintMedium;
725 return QFontEngine::HintFull;
731 if (xftHintStyle > 0)
732 return QFontEngine::HintStyle(xftHintStyle - 1);
734 return QFontEngine::HintFull;
737QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match,
bool preferXftConf)
739 void *subpixelTypeResource =
740 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
741 QGuiApplication::primaryScreen());
742 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
743 if (preferXftConf && xftSubpixelType > 0)
744 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
746 int subpixel = FC_RGBA_UNKNOWN;
747 if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
749 case FC_RGBA_UNKNOWN:
751 return QFontEngine::Subpixel_None;
753 return QFontEngine::Subpixel_RGB;
755 return QFontEngine::Subpixel_BGR;
757 return QFontEngine::Subpixel_VRGB;
759 return QFontEngine::Subpixel_VBGR;
766 if (xftSubpixelType > 0)
767 return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
769 return QFontEngine::Subpixel_None;
773QFontEngine *QFontconfigDatabase::fontEngine(
const QFontDef &f,
void *usrPtr)
778 FontFile *fontfile =
static_cast<FontFile *> (usrPtr);
779 QFontEngine::FaceId fid;
780 fid.filename = QFile::encodeName(fontfile->fileName);
781 fid.index = fontfile->indexValue;
782 fid.instanceIndex = fontfile->instanceIndex;
783 fid.variableAxes = f.variableAxisValues;
786 QFontEngineFT *engine =
new QFontEngineFT(f);
787 engine->face_id = fid;
789 setupFontEngine(engine, f);
791 if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
799QFontEngine *QFontconfigDatabase::fontEngine(
const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
801 QFontEngineFT *engine =
static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference));
802 if (engine ==
nullptr)
805 setupFontEngine(engine, engine->fontDef);
810QStringList QFontconfigDatabase::fallbacksForFamily(
const QString &family,
812 QFont::StyleHint styleHint,
813 QFontDatabasePrivate::ExtendedScript script)
const
815 QStringList fallbackFamilies;
816 FcPattern *pattern = FcPatternCreate();
818 return fallbackFamilies;
821 value.type = FcTypeString;
822 const QByteArray cs = family.toUtf8();
823 value.u.s = (
const FcChar8 *)cs.data();
824 FcPatternAdd(pattern,FC_FAMILY,value,
true);
827 if (script == QFontDatabasePrivate::Script_Emoji) {
828 FcPatternAddBool(pattern, FC_COLOR,
true);
829 value.u.s = (
const FcChar8 *)
"emoji";
830 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
834 int slant_value = FC_SLANT_ROMAN;
835 if (style == QFont::StyleItalic)
836 slant_value = FC_SLANT_ITALIC;
837 else if (style == QFont::StyleOblique)
838 slant_value = FC_SLANT_OBLIQUE;
839 FcPatternAddInteger(pattern, FC_SLANT, slant_value);
841 Q_ASSERT(uint(script) < QFontDatabasePrivate::ScriptCount);
842 if (uint(script) < QChar::ScriptCount && *specialLanguages[script] !=
'\0') {
843 FcLangSet *ls = FcLangSetCreate();
844 FcLangSetAdd(ls, (
const FcChar8*)specialLanguages[script]);
845 FcPatternAddLangSet(pattern, FC_LANG, ls);
846 FcLangSetDestroy(ls);
847 }
else if (!family.isEmpty()) {
853 FcPattern *dummy = FcPatternCreate();
854 FcDefaultSubstitute(dummy);
855 FcChar8 *lang =
nullptr;
856 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
857 if (res == FcResultMatch)
858 FcPatternAddString(pattern, FC_LANG, lang);
859 FcPatternDestroy(dummy);
862 const char *stylehint = getFcFamilyForStyleHint(styleHint);
864 value.u.s = (
const FcChar8 *)stylehint;
865 FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue);
868 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
869 FcDefaultSubstitute(pattern);
871 FcResult result = FcResultMatch;
872 FcFontSet *fontSet = FcFontSort(
nullptr,pattern,FcFalse,
nullptr,&result);
873 FcPatternDestroy(pattern);
876 QDuplicateTracker<QString> duplicates(fontSet->nfont + 1);
877 (
void)duplicates.hasSeen(family.toCaseFolded());
878 for (
int i = 0; i < fontSet->nfont; i++) {
879 FcChar8 *value =
nullptr;
880 if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch)
883 const QString familyName = QString::fromUtf8((
const char *)value);
884 const QString familyNameCF = familyName.toCaseFolded();
885 if (!duplicates.hasSeen(familyNameCF)) {
886 fallbackFamilies << familyName;
889 FcFontSetDestroy(fontSet);
893 return fallbackFamilies;
896static FcPattern *
queryFont(
const FcChar8 *file,
const QByteArray &data,
int id, FcBlanks *blanks,
int *count, FT_Face *face)
898#if FC_VERSION
< 20402
901 return FcFreeTypeQuery(file, id, blanks, count);
903 if (data.isEmpty()) {
905 return FcFreeTypeQuery(file, id, blanks, count);
908 FT_Library lib = qt_getFreetype();
910 FcPattern *pattern =
nullptr;
912 if (!FT_New_Memory_Face(lib, (
const FT_Byte *)data.constData(), data.size(), id, face)) {
913 *count = (*face)->num_faces;
915 pattern = FcFreeTypeQueryFace(*face, file, id, blanks);
924QStringList QFontconfigDatabase::addApplicationFont(
const QByteArray &fontData,
const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
926 QStringList families;
928 if (applicationFont !=
nullptr)
929 applicationFont->properties.clear();
931 FcFontSet *set = FcConfigGetFonts(
nullptr, FcSetApplication);
933 FcConfigAppFontAddFile(
nullptr, (
const FcChar8 *)
":/non-existent");
934 set = FcConfigGetFonts(
nullptr, FcSetApplication);
940 FcBlanks *blanks = FcConfigGetBlanks(
nullptr);
946 pattern = queryFont((
const FcChar8 *)QFile::encodeName(fileName).constData(),
947 fontData, id, blanks, &count, &face);
951 FcChar8 *fam =
nullptr;
952 if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
953 QString family = QString::fromUtf8(
reinterpret_cast<
const char *>(fam));
956 populateFromPattern(pattern, applicationFont, face,
this);
961 FcFontSetAdd(set, pattern);
964 }
while (id < count);
969QString QFontconfigDatabase::resolveFontFamilyAlias(
const QString &family)
const
971 QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family);
972 if (!resolved.isEmpty() && resolved != family)
974 FcPattern *pattern = FcPatternCreate();
978 if (!family.isEmpty()) {
979 const QByteArray cs = family.toUtf8();
980 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8 *) cs.constData());
982 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
983 FcDefaultSubstitute(pattern);
985 FcChar8 *familyAfterSubstitution =
nullptr;
986 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
987 resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
988 FcPatternDestroy(pattern);
993QFont QFontconfigDatabase::defaultFont()
const
998 FcPattern *dummy = FcPatternCreate();
999 FcDefaultSubstitute(dummy);
1000 FcChar8 *lang =
nullptr;
1001 FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang);
1003 FcPattern *pattern = FcPatternCreate();
1004 if (res == FcResultMatch) {
1007 FcPatternAddString(pattern, FC_LANG, lang);
1009 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1010 FcDefaultSubstitute(pattern);
1012 FcChar8 *familyAfterSubstitution =
nullptr;
1013 FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution);
1014 QString resolved = QString::fromUtf8((
const char *) familyAfterSubstitution);
1015 FcPatternDestroy(pattern);
1016 FcPatternDestroy(dummy);
1018 return QFont(resolved);
1021void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine,
const QFontDef &fontDef)
const
1023 bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
1024 bool forcedAntialiasSetting = !antialias || isDprScaling();
1026 const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
1027 bool preferXftConf =
false;
1030 const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(
':');
1031 preferXftConf = !(desktopEnv.contains(
"KDE") || desktopEnv.contains(
"LXQT") || desktopEnv.contains(
"UKUI"));
1034 QFontEngine::GlyphFormat format;
1036 FcPattern *pattern = FcPatternCreate();
1037 FcPattern *match =
nullptr;
1040 value.type = FcTypeString;
1041 QByteArray cs = fontDef.families.first().toUtf8();
1042 value.u.s = (
const FcChar8 *)cs.data();
1043 FcPatternAdd(pattern,FC_FAMILY,value,
true);
1045 QFontEngine::FaceId fid = engine->faceId();
1047 if (!fid.filename.isEmpty()) {
1048 value.u.s = (
const FcChar8 *)fid.filename.data();
1049 FcPatternAdd(pattern,FC_FILE,value,
true);
1051 value.type = FcTypeInteger;
1052 value.u.i = fid.index;
1053 FcPatternAdd(pattern,FC_INDEX,value,
true);
1056 if (!qFuzzyIsNull(fontDef.pixelSize))
1057 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
1061 FcConfigSubstitute(
nullptr, pattern, FcMatchPattern);
1062 FcDefaultSubstitute(pattern);
1065 if (!fid.filename.isEmpty()) {
1068 FcFontSet *fcsets[2], *fcfs;
1070 fcsets[0] = FcConfigGetFonts(
nullptr, FcSetSystem);
1071 fcsets[1] = FcConfigGetFonts(
nullptr, FcSetApplication);
1072 for (
int nset = 0; nset < 2; nset++) {
1073 fcfs = fcsets[nset];
1074 if (fcfs ==
nullptr)
1076 for (
int fnum = 0; fnum < fcfs->nfont; fnum++) {
1077 FcPattern *fcpat = fcfs->fonts[fnum];
1084 if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
1088 if (!qFuzzyIsNull(fontDef.pixelSize)) {
1089 if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch &&
1090 fontDef.pixelSize != fcpixelsize)
1094 if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
1095 FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
1096 QByteArray f = QByteArray::fromRawData((
const char *)fcfile,
1097 qstrlen((
const char *)fcfile));
1098 if (f == fid.filename && fcindex == fid.index) {
1100 match = FcFontRenderPrepare(
nullptr, pattern, fcpat);
1111 match = FcFontMatch(
nullptr, pattern, &result);
1113 int xftAntialias = 0;
1114 if (!forcedAntialiasSetting) {
1115 void *antialiasResource =
1116 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"antialiasingEnabled",
1117 QGuiApplication::primaryScreen());
1118 xftAntialias =
int(
reinterpret_cast<qintptr>(antialiasResource));
1119 if ((preferXftConf || !match) && xftAntialias > 0) {
1120 antialias = xftAntialias - 1;
1121 forcedAntialiasSetting =
true;
1125 engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
1128 if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
1129 engine->forceAutoHint = fc_autohint;
1131#if defined(FT_LCD_FILTER_H)
1133 if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
1134 engine->lcdFilterType = lcdFilter;
1137 if (!forcedAntialiasSetting) {
1138 FcBool fc_antialias;
1139 if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
1140 antialias = fc_antialias;
1144 QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
1145 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
1146 subpixelType = subpixelTypeFromMatch(match, preferXftConf);
1147 engine->subpixelType = subpixelType;
1150 FcPatternDestroy(match);
1152 void *hintStyleResource =
1153 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"hintstyle",
1154 QGuiApplication::primaryScreen());
1155 int xftHintStyle =
int(
reinterpret_cast<qintptr>(hintStyleResource));
1156 if (xftHintStyle > 0)
1157 engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
1159 engine->subpixelType = QFontEngine::Subpixel_None;
1160 if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
1161 void *subpixelTypeResource =
1162 QGuiApplication::platformNativeInterface()->nativeResourceForScreen(
"subpixeltype",
1163 QGuiApplication::primaryScreen());
1164 int xftSubpixelType =
int(
reinterpret_cast<qintptr>(subpixelTypeResource));
1165 if (xftSubpixelType > 1)
1166 engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
1171 format = (engine->subpixelType == QFontEngine::Subpixel_None)
1172 ? QFontEngine::Format_A8
1173 : QFontEngine::Format_A32;
1175 format = QFontEngine::Format_Mono;
1178 FcPatternDestroy(pattern);
1180 engine->antialias = antialias;
1181 engine->defaultFormat = format;
1182 engine->glyphFormat = format;
1185bool QFontconfigDatabase::supportsVariableApplicationFonts()
const
1187#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)