QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const { QStringList fallbackFamilies; FcPattern *pattern = FcPatternCreate(); if (!pattern) return fallbackFamilies; FcValue value; value.type = FcTypeString; QByteArray cs = family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern,FC_FAMILY,value,true); int slant_value = FC_SLANT_ROMAN; if (style == QFont::StyleItalic) slant_value = FC_SLANT_ITALIC; else if (style == QFont::StyleOblique) slant_value = FC_SLANT_OBLIQUE; FcPatternAddInteger(pattern, FC_SLANT, slant_value); if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { Q_ASSERT(script < QUnicodeTables::ScriptCount); FcLangSet *ls = FcLangSetCreate(); FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); FcPatternAddLangSet(pattern, FC_LANG, ls); FcLangSetDestroy(ls); } const char *stylehint = getFcFamilyForStyleHint(styleHint); if (stylehint) { value.u.s = (const FcChar8 *)stylehint; FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); } FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result = FcResultMatch; FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); FcPatternDestroy(pattern); if (fontSet) { for (int i = 0; i < fontSet->nfont; i++) { FcChar8 *value = 0; if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); QString familyName = QString::fromUtf8((const char *)value); if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive)) { fallbackFamilies << familyName; } } FcFontSetDestroy(fontSet); } // qDebug() << "fallbackFamilies for:" << family << fallbackFamilies; return fallbackFamilies; }
CAMLprim value pattern_add(value pat, value prop, value append) { CAMLparam0(); FcPatternAdd(FcPattern_val(pat), String_val(Field(prop, 0)), fcvalue_from_caml(Field(prop, 1)), Bool_val(append) ? FcTrue : FcFalse); CAMLreturn(Val_unit); }
static void claro_ft2_set_family(claro_font_pattern_t * pattern, const char * family) { FcPattern * fc_pattern; FcValue val; val.u.s = family; val.type = FcTypeString; g_return_if_fail(pattern != NULL); fc_pattern = (FcPattern *)pattern->native; g_assert(FcPatternAdd(fc_pattern, FC_FAMILY, val, TRUE)); }
// coverity[+alloc : arg-*0] GpStatus GdipNewInstalledFontCollection (GpFontCollection **font_collection) { if (!font_collection) return InvalidParameter; /* * Ensure we leak this data only a single time, because: * (a) there is no API to free it; * (b) other libgdiplus structures depends on that allocated data; */ if (!system_fonts) { FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_FOUNDRY, NULL); FcPattern *pat = FcPatternCreate (); FcValue val; FcFontSet *col; /* Only Scalable fonts for now */ val.type = FcTypeBool; val.u.b = FcTrue; FcPatternAdd (pat, FC_SCALABLE, val, TRUE); FcObjectSetAdd (os, FC_SCALABLE); col = FcFontList (0, pat, os); FcPatternDestroy (pat); FcObjectSetDestroy (os); system_fonts = (GpFontCollection *) GdipAlloc (sizeof (GpFontCollection)); if (system_fonts) { system_fonts->fontset = col; system_fonts->config = NULL; } } *font_collection = system_fonts; return Ok; }
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { FcCharSet* cset = FcCharSetCreate(); for (int i = 0; i < length; ++i) FcCharSetAddChar(cset, characters[i]); FcPattern* pattern = FcPatternCreate(); FcValue fcvalue; fcvalue.type = FcTypeCharSet; fcvalue.u.c = cset; FcPatternAdd(pattern, FC_CHARSET, fcvalue, 0); FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; FcPattern* match = FcFontMatch(0, pattern, &result); FcPatternDestroy(pattern); SimpleFontData* ret = 0; if (match) { FcChar8* family; if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) { AtomicString fontFamily(reinterpret_cast<char*>(family)); ret = getCachedFontData(getCachedFontPlatformData(font.fontDescription(), fontFamily, false)); } FcPatternDestroy(match); } FcCharSetDestroy(cset); return ret; }
FcPattern * FcNameParse (const FcChar8 *name) { FcChar8 *save; FcPattern *pat; double d; FcChar8 *e; FcChar8 delim; FcValue v; FcMatrix m; const FcObjectType *t; const FcConstant *c; /* freed below */ save = malloc (strlen ((char *) name) + 1); if (!save) goto bail0; pat = FcPatternCreate (); if (!pat) goto bail1; for (;;) { name = FcNameFindNext (name, "-,:", save, &delim); if (save[0]) { if (!FcPatternAddString (pat, FC_FAMILY, save)) goto bail2; } if (delim != ',') break; } if (delim == '-') { for (;;) { name = FcNameFindNext (name, "-,:", save, &delim); d = strtod ((char *) save, (char **) &e); if (e != save) { if (!FcPatternAddDouble (pat, FC_SIZE, d)) goto bail2; } if (delim != ',') break; } } while (delim == ':') { name = FcNameFindNext (name, "=_:", save, &delim); if (save[0]) { if (delim == '=' || delim == '_') { t = FcNameGetObjectType ((char *) save); for (;;) { name = FcNameFindNext (name, ":,", save, &delim); if (t) { v = FcNameConvert (t->type, save, &m); if (!FcPatternAdd (pat, t->object, v, FcTrue)) { switch (v.type) { case FcTypeCharSet: FcCharSetDestroy ((FcCharSet *) v.u.c); break; case FcTypeLangSet: FcLangSetDestroy ((FcLangSet *) v.u.l); break; default: break; } goto bail2; } switch (v.type) { case FcTypeCharSet: FcCharSetDestroy ((FcCharSet *) v.u.c); break; case FcTypeLangSet: FcLangSetDestroy ((FcLangSet *) v.u.l); break; default: break; } } if (delim != ',') break; } } else { if ((c = FcNameGetConstant (save))) { if (!FcPatternAddInteger (pat, c->object, c->value)) goto bail2; } } } } free (save); return pat; bail2: FcPatternDestroy (pat); bail1: free (save); bail0: return 0; }
static FcBool FcListAppend (FcListHashTable *table, FcPattern *font, FcObjectSet *os, const FcChar8 *lang) { int o; FcPatternElt *e; FcValueListPtr v; FcChar32 hash; FcListBucket **prev, *bucket; int familyidx = -1; int fullnameidx = -1; int styleidx = -1; int defidx = 0; int idx; hash = FcListPatternHash (font, os); for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE]; (bucket = *prev); prev = &(bucket->next)) { if (bucket->hash == hash && FcListPatternEqual (bucket->pattern, font, os)) return FcTrue; } bucket = (FcListBucket *) malloc (sizeof (FcListBucket)); if (!bucket) goto bail0; FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket)); bucket->next = 0; bucket->hash = hash; bucket->pattern = FcPatternCreate (); if (!bucket->pattern) goto bail1; for (o = 0; o < os->nobject; o++) { if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG)) { if (familyidx < 0) familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang); defidx = familyidx; } else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG)) { if (fullnameidx < 0) fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang); defidx = fullnameidx; } else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG)) { if (styleidx < 0) styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang); defidx = styleidx; } else defidx = 0; e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o])); if (e) { for (v = FcPatternEltValues(e), idx = 0; v; v = FcValueListNext(v), ++idx) { if (!FcPatternAdd (bucket->pattern, os->objects[o], FcValueCanonicalize(&v->value), defidx != idx)) goto bail2; } } } *prev = bucket; ++table->entries; return FcTrue; bail2: FcPatternDestroy (bucket->pattern); bail1: FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket)); free (bucket); bail0: return FcFalse; }
void WebFontInfo::renderStyleForStrike(const char* family, int sizeAndStyle, WebFontRenderStyle* out) { bool isBold = sizeAndStyle & 1; bool isItalic = sizeAndStyle & 2; int pixelSize = sizeAndStyle >> 2; FcPattern* pattern = FcPatternCreate(); FcValue fcvalue; fcvalue.type = FcTypeString; fcvalue.u.s = reinterpret_cast<const FcChar8 *>(family); FcPatternAdd(pattern, FC_FAMILY, fcvalue, FcFalse); fcvalue.type = FcTypeInteger; fcvalue.u.i = isBold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL; FcPatternAdd(pattern, FC_WEIGHT, fcvalue, FcFalse); fcvalue.type = FcTypeInteger; fcvalue.u.i = isItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN; FcPatternAdd(pattern, FC_SLANT, fcvalue, FcFalse); fcvalue.type = FcTypeBool; fcvalue.u.b = FcTrue; FcPatternAdd(pattern, FC_SCALABLE, fcvalue, FcFalse); fcvalue.type = FcTypeDouble; fcvalue.u.d = pixelSize; FcPatternAdd(pattern, FC_SIZE, fcvalue, FcFalse); FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; // Some versions of fontconfig don't actually write a value into result. // However, it's not clear from the documentation if result should be a // non-0 pointer: future versions might expect to be able to write to // it. So we pass in a valid pointer and ignore it. FcPattern* match = FcFontMatch(0, pattern, &result); FcPatternDestroy(pattern); out->setDefaults(); if (!match) return; FcBool b; int i; if (FcPatternGetBool(match, FC_ANTIALIAS, 0, &b) == FcResultMatch) out->useAntiAlias = b; if (FcPatternGetBool(match, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch) out->useBitmaps = b; if (FcPatternGetBool(match, FC_AUTOHINT, 0, &b) == FcResultMatch) out->useAutoHint = b; if (FcPatternGetBool(match, FC_HINTING, 0, &b) == FcResultMatch) out->useHinting = b; if (FcPatternGetInteger(match, FC_HINT_STYLE, 0, &i) == FcResultMatch) out->hintStyle = i; if (FcPatternGetInteger(match, FC_RGBA, 0, &i) == FcResultMatch) { switch (i) { case FC_RGBA_NONE: out->useSubpixel = 0; break; case FC_RGBA_RGB: case FC_RGBA_BGR: case FC_RGBA_VRGB: case FC_RGBA_VBGR: out->useSubpixel = 1; break; default: // This includes FC_RGBA_UNKNOWN. out->useSubpixel = 2; break; } } FcPatternDestroy(match); }
QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const { QStringList fallbackFamilies; FcPattern *pattern = FcPatternCreate(); if (!pattern) return fallbackFamilies; FcValue value; value.type = FcTypeString; QByteArray cs = family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern,FC_FAMILY,value,true); int slant_value = FC_SLANT_ROMAN; if (style == QFont::StyleItalic) slant_value = FC_SLANT_ITALIC; else if (style == QFont::StyleOblique) slant_value = FC_SLANT_OBLIQUE; FcPatternAddInteger(pattern, FC_SLANT, slant_value); Q_ASSERT(uint(script) < QChar::ScriptCount); if (*specialLanguages[script] != '\0') { FcLangSet *ls = FcLangSetCreate(); FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); FcPatternAddLangSet(pattern, FC_LANG, ls); FcLangSetDestroy(ls); } else if (!family.isEmpty()) { // If script is Common or Han, then it may include languages like CJK, // we should attach system default language set to the pattern // to obtain correct font fallback list (i.e. if LANG=zh_CN // then we normally want to use a Chinese font for CJK text; // while a Japanese font should be used for that if LANG=ja) FcPattern *dummy = FcPatternCreate(); FcDefaultSubstitute(dummy); FcChar8 *lang = 0; FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); if (res == FcResultMatch) FcPatternAddString(pattern, FC_LANG, lang); FcPatternDestroy(dummy); } const char *stylehint = getFcFamilyForStyleHint(styleHint); if (stylehint) { value.u.s = (const FcChar8 *)stylehint; FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); } FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result = FcResultMatch; FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); FcPatternDestroy(pattern); if (fontSet) { for (int i = 0; i < fontSet->nfont; i++) { FcChar8 *value = 0; if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); QString familyName = QString::fromUtf8((const char *)value); if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) && familyName.compare(family, Qt::CaseInsensitive)) { fallbackFamilies << familyName; } } FcFontSetDestroy(fontSet); } // qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies; return fallbackFamilies; }
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr) { if (!usrPtr) return 0; QFontDef fontDef = f; QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); engine = new QFontEngineFT(fontDef); QFontEngineFT::GlyphFormat format; // try and get the pattern FcPattern *pattern = FcPatternCreate(); FcValue value; value.type = FcTypeString; QByteArray cs = fontDef.family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern,FC_FAMILY,value,true); value.u.s = (const FcChar8 *)fid.filename.data(); FcPatternAdd(pattern,FC_FILE,value,true); value.type = FcTypeInteger; value.u.i = fid.index; FcPatternAdd(pattern,FC_INDEX,value,true); FcResult result; FcPattern *match = FcFontMatch(0, pattern, &result); if (match) { QFontEngineFT::HintStyle default_hint_style; if (f.hintingPreference != QFont::PreferDefaultHinting) { switch (f.hintingPreference) { case QFont::PreferNoHinting: default_hint_style = QFontEngineFT::HintNone; break; case QFont::PreferVerticalHinting: default_hint_style = QFontEngineFT::HintLight; break; case QFont::PreferFullHinting: default: default_hint_style = QFontEngineFT::HintFull; break; } } else { int hint_style = 0; if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) hint_style = QFontEngineFT::HintFull; switch (hint_style) { case FC_HINT_NONE: default_hint_style = QFontEngineFT::HintNone; break; case FC_HINT_SLIGHT: default_hint_style = QFontEngineFT::HintLight; break; case FC_HINT_MEDIUM: default_hint_style = QFontEngineFT::HintMedium; break; default: default_hint_style = QFontEngineFT::HintFull; break; } } if (antialias) { // If antialiasing is not fully disabled, fontconfig may still disable it on a font match basis. FcBool fc_antialias; if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) != FcResultMatch) fc_antialias = true; antialias = fc_antialias; } if (f.hintingPreference == QFont::PreferDefaultHinting) { const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); if (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")) { void *hintStyleResource = QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle", QGuiApplication::primaryScreen()); int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource)); if (hintStyle > 0) default_hint_style = QFontEngine::HintStyle(hintStyle - 1); } } engine->setDefaultHintStyle(default_hint_style); if (antialias) { QFontEngineFT::SubpixelAntialiasingType subpixelType = QFontEngineFT::Subpixel_None; int subpixel = FC_RGBA_NONE; FcPatternGetInteger(match, FC_RGBA, 0, &subpixel); if (subpixel == FC_RGBA_UNKNOWN) subpixel = FC_RGBA_NONE; switch (subpixel) { case FC_RGBA_NONE: subpixelType = QFontEngineFT::Subpixel_None; break; case FC_RGBA_RGB: subpixelType = QFontEngineFT::Subpixel_RGB; break; case FC_RGBA_BGR: subpixelType = QFontEngineFT::Subpixel_BGR; break; case FC_RGBA_VRGB: subpixelType = QFontEngineFT::Subpixel_VRGB; break; case FC_RGBA_VBGR: subpixelType = QFontEngineFT::Subpixel_VBGR; break; default: break; } format = subpixelType == QFontEngineFT::Subpixel_None ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32; engine->subpixelType = subpixelType; } else format = QFontEngineFT::Format_Mono; FcPatternDestroy(match); } else format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; FcPatternDestroy(pattern); if (!engine->init(fid,antialias,format)) { delete engine; engine = 0; return engine; } if (engine->invalid()) { delete engine; engine = 0; } else if (!engine->supportsScript(script)) { qWarning(" OpenType support missing for script %d", int(script)); delete engine; engine = 0; } return engine; }
vlc_family_t *FontConfig_GetFallbacks( filter_t *p_filter, const char *psz_family, uni_char_t codepoint ) { VLC_UNUSED( codepoint ); vlc_family_t *p_family = NULL; filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; p_family = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc ); if( p_family != kVLCDictionaryNotFound ) { free( psz_lc ); return p_family; } else p_family = NULL; const char *psz_last_name = ""; FcPattern *p_pattern = FcPatternCreate(); FcValue family; family.type = FcTypeString; family.u.s = ( const FcChar8* ) psz_family; FcPatternAdd( p_pattern, FC_FAMILY, family, FcFalse ); if( FcConfigSubstitute( NULL, p_pattern, FcMatchPattern ) == FcTrue ) { FcDefaultSubstitute( p_pattern ); FcResult result; FcFontSet* p_font_set = FcFontSort( NULL, p_pattern, FcTrue, NULL, &result ); if( p_font_set ) { for( int i = 0; i < p_font_set->nfont; ++i ) { char* psz_name = NULL; FcPatternGetString( p_font_set->fonts[i], FC_FAMILY, 0, ( FcChar8** )( &psz_name ) ); /* Avoid duplicate family names */ if( strcasecmp( psz_last_name, psz_name ) ) { vlc_family_t *p_temp = NewFamily( p_filter, psz_name, &p_family, NULL, NULL ); if( unlikely( !p_temp ) ) { FcFontSetDestroy( p_font_set ); FcPatternDestroy( p_pattern ); if( p_family ) FreeFamilies( p_family, NULL ); free( psz_lc ); return NULL; } psz_last_name = p_temp->psz_name; } } FcFontSetDestroy( p_font_set ); } } FcPatternDestroy( p_pattern ); if( p_family ) vlc_dictionary_insert( &p_sys->fallback_map, psz_lc, p_family ); free( psz_lc ); return p_family; }
Bool XftPatternAdd (XftPattern *p, const char *object, XftValue value, Bool append) { return FcPatternAdd (p, object, value, append); }
void WebFontInfo::fallbackFontForChar(WebUChar32 c, const char* preferredLocale, WebFallbackFont* fallbackFont) { FcCharSet* cset = FcCharSetCreate(); FcCharSetAddChar(cset, c); FcPattern* pattern = FcPatternCreate(); FcValue fcvalue; fcvalue.type = FcTypeCharSet; fcvalue.u.c = cset; FcPatternAdd(pattern, FC_CHARSET, fcvalue, FcFalse); fcvalue.type = FcTypeBool; fcvalue.u.b = FcTrue; FcPatternAdd(pattern, FC_SCALABLE, fcvalue, FcFalse); if (preferredLocale) { FcLangSet* langset = FcLangSetCreate(); FcLangSetAdd(langset, reinterpret_cast<const FcChar8 *>(preferredLocale)); FcPatternAddLangSet(pattern, FC_LANG, langset); FcLangSetDestroy(langset); } FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; FcFontSet* fontSet = FcFontSort(0, pattern, 0, 0, &result); FcPatternDestroy(pattern); FcCharSetDestroy(cset); if (!fontSet) { fallbackFont->name = WebCString(); fallbackFont->isBold = false; fallbackFont->isItalic = false; return; } // Older versions of fontconfig have a bug where they cannot select // only scalable fonts so we have to manually filter the results. for (int i = 0; i < fontSet->nfont; ++i) { FcPattern* current = fontSet->fonts[i]; FcBool isScalable; if (FcPatternGetBool(current, FC_SCALABLE, 0, &isScalable) != FcResultMatch || !isScalable) continue; // fontconfig can also return fonts which are unreadable FcChar8* cFilename; if (FcPatternGetString(current, FC_FILE, 0, &cFilename) != FcResultMatch) continue; if (access(reinterpret_cast<char*>(cFilename), R_OK)) continue; const char* fontFilename = reinterpret_cast<char*>(cFilename); fallbackFont->filename = WebCString(fontFilename, strlen(fontFilename)); // Index into font collection. int ttcIndex; if (FcPatternGetInteger(current, FC_INDEX, 0, &ttcIndex) != FcResultMatch && ttcIndex < 0) continue; fallbackFont->ttcIndex = ttcIndex; FcChar8* familyName; if (FcPatternGetString(current, FC_FAMILY, 0, &familyName) == FcResultMatch) { const char* charFamily = reinterpret_cast<char*>(familyName); fallbackFont->name = WebCString(charFamily, strlen(charFamily)); } int weight; if (FcPatternGetInteger(current, FC_WEIGHT, 0, &weight) == FcResultMatch) fallbackFont->isBold = weight >= FC_WEIGHT_BOLD; else fallbackFont->isBold = false; int slant; if (FcPatternGetInteger(current, FC_SLANT, 0, &slant) == FcResultMatch) fallbackFont->isItalic = slant != FC_SLANT_ROMAN; else fallbackFont->isItalic = false; FcFontSetDestroy(fontSet); return; } FcFontSetDestroy(fontSet); }
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) { if (!usrPtr) return 0; QFontDef fontDef = f; QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = fontfile->fileName.toLocal8Bit(); fid.index = fontfile->indexValue; bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); engine = new QFontEngineFT(fontDef); QFontEngineFT::GlyphFormat format; // try and get the pattern FcPattern *pattern = FcPatternCreate(); FcValue value; value.type = FcTypeString; QByteArray cs = fontDef.family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern,FC_FAMILY,value,true); value.u.s = (const FcChar8 *)fid.filename.data(); FcPatternAdd(pattern,FC_FILE,value,true); value.type = FcTypeInteger; value.u.i = fid.index; FcPatternAdd(pattern,FC_INDEX,value,true); FcResult result; FcPattern *match = FcFontMatch(0, pattern, &result); if (match) { QFontEngineFT::HintStyle default_hint_style; if (f.hintingPreference != QFont::PreferDefaultHinting) { switch (f.hintingPreference) { case QFont::PreferNoHinting: default_hint_style = QFontEngineFT::HintNone; break; case QFont::PreferVerticalHinting: default_hint_style = QFontEngineFT::HintLight; break; case QFont::PreferFullHinting: default: default_hint_style = QFontEngineFT::HintFull; break; } } else { int hint_style = 0; if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) hint_style = QFontEngineFT::HintFull; switch (hint_style) { case FC_HINT_NONE: default_hint_style = QFontEngineFT::HintNone; break; case FC_HINT_SLIGHT: default_hint_style = QFontEngineFT::HintLight; break; case FC_HINT_MEDIUM: default_hint_style = QFontEngineFT::HintMedium; break; default: default_hint_style = QFontEngineFT::HintFull; break; } } engine->setDefaultHintStyle(default_hint_style); if (antialias) { QFontEngineFT::SubpixelAntialiasingType subpixelType = QFontEngineFT::Subpixel_None; int subpixel = FC_RGBA_NONE; FcPatternGetInteger(match, FC_RGBA, 0, &subpixel); if (subpixel == FC_RGBA_UNKNOWN) subpixel = FC_RGBA_NONE; switch (subpixel) { case FC_RGBA_NONE: subpixelType = QFontEngineFT::Subpixel_None; break; case FC_RGBA_RGB: subpixelType = QFontEngineFT::Subpixel_RGB; break; case FC_RGBA_BGR: subpixelType = QFontEngineFT::Subpixel_BGR; break; case FC_RGBA_VRGB: subpixelType = QFontEngineFT::Subpixel_VRGB; break; case FC_RGBA_VBGR: subpixelType = QFontEngineFT::Subpixel_VBGR; break; default: break; } format = subpixelType == QFontEngineFT::Subpixel_None ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32; engine->subpixelType = subpixelType; } else format = QFontEngineFT::Format_Mono; FcPatternDestroy(match); } else format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; FcPatternDestroy(pattern); if (!engine->init(fid,antialias,format)) { delete engine; engine = 0; return engine; } if (engine->invalid()) { delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { HB_Face hbFace = engine->initializedHarfbuzzFace(); if (!hbFace || !hbFace->supported_scripts[script]) { delete engine; engine = 0; } } return engine; }
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, const char *str) { if (!FcInit()) return false; bool ret = false; /* Fontconfig doesn't handle full language isocodes, only the part * before the _ of e.g. en_GB is used, so "remove" everything after * the _. */ char lang[16]; strecpy(lang, language_isocode, lastof(lang)); char *split = strchr(lang, '_'); if (split != NULL) *split = '\0'; FcPattern *pat; FcPattern *match; FcResult result; FcChar8 *file; FcFontSet *fs; FcValue val; val.type = FcTypeString; val.u.s = (FcChar8*)lang; /* First create a pattern to match the wanted language */ pat = FcPatternCreate(); /* And fill it with the language and other defaults */ if (pat == NULL || !FcPatternAdd(pat, "lang", val, false) || !FcConfigSubstitute(0, pat, FcMatchPattern)) { goto error_pattern; } FcDefaultSubstitute(pat); /* Then create a font set and match that */ match = FcFontMatch(0, pat, &result); if (match == NULL) { goto error_pattern; } /* Find all fonts that do match */ fs = FcFontSetCreate(); FcFontSetAdd(fs, match); /* And take the first, if it exists */ if (fs->nfont <= 0 || FcPatternGetString(fs->fonts[0], FC_FILE, 0, &file)) { goto error_fontset; } strecpy(settings->small_font, (const char*)file, lastof(settings->small_font)); strecpy(settings->medium_font, (const char*)file, lastof(settings->medium_font)); strecpy(settings->large_font, (const char*)file, lastof(settings->large_font)); ret = true; error_fontset: FcFontSetDestroy(fs); error_pattern: if (pat != NULL) FcPatternDestroy(pat); FcFini(); return ret; }
QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) { if (!usrPtr) return 0; QFontDef fontDef = f; QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = fontfile->fileName.toLocal8Bit(); fid.index = fontfile->indexValue; //try and get the pattern FcPattern *pattern = FcPatternCreate(); bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; engine = new QFontEngineFT(fontDef); FcValue value; value.type = FcTypeString; QByteArray cs = fontDef.family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern,FC_FAMILY,value,true); value.u.s = (const FcChar8 *)fid.filename.data(); FcPatternAdd(pattern,FC_FILE,value,true); value.type = FcTypeInteger; value.u.i = fid.index; FcPatternAdd(pattern,FC_INDEX,value,true); QFontEngineFT::HintStyle default_hint_style; if (FcConfigSubstitute(0,pattern,FcMatchPattern)) { //hinting int hint_style = 0; if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) hint_style = QFontEngineFT::HintFull; switch (hint_style) { case FC_HINT_NONE: default_hint_style = QFontEngineFT::HintNone; break; case FC_HINT_SLIGHT: default_hint_style = QFontEngineFT::HintLight; break; case FC_HINT_MEDIUM: default_hint_style = QFontEngineFT::HintMedium; break; default: default_hint_style = QFontEngineFT::HintFull; break; } } engine->setDefaultHintStyle(default_hint_style); if (!engine->init(fid,antialias,format)) { delete engine; engine = 0; return engine; } if (engine->invalid()) { delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { HB_Face hbFace = engine->harfbuzzFace(); if (!hbFace || !hbFace->supported_scripts[script]) { delete engine; engine = 0; } } return engine; }
Common::SeekableReadStream *FontconfigFontProvider::createReadStreamForFont(const Common::String &name, uint32 style) { if (!_config) return 0; Common::String styleName = makeStyleString(style); FcPattern *pattern = FcPatternCreate(); // Match on the family name FcValue value; value.type = FcTypeString; value.u.s = reinterpret_cast<const FcChar8 *>(name.c_str()); if (!FcPatternAdd(pattern, FC_FAMILY, value, FcFalse)) { FcPatternDestroy(pattern); return 0; } // Match on the style string value.u.s = reinterpret_cast<const FcChar8 *>(styleName.c_str()); if (!FcPatternAdd(pattern, FC_STYLE, value, FcFalse)) { FcPatternDestroy(pattern); return 0; } // Only allow TrueType fonts // Might change in the future. value.u.s = reinterpret_cast<const FcChar8 *>("TrueType"); if (!FcPatternAdd(pattern, FC_FONTFORMAT, value, FcFalse)) { FcPatternDestroy(pattern); return 0; } // Call these functions // Might be doing pattern matching. Documentation is awful. FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); // Fetch the match FcResult result; FcFontSet* fontSet = FcFontSort(0, pattern, 0, 0, &result); FcPatternDestroy(pattern); if (!fontSet) return 0; for (int i = 0; i < fontSet->nfont; i++) { FcPattern *foundPattern = fontSet->fonts[i]; // Get the family name of the font FcChar8 *familyName; if (FcPatternGetString(foundPattern, FC_FAMILY, 0, &familyName) != FcResultMatch) continue; // If we don't actually match, bail out. We don't want to end // up with the default fontconfig font, which would look horrible. if (!name.equalsIgnoreCase(reinterpret_cast<const char *>(familyName))) continue; // Get the name of the font FcChar8 *fileName; if (FcPatternGetString(foundPattern, FC_FILE, 0, &fileName) != FcResultMatch) continue; // Let's make sure we can actually get that Common::FSNode fontNode(reinterpret_cast<const char *>(fileName)); if (!fontNode.exists() || !fontNode.isReadable()) continue; debug(1, "Matched %s %s -> '%s'", name.c_str(), styleName.c_str(), fontNode.getPath().c_str()); FcFontSetDestroy(fontSet); return fontNode.createReadStream(); } // We ain't found s#&t FcFontSetDestroy(fontSet); return 0; }
void find_font(font & f, std::string const& name, int height, int weight, int style) { // FIXME: shouldn't require fonts to be empty BOOST_ASSERT(!f); FcValue fcval; // build pattern FcPattern * pattern = FcPatternCreate(); // typeface name fcval.type = FcTypeString; fcval.u.s = (FcChar8 const*) name.c_str(); FcPatternAdd(pattern, FC_FAMILY, fcval, FcTrue); // pixel size fcval.type = FcTypeInteger; fcval.u.i = height; FcPatternAdd(pattern, FC_PIXEL_SIZE, fcval, FcTrue); // italic if (style & font_style::italic) { fcval.type = FcTypeInteger; fcval.u.i = FC_SLANT_ITALIC; FcPatternAdd(pattern, FC_SLANT, fcval, FcTrue); } // weight fcval.type = FcTypeInteger; switch (weight) { case font_weight::thin: fcval.u.i = FC_WEIGHT_THIN; break; case font_weight::extra_light: fcval.u.i = FC_WEIGHT_EXTRALIGHT; break; case font_weight::light: fcval.u.i = FC_WEIGHT_LIGHT; break; case font_weight::normal: fcval.u.i = FC_WEIGHT_NORMAL; break; case font_weight::medium: fcval.u.i = FC_WEIGHT_MEDIUM; break; case font_weight::semi_bold: fcval.u.i = FC_WEIGHT_SEMIBOLD; break; case font_weight::bold: fcval.u.i = FC_WEIGHT_BOLD; break; case font_weight::ultra_bold: fcval.u.i = FC_WEIGHT_ULTRABOLD; break; case font_weight::heavy: fcval.u.i = FC_WEIGHT_HEAVY; break; default: fcval.u.i = FC_WEIGHT_NORMAL; break; }; FcPatternAdd(pattern, FC_WEIGHT, fcval, FcTrue); // transform pattern FcConfigSubstitute(NULL, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult res; FcPattern * real_pattern = FcFontMatch(NULL, pattern, &res); FcPatternDestroy(pattern); // get filename if (real_pattern) { char * fname; int id; FcPatternGetString(real_pattern, FC_FILE, 0, (FcChar8 **) &fname); FcPatternGetInteger(real_pattern, FC_INDEX, 0, &id); // load font FT_Face face; if (FT_New_Face(::ftlib, fname, id, &face)) return; FcPatternDestroy(real_pattern); // create font ft_font_extra * extra = static_cast<ft_font_extra *>(f.extra_data); extra->face = face; FT_Set_Pixel_Sizes(face, 0, height); // get avg char width/height point pt = detail::font_units_to_pixels(face, face->max_advance_width, face->max_advance_height); extra->width = pt.x; extra->height = pt.y; pt = detail::font_units_to_pixels(face, 0, face->ascender); extra->ascender = pt.y; pt = detail::font_units_to_pixels(face, 0, face->descender); extra->descender = pt.y; } }