PangoGlyph mozilla_decoder_get_glyph (PangoFcDecoder *decoder, PangoFcFont *fcfont, guint32 wc) { MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder); PangoGlyph retval = 0; PRUnichar inchar = wc; PRInt32 inlen = 1; char outchar[2] = {0,0}; PRInt32 outlen = 2; priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen); if (outlen != 1) { printf("Warning: mozilla_decoder_get_glyph doesn't support more than one character conversions.\n"); return 0; } FT_Face face = pango_fc_font_lock_face(fcfont); #ifdef DEBUG_CUSTOM_ENCODER char *filename; FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename); printf("filename is %s\n", filename); #endif // Make sure to set the right charmap before trying to get the // glyph if (priv->cmap) { if (!strcmp(priv->cmap, "mac_roman")) { FT_Select_Charmap(face, ft_encoding_apple_roman); } else if (!strcmp(priv->cmap, "unicode")) { FT_Select_Charmap(face, ft_encoding_unicode); } else { printf("Warning: Invalid charmap entry for family %s\n", priv->family); } } // Standard 8 bit to glyph translation if (!priv->is_wide) { FcChar32 blah = PRUint8(outchar[0]); retval = FT_Get_Char_Index(face, blah); #ifdef DEBUG_CUSTOM_ENCODER printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n", wc, outchar[0], blah, retval, (void *)face); #endif } else { printf("Warning: We don't support .wide fonts!\n"); retval = 0; } pango_fc_font_unlock_face(fcfont); return retval; }
std::string FontSupport::fontPath(PangoFont *font) { PANGO_LOCK; PangoFcFont *f = (PangoFcFont *)font; FT_Face face = pango_fc_font_lock_face(f); std::string result; if (face->stream->pathname.pointer) result = (const char *)face->stream->pathname.pointer; pango_fc_font_unlock_face(f); return result; }
void text_widget_set_text ( struct TEXT_WIDGET_HANDLE handle, const char* text, int length ) { if ( handle.d == NULL || handle.d->layout == NULL ) return; pango_layout_set_markup( handle.d->layout, text, length ); // The idea here is to make sure that the VGFont contains // all the glyphs at the proper size so that when we want // to draw, we can can just call vgDrawGlyphs (well, maybe // not since PangoGlyphInfo is not an array of glyph // indexes; aww). PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout ); do { PangoLayoutRun* run = pango_layout_iter_get_run( li ); if ( run == NULL ) continue; PangoFont* font = run->item->analysis.font; // Well, you can see how C is not the most ideal language for // abstraction. Have to read the documentation to discover // that this font is a PangoFcFont. FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)font ); if ( face != NULL ) { struct VG_DATA* vg_data = face->size->generic.data; if ( vg_data == NULL ) { vg_data = vg_data_new(); face->size->generic.data = vg_data; face->size->generic.finalizer = vg_data_free; } int g; for ( g = 0; g < run->glyphs->num_glyphs; g++ ) { int byte = run->glyphs->glyphs[g].glyph / 8; int bit = 1 << ( run->glyphs->glyphs[g].glyph & 0x7 ); if ( ! ( vg_data->cmap[byte] & bit ) ) { vg_data->cmap[byte] |= bit; add_char( vg_data->font, face, run->glyphs->glyphs[g].glyph ); } } pango_fc_font_unlock_face( (PangoFcFont*)font ); } } while ( pango_layout_iter_next_run( li ) ); pango_layout_iter_free( li ); }
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)); }
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject obj __attribute__((unused)), jint rightGlyph, jint leftGlyph, jlong fnt, jfloatArray p) { FT_Face ft_face; FT_Vector kern; PangoFcFont *font; font = JLONG_TO_PTR(PangoFcFont, fnt); ft_face = pango_fc_font_lock_face( font ); g_assert (ft_face != NULL); FT_Get_Kerning( ft_face, rightGlyph, leftGlyph, FT_KERNING_DEFAULT, &kern ); pango_fc_font_unlock_face( font ); jfloat *pelements = (*env)->GetPrimitiveArrayCritical(env, p, NULL); pelements[0] = (jfloat)kern.x/64.0; pelements[1] = (jfloat)kern.y/64.0; (*env)->ReleasePrimitiveArrayCritical (env, p, pelements, 0); }
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt) { FT_Face ft_face; jdouble *values; jdoubleArray retArray = NULL; PangoFcFont *font; font = JLONG_TO_PTR(PangoFcFont, fnt); ft_face = pango_fc_font_lock_face( font ); g_assert (ft_face != NULL); FT_Set_Transform( ft_face, NULL, NULL ); if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 ) { pango_fc_font_unlock_face( font ); printf("Couldn't load glyph %i\n", glyphIndex); return NULL; } retArray = (*env)->NewDoubleArray (env, 8); values = (*env)->GetDoubleArrayElements (env, retArray, NULL); values[0] = 0; values[1] = (jdouble)ft_face->glyph->advance.x/64.0; values[2] = (jdouble)ft_face->glyph->advance.y/64.0; values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0; values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0; values[5] = (jdouble)ft_face->glyph->metrics.width/64.0; values[6] = (jdouble)ft_face->glyph->metrics.height/64.0; values[7] = 0; (*env)->ReleaseDoubleArrayElements (env, retArray, values, 0); pango_fc_font_unlock_face( font ); return retArray; }
/** * pango_ot_buffer_new * @font: a #PangoFcFont * * Creates a new #PangoOTBuffer for the given OpenType font. * * Return value: the newly allocated #PangoOTBuffer, which should * be freed with pango_ot_buffer_destroy(). * * Since: 1.4 **/ PangoOTBuffer * pango_ot_buffer_new (PangoFcFont *font) { /* We lock the font here immediately for the silly reason * of getting the FT_Memory; otherwise we'd have to * add a new operation to PangoFcFontmap; callers will * probably already have the font locked, however, * so there is little performance penalty. */ PangoOTBuffer *buffer = g_slice_new (PangoOTBuffer); FT_Face face = pango_fc_font_lock_face (font); if (hb_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok) g_warning ("Allocation of HB_Buffer failed"); /* this doesn't happen */ buffer->font = g_object_ref (font); buffer->applied_gpos = FALSE; buffer->rtl = FALSE; buffer->zero_width_marks = FALSE; pango_fc_font_unlock_face (font); return buffer; }
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); }
JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt) { generalpath *path; jobject gp; FT_Outline_Funcs ftCallbacks = { (FT_Outline_MoveToFunc) _moveTo, (FT_Outline_LineToFunc) _lineTo, (FT_Outline_ConicToFunc) _quadTo, (FT_Outline_CubicToFunc) _curveTo, 0, 0 }; PangoFcFont *font; FT_Face ft_face; FT_Glyph glyph; font = JLONG_TO_PTR(PangoFcFont, fnt); ft_face = pango_fc_font_lock_face( font ); g_assert (ft_face != NULL); path = g_malloc0 (sizeof (generalpath)); g_assert(path != NULL); path->env = env; path->px = path->py = 0.0; path->sx = 1.0/64.0; path->sy = -1.0/64.0; { /* create a GeneralPath instance */ jclass cls; jmethodID method; cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); method = (*env)->GetMethodID (env, cls, "<init>", "()V"); gp = path->obj = (*env)->NewObject (env, cls, method); } if(FT_Load_Glyph(ft_face, (FT_UInt)(glyphIndex), FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0) { pango_fc_font_unlock_face( font ); g_free(path); return NULL; } FT_Get_Glyph( ft_face->glyph, &glyph ); if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline), &ftCallbacks, path); } else { char format[5]; format[0] = (glyph->format & 0xFF000000) >> 24; format[1] = (glyph->format & 0x00FF0000) >> 16; format[2] = (glyph->format & 0x0000FF00) >> 8; format[3] = (glyph->format & 0x000000FF); format[4] = '\0'; printf("WARNING: Unable to create outline for font %s %s of format %s\n", ft_face->family_name, ft_face->style_name, format); } FT_Done_Glyph( glyph ); pango_fc_font_unlock_face( font ); g_free(path); return gp; }
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); }
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; }
void text_widget_draw_text ( struct TEXT_WIDGET_HANDLE handle ) { if ( handle.d == NULL || handle.d->layout == NULL ) return; vgSetPaint( handle.d->foreground, VG_FILL_PATH ); vgSeti( VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE ); vgLoadIdentity(); #if 0 // Overscan (in dots, evidently). vgTranslate( 14.f, 8.f ); #endif // Offset in mm. vgScale( handle.d->dpmm_x, handle.d->dpmm_y ); // Move to the corner. vgTranslate( handle.d->x_mm, handle.d->y_mm ); // Back to dots. vgScale( 1.f/handle.d->dpmm_x, 1.f/handle.d->dpmm_y ); int height = PANGO_PIXELS( pango_layout_get_height( handle.d->layout ) ); PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout ); do { PangoLayoutRun* run = pango_layout_iter_get_run( li ); if ( run == NULL ) continue; PangoRectangle logical_rect; int baseline_pango = pango_layout_iter_get_baseline( li ); int baseline_pixel = PANGO_PIXELS( baseline_pango ); pango_layout_iter_get_run_extents( li, NULL, &logical_rect ); int x_pixel = PANGO_PIXELS( logical_rect.x ); PangoFont* pg_font = run->item->analysis.font; FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)pg_font ); if ( face != NULL ) { struct VG_DATA* vg_data = face->size->generic.data; if ( vg_data != NULL ) { // About the only extra attribute we can manage is the foreground // color. But, it might be nice to render a background color // to see just how badly the text is fitted into the widget // box. GSList* attr_item = run->item->analysis.extra_attrs; while ( attr_item ) { PangoAttribute* attr = attr_item->data; switch ( attr->klass->type ) { case PANGO_ATTR_FOREGROUND: { PangoColor color = ((PangoAttrColor*)attr)->color; VGfloat new_color[] = { (float)color.red / 65535.f, (float)color.green / 65535.f, (float)color.blue / 65535.f, 1.f }; VGPaint new_paint = vgCreatePaint(); vgSetParameterfv( new_paint, VG_PAINT_COLOR, 4, new_color ); vgSetPaint( new_paint, VG_FILL_PATH ); vgDestroyPaint( new_paint ); } break; default: printf( "\tHmm. Unknown attribute: %d\n", attr->klass->type ); } attr_item = attr_item->next; } // Note: inverted Y coordinate VGfloat point[2] = { x_pixel, height - baseline_pixel }; vgSetfv( VG_GLYPH_ORIGIN, 2, point ); VGFont vg_font = vg_data->font; int g; for ( g = 0; g < run->glyphs->num_glyphs; g++ ) { vgDrawGlyph( vg_font, run->glyphs->glyphs[g].glyph, VG_FILL_PATH, VG_TRUE ); } if ( vgGetPaint( VG_FILL_PATH ) != handle.d->foreground ) { vgSetPaint( handle.d->foreground, VG_FILL_PATH ); } } pango_fc_font_unlock_face( (PangoFcFont*)pg_font ); } } while ( pango_layout_iter_next_run( li ) ); // Iterators are not free. pango_layout_iter_free( li); }
void doDrawGlyphs(PangoRenderer* renderer, PangoFont* font, PangoGlyphString* glyphs, int px, int py) { Renderer* ren = RENDERER(renderer); if (!ren->m_runs) return; std::vector<ViewdoTextRun>& runs = *(ren->m_runs); const float s = ren->m_scale; PangoColor* fg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_FOREGROUND); //PangoColor* bg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_BACKGROUND); float red = !fg ? 0.0f : fg->red / 65536.0f; float green = !fg ? 0.0f : fg->green / 65536.0f; float blue = !fg ? 0.0f : fg->blue / 65536.0f; PangoFontDescription* desc = pango_font_describe(font); unsigned int fontHash = pango_font_description_hash(desc); pango_font_description_free(desc); FT_Face face = pango_fc_font_lock_face((PangoFcFont*) font); PangoGlyphUnit layoutX = px; PangoGlyphUnit layoutY = py; ViewdoGlyphCache& cache = ViewdoGlyphCache::instance(); for (int i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo* gi = glyphs->glyphs + i; if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) { // XXX: Draw the fallback square. continue; } unsigned int glyph = gi->glyph; PangoRectangle r; pango_font_get_glyph_extents(font, glyph, &r, 0); pango_extents_to_pixels(&r, 0); float w = r.width; float h = r.height; if (w <= 0.f && h <= 0.f) { // Space. layoutX += gi->geometry.width; continue; } // Load and render the glyph. We probably need to just tell the font to cache it // and then grab the coordinates of it. const ViewdoGlyph& cachedGlyph = cache.findOrCreate(gi->glyph, fontHash, face); // Walk our existing runs and try to find one with the same color and page. // XXX: Fastpath try and use the run from the last glyph. ViewdoTextRun* run = nullptr; for (auto i = runs.begin(); i != runs.end(); i++) { if (i->m_page == cachedGlyph.m_page && i->m_red == red && i->m_green == green && i->m_blue == blue) { run = &(*i); break; } } if (!run) { runs.push_back(ViewdoTextRun(cachedGlyph.m_page, red, green, blue)); run = &(runs[runs.size() - 1]); } float x = PANGO_PIXELS(layoutX + gi->geometry.x_offset) + cachedGlyph.m_offsetLeft; float y = PANGO_PIXELS(layoutY + gi->geometry.y_offset) - cachedGlyph.m_offsetTop; // Append ourselves onto this run. addPoint(run->m_geometry, x, y, cachedGlyph.m_x0, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); // Triangle 2. addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y + cachedGlyph.m_height, cachedGlyph.m_x1, cachedGlyph.m_y1, s); layoutX += gi->geometry.width; } pango_fc_font_unlock_face((PangoFcFont*) font); }
/* 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); }
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);
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); }
/** * pango_ot_buffer_output * @buffer: a #PangoOTBuffer * @glyphs: a #PangoGlyphString * * Exports the glyphs in a #PangoOTBuffer into a #PangoGlyphString. This is * typically used after the OpenType layout processing is over, to convert the * resulting glyphs into a generic Pango glyph string. * * Since: 1.4 **/ void pango_ot_buffer_output (PangoOTBuffer *buffer, PangoGlyphString *glyphs) { FT_Face face; PangoOTInfo *info; HB_GDEF gdef = NULL; unsigned int i; int last_cluster; face = pango_fc_font_lock_face (buffer->font); g_assert (face); /* Copy glyphs into output glyph string */ pango_glyph_string_set_size (glyphs, buffer->buffer->in_length); last_cluster = -1; for (i = 0; i < buffer->buffer->in_length; i++) { HB_GlyphItem item = &buffer->buffer->in_string[i]; glyphs->glyphs[i].glyph = item->gindex; glyphs->log_clusters[i] = item->cluster; if (glyphs->log_clusters[i] != last_cluster) glyphs->glyphs[i].attr.is_cluster_start = 1; else glyphs->glyphs[i].attr.is_cluster_start = 0; last_cluster = glyphs->log_clusters[i]; } info = pango_ot_info_get (face); gdef = pango_ot_info_get_gdef (info); /* Apply default positioning */ for (i = 0; i < (unsigned int)glyphs->num_glyphs; i++) { if (glyphs->glyphs[i].glyph) { PangoRectangle logical_rect; FT_UShort property; if (buffer->zero_width_marks && gdef && HB_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok && (property == HB_GDEF_MARK || (property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS) != 0)) { glyphs->glyphs[i].geometry.width = 0; } else { pango_font_get_glyph_extents ((PangoFont *)buffer->font, glyphs->glyphs[i].glyph, NULL, &logical_rect); glyphs->glyphs[i].geometry.width = logical_rect.width; } } else glyphs->glyphs[i].geometry.width = 0; glyphs->glyphs[i].geometry.x_offset = 0; glyphs->glyphs[i].geometry.y_offset = 0; } if (buffer->rtl) { /* Swap all glyphs */ swap_range (glyphs, 0, glyphs->num_glyphs); } if (buffer->applied_gpos) { if (buffer->rtl) apply_gpos_rtl (glyphs, buffer->buffer->positions); else apply_gpos_ltr (glyphs, buffer->buffer->positions); } else pango_fc_font_kern_glyphs (buffer->font, glyphs); pango_fc_font_unlock_face (buffer->font); }