Support the named instances 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. [ChangeLog][Fonts] Added support for the named instances from the variable fonts. Fixes: QTBUG-111994 Fixes: QTBUG-112136 Co-authored-by: Peng Wu <alexepico@gmail.com> Change-Id: Ic598d69a1e76109958fafa1226ea927656092319 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 185add27b2f7a4aa477e7988260bfaccb930f95c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
3b8de80dfe
commit
1b90474986
@ -278,6 +278,13 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
|
||||
}
|
||||
#endif
|
||||
newFreetype->face = face;
|
||||
newFreetype->mm_var = nullptr;
|
||||
if (FT_IS_NAMED_INSTANCE(newFreetype->face)) {
|
||||
FT_Error ftresult;
|
||||
ftresult = FT_Get_MM_Var(face, &newFreetype->mm_var);
|
||||
if (ftresult != FT_Err_Ok)
|
||||
newFreetype->mm_var = nullptr;
|
||||
}
|
||||
|
||||
newFreetype->ref.storeRelaxed(1);
|
||||
newFreetype->xsize = 0;
|
||||
@ -351,6 +358,9 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
|
||||
void QFreetypeFace::cleanup()
|
||||
{
|
||||
hbFace.reset();
|
||||
if (mm_var && face && face->glyph)
|
||||
FT_Done_MM_Var(face->glyph->library, mm_var);
|
||||
mm_var = nullptr;
|
||||
FT_Done_Face(face);
|
||||
face = nullptr;
|
||||
}
|
||||
@ -818,16 +828,13 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
|
||||
|
||||
static void dont_delete(void*) {}
|
||||
|
||||
static FT_UShort calculateActualWeight(FT_Face face, QFontEngine::FaceId faceId)
|
||||
static FT_UShort calculateActualWeight(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
|
||||
{
|
||||
if (faceId.instanceIndex >= 0) {
|
||||
FT_MM_Var *var = nullptr;
|
||||
FT_Get_MM_Var(face, &var);
|
||||
if (var != nullptr && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
|
||||
for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
|
||||
if (var->axis[axis].tag == QFont::Tag("wght").value()) {
|
||||
return var->namedstyle[faceId.instanceIndex].coords[axis] >> 16;
|
||||
}
|
||||
FT_MM_Var *var = freetypeFace->mm_var;
|
||||
if (var != nullptr && faceId.instanceIndex >= 0 && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
|
||||
for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
|
||||
if (var->axis[axis].tag == QFont::Tag("wght").value()) {
|
||||
return var->namedstyle[faceId.instanceIndex].coords[axis] >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -838,16 +845,13 @@ static FT_UShort calculateActualWeight(FT_Face face, QFontEngine::FaceId faceId)
|
||||
return 700;
|
||||
}
|
||||
|
||||
static bool calculateActualItalic(FT_Face face, QFontEngine::FaceId faceId)
|
||||
static bool calculateActualItalic(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
|
||||
{
|
||||
if (faceId.instanceIndex >= 0) {
|
||||
FT_MM_Var *var = nullptr;
|
||||
FT_Get_MM_Var(face, &var);
|
||||
if (var != nullptr && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
|
||||
for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
|
||||
if (var->axis[axis].tag == QFont::Tag("ital").value()) {
|
||||
return (var->namedstyle[faceId.instanceIndex].coords[axis] >> 16) == 1;
|
||||
}
|
||||
FT_MM_Var *var = freetypeFace->mm_var;
|
||||
if (var != nullptr && faceId.instanceIndex >= 0 && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
|
||||
for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
|
||||
if (var->axis[axis].tag == QFont::Tag("ital").value()) {
|
||||
return (var->namedstyle[faceId.instanceIndex].coords[axis] >> 16) == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -886,7 +890,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
|
||||
FT_Face face = lockFace();
|
||||
|
||||
if (FT_IS_SCALABLE(face)) {
|
||||
bool isItalic = calculateActualItalic(face, faceId);
|
||||
bool isItalic = calculateActualItalic(freetype, face, faceId);
|
||||
bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !isItalic && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_ITALIC");
|
||||
if (fake_oblique)
|
||||
obliquen = true;
|
||||
@ -894,7 +898,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
|
||||
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")) {
|
||||
FT_UShort actualWeight = calculateActualWeight(face, faceId);
|
||||
FT_UShort actualWeight = calculateActualWeight(freetype, face, faceId);
|
||||
if (actualWeight < 700 &&
|
||||
(fontDef.pixelSize < 64 || qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD_LIMIT"))) {
|
||||
embolden = true;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
@ -62,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
FT_MM_Var *mm_var;
|
||||
int xsize; // 26.6
|
||||
int ysize; // 26.6
|
||||
FT_Matrix matrix;
|
||||
|
@ -575,6 +575,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);
|
||||
@ -974,6 +980,7 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
|
||||
QFontEngine::GlyphFormat format;
|
||||
// try and get the pattern
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
FcPattern *match = nullptr;
|
||||
|
||||
FcValue value;
|
||||
value.type = FcTypeString;
|
||||
@ -992,7 +999,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;
|
||||
@ -1000,7 +1007,55 @@ 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);
|
||||
|
||||
if (match) {
|
||||
engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user