summaryrefslogtreecommitdiff
path: root/modules/arabic
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2004-02-29 15:44:50 +0000
committerOwen Taylor <otaylor@src.gnome.org>2004-02-29 15:44:50 +0000
commit25689428204726ab37e7389661cf2827263b9893 (patch)
tree38d9d9dcdec9163cb61599d21b3dead55ee6e021 /modules/arabic
parent309373b42cd6f03fe45e129e586d18bf11076be6 (diff)
downloadpango-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')
-rw-r--r--modules/arabic/arabic-fc.c236
-rw-r--r--modules/arabic/arabic-ot.c4
2 files changed, 148 insertions, 92 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,