static gboolean language_has_font (const gchar *locale) { const FcCharSet *charset; FcPattern *pattern; FcObjectSet *object_set; FcFontSet *font_set; gchar *language_code; gboolean is_displayable; is_displayable = FALSE; pattern = NULL; object_set = NULL; font_set = NULL; if (!gdm_parse_language_name (locale, &language_code, NULL, NULL, NULL)) return FALSE; charset = FcLangGetCharSet ((FcChar8 *) language_code); if (!charset) { /* fontconfig does not know about this language */ is_displayable = TRUE; } else { /* see if any fonts support rendering it */ pattern = FcPatternBuild (NULL, FC_LANG, FcTypeString, language_code, NULL); if (pattern == NULL) goto done; object_set = FcObjectSetCreate (); if (object_set == NULL) goto done; font_set = FcFontList (NULL, pattern, object_set); if (font_set == NULL) goto done; is_displayable = (font_set->nfont > 0); } done: if (font_set != NULL) FcFontSetDestroy (font_set); if (object_set != NULL) FcObjectSetDestroy (object_set); if (pattern != NULL) FcPatternDestroy (pattern); g_free (language_code); return is_displayable; }
/** * 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; }
std::string FontConfig::match_font(const std::string &typeface_name, const FontDescription &desc) const { FcPattern * fc_pattern = nullptr; FcPattern * fc_match = nullptr; try { int weight = static_cast<int>(desc.get_weight()); // Build font matching pattern. fc_pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, typeface_name.c_str(), FC_PIXEL_SIZE, FcTypeDouble, (double)std::abs(desc.get_height()), FC_WEIGHT, FcTypeInteger, (weight > 0) ? (int)(weight * (FC_WEIGHT_HEAVY / 900.0)) : FC_WEIGHT_NORMAL, FC_SLANT, FcTypeInteger, (desc.get_style() == clan::FontStyle::italic) ? FC_SLANT_ITALIC : ((desc.get_style() == clan::FontStyle::oblique) ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN), FC_SPACING, FcTypeInteger, FC_PROPORTIONAL, (char*) nullptr ); if (!fc_pattern) { throw Exception("CL_FontConfig: Building FontConfig pattern failed."); } // Execute any needed param substitutions required by the system config. if (FcTrue != FcConfigSubstitute(fc_config, fc_pattern, FcMatchPattern)) { throw Exception("CL_FontConfig: Font config substitutions failed."); } // Supply default values for underspecified font patterns. Never fails. FcDefaultSubstitute(fc_pattern); // Find best match for pattern and extract filename. FcResult match_result; // Doesn't appear to be actually updated. fc_match = FcFontMatch(fc_config, fc_pattern, &match_result); FcChar8 * fc_font_file_path = nullptr; if (FcResultMatch != FcPatternGetString(fc_match, FC_FILE, 0, &fc_font_file_path)) { throw Exception("CL_FontConfig: Could not resolve font pattern to a font file."); } // Release resources and return results. std::string cl_font_file_path((char*)fc_font_file_path); FcPatternDestroy(fc_match); FcPatternDestroy(fc_pattern); return cl_font_file_path; } catch (...) { // If any exceptions thrown, ensure fontconfig resources are released. if (fc_match) FcPatternDestroy(fc_match); if (fc_pattern) FcPatternDestroy(fc_pattern); throw; } }
GeeArrayList * FcListFonts(gchar * family_name) { int i; FcPattern * pattern; FcFontSet * fontset; FcObjectSet * objectset = 0; GeeArrayList * fontlist = gee_array_list_new(G_TYPE_OBJECT, NULL, NULL, NULL, NULL, NULL); g_assert(FcInit()); if (family_name) pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, family_name, NULL); else pattern = FcNameParse((FcChar8 *) ":"); objectset = FcObjectSetBuild (FC_FILE, FC_INDEX, FC_FAMILY, FC_STYLE, FC_SLANT, FC_WEIGHT, FC_WIDTH, FC_SPACING, NULL); fontset = FcFontList(NULL, pattern, objectset); for (i = 0; i < fontset->nfont; i++) { FontConfigFont * font = font_config_font_new(); get_font_details_from_pattern(font, fontset->fonts[i]); gee_abstract_collection_add((GeeAbstractCollection *) fontlist, font); } if (objectset) FcObjectSetDestroy(objectset); if (pattern) FcPatternDestroy(pattern); if (fontset) FcFontSetDestroy(fontset); return fontlist; }
void *gp_enumerate_fonts_init(gs_memory_t *mem) { #ifdef HAVE_FONTCONFIG unix_fontenum_t *state; FcPattern *pat; FcObjectSet *os; state = (unix_fontenum_t *)malloc(sizeof(unix_fontenum_t)); if (state == NULL) return NULL; /* Failed to allocate state */ state->index = 0; state->fc = NULL; state->font_list = NULL; /* Load the fontconfig library */ state->fc = FcInitLoadConfigAndFonts(); if (state->fc == NULL) { free(state); state = NULL; dlprintf("destroyed state - fontconfig init failed"); return NULL; /* Failed to open fontconfig library */ } /* load the font set that we'll iterate over */ pat = FcPatternBuild(NULL, FC_OUTLINE, FcTypeBool, 1, FC_SCALABLE, FcTypeBool, 1, NULL); os = FcObjectSetBuild(FC_FILE, FC_OUTLINE, FC_FAMILY, FC_WEIGHT, FC_SLANT, NULL); state->font_list = FcFontList(0, pat, os); FcPatternDestroy(pat); FcObjectSetDestroy(os); if (state->font_list == NULL) { free(state); state = NULL; return NULL; /* Failed to generate font list */ } return (void *)state; #else return NULL; #endif }
static inline XftFont * get_font(Display *xdisplay, FT_Face face, gint size, FcCharSet *charset) { FcPattern *pattern; XftFont *font; int screen = DefaultScreen (xdisplay); pattern = FcPatternBuild(NULL, FC_FT_FACE, FcTypeFTFace, face, FC_PIXEL_SIZE, FcTypeDouble, (double)size, NULL); if (charset) FcPatternAddCharSet (pattern, "charset", charset); FcConfigSubstitute (NULL, pattern, FcMatchPattern); XftDefaultSubstitute (xdisplay, screen, pattern); font = XftFontOpenPattern(xdisplay, pattern); return font; }
static int find_font(info_rec* info, char* family, char* path) { FcPattern* pattern; FcPattern* matchedPattern; FcResult result; FcChar8* s; pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, family, (char*) NULL); if (pattern == NULL) return YUV_fontconfig; if (FcConfigSubstitute(info->config, pattern, FcMatchPattern) != FcTrue) return YUV_fontconfig; FcDefaultSubstitute(pattern); matchedPattern = FcFontMatch(info->config, pattern, &result); FcPatternDestroy(pattern); if (FcPatternGetString(matchedPattern, FC_FILE, 0, &s) != FcResultMatch) return YUV_fontconfig; strcpy(path, (char*)s); FcPatternDestroy(matchedPattern); return YUV_OK; }
std::string PdfFontCache::GetFontConfigFontPath( FcConfig* pConfig, const char* pszFontName, bool bBold, bool bItalic ) { FcPattern* pattern; FcPattern* matched; FcResult result = FcResultMatch; FcValue v; std::string sPath; // Build a pattern to search using fontname, bold and italic pattern = FcPatternBuild (0, FC_FAMILY, FcTypeString, pszFontName, FC_WEIGHT, FcTypeInteger, (bBold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM), FC_SLANT, FcTypeInteger, (bItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN), static_cast<char*>(0)); FcDefaultSubstitute( pattern ); if( !FcConfigSubstitute( pConfig, pattern, FcMatchFont ) ) { FcPatternDestroy( pattern ); return sPath; } matched = FcFontMatch( pConfig, pattern, &result ); if( result != FcResultNoMatch ) { result = FcPatternGet( matched, FC_FILE, 0, &v ); sPath = reinterpret_cast<const char*>(v.u.s); #ifdef PODOFO_VERBOSE_DEBUG printf("Got Font %s for for %s\n", sPath.c_str(), pszFontname ); #endif // PODOFO_DEBUG } FcPatternDestroy( pattern ); FcPatternDestroy( matched ); return sPath; }
static void setup_font_sample(GtkWidget* darea, Antialiasing antialiasing, Hinting hinting) { const char* string1 = "abcfgop AO "; const char* string2 = "abcfgop"; XftColor black, white; XRenderColor rendcolor; Display* xdisplay = gdk_x11_get_default_xdisplay(); #if GTK_CHECK_VERSION (3, 0, 0) Colormap xcolormap = DefaultColormap(xdisplay, 0); #else GdkColormap* colormap = gdk_rgb_get_colormap(); Colormap xcolormap = GDK_COLORMAP_XCOLORMAP(colormap); #endif #if GTK_CHECK_VERSION (3, 0, 0) GdkVisual* visual = gdk_visual_get_system (); #else GdkVisual* visual = gdk_colormap_get_visual(colormap); #endif Visual* xvisual = GDK_VISUAL_XVISUAL(visual); FcPattern* pattern; XftFont* font1; XftFont* font2; XGlyphInfo extents1 = { 0 }; XGlyphInfo extents2 = { 0 }; #if !GTK_CHECK_VERSION (3, 0, 0) GdkPixmap* pixmap; #endif XftDraw* draw; GdkPixbuf* tmp_pixbuf; GdkPixbuf* pixbuf; int width, height; int ascent, descent; pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "Serif", FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN, FC_SIZE, FcTypeDouble, 18., NULL); font1 = open_pattern (pattern, antialiasing, hinting); FcPatternDestroy (pattern); pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "Serif", FC_SLANT, FcTypeInteger, FC_SLANT_ITALIC, FC_SIZE, FcTypeDouble, 20., NULL); font2 = open_pattern (pattern, antialiasing, hinting); FcPatternDestroy (pattern); ascent = 0; descent = 0; if (font1) { XftTextExtentsUtf8 (xdisplay, font1, (unsigned char*) string1, strlen (string1), &extents1); ascent = MAX (ascent, font1->ascent); descent = MAX (descent, font1->descent); } if (font2) { XftTextExtentsUtf8 (xdisplay, font2, (unsigned char*) string2, strlen (string2), &extents2); ascent = MAX (ascent, font2->ascent); descent = MAX (descent, font2->descent); } width = extents1.xOff + extents2.xOff + 4; height = ascent + descent + 2; #if !GTK_CHECK_VERSION (3, 0, 0) pixmap = gdk_pixmap_new (NULL, width, height, visual->depth); #endif #if GTK_CHECK_VERSION (3, 0, 0) draw = XftDrawCreate (xdisplay, GDK_WINDOW_XID (gdk_screen_get_root_window (gdk_screen_get_default ())), xvisual, xcolormap); #else draw = XftDrawCreate (xdisplay, GDK_DRAWABLE_XID (pixmap), xvisual, xcolormap); #endif rendcolor.red = 0; rendcolor.green = 0; rendcolor.blue = 0; rendcolor.alpha = 0xffff; XftColorAllocValue(xdisplay, xvisual, xcolormap, &rendcolor, &black); rendcolor.red = 0xffff; rendcolor.green = 0xffff; rendcolor.blue = 0xffff; rendcolor.alpha = 0xffff; XftColorAllocValue(xdisplay, xvisual, xcolormap, &rendcolor, &white); XftDrawRect(draw, &white, 0, 0, width, height); if (font1) { XftDrawStringUtf8(draw, &black, font1, 2, 2 + ascent, (unsigned char*) string1, strlen(string1)); } if (font2) { XftDrawStringUtf8(draw, &black, font2, 2 + extents1.xOff, 2 + ascent, (unsigned char*) string2, strlen(string2)); } XftDrawDestroy(draw); if (font1) { XftFontClose(xdisplay, font1); } if (font2) { XftFontClose(xdisplay, font2); } #if GTK_CHECK_VERSION (3, 0, 0) tmp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE,8, width, height); #else tmp_pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, colormap, 0, 0, 0, 0, width, height); #endif pixbuf = gdk_pixbuf_scale_simple(tmp_pixbuf, 1 * width, 1 * height, GDK_INTERP_TILES); #if !GTK_CHECK_VERSION (3, 0, 0) g_object_unref(pixmap); #endif g_object_unref(tmp_pixbuf); g_object_set_data_full(G_OBJECT(darea), "sample-pixbuf", pixbuf, (GDestroyNotify) g_object_unref); #if GTK_CHECK_VERSION (3, 0, 0) gtk_widget_set_size_request (GTK_WIDGET(darea), width + 2, height + 2); g_signal_connect(darea, "draw", G_CALLBACK(sample_draw), NULL); #else g_signal_connect(darea, "size_request", G_CALLBACK(sample_size_request), NULL); g_signal_connect(darea, "expose_event", G_CALLBACK(sample_expose), NULL); #endif }
/** * Init and load font **/ OpenGLFont::OpenGLFont(RenderOpenGL* render, string name, Mod* mod, float size) { int error; // Basics this->pmpl = new OpenGLFont_Implementation(); this->render = render; this->size = size; // Init freetype // TODO: Should we share the tf ptr between OpenGLFont instances error = FT_Init_FreeType(&this->pmpl->ft); if (error) { reportFatalError("Freetype: Unable to init library."); } // On Linux, the system font is found using fontconfig #if defined(__linux__) FcConfig* config = FcInitLoadConfigAndFonts(); FcPattern* pat = FcPatternBuild( NULL, FC_FAMILY, FcTypeString, reinterpret_cast<const char*>(name.c_str()), NULL ); FcConfigSubstitute(config, pat, FcMatchPattern); FcDefaultSubstitute(pat); FcResult result; FcPattern* font = FcFontMatch(config, pat, &result); if (font == NULL) { reportFatalError("Fontconfig: Unable to find font " + name); } FcChar8* filename = NULL; if (FcPatternGetString(font, FC_FILE, 0, &filename) != FcResultMatch) { reportFatalError("Fontconfig: No filename in fontconfig match"); } error = FT_New_Face(this->pmpl->ft, reinterpret_cast<const char*>(filename), 0, &this->pmpl->face); FcPatternDestroy(font); FcPatternDestroy(pat); #else // All other systems use a file in the cr/ mod Sint64 len; name.append(".ttf"); this->pmpl->buf = mod->loadBinary(name, &len); if (this->pmpl->buf == NULL) { reportFatalError("Freetype: Unable to load data"); } error = FT_New_Memory_Face(this->pmpl->ft, (const FT_Byte *) this->pmpl->buf, (FT_Long)len, 0, &this->pmpl->face); #endif // Handle errors if (error == FT_Err_Unknown_File_Format) { reportFatalError("Freetype: Unsupported font format"); } else if (error) { reportFatalError("Freetype: Unable to load font"); } // Set character size error = FT_Set_Char_Size(this->pmpl->face, 0, size * 64, 72, 72); if (error) { reportFatalError("Freetype: Unable to load font size"); } }
void ScreenPainter::drawGlyph(const GlyphLayout gl) { bool showControls = (m_item->doc()->guidesPrefs().showControls) && (gl.glyph == font().char2CMap(QChar(' ')) || gl.glyph >= ScFace::CONTROL_GLYPHS); #if CAIRO_HAS_FC_FONT if (m_painter->fillMode() == 1 && m_painter->maskMode() <= 0 && !showControls) { m_painter->save(); setupState(false); cairo_t* cr = m_painter->context(); double r, g, b; m_painter->brush().getRgbF(&r, &g, &b); cairo_set_source_rgba(cr, r, g, b, m_painter->brushOpacity()); m_painter->setRasterOp(m_painter->blendModeFill()); if (m_fontPath != font().fontFilePath() || m_faceIndex != font().faceIndex() || m_cairoFace == NULL) { m_fontPath = font().fontFilePath(); m_faceIndex = font().faceIndex(); // A very ugly hack as we can’t use the font().ftFace() because // Scribus liberally calls FT_Set_CharSize() with all sorts of // crazy values, breaking any subsequent call to the layout // painter. FIXME: drop the FontConfig dependency here once // Scribus font handling code is made sane! FcPattern *pattern = FcPatternBuild(NULL, FC_FILE, FcTypeString, QFile::encodeName(font().fontFilePath()).data(), FC_INDEX, FcTypeInteger, font().faceIndex(), NULL); m_cairoFace = cairo_ft_font_face_create_for_pattern(pattern); FcPatternDestroy(pattern); } cairo_set_font_face(cr, m_cairoFace); cairo_set_font_size(cr, fontSize()); cairo_scale(cr, gl.scaleH, gl.scaleV); cairo_glyph_t glyph = { gl.glyph, 0, 0 }; cairo_show_glyphs(cr, &glyph, 1); m_painter->restore(); return; } #endif m_painter->save(); setupState(false); bool fr = m_painter->fillRule(); m_painter->setFillRule(false); uint gid = gl.glyph; if (showControls) { bool stroke = false; if (gid >= ScFace::CONTROL_GLYPHS) gid -= ScFace::CONTROL_GLYPHS; else gid = 32; QTransform chma, chma4; FPointArray outline; if (gid == SpecialChars::TAB.unicode()) { outline = m_item->doc()->symTab.copy(); chma4.translate(gl.xadvance - fontSize() * gl.scaleH * 0.7, -fontSize() * gl.scaleV * 0.5); } else if (gid == SpecialChars::COLBREAK.unicode()) { outline = m_item->doc()->symNewCol.copy(); chma4.translate(0, -fontSize() * gl.scaleV * 0.6); } else if (gid == SpecialChars::FRAMEBREAK.unicode()) { outline = m_item->doc()->symNewFrame.copy(); chma4.translate(0, -fontSize() * gl.scaleV * 0.6); } else if (gid == SpecialChars::PARSEP.unicode()) { outline = m_item->doc()->symReturn.copy(); chma4.translate(0, -fontSize() * gl.scaleV * 0.8); } else if (gid == SpecialChars::LINEBREAK.unicode()) { outline = m_item->doc()->symNewLine.copy(); chma4.translate(0, -fontSize() * gl.scaleV * 0.4); } else if (gid == SpecialChars::NBSPACE.unicode() || gid == 32) { stroke = (gid == 32); outline = m_item->doc()->symNonBreak.copy(); chma4.translate(0, -fontSize() * gl.scaleV * 0.4); } else if (gid == SpecialChars::NBHYPHEN.unicode()) { outline = font().glyphOutline(font().char2CMap(QChar('-')), fontSize()); chma4.translate(0, -fontSize() * gl.scaleV); } else if (gid == SpecialChars::SHYPHEN.unicode()) { outline.resize(0); outline.addQuadPoint(0, -10, 0, -10, 0, -6, 0, -6); stroke = true; } else if (gid == SpecialChars::OBJECT.unicode()) { //for showing marks entries as control chars outline.resize(0); outline.addQuadPoint(0, -8, 1, -8, 0, -6, 1, -6); stroke = true; } else // ??? { outline.resize(0); outline.addQuadPoint(0, -10, 0, -10, 0, -9, 0, -9); outline.addQuadPoint(0, -9, 0, -9, 1, -9, 1, -9); outline.addQuadPoint(1, -9, 1, -9, 1, -10, 1, -10); outline.addQuadPoint(1, -10, 1, -10, 0, -10, 0, -10); } chma.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0); outline.map(chma * chma4); m_painter->setupPolygon(&outline, true); QColor oldBrush = m_painter->brush(); // FIXME /* p->setBrush( (flags & ScLayout_SuppressSpace) ? Qt::green : PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor);*/ m_painter->setBrush(PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor); if (stroke) { QColor tmp = m_painter->pen(); m_painter->setStrokeMode(1); m_painter->setPen(m_painter->brush(), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); m_painter->setLineWidth(fontSize() * gl.scaleV / 20.0); m_painter->strokePath(); m_painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); } else { m_painter->setFillMode(1); m_painter->fillPath(); } m_painter->setBrush(oldBrush); } else { m_painter->translate(0, -(fontSize() * gl.scaleV)); double scaleH = gl.scaleH * fontSize() / 10.0; double scaleV = gl.scaleV * fontSize() / 10.0; m_painter->scale(scaleH, scaleV); FPointArray outline = font().glyphOutline(gid); m_painter->setupPolygon(&outline, true); if (outline.size() > 3) m_painter->fillPath(); } m_painter->setFillRule(fr); m_painter->restore(); }
/* 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; }
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); }
static XftFont *gui_find_font(winlist_t *win, FcChar32 ucs4) { unsigned int i; int weight, slant, scalable; double font_size; FcFontSet *fontset; XftFont *font = NULL; /* 缺字列表有這個字,那就不用再找啦 */ if (FcCharSetHasChar(gui->missing_chars, ucs4)) { return NULL; } /* 找出 Cache 相符的字型 */ for (i=0 ; i < gui->num_fonts ; i++) { XftPatternGetDouble(gui->xftfonts[i]->pattern, XFT_PIXEL_SIZE, 0, &font_size); if ((int)font_size == win->font_size && FcCharSetHasChar(gui->xftfonts[i]->charset, ucs4)) { return gui->xftfonts[i]; } } /* 列出所有可能的字型 */ FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_CHARSET, NULL); /* 只要標準、非斜體、可縮放字型即可 */ FcPattern *listpat = FcPatternBuild(NULL, FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN, FC_SCALABLE, FcTypeBool, FcTrue, NULL); fontset = FcFontList(NULL, listpat, os); FcPatternDestroy(listpat); FcObjectSetDestroy(os); for (i=0; i< fontset->nfont; i++) { FcPattern *pat = fontset->fonts[i]; FcCharSet *fcs = NULL; if (FcPatternGetCharSet(pat, FC_CHARSET, 0, &fcs) != FcResultMatch) continue; if (!FcCharSetHasChar(fcs, ucs4)) continue; FcResult res; FcPattern *mpat = FcFontMatch(0, pat, &res); if (!mpat) continue; XftPatternAddDouble(mpat, XFT_PIXEL_SIZE, (double)win->font_size); XftFont *chkfont = XftFontOpenPattern(gui->display, mpat); if (chkfont) { gui->num_fonts ++; gui->xftfonts = (XftFont **)oxim_realloc(gui->xftfonts, gui->num_fonts * sizeof(XftFont *)); if (!gui->xftfonts) { FcPatternDestroy(mpat); continue; } gui->xftfonts[gui->num_fonts - 1] = chkfont; font = chkfont; break; } else { FcPatternDestroy(mpat); } } FcFontSetDestroy(fontset); if (!font) FcCharSetAddChar(gui->missing_chars, ucs4); 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; }
bool sui_font_fromfamily(sui_font *font, sui_library *l, char **error, const char *family) { return sui_font_fromfc(font, l, error, FcPatternBuild(0, FC_FAMILY, FcTypeString, family, (char*)0)); }