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); } }
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); }
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 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); }