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 | |
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')
-rw-r--r-- | modules/arabic/arabic-fc.c | 236 | ||||
-rw-r--r-- | modules/arabic/arabic-ot.c | 4 | ||||
-rw-r--r-- | modules/indic/indic-fc.c | 56 | ||||
-rw-r--r-- | modules/indic/indic-ot.c | 2 | ||||
-rw-r--r-- | modules/indic/mprefixups.c | 30 | ||||
-rw-r--r-- | modules/indic/mprefixups.h | 3 |
6 files changed, 181 insertions, 150 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); } diff --git a/modules/arabic/arabic-ot.c b/modules/arabic/arabic-ot.c index ccde4fa9..cf1d76b5 100644 --- a/modules/arabic/arabic-ot.c +++ b/modules/arabic/arabic-ot.c @@ -54,8 +54,8 @@ joining_class arabic[] = transparent, transparent, transparent, transparent, /* U+0650 */ - transparent, transparent, transparent, none, - none, none, none, none, + transparent, transparent, transparent, transparent, + transparent, transparent, transparent, transparent, none, none, none, none, none, none, none, none, diff --git a/modules/indic/indic-fc.c b/modules/indic/indic-fc.c index 68b28662..45eb48f8 100644 --- a/modules/indic/indic-fc.c +++ b/modules/indic/indic-fc.c @@ -241,20 +241,18 @@ get_gpos_ruleset (FT_Face face, PangoIndicInfo *indic_info) return ruleset; } static void -set_glyphs (PangoFont *font, FT_Face face, const gunichar *wcs, glong n_glyphs, PangoGlyphString *glyphs) +set_glyphs (PangoFont *font, FT_Face face, const gunichar *wcs, gulong *tags, glong n_glyphs, PangoOTBuffer *buffer) { gint i; g_assert (face); - pango_glyph_string_set_size (glyphs, n_glyphs); - for (i = 0; i < n_glyphs; i += 1) { - PangoGlyph glyph = FT_Get_Char_Index (face, wcs[i]); - - glyphs->glyphs[i].glyph = glyph; - glyphs->log_clusters[i] = i; + pango_ot_buffer_add_glyph (buffer, + FT_Get_Char_Index (face, wcs[i]), + tags[i], + i); } } @@ -305,6 +303,7 @@ indic_engine_shape (PangoEngineShape *engine, glong *indices = NULL; FT_Face face; PangoOTRuleset *gsub_ruleset = NULL, *gpos_ruleset = NULL; + PangoOTBuffer *buffer; IndicEngineFc *indic_shape_engine = NULL; PangoIndicInfo *indic_info = NULL; PangoFcFont *fc_font; @@ -334,55 +333,27 @@ indic_engine_shape (PangoEngineShape *engine, 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); - set_glyphs(font, face, wc_out, n_glyphs, glyphs); + buffer = pango_ot_buffer_new (fc_font); + set_glyphs(font, face, wc_out, tags, n_glyphs, buffer); /* do gsub processing */ gsub_ruleset = get_gsub_ruleset (face, indic_info); if (gsub_ruleset != NULL) - { - pango_ot_ruleset_shape (gsub_ruleset, glyphs, tags); - } + pango_ot_ruleset_substitute (gsub_ruleset, buffer); /* Fix pre-modifiers for some scripts before base consonant */ if (mprefixups) { - indic_mprefixups_apply (mprefixups, glyphs); + indic_mprefixups_apply (mprefixups, buffer); indic_mprefixups_free (mprefixups); } - /* apply default positioning */ - for (i = 0; i < glyphs->num_glyphs; i += 1) - { - if (glyphs->glyphs[i].glyph != 0) - { - 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; - } - /* do gpos processing */ gpos_ruleset = get_gpos_ruleset (face, indic_info); if (gpos_ruleset != NULL) - { - gulong *tags_after_gsub; - - tags_after_gsub = g_new (gulong, glyphs->num_glyphs); - for (i = 0; i < glyphs->num_glyphs; i += 1) - tags_after_gsub[i] = tags[glyphs->log_clusters[i]]; - - pango_ot_ruleset_shape (gpos_ruleset, glyphs, tags_after_gsub); - - g_free (tags_after_gsub); - } + 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) @@ -390,6 +361,7 @@ indic_engine_shape (PangoEngineShape *engine, pango_fc_font_unlock_face (fc_font); + pango_ot_buffer_destroy (buffer); g_free (tags); g_free (indices); g_free (wc_out); diff --git a/modules/indic/indic-ot.c b/modules/indic/indic-ot.c index 94a689de..211d3e9c 100644 --- a/modules/indic/indic-ot.c +++ b/modules/indic/indic-ot.c @@ -10,7 +10,7 @@ #include "mprefixups.h" /* * FIXME: should the IndicOutput stuff be moved - * to a spereate .h and .c file just to keep the + * to a separate .h and .c file just to keep the * clutter down here? (it's not really usefull * anyplace else, is it?) */ diff --git a/modules/indic/mprefixups.c b/modules/indic/mprefixups.c index 29b126d0..183f29ce 100644 --- a/modules/indic/mprefixups.c +++ b/modules/indic/mprefixups.c @@ -59,7 +59,7 @@ void indic_mprefixups_add (MPreFixups *mprefixups, glong baseIndex, glong mpreIn } } -void indic_mprefixups_apply(MPreFixups *mprefixups, PangoGlyphString *glyphs) +void indic_mprefixups_apply(MPreFixups *mprefixups, PangoOTBuffer *buffer) { glong fixup; @@ -68,17 +68,22 @@ void indic_mprefixups_apply(MPreFixups *mprefixups, PangoGlyphString *glyphs) glong mpreIndex = mprefixups->fFixupData[fixup].fMPreIndex; glong mpreLimit, mpreCount, moveCount, mpreDest; glong i; - PangoGlyph *mpreSave; + PangoOTGlyph *glyphs; + int n_glyphs; + PangoOTGlyph *mpreSave; int *clusterSave; /* determine post GSUB location of baseIndex and mpreIndex */ gboolean no_base = TRUE; - for (i = 0; i<glyphs->num_glyphs; i++) { - if (glyphs->log_clusters[i] == baseIndex) { + + pango_ot_buffer_get_glyphs (buffer, &glyphs, &n_glyphs); + + for (i = 0; i < n_glyphs; i++) { + if (glyphs[i].cluster == baseIndex) { baseIndex = i + 1; no_base = FALSE; } - if (glyphs->log_clusters[i] == mpreIndex) + if (glyphs[i].cluster == mpreIndex) mpreIndex = i; } if (no_base) @@ -86,11 +91,11 @@ void indic_mprefixups_apply(MPreFixups *mprefixups, PangoGlyphString *glyphs) mpreLimit = mpreIndex + 1; - while (glyphs->glyphs[baseIndex].glyph == 0xFFFF || glyphs->glyphs[baseIndex].glyph == 0xFFFE) { + while (glyphs[baseIndex].glyph == 0xFFFF || glyphs[baseIndex].glyph == 0xFFFE) { baseIndex -= 1; } - while (glyphs->glyphs[mpreIndex].glyph == 0xFFFF || glyphs->glyphs[mpreIndex].glyph == 0xFFFE) { + while (glyphs[mpreIndex].glyph == 0xFFFF || glyphs[mpreIndex].glyph == 0xFFFE) { mpreLimit += 1; } @@ -102,22 +107,19 @@ void indic_mprefixups_apply(MPreFixups *mprefixups, PangoGlyphString *glyphs) moveCount = baseIndex - mpreLimit; mpreDest = baseIndex - mpreCount - 1; - mpreSave = g_new (PangoGlyph, mpreCount); + mpreSave = g_new (PangoOTGlyph, mpreCount); clusterSave = g_new (int, mpreCount); for (i = 0; i < mpreCount; i += 1) { - mpreSave[i] = glyphs->glyphs[mpreIndex + i].glyph; - clusterSave[i] = glyphs->log_clusters[mpreIndex + i]; + mpreSave[i] = glyphs[mpreIndex + i]; } for (i = 0; i < moveCount; i += 1) { - glyphs->glyphs[mpreIndex + i].glyph = glyphs->glyphs[mpreLimit + i].glyph; - glyphs->log_clusters[mpreIndex + i] = glyphs->log_clusters[mpreLimit + i]; + glyphs[mpreIndex + i] = glyphs[mpreLimit + i]; } for (i = 0; i < mpreCount; i += 1) { - glyphs->glyphs[mpreDest + i].glyph = mpreSave[i]; - glyphs->log_clusters[mpreDest + i] = clusterSave[i]; + glyphs[mpreDest + i] = mpreSave[i]; } g_free(mpreSave); diff --git a/modules/indic/mprefixups.h b/modules/indic/mprefixups.h index 4bab8cac..d09d6be5 100644 --- a/modules/indic/mprefixups.h +++ b/modules/indic/mprefixups.h @@ -26,6 +26,7 @@ #include <pango/pango-types.h> #include <pango/pango-glyph.h> +#include <pango/pango-ot.h> G_BEGIN_DECLS @@ -41,7 +42,7 @@ typedef struct _MPreFixups MPreFixups; MPreFixups *indic_mprefixups_new(glong char_count); void indic_mprefixups_free(MPreFixups *mprefixups); void indic_mprefixups_add(MPreFixups *mprefixups, glong baseIndex, glong mpreIndex); -void indic_mprefixups_apply(MPreFixups *mprefixups, PangoGlyphString *glyphs); +void indic_mprefixups_apply(MPreFixups *mprefixups, PangoOTBuffer *buffer); G_END_DECLS |