diff options
author | Owen Taylor <otaylor@redhat.com> | 2004-02-29 15:44:50 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2004-02-29 15:44:50 +0000 |
commit | 25689428204726ab37e7389661cf2827263b9893 (patch) | |
tree | 38d9d9dcdec9163cb61599d21b3dead55ee6e021 /modules/arabic/arabic-fc.c | |
parent | 309373b42cd6f03fe45e129e586d18bf11076be6 (diff) | |
download | pango-25689428204726ab37e7389661cf2827263b9893.tar.gz |
Rework opentype interfaces and other changes to make GPOS work for Arabic.
Sun Feb 29 09:25:13 2004 Owen Taylor <otaylor@redhat.com>
Rework opentype interfaces and other changes to make GPOS
work for Arabic. (Most of #117282, #121060)
* pango/opentype/otlbuffer.[ch]: OTL_Buffer that
acts as a replacement for the separate GSUB and
GPOS string structures and hides many of the internal
details.
* pango/opentype/ftxgsub.[ch] pango/opentype/ftxgpos.[ch]:
Adapt to OTL_Buffer.
* pango/opentype/ftxgpos.c: Redo handling of cursive
chains so that it actually works.
* pango/pango-ot.h pango/opentype/pango-ot-buffer.c:
Pango wrapper around OTL_Buffer.
* pango/pango-ot.h pango/pango-ot-ruleset.c pango/pango-ot-buffer.c:
Split pango_ot_ruleset_shape() into pango_ot_ruleset_substitute(),
pango_ot_ruleset_position(), make them act on
PangoOTBuffer, add a separate pango_ot_buffer_output()
which does the default positioning and writes to a
PangoGlyphString.
* modules/arabic/arabic-fc.c modules/indic/indic-fc.c
modules/indic/mprefixups.[ch]: Adapt to new OpenType
interfaces; add GPOS features for Arabic.
* pango/opentype/pango-ot-info.c: Don't derive class information
from Unicode properties for Arabic presentation forms,
let the shaping process derive the properties.
Diffstat (limited to 'modules/arabic/arabic-fc.c')
-rw-r--r-- | modules/arabic/arabic-fc.c | 236 |
1 files changed, 146 insertions, 90 deletions
diff --git a/modules/arabic/arabic-fc.c b/modules/arabic/arabic-fc.c index d3e2fcd9..bf0270c9 100644 --- a/modules/arabic/arabic-fc.c +++ b/modules/arabic/arabic-fc.c @@ -49,11 +49,11 @@ static PangoEngineInfo script_engines[] = { }; static void -maybe_add_feature (PangoOTRuleset *ruleset, - PangoOTInfo *info, - guint script_index, - PangoOTTag tag, - gulong property_bit) +maybe_add_gsub_feature (PangoOTRuleset *ruleset, + PangoOTInfo *info, + guint script_index, + PangoOTTag tag, + gulong property_bit) { guint feature_index; @@ -64,6 +64,22 @@ maybe_add_feature (PangoOTRuleset *ruleset, property_bit); } +static void +maybe_add_gpos_feature (PangoOTRuleset *ruleset, + PangoOTInfo *info, + guint script_index, + PangoOTTag tag, + gulong property_bit) +{ + guint feature_index; + + /* 0xffff == default language system */ + if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GPOS, + tag, script_index, 0xffff, &feature_index)) + pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GPOS, feature_index, + property_bit); +} + static PangoOTRuleset * get_ruleset (FT_Face face) { @@ -90,11 +106,24 @@ get_ruleset (FT_Face face) if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB, arab_tag, &script_index)) { - maybe_add_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','s','o','l'), isolated); - maybe_add_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','n','i','t'), initial); - maybe_add_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','e','d','i'), medial); - maybe_add_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','a'), final); - maybe_add_feature (ruleset, info, script_index, FT_MAKE_TAG ('l','i','g','a'), 0xFFFF); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','c','m','p'), 0xFFFF); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','s','o','l'), isolated); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','a'), final); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','e','d','i'), medial); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','n','i','t'), initial); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('r','l','i','g'), 0xFFFF); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','a','l','t'), 0xFFFF); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('l','i','g','a'), 0xFFFF); + maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','s','e','t'), 0xFFFF); + } + + if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS, + arab_tag, &script_index)) + { + maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','u','r','s'), 0xFFFF); + maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('k','e','r','n'), 0xFFFF); + maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','a','r','k'), 0xFFFF); + maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), 0xFFFF); } g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset, @@ -132,6 +161,86 @@ set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGl } static void +fallback_shape (PangoEngineShape *engine, + PangoFont *font, + const char *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs) +{ + PangoFcFont *fc_font = PANGO_FC_FONT (font); + glong n_chars; + gunichar *wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); + const char *p; + int i; + + pango_glyph_string_set_size (glyphs, n_chars); + p = text; + + for (i=0; i < n_chars; i++) + { + gunichar wc; + gunichar mirrored_ch; + PangoGlyph index; + char buf[6]; + const char *input; + + wc = g_utf8_get_char (p); + + input = p; + if (analysis->level % 2) + if (pango_get_mirror_char (wc, &mirrored_ch)) + { + wc = mirrored_ch; + + g_unichar_to_utf8 (wc, buf); + input = buf; + } + + if (wc >= 0x200B && wc <= 0x200F) /* Zero-width characters */ + { + set_glyph (font, glyphs, i, p - text, 0); + } + else + { + index = pango_fc_font_get_glyph (fc_font, wc); + + if (!index) + index = pango_fc_font_get_unknown_glyph (fc_font, wc); + + set_glyph (font, glyphs, i, p - text, index); + } + + p = g_utf8_next_char (p); + } + + /* Apply default positioning */ + for (i = 0; i < glyphs->num_glyphs; i++) + { + if (glyphs->glyphs[i].glyph) + { + PangoRectangle logical_rect; + + pango_font_get_glyph_extents (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 (analysis->level % 2 != 0) + { + /* Swap all glyphs */ + swap_range (glyphs, 0, glyphs->num_glyphs); + } + + g_free (wcs); +} + +static void arabic_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, @@ -139,13 +248,14 @@ arabic_engine_shape (PangoEngineShape *engine, PangoAnalysis *analysis, PangoGlyphString *glyphs) { - int n_chars; + glong n_chars; + gunichar *wcs; int i; const char *p; gulong *properties = NULL; - gunichar *wcs = NULL; FT_Face face; PangoOTRuleset *ruleset; + PangoOTBuffer *buffer; PangoFcFont *fc_font; g_return_if_fail (font != NULL); @@ -158,17 +268,20 @@ arabic_engine_shape (PangoEngineShape *engine, face = pango_fc_font_lock_face (fc_font); g_assert (face); - n_chars = g_utf8_strlen (text, length); - pango_glyph_string_set_size (glyphs, n_chars); - ruleset = get_ruleset (face); - if (ruleset) + if (!ruleset) { - wcs = g_utf8_to_ucs4_fast (text, length, NULL); - properties = g_new0 (gulong, n_chars); - - Arabic_Assign_Properties (wcs, properties, n_chars); + fallback_shape (engine, font, text, length, analysis, glyphs); + goto out; } + + buffer = pango_ot_buffer_new (fc_font); + pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0); + + wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); + properties = g_new0 (gulong, n_chars); + + Arabic_Assign_Properties (wcs, properties, n_chars); p = text; for (i=0; i < n_chars; i++) @@ -193,7 +306,7 @@ arabic_engine_shape (PangoEngineShape *engine, if (wc >= 0x200B && wc <= 0x200F) /* Zero-width characters */ { - set_glyph (font, glyphs, i, p - text, 0); + pango_ot_buffer_add_glyph (buffer, 0, properties[i], p - text); } else { @@ -210,33 +323,18 @@ arabic_engine_shape (PangoEngineShape *engine, if (!index) { - set_glyph (font, glyphs, i, p - text, - pango_fc_font_get_unknown_glyph (fc_font, wc)); + pango_ot_buffer_add_glyph (buffer, pango_fc_font_get_unknown_glyph (fc_font, wc), + properties[i], p - text); } else { - set_glyph (font, glyphs, i, p - text, index); + pango_ot_buffer_add_glyph (buffer, index, + properties[i], p - text); if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK) { if (i > 0) - { - glyphs->log_clusters[i] = glyphs->log_clusters[i-1]; -#if 0 - PangoRectangle logical_rect, ink_rect; - - glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width, - glyphs->glyphs[i].geometry.width); - glyphs->glyphs[i-1].geometry.width = 0; - - /* Some heuristics to try to guess how overstrike glyphs are - * done and compensate - */ - pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect); - if (logical_rect.width == 0 && ink_rect.x == 0) - glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2; -#endif - } + glyphs->log_clusters[i] = glyphs->log_clusters[i-1]; } } } @@ -244,57 +342,15 @@ arabic_engine_shape (PangoEngineShape *engine, p = g_utf8_next_char (p); } - ruleset = get_ruleset (face); - - if (ruleset) - { - pango_ot_ruleset_shape (ruleset, glyphs, properties); - - g_free (wcs); - g_free (properties); - - } - - for (i = 0; i < glyphs->num_glyphs; i++) - { - - if (glyphs->glyphs[i].glyph) - { - PangoRectangle logical_rect; - - pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect); - glyphs->glyphs[i].geometry.width = logical_rect.width; - } - else - glyphs->glyphs[i].geometry.width = 0; + pango_ot_ruleset_substitute (ruleset, buffer); + pango_ot_ruleset_position (ruleset, buffer); + pango_ot_buffer_output (buffer, glyphs); - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - } - - /* Simple bidi support */ - - if (analysis->level % 2) - { - int start, end; + g_free (wcs); + g_free (properties); + pango_ot_buffer_destroy (buffer); - /* Swap all glyphs */ - swap_range (glyphs, 0, glyphs->num_glyphs); - - /* Now reorder glyphs within each cluster back to LTR */ - for (start=0; start<glyphs->num_glyphs;) - { - end = start; - while (end < glyphs->num_glyphs && - glyphs->log_clusters[end] == glyphs->log_clusters[start]) - end++; - - if (end > start + 1) - swap_range (glyphs, start, end); - start = end; - } - } - + out: pango_fc_font_unlock_face (fc_font); } |