void property(string&& property, int* dst) const { FcPatternGetInteger(m_pattern, property.c_str(), 0, dst); }
static void populateFromPattern(FcPattern *pattern) { QString familyName; FcChar8 *value = 0; int weight_value; int slant_value; int spacing_value; int width_value; FcChar8 *file_value; int indexValue; FcChar8 *foundry_value; FcChar8 *style_value; FcBool scalable; FcBool antialias; if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch) return; familyName = QString::fromUtf8((const char *)value); if (familyName == QLatin1String("Open Sans")) { FcChar8 *styl = 0; if (FcPatternGetString(pattern, FC_STYLE, 0, &styl) == FcResultMatch) { QString style = QString::fromUtf8(reinterpret_cast<const char *>(styl)); if (style == QLatin1String("Semibold")) { familyName.append(QChar(QChar::Space)).append(style); } } } slant_value = FC_SLANT_ROMAN; weight_value = FC_WEIGHT_REGULAR; spacing_value = FC_PROPORTIONAL; file_value = 0; indexValue = 0; scalable = FcTrue; if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch) slant_value = FC_SLANT_ROMAN; if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch) weight_value = FC_WEIGHT_REGULAR; if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch) width_value = FC_WIDTH_NORMAL; if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) spacing_value = FC_PROPORTIONAL; if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) file_value = 0; if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) indexValue = 0; if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) scalable = FcTrue; if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) foundry_value = 0; if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) style_value = 0; if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) antialias = true; QSupportedWritingSystems writingSystems; FcLangSet *langset = 0; FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); if (res == FcResultMatch) { bool hasLang = false; for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; if (lang) { FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) { writingSystems.setSupported(QFontDatabase::WritingSystem(j)); hasLang = true; } } } if (!hasLang) // none of our known languages, add it to the other set writingSystems.setSupported(QFontDatabase::Other); } else { // we set Other to supported for symbol fonts. It makes no // sense to merge these with other ones, as they are // special in a way. writingSystems.setSupported(QFontDatabase::Other); } #if FC_VERSION >= 20297 for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { if (writingSystems.supported(QFontDatabase::WritingSystem(j)) && requiresOpenType(j) && openType[j]) { FcChar8 *cap; res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap); if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); } } #endif FontFile *fontFile = new FontFile; fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); fontFile->indexValue = indexValue; QFont::Style style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) ? QFont::StyleOblique : QFont::StyleNormal); // Note: weight should really be an int but registerFont incorrectly uses an enum QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); double pixel_size = 0; if (!scalable) FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); bool fixedPitch = spacing_value >= FC_MONO; // Note: stretch should really be an int but registerFont incorrectly uses an enum QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); // 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) QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); }
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; } }
int PsychRebuildFont(void) { // Destroy old font object, if any: if (faceT || faceM) { // Delete OGLFT face object: if (faceT) delete(faceT); faceT = NULL; if (faceM) delete(faceM); faceM = NULL; if (_verbosity > 3) fprintf(stderr, "libptbdrawtext_ftgl: Destroying old font face...\n"); // Delete underlying FreeType representation: FT_Done_Face(ft_face); ft_face = NULL; } if (_useOwnFontmapper) { FcResult result; FcPattern* target = NULL; if (_fontName[0] == '-') { // _fontName starts with a '-' dash: This is not a simple font family string but a special // fontspec string in FontConfig's special format. It contains many possible required font // properties encoded in the string. Parse it into a font matching pattern: target = FcNameParse((FcChar8*) &(_fontName[1])); // Need to manually add the current _fontSize, otherwise inconsistent stuff may happen: FcPatternAddDouble(target, FC_PIXEL_SIZE, _fontSize); } else { // _fontName contains only font family name: Build matching pattern based on _fontSize and // the flags provided in _fontStyle, according to the conventions in Psychtoolbox Screen('TextStyle'): target = FcPatternBuild (0, FC_FAMILY, FcTypeString, _fontName, FC_PIXEL_SIZE, FcTypeDouble, _fontSize, FC_WEIGHT, FcTypeInteger, ((_fontStyle & 1) ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL), FC_SLANT, FcTypeInteger, ((_fontStyle & 2) ? FC_SLANT_ITALIC : FC_SLANT_ROMAN), FC_OUTLINE, FcTypeBool, ((_fontStyle & 8) ? true : false), FC_WIDTH, FcTypeInteger, ( (_fontStyle & 32) ? FC_WIDTH_CONDENSED : ((_fontStyle & 64) ? FC_WIDTH_EXPANDED : FC_WIDTH_NORMAL) ), FC_DPI, FcTypeDouble, (double) 72.0, FC_SCALABLE, FcTypeBool, true, FC_ANTIALIAS, FcTypeBool, ((_antiAliasing != 0) ? true : false), NULL); } FcDefaultSubstitute(target); // Have a matching pattern: if (_verbosity > 3) { fprintf(stderr, "libptbdrawtext_ftgl: Trying to find font that closely matches following specification:\n"); FcPatternPrint(target); } // Perform font matching for the font in the default configuration (0) that best matches the // specified target pattern: FcPattern* matched = FcFontMatch(0, target, &result); if (result == FcResultNoMatch) { // Failed! if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig failed to find a matching font for family %s, size %f pts and style flags %i.\n", _fontName, (float) _fontSize, _fontStyle); FcPatternDestroy(target); return(1); } // Success: Extract relevant information for Freetype-2, the font filename and faceIndex: if (_verbosity > 3) { fprintf(stderr, "libptbdrawtext_ftgl: Best matching font which will be selected for drawing has following specs:\n"); FcPatternPrint(matched); } // Retrieve font filename for matched font: FcChar8* localfontFileName = NULL; if (FcPatternGetString(matched, FC_FILE, 0, (FcChar8**) &localfontFileName) != FcResultMatch) { // Failed! if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig did not find filename for font with family %s, size %f pts and style flags %i.\n", _fontName, (float) _fontSize, _fontStyle); FcPatternDestroy(target); FcPatternDestroy(matched); return(1); } strcpy(_fontFileName, (char*) localfontFileName); // Retrieve faceIndex within fontfile: if (FcPatternGetInteger(matched, FC_INDEX, 0, &_faceIndex) != FcResultMatch) { // Failed! if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: FontConfig did not find faceIndex for font file %s, family %s, size %f pts and style flags %i.\n", _fontFileName, _fontName, (float) _fontSize, _fontStyle); FcPatternDestroy(target); FcPatternDestroy(matched); return(1); } // Release target pattern and matched pattern objects: FcPatternDestroy(target); FcPatternDestroy(matched); } else { // Use "raw" values as passed by calling client code: strcpy(_fontFileName, _fontName); _faceIndex = (int) _fontStyle; } // Load & Create new font and face object, based on current spec settings: // We directly use the Freetype library, so we can spec the faceIndex for selection of textstyle, which wouldn't be // possible with the higher-level OGLFT constructor... FT_Error error = FT_New_Face( OGLFT::Library::instance(), _fontFileName, _faceIndex, &ft_face ); if (error) { if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not load face with index %i from font file %s.\n", _faceIndex, _fontFileName); return(1); } else { if (_verbosity > 3) fprintf(stderr, "libptbdrawtext_ftgl: Freetype loaded face %p with index %i from font file %s.\n", ft_face, _faceIndex, _fontFileName); } // Create FTGL face from Freetype face with given size and a 72 DPI resolution, aka _fontSize == pixelsize: if (_antiAliasing != 0) { faceT = new OGLFT::TranslucentTexture(ft_face, _fontSize, 72); // Test the created face to make sure it will work correctly: if (!faceT->isValid()) { if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not recognize %s as a font file.\n", _fontName); return(1); } } else { faceM = new OGLFT::MonochromeTexture(ft_face, _fontSize, 72); // Test the created face to make sure it will work correctly: if (!faceM->isValid()) { if (_verbosity > 1) fprintf(stderr, "libptbdrawtext_ftgl: Freetype did not recognize %s as a font file.\n", _fontName); return(1); } } // Ready! _needsRebuild = false; return(0); }
/* Constructor of the object : it allocates memory and initializes the member * of the new object. * The user must give the FcPattern of the font or the master (which may be NULL * in which case the character map will be empty). */ __GLCcharMap* __glcCharMapCreate(const __GLCmaster* inMaster, const __GLCcontext* inContext) { __GLCcharMap* This = NULL; assert(inContext); This = (__GLCcharMap*)__glcMalloc(sizeof(__GLCcharMap)); if (!This) { __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } memset(This, 0, sizeof(__GLCcharMap)); This->charSet = FcCharSetCreate(); if (!This->charSet) { __glcRaiseError(GLC_RESOURCE_ERROR); __glcFree(This); return NULL; } if (inMaster) { FcCharSet* charSet = NULL; FcFontSet* fontSet = NULL; int i = 0; FcObjectSet* objectSet = NULL; FcPattern* pattern = FcPatternCreate(); if (!pattern) { __glcRaiseError(GLC_RESOURCE_ERROR); FcCharSetDestroy(This->charSet); __glcFree(This); return NULL; } objectSet = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, FC_SPACING, FC_OUTLINE, FC_CHARSET, NULL); if (!objectSet) { __glcRaiseError(GLC_RESOURCE_ERROR); FcPatternDestroy(pattern); FcCharSetDestroy(This->charSet); __glcFree(This); return NULL; } fontSet = FcFontList(inContext->config, pattern, objectSet); FcObjectSetDestroy(objectSet); FcPatternDestroy(pattern); if (!fontSet) { __glcRaiseError(GLC_RESOURCE_ERROR); FcCharSetDestroy(This->charSet); __glcFree(This); return NULL; } for (i = 0; i < fontSet->nfont; i++) { FcChar8* family = NULL; int fixed = 0; FcChar8* foundry = NULL; FcBool outline = FcFalse; FcBool equal = FcFalse; #ifdef DEBUGMODE FcResult result = FcResultMatch; result = FcPatternGetBool(fontSet->fonts[i], FC_OUTLINE, 0, &outline); assert(result != FcResultTypeMismatch); #else FcPatternGetBool(fontSet->fonts[i], FC_OUTLINE, 0, &outline); #endif /* Check whether the glyphs are outlines */ if (!outline) continue; #ifdef DEBUGMODE result = FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &family); assert(result != FcResultTypeMismatch); result = FcPatternGetString(fontSet->fonts[i], FC_FOUNDRY, 0, &foundry); assert(result != FcResultTypeMismatch); result = FcPatternGetInteger(fontSet->fonts[i], FC_SPACING, 0, &fixed); assert(result != FcResultTypeMismatch); #else FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &family); FcPatternGetString(fontSet->fonts[i], FC_FOUNDRY, 0, &foundry); FcPatternGetInteger(fontSet->fonts[i], FC_SPACING, 0, &fixed); #endif if (foundry) pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family, FC_FOUNDRY, FcTypeString, foundry, FC_SPACING, FcTypeInteger, fixed, NULL); else pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family, FC_SPACING, FcTypeInteger, fixed, NULL); if (!pattern) { __glcRaiseError(GLC_RESOURCE_ERROR); FcCharSetDestroy(This->charSet); FcFontSetDestroy(fontSet); __glcFree(This); return NULL; } equal = FcPatternEqual(pattern, inMaster->pattern); FcPatternDestroy(pattern); if (equal) { FcCharSet* newCharSet = NULL; #ifdef DEBUGMODE result = FcPatternGetCharSet(fontSet->fonts[i], FC_CHARSET, 0, &charSet); assert(result != FcResultTypeMismatch); #else FcPatternGetCharSet(fontSet->fonts[i], FC_CHARSET, 0, &charSet); #endif newCharSet = FcCharSetUnion(This->charSet, charSet); if (!newCharSet) { __glcRaiseError(GLC_RESOURCE_ERROR); FcCharSetDestroy(This->charSet); FcFontSetDestroy(fontSet); __glcFree(This); return NULL; } FcCharSetDestroy(This->charSet); This->charSet = newCharSet; } } FcFontSetDestroy(fontSet); } /* The array 'map' will contain the actual character map */ This->map = __glcArrayCreate(sizeof(__GLCcharMapElement)); if (!This->map) { FcCharSetDestroy(This->charSet); __glcFree(This); return NULL; } return This; }
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->useSubpixelRendering = 0; break; case FC_RGBA_RGB: case FC_RGBA_BGR: case FC_RGBA_VRGB: case FC_RGBA_VBGR: out->useSubpixelRendering = 1; break; default: // This includes FC_RGBA_UNKNOWN. out->useSubpixelRendering = 2; break; } } // FontConfig doesn't provide parameters to configure whether subpixel // positioning should be used or not, so we just use a global setting. out->useSubpixelPositioning = useSubpixelPositioning; FcPatternDestroy(match); }
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; }
static void apply_xft_settings (struct x_display_info *dpyinfo, struct xsettings *settings) { #ifdef HAVE_XFT FcPattern *pat; struct xsettings oldsettings; bool changed = false; memset (&oldsettings, 0, sizeof (oldsettings)); pat = FcPatternCreate (); XftDefaultSubstitute (dpyinfo->display, XScreenNumberOfScreen (dpyinfo->screen), pat); FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa); FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting); #ifdef FC_HINT_STYLE FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle); #endif FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter); FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba); FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi); if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa) { FcPatternDel (pat, FC_ANTIALIAS); FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa); changed = true; oldsettings.aa = settings->aa; } if ((settings->seen & SEEN_HINTING) != 0 && oldsettings.hinting != settings->hinting) { FcPatternDel (pat, FC_HINTING); FcPatternAddBool (pat, FC_HINTING, settings->hinting); changed = true; oldsettings.hinting = settings->hinting; } if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba) { FcPatternDel (pat, FC_RGBA); FcPatternAddInteger (pat, FC_RGBA, settings->rgba); oldsettings.rgba = settings->rgba; changed = true; } /* Older fontconfig versions don't have FC_LCD_FILTER. */ if ((settings->seen & SEEN_LCDFILTER) != 0 && oldsettings.lcdfilter != settings->lcdfilter) { FcPatternDel (pat, FC_LCD_FILTER); FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter); changed = true; oldsettings.lcdfilter = settings->lcdfilter; } #ifdef FC_HINT_STYLE if ((settings->seen & SEEN_HINTSTYLE) != 0 && oldsettings.hintstyle != settings->hintstyle) { FcPatternDel (pat, FC_HINT_STYLE); FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle); changed = true; oldsettings.hintstyle = settings->hintstyle; } #endif if ((settings->seen & SEEN_DPI) != 0 && oldsettings.dpi != settings->dpi && settings->dpi > 0) { FcPatternDel (pat, FC_DPI); FcPatternAddDouble (pat, FC_DPI, settings->dpi); changed = true; oldsettings.dpi = settings->dpi; /* Changing the DPI on this display affects all frames on it. Check FRAME_RES_X and FRAME_RES_Y in frame.h to see how. */ dpyinfo->resy = dpyinfo->resx = settings->dpi; } if (changed) { static char const format[] = "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, " "Hintstyle: %d, DPI: %f"; enum { d_formats = 5, d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d", lf_formats = 1, max_f_integer_digits = DBL_MAX_10_EXP + 1, f_precision = 6, lf_growth = (sizeof "-." + max_f_integer_digits + f_precision - sizeof "%f") }; char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth]; XftDefaultSet (dpyinfo->display, pat); store_config_changed_event (Qfont_render, XCAR (dpyinfo->name_list_element)); Vxft_settings = make_formatted_string (buf, format, oldsettings.aa, oldsettings.hinting, oldsettings.rgba, oldsettings.lcdfilter, oldsettings.hintstyle, oldsettings.dpi); } else FcPatternDestroy (pat); #endif /* HAVE_XFT */ }
const vlc_family_t *FontConfig_GetFamily( filter_t *p_filter, const char *psz_family ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; vlc_family_t *p_family = vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc ); if( p_family != kVLCDictionaryNotFound ) { free( psz_lc ); return p_family; } p_family = NewFamily( p_filter, psz_lc, &p_sys->p_families, &p_sys->family_map, psz_lc ); free( psz_lc ); if( !p_family ) return NULL; bool b_bold, b_italic; for( int i = 0; i < 4; ++i ) { switch( i ) { case 0: b_bold = false; b_italic = false; break; case 1: b_bold = true; b_italic = false; break; case 2: b_bold = false; b_italic = true; break; case 3: b_bold = true; b_italic = true; break; } int i_index = 0; FcResult result = FcResultMatch; FcPattern *pat, *p_pat; FcChar8* val_s; FcBool val_b; char *psz_fontfile = NULL; FcConfig* config = NULL; /* Create a pattern and fill it */ pat = FcPatternCreate(); if (!pat) continue; /* */ FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_family ); FcPatternAddBool( pat, FC_OUTLINE, FcTrue ); FcPatternAddInteger( pat, FC_SLANT, b_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN ); FcPatternAddInteger( pat, FC_WEIGHT, b_bold ? FC_WEIGHT_EXTRABOLD : FC_WEIGHT_NORMAL ); /* */ FcDefaultSubstitute( pat ); if( !FcConfigSubstitute( config, pat, FcMatchPattern ) ) { FcPatternDestroy( pat ); continue; } /* Find the best font for the pattern, destroy the pattern */ p_pat = FcFontMatch( config, pat, &result ); FcPatternDestroy( pat ); if( !p_pat || result == FcResultNoMatch ) continue; /* Check the new pattern */ if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) ) || ( val_b != FcTrue ) ) { FcPatternDestroy( p_pat ); continue; } if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) ) { i_index = 0; } if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) ) { FcPatternDestroy( p_pat ); continue; } if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) ) psz_fontfile = strdup( (const char*)val_s ); FcPatternDestroy( p_pat ); if( !psz_fontfile ) continue; NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family ); } return p_family; }
FcFontSet *fcinfo_families_index(const FcPattern *filter) { int unused_int, f, nfamilies; FcPattern *pattern, *match; FcFontSet *fontset, *tmp, *families; FcResult r; FcChar8 *family, *next_family, *normal_style, *style; FcInit(); pattern = FcPatternDuplicate(filter); fontset = fcinfo(NULL, filter, FcFalse, 5, FC_FAMILY, FC_STYLE, FC_LANG,/* fonts like Misc Fixed need to be sorted by LANG (subset-like) */ FC_PIXEL_SIZE, FC_FILE); /* for identifying the best font in FC_LANG terms */ if (fontset->nfont == 0) return fontset; tmp = fcinfo_match(fontset, pattern); FcFontSetDestroy(fontset); fontset = tmp; if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &unused_int) != FcResultMatch) FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR); if (FcPatternGetInteger(pattern, FC_SLANT, 0, &unused_int) != FcResultMatch) FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &unused_int) != FcResultMatch) FcPatternAddInteger(pattern, FC_WIDTH, FC_WIDTH_NORMAL); /* choose 'normal' styles according to pattern */ families = FcFontSetCreate(); nfamilies = 0; for (f = 0; f < fontset->nfont; ) { assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, LANG_EN, &family) == FcResultMatch); FcPatternDel(pattern, FC_FAMILY); FcPatternAddString(pattern, FC_FAMILY, family); match = FcFontSetMatch(NULL, &fontset, 1, pattern, &r); assert(fcinfo_get_translated_string(match, FC_STYLE, LANG_EN, &normal_style) == FcResultMatch); do { assert(fcinfo_get_translated_string(fontset->fonts[f], FC_STYLE, LANG_EN, &style) == FcResultMatch); if (FcStrCmpIgnoreCase(style, normal_style) == 0) FcFontSetAdd(families, FcPatternDuplicate(fontset->fonts[f])); if (++f == fontset->nfont) break; assert(fcinfo_get_translated_string(fontset->fonts[f], FC_FAMILY, LANG_EN, &next_family) == FcResultMatch); } while (FcStrCmpIgnoreCase(family, next_family) == 0); nfamilies++; } FcPatternDestroy(pattern); FcFontSetDestroy(fontset); return families; }
static int pattern_compare (const void *arg1, const void *arg2, void *arg3) { const FcPattern *p1 = *(FcPattern * const *)arg1; const FcPattern *p2 = *(FcPattern * const *)arg2; const char **el = (const char **)arg3; FcChar8 *string1, *string2; int int1, int2; FcBool bool1, bool2; FcLangSet *langset1, *langset2; double double1, double2; int ret = 0; while (*el) { /* string */ if (!strcmp(*el, FC_FAMILY) || !strcmp(*el, FC_STYLE) || !strcmp(*el, FC_FONTFORMAT)) { if (FcPatternGetString (p1, *el, 0, &string1) == FcResultMatch && FcPatternGetString (p2, *el, 0, &string2) == FcResultMatch) ret = strings_compare((char *)string1, (char *)string2); } /* integer */ else if (!strcmp(*el, FC_WEIGHT) || !strcmp(*el, FC_WIDTH) || !strcmp(*el, FC_SLANT) || !strcmp(*el, FC_SPACING)) { if (FcPatternGetInteger(p1, *el, 0, &int1) == FcResultMatch && FcPatternGetInteger(p2, *el, 0, &int2) == FcResultMatch) ret = int2 - int1; } /* bool */ else if (!strcmp(*el, FC_SCALABLE) || !strcmp(*el, FC_DECORATIVE)) { if (FcPatternGetBool(p1, *el, 0, &bool1) == FcResultMatch && FcPatternGetBool(p1, *el, 0, &bool2) == FcResultMatch) ret = bool2 - bool1; } /* double */ else if (!strcmp(*el, FC_PIXEL_SIZE)) { if (FcPatternGetDouble(p1, *el, 0, &double1) == FcResultMatch && FcPatternGetDouble(p2, *el, 0, &double2) == FcResultMatch) ret = fabs(double1 - SIZE_MEAN) - fabs(double2 - SIZE_MEAN); } /* lang set */ else if (!strcmp(*el, FC_LANG)) { /* to choose size of bitmap font which supports widest range of langs */ /* maybe charset would be better? */ if (FcPatternGetLangSet(p1, *el, 0, &langset1) == FcResultMatch && FcPatternGetLangSet(p2, *el, 0, &langset2) == FcResultMatch) { ret = 0; if (FcLangSetContains(langset1, langset2)) ret = -1; if (FcLangSetContains(langset2, langset1)) { if (ret == -1) ret = 0; /* langset1 <= langset2 & langset1 >= langset2 */ else ret = 1; } } } if (ret) break; el++; } return ret; }
bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], SkFontStyle style, FontIdentity* outIdentity, SkString* outFamilyName, SkFontStyle* outStyle) { SkString familyStr(familyName ? familyName : ""); if (familyStr.size() > kMaxFontFamilyLength) { return false; } SkAutoMutexAcquire ac(mutex_); FcPattern* pattern = FcPatternCreate(); if (familyName) { FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); } fcpattern_from_skfontstyle(style, pattern); FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); // Font matching: // CSS often specifies a fallback list of families: // font-family: a, b, c, serif; // However, fontconfig will always do its best to find *a* font when asked // for something so we need a way to tell if the match which it has found is // "good enough" for us. Otherwise, we can return nullptr which gets piped up // and lets WebKit know to try the next CSS family name. However, fontconfig // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we // wish to support that. // // Thus, if a specific family is requested we set @family_requested. Then we // record two strings: the family name after config processing and the // family name after resolving. If the two are equal, it's a good match. // // So consider the case where a user has mapped Arial to Helvetica in their // config. // requested family: "Arial" // post_config_family: "Helvetica" // post_match_family: "Helvetica" // -> good match // // and for a missing font: // requested family: "Monaco" // post_config_family: "Monaco" // post_match_family: "Times New Roman" // -> BAD match // // However, we special-case fallback fonts; see IsFallbackFontAllowed(). const char* post_config_family = get_name(pattern, FC_FAMILY); if (!post_config_family) { // we can just continue with an empty name, e.g. default font post_config_family = ""; } FcResult result; FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); if (!font_set) { FcPatternDestroy(pattern); return false; } FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr); if (!match) { FcPatternDestroy(pattern); FcFontSetDestroy(font_set); return false; } FcPatternDestroy(pattern); // From here out we just extract our results from 'match' post_config_family = get_name(match, FC_FAMILY); if (!post_config_family) { FcFontSetDestroy(font_set); return false; } const char* c_filename = get_name(match, FC_FILE); if (!c_filename) { FcFontSetDestroy(font_set); return false; } int face_index; if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { FcFontSetDestroy(font_set); return false; } FcFontSetDestroy(font_set); if (outIdentity) { outIdentity->fTTCIndex = face_index; outIdentity->fString.set(c_filename); } if (outFamilyName) { outFamilyName->set(post_config_family); } if (outStyle) { *outStyle = skfontstyle_from_fcpattern(match); } return true; }
int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path) { #ifdef HAVE_FONTCONFIG unix_fontenum_t* state = (unix_fontenum_t *)enum_state; FcChar8 *file_fc = NULL; FcChar8 *family_fc = NULL; int outline_fc, slant_fc, weight_fc; FcPattern *font; FcResult result; if (state == NULL) { return 0; /* gp_enumerate_fonts_init failed for some reason */ } if (state->index == state->font_list->nfont) { return 0; /* we've run out of fonts */ } /* Bits of the following were borrowed from Red Hat's * fontconfig patch for Ghostscript 7 */ font = state->font_list->fonts[state->index]; result = FcPatternGetString (font, FC_FAMILY, 0, &family_fc); if (result != FcResultMatch || family_fc == NULL) { dlprintf ("DEBUG: FC_FAMILY mismatch\n"); return 0; } result = FcPatternGetString (font, FC_FILE, 0, &file_fc); if (result != FcResultMatch || file_fc == NULL) { dlprintf ("DEBUG: FC_FILE mismatch\n"); return 0; } result = FcPatternGetBool (font, FC_OUTLINE, 0, &outline_fc); if (result != FcResultMatch) { dlprintf1 ("DEBUG: FC_OUTLINE failed to match on %s\n", (char*)family_fc); return 0; } result = FcPatternGetInteger (font, FC_SLANT, 0, &slant_fc); if (result != FcResultMatch) { dlprintf ("DEBUG: FC_SLANT didn't match\n"); return 0; } result = FcPatternGetInteger (font, FC_WEIGHT, 0, &weight_fc); if (result != FcResultMatch) { dlprintf ("DEBUG: FC_WEIGHT didn't match\n"); return 0; } /* Gross hack to work around Fontconfig's inability to tell * us the font's PostScript name - generate it ourselves. * We must free the memory allocated here next time around. */ makePSFontName((char *)family_fc, weight_fc, slant_fc, (char *)&state->name, sizeof(state->name)); *fontname = (char *)&state->name; /* return the font path straight out of fontconfig */ *path = (char*)file_fc; state->index ++; return 1; #else return 0; #endif }
/** * \brief Low-level font selection. * \param priv private data * \param family font family * \param bold font weight value * \param italic font slant value * \param index out: font index inside a file * \param code: the character that should be present in the font, can be 0 * \return font file path */ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, uint32_t code) { FcBool rc; FcResult result; FcPattern *pat = 0, *rpat = 0; int r_index, r_slant, r_weight; FcChar8 *r_family, *r_style, *r_file, *r_fullname; FcBool r_outline, r_embolden; FcCharSet* r_charset; FcFontSet* fset = 0; int curf; char* retval = 0; int family_cnt; *index = 0; pat = FcPatternCreate(); if (!pat) goto error; FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)family); // In SSA/ASS fonts are sometimes referenced by their "full name", // which is usually a concatenation of family name and font // style (ex. Ottawa Bold). Full name is available from // FontConfig pattern element FC_FULLNAME, but it is never // used for font matching. // Therefore, I'm removing words from the end of the name one // by one, and adding shortened names to the pattern. It seems // that the first value (full name in this case) has // precedence in matching. // An alternative approach could be to reimplement FcFontSort // using FC_FULLNAME instead of FC_FAMILY. family_cnt = 1; { char* s = strdup(family); char* p = s + strlen(s); while (--p > s) if (*p == ' ' || *p == '-') { *p = '\0'; FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)s); ++ family_cnt; } free(s); } FcPatternAddBool(pat, FC_OUTLINE, FcTrue); FcPatternAddInteger(pat, FC_SLANT, italic); FcPatternAddInteger(pat, FC_WEIGHT, bold); FcDefaultSubstitute(pat); rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern); if (!rc) goto error; fset = FcFontSort(priv->config, pat, FcTrue, NULL, &result); for (curf = 0; curf < fset->nfont; ++curf) { FcPattern* curp = fset->fonts[curf]; result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline); if (result != FcResultMatch) continue; if (r_outline != FcTrue) continue; if (!code) break; result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset); if (result != FcResultMatch) continue; if (FcCharSetHasChar(r_charset, code)) break; } if (curf >= fset->nfont) goto error; #if (FC_VERSION >= 20297) // Remove all extra family names from original pattern. // After this, FcFontRenderPrepare will select the most relevant family // name in case there are more than one of them. for (; family_cnt > 1; --family_cnt) FcPatternRemove(pat, FC_FAMILY, family_cnt - 1); #endif rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]); if (!rpat) goto error; result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index); if (result != FcResultMatch) goto error; *index = r_index; result = FcPatternGetString(rpat, FC_FILE, 0, &r_file); if (result != FcResultMatch) goto error; retval = strdup((const char*)r_file); result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family); if (result != FcResultMatch) r_family = NULL; result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname); if (result != FcResultMatch) r_fullname = NULL; if (!(r_family && strcasecmp((const char*)r_family, family) == 0) && !(r_fullname && strcasecmp((const char*)r_fullname, family) == 0)) mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne, (const char*)(r_fullname ? r_fullname : r_family), family); result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style); if (result != FcResultMatch) r_style = NULL; result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant); if (result != FcResultMatch) r_slant = 0; result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight); if (result != FcResultMatch) r_weight = 0; result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden); if (result != FcResultMatch) r_embolden = 0; mp_msg(MSGT_ASS, MSGL_V, "[ass] Font info: family '%s', style '%s', fullname '%s'," " slant %d, weight %d%s\n", (const char*)r_family, (const char*)r_style, (const char*)r_fullname, r_slant, r_weight, r_embolden ? ", embolden" : ""); error: if (pat) FcPatternDestroy(pat); if (rpat) FcPatternDestroy(rpat); if (fset) FcFontSetDestroy(fset); return retval; }
bool FontConfigDirect::Match(std::string* result_family, unsigned* result_filefaceid, bool filefaceid_valid, unsigned filefaceid, const std::string& family, const void* data, size_t characters_bytes, bool* is_bold, bool* is_italic) { if (family.length() > kMaxFontFamilyLength) return false; SkAutoMutexAcquire ac(mutex_); // Given |family|, |is_bold| and |is_italic| but not |data|, the result will // be a function of these three parameters, and thus eligible for caching. // This is the fast path for |SkTypeface::CreateFromName()|. bool eligible_for_cache = !family.empty() && is_bold && is_italic && !data; if (eligible_for_cache) { int style = (*is_bold ? SkTypeface::kBold : 0 ) | (*is_italic ? SkTypeface::kItalic : 0); FontMatchKey key = FontMatchKey(family, style); const std::map<FontMatchKey, FontMatch>::const_iterator i = font_match_cache_.find(key); if (i != font_match_cache_.end()) { *is_bold = i->second.is_bold; *is_italic = i->second.is_italic; if (result_family) *result_family = i->second.family; if (result_filefaceid) *result_filefaceid = i->second.filefaceid; return true; } } FcPattern* pattern = FcPatternCreate(); if (filefaceid_valid) { const std::map<unsigned, std::string>::const_iterator i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid)); if (i == fileid_to_filename_.end()) { FcPatternDestroy(pattern); return false; } int face_index = filefaceid & 0xfu; FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(i->second.c_str())); // face_index is added only when family is empty because it is not // necessary to uniquiely identify a font if both file and // family are given. if (family.empty()) FcPatternAddInteger(pattern, FC_INDEX, face_index); } if (!family.empty()) { FcPatternAddString(pattern, FC_FAMILY, (FcChar8*) family.c_str()); } FcCharSet* charset = NULL; if (data) { charset = FcCharSetCreate(); const uint16_t* chars = (const uint16_t*) data; size_t num_chars = characters_bytes / 2; for (size_t i = 0; i < num_chars; ++i) { if (U16_IS_SURROGATE(chars[i]) && U16_IS_SURROGATE_LEAD(chars[i]) && i != num_chars - 1 && U16_IS_TRAIL(chars[i + 1])) { FcCharSetAddChar(charset, U16_GET_SUPPLEMENTARY(chars[i], chars[i+1])); i++; } else { FcCharSetAddChar(charset, chars[i]); } } FcPatternAddCharSet(pattern, FC_CHARSET, charset); FcCharSetDestroy(charset); // pattern now owns it. } FcPatternAddInteger(pattern, FC_WEIGHT, is_bold && *is_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL); FcPatternAddInteger(pattern, FC_SLANT, is_italic && *is_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN); FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); FcConfigSubstitute(NULL, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); // Font matching: // CSS often specifies a fallback list of families: // font-family: a, b, c, serif; // However, fontconfig will always do its best to find *a* font when asked // for something so we need a way to tell if the match which it has found is // "good enough" for us. Otherwise, we can return NULL which gets piped up // and lets WebKit know to try the next CSS family name. However, fontconfig // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we // wish to support that. // // Thus, if a specific family is requested we set @family_requested. Then we // record two strings: the family name after config processing and the // family name after resolving. If the two are equal, it's a good match. // // So consider the case where a user has mapped Arial to Helvetica in their // config. // requested family: "Arial" // post_config_family: "Helvetica" // post_match_family: "Helvetica" // -> good match // // and for a missing font: // requested family: "Monaco" // post_config_family: "Monaco" // post_match_family: "Times New Roman" // -> BAD match // // However, we special-case fallback fonts; see IsFallbackFontAllowed(). FcChar8* post_config_family; FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family); FcResult result; FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); if (!font_set) { FcPatternDestroy(pattern); return false; } FcPattern* match = MatchFont(font_set, post_config_family, family); if (!match) { FcPatternDestroy(pattern); FcFontSetDestroy(font_set); return false; } FcPatternDestroy(pattern); FcChar8* c_filename; if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { FcFontSetDestroy(font_set); return false; } int face_index; if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { FcFontSetDestroy(font_set); return false; } FontMatch font_match; if (filefaceid_valid) { font_match.filefaceid = filefaceid; } else { unsigned out_fileid; const std::string filename(reinterpret_cast<char*>(c_filename)); const std::map<std::string, unsigned>::const_iterator i = filename_to_fileid_.find(filename); if (i == filename_to_fileid_.end()) { out_fileid = next_file_id_++; filename_to_fileid_[filename] = out_fileid; fileid_to_filename_[out_fileid] = filename; } else { out_fileid = i->second; } // fileid stored in filename_to_fileid_ and fileid_to_filename_ is // unique only up to the font file. We have to encode face_index for // the out param. font_match.filefaceid = FileIdAndFaceIndexToFileFaceId(out_fileid, face_index); } bool success = GetFontProperties(match, &font_match.family, &font_match.is_bold, &font_match.is_italic); FcFontSetDestroy(font_set); if (success) { // If eligible, cache the result of the matching. if (eligible_for_cache) { int style = (*is_bold ? SkTypeface::kBold : 0 ) | (*is_italic ? SkTypeface::kItalic : 0); font_match_cache_[FontMatchKey(family, style)] = font_match; } if (result_family) *result_family = font_match.family; if (result_filefaceid) *result_filefaceid = font_match.filefaceid; if (is_bold) *is_bold = font_match.is_bold; if (is_italic) *is_italic = font_match.is_italic; } return success; }
int face_from_options(lua_State* L) { FT_Face face; FcChar8 * font_path; FcPattern* p; FcPattern* matched; FcResult result; int index = 0; const char *family = "Gentium"; double pointSize = 12; int slant = FC_SLANT_ROMAN; int weight = 100; const char *script = "latin"; const char *language = "eng"; int direction = HB_DIRECTION_LTR; if (!lua_istable(L, 1)) return 0; lua_pushstring(L, "font"); lua_gettable(L, -2); if (lua_isstring(L, -1)) { family = lua_tostring(L, -1); } lua_pop(L,1); lua_pushstring(L, "weight"); lua_gettable(L, -2); if (lua_isnumber(L, -1)) { int newWeight = lua_tointeger(L, -1); if (newWeight <= 100) newWeight = FC_WEIGHT_THIN; else if (newWeight <= 200) newWeight = FC_WEIGHT_ULTRALIGHT; else if (newWeight <= 300) newWeight = FC_WEIGHT_LIGHT; else if (newWeight <= 400) newWeight = FC_WEIGHT_NORMAL; else if (newWeight <= 500) newWeight = FC_WEIGHT_MEDIUM; else if (newWeight <= 600) newWeight = FC_WEIGHT_DEMIBOLD; else if (newWeight <= 700) newWeight = FC_WEIGHT_BOLD; else if (newWeight <= 800) newWeight = FC_WEIGHT_ULTRABOLD; else newWeight = FC_WEIGHT_HEAVY; weight = newWeight; } lua_pop(L,1); lua_pushstring(L, "size"); lua_gettable(L, -2); if (lua_isnumber(L, -1)) { pointSize = lua_tonumber(L, -1); } lua_pop(L,1); lua_pushstring(L, "language"); lua_gettable(L, -2); if (lua_isstring(L, -1)) { language = lua_tostring(L, -1); } lua_pop(L,1); lua_pushstring(L, "style"); lua_gettable(L, -2); if (lua_isstring(L, -1)) { const char* newStyleAsText = lua_tostring(L, -1); if (!strcmp(newStyleAsText, "italic")) slant = FC_SLANT_ITALIC; } lua_pop(L,1); p = FcPatternCreate(); FcPatternAddString (p, FC_FAMILY, (FcChar8*)(family)); FcPatternAddDouble (p, FC_SIZE, pointSize); FcPatternAddInteger(p, FC_SLANT, slant); FcPatternAddInteger(p, FC_WEIGHT, weight); // /* Add fallback fonts here. Some of the standard 14 should be fine. */ FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Times-Roman"); FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Times"); FcPatternAddString (p, FC_FAMILY,(FcChar8*) "Helvetica"); matched = FcFontMatch (0, p, &result); if (FcPatternGetString (matched, FC_FILE, 0, &font_path) != FcResultMatch) return 0; FcPatternGetInteger(matched, FC_INDEX, 0, &index); font_path = (FcChar8 *)strdup((char*)font_path); /* XXX signedness problems? */ if (!font_path) { printf("Finding font path failed\n"); return 0; } /* Push back slant and weight, we need to pass them to libpdftex */ FcPatternGetInteger(matched, FC_SLANT, 0, &slant); FcPatternGetInteger(matched, FC_WEIGHT, 0, &weight); /* Find out which family we did actually pick up */ if (FcPatternGetString (matched, FC_FAMILY, 0, &family) != FcResultMatch) return 0; lua_newtable(L); lua_pushstring(L, "filename"); lua_pushstring(L, (char*)font_path); lua_settable(L, -3); lua_pushstring(L, "family"); lua_pushstring(L, (char*)(family)); lua_settable(L, -3); FcPatternDestroy (matched); FcPatternDestroy (p); face = (FT_Face)malloc(sizeof(FT_Face)); if (FT_New_Face(ft_library, (char*)font_path, index, &face)) return 0; if (FT_Set_Char_Size(face,pointSize * 64.0, 0, 0, 0)) return 0; lua_pushstring(L, "index"); lua_pushinteger(L, index); lua_settable(L, -3); lua_pushstring(L, "pointsize"); lua_pushnumber(L, pointSize); lua_settable(L, -3); lua_pushstring(L, "face"); lua_pushlightuserdata(L, face); lua_settable(L, -3); return 1; }
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); }
void SkScalerContext_CairoFT::parsePattern(FcPattern* pattern) { FcBool antialias, autohint, bitmap, embolden, hinting, vertical; if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && autohint) { fRec.fFlags |= SkScalerContext::kForceAutohinting_Flag; } if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == FcResultMatch && bitmap) { fRec.fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag; } if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && embolden) { fRec.fFlags |= SkScalerContext::kEmbolden_Flag; } if (FcPatternGetBool(pattern, FC_VERTICAL_LAYOUT, 0, &vertical) == FcResultMatch && vertical) { fRec.fFlags |= SkScalerContext::kVertical_Flag; } if (fRec.fMaskFormat != SkMask::kBW_Format && (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch || antialias)) { int rgba; if (!isLCD(fRec) || FcPatternGetInteger(pattern, FC_RGBA, 0, &rgba) != FcResultMatch) { rgba = FC_RGBA_UNKNOWN; } switch (rgba) { case FC_RGBA_RGB: break; case FC_RGBA_BGR: fRec.fFlags |= SkScalerContext::kLCD_BGROrder_Flag; break; case FC_RGBA_VRGB: fRec.fFlags |= SkScalerContext::kLCD_Vertical_Flag; break; case FC_RGBA_VBGR: fRec.fFlags |= SkScalerContext::kLCD_Vertical_Flag | SkScalerContext::kLCD_BGROrder_Flag; break; default: fRec.fMaskFormat = SkMask::kA8_Format; break; } int filter; if (isLCD(fRec)) { if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) != FcResultMatch) { filter = FC_LCD_LEGACY; } switch (filter) { case FC_LCD_NONE: fLcdFilter = FT_LCD_FILTER_NONE; break; case FC_LCD_DEFAULT: fLcdFilter = FT_LCD_FILTER_DEFAULT; break; case FC_LCD_LIGHT: fLcdFilter = FT_LCD_FILTER_LIGHT; break; case FC_LCD_LEGACY: default: fLcdFilter = FT_LCD_FILTER_LEGACY; break; } } } else { fRec.fMaskFormat = SkMask::kBW_Format; } if (fRec.getHinting() != SkPaint::kNo_Hinting && (FcPatternGetBool(pattern, FC_HINTING, 0, &hinting) != FcResultMatch || hinting)) { int hintstyle; if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) { hintstyle = FC_HINT_FULL; } switch (hintstyle) { case FC_HINT_NONE: fRec.setHinting(SkPaint::kNo_Hinting); break; case FC_HINT_SLIGHT: fRec.setHinting(SkPaint::kSlight_Hinting); break; case FC_HINT_MEDIUM: default: fRec.setHinting(SkPaint::kNormal_Hinting); break; case FC_HINT_FULL: fRec.setHinting(SkPaint::kFull_Hinting); break; } } }
void QFontconfigDatabase::populateFontDatabase() { FcFontSet *fonts; QString familyName; FcChar8 *value = 0; int weight_value; int slant_value; int spacing_value; FcChar8 *file_value; int indexValue; FcChar8 *foundry_value; FcBool scalable; FcBool antialias; { FcObjectSet *os = FcObjectSetCreate(); FcPattern *pattern = FcPatternCreate(); const char *properties [] = { FC_FAMILY, FC_WEIGHT, FC_SLANT, FC_SPACING, FC_FILE, FC_INDEX, FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WIDTH, #if FC_VERSION >= 20297 FC_CAPABILITY, #endif (const char *)0 }; const char **p = properties; while (*p) { FcObjectSetAdd(os, *p); ++p; } fonts = FcFontList(0, pattern, os); FcObjectSetDestroy(os); FcPatternDestroy(pattern); } for (int i = 0; i < fonts->nfont; i++) { if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); familyName = QString::fromUtf8((const char *)value); slant_value = FC_SLANT_ROMAN; weight_value = FC_WEIGHT_MEDIUM; spacing_value = FC_PROPORTIONAL; file_value = 0; indexValue = 0; scalable = FcTrue; if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) slant_value = FC_SLANT_ROMAN; if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) weight_value = FC_WEIGHT_MEDIUM; if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) spacing_value = FC_PROPORTIONAL; if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) file_value = 0; if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) indexValue = 0; if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) scalable = FcTrue; if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) foundry_value = 0; if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) antialias = true; QSupportedWritingSystems writingSystems; FcLangSet *langset = 0; FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); if (res == FcResultMatch) { for (int i = 1; i < LanguageCount; ++i) { const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; if (lang) { FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) writingSystems.setSupported(QFontDatabase::WritingSystem(i)); } } } else { // we set Other to supported for symbol fonts. It makes no // sense to merge these with other ones, as they are // special in a way. writingSystems.setSupported(QFontDatabase::Other); } FcCharSet *cs = 0; res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); if (res == FcResultMatch) { // some languages are not supported by FontConfig, we rather check the // charset to detect these for (int i = 1; i < SampleCharCount; ++i) { if (!sampleCharForWritingSystem[i]) continue; if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) writingSystems.setSupported(QFontDatabase::WritingSystem(i)); } } #if FC_VERSION >= 20297 for (int j = 1; j < LanguageCount; ++j) { if (writingSystems.supported(QFontDatabase::WritingSystem(j)) && requiresOpenType(j) && openType[j]) { FcChar8 *cap; res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); } } #endif FontFile *fontFile = new FontFile; fontFile->fileName = QLatin1String((const char *)file_value); fontFile->indexValue = indexValue; QFont::Style style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) ? QFont::StyleOblique : QFont::StyleNormal); QFont::Weight weight = QFont::Weight(getFCWeight(weight_value)); double pixel_size = 0; if (!scalable) FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); int width = FC_WIDTH_NORMAL; FcPatternGetInteger(fonts->fonts[i], FC_WIDTH, 0, &width); QFont::Stretch stretch; switch (width) { case FC_WIDTH_ULTRACONDENSED: stretch = QFont::UltraCondensed; break; case FC_WIDTH_EXTRACONDENSED: stretch = QFont::ExtraCondensed; break; case FC_WIDTH_CONDENSED: stretch = QFont::Condensed; break; case FC_WIDTH_SEMICONDENSED: stretch = QFont::SemiCondensed; break; case FC_WIDTH_NORMAL: stretch = QFont::Unstretched; break; case FC_WIDTH_SEMIEXPANDED: stretch = QFont::SemiExpanded; break; case FC_WIDTH_EXPANDED: stretch = QFont::Expanded; break; case FC_WIDTH_EXTRAEXPANDED: stretch = QFont::ExtraExpanded; break; case FC_WIDTH_ULTRAEXPANDED: stretch = QFont::UltraExpanded; break; default: stretch = QFont::Unstretched; break; } QPlatformFontDatabase::registerFont(familyName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,writingSystems,fontFile); // qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; } FcFontSetDestroy (fonts); struct FcDefaultFont { const char *qtname; const char *rawname; bool fixed; }; const FcDefaultFont defaults[] = { { "Serif", "serif", false }, { "Sans Serif", "sans-serif", false }, { "Monospace", "monospace", true }, { 0, 0, false } }; const FcDefaultFont *f = defaults; // aliases only make sense for 'common', not for any of the specials QSupportedWritingSystems ws; ws.setSupported(QFontDatabase::Latin); while (f->qtname) { registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,ws,0); registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,ws,0); registerFont(f->qtname,QLatin1String(""),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,ws,0); ++f; } //Lighthouse has very lazy population of the font db. We want it to be initialized when //QApplication is constructed, so that the population procedure can do something like this to //set the default font // const FcDefaultFont *s = defaults; // QFont font("Sans Serif"); // font.setPointSize(9); // QApplication::setFont(font); }
static void apply_xft_settings (struct x_display_info *dpyinfo, struct xsettings *settings) { #ifdef HAVE_XFT FcPattern *pat; struct xsettings oldsettings; bool changed = false; memset (&oldsettings, 0, sizeof (oldsettings)); pat = FcPatternCreate (); XftDefaultSubstitute (dpyinfo->display, XScreenNumberOfScreen (dpyinfo->screen), pat); FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa); FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting); #ifdef FC_HINT_STYLE FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle); #endif FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter); FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba); FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi); if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa) { FcPatternDel (pat, FC_ANTIALIAS); FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa); changed = true; oldsettings.aa = settings->aa; } if ((settings->seen & SEEN_HINTING) != 0 && oldsettings.hinting != settings->hinting) { FcPatternDel (pat, FC_HINTING); FcPatternAddBool (pat, FC_HINTING, settings->hinting); changed = true; oldsettings.hinting = settings->hinting; } if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba) { FcPatternDel (pat, FC_RGBA); FcPatternAddInteger (pat, FC_RGBA, settings->rgba); oldsettings.rgba = settings->rgba; changed = true; } /* Older fontconfig versions don't have FC_LCD_FILTER. */ if ((settings->seen & SEEN_LCDFILTER) != 0 && oldsettings.lcdfilter != settings->lcdfilter) { FcPatternDel (pat, FC_LCD_FILTER); FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter); changed = true; oldsettings.lcdfilter = settings->lcdfilter; } #ifdef FC_HINT_STYLE if ((settings->seen & SEEN_HINTSTYLE) != 0 && oldsettings.hintstyle != settings->hintstyle) { FcPatternDel (pat, FC_HINT_STYLE); FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle); changed = true; oldsettings.hintstyle = settings->hintstyle; } #endif if ((settings->seen & SEEN_DPI) != 0 && settings->dpi > 0 /* The following conjunct avoids setting `changed' to true when old and new dpi settings do not differ "substantially". Otherwise, the dynamic-setting Elisp code may process all sorts of unrelated settings that override users' font customizations, among others. Compare: https://lists.gnu.org/r/emacs-devel/2016-05/msg00557.html https://lists.gnu.org/r/bug-gnu-emacs/2016-12/msg00820.html As soon as the dynamic-settings code has been tested and verified, this Emacs 25.2 workaround should be removed. */ && ((oldsettings.dpi >= settings->dpi && (oldsettings.dpi - settings->dpi) > 2) || ((settings->dpi > oldsettings.dpi) && (settings->dpi - oldsettings.dpi) > 2))) { FcPatternDel (pat, FC_DPI); FcPatternAddDouble (pat, FC_DPI, settings->dpi); changed = true; oldsettings.dpi = settings->dpi; /* Changing the DPI on this display affects all frames on it. Check FRAME_RES_X and FRAME_RES_Y in frame.h to see how. */ dpyinfo->resy = dpyinfo->resx = settings->dpi; } if (changed) { static char const format[] = "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, " "Hintstyle: %d, DPI: %f"; enum { d_formats = 5, d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d", lf_formats = 1, max_f_integer_digits = DBL_MAX_10_EXP + 1, f_precision = 6, lf_growth = (sizeof "-." + max_f_integer_digits + f_precision - sizeof "%f") }; char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth]; XftDefaultSet (dpyinfo->display, pat); store_config_changed_event (Qfont_render, XCAR (dpyinfo->name_list_element)); Vxft_settings = make_formatted_string (buf, format, oldsettings.aa, oldsettings.hinting, oldsettings.rgba, oldsettings.lcdfilter, oldsettings.hintstyle, oldsettings.dpi); } else FcPatternDestroy (pat); #endif /* HAVE_XFT */ }
/** * \brief Low-level font selection. * \param priv private data * \param family font family * \param treat_family_as_pattern treat family as fontconfig pattern * \param bold font weight value * \param italic font slant value * \param index out: font index inside a file * \param code: the character that should be present in the font, can be 0 * \return font file path */ static char *select_font(ASS_Library *library, FCInstance *priv, const char *family, int treat_family_as_pattern, unsigned bold, unsigned italic, int *index, uint32_t code) { FcBool rc; FcResult result; FcPattern *pat = NULL, *rpat = NULL; int r_index, r_slant, r_weight; FcChar8 *r_family, *r_style, *r_file, *r_fullname; FcBool r_outline, r_embolden; FcCharSet *r_charset; FcFontSet *ffullname = NULL, *fsorted = NULL, *fset = NULL; int curf; char *retval = NULL; int family_cnt = 0; *index = 0; if (treat_family_as_pattern) pat = FcNameParse((const FcChar8 *) family); else pat = FcPatternCreate(); if (!pat) goto error; if (!treat_family_as_pattern) { FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family); // In SSA/ASS fonts are sometimes referenced by their "full name", // which is usually a concatenation of family name and font // style (ex. Ottawa Bold). Full name is available from // FontConfig pattern element FC_FULLNAME, but it is never // used for font matching. // Therefore, I'm removing words from the end of the name one // by one, and adding shortened names to the pattern. It seems // that the first value (full name in this case) has // precedence in matching. // An alternative approach could be to reimplement FcFontSort // using FC_FULLNAME instead of FC_FAMILY. family_cnt = 1; { char *s = strdup(family); if (!s) goto error; char *p = s + strlen(s); while (--p > s) if (*p == ' ' || *p == '-') { *p = '\0'; FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) s); ++family_cnt; } free(s); } } FcPatternAddBool(pat, FC_OUTLINE, FcTrue); FcPatternAddInteger(pat, FC_SLANT, italic); FcPatternAddInteger(pat, FC_WEIGHT, bold); FcDefaultSubstitute(pat); rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern); if (!rc) goto error; /* Fontconfig defaults include a language setting, which it sets based on * some environment variables or defaults to "en". Unset this as we don't * know the real language, and because some some attached fonts lack * non-ascii characters included in fontconfig's list of characters * required for English support and therefore don't match the lang=en * criterion. */ FcPatternDel(pat, "lang"); fsorted = FcFontSort(priv->config, pat, FcFalse, NULL, &result); ffullname = match_fullname(library, priv, family, bold, italic); if (!fsorted || !ffullname) goto error; fset = FcFontSetCreate(); for (curf = 0; curf < ffullname->nfont; ++curf) { FcPattern *curp = ffullname->fonts[curf]; FcPatternReference(curp); FcFontSetAdd(fset, curp); } for (curf = 0; curf < fsorted->nfont; ++curf) { FcPattern *curp = fsorted->fonts[curf]; FcPatternReference(curp); FcFontSetAdd(fset, curp); } for (curf = 0; curf < fset->nfont; ++curf) { FcPattern *curp = fset->fonts[curf]; result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline); if (result != FcResultMatch) continue; if (r_outline != FcTrue) continue; if (!code) break; result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset); if (result != FcResultMatch) continue; if (FcCharSetHasChar(r_charset, code)) break; } if (curf >= fset->nfont) goto error; if (!treat_family_as_pattern) { // Remove all extra family names from original pattern. // After this, FcFontRenderPrepare will select the most relevant family // name in case there are more than one of them. for (; family_cnt > 1; --family_cnt) FcPatternRemove(pat, FC_FAMILY, family_cnt - 1); } rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]); if (!rpat) goto error; result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index); if (result != FcResultMatch) goto error; *index = r_index; result = FcPatternGetString(rpat, FC_FILE, 0, &r_file); if (result != FcResultMatch) goto error; retval = strdup((const char *) r_file); if (!retval) goto error; result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family); if (result != FcResultMatch) r_family = NULL; result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname); if (result != FcResultMatch) r_fullname = NULL; if (!treat_family_as_pattern && !(r_family && strcasecmp((const char *) r_family, family) == 0) && !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0)) { char *fallback = (char *) (r_fullname ? r_fullname : r_family); if (code) { ass_msg(library, MSGL_WARN, "fontconfig: cannot find glyph U+%04X in font '%s', falling back to '%s'", (unsigned int)code, family, fallback); } else { ass_msg(library, MSGL_WARN, "fontconfig: cannot find font '%s', falling back to '%s'", family, fallback); } } result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style); if (result != FcResultMatch) r_style = NULL; result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant); if (result != FcResultMatch) r_slant = 0; result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight); if (result != FcResultMatch) r_weight = 0; result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden); if (result != FcResultMatch) r_embolden = 0; ass_msg(library, MSGL_V, "Font info: family '%s', style '%s', fullname '%s'," " slant %d, weight %d%s", (const char *) r_family, (const char *) r_style, (const char *) r_fullname, r_slant, r_weight, r_embolden ? ", embolden" : ""); error: if (pat) FcPatternDestroy(pat); if (rpat) FcPatternDestroy(rpat); if (fsorted) FcFontSetDestroy(fsorted); if (ffullname) FcFontSetDestroy(ffullname); if (fset) FcFontSetDestroy(fset); return retval; }
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName) : m_pattern(0) , m_size(fontDescription.computedSize()) , m_syntheticBold(false) , m_syntheticOblique(false) , m_scaledFont(0) , m_face(0) { FontPlatformData::init(); CString familyNameString = familyName.string().utf8(); const char* fcfamily = familyNameString.data(); int fcslant = FC_SLANT_ROMAN; // FIXME: Map all FontWeight values to fontconfig weights. int fcweight = FC_WEIGHT_NORMAL; float fcsize = fontDescription.computedSize(); if (fontDescription.italic()) fcslant = FC_SLANT_ITALIC; if (fontDescription.weight() >= FontWeight600) fcweight = FC_WEIGHT_BOLD; FcConfig *config = FcConfigGetCurrent(); //printf("family = %s\n", fcfamily); int type = fontDescription.genericFamily(); FcPattern* pattern = FcPatternCreate(); if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) goto freePattern; switch (type) { case FontDescription::SerifFamily: fcfamily = "serif"; break; case FontDescription::SansSerifFamily: fcfamily = "sans-serif"; break; case FontDescription::MonospaceFamily: fcfamily = "monospace"; break; case FontDescription::NoFamily: case FontDescription::StandardFamily: default: fcfamily = "sans-serif"; } if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) goto freePattern; if (!FcPatternAddInteger(pattern, FC_SLANT, fcslant)) goto freePattern; if (!FcPatternAddInteger(pattern, FC_WEIGHT, fcweight)) goto freePattern; if (!FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fcsize)) goto freePattern; FcConfigSubstitute(config, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult fcresult; m_pattern = FcFontMatch(config, pattern, &fcresult); FcPatternReference(m_pattern); // FIXME: should we set some default font? if (!m_pattern) goto freePattern; FcChar8 *fc_filename; char *filename; int id; id = 0; if (FcPatternGetString(m_pattern, FC_FILE, 0, &fc_filename) != FcResultMatch) { DS_WAR("cannot retrieve font\n"); goto freePattern; } filename = (char *) fc_filename; //use C cast as FcChar is a fontconfig type //printf("filename = %s\n", filename); if (FcPatternGetInteger(m_pattern, FC_INDEX, 0, &id) != FcResultMatch) { DS_WAR("cannot retrieve font index\n"); goto freePattern; } if (FT_Error error = FT_New_Face(m_library, filename, id, &m_face)) { //if (FT_Error error = FT_New_Face(m_library, too, id, &m_face)) { DS_WAR("fail to open font" << filename << "with index " << id << " (error = 0x%x)\n" << error); m_face = 0; goto freePattern; } FT_Set_Pixel_Sizes(m_face, 0, static_cast<uint> (fontDescription.computedSize())); //DBGML(MODULE_FONTS, LEVEL_INFO, "open font %s with size %d\n", filename, static_cast<uint> (fontDescription.specifiedSize())); freePattern: FcPatternDestroy(pattern); FcConfigDestroy(config); }
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { 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]; seprintf(lang, lastof(lang), ":lang=%s", language_isocode); char *split = strchr(lang, '_'); if (split != NULL) *split = '\0'; /* First create a pattern to match the wanted language. */ FcPattern *pat = FcNameParse((FcChar8*)lang); /* We only want to know the filename. */ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, NULL); /* Get the list of filenames matching the wanted language. */ FcFontSet *fs = FcFontList(NULL, pat, os); /* We don't need these anymore. */ FcObjectSetDestroy(os); FcPatternDestroy(pat); if (fs != NULL) { int best_weight = -1; const char *best_font = NULL; for (int i = 0; i < fs->nfont; i++) { FcPattern *font = fs->fonts[i]; FcChar8 *file = NULL; FcResult res = FcPatternGetString(font, FC_FILE, 0, &file); if (res != FcResultMatch || file == NULL) { continue; } /* Get a font with the right spacing .*/ int value = 0; FcPatternGetInteger(font, FC_SPACING, 0, &value); if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue; /* Do not use those that explicitly say they're slanted. */ FcPatternGetInteger(font, FC_SLANT, 0, &value); if (value != 0) continue; /* We want the fatter font as they look better at small sizes. */ FcPatternGetInteger(font, FC_WEIGHT, 0, &value); if (value <= best_weight) continue; callback->SetFontNames(settings, (const char*)file); bool missing = callback->FindMissingGlyphs(NULL); DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no"); if (!missing) { best_weight = value; best_font = (const char *)file; } } if (best_font != NULL) { ret = true; callback->SetFontNames(settings, best_font); InitFreeType(callback->Monospace()); } /* Clean up the list of filenames. */ FcFontSetDestroy(fs); } FcFini(); return ret; }
static int load_font_fontconfig(AVFilterContext *ctx) { DrawTextContext *s = ctx->priv; FcConfig *fontconfig; FcPattern *pat, *best; FcResult result = FcResultMatch; FcChar8 *filename; int index; double size; int err = AVERROR(ENOENT); fontconfig = FcInitLoadConfigAndFonts(); if (!fontconfig) { av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n"); return AVERROR_UNKNOWN; } pat = FcNameParse(s->fontfile ? s->fontfile : (uint8_t *)(intptr_t)"default"); if (!pat) { av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat"); return AVERROR(EINVAL); } FcPatternAddString(pat, FC_FAMILY, s->font); if (s->fontsize) FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize); FcDefaultSubstitute(pat); if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) { av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */ FcPatternDestroy(pat); return AVERROR(ENOMEM); } best = FcFontMatch(fontconfig, pat, &result); FcPatternDestroy(pat); if (!best || result != FcResultMatch) { av_log(ctx, AV_LOG_ERROR, "Cannot find a valid font for the family %s\n", s->font); goto fail; } if ( FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch || FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) { av_log(ctx, AV_LOG_ERROR, "impossible to find font information"); return AVERROR(EINVAL); } if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) { av_log(ctx, AV_LOG_ERROR, "No file path for %s\n", s->font); goto fail; } av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename); if (!s->fontsize) s->fontsize = size + 0.5; err = load_font_file(ctx, filename, index); if (err) return err; FcConfigDestroy(fontconfig); fail: FcPatternDestroy(best); return err; }
static void populateFromPattern(FcPattern *pattern) { QString familyName; QString familyNameLang; FcChar8 *value = 0; int weight_value; int slant_value; int spacing_value; int width_value; FcChar8 *file_value; int indexValue; FcChar8 *foundry_value; FcChar8 *style_value; FcBool scalable; FcBool antialias; if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch) return; familyName = QString::fromUtf8((const char *)value); if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch) familyNameLang = QString::fromUtf8((const char *)value); slant_value = FC_SLANT_ROMAN; weight_value = FC_WEIGHT_REGULAR; spacing_value = FC_PROPORTIONAL; file_value = 0; indexValue = 0; scalable = FcTrue; if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch) slant_value = FC_SLANT_ROMAN; if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch) weight_value = FC_WEIGHT_REGULAR; if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch) width_value = FC_WIDTH_NORMAL; if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) spacing_value = FC_PROPORTIONAL; if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) file_value = 0; if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) indexValue = 0; if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) scalable = FcTrue; if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) foundry_value = 0; if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) style_value = 0; if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) antialias = true; QSupportedWritingSystems writingSystems; FcLangSet *langset = 0; FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); if (res == FcResultMatch) { bool hasLang = false; #if FC_VERSION >= 20297 FcChar8 *cap = Q_NULLPTR; FcResult capRes = FcResultNoMatch; #endif for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; if (lang) { FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) { #if FC_VERSION >= 20297 if (*capabilityForWritingSystem[j] && requiresOpenType(j)) { if (cap == Q_NULLPTR) capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0) continue; } #endif writingSystems.setSupported(QFontDatabase::WritingSystem(j)); hasLang = true; } } } if (!hasLang) // none of our known languages, add it to the other set writingSystems.setSupported(QFontDatabase::Other); } else { // we set Other to supported for symbol fonts. It makes no // sense to merge these with other ones, as they are // special in a way. writingSystems.setSupported(QFontDatabase::Other); } FontFile *fontFile = new FontFile; fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); fontFile->indexValue = indexValue; QFont::Style style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) ? QFont::StyleOblique : QFont::StyleNormal); // Note: weight should really be an int but registerFont incorrectly uses an enum QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); double pixel_size = 0; if (!scalable) FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); bool fixedPitch = spacing_value >= FC_MONO; // Note: stretch should really be an int but registerFont incorrectly uses an enum QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); // 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) { const QString altFamilyName = QString::fromUtf8((const char *)value); // Extra family names can be aliases or subfamilies. // If it is a subfamily, register it as a separate font, so only members of the subfamily are // matched when the subfamily is requested. QString altStyleName; if (FcPatternGetString(pattern, FC_STYLE, k, &value) == FcResultMatch) altStyleName = QString::fromUtf8((const char *)value); else altStyleName = styleName; QString altFamilyNameLang; if (FcPatternGetString(pattern, FC_FAMILYLANG, k, &value) == FcResultMatch) altFamilyNameLang = QString::fromUtf8((const char *)value); else altFamilyNameLang = familyNameLang; if (familyNameLang == altFamilyNameLang && altStyleName != styleName) { FontFile *altFontFile = new FontFile(*fontFile); QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile); } else { QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName); } } }
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; }
MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_cache, ExceptionInfo *exception) { #if !defined(FC_FULLNAME) #define FC_FULLNAME "fullname" #endif char extension[MagickPathExtent], name[MagickPathExtent]; FcChar8 *family, *file, *fullname, *style; FcConfig *font_config; FcFontSet *font_set; FcObjectSet *object_set; FcPattern *pattern; FcResult status; int slant, width, weight; register ssize_t i; TypeInfo *type_info; /* Load system fonts. */ (void) exception; font_config=FcInitLoadConfigAndFonts(); if (font_config == (FcConfig *) NULL) return(MagickFalse); font_set=(FcFontSet *) NULL; object_set=FcObjectSetBuild(FC_FULLNAME,FC_FAMILY,FC_STYLE,FC_SLANT, FC_WIDTH,FC_WEIGHT,FC_FILE,(char *) NULL); if (object_set != (FcObjectSet *) NULL) { pattern=FcPatternCreate(); if (pattern != (FcPattern *) NULL) { font_set=FcFontList(0,pattern,object_set); FcPatternDestroy(pattern); } FcObjectSetDestroy(object_set); } if (font_set == (FcFontSet *) NULL) { FcConfigDestroy(font_config); return(MagickFalse); } for (i=0; i < (ssize_t) font_set->nfont; i++) { status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family); if (status != FcResultMatch) continue; status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file); if (status != FcResultMatch) continue; *extension='\0'; GetPathComponent((const char *) file,ExtensionPath,extension); if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0)) continue; type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info)); if (type_info == (TypeInfo *) NULL) continue; (void) ResetMagickMemory(type_info,0,sizeof(*type_info)); type_info->path=ConstantString("System Fonts"); type_info->signature=MagickCoreSignature; (void) CopyMagickString(name,"Unknown",MagickPathExtent); status=FcPatternGetString(font_set->fonts[i],FC_FULLNAME,0,&fullname); if ((status == FcResultMatch) && (fullname != (FcChar8 *) NULL)) (void) CopyMagickString(name,(const char *) fullname,MagickPathExtent); else { if (family != (FcChar8 *) NULL) (void) CopyMagickString(name,(const char *) family,MagickPathExtent); status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style); if ((status == FcResultMatch) && (style != (FcChar8 *) NULL) && (LocaleCompare((const char *) style,"Regular") != 0)) { (void) ConcatenateMagickString(name," ",MagickPathExtent); (void) ConcatenateMagickString(name,(const char *) style, MagickPathExtent); } } type_info->name=ConstantString(name); (void) SubstituteString(&type_info->name," ","-"); type_info->family=ConstantString((const char *) family); status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant); type_info->style=NormalStyle; if (slant == FC_SLANT_ITALIC) type_info->style=ItalicStyle; if (slant == FC_SLANT_OBLIQUE) type_info->style=ObliqueStyle; status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width); type_info->stretch=NormalStretch; if (width >= FC_WIDTH_ULTRACONDENSED) type_info->stretch=UltraCondensedStretch; if (width >= FC_WIDTH_EXTRACONDENSED) type_info->stretch=ExtraCondensedStretch; if (width >= FC_WIDTH_CONDENSED) type_info->stretch=CondensedStretch; if (width >= FC_WIDTH_SEMICONDENSED) type_info->stretch=SemiCondensedStretch; if (width >= FC_WIDTH_NORMAL) type_info->stretch=NormalStretch; if (width >= FC_WIDTH_SEMIEXPANDED) type_info->stretch=SemiExpandedStretch; if (width >= FC_WIDTH_EXPANDED) type_info->stretch=ExpandedStretch; if (width >= FC_WIDTH_EXTRAEXPANDED) type_info->stretch=ExtraExpandedStretch; if (width >= FC_WIDTH_ULTRAEXPANDED) type_info->stretch=UltraExpandedStretch; type_info->weight=400; status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight); if (weight >= FC_WEIGHT_THIN) type_info->weight=100; if (weight >= FC_WEIGHT_EXTRALIGHT) type_info->weight=200; if (weight >= FC_WEIGHT_LIGHT) type_info->weight=300; if (weight >= FC_WEIGHT_NORMAL) type_info->weight=400; if (weight >= FC_WEIGHT_MEDIUM) type_info->weight=500; if (weight >= FC_WEIGHT_DEMIBOLD) type_info->weight=600; if (weight >= FC_WEIGHT_BOLD) type_info->weight=700; if (weight >= FC_WEIGHT_EXTRABOLD) type_info->weight=800; if (weight >= FC_WEIGHT_BLACK) type_info->weight=900; type_info->glyphs=ConstantString((const char *) file); (void) AddValueToSplayTree(type_cache,type_info->name,type_info); } FcFontSetDestroy(font_set); FcConfigDestroy(font_config); return(MagickTrue); }
static void apply_xft_settings (struct x_display_info *dpyinfo, int send_event_p, struct xsettings *settings) { #ifdef HAVE_XFT FcPattern *pat; struct xsettings oldsettings; int changed = 0; memset (&oldsettings, 0, sizeof (oldsettings)); pat = FcPatternCreate (); XftDefaultSubstitute (dpyinfo->display, XScreenNumberOfScreen (dpyinfo->screen), pat); FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa); FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting); #ifdef FC_HINT_STYLE FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle); #endif FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter); FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba); FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi); if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa) { FcPatternDel (pat, FC_ANTIALIAS); FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa); ++changed; oldsettings.aa = settings->aa; } if ((settings->seen & SEEN_HINTING) != 0 && oldsettings.hinting != settings->hinting) { FcPatternDel (pat, FC_HINTING); FcPatternAddBool (pat, FC_HINTING, settings->hinting); ++changed; oldsettings.hinting = settings->hinting; } if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba) { FcPatternDel (pat, FC_RGBA); FcPatternAddInteger (pat, FC_RGBA, settings->rgba); oldsettings.rgba = settings->rgba; ++changed; } /* Older fontconfig versions don't have FC_LCD_FILTER. */ if ((settings->seen & SEEN_LCDFILTER) != 0 && oldsettings.lcdfilter != settings->lcdfilter) { FcPatternDel (pat, FC_LCD_FILTER); FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter); ++changed; oldsettings.lcdfilter = settings->lcdfilter; } #ifdef FC_HINT_STYLE if ((settings->seen & SEEN_HINTSTYLE) != 0 && oldsettings.hintstyle != settings->hintstyle) { FcPatternDel (pat, FC_HINT_STYLE); FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle); ++changed; oldsettings.hintstyle = settings->hintstyle; } #endif if ((settings->seen & SEEN_DPI) != 0 && oldsettings.dpi != settings->dpi && settings->dpi > 0) { Lisp_Object frame, tail; FcPatternDel (pat, FC_DPI); FcPatternAddDouble (pat, FC_DPI, settings->dpi); ++changed; oldsettings.dpi = settings->dpi; /* Change the DPI on this display and all frames on the display. */ dpyinfo->resy = dpyinfo->resx = settings->dpi; FOR_EACH_FRAME (tail, frame) if (FRAME_X_P (XFRAME (frame)) && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) XFRAME (frame)->resy = XFRAME (frame)->resx = settings->dpi; }