From 6c4a8de3b2904a4ecf713c114604f29beadd1757 Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Tue, 15 Aug 2023 15:26:52 +0800 Subject: [PATCH] Support the named instance of Variable Fonts In the fontconfig, the fonts will be populated with the variable font and the named instance from the variable font. In this patch, it will skip the variable font, and populate the named instances from the variable font. The FcFontMatch function ignores the FC_INDEX when match the font, changed the code to match the FC_INDEX by iterate the font list. Also use the embolden value from fontconfig if fontconfig is available. [ChangeLog][Fonts] Added support for the named instances from the variable fonts. Fixes: QTBUG-111994 Fixes: QTBUG-112136 Co-authored-by: Peng Wu Change-Id: Ic598d69a1e76109958fafa1226ea927656092319 --- src/gui/text/freetype/qfontengine_ft.cpp | 4 +- src/gui/text/freetype/qfontengine_ft_p.h | 1 + src/gui/text/unix/qfontconfigdatabase.cpp | 55 ++++++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/gui/text/freetype/qfontengine_ft.cpp b/src/gui/text/freetype/qfontengine_ft.cpp index b7eb9f412b..55a3652189 100644 --- a/src/gui/text/freetype/qfontengine_ft.cpp +++ b/src/gui/text/freetype/qfontengine_ft.cpp @@ -729,6 +729,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) cache_cost = 100 * 1024; kerning_pairs_loaded = false; transform = false; + auto_embolden = false; embolden = false; obliquen = false; antialias = true; @@ -835,7 +836,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, FT_Set_Transform(face, &matrix, nullptr); freetype->matrix = matrix; // fake bold - if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD")) { + if (!auto_embolden && (fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD")) { FT_UShort actualWeight = calculateActualWeight(face, faceId); if (actualWeight < 700 && (fontDef.pixelSize < 64 || qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD_LIMIT"))) { @@ -2214,6 +2215,7 @@ bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe) default_hint_style = fe->default_hint_style; antialias = fe->antialias; transform = fe->transform; + auto_embolden = fe->auto_embolden; embolden = fe->embolden; obliquen = fe->obliquen; subpixelType = fe->subpixelType; diff --git a/src/gui/text/freetype/qfontengine_ft_p.h b/src/gui/text/freetype/qfontengine_ft_p.h index 85f1d87a3c..b1e3afe555 100644 --- a/src/gui/text/freetype/qfontengine_ft_p.h +++ b/src/gui/text/freetype/qfontengine_ft_p.h @@ -277,6 +277,7 @@ protected: HintStyle default_hint_style; bool antialias; bool transform; + bool auto_embolden; // a flag to decide if embolden is set by fontconfig bool embolden; bool obliquen; SubpixelAntialiasingType subpixelType; diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp index 4a402cd764..c8f2936c9e 100644 --- a/src/gui/text/unix/qfontconfigdatabase.cpp +++ b/src/gui/text/unix/qfontconfigdatabase.cpp @@ -575,6 +575,8 @@ void QFontconfigDatabase::populateFontDatabase() FcObjectSetAdd(os, *p); ++p; } + /* Support the named instance of Variable Fonts. */ + FcPatternAddBool(pattern, FC_VARIABLE, FcFalse); fonts = FcFontList(nullptr, pattern, os); FcObjectSetDestroy(os); FcPatternDestroy(pattern); @@ -973,6 +975,7 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef QFontEngine::GlyphFormat format; // try and get the pattern FcPattern *pattern = FcPatternCreate(); + FcPattern *match = NULL; FcValue value; value.type = FcTypeString; @@ -999,7 +1002,52 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); - FcPattern *match = FcFontMatch(nullptr, pattern, &result); + 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 (fontDef.pixelSize > 0.1 ) { + 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: + if (!match) + match = FcFontMatch(nullptr, pattern, &result); + if (match) { engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); @@ -1019,6 +1067,11 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef antialias = fc_antialias; } + FcBool embolden; + engine->auto_embolden = true; + if (FcPatternGetBool(match, FC_EMBOLDEN, 0, &embolden) == FcResultMatch) + engine->embolden = embolden; + if (antialias) { QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) -- 2.41.0