summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}