diff options
Diffstat (limited to 'src/gui/text/unix/qfontconfigdatabase.cpp')
-rw-r--r-- | src/gui/text/unix/qfontconfigdatabase.cpp | 227 |
1 files changed, 171 insertions, 56 deletions
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp index 474644b871..cfa141f5ed 100644 --- a/src/gui/text/unix/qfontconfigdatabase.cpp +++ b/src/gui/text/unix/qfontconfigdatabase.cpp @@ -16,7 +16,6 @@ #include <qpa/qplatformservices.h> #include <QtGui/private/qguiapplication_p.h> -#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/qguiapplication.h> @@ -366,7 +365,10 @@ static inline bool requiresOpenType(int writingSystem) || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); } -static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) +static void populateFromPattern(FcPattern *pattern, + QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr, + FT_Face face = nullptr, + QFontconfigDatabase *db = nullptr) { QString familyName; QString familyNameLang; @@ -489,6 +491,20 @@ static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::Applic } QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); + if (applicationFont != nullptr && face != nullptr && db != nullptr) { + db->addNamedInstancesForFace(face, + indexValue, + familyName, + styleName, + weight, + stretch, + style, + fixedPitch, + writingSystems, + QByteArray((const char*)file_value), + applicationFont->data); + } + // qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) { @@ -528,6 +544,11 @@ static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::Applic } +static bool isDprScaling() +{ + return !qFuzzyCompare(qApp->devicePixelRatio(), 1.0); +} + QFontconfigDatabase::~QFontconfigDatabase() { FcConfigDestroy(FcConfigGetCurrent()); @@ -556,6 +577,12 @@ void QFontconfigDatabase::populateFontDatabase() FcObjectSetAdd(os, *p); ++p; } + +#ifdef FC_VARIABLE + /* Support the named instance of Variable Fonts. */ + FcPatternAddBool(pattern, FC_VARIABLE, FcFalse); +#endif + fonts = FcFontList(nullptr, pattern, os); FcObjectSetDestroy(os); FcPatternDestroy(pattern); @@ -613,7 +640,7 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, } namespace { -QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf) +QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool preferXftConf) { switch (hintingPreference) { case QFont::PreferNoHinting: @@ -626,9 +653,16 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin break; } - if (QHighDpiScaling::isActive()) + if (isDprScaling()) return QFontEngine::HintNone; + void *hintStyleResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", + QGuiApplication::primaryScreen()); + int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource)); + if (preferXftConf && xftHintStyle > 0) + return QFontEngine::HintStyle(xftHintStyle - 1); + int hint_style = 0; if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) { switch (hint_style) { @@ -645,21 +679,21 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin break; } } - - if (useXftConf) { - void *hintStyleResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", - QGuiApplication::primaryScreen()); - int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource)); - if (hintStyle > 0) - return QFontEngine::HintStyle(hintStyle - 1); - } + if (xftHintStyle > 0) + return QFontEngine::HintStyle(xftHintStyle - 1); return QFontEngine::HintFull; } -QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf) +QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool preferXftConf) { + void *subpixelTypeResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype", + QGuiApplication::primaryScreen()); + int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource)); + if (preferXftConf && xftSubpixelType > 0) + return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1); + int subpixel = FC_RGBA_UNKNOWN; if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) { switch (subpixel) { @@ -680,14 +714,8 @@ QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bo } } - if (useXftConf) { - void *subpixelTypeResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype", - QGuiApplication::primaryScreen()); - int subpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource)); - if (subpixelType > 0) - return QFontEngine::SubpixelAntialiasingType(subpixelType - 1); - } + if (xftSubpixelType > 0) + return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1); return QFontEngine::Subpixel_None; } @@ -702,6 +730,8 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; + fid.instanceIndex = fontfile->instanceIndex; + fid.variableAxes = f.variableAxisValues; // FIXME: Unify with logic in QFontEngineFT::create() QFontEngineFT *engine = new QFontEngineFT(f); @@ -803,26 +833,28 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont return fallbackFamilies; } -static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count) +static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count, FT_Face *face) { #if FC_VERSION < 20402 Q_UNUSED(data); + *face = nullptr; return FcFreeTypeQuery(file, id, blanks, count); #else - if (data.isEmpty()) + if (data.isEmpty()) { + *face = nullptr; return FcFreeTypeQuery(file, id, blanks, count); + } FT_Library lib = qt_getFreetype(); FcPattern *pattern = nullptr; - FT_Face face; - if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { - *count = face->num_faces; - - pattern = FcFreeTypeQueryFace(face, file, id, blanks); + if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, face)) { + *count = (*face)->num_faces; - FT_Done_Face(face); + pattern = FcFreeTypeQueryFace(*face, file, id, blanks); + } else { + *face = nullptr; } return pattern; @@ -850,8 +882,9 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, FcPattern *pattern; do { + FT_Face face; pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(), - fontData, id, blanks, &count); + fontData, id, blanks, &count, &face); if (!pattern) return families; @@ -860,7 +893,10 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); families << family; } - populateFromPattern(pattern, applicationFont); + populateFromPattern(pattern, applicationFont, face, this); + + if (face) + FT_Done_Face(face); FcFontSetAdd(set, pattern); @@ -925,28 +961,20 @@ QFont QFontconfigDatabase::defaultFont() const void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const { bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - bool forcedAntialiasSetting = !antialias || QHighDpiScaling::isActive(); + bool forcedAntialiasSetting = !antialias || isDprScaling(); const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); - bool useXftConf = false; + bool preferXftConf = false; if (services) { const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':'); - useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE"); - } - - if (useXftConf && !forcedAntialiasSetting) { - void *antialiasResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", - QGuiApplication::primaryScreen()); - int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource)); - if (antialiasingEnabled > 0) - antialias = antialiasingEnabled - 1; + preferXftConf = !(desktopEnv.contains("KDE") || desktopEnv.contains("LXQT") || desktopEnv.contains("UKUI")); } QFontEngine::GlyphFormat format; // try and get the pattern FcPattern *pattern = FcPatternCreate(); + FcPattern *match = nullptr; FcValue value; value.type = FcTypeString; @@ -965,7 +993,7 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef FcPatternAdd(pattern,FC_INDEX,value,true); } - if (fontDef.pixelSize > 0.1) + if (!qFuzzyIsNull(fontDef.pixelSize)) FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); FcResult result; @@ -973,9 +1001,68 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); - FcPattern *match = FcFontMatch(nullptr, pattern, &result); +#ifdef FC_VARIABLE + if (!fid.filename.isEmpty()) { + // FC_INDEX is ignored during processing in FcFontMatch. + // So iterate FcPatterns directly and find it out. + FcFontSet *fcsets[2], *fcfs; + + fcsets[0] = FcConfigGetFonts(nullptr, FcSetSystem); + fcsets[1] = FcConfigGetFonts(nullptr, FcSetApplication); + for (int nset = 0; nset < 2; nset++) { + fcfs = fcsets[nset]; + if (fcfs == nullptr) + continue; + for (int fnum = 0; fnum < fcfs->nfont; fnum++) { + FcPattern *fcpat = fcfs->fonts[fnum]; + FcChar8 *fcfile; + FcBool variable; + double fcpixelsize; + int fcindex; + + // Skip the variable font itself, only to use the named instances and normal fonts here + if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch && + variable == FcTrue) + continue; + + if (!qFuzzyIsNull(fontDef.pixelSize)) { + if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch && + fontDef.pixelSize != fcpixelsize) + continue; + } + + if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch && + FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) { + QByteArray f = QByteArray::fromRawData((const char *)fcfile, + qstrlen((const char *)fcfile)); + if (f == fid.filename && fcindex == fid.index) { + // We found it. + match = FcFontRenderPrepare(nullptr, pattern, fcpat); + goto bail; + } + } + } + } + } +bail: +#endif + + if (!match) + match = FcFontMatch(nullptr, pattern, &result); + + int xftAntialias = 0; + if (!forcedAntialiasSetting) { + void *antialiasResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", + QGuiApplication::primaryScreen()); + xftAntialias = int(reinterpret_cast<qintptr>(antialiasResource)); + if ((preferXftConf || !match) && xftAntialias > 0) { + antialias = xftAntialias - 1; + forcedAntialiasSetting = true; + } + } if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); + engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf)); FcBool fc_autohint; if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) @@ -996,18 +1083,37 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef if (antialias) { QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) - subpixelType = subpixelTypeFromMatch(match, useXftConf); + subpixelType = subpixelTypeFromMatch(match, preferXftConf); engine->subpixelType = subpixelType; - - format = (subpixelType == QFontEngine::Subpixel_None) - ? QFontEngine::Format_A8 - : QFontEngine::Format_A32; - } else - format = QFontEngine::Format_Mono; + } FcPatternDestroy(match); - } else - format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono; + } else { + void *hintStyleResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", + QGuiApplication::primaryScreen()); + int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource)); + if (xftHintStyle > 0) + engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1)); + if (antialias) { + engine->subpixelType = QFontEngine::Subpixel_None; + if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { + void *subpixelTypeResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype", + QGuiApplication::primaryScreen()); + int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource)); + if (xftSubpixelType > 1) + engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1); + } + } + } + if (antialias) { + format = (engine->subpixelType == QFontEngine::Subpixel_None) + ? QFontEngine::Format_A8 + : QFontEngine::Format_A32; + } else { + format = QFontEngine::Format_Mono; + } FcPatternDestroy(pattern); @@ -1016,4 +1122,13 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef engine->glyphFormat = format; } +bool QFontconfigDatabase::supportsVariableApplicationFonts() const +{ +#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900 + return true; +#else + return false; +#endif +} + QT_END_NAMESPACE |