summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2007-05-14 07:22:08 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2007-05-14 07:22:08 +0000
commit82e04d3696977d11611f9356707f9e00ea1e04d4 (patch)
tree77f99e1d3318e2b82a77a57da430162013f676fd
parent8c148a9134427e02c1097b45e59c34d237972f6b (diff)
downloadpango-82e04d3696977d11611f9356707f9e00ea1e04d4.tar.gz
Part of Bug 325714 – Pango should respect $LANGUAGE Bug 414264 – Pango
2007-05-14 Behdad Esfahbod <behdad@gnome.org> Part of Bug 325714 – Pango should respect $LANGUAGE Bug 414264 – Pango vertical writing support is different with real CJK usage. * modules/arabic/arabic-fc.c (arabic_engine_shape): * modules/basic/basic-fc.c (basic_engine_shape): * modules/syriac/syriac-fc.c (syriac_engine_shape): Remove fallback_shape() paths. Remove get_ruleset(). Use pango_ot_ruleset_get_for(), that correctly works for multiple languages. Also makes basic shaper apply the 'vert' feature for vertical text. Removes a net 500 lines. Other OpenType modules need to be ported over time, however some extensions may be needed. For example, the Hebrew shaper uses fallback code if no GPOS tables are available. Currently using pango_ot_ruleset_get_for() one cannot see which features were found. svn path=/trunk/; revision=2292
-rw-r--r--ChangeLog20
-rw-r--r--modules/arabic/arabic-fc.c293
-rw-r--r--modules/basic/basic-fc.c316
-rw-r--r--modules/syriac/syriac-fc.c268
4 files changed, 196 insertions, 701 deletions
diff --git a/ChangeLog b/ChangeLog
index b2d1f6a2..0575795b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+ Part of Bug 325714 – Pango should respect $LANGUAGE
+ Bug 414264 – Pango vertical writing support is different with real
+ CJK usage.
+
+ * modules/arabic/arabic-fc.c (arabic_engine_shape):
+ * modules/basic/basic-fc.c (basic_engine_shape):
+ * modules/syriac/syriac-fc.c (syriac_engine_shape):
+ Remove fallback_shape() paths. Remove get_ruleset().
+ Use pango_ot_ruleset_get_for(), that correctly works for multiple
+ languages. Also makes basic shaper apply the 'vert' feature for
+ vertical text. Removes a net 500 lines.
+
+ Other OpenType modules need to be ported over time, however some
+ extensions may be needed. For example, the Hebrew shaper uses
+ fallback code if no GPOS tables are available. Currently using
+ pango_ot_ruleset_get_for() one cannot see which features were
+ found.
+
+2007-05-14 Behdad Esfahbod <behdad@gnome.org>
+
Part of Bug 414264 – Pango vertical writing support is different with
real CJK usage.
diff --git a/modules/arabic/arabic-fc.c b/modules/arabic/arabic-fc.c
index 2306bfe5..8b393fb8 100644
--- a/modules/arabic/arabic-fc.c
+++ b/modules/arabic/arabic-fc.c
@@ -49,199 +49,30 @@ static PangoEngineInfo script_engines[] = {
}
};
-static void
-maybe_add_gsub_feature (PangoOTRuleset *ruleset,
- PangoOTInfo *info,
- guint script_index,
- PangoOTTag tag,
- gulong property_bit)
-{
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GSUB,
- tag, script_index, PANGO_OT_DEFAULT_LANGUAGE, &feature_index))
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GSUB, feature_index,
- property_bit);
-}
-
-static void
-maybe_add_gpos_feature (PangoOTRuleset *ruleset,
- PangoOTInfo *info,
- guint script_index,
- PangoOTTag tag,
- gulong property_bit)
+static const PangoOTFeatureMap gsub_features[] =
{
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GPOS,
- tag, script_index, PANGO_OT_DEFAULT_LANGUAGE, &feature_index))
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GPOS, feature_index,
- property_bit);
-}
-
-static PangoOTRuleset *
-get_ruleset (FT_Face face)
-{
- PangoOTRuleset *ruleset;
- static GQuark ruleset_quark = 0;
-
- PangoOTInfo *info = pango_ot_info_get (face);
-
- if (!ruleset_quark)
- ruleset_quark = g_quark_from_string ("pango-arabic-ruleset");
-
- if (!info)
- return NULL;
-
- ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);
-
- if (!ruleset)
- {
- PangoOTTag arab_tag = FT_MAKE_TAG ('a', 'r', 'a', 'b');
- guint script_index;
-
- ruleset = pango_ot_ruleset_new (info);
-
- /* according to the Arabic OpenType spec, available here:
- * http://www.microsoft.com/typography/otfntdev/arabicot/features.htm
- */
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB,
- arab_tag, &script_index))
- {
- /* Language based forms: */
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','c','m','p'), PANGO_OT_ALL_GLYPHS);
- 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'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','a','l','t'), PANGO_OT_ALL_GLYPHS);
-
- /* Typographical forms: */
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('l','i','g','a'), PANGO_OT_ALL_GLYPHS);
- /* this one should be turned-on/off-able. lets turn off for now. */
- /* maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','l','i','g'), PANGO_OT_ALL_GLYPHS); */
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','s','w','h'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','s','e','t'), PANGO_OT_ALL_GLYPHS);
- }
-
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS,
- arab_tag, &script_index))
- {
- /* Positioning features: */
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','u','r','s'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('k','e','r','n'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','a','r','k'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), PANGO_OT_ALL_GLYPHS);
- }
-
- g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
- (GDestroyNotify)g_object_unref);
- }
-
- return ruleset;
-}
-
-static void
-swap_range (PangoGlyphString *glyphs, int start, int end)
-{
- int i, j;
-
- for (i = start, j = end - 1; i < j; i++, j--)
- {
- PangoGlyphInfo glyph_info;
- gint log_cluster;
-
- glyph_info = glyphs->glyphs[i];
- glyphs->glyphs[i] = glyphs->glyphs[j];
- glyphs->glyphs[j] = glyph_info;
-
- log_cluster = glyphs->log_clusters[i];
- glyphs->log_clusters[i] = glyphs->log_clusters[j];
- glyphs->log_clusters[j] = log_cluster;
- }
-}
-
-static void
-set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
-{
- glyphs->glyphs[i].glyph = glyph;
- glyphs->log_clusters[i] = offset;
-}
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"isol", isolated},
+ {"fina", final},
+ {"medi", medial},
+ {"init", initial},
+ {"rlig", PANGO_OT_ALL_GLYPHS},
+ {"calt", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ /* 'dlig' should be turned-on/off-able. lets turn off for now. */
+ /* {"dlig", PANGO_OT_ALL_GLYPHS}, */
+ {"cswh", PANGO_OT_ALL_GLYPHS},
+ {"mset", PANGO_OT_ALL_GLYPHS}
+};
-static void
-fallback_shape (PangoEngineShape *engine,
- PangoFont *font,
- const char *text,
- gint length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
+static const PangoOTFeatureMap gpos_features[] =
{
- PangoFcFont *fc_font = PANGO_FC_FONT (font);
- glong n_chars = g_utf8_strlen (text, length);
- 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];
-
- wc = g_utf8_get_char (p);
-
- if (analysis->level % 2)
- if (pango_get_mirror_char (wc, &mirrored_ch))
- {
- wc = mirrored_ch;
-
- g_unichar_to_utf8 (wc, buf);
- }
-
- if (pango_is_zero_width (wc))
- {
- set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
- }
- else
- {
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- index = PANGO_GET_UNKNOWN_GLYPH ( 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);
- }
-}
+ {"curs", PANGO_OT_ALL_GLYPHS},
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
static void
arabic_engine_shape (PangoEngineShape *engine,
@@ -253,7 +84,8 @@ arabic_engine_shape (PangoEngineShape *engine,
{
PangoFcFont *fc_font;
FT_Face face;
- PangoOTRuleset *ruleset;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
PangoOTBuffer *buffer;
gulong *properties = NULL;
glong n_chars;
@@ -272,12 +104,19 @@ arabic_engine_shape (PangoEngineShape *engine,
if (!face)
return;
- ruleset = get_ruleset (face);
- if (!ruleset)
- {
- fallback_shape (engine, font, text, length, analysis, glyphs);
- goto out;
- }
+ 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 (pango_ot_info_get (face), &desc);
buffer = pango_ot_buffer_new (fc_font);
pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
@@ -294,64 +133,52 @@ arabic_engine_shape (PangoEngineShape *engine,
for (i=0; i < n_chars; i++)
{
gunichar wc;
- gunichar mirrored_ch;
- PangoGlyph index;
- char buf[6];
+ PangoGlyph glyph;
wc = g_utf8_get_char (p);
- if (analysis->level % 2)
- if (pango_get_mirror_char (wc, &mirrored_ch))
- {
- wc = mirrored_ch;
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
- g_unichar_to_utf8 (wc, buf);
- }
-
- if (pango_is_zero_width (wc)) /* Zero-width characters */
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GLYPH_EMPTY, properties[i], 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);
+
/* Hack - Microsoft fonts are strange and don't contain the
* correct rules to shape ARABIC LETTER FARSI YEH in
* medial/initial position. It looks identical to ARABIC LETTER
* YEH in these positions, so we substitute if the font contains
* ARABIC LETTER YEH
*/
- if (wc == 0x6cc && ruleset && pango_fc_font_get_glyph (fc_font, 0x64a) &&
- ((properties[i] & (initial | medial)) != (initial | medial)))
- wc = 0x64a;
-
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GET_UNKNOWN_GLYPH ( wc),
- properties[i], p - text);
- }
- else
- {
- if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
- cluster = p - text;
-
- pango_ot_buffer_add_glyph (buffer, index,
- properties[i], cluster);
- }
+ if (c == 0x6cc &&
+ ((properties[i] & (initial | medial)) != (initial | medial)) &&
+ pango_fc_font_has_char (fc_font, 0x64a))
+ c = 0x64a;
+
+ 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);
+
pango_ot_ruleset_substitute (ruleset, buffer);
pango_ot_ruleset_position (ruleset, buffer);
pango_ot_buffer_output (buffer, glyphs);
- g_free (properties);
pango_ot_buffer_destroy (buffer);
- out:
pango_fc_font_unlock_face (fc_font);
}
diff --git a/modules/basic/basic-fc.c b/modules/basic/basic-fc.c
index 300dd1f8..f576af1c 100644
--- a/modules/basic/basic-fc.c
+++ b/modules/basic/basic-fc.c
@@ -39,23 +39,27 @@ typedef PangoEngineShapeClass BasicEngineFcClass;
#define RENDER_TYPE PANGO_RENDER_TYPE_FC
static PangoEngineScriptInfo basic_scripts[] = {
+ /* Listed in OpenType "Standard scripts" standard */
+ { PANGO_SCRIPT_LATIN, "*" },
+ { PANGO_SCRIPT_CYRILLIC, "*" },
+ { PANGO_SCRIPT_GREEK, "*" },
{ PANGO_SCRIPT_ARMENIAN, "*" },
+ { PANGO_SCRIPT_GEORGIAN, "*" },
+ { PANGO_SCRIPT_RUNIC, "*" },
+ { PANGO_SCRIPT_OGHAM, "*" },
+
+ /* The following are simple and can be shaped easily too */
+
{ PANGO_SCRIPT_BOPOMOFO, "*" },
{ PANGO_SCRIPT_CHEROKEE, "*" },
{ PANGO_SCRIPT_COPTIC, "*" },
- { PANGO_SCRIPT_CYRILLIC, "*" },
{ PANGO_SCRIPT_DESERET, "*" },
{ PANGO_SCRIPT_ETHIOPIC, "*" },
- { PANGO_SCRIPT_GEORGIAN, "*" },
{ PANGO_SCRIPT_GOTHIC, "*" },
- { PANGO_SCRIPT_GREEK, "*" },
{ PANGO_SCRIPT_HAN, "*" },
{ PANGO_SCRIPT_HIRAGANA, "*" },
{ PANGO_SCRIPT_KATAKANA, "*" },
- { PANGO_SCRIPT_LATIN, "*" },
- { PANGO_SCRIPT_OGHAM, "*" },
{ PANGO_SCRIPT_OLD_ITALIC, "*" },
- { PANGO_SCRIPT_RUNIC, "*" },
{ PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
{ PANGO_SCRIPT_YI, "*" },
@@ -75,6 +79,7 @@ static PangoEngineScriptInfo basic_scripts[] = {
{ PANGO_SCRIPT_CUNEIFORM, "*" },
{ PANGO_SCRIPT_PHOENICIAN, "*" },
+ /* In fact any script we don't know how to shape can go here */
{ PANGO_SCRIPT_COMMON, "" }
};
@@ -87,220 +92,28 @@ static PangoEngineInfo script_engines[] = {
}
};
-static void
-swap_range (PangoGlyphString *glyphs,
- int start,
- int end)
-{
- int i, j;
-
- for (i = start, j = end - 1; i < j; i++, j--)
- {
- PangoGlyphInfo glyph_info;
- gint log_cluster;
-
- glyph_info = glyphs->glyphs[i];
- glyphs->glyphs[i] = glyphs->glyphs[j];
- glyphs->glyphs[j] = glyph_info;
-
- log_cluster = glyphs->log_clusters[i];
- glyphs->log_clusters[i] = glyphs->log_clusters[j];
- glyphs->log_clusters[j] = log_cluster;
- }
-}
-
-static void
-set_glyph (PangoFont *font,
- PangoGlyphString *glyphs,
- int i,
- int offset,
- PangoGlyph glyph)
-{
- PangoRectangle logical_rect;
-
- glyphs->glyphs[i].glyph = glyph;
-
- glyphs->glyphs[i].geometry.x_offset = 0;
- glyphs->glyphs[i].geometry.y_offset = 0;
-
- glyphs->log_clusters[i] = offset;
-
- pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
- glyphs->glyphs[i].geometry.width = logical_rect.width;
-}
-
-static void
-fallback_shape (PangoEngineShape *engine,
- PangoFont *font,
- const char *text,
- gint length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
-{
- PangoFcFont *fc_font = PANGO_FC_FONT (font);
- glong n_chars = g_utf8_strlen (text, length);
- 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];
-
- wc = g_utf8_get_char (p);
-
- if (analysis->level % 2)
- if (pango_get_mirror_char (wc, &mirrored_ch))
- {
- wc = mirrored_ch;
-
- g_unichar_to_utf8 (wc, buf);
- }
-
- if (wc == 0xa0) /* non-break-space */
- wc = 0x20;
-
- if (pango_is_zero_width (wc))
- {
- set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
- }
- else
- {
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- {
- index = PANGO_GET_UNKNOWN_GLYPH ( wc);
- set_glyph (font, glyphs, i, p - text, index);
- }
- else
- {
- set_glyph (font, glyphs, i, p - text, index);
-
- if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
- {
- if (i > 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;
- glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
-
- /* 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;
- }
- }
- }
- }
-
- p = g_utf8_next_char (p);
- }
-
- if (analysis->level % 2 != 0)
- {
- /* Swap all glyphs */
- swap_range (glyphs, 0, glyphs->num_glyphs);
- }
-}
-
-static const gchar scripts[][5] =
+static const PangoOTFeatureMap gsub_features[] =
{
- "latn",
- "cyrl",
- "grek",
- "armn",
- "geor",
- "runr",
- "ogam"
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ {"clig", PANGO_OT_ALL_GLYPHS}
};
-static const gchar gsub_features[][5] =
+static const PangoOTFeatureMap gpos_features[] =
{
- "ccmp",
- "liga",
- "clig",
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
};
-static const gchar gpos_features[][5] =
+static const PangoOTFeatureMap vertical_gsub_features[] =
{
- "kern",
- "mark",
- "mkmk"
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"vert", PANGO_OT_ALL_GLYPHS}
};
-static PangoOTRuleset *
-get_ruleset (FT_Face face)
-{
- PangoOTRuleset *ruleset;
- PangoOTInfo *info = NULL;
- static GQuark ruleset_quark = 0;
- unsigned int i, j;
-
- info = pango_ot_info_get (face);
- if (!info)
- return NULL;
-
- if (!ruleset_quark)
- ruleset_quark = g_quark_from_string ("pango-basic-ruleset");
-
- ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);
-
- if (!ruleset)
- {
- ruleset = pango_ot_ruleset_new (info);
-
- for (i = 0; i < G_N_ELEMENTS (scripts); i++)
- {
- PangoOTTag script_tag = FT_MAKE_TAG (scripts[i][0], scripts[i][1], scripts[i][2], scripts[i][3]);
- guint script_index;
-
-
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS, script_tag, &script_index))
- for (j = 0; j < G_N_ELEMENTS (gpos_features); j++)
- {
- PangoOTTag feature_tag = FT_MAKE_TAG (gpos_features[j][0], gpos_features[j][1],
- gpos_features[j][2], gpos_features[j][3]);
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GPOS, feature_tag, script_index, PANGO_OT_DEFAULT_LANGUAGE ,&feature_index))
- {
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GPOS, feature_index, PANGO_OT_ALL_GLYPHS);
- }
- }
-
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB, script_tag, &script_index))
- for (j = 0; j < G_N_ELEMENTS (gsub_features); j++)
- {
- PangoOTTag feature_tag = FT_MAKE_TAG (gsub_features[j][0], gsub_features[j][1],
- gsub_features[j][2], gsub_features[j][3]);
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GSUB, feature_tag,
- script_index, PANGO_OT_DEFAULT_LANGUAGE, &feature_index))
- {
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GSUB, feature_index, PANGO_OT_ALL_GLYPHS);
- }
- }
- }
-
- g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset, (GDestroyNotify) g_object_unref);
- }
-
- return ruleset;
-
-}
-
static void
basic_engine_shape (PangoEngineShape *engine,
PangoFont *font,
@@ -311,14 +124,13 @@ basic_engine_shape (PangoEngineShape *engine,
{
PangoFcFont *fc_font;
FT_Face face;
- PangoOTRuleset *ruleset;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
PangoOTBuffer *buffer;
- gint unknown_property = 0;
glong n_chars;
const char *p;
int cluster = 0;
int i;
- gboolean vertical;
g_return_if_fail (font != NULL);
g_return_if_fail (text != NULL);
@@ -330,21 +142,30 @@ basic_engine_shape (PangoEngineShape *engine,
if (!face)
return;
- vertical = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity);
- if (vertical)
+ desc.script = analysis->script;
+ desc.language = analysis->language;
+
+ if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
{
- fallback_shape (engine, font, text, length, analysis, glyphs);
- goto out;
+ desc.n_static_gsub_features = G_N_ELEMENTS (vertical_gsub_features);
+ desc.static_gsub_features = vertical_gsub_features;
+ desc.n_static_gpos_features = 0;
+ desc.static_gpos_features = NULL;
}
-
- ruleset = get_ruleset (face);
- if (!ruleset)
+ else
{
- fallback_shape (engine, font, text, length, analysis, glyphs);
- pango_fc_font_kern_glyphs (fc_font, glyphs);
- goto out;
+ 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 (pango_ot_info_get (face), &desc);
+
buffer = pango_ot_buffer_new (fc_font);
pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
@@ -355,42 +176,30 @@ basic_engine_shape (PangoEngineShape *engine,
for (i=0; i < n_chars; i++)
{
gunichar wc;
- gunichar mirrored_ch;
- PangoGlyph index;
- char buf[6];
+ PangoGlyph glyph;
wc = g_utf8_get_char (p);
- if (analysis->level % 2)
- if (pango_get_mirror_char (wc, &mirrored_ch))
- {
- wc = mirrored_ch;
- g_unichar_to_utf8 (wc, buf);
- }
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
- if (pango_is_zero_width (wc)) /* Zero-width characters */
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GLYPH_EMPTY, unknown_property, p - text);
- }
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
else
- {
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GET_UNKNOWN_GLYPH ( wc),
- unknown_property, p - text);
- }
- else
- {
- if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
- cluster = p - text;
-
- pango_ot_buffer_add_glyph (buffer, index,
- unknown_property, cluster);
- }
+ {
+ 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, 0, cluster);
+
p = g_utf8_next_char (p);
}
@@ -401,7 +210,6 @@ basic_engine_shape (PangoEngineShape *engine,
pango_ot_buffer_destroy (buffer);
-out:
pango_fc_font_unlock_face (fc_font);
}
diff --git a/modules/syriac/syriac-fc.c b/modules/syriac/syriac-fc.c
index 3065ceba..b024cb14 100644
--- a/modules/syriac/syriac-fc.c
+++ b/modules/syriac/syriac-fc.c
@@ -51,190 +51,30 @@ static PangoEngineInfo script_engines[] = {
}
};
-static void
-maybe_add_gsub_feature (PangoOTRuleset *ruleset,
- PangoOTInfo *info,
- guint script_index,
- PangoOTTag tag,
- gulong property_bit)
-{
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GSUB,
- tag, script_index, PANGO_OT_DEFAULT_LANGUAGE, &feature_index))
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GSUB, feature_index,
- property_bit);
-}
-
-static void
-maybe_add_gpos_feature (PangoOTRuleset *ruleset,
- PangoOTInfo *info,
- guint script_index,
- PangoOTTag tag,
- gulong property_bit)
+static const PangoOTFeatureMap gsub_features[] =
{
- guint feature_index;
-
- if (pango_ot_info_find_feature (info, PANGO_OT_TABLE_GPOS,
- tag, script_index, PANGO_OT_DEFAULT_LANGUAGE, &feature_index))
- pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GPOS, feature_index,
- property_bit);
-}
-
-static PangoOTRuleset *
-get_ruleset (FT_Face face)
-{
- PangoOTRuleset *ruleset;
- static GQuark ruleset_quark = 0;
-
- PangoOTInfo *info = pango_ot_info_get (face);
-
- if (!ruleset_quark)
- ruleset_quark = g_quark_from_string ("pango-syriac-ruleset");
-
- if (!info)
- return NULL;
-
- ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);
-
- if (!ruleset)
- {
- PangoOTTag syrc_tag = FT_MAKE_TAG ('s', 'y', 'r', 'c');
- guint script_index;
-
- ruleset = pango_ot_ruleset_new (info);
-
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB,
- syrc_tag, &script_index))
- {
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','c','m','p'), PANGO_OT_ALL_GLYPHS);
- 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 ('f','i','n','2'), final2);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','3'), final3);
- 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 ('m','e','d','2'), medial2);
- 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'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','a','l','t'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('l','i','g','a'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','l','i','g'), PANGO_OT_ALL_GLYPHS);
- }
-
- if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS,
- syrc_tag, &script_index))
- {
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('k','e','r','n'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','a','r','k'), PANGO_OT_ALL_GLYPHS);
- maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), PANGO_OT_ALL_GLYPHS);
- }
-
- g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
- (GDestroyNotify)g_object_unref);
- }
-
- return ruleset;
-}
-
-static void
-swap_range (PangoGlyphString *glyphs, int start, int end)
-{
- int i, j;
-
- for (i = start, j = end - 1; i < j; i++, j--)
- {
- PangoGlyphInfo glyph_info;
- gint log_cluster;
-
- glyph_info = glyphs->glyphs[i];
- glyphs->glyphs[i] = glyphs->glyphs[j];
- glyphs->glyphs[j] = glyph_info;
-
- log_cluster = glyphs->log_clusters[i];
- glyphs->log_clusters[i] = glyphs->log_clusters[j];
- glyphs->log_clusters[j] = log_cluster;
- }
-}
-
-static void
-set_glyph (PangoFont *font,
- PangoGlyphString *glyphs,
- int i,
- int offset,
- PangoGlyph glyph)
-{
- glyphs->glyphs[i].glyph = glyph;
- glyphs->log_clusters[i] = offset;
-}
+ {"ccmp", PANGO_OT_ALL_GLYPHS},
+ {"locl", PANGO_OT_ALL_GLYPHS},
+ {"isol", isolated},
+ {"fina", final},
+ {"fin2", final2},
+ {"fin3", final3},
+ {"medi", medial},
+ {"med2", medial2},
+ {"init", initial},
+ {"rlig", PANGO_OT_ALL_GLYPHS},
+ {"calt", PANGO_OT_ALL_GLYPHS},
+ {"liga", PANGO_OT_ALL_GLYPHS},
+ /* 'dlig' should be turned-on/off-able. lets turn off for now. */
+ /* {"dlig", PANGO_OT_ALL_GLYPHS}, */
+};
-static void
-fallback_shape (PangoEngineShape *engine,
- PangoFont *font,
- const char *text,
- gint length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
+static const PangoOTFeatureMap gpos_features[] =
{
- PangoFcFont *fc_font = PANGO_FC_FONT (font);
- glong n_chars = g_utf8_strlen (text, length);
- 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;
-
- wc = g_utf8_get_char (p);
-
- if ((analysis->level % 2) &&
- pango_get_mirror_char (wc, &mirrored_ch))
- wc = mirrored_ch;
-
- if (pango_is_zero_width (wc))
- {
- set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
- }
- else
- {
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- index = PANGO_GET_UNKNOWN_GLYPH ( 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);
- }
-}
+ {"kern", PANGO_OT_ALL_GLYPHS},
+ {"mark", PANGO_OT_ALL_GLYPHS},
+ {"mkmk", PANGO_OT_ALL_GLYPHS}
+};
static void
syriac_engine_shape (PangoEngineShape *engine,
@@ -246,7 +86,8 @@ syriac_engine_shape (PangoEngineShape *engine,
{
PangoFcFont *fc_font;
FT_Face face;
- PangoOTRuleset *ruleset;
+ PangoOTRulesetDescription desc;
+ const PangoOTRuleset *ruleset;
PangoOTBuffer *buffer;
gulong *properties = NULL;
glong n_chars;
@@ -265,12 +106,19 @@ syriac_engine_shape (PangoEngineShape *engine,
if (!face)
return;
- ruleset = get_ruleset (face);
- if (!ruleset)
- {
- fallback_shape (engine, font, text, length, analysis, glyphs);
- goto out;
- }
+ 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 (pango_ot_info_get (face), &desc);
buffer = pango_ot_buffer_new (fc_font);
pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
@@ -287,49 +135,41 @@ syriac_engine_shape (PangoEngineShape *engine,
for (i=0; i < n_chars; i++)
{
gunichar wc;
- gunichar mirrored_ch;
- PangoGlyph index;
+ PangoGlyph glyph;
wc = g_utf8_get_char (p);
- if ((analysis->level % 2) &&
- pango_get_mirror_char (wc, &mirrored_ch))
- wc = mirrored_ch;
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
if (pango_is_zero_width (wc))
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GLYPH_EMPTY, properties[i], p - text);
- }
+ glyph = PANGO_GLYPH_EMPTY;
else
- {
- index = pango_fc_font_get_glyph (fc_font, wc);
-
- if (!index)
- {
- pango_ot_buffer_add_glyph (buffer, PANGO_GET_UNKNOWN_GLYPH ( wc),
- properties[i], p - text);
- }
- else
- {
- if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
- cluster = p - text;
-
- pango_ot_buffer_add_glyph (buffer, index,
- properties[i], cluster);
- }
+ {
+ 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);
+
pango_ot_ruleset_substitute (ruleset, buffer);
pango_ot_ruleset_position (ruleset, buffer);
pango_ot_buffer_output (buffer, glyphs);
- g_free (properties);
pango_ot_buffer_destroy (buffer);
- out:
pango_fc_font_unlock_face (fc_font);
}