static void set_glyphs (PangoFont *font, const gunichar *wcs, gulong *tags, glong n_glyphs, PangoOTBuffer *buffer, gboolean process_zwj) { gint i; PangoFcFont *fc_font; g_assert (font); fc_font = PANGO_FC_FONT (font); for (i = 0; i < n_glyphs; i++) { guint glyph; if (pango_is_zero_width (wcs[i]) && (!process_zwj || wcs[i] != 0x200D)) glyph = PANGO_GLYPH_EMPTY; else { glyph = pango_fc_font_get_glyph (fc_font, wcs[i]); if (!glyph) glyph = PANGO_GET_UNKNOWN_GLYPH ( wcs[i]); } pango_ot_buffer_add_glyph (buffer, glyph, tags[i], i); } }
/* Finds the #GnomeFont corresponding to a #PangoFont. This differs * from gnome_font_face_find_closest_from_pango_font() because it * requires a PangoFcFont not an arbitrary font and works off the * filename rather than making guesses about name correspondences. */ static GnomeFont * font_from_pango_font (PangoFont *font) { PangoFcFont *fcfont; FcChar8 *filename; gint id; gdouble size; FcResult result; if (!PANGO_IS_FC_FONT (font)) return NULL; fcfont = PANGO_FC_FONT (font); if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, &filename) != FcResultMatch) return NULL; if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &id) != FcResultMatch) return NULL; /* Look for either FC_SIZE or FC_PIXEL_SIZE, since the resolution is 72, * they are the same thing. */ result = FcPatternGetDouble (fcfont->font_pattern, FC_SIZE, 0, &size); if (result == FcResultNoMatch) result = FcPatternGetDouble (fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size); if (result != FcResultMatch) return NULL; return gnome_font_find_from_filename (filename, id, size); }
static void gimp_text_render_vectors (PangoFont *font, PangoGlyph pango_glyph, FT_Int32 flags, FT_Matrix *trafo, gint x, gint y, RenderContext *context) { const FT_Outline_Funcs outline_funcs = { moveto, lineto, conicto, cubicto, 0, 0 }; FT_Face face; FT_Glyph glyph; face = pango_fc_font_lock_face (PANGO_FC_FONT (font)); FT_Load_Glyph (face, (FT_UInt) pango_glyph, flags); FT_Get_Glyph (face->glyph, &glyph); if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_OutlineGlyph outline_glyph = (FT_OutlineGlyph) glyph; context->offset_x = (gdouble) x / PANGO_SCALE; context->offset_y = (gdouble) y / PANGO_SCALE; FT_Outline_Decompose (&outline_glyph->outline, &outline_funcs, context); } FT_Done_Glyph (glyph); pango_fc_font_unlock_face (PANGO_FC_FONT (font)); }
static boolean pango_textlayout(textpara_t * para, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, para->fontname) != 0 || fontsize != para->fontsize) { fontname = para->fontname; fontsize = para->fontsize; pango_font_description_free (desc); if (para->postscript_alias) { psfnt = fnt = gv_fmap[para->postscript_alias->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (para->postscript_alias); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((para->font) && (flags = para->font->flags)) { char* markup = N_NEW(strlen(para->str) + sizeof(FULL_MARKUP), char); strcpy(markup,"<span"); if (flags & HTML_BF) strcat(markup," weight=\"bold\""); if (flags & HTML_IF) strcat(markup," style=\"italic\""); if (flags & HTML_UL) strcat(markup," underline=\"single\""); strcat (markup,">"); if (flags & HTML_SUP) strcat(markup,"<sup>"); if (flags & HTML_SUB) strcat(markup,"<sub>"); strcat (markup,para->str); if (flags & HTML_SUB) strcat(markup,"</sub>"); if (flags & HTML_SUP) strcat(markup,"</sup>"); strcat (markup,"</span>"); if (!pango_parse_markup (markup, -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = para->str; attrs = NULL; } free (markup); }
/* analysis->shape_engine has the PangoEngine... */ static void indic_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, gint length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRuleset *gsub_ruleset, *gpos_ruleset; PangoOTBuffer *buffer; glong i, n_chars, n_glyphs; gulong *tags = NULL; gunichar *wc_in = NULL, *wc_out = NULL; glong *utf8_offsets = NULL; glong *indices = NULL; IndicEngineFc *indic_shape_engine = NULL; const PangoIndicInfo *indic_info = NULL; MPreFixups *mprefixups; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; indic_shape_engine = (IndicEngineFc *) engine; indic_info = indic_shape_engine->indicInfo; wc_in = expand_text (text, length, &utf8_offsets, &n_chars); n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_info->classTable, NULL, NULL, NULL, NULL); wc_out = g_new (gunichar, n_glyphs); indices = g_new (glong, n_glyphs); tags = g_new (gulong, n_glyphs); n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_info->classTable, wc_out, indices, tags, &mprefixups); pango_glyph_string_set_size (glyphs, n_glyphs); buffer = pango_ot_buffer_new (fc_font); set_glyphs(font, wc_out, tags, n_glyphs, buffer, (indic_info->classTable->scriptFlags & SF_PROCESS_ZWJ) != 0); /* do gsub processing */ gsub_ruleset = get_gsub_ruleset (face, indic_info); if (gsub_ruleset != NULL) pango_ot_ruleset_substitute (gsub_ruleset, buffer); /* Fix pre-modifiers for some scripts before base consonant */ if (mprefixups) { indic_mprefixups_apply (mprefixups, buffer); indic_mprefixups_free (mprefixups); } /* do gpos processing */ gpos_ruleset = get_gpos_ruleset (face, indic_info); if (gpos_ruleset != NULL) pango_ot_ruleset_position (gpos_ruleset, buffer); pango_ot_buffer_output (buffer, glyphs); /* Get the right log_clusters values */ for (i = 0; i < glyphs->num_glyphs; i += 1) glyphs->log_clusters[i] = indices[glyphs->log_clusters[i]]; pango_fc_font_unlock_face (fc_font); pango_ot_buffer_destroy (buffer); g_free (tags); g_free (indices); g_free (wc_out); g_free (wc_in); g_free (utf8_offsets); }
static void khmer_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, int length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRuleset *ruleset; PangoOTBuffer *buffer; glong n_chars; gunichar *wcs; const char *p; int i; glong syllable; KhmerCharClass charClass; glong cursor = 0; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); p = text; /* This loop only exits when we reach the end of a run, which may contain * several syllables. */ while (cursor < n_chars) { /* write a pre vowel or the pre part of a split vowel first * and look out for coeng + ro. RO is the only vowel of type 2, and * therefore the only one that requires saving space before the base. */ glong coengRo = -1; /* There is no Coeng Ro, if found this value will change */ syllable = find_syllable (wcs, cursor, n_chars); for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); /* if a split vowel, write the pre part. In Khmer the pre part * is the same for all split vowels, same glyph as pre vowel C_VOWEL_E */ if (charClass & CF_SPLIT_VOWEL) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_VOWEL_E), pref_p, p - text); break; /* there can be only one vowel */ } /* if a vowel with pos before write it out */ if (charClass & CF_POS_BEFORE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text); break; /* there can be only one vowel */ } /* look for coeng + ro and remember position * works because coeng + ro is always in front of a vowel (if there is a vowel) * and because CC_CONSONANT2 is enough to identify it, as it is the only consonant * with this flag */ if ((charClass & CF_COENG) && (i + 1 < syllable) && ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT2)) { coengRo = i; } } /* write coeng + ro if found */ if (coengRo > -1) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_COENG), pref_p, p - text); pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_RO), pref_p, p - text); } /* shall we add a dotted circle? * If in the position in which the base should be (first char in the string) there is * a character that has the Dotted circle flag (a character that cannot be a base) * then write a dotted circle */ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text); } /* copy what is left to the output, skipping before vowels and * coeng Ro if they are present */ for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); /* skip a before vowel, it was already processed */ if (charClass & CF_POS_BEFORE) { p = g_utf8_next_char (p); continue; } /* skip coeng + ro, it was already processed */ if (i == coengRo) { p = g_utf8_next_char (p); i += 1; p = g_utf8_next_char (p); continue; } switch (charClass & CF_POS_MASK) { case CF_POS_ABOVE : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text); break; case CF_POS_AFTER : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; case CF_POS_BELOW : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; default: /* assign the correct flags to a coeng consonant * Consonants of type 3 are taged as Post forms and those type 1 as below forms */ if ((charClass & CF_COENG) && i + 1 < syllable) { if ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT3) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); p = g_utf8_next_char (p); i += 1; pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; } else { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); p = g_utf8_next_char (p); i += 1; pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } } /* if a shifter is followed by an above vowel change the shifter to below form, * an above vowel can have two possible positions i + 1 or i + 3 * (position i+1 corresponds to unicode 3, position i+3 to Unicode 4) * and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two * different positions, right after the shifter or after a vowel (Unicode 4) */ if ((charClass & CF_SHIFTER) && (i + 1 < syllable)) { if (get_char_class (wcs[i + 1]) & CF_ABOVE_VOWEL) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 2 < syllable && (wcs[i + 1] == C_VOWEL_AA) && (wcs[i + 2] == C_SIGN_NIKAHIT) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 3 < syllable && (get_char_class (wcs[i + 3]) & CF_ABOVE_VOWEL) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 4 < syllable && (wcs[i + 3] == C_VOWEL_AA) && (wcs[i + 4] == C_SIGN_NIKAHIT) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } } /* default - any other characters */ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text); break; } /* switch */ p = g_utf8_next_char (p); } /* for */ cursor = syllable; /* move the pointer to the start of next syllable */ } /* while */ /* do gsub processing */ ruleset = get_ruleset (face); if (ruleset != NULL) { pango_ot_ruleset_substitute (ruleset, buffer); pango_ot_ruleset_position (ruleset, buffer); } pango_ot_buffer_output (buffer, glyphs); g_free (wcs); pango_ot_buffer_destroy (buffer); pango_fc_font_unlock_face (fc_font); }
static void tibetan_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, int length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRuleset *ruleset; PangoOTBuffer *buffer; glong n_chars; gunichar *wcs; const char *p; int i; glong syllable; TibetanCharClass charClass; glong cursor = 0; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); p = text; /* This loop only exits when we reach the end of a run, which may contain * several syllables. */ while (cursor < n_chars) { syllable = find_syllable (wcs, cursor, n_chars); /* shall we add a dotted circle? * If in the position in which the base should be (first char in the string) there is * a character that has the Dotted circle flag (a character that cannot be a base) * then write a dotted circle */ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text); } /* If it encounters a digit followed by number pre combining mark, then reorder the two characters * coeng Ro if they are present */ for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); if ((charClass & CF_DIGIT ) && ( get_char_class (wcs[i+1]) & CF_PREDIGIT)) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_PRE_NUMBER_MARK), pref_p, p - text); p = g_utf8_next_char (p); pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text); i += 1; } else { switch (charClass & CF_POS_MASK) { case CF_POS_ABOVE : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text); break; case CF_POS_AFTER : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; case CF_POS_BELOW : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; default: /* default - any other characters */ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text); break; } /* switch */ } p = g_utf8_next_char (p); } /* for */ cursor = syllable; /* move the pointer to the start of next syllable */ } /* while */ /* do gsub processing */ ruleset = get_ruleset (face); if (ruleset != NULL) { pango_ot_ruleset_substitute (ruleset, buffer); pango_ot_ruleset_position (ruleset, buffer); } pango_ot_buffer_output (buffer, glyphs); g_free (wcs); pango_ot_buffer_destroy (buffer); pango_fc_font_unlock_face (fc_font); }
* A PangoFcFontMap implementation that detects font-not-found events **/ typedef struct { PangoLanguage *language; gboolean found; } FontsetForeachClosure; static gboolean fontset_foreach_cb (PangoFontset *fontset G_GNUC_UNUSED, PangoFont *font, gpointer data) { FontsetForeachClosure *closure = data; PangoFcFont *fcfont = PANGO_FC_FONT (font); const FcPattern *pattern = NULL; FcLangSet *langset = NULL; g_object_get (fcfont, "pattern", &pattern, NULL); /* old Pango version with non-readable pattern */ if (pattern == NULL) { g_warning ("Old Pango version with non-readable pattern. " "Skipping automatic missing-font installation."); return closure->found = TRUE; } if (FcPatternGetLangSet (pattern, FC_LANG, 0, &langset) == FcResultMatch && FcLangGetCharSet ((FcChar8 *) closure->language) != NULL && FcLangSetHasLang (langset, (FcChar8 *) closure->language) != FcLangDifferentLang)
static void syriac_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, gint length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRulesetDescription desc; const PangoOTRuleset *ruleset; PangoOTBuffer *buffer; gulong *properties = NULL; glong n_chars; gunichar *wcs; const char *p; int cluster = 0; int i; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0); pango_ot_buffer_set_zero_width_marks (buffer, TRUE); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); properties = g_new0 (gulong, n_chars); syriac_assign_properties (wcs, properties, n_chars); g_free (wcs); p = text; for (i=0; i < n_chars; i++) { gunichar wc; PangoGlyph glyph; wc = g_utf8_get_char (p); if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK) cluster = p - text; if (pango_is_zero_width (wc)) glyph = PANGO_GLYPH_EMPTY; else { gunichar c = wc; if (analysis->level % 2) g_unichar_get_mirror_char (c, &c); glyph = pango_fc_font_get_glyph (fc_font, c); } if (!glyph) glyph = PANGO_GET_UNKNOWN_GLYPH (wc); pango_ot_buffer_add_glyph (buffer, glyph, properties[i], cluster); p = g_utf8_next_char (p); } g_free (properties); desc.script = analysis->script; desc.language = analysis->language; desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features); desc.static_gsub_features = gsub_features; desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features); desc.static_gpos_features = gpos_features; /* TODO populate other_features from analysis->extra_attrs */ desc.n_other_features = 0; desc.other_features = NULL; ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc); pango_ot_ruleset_substitute (ruleset, buffer); pango_ot_ruleset_position (ruleset, buffer); pango_ot_buffer_output (buffer, glyphs); pango_ot_buffer_destroy (buffer); pango_fc_font_unlock_face (fc_font); }
PangoOTBuffer *buffer; gulong *properties = NULL; glong n_chars; gunichar *wcs; const char *p; int cluster = 0; gboolean rtl = analysis->level % 2 != 0; gboolean reverse; int i; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); pango_ot_buffer_set_rtl (buffer, rtl); pango_ot_buffer_set_zero_width_marks (buffer, TRUE); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); properties = g_new0 (gulong, n_chars); reverse = !rtl ^ (analysis->gravity == PANGO_GRAVITY_NORTH || analysis->gravity == PANGO_GRAVITY_WEST); Arabic_Assign_Properties (wcs, properties, n_chars, reverse); g_free (wcs);
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName) : m_context(0) , m_font(0) , m_size(fontDescription.computedSize()) , m_syntheticBold(false) , m_syntheticOblique(false) , m_scaledFont(0) { FontPlatformData::init(); CString stored_family = familyName.string().utf8(); char const* families[] = { stored_family.data(), NULL }; switch (fontDescription.genericFamily()) { case FontDescription::SerifFamily: families[1] = "serif"; break; case FontDescription::SansSerifFamily: families[1] = "sans"; break; case FontDescription::MonospaceFamily: families[1] = "monospace"; break; case FontDescription::NoFamily: case FontDescription::StandardFamily: default: families[1] = "sans"; break; } PangoFontDescription* description = pango_font_description_new(); pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE); // FIXME: Map all FontWeight values to Pango font weights. if (fontDescription.weight() >= FontWeight600) pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD); if (fontDescription.italic()) pango_font_description_set_style(description, PANGO_STYLE_ITALIC); #if PANGO_VERSION_CHECK(1,21,5) // deprecated in 1.21 m_context = pango_font_map_create_context(m_fontMap); #else m_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(m_fontMap)); #endif for (unsigned int i = 0; !m_font && i < G_N_ELEMENTS(families); i++) { pango_font_description_set_family(description, families[i]); pango_context_set_font_description(m_context, description); m_font = pango_font_map_load_font(m_fontMap, m_context, description); } #if PANGO_VERSION_CHECK(1,18,0) if (m_font) m_scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(m_font))); #else // This compatibility code for older versions of Pango is not well-tested. if (m_font) { PangoFcFont* fcfont = PANGO_FC_FONT(m_font); cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(fcfont->font_pattern); double size; if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch) size = 12.0; cairo_matrix_t fontMatrix; cairo_matrix_init_scale(&fontMatrix, size, size); cairo_font_options_t* fontOptions; if (pango_cairo_context_get_font_options(m_context)) fontOptions = cairo_font_options_copy(pango_cairo_context_get_font_options(m_context)); else fontOptions = cairo_font_options_create(); cairo_matrix_t ctm; cairo_matrix_init_identity(&ctm); m_scaledFont = cairo_scaled_font_create(face, &fontMatrix, &ctm, fontOptions); cairo_font_options_destroy(fontOptions); cairo_font_face_destroy(face); } #endif pango_font_description_free(description); }
TGlyphInfo *glyph_cache_get_info(TGlyphCache *cache, gunichar glyph) { TGlyphInfo *gfi; XftFont *xftfont; PangoFont *font; PangoGlyph pglyph; PangoRectangle ink, logical; gint ascent, descent; gint x_offset; gint nominal_width; double scale_y, scale_x; if (!cache->hash) return NULL; gfi = g_hash_table_lookup(cache->hash, GINT_TO_POINTER(glyph)); if (gfi) return gfi; font = pango_fontset_get_font(cache->font_set, glyph); pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph); if (!pglyph) { fprintf (stderr, "Error: Unable to find glyph %d.\n", glyph); if (!pglyph) pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph); if (!pglyph) pglyph = PANGO_GET_UNKNOWN_GLYPH (glyph); if (!pglyph) return NULL; } pango_font_get_glyph_extents(font, pglyph, &ink, &logical); ascent = PANGO_ASCENT(logical); descent = PANGO_DESCENT(logical); xftfont = pango_xft_font_get_font(font); x_offset = 0; nominal_width = cache->width; if (g_unichar_iswide(glyph)) nominal_width *= 2; scale_x = scale_y = 1.0; if (logical.width > nominal_width) { if (logical.width) scale_x = (double)nominal_width / (double)logical.width; else scale_x = 1.0; } if (logical.height != cache->height) { double scale; if (ascent) { scale_y = (double)cache->ascent / (double)ascent; } else { scale_y = 1.0; } if (descent) { scale = (double)cache->descent / (double)descent; if (scale < scale_y) scale_y = scale; } } if (scale_x >= 1.0) { scale_x = 1.0; x_offset += (nominal_width - logical.width) / 2; } if (scale_x < 1.0 || scale_y != 1.0) { FcBool scalable; FcPatternGetBool(xftfont->pattern, FC_SCALABLE, 0, &scalable); if (!scalable) { /* Bah. Need better handling of non-scalable fonts */ if (scale_x < 1.0) scale_x = 1.0; scale_y = 1.0; } else if (scale_x < 1.0 || scale_y != 1.0) { FcPattern *pattern; FcMatrix mat; pattern = FcPatternDuplicate(xftfont->pattern); FcMatrixInit (&mat); FcMatrixScale(&mat, scale_x, scale_y); FcPatternDel (pattern, FC_MATRIX); FcPatternAddMatrix(pattern, FC_MATRIX, &mat); xftfont = XftFontOpenPattern( GDK_DISPLAY_XDISPLAY(cache->display), pattern ); } ascent = ascent * scale_y; } g_object_unref(font); // gfi = calloc(sizeof(TGlyphInfo), 1); gfi = g_slice_new(TGlyphInfo); gfi->font = xftfont; gfi->x_offset = PANGO_PIXELS(x_offset); gfi->y_offset = cache->ascent + (cache->ascent - ascent); gfi->y_offset = PANGO_PIXELS(gfi->y_offset); g_hash_table_insert(cache->hash, GINT_TO_POINTER(glyph), gfi); return gfi; }
static boolean pango_textlayout(textspan_t * span, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; PostscriptAlias *pA; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); #ifdef HAVE_PANGO_FONT_MAP_CREATE_CONTEXT context = pango_font_map_create_context (fontmap); #else context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); #endif options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, span->font->name) != 0 || fontsize != span->font->size) { fontname = span->font->name; fontsize = span->font->size; pango_font_description_free (desc); pA = span->font->postscript_alias; if (pA) { psfnt = fnt = gv_fmap[pA->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (pA); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((span->font) && (flags = span->font->flags)) { unsigned char buf[BUFSIZ]; agxbuf xb; agxbinit(&xb, BUFSIZ, buf); agxbput(&xb,"<span"); if (flags & HTML_BF) agxbput(&xb," weight=\"bold\""); if (flags & HTML_IF) agxbput(&xb," style=\"italic\""); if (flags & HTML_UL) agxbput(&xb," underline=\"single\""); if (flags & HTML_S) agxbput(&xb," strikethrough=\"true\""); agxbput (&xb,">"); if (flags & HTML_SUP) agxbput(&xb,"<sup>"); if (flags & HTML_SUB) agxbput(&xb,"<sub>"); agxbput (&xb,xml_string0(span->str, TRUE)); if (flags & HTML_SUB) agxbput(&xb,"</sub>"); if (flags & HTML_SUP) agxbput(&xb,"</sup>"); agxbput (&xb,"</span>"); if (!pango_parse_markup (agxbuse(&xb), -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = span->str; attrs = NULL; } agxbfree (&xb); } else { text = span->str; attrs = NULL; } #else text = span->str; #endif layout = pango_layout_new (context); span->layout = (void *)layout; /* layout free with textspan - see labels.c */ span->free_layout = pango_free_layout; /* function for freeing pango layout */ pango_layout_set_text (layout, text, -1); pango_layout_set_font_description (layout, desc); #ifdef ENABLE_PANGO_MARKUP if (attrs) pango_layout_set_attributes (layout, attrs); #endif pango_layout_get_extents (layout, NULL, &logical_rect); /* if pango doesn't like the font then it sets width=0 but height = garbage */ if (logical_rect.width == 0) logical_rect.height = 0; textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE); span->size.x = (int)(logical_rect.width * textlayout_scale + 1); /* round up so that width/height are never too small */ span->size.y = (int)(logical_rect.height * textlayout_scale + 1); /* FIXME -- Horrible kluge !!! */ /* For now we are using pango for single line blocks only. * The logical_rect.height seems to be too high from the font metrics on some platforms. * Use an assumed height based on the point size. */ span->size.y = (int)(span->font->size * 1.1 + .5); /* The y offset from baseline to 0,0 of the bitmap representation */ #if !defined(WIN32) && defined PANGO_VERSION_MAJOR && (PANGO_VERSION_MAJOR >= 1) span->yoffset_layout = pango_layout_get_baseline (layout) * textlayout_scale; #else { /* do it the hard way on rhel5/centos5 */ PangoLayoutIter *iter = pango_layout_get_iter (layout); span->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale; } #endif /* The distance below midline for y centering of text strings */ span->yoffset_centerline = 0.2 * span->font->size; if (logical_rect.width == 0) return FALSE; return TRUE; }
FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const UChar *characters, int length) : m_context(0) , m_font(0) , m_size(fontDescription.computedSize()) , m_syntheticBold(false) , m_syntheticOblique(false) , m_scaledFont(0) { FontPlatformData::init(); const UChar character = characters[0]; char const *family; switch (fontDescription.genericFamily()) { case FontDescription::SerifFamily: family = "serif"; break; case FontDescription::SansSerifFamily: family = "sans"; break; case FontDescription::MonospaceFamily: family = "monospace"; break; case FontDescription::NoFamily: case FontDescription::StandardFamily: default: family = "sans"; break; } m_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(m_fontMap)); PangoFontDescription* description = pango_font_description_new(); pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE); if (fontDescription.weight() >= FontWeight600) pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD); if (fontDescription.italic()) pango_font_description_set_style(description, PANGO_STYLE_ITALIC); pango_font_description_set_family(description, family); pango_context_set_font_description(m_context, description); PangoFontset *fset = pango_font_map_load_fontset (m_fontMap, m_context, description, NULL); // Get the font from the fontset which contains the best glyph for this character m_font = pango_fontset_get_font(fset, (guint)character); #if PANGO_VERSION_CHECK(1,18,0) if (m_font) m_scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(m_font))); #else // This compatibility code for older versions of Pango is not well-tested. if (m_font) { PangoFcFont* fcfont = PANGO_FC_FONT(m_font); cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(fcfont->font_pattern); double size; if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch) size = 12.0; cairo_matrix_t fontMatrix; cairo_matrix_init_scale(&fontMatrix, size, size); cairo_font_options_t* fontOptions; if (pango_cairo_context_get_font_options(m_context)) fontOptions = cairo_font_options_copy(pango_cairo_context_get_font_options(m_context)); else fontOptions = cairo_font_options_create(); cairo_matrix_t ctm; cairo_matrix_init_identity(&ctm); m_scaledFont = cairo_scaled_font_create(face, &fontMatrix, &ctm, fontOptions); cairo_font_options_destroy(fontOptions); cairo_font_face_destroy(face); } #endif pango_font_description_free(description); }