summaryrefslogtreecommitdiff
path: root/modules
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
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')
-rw-r--r--modules/arabic/arabic-fc.c236
-rw-r--r--modules/arabic/arabic-ot.c4
-rw-r--r--modules/indic/indic-fc.c56
-rw-r--r--modules/indic/indic-ot.c2
-rw-r--r--modules/indic/mprefixups.c30
-rw-r--r--modules/indic/mprefixups.h3
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