static void pk_font_not_found (PangoLanguage *language) { FcPattern *pat = NULL; gchar *tag = NULL; const gchar *lang; g_return_if_fail (language != NULL); /* convert to language */ lang = pango_language_to_string (language); if (lang == NULL || lang[0] == '\0') { g_warning ("failed to convert language to string"); goto out; } /* create the font tag used in as a package provides */ pat = FcPatternCreate (); FcPatternAddString (pat, FC_LANG, (FcChar8 *) lang); tag = (gchar *) FcNameUnparse (pat); if (tag == NULL || tag[0] == '\0') { g_warning ("failed to create font tag: %s", lang); goto out; } /* add to array for processing in idle callback */ queue_install_fonts_tag (tag); out: if (pat != NULL) FcPatternDestroy (pat); if (tag != NULL) free (tag); }
// also handle an xlfd with %d for size? static char* makeFontOfSize(char *font, int size, char *fallback) { FcPattern *pattern; char *result; if (font[0]=='-') { char *fname; fname = fixXLFD(font, size); pattern = XftXlfdParse(fname, False, False); wfree(fname); } else { pattern = FcNameParse(font); } //FcPatternPrint(pattern); if (size > 0) { FcPatternDel(pattern, "pixelsize"); FcPatternAddDouble(pattern, "pixelsize", (double)size); } else if (size==0 && !hasProperty(pattern, "size") && !hasProperty(pattern, "pixelsize")) { FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE); } if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) { FcPatternAddString(pattern, "family", fallback); } result = FcNameUnparse(pattern); FcPatternDestroy(pattern); return result; }
map<string, string> populateHelper() { map<string, string> rtn; for (int i = 0; fontConfigFontSet != NULL && i < fontConfigFontSet->nfont; i++) { FcPattern *font = fontConfigFontSet->fonts[i]; string s = string((char *)FcNameUnparse(font)); rtn[s.substr(0, s.find(":"))] = s.substr(s.find("=")+1); } return rtn; }
Bool XftNameUnparse (XftPattern *pat, char *dest, int len) { FcChar8 *name = FcNameUnparse (pat); if (!name) return FcFalse; if (strlen ((char *) name) > len - 1) { free (name); return FcFalse; } strcpy (dest, (void *) name); free (name); return FcTrue; }
WMFont* WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style) { FcPattern *pattern; WMFont *copy; char *name; if (!font) return NULL; pattern = FcNameParse(WMGetFontName(font)); switch (style) { case WFSNormal: FcPatternDel(pattern, "weight"); FcPatternDel(pattern, "slant"); FcPatternAddString(pattern, "weight", "regular"); FcPatternAddString(pattern, "weight", "medium"); FcPatternAddString(pattern, "slant", "roman"); break; case WFSBold: FcPatternDel(pattern, "weight"); FcPatternAddString(pattern, "weight", "bold"); break; case WFSEmphasized: FcPatternDel(pattern, "slant"); FcPatternAddString(pattern, "slant", "italic"); FcPatternAddString(pattern, "slant", "oblique"); break; case WFSBoldEmphasized: FcPatternDel(pattern, "weight"); FcPatternDel(pattern, "slant"); FcPatternAddString(pattern, "weight", "bold"); FcPatternAddString(pattern, "slant", "italic"); FcPatternAddString(pattern, "slant", "oblique"); break; } name = FcNameUnparse(pattern); copy = WMCreateFont(scrPtr, name); FcPatternDestroy(pattern); wfree(name); return copy; }
/** * using fontconfig for just getting the font file name by a wanted font name and style. */ char *get_font_filename(const char *family, const char *style) { //initialize fontconfig if (!FcInit()) { throw util::Error{MSG(err) << "Failed to initialize fontconfig."}; } //FcPattern *font_pattern = FcNameParse((const unsigned char *)"DejaVu Serif:style=Book"); FcPattern *font_pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, family, nullptr); FcPatternBuild(font_pattern, FC_STYLE, FcTypeString, style, nullptr); //debug output: display above pattern as parsable string. FcChar8 *query_string = FcNameUnparse(font_pattern); log::log(MSG(info) << "Font queried: " << query_string); free(query_string); //tell fontconfig to find the best match FcResult font_match_result; FcPattern *font_match = FcFontMatch(nullptr, font_pattern, &font_match_result); /* //debug output: display matching font pattern as parsable string FcChar8 *match_string = FcNameUnparse(font_match); log::dbg2("resulting font: %s", match_string); free(match_string); */ //get attibute FC_FILE (= filename) of best-matched font FcChar8 *font_filename_tmp; if (FcPatternGetString(font_match, FC_FILE, 0, &font_filename_tmp) != FcResultMatch) { throw util::Error(MSG(err) << "Fontconfig could not provide font " << family << " " << style); } //copy the font filename because it will be freed when the pattern is destroyed. char *font_filename = util::copy((const char *)font_filename_tmp); log::log(MSG(info) << "Font file: " << font_filename); //deinitialize fontconfig. FcPatternDestroy(font_match); FcPatternDestroy(font_pattern); FcFini(); return font_filename; }
void JXFontManager::GetMonospaceFontNames ( JPtrArray<JString>* fontNames ) const { if (itsMonoFontNames != NULL) { fontNames->CopyObjects(*itsMonoFontNames, fontNames->GetCleanUpAction(), kJFalse); } else { (JXGetApplication())->DisplayBusyCursor(); fontNames->CleanOut(); fontNames->SetCompareFunction(JCompareStringsCaseInsensitive); fontNames->SetSortOrder(JOrderedSetT::kSortAscending); JPtrArray<JString> allFontNames(JPtrArrayT::kDeleteAll); allFontNames.SetCompareFunction(JCompareStringsCaseInsensitive); allFontNames.SetSortOrder(JOrderedSetT::kSortAscending); JString name; #if ENABLE_TRUE_TYPE FcFontSet* set = XftListFonts(*itsDisplay, itsDisplay->GetScreen(), FC_SPACING, FcTypeInteger, FC_MONO, NULL, FC_FAMILY, NULL); for (int i=0; i < set->nfont; i++) { FcChar8* s = FcNameUnparse(set->fonts[i]); name.Set((JCharacter*) s); // cout << "tt mono: " << name << endl; #if ONLY_STD_MONOSPACE if (!name.BeginsWith("Courier") && !name.BeginsWith("Consolas") && !name.Contains(" Mono") && name != "LucidaTypewriter") { FcStrFree(s); continue; } #endif if (IsUseless(name)) { FcStrFree(s); continue; } JBoolean isDuplicate; const JIndex index = allFontNames.GetInsertionSortIndex(&name, &isDuplicate); if (!isDuplicate) { allFontNames.InsertAtIndex(index, name); JString* n = new JString(name); assert( n != NULL ); const JBoolean ok = fontNames->InsertSorted(n, kJFalse); assert( ok ); } FcStrFree(s); } FcFontSetDestroy(set); #else for (int j=0; j<kMonospaceFontPatternCount; j++) { int nameCount; char** nameList = XListFonts(*itsDisplay, kMonospaceFontPattern[j], INT_MAX, &nameCount); if (nameList == NULL) { return; } for (int i=0; i<nameCount; i++) { const std::string s(nameList[i], strlen(nameList[i])); std::istringstream input(s); input.ignore(); // initial dash JIgnoreUntil(input, '-'); // foundry name name = JReadUntil(input, '-'); // font name if (name.IsEmpty() || name == "nil") { continue; } ConvertToPSFontName(&name); // cout << "std mono: " << name << endl; #if ONLY_STD_MONOSPACE if (name != "Clean" && name != "Fixed" && name != "Terminal" && name != "Courier" && name != "Lucidatypewriter" && name != "Profontwindows") { continue; } #endif if (IsUseless(name)) { continue; } JBoolean isDuplicate; const JIndex index = allFontNames.GetInsertionSortIndex(&name, &isDuplicate); if (!isDuplicate) { allFontNames.InsertAtIndex(index, name); XFontStruct* xfont = XLoadQueryFont(*itsDisplay, nameList[i]); if (xfont != NULL) { if (xfont->min_bounds.width == xfont->max_bounds.width) { JString* n = new JString(name); assert( n != NULL ); const JBoolean ok = fontNames->InsertSorted(n, kJFalse); assert( ok ); } XFreeFont(*itsDisplay, xfont); } } } XFreeFontNames(nameList); } #endif // save names for next time itsMonoFontNames = new JDCCPtrArray<JString>(*fontNames, JPtrArrayT::kDeleteAll); assert( itsMonoFontNames != NULL ); } }
void JXFontManager::GetFontNames ( JPtrArray<JString>* fontNames ) const { if (itsAllFontNames != NULL) { fontNames->CopyObjects(*itsAllFontNames, fontNames->GetCleanUpAction(), kJFalse); } else { fontNames->CleanOut(); fontNames->SetCompareFunction(JCompareStringsCaseInsensitive); fontNames->SetSortOrder(JOrderedSetT::kSortAscending); JString name; #if ENABLE_TRUE_TYPE FcFontSet* set = XftListFonts(*itsDisplay, itsDisplay->GetScreen(), NULL, FC_FAMILY, NULL); for (int i=0; i < set->nfont; i++) { FcChar8* s = FcNameUnparse(set->fonts[i]); name.Set((JCharacter*) s); // cout << "tt font: " << name << endl; if (!IsPostscript(name) || IsUseless(name)) { FcStrFree(s); continue; } JBoolean isDuplicate; const JIndex index = fontNames->GetInsertionSortIndex(&name, &isDuplicate); if (!isDuplicate) { fontNames->InsertAtIndex(index, name); } FcStrFree(s); } FcFontSetDestroy(set); #endif int nameCount; char** nameList = XListFonts(*itsDisplay, "-*-*-medium-r-normal-*-*-*-75-75-*-*-*-*", INT_MAX, &nameCount); if (nameList == NULL) { return; } for (int i=0; i<nameCount; i++) { const std::string s(nameList[i], strlen(nameList[i])); std::istringstream input(s); input.ignore(); // initial dash JIgnoreUntil(input, '-'); // foundry name name = JReadUntil(input, '-'); // font name if (name.IsEmpty() || name == "nil") { continue; } ConvertToPSFontName(&name); // cout << "std font: " << name << endl; if (!IsPostscript(name) || IsUseless(name)) { continue; } JBoolean isDuplicate; const JIndex index = fontNames->GetInsertionSortIndex(&name, &isDuplicate); if (!isDuplicate) { fontNames->InsertAtIndex(index, name); } } XFreeFontNames(nameList); // save names for next time itsAllFontNames = new JDCCPtrArray<JString>(*fontNames, JPtrArrayT::kDeleteAll); assert( itsAllFontNames != NULL ); } }
fz_error * pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection) { fz_error *error; FcResult fcerr; int fterr; char fontname[200]; FcPattern *searchpat; FcPattern *matchpat; FT_Face face; char *style; char *file; int index; error = initfontlibs(); if (error) return error; /* parse windows-style font name descriptors Font,Style */ /* TODO: reliable way to split style from Font-Style type names */ strlcpy(fontname, basefont, sizeof fontname); style = strchr(fontname, ','); if (style) *style++ = 0; searchpat = FcPatternCreate(); if (!searchpat) return fz_outofmem; error = fz_outofmem; if (!FcPatternAddString(searchpat, FC_FAMILY, fontname)) goto cleanup; if (collection) { if (!strcmp(collection, "Adobe-GB1")) if (!FcPatternAddString(searchpat, FC_LANG, "zh-TW")) goto cleanup; if (!strcmp(collection, "Adobe-CNS1")) if (!FcPatternAddString(searchpat, FC_LANG, "zh-CN")) goto cleanup; if (!strcmp(collection, "Adobe-Japan1")) if (!FcPatternAddString(searchpat, FC_LANG, "ja")) goto cleanup; if (!strcmp(collection, "Adobe-Japan2")) if (!FcPatternAddString(searchpat, FC_LANG, "ja")) goto cleanup; if (!strcmp(collection, "Adobe-Korea1")) if (!FcPatternAddString(searchpat, FC_LANG, "ko")) goto cleanup; } if (style) if (!FcPatternAddString(searchpat, FC_STYLE, style)) goto cleanup; if (font->flags & FD_SERIF) FcPatternAddString(searchpat, FC_FAMILY, "serif"); else FcPatternAddString(searchpat, FC_FAMILY, "sans-serif"); if (font->flags & FD_ITALIC) FcPatternAddString(searchpat, FC_STYLE, "Italic"); if (font->flags & FD_FORCEBOLD) FcPatternAddString(searchpat, FC_STYLE, "Bold"); if (!FcPatternAddBool(searchpat, FC_OUTLINE, 1)) goto cleanup; file = FcNameUnparse(searchpat); pdf_logfont("fontconfig0 %s\n", file); free(file); fcerr = FcResultMatch; /* FcDefaultSubstitute(searchpat); */ FcConfigSubstitute(fclib, searchpat, FcMatchPattern); file = FcNameUnparse(searchpat); pdf_logfont("fontconfig1 %s\n", file); free(file); matchpat = FcFontMatch(fclib, searchpat, &fcerr); if (fcerr != FcResultMatch) return fz_throw("fontconfig could not find font %s", basefont); fcerr = FcPatternGetString(matchpat, FC_FAMILY, 0, (FcChar8**)&file); if (file && strcmp(fontname, file)) font->substitute = 1; fcerr = FcPatternGetString(matchpat, FC_STYLE, 0, (FcChar8**)&file); if (file && style && strcmp(style, file)) font->substitute = 1; fcerr = FcPatternGetString(matchpat, FC_FILE, 0, (FcChar8**)&file); if (fcerr != FcResultMatch) return fz_throw("fontconfig could not find font %s", basefont); index = 0; fcerr = FcPatternGetInteger(matchpat, FC_INDEX, 0, &index); pdf_logfont("load font file %s %d\n", file, index); fterr = FT_New_Face(ftlib, file, index, &face); if (fterr) { FcPatternDestroy(matchpat); FcPatternDestroy(searchpat); return fz_throw("freetype could not load font file '%s': %s", file, pdf_fterrorstring(fterr)); } FcPatternDestroy(matchpat); FcPatternDestroy(searchpat); font->ftface = face; return nil; cleanup: FcPatternDestroy(searchpat); return error; }
/** * grx_font_load_full: * @family: (nullable): the font family name or %NULL * @size: the preferred size in points or -1 for any size * @dpi: the screen resolution or -1 to ignore dpi * @weight: the font weight (e.g. bold) or -1 for any weight * @slant: the font slant (e.g. italic) or -1 for any slant * @width: the font width (e.g. narrow) or -1 for any width * @monospace: set to %TRUE to prefer a monospace font * @lang: (nullable): a RFC-3066-style language code or %NULL * @script: (nullable): an ISO 15924 script code or %NULL * @err: pointer to hold an error * * Loads the font that best matches the parameters. * * Uses fontconfig for font matching. * * Returns: (transfer full) (nullable): the font or %NULL if there was an error */ GrxFont *grx_font_load_full(const gchar *family, gint size, gint dpi, GrxFontWeight weight, GrxFontSlant slant, GrxFontWidth width, gboolean monospace, const gchar *lang, const gchar *script, GError **err) { FcPattern *pattern, *match; FcResult result; GrxFont *font; FcChar8 *file; if (!FcInit()) { g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR, "Failed to init fontconfig"); return NULL; } pattern = FcPatternCreate(); FcPatternAddBool(pattern, FC_SCALABLE, FcFalse); FcPatternAddBool(pattern, FC_OUTLINE, FcFalse); FcPatternAddString(pattern, FC_FONTFORMAT, (FcChar8 *)"PCF"); if (family) { FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *)family); } if (size >= 0) { FcPatternAddDouble(pattern, FC_SIZE, size); } if (dpi >= 0) { FcPatternAddDouble(pattern, FC_DPI, dpi); } switch (weight) { case GRX_FONT_WEIGHT_REGULAR: FcPatternAddInteger(pattern, FC_WEIGHT, 80); break; case GRX_FONT_WEIGHT_BOLD: FcPatternAddInteger(pattern, FC_WEIGHT, 200); break; } switch (slant) { case GRX_FONT_SLANT_REGULAR: FcPatternAddInteger(pattern, FC_SLANT, 0); break; case GRX_FONT_SLANT_ITALIC: FcPatternAddInteger(pattern, FC_SLANT, 100); break; } switch (width) { case GRX_FONT_WIDTH_NARROW: FcPatternAddInteger(pattern, FC_WIDTH, 75); break; case GRX_FONT_WIDTH_REGULAR: FcPatternAddInteger(pattern, FC_WIDTH, 100); break; case GRX_FONT_WIDTH_WIDE: FcPatternAddInteger(pattern, FC_WIDTH, 125); break; } if (monospace) { FcPatternAddInteger(pattern, FC_SPACING, 100); } if (lang) { FcPatternAddString(pattern, FC_LANG, (FcChar8 *)lang); } if (script) { FcPatternAddCharSet(pattern, FC_CHARSET, script_to_charset(script)); } { FcChar8 *pattern_str; pattern_str = FcNameUnparse(pattern); g_debug("searching for pattern: %s", pattern_str); free(pattern_str); } FcConfigSubstitute(NULL, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); match = FcFontMatch(NULL, pattern, &result); if (!match) { // TODO: use result for better error g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR, "Failed to find match"); FcPatternDestroy(pattern); return NULL; } if (FcPatternGetString(match, FC_FILE, 0, &file) != FcResultMatch) { g_set_error_literal(err, GRX_ERROR, GRX_ERROR_FONT_ERROR, "Failed to get file name"); FcPatternDestroy(match); FcPatternDestroy(pattern); return NULL; } font = grx_font_load_from_file((gchar *)file, err); FcPatternDestroy(match); FcPatternDestroy(pattern); return font; }
static void SearchFont(VALUE rbFilePathOrName, VALUE* volatile rbRealFilePath, int* ttcIndex) { *rbRealFilePath = Qnil; if (ttcIndex != NULL) { *ttcIndex = -1; } *rbRealFilePath = strb_GetCompletePath(rbFilePathOrName, false); if (!NIL_P(*rbRealFilePath)) { return; } volatile VALUE rbFontNameSymbol = ID2SYM(rb_intern_str(rbFilePathOrName)); FontFileInfo* info = fontFileInfos; while (info) { if (info->rbFontNameSymbol == rbFontNameSymbol) { *rbRealFilePath = rb_str_new2(rb_id2name(SYM2ID(info->rbFileNameSymbol))); #ifdef WIN32 volatile VALUE rbTemp = rb_str_new2(rb_id2name(SYM2ID(rbWindowsFontDirPathSymbol))); *rbRealFilePath = rb_str_concat(rb_str_cat2(rbTemp, "\\"), *rbRealFilePath); #endif if (ttcIndex != NULL) { *ttcIndex = info->ttcIndex; } return; } info = info->next; } #ifdef HAVE_FONTCONFIG_FONTCONFIG_H if (!FcInit()) { FcFini(); rb_raise(strb_GetStarRubyErrorClass(), "can't initialize fontconfig library"); return; } int nameLength = RSTRING_LEN(rbFilePathOrName) + 1; char name[nameLength]; strncpy(name, StringValueCStr(rbFilePathOrName), nameLength); char* delimiter = strchr(name, ','); char* style = NULL; if (delimiter) { *delimiter = '\0'; style = delimiter + 1; char* nameTail = delimiter - 1; while (*nameTail == ' ') { *nameTail = '\0'; nameTail--; } while (*style == ' ') { style++; } } FcPattern* pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, name, NULL); if (style && 0 < strlen(style)) { FcPatternAddString(pattern, FC_STYLE, (FcChar8*)style); } FcObjectSet* objectSet = FcObjectSetBuild(FC_FAMILY, FC_FILE, NULL); FcFontSet* fontSet = FcFontList(NULL, pattern, objectSet); if (objectSet) { FcObjectSetDestroy(objectSet); } if (pattern) { FcPatternDestroy(pattern); } if (fontSet) { for (int i = 0; i < fontSet->nfont; i++) { FcChar8* fileName = NULL; if (FcPatternGetString(fontSet->fonts[i], FC_FILE, 0, &fileName) == FcResultMatch) { FcChar8* fontName = FcNameUnparse(fontSet->fonts[i]); *rbRealFilePath = rb_str_new2((char*)fileName); volatile VALUE rbFontName = rb_str_new2((char*)fontName); free(fontName); fontName = NULL; if (ttcIndex != NULL && strchr(StringValueCStr(rbFontName), ',')) { *ttcIndex = 0; } } } FcFontSetDestroy(fontSet); } FcFini(); if (!NIL_P(*rbRealFilePath)) { return; } #endif return; }