summaryrefslogtreecommitdiff
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
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.
-rw-r--r--ChangeLog34
-rw-r--r--ChangeLog.pre-1-1034
-rw-r--r--ChangeLog.pre-1-434
-rw-r--r--ChangeLog.pre-1-634
-rw-r--r--ChangeLog.pre-1-834
-rw-r--r--docs/tmpl/opentype.sgml14
-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
-rw-r--r--pango/opentype/Makefile.am3
-rw-r--r--pango/opentype/ftxgdef.c4
-rw-r--r--pango/opentype/ftxgpos.c573
-rw-r--r--pango/opentype/ftxgpos.h23
-rw-r--r--pango/opentype/ftxgsub.c719
-rw-r--r--pango/opentype/ftxgsub.h40
-rw-r--r--pango/opentype/ftxopen.h1
-rw-r--r--pango/opentype/otlbuffer.c213
-rw-r--r--pango/opentype/otlbuffer.h97
-rw-r--r--pango/opentype/ottest.c2
-rw-r--r--pango/opentype/pango-ot-buffer.c265
-rw-r--r--pango/opentype/pango-ot-info.c27
-rw-r--r--pango/opentype/pango-ot-private.h8
-rw-r--r--pango/opentype/pango-ot-ruleset.c148
-rw-r--r--pango/pango-ot.h38
27 files changed, 1426 insertions, 1250 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f5f45dc..b34e1560 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+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.
+
2004-02-28 Hans Breuer <hans@breuer.org>
* pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10
index 7f5f45dc..b34e1560 100644
--- a/ChangeLog.pre-1-10
+++ b/ChangeLog.pre-1-10
@@ -1,3 +1,37 @@
+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.
+
2004-02-28 Hans Breuer <hans@breuer.org>
* pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4
index 7f5f45dc..b34e1560 100644
--- a/ChangeLog.pre-1-4
+++ b/ChangeLog.pre-1-4
@@ -1,3 +1,37 @@
+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.
+
2004-02-28 Hans Breuer <hans@breuer.org>
* pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6
index 7f5f45dc..b34e1560 100644
--- a/ChangeLog.pre-1-6
+++ b/ChangeLog.pre-1-6
@@ -1,3 +1,37 @@
+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.
+
2004-02-28 Hans Breuer <hans@breuer.org>
* pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8
index 7f5f45dc..b34e1560 100644
--- a/ChangeLog.pre-1-8
+++ b/ChangeLog.pre-1-8
@@ -1,3 +1,37 @@
+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.
+
2004-02-28 Hans Breuer <hans@breuer.org>
* pango/modules/basic/basic-win32.c : use uniscribe_scripts instead of
diff --git a/docs/tmpl/opentype.sgml b/docs/tmpl/opentype.sgml
index 19c554fe..1cd93ffe 100644
--- a/docs/tmpl/opentype.sgml
+++ b/docs/tmpl/opentype.sgml
@@ -61,8 +61,10 @@ identify the various OpenType tables in the
</para>
-@face:
+@font:
@Returns:
+<!-- # Unused Parameters # -->
+@face:
<!-- ##### FUNCTION pango_ot_info_find_script ##### -->
@@ -160,13 +162,3 @@ identify the various OpenType tables in the
@property_bit:
-<!-- ##### FUNCTION pango_ot_ruleset_shape ##### -->
-<para>
-
-</para>
-
-@ruleset:
-@glyphs:
-@properties:
-
-
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
diff --git a/pango/opentype/Makefile.am b/pango/opentype/Makefile.am
index 969b2dbc..4634b8ca 100644
--- a/pango/opentype/Makefile.am
+++ b/pango/opentype/Makefile.am
@@ -30,6 +30,9 @@ libpango_ot_la_SOURCES = \
ftxgpos.h \
ftxgsub.c \
ftxgsub.h \
+ otlbuffer.c \
+ otlbuffer.h \
+ pango-ot-buffer.c \
pango-ot-info.c \
pango-ot-private.h \
pango-ot-ruleset.c
diff --git a/pango/opentype/ftxgdef.c b/pango/opentype/ftxgdef.c
index 36146970..9077490b 100644
--- a/pango/opentype/ftxgdef.c
+++ b/pango/opentype/ftxgdef.c
@@ -761,7 +761,7 @@
if ( glyphID < gcrr[index].Start )
{
- array_index = 0;
+ array_index = index;
if ( index == 0 )
glyph_index = glyphID;
else
@@ -1129,7 +1129,7 @@
if ( glyphID < gcrr[index].Start )
{
- array_index = 0;
+ array_index = index;
if ( index == 0 )
glyph_index = glyphID;
else
diff --git a/pango/opentype/ftxgpos.c b/pango/opentype/ftxgpos.c
index 8d9a7d48..8bbddcdd 100644
--- a/pango/opentype/ftxgpos.c
+++ b/pango/opentype/ftxgpos.c
@@ -42,8 +42,6 @@
FT_UShort load_flags; /* how the glyph should be loaded */
FT_Bool r2l;
- FT_UShort first; /* the first glyph in a chain of
- cursive connections */
FT_UShort last; /* the last valid glyph -- used
with cursive positioning */
FT_Pos anchor_x; /* the coordinates of the anchor point */
@@ -55,13 +53,19 @@
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level );
- /* the client application must replace this with something more
+#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
+#define IN_CURGLYPH( pos ) (buffer->in_string[(pos) + buffer->in_pos].gindex)
+#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
+#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
+#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
+#define POSITION( pos ) (&buffer->positions[(pos)])
+
+/* the client application must replace this with something more
meaningful if multiple master fonts are to be supported. */
static FT_Error default_mmfunc( FT_Face face,
@@ -73,100 +77,6 @@
}
-#if 0
-#define GPOS_ID Build_Extension_ID( 'G', 'P', 'O', 'S' )
-
- /**********************
- * Extension Functions
- **********************/
-
- static FT_Error GPOS_Create( void* ext,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext;
- FT_Long table;
-
-
- /* by convention */
-
- if ( !gpos )
- return TT_Err_Ok;
-
- /* a null offset indicates that there is no GPOS table */
-
- gpos->offset = 0;
-
- /* we store the start offset and the size of the subtable */
-
- table = face->lookup_table ( face, TTAG_GPOS );
- if ( table < 0 )
- return TT_Err_Ok; /* The table is optional */
-
- if ( FILE_Seek( face->dirTables[table].Offset ) ||
- ACCESS_Frame( 4L ) )
- return error;
-
- gpos->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
- gpos->Version = GET_ULong();
-
- FORGET_Frame();
-
- /* a default mmfunc() handler which just returns an error */
-
- gpos->mmfunc = default_mmfunc;
-
- /* the default glyph function is TT_Load_Glyph() */
-
- gpos->gfunc = FT_Load_Glyph;
-
- gpos->loaded = FALSE;
-
- return TT_Err_Ok;
- }
-
-
- static FT_Error GPOS_Destroy( void* ext,
- PFace face )
- {
- TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext;
-
-
- /* by convention */
-
- if ( !gpos )
- return TT_Err_Ok;
-
- if ( gpos->loaded )
- {
- Free_LookupList( &gpos->LookupList, GPOS );
- Free_FeatureList( &gpos->FeatureList );
- Free_ScriptList( &gpos->ScriptList );
- }
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_Init_GPOS_Extension( TT_Engine engine )
- {
- PEngine_Instance _engine = HANDLE_Engine( engine );
-
-
- if ( !_engine )
- return TT_Err_Invalid_Engine;
-
- return TT_Register_Extension( _engine,
- GPOS_ID,
- sizeof ( TTO_GPOSHeader ),
- GPOS_Create,
- GPOS_Destroy );
- }
-#endif
-
EXPORT_FUNC
FT_Error TT_Load_GPOS_Table( FT_Face face,
TTO_GPOSHeader** retptr,
@@ -584,7 +494,7 @@
static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
TTO_ValueRecord* vr,
FT_UShort format,
- TTO_GPOS_Data* gd )
+ OTL_Position gd )
{
FT_Pos value;
FT_Short pixel_value;
@@ -1123,8 +1033,7 @@
static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
TTO_SinglePos* sp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -1136,10 +1045,10 @@
if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &sp->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &sp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -1147,7 +1056,7 @@
{
case 1:
error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
- sp->ValueFormat, &out[in->pos] );
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error )
return error;
break;
@@ -1156,7 +1065,7 @@
if ( index >= sp->spf.spf2.ValueCount )
return TTO_Err_Invalid_GPOS_SubTable;
error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
- sp->ValueFormat, &out[in->pos] );
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error )
return error;
break;
@@ -1165,7 +1074,7 @@
return TTO_Err_Invalid_GPOS_SubTable;
}
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
@@ -1606,8 +1515,7 @@
static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
TTO_PairPosFormat1* ppf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort first_pos,
FT_UShort index,
FT_UShort format1,
@@ -1626,7 +1534,7 @@
if ( !pvr )
return TTO_Err_Invalid_GPOS_SubTable;
- glyph2 = in->string[in->pos];
+ glyph2 = IN_CURGLYPH( 0 );
for ( numpvr = ppf1->PairSet[index].PairValueCount;
numpvr;
@@ -1635,11 +1543,11 @@
if ( glyph2 == pvr->SecondGlyph )
{
error = Get_ValueRecord( gpi, &pvr->Value1, format1,
- &out[first_pos] );
+ POSITION( first_pos ) );
if ( error )
return error;
return Get_ValueRecord( gpi, &pvr->Value2, format2,
- &out[in->pos] );
+ POSITION( buffer->in_pos ) );
}
}
@@ -1649,8 +1557,7 @@
static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
TTO_PairPosFormat2* ppf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort first_pos,
FT_UShort format1,
FT_UShort format2 )
@@ -1662,11 +1569,11 @@
TTO_Class2Record* c2r;
- error = Get_Class( &ppf2->ClassDef1, in->string[first_pos],
+ error = Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
&cl1, NULL );
if ( error && error != TTO_Err_Not_Covered )
return error;
- error = Get_Class( &ppf2->ClassDef2, in->string[in->pos],
+ error = Get_Class( &ppf2->ClassDef2, IN_CURGLYPH( 0 ),
&cl2, NULL );
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -1676,17 +1583,16 @@
return TTO_Err_Invalid_GPOS_SubTable;
c2r = &c1r->Class2Record[cl2];
- error = Get_ValueRecord( gpi, &c2r->Value1, format1, &out[first_pos] );
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
if ( error )
return error;
- return Get_ValueRecord( gpi, &c2r->Value2, format2, &out[in->pos] );
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
}
static FT_Error Lookup_PairPos( GPOS_Instance* gpi,
TTO_PairPos* pp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -1695,32 +1601,32 @@
TTO_GPOSHeader* gpos = gpi->gpos;
- if ( in->pos >= in->length - 1 )
+ if ( buffer->in_pos >= buffer->in_length - 1 )
return TTO_Err_Not_Covered; /* Not enough glyphs in stream */
if ( context_length != 0xFFFF && context_length < 2 )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &pp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
/* second glyph */
- first_pos = in->pos;
- (in->pos)++;
+ first_pos = buffer->in_pos;
+ (buffer->in_pos)++;
- while ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ while ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos < in->length )
- (in->pos)++;
+ if ( buffer->in_pos < buffer->in_length )
+ (buffer->in_pos)++;
else
break;
}
@@ -1728,13 +1634,13 @@
switch ( pp->PosFormat )
{
case 1:
- error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out,
+ error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
first_pos, index,
pp->ValueFormat1, pp->ValueFormat2 );
break;
case 2:
- error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, in, out, first_pos,
+ error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
pp->ValueFormat1, pp->ValueFormat2 );
break;
@@ -1745,7 +1651,7 @@
/* adjusting the `next' glyph */
if ( pp->ValueFormat2 )
- (in->pos)++;
+ (buffer->in_pos)++;
return error;
}
@@ -1893,8 +1799,7 @@
static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
TTO_CursivePos* cp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -1916,7 +1821,7 @@
/* Glyphs not having the right GDEF properties will be ignored, i.e.,
gpi->last won't be reset (contrary to user defined properties). */
- if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* We don't handle mark glyphs here. According to Andrei, this isn't
@@ -1928,7 +1833,7 @@
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &cp->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &cp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
{
gpi->last = 0xFFFF;
@@ -2063,7 +1968,7 @@
/* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor
table. */
- error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos],
+ error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH( 0 ),
&entry_x, &entry_y );
if ( error == TTO_Err_Not_Covered )
goto end;
@@ -2072,34 +1977,41 @@
if ( gpi->r2l )
{
- out[in->pos].x_advance = entry_x - gpi->anchor_x;
- out[in->pos].new_advance = TRUE;
+ POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
+ POSITION( buffer->in_pos )->new_advance = TRUE;
}
else
{
- out[gpi->last].x_advance = gpi->anchor_x - entry_x;
- out[gpi->last].new_advance = TRUE;
+ POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
+ POSITION( gpi->last )->new_advance = TRUE;
}
- out[in->pos].y_pos = gpi->anchor_y - entry_y + out[gpi->last].y_pos;
+ if ( flags & RIGHT_TO_LEFT )
+ {
+ POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
+ POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
+ }
+ else
+ {
+ POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
+ POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
+ }
end:
- error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos],
+ error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH( 0 ),
&exit_x, &exit_y );
if ( error == TTO_Err_Not_Covered )
gpi->last = 0xFFFF;
else
{
- if ( gpi->first == 0xFFFF )
- gpi->first = in->pos;
- gpi->last = in->pos;
+ gpi->last = buffer->in_pos;
gpi->anchor_x = exit_x;
gpi->anchor_y = exit_y;
}
if ( error )
return error;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
@@ -2312,8 +2224,7 @@
static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
TTO_MarkBasePos* mbp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -2328,7 +2239,7 @@
TTO_Anchor* mark_anchor;
TTO_Anchor* base_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
@@ -2337,11 +2248,11 @@
if ( flags & IGNORE_BASE_GLYPHS )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
return error;
- error = Coverage_Index( &mbp->MarkCoverage, in->string[in->pos],
+ error = Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH( 0 ),
&mark_index );
if ( error )
return error;
@@ -2349,11 +2260,11 @@
/* now we search backwards for a non-mark glyph */
i = 1;
- j = in->pos - 1;
+ j = buffer->in_pos - 1;
- while ( i <= in->pos )
+ while ( i <= buffer->in_pos )
{
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j],
+ error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property );
if ( error )
return error;
@@ -2371,10 +2282,10 @@
return TTO_Err_Not_Covered;
#endif
- if ( i > in->pos )
+ if ( i > buffer->in_pos )
return TTO_Err_Not_Covered;
- error = Coverage_Index( &mbp->BaseCoverage, in->string[j],
+ error = Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
&base_index );
if ( error )
return error;
@@ -2398,19 +2309,19 @@
br = &ba->BaseRecord[base_index];
base_anchor = &br->BaseAnchor[class];
- error = Get_Anchor( gpi, mark_anchor, in->string[in->pos],
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH( 0 ),
&x_mark_value, &y_mark_value );
if ( error )
return error;
- error = Get_Anchor( gpi, base_anchor, in->string[j],
+ error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
&x_base_value, &y_base_value );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_base_value - x_mark_value;
o->y_pos = y_base_value - y_mark_value;
@@ -2418,7 +2329,7 @@
o->y_advance = 0;
o->back = i;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
@@ -2720,8 +2631,7 @@
static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
TTO_MarkLigPos* mlp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -2739,7 +2649,7 @@
TTO_Anchor* mark_anchor;
TTO_Anchor* lig_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
@@ -2748,7 +2658,7 @@
if ( flags & IGNORE_LIGATURES )
return TTO_Err_Not_Covered;
- mark_glyph = in->string[in->pos];
+ mark_glyph = IN_CURGLYPH( 0 );
if ( CHECK_Property( gpos->gdef, mark_glyph, flags, &property ) )
return error;
@@ -2760,11 +2670,11 @@
/* now we search backwards for a non-mark glyph */
i = 1;
- j = in->pos - 1;
+ j = buffer->in_pos - 1;
- while ( i <= in->pos )
+ while ( i <= buffer->in_pos )
{
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j],
+ error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property );
if ( error )
return error;
@@ -2783,10 +2693,10 @@
return TTO_Err_Not_Covered;
#endif
- if ( i > in->pos )
+ if ( i > buffer->in_pos )
return TTO_Err_Not_Covered;
- error = Coverage_Index( &mlp->LigatureCoverage, in->string[j],
+ error = Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
&lig_index );
if ( error )
return error;
@@ -2814,10 +2724,9 @@
can directly use the component index. If not, we attach the mark
glyph to the last component of the ligature. */
- if ( in->ligIDs && in->components &&
- in->ligIDs[j] == in->ligIDs[in->pos] )
+ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
{
- comp_index = in->components[in->pos];
+ comp_index = IN_COMPONENT( buffer->in_pos );
if ( comp_index >= lat->ComponentCount )
return TTO_Err_Not_Covered;
}
@@ -2827,18 +2736,18 @@
cr = &lat->ComponentRecord[comp_index];
lig_anchor = &cr->LigatureAnchor[class];
- error = Get_Anchor( gpi, mark_anchor, in->string[in->pos],
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH( 0 ),
&x_mark_value, &y_mark_value );
if ( error )
return error;
- error = Get_Anchor( gpi, lig_anchor, in->string[j],
+ error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
&x_lig_value, &y_lig_value );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_lig_value - x_mark_value;
o->y_pos = y_lig_value - y_mark_value;
@@ -2846,7 +2755,7 @@
o->y_advance = 0;
o->back = i;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
@@ -3061,8 +2970,7 @@
static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
TTO_MarkMarkPos* mmp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
@@ -3078,7 +2986,7 @@
TTO_Anchor* mark1_anchor;
TTO_Anchor* mark2_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
@@ -3087,11 +2995,11 @@
if ( flags & IGNORE_MARKS )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
return error;
- error = Coverage_Index( &mmp->Mark1Coverage, in->string[in->pos],
+ error = Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH( 0 ),
&mark1_index );
if ( error )
return error;
@@ -3099,11 +3007,11 @@
/* now we check the preceding glyph whether it is a suitable
mark glyph */
- if ( in->pos == 0 )
+ if ( buffer->in_pos == 0 )
return TTO_Err_Not_Covered;
- j = in->pos - 1;
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j],
+ j = buffer->in_pos - 1;
+ error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property );
if ( error )
return error;
@@ -3119,7 +3027,7 @@
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &mmp->Mark2Coverage, in->string[j],
+ error = Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
&mark2_index );
if ( error )
return error;
@@ -3143,18 +3051,18 @@
m2r = &ma2->Mark2Record[mark2_index];
mark2_anchor = &m2r->Mark2Anchor[class];
- error = Get_Anchor( gpi, mark1_anchor, in->string[in->pos],
+ error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH( 0 ),
&x_mark1_value, &y_mark1_value );
if ( error )
return error;
- error = Get_Anchor( gpi, mark2_anchor, in->string[j],
+ error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
&x_mark2_value, &y_mark2_value );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_mark2_value - x_mark1_value;
o->y_pos = y_mark2_value - y_mark1_value;
@@ -3162,7 +3070,7 @@
o->y_advance = 0;
o->back = 1;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
@@ -3176,8 +3084,7 @@
FT_UShort GlyphCount,
FT_UShort PosCount,
TTO_PosLookupRecord* pos,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
int nesting_level )
{
FT_Error error;
@@ -3190,11 +3097,11 @@
{
if ( PosCount && i == pos->SequenceIndex )
{
- old_pos = in->pos;
+ old_pos = buffer->in_pos;
/* Do a positioning */
- error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, in, out,
+ error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
GlyphCount, nesting_level );
if ( error )
@@ -3202,12 +3109,12 @@
pos++;
PosCount--;
- i += in->pos - old_pos;
+ i += buffer->in_pos - old_pos;
}
else
{
i++;
- (in->pos)++;
+ (buffer->in_pos)++;
}
}
@@ -3928,8 +3835,7 @@
static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
TTO_ContextPosFormat1* cpf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -3937,7 +3843,6 @@
FT_UShort index, property;
FT_UShort i, j, k, numpr;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_PosRule* pr;
@@ -3946,10 +3851,10 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &cpf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &cpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -3961,32 +3866,30 @@
if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
continue;
- if ( in->pos + pr[k].GlyphCount > in->length )
+ if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
-
for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != pr[k].Input[i - 1] )
+ if ( IN_CURGLYPH( j ) != pr[k].Input[i - 1] )
break;
}
if ( i == pr[k].GlyphCount )
return Do_ContextPos( gpi, pr[k].GlyphCount,
pr[k].PosCount, pr[k].PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -3996,8 +3899,7 @@
static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
TTO_ContextPosFormat2* cpf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -4008,7 +3910,6 @@
FT_UShort i, j, k, known_classes;
FT_UShort* classes;
- FT_UShort* s_in;
FT_UShort* cl;
TTO_GPOSHeader* gpos = gpi->gpos;
@@ -4019,21 +3920,21 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to
do any lookup at all. */
- error = Coverage_Index( &cpf2->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &cpf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
return error;
- error = Get_Class( &cpf2->ClassDef, in->string[in->pos],
+ error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
@@ -4053,22 +3954,21 @@
if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
continue;
- if ( in->pos + pr->GlyphCount > in->length )
+ if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
cl = pr->Class;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
@@ -4078,7 +3978,7 @@
{
/* Keeps us from having to do this for each rule */
- error = Get_Class( &cpf2->ClassDef, s_in[j], &classes[i], NULL );
+ error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
known_classes = i;
@@ -4092,7 +3992,7 @@
{
error = Do_ContextPos( gpi, pr->GlyphCount,
pr->PosCount, pr->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End;
}
@@ -4108,15 +4008,13 @@
static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
TTO_ContextPosFormat3* cpf3,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
{
FT_Error error;
FT_UShort index, i, j, property;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* c;
@@ -4125,47 +4023,45 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
return TTO_Err_Not_Covered;
- if ( in->pos + cpf3->GlyphCount > in->length )
+ if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
return TTO_Err_Not_Covered; /* context is too long */
- s_in = &in->string[in->pos];
c = cpf3->Coverage;
for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &c[i], s_in[j], &index );
+ error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index );
if ( error )
return error;
}
return Do_ContextPos( gpi, cpf3->GlyphCount,
cpf3->PosCount, cpf3->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
TTO_ContextPos* cp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -4173,15 +4069,15 @@
switch ( cp->PosFormat )
{
case 1:
- return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, in, out,
+ return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
flags, context_length, nesting_level );
case 2:
- return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, in, out,
+ return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
flags, context_length, nesting_level );
case 3:
- return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, in, out,
+ return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
flags, context_length, nesting_level );
default:
@@ -5210,8 +5106,7 @@
static FT_Error Lookup_ChainContextPos1(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat1* ccpf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -5220,7 +5115,6 @@
FT_UShort i, j, k, num_cpr, curr_pos;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_ChainPosRule* cpr;
@@ -5230,10 +5124,10 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ccpf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -5252,7 +5146,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue;
if ( bgc )
@@ -5261,11 +5155,10 @@
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -5286,7 +5179,7 @@
Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */
- if ( s_in[j] != curr_cpr.Backtrack[i] )
+ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
break;
}
@@ -5294,25 +5187,24 @@
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_cpr.Input[i - 1] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Input[i - 1] )
break;
}
@@ -5323,22 +5215,21 @@
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_cpr.Lookahead[i] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Lookahead[i] )
break;
}
@@ -5346,7 +5237,7 @@
return Do_ContextPos( gpi, igc,
curr_cpr.PosCount,
curr_cpr.PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -5357,8 +5248,7 @@
static FT_Error Lookup_ChainContextPos2(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat2* ccpf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -5376,8 +5266,6 @@
FT_UShort* input_classes;
FT_UShort* lookahead_classes;
- FT_UShort* s_in;
-
FT_UShort* bc;
FT_UShort* ic;
FT_UShort* lc;
@@ -5390,14 +5278,14 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to
do any lookup at all. */
- error = Coverage_Index( &ccpf2->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -5413,7 +5301,7 @@
goto End2;
known_lookahead_classes = 0;
- error = Get_Class( &ccpf2->InputClassDef, in->string[in->pos],
+ error = Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH( 0 ),
&input_classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -5437,7 +5325,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue;
if ( bgc )
@@ -5447,12 +5335,11 @@
Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
- s_in = &in->string[curr_pos];
bc = cpcr.Backtrack;
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -5467,7 +5354,7 @@
{
/* Keeps us from having to do this for each rule */
- error = Get_Class( &ccpf2->BacktrackClassDef, s_in[j],
+ error = Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
&backtrack_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -5482,20 +5369,19 @@
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = cpcr.Input;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
@@ -5503,7 +5389,7 @@
if ( i >= known_input_classes )
{
- error = Get_Class( &ccpf2->InputClassDef, s_in[j],
+ error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( curr_pos + j ),
&input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -5521,17 +5407,16 @@
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = cpcr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
@@ -5539,7 +5424,7 @@
if ( i >= known_lookahead_classes )
{
- error = Get_Class( &ccpf2->LookaheadClassDef, s_in[j],
+ error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ),
&lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -5555,7 +5440,7 @@
error = Do_ContextPos( gpi, igc,
cpcr.PosCount,
cpcr.PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End1;
}
@@ -5578,8 +5463,7 @@
static FT_Error Lookup_ChainContextPos3(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat3* ccpf3,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -5587,7 +5471,6 @@
FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* bc;
@@ -5598,7 +5481,7 @@
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
bgc = ccpf3->BacktrackGlyphCount;
@@ -5610,7 +5493,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
return TTO_Err_Not_Covered;
if ( bgc )
@@ -5619,12 +5502,11 @@
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
bc = ccpf3->BacktrackCoverage;
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -5635,31 +5517,30 @@
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &bc[i], s_in[j], &index );
+ error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
if ( error )
return error;
}
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccpf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ )
{
/* We already called CHECK_Property for s_in[0] */
- while ( j > 0 && CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &ic[i], s_in[j], &index );
+ error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index );
if ( error )
return error;
}
@@ -5668,23 +5549,22 @@
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccpf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &lc[i], s_in[j], &index );
+ error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index );
if ( error )
return error;
}
@@ -5692,7 +5572,7 @@
return Do_ContextPos( gpi, igc,
ccpf3->PosCount,
ccpf3->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -5700,8 +5580,7 @@
static FT_Error Lookup_ChainContextPos(
GPOS_Instance* gpi,
TTO_ChainContextPos* ccp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -5709,17 +5588,17 @@
switch ( ccp->PosFormat )
{
case 1:
- return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, in, out,
+ return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
flags, context_length,
nesting_level );
case 2:
- return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, in, out,
+ return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
flags, context_length,
nesting_level );
case 3:
- return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, in, out,
+ return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
flags, context_length,
nesting_level );
@@ -6025,8 +5904,7 @@
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level )
{
@@ -6051,49 +5929,49 @@
case GPOS_LOOKUP_SINGLE:
error = Lookup_SinglePos( gpi,
&lo->SubTable[i].st.gpos.single,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_PAIR:
error = Lookup_PairPos( gpi,
&lo->SubTable[i].st.gpos.pair,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_CURSIVE:
error = Lookup_CursivePos( gpi,
&lo->SubTable[i].st.gpos.cursive,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKBASE:
error = Lookup_MarkBasePos( gpi,
&lo->SubTable[i].st.gpos.markbase,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKLIG:
error = Lookup_MarkLigPos( gpi,
&lo->SubTable[i].st.gpos.marklig,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKMARK:
error = Lookup_MarkMarkPos( gpi,
&lo->SubTable[i].st.gpos.markmark,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_CONTEXT:
error = Lookup_ContextPos( gpi,
&lo->SubTable[i].st.gpos.context,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
@@ -6101,7 +5979,7 @@
case GPOS_LOOKUP_CHAIN:
error = Lookup_ChainContextPos( gpi,
&lo->SubTable[i].st.gpos.chain,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
@@ -6122,28 +6000,23 @@
static FT_Error Do_String_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
TTO_GPOSHeader* gpos = gpi->gpos;
FT_UShort* properties = gpos->LookupList.Properties;
- FT_UShort* p_in = in->properties;
int nesting_level = 0;
- FT_UShort i;
- FT_Pos offset;
- gpi->first = 0xFFFF;
gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
- in->pos = 0;
+ buffer->in_pos = 0;
- while ( in->pos < in->length )
+ while ( buffer->in_pos < buffer->in_length )
{
- if ( ~p_in[in->pos] & properties[lookup_index] )
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
{
/* 0xFFFF indicates that we don't have a context length yet. */
@@ -6154,7 +6027,7 @@
It is up to the font designer to provide meaningful lookups and
lookup order. */
- error = Do_Glyph_Lookup( gpi, lookup_index, in, out,
+ error = Do_Glyph_Lookup( gpi, lookup_index, buffer,
0xFFFF, nesting_level );
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -6168,24 +6041,8 @@
error = TTO_Err_Not_Covered;
}
- /* test whether we have to adjust the offsets for cursive connections */
-
- if ( gpi->first != 0xFFFF && gpi->last == 0xFFFF &&
- gpos->LookupList.Lookup[lookup_index].LookupFlag & RIGHT_TO_LEFT )
- {
- offset = out[in->pos].y_pos;
-
- /* no horizontal offsets (for vertical writing direction)
- supported yet */
-
- for ( i = gpi->first; i <= in->pos; i++ )
- out[i].y_pos -= offset;
-
- gpi->first = 0xFFFF;
- }
-
if ( error == TTO_Err_Not_Covered )
- (in->pos)++;
+ (buffer->in_pos)++;
else
retError = error;
}
@@ -6194,6 +6051,30 @@
}
+ static FT_Error Position_CursiveChain ( OTL_Buffer buffer )
+ {
+ FT_ULong i, j;
+ OTL_Position positions = buffer->positions;
+
+ /* First handle all left-to-right connections */
+ for (j = 0; j < buffer->in_length; j--)
+ {
+ if (positions[j].cursive_chain > 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ /* Then handle all right-to-left connections */
+ for (i = buffer->in_length; i > 0; i--)
+ {
+ j = i - 1;
+
+ if (positions[j].cursive_chain < 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ return TT_Err_Ok;
+ }
+
EXPORT_FUNC
FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos,
FT_UShort feature_index,
@@ -6269,7 +6150,6 @@
return TT_Err_Ok;
}
-
/* If `dvi' is TRUE, glyph contour points for anchor points and device
tables are ignored -- you will get device independent values. */
@@ -6277,12 +6157,10 @@
FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos,
FT_UShort load_flags,
- TTO_GSUB_String* in,
- TTO_GPOS_Data** out,
+ OTL_Buffer buffer,
FT_Bool dvi,
FT_Bool r2l )
{
- FT_Memory memory = gpos->memory;
FT_Error error, retError = TTO_Err_Not_Covered;
GPOS_Instance gpi;
@@ -6292,7 +6170,7 @@
if ( !face || !gpos ||
- !in || in->length == 0 || in->pos >= in->length )
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
return TT_Err_Invalid_Argument;
properties = gpos->LookupList.Properties;
@@ -6303,15 +6181,10 @@
gpi.r2l = r2l;
gpi.dvi = dvi;
- if ( *out )
- FREE( *out );
- if ( ALLOC_ARRAY( *out, in->length, TTO_GPOS_Data ) )
- return error;
-
for ( j = 0; j < gpos->LookupList.LookupCount; j++ )
if ( !properties || properties[j] )
{
- error = Do_String_Lookup( &gpi, j, in, *out );
+ error = Do_String_Lookup( &gpi, j, buffer );
if ( error )
{
if ( error != TTO_Err_Not_Covered )
@@ -6321,6 +6194,10 @@
retError = error;
}
+ error = Position_CursiveChain ( buffer );
+ if ( error )
+ return error;
+
return retError;
}
diff --git a/pango/opentype/ftxgpos.h b/pango/opentype/ftxgpos.h
index 408bcb0a..bb766c65 100644
--- a/pango/opentype/ftxgpos.h
+++ b/pango/opentype/ftxgpos.h
@@ -758,26 +758,6 @@ extern "C" {
typedef union TTO_GPOS_SubTable_ TTO_GPOS_SubTable;
- /* This `string object' is much simpler compared to TTO_GSUB_String.
- A call to TTO_GPOS_Apply_String() will allocate it. */
-
- struct TTO_GPOS_Data_
- {
- FT_Pos x_pos;
- FT_Pos y_pos;
- FT_Pos x_advance;
- FT_Pos y_advance;
- FT_UShort back; /* number of glyphs to go back
- for drawing current glyph */
- FT_Bool new_advance; /* if set, the advance width values are
- absolute, i.e., they won't be
- added to the original glyph's value
- but rather replace them. */
- };
-
- typedef struct TTO_GPOS_Data_ TTO_GPOS_Data;
-
-
/* finally, the GPOS API */
/* EXPORT_DEF
@@ -844,8 +824,7 @@ extern "C" {
FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos,
FT_UShort load_flags,
- TTO_GSUB_String* in,
- TTO_GPOS_Data** out,
+ OTL_Buffer buffer,
FT_Bool dvi,
FT_Bool r2l );
diff --git a/pango/opentype/ftxgsub.c b/pango/opentype/ftxgsub.c
index 96aaffa2..0ec246dc 100644
--- a/pango/opentype/ftxgsub.c
+++ b/pango/opentype/ftxgsub.c
@@ -38,17 +38,26 @@
#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' )
-#define ADD_String( in, num_in, out, num_out, glyph_data, component, ligID ) \
- ( ( error = TT_GSUB_Add_String( (in), (num_in), \
- (out), (num_out), \
- (glyph_data), (component), (ligID) \
- ) ) != TT_Err_Ok )
+#define IN_GLYPH( pos ) buffer->in_string[(pos)].gindex
+#define IN_CURGLYPH( pos ) buffer->in_string[(pos) + buffer->in_pos].gindex
+#define IN_PROPERTIES( pos ) buffer->in_string[(pos)].properties
+#define IN_LIGID( pos ) buffer->in_string[(pos)].ligID
+
+
+#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
+ ( ( error = otl_buffer_add_output_glyphs( (buffer), \
+ (num_in), (num_out), \
+ (glyph_data), (component), (ligID) \
+ ) ) != TT_Err_Ok )
+#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
+ ( ( error = otl_buffer_add_output_glyph( (buffer), \
+ (glyph_index), (component), (ligID) \
+ ) ) != TT_Err_Ok )
static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level );
@@ -59,203 +68,6 @@
**********************/
- /* The following function copies `num_out' elements from `glyph_data'
- to `out', advancing the array pointer in the `in' structure by
- `num_in' elements, and in `out' by `num_out' elements. If the
- string (resp. the properties) array in `out' is empty or too
- small, it allocates resp. reallocates the string (and properties)
- array. Finally, it sets the `length' field of `out' equal to
- `pos' of the `out' structure.
-
- If `component' is 0xFFFF, the value `in->component[in->pos]'
- will be copied `num_out' times, otherwise `component' itself will
- be used to fill `out->component'.
-
- If `ligID' is 0xFFFF, the value `in->lig_IDs[in->pos]' will be
- copied `num_out' times, otherwise `ligID' itself will be used to
- fill `out->ligIDs'.
-
- The properties (if defined) for all replaced glyphs are taken
- from the glyph at position `in->pos'.
-
- The logClusters[] value for the glyph at position in->pos is used
- for all replacement glyphs */
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Add_String( TTO_GSUB_String* in,
- FT_UShort num_in,
- TTO_GSUB_String* out,
- FT_UShort num_out,
- FT_UShort* glyph_data,
- FT_UShort component,
- FT_UShort ligID )
- {
- FT_Memory memory = in->memory;
- FT_Error error;
- FT_UShort i;
- FT_UShort p_in;
- FT_UShort*p_out;
-
-
- /* sanity check */
-
- if ( !in || !out ||
- in->length == 0 || in->pos >= in->length ||
- in->length < in->pos + num_in )
- return TT_Err_Invalid_Argument;
-
- if ( out->pos + num_out >= out->allocated )
- {
- FT_ULong size = out->pos + num_out + 256L;
-
-
- /* The following works because all fields in `out' must be
- initialized to zero (including the `string' field) for the
- first use. */
-
- if ( REALLOC_ARRAY( out->string, out->allocated, size, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( out->components, out->allocated, size, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( out->ligIDs, out->allocated, size, FT_UShort ) )
- return error;
- if ( in->properties )
- if ( REALLOC_ARRAY( out->properties, out->allocated, size, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( out->logClusters, out->allocated, size, FT_Int ) )
- return error;
-
- out->allocated = size;
- }
-
- if ( num_out )
- {
- MEM_Copy( &out->string[out->pos], glyph_data,
- num_out * sizeof ( FT_UShort ) );
-
- if ( component == 0xFFFF )
- component = in->components[in->pos];
-
- p_out = out->components;
-
- for ( i = out->pos; i < out->pos + num_out; i++ )
- p_out[i] = component;
-
- p_out = out->ligIDs;
-
- if ( ligID == 0xFFFF )
- ligID = in->ligIDs[in->pos];
-
- for ( i = out->pos; i < out->pos + num_out; i++ )
- p_out[i] = ligID;
-
- if ( in->properties )
- {
- p_in = in->properties[in->pos];
- p_out = out->properties;
-
- for ( i = out->pos; i < out->pos + num_out; i++ )
- p_out[i] = p_in;
- }
-
- for ( i = out->pos; i < out->pos + num_out; i++ )
- out->logClusters[i] = in->logClusters[in->pos];
- }
-
- in->pos += num_in;
- out->pos += num_out;
-
- out->length = out->pos;
-
- return TT_Err_Ok;
- }
-
-
-#if 0
-
- /**********************
- * Extension Functions
- **********************/
-
-
- static FT_Error GSUB_Create( void* ext,
- PFace face )
- {
- DEFINE_LOAD_LOCALS( face->stream );
-
- TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
- Long table;
-
-
- /* by convention */
-
- if ( !gsub )
- return TT_Err_Ok;
-
- /* a null offset indicates that there is no GSUB table */
-
- gsub->offset = 0;
-
- /* we store the start offset and the size of the subtable */
-
- table = TT_LookUp_Table( face, TTAG_GSUB );
- if ( table < 0 )
- return TT_Err_Ok; /* The table is optional */
-
- if ( FILE_Seek( face->dirTables[table].Offset ) ||
- ACCESS_Frame( 4L ) )
- return error;
-
- gsub->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
- gsub->Version = GET_ULong();
-
- FORGET_Frame();
-
- gsub->loaded = FALSE;
-
- return TT_Err_Ok;
- }
-
-
- static FT_Error GSUB_Destroy( void* ext,
- PFace face )
- {
- TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
-
-
- /* by convention */
-
- if ( !gsub )
- return TT_Err_Ok;
-
- if ( gsub->loaded )
- {
- Free_LookupList( &gsub->LookupList, GSUB, memory );
- Free_FeatureList( &gsub->FeatureList, memory );
- Free_ScriptList( &gsub->ScriptList, memory );
- }
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_Init_GSUB_Extension( TT_Engine engine )
- {
- PEngine_Instance _engine = HANDLE_Engine( engine );
-
-
- if ( !_engine )
- return TT_Err_Invalid_Engine;
-
- return TT_Register_Extension( _engine,
- GSUB_ID,
- sizeof ( TTO_GSUBHeader ),
- GSUB_Create,
- GSUB_Destroy );
- }
-#endif
-
EXPORT_FUNC
FT_Error TT_Load_GSUB_Table( FT_Face face,
TTO_GSUBHeader** retptr,
@@ -502,39 +314,38 @@
static FT_Error Lookup_SingleSubst( TTO_SingleSubst* ss,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
{
- FT_UShort index, value[1], property;
+ FT_UShort index, value, property;
FT_Error error;
if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ss->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ss->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
switch ( ss->SubstFormat )
{
case 1:
- value[0] = ( in->string[in->pos] + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
- if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) )
+ value = ( IN_CURGLYPH( 0 ) + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error;
break;
case 2:
if ( index >= ss->ssf.ssf2.GlyphCount )
return TTO_Err_Invalid_GSUB_SubTable;
- value[0] = ss->ssf.ssf2.Substitute[index];
- if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) )
+ value = ss->ssf.ssf2.Substitute[index];
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error;
break;
@@ -546,7 +357,7 @@
{
/* we inherit the old glyph class to the substituted glyph */
- error = Add_Glyph_Property( gdef, value[0], property );
+ error = Add_Glyph_Property( gdef, value, property );
if ( error && error != TTO_Err_Not_Covered )
return error;
}
@@ -706,8 +517,7 @@
static FT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
@@ -720,10 +530,10 @@
if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ms->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ms->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -733,7 +543,7 @@
count = ms->Sequence[index].GlyphCount;
s = ms->Sequence[index].Substitute;
- if ( ADD_String( in, 1, out, count, s, 0xFFFF, 0xFFFF ) )
+ if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
return error;
if ( gdef && gdef->NewGlyphClasses )
@@ -904,8 +714,7 @@
static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub,
TTO_AlternateSubst* as,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
@@ -919,10 +728,10 @@
if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &as->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &as->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -931,14 +740,14 @@
/* we use a user-defined callback function to get the alternate index */
if ( gsub->altfunc )
- alt_index = (gsub->altfunc)( out->pos, in->string[in->pos],
+ alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH( 0 ),
aset.GlyphCount, aset.Alternate,
gsub->data );
else
alt_index = 0;
- if ( ADD_String( in, 1, out, 1, &aset.Alternate[alt_index],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
+ 0xFFFF, 0xFFFF ) )
return error;
if ( gdef && gdef->NewGlyphClasses )
@@ -1184,8 +993,7 @@
static FT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
@@ -1193,19 +1001,18 @@
FT_UShort index, property;
FT_Error error;
FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
- FT_UShort* s_in;
FT_UShort* c;
TTO_Ligature* lig;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS )
first_is_mark = TRUE;
- error = Coverage_Index( &ls->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ls->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -1218,10 +1025,9 @@
numlig;
numlig--, lig++ )
{
- if ( in->pos + lig->ComponentCount > in->length )
+ if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
continue; /* Not enough glyphs in input */
- s_in = &in->string[in->pos];
c = lig->Component;
is_mark = first_is_mark;
@@ -1231,12 +1037,12 @@
for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
@@ -1245,7 +1051,7 @@
if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
is_mark = FALSE;
- if ( s_in[j] != c[i - 1] )
+ if ( IN_CURGLYPH( j ) != c[i - 1] )
break;
}
@@ -1266,25 +1072,25 @@
/* We don't use a new ligature ID if there are no skipped
glyphs and the ligature already has an ID. */
- if ( in->ligIDs[in->pos] )
+ if ( IN_LIGID( buffer->in_pos ) )
{
- if ( ADD_String( in, i, out, 1, &lig->LigGlyph,
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, 0xFFFF ) )
return error;
}
else
{
- if ( ADD_String( in, i, out, 1, &lig->LigGlyph,
- 0xFFFF, in->max_ligID ) )
+ FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, ligID ) )
return error;
-
- (in->max_ligID)++;
}
}
else
{
- if ( ADD_String( in, 1, out, 1, &lig->LigGlyph,
- 0xFFFF, in->max_ligID ) )
+ FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
+ if ( ADD_Glyph( buffer, lig->LigGlyph,
+ 0xFFFF, ligID ) )
return error;
/* Now we must do a second loop to copy the skipped glyphs to
@@ -1296,16 +1102,14 @@
for ( i = 0; i < lig->ComponentCount - 1; i++ )
{
- while ( CHECK_Property( gdef, in->string[in->pos],
+ while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- i, in->max_ligID ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ i, ligID ) )
return error;
- (in->pos)++;
+ (buffer->in_pos)++;
}
-
- (in->max_ligID)++;
}
return TT_Err_Ok;
@@ -1324,8 +1128,7 @@
FT_UShort GlyphCount,
FT_UShort SubstCount,
TTO_SubstLookupRecord* subst,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
int nesting_level )
{
FT_Error error;
@@ -1338,23 +1141,23 @@
{
if ( SubstCount && i == subst->SequenceIndex )
{
- old_pos = in->pos;
+ old_pos = buffer->in_pos;
/* Do a substitution */
- error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, in, out,
+ error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
GlyphCount, nesting_level );
subst++;
SubstCount--;
- i += in->pos - old_pos;
+ i += buffer->in_pos - old_pos;
if ( error == TTO_Err_Not_Covered )
{
/* XXX "can't happen" -- but don't count on it */
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ 0xFFFF, 0xFFFF ) )
return error;
i++;
}
@@ -1365,8 +1168,8 @@
{
/* No substitution for this index */
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ 0xFFFF, 0xFFFF ) )
return error;
i++;
}
@@ -2090,8 +1893,7 @@
static FT_Error Lookup_ContextSubst1(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat1* csf1,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -2099,7 +1901,6 @@
FT_UShort index, property;
FT_UShort i, j, k, numsr;
FT_Error error;
- FT_UShort* s_in;
TTO_SubRule* sr;
TTO_GDEFHeader* gdef;
@@ -2107,10 +1908,10 @@
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &csf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &csf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -2122,32 +1923,30 @@
if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
continue;
- if ( in->pos + sr[k].GlyphCount > in->length )
+ if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
-
for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != sr[k].Input[i - 1] )
+ if ( IN_CURGLYPH( j ) != sr[k].Input[i - 1] )
break;
}
if ( i == sr[k].GlyphCount )
return Do_ContextSubst( gsub, sr[k].GlyphCount,
sr[k].SubstCount, sr[k].SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -2158,8 +1957,7 @@
static FT_Error Lookup_ContextSubst2(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat2* csf2,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -2170,7 +1968,6 @@
FT_UShort i, j, k, known_classes;
FT_UShort* classes;
- FT_UShort* s_in;
FT_UShort* cl;
TTO_SubClassSet* scs;
@@ -2180,21 +1977,21 @@
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to
do any lookup at all. */
- error = Coverage_Index( &csf2->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &csf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
return error;
- error = Get_Class( &csf2->ClassDef, in->string[in->pos],
+ error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
@@ -2214,22 +2011,21 @@
if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
continue;
- if ( in->pos + sr->GlyphCount > in->length )
+ if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
cl = sr->Class;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
@@ -2239,7 +2035,7 @@
{
/* Keeps us from having to do this for each rule */
- error = Get_Class( &csf2->ClassDef, s_in[j], &classes[i], NULL );
+ error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
known_classes = i;
@@ -2253,7 +2049,7 @@
{
error = Do_ContextSubst( gsub, sr->GlyphCount,
sr->SubstCount, sr->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End;
}
@@ -2270,15 +2066,13 @@
static FT_Error Lookup_ContextSubst3(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat3* csf3,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
{
FT_Error error;
FT_UShort index, i, j, property;
- FT_UShort* s_in;
TTO_Coverage* c;
TTO_GDEFHeader* gdef;
@@ -2286,47 +2080,45 @@
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
return TTO_Err_Not_Covered;
- if ( in->pos + csf3->GlyphCount > in->length )
+ if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
return TTO_Err_Not_Covered; /* context is too long */
- s_in = &in->string[in->pos];
c = csf3->Coverage;
for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &c[i], s_in[j], &index );
+ error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index );
if ( error )
return error;
}
return Do_ContextSubst( gsub, csf3->GlyphCount,
csf3->SubstCount, csf3->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub,
TTO_ContextSubst* cs,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -2334,15 +2126,15 @@
switch ( cs->SubstFormat )
{
case 1:
- return Lookup_ContextSubst1( gsub, &cs->csf.csf1, in, out,
+ return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
flags, context_length, nesting_level );
case 2:
- return Lookup_ContextSubst2( gsub, &cs->csf.csf2, in, out,
+ return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
flags, context_length, nesting_level );
case 3:
- return Lookup_ContextSubst3( gsub, &cs->csf.csf3, in, out,
+ return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
flags, context_length, nesting_level );
default:
@@ -3377,8 +3169,7 @@
static FT_Error Lookup_ChainContextSubst1(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat1* ccsf1,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -3387,7 +3178,6 @@
FT_UShort i, j, k, num_csr, curr_pos;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_ChainSubRule* csr;
TTO_ChainSubRule curr_csr;
@@ -3396,10 +3186,10 @@
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ccsf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -3418,7 +3208,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue;
if ( bgc )
@@ -3427,11 +3217,10 @@
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -3452,7 +3241,7 @@
Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */
- if ( s_in[j] != curr_csr.Backtrack[i] )
+ if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] )
break;
}
@@ -3460,25 +3249,24 @@
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_csr.Input[i - 1] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_csr.Input[i - 1] )
break;
}
@@ -3489,22 +3277,21 @@
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_csr.Lookahead[i] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_csr.Lookahead[i] )
break;
}
@@ -3512,7 +3299,7 @@
return Do_ContextSubst( gsub, igc,
curr_csr.SubstCount,
curr_csr.SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -3523,8 +3310,7 @@
static FT_Error Lookup_ChainContextSubst2(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat2* ccsf2,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -3542,8 +3328,6 @@
FT_UShort* input_classes;
FT_UShort* lookahead_classes;
- FT_UShort* s_in;
-
FT_UShort* bc;
FT_UShort* ic;
FT_UShort* lc;
@@ -3556,14 +3340,14 @@
gdef = gsub->gdef;
memory = gsub->memory;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to
do any lookup at all. */
- error = Coverage_Index( &ccsf2->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
@@ -3579,7 +3363,7 @@
goto End2;
known_lookahead_classes = 0;
- error = Get_Class( &ccsf2->InputClassDef, in->string[in->pos],
+ error = Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH( 0 ),
&input_classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -3603,7 +3387,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue;
if ( bgc )
@@ -3613,12 +3397,11 @@
Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
- s_in = &in->string[curr_pos];
bc = ccsr.Backtrack;
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -3633,7 +3416,7 @@
{
/* Keeps us from having to do this for each rule */
- error = Get_Class( &ccsf2->BacktrackClassDef, s_in[j],
+ error = Get_Class( &ccsf2->BacktrackClassDef, IN_GLYPH( j ),
&backtrack_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -3648,20 +3431,19 @@
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccsr.Input;
/* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
@@ -3669,7 +3451,7 @@
if ( i >= known_input_classes )
{
- error = Get_Class( &ccsf2->InputClassDef, s_in[j],
+ error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( curr_pos + j ),
&input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -3687,17 +3469,16 @@
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccsr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
@@ -3705,7 +3486,7 @@
if ( i >= known_lookahead_classes )
{
- error = Get_Class( &ccsf2->LookaheadClassDef, s_in[j],
+ error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ),
&lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
@@ -3721,7 +3502,7 @@
error = Do_ContextSubst( gsub, igc,
ccsr.SubstCount,
ccsr.SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End1;
}
@@ -3744,8 +3525,7 @@
static FT_Error Lookup_ChainContextSubst3(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat3* ccsf3,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -3753,7 +3533,6 @@
FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_Coverage* bc;
TTO_Coverage* ic;
@@ -3763,7 +3542,7 @@
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
bgc = ccsf3->BacktrackGlyphCount;
@@ -3775,7 +3554,7 @@
/* check whether context is too long; it is a first guess only */
- if ( bgc > in->pos || in->pos + igc + lgc > in->length )
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
return TTO_Err_Not_Covered;
if ( bgc )
@@ -3784,12 +3563,11 @@
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
bc = ccsf3->BacktrackCoverage;
- for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- )
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
@@ -3800,31 +3578,30 @@
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &bc[i], s_in[j], &index );
+ error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
if ( error )
return error;
}
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccsf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ )
{
- /* We already called CHECK_Property for s_in[0] */
- while ( j > 0 && CHECK_Property( gdef, s_in[j], flags, &property ) )
+ /* We already called CHECK_Property for IN_GLYPH( curr_pos ) */
+ while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &ic[i], s_in[j], &index );
+ error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index );
if ( error )
return error;
}
@@ -3833,23 +3610,22 @@
glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccsf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ )
{
- while ( CHECK_Property( gdef, s_in[j], flags, &property ) )
+ while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &lc[i], s_in[j], &index );
+ error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index );
if ( error )
return error;
}
@@ -3857,7 +3633,7 @@
return Do_ContextSubst( gsub, igc,
ccsf3->SubstCount,
ccsf3->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
@@ -3865,8 +3641,7 @@
static FT_Error Lookup_ChainContextSubst(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubst* ccs,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
@@ -3874,17 +3649,17 @@
switch ( ccs->SubstFormat )
{
case 1:
- return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, in, out,
+ return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
flags, context_length,
nesting_level );
case 2:
- return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, in, out,
+ return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
flags, context_length,
nesting_level );
case 3:
- return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, in, out,
+ return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
flags, context_length,
nesting_level );
@@ -4196,8 +3971,7 @@
static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level )
{
@@ -4220,39 +3994,39 @@
{
case GSUB_LOOKUP_SINGLE:
error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_MULTIPLE:
error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_ALTERNATE:
error = Lookup_AlternateSubst( gsub,
&lo->SubTable[i].st.gsub.alternate,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_LIGATURE:
error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_CONTEXT:
error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context,
- in, out,
+ buffer,
flags, context_length, nesting_level );
break;
case GSUB_LOOKUP_CHAIN:
error = Lookup_ChainContextSubst( gsub,
&lo->SubTable[i].st.gsub.chain,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
@@ -4268,29 +4042,25 @@
return TTO_Err_Not_Covered;
}
-
/* apply one lookup to the input string object */
static FT_Error Do_String_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
FT_UShort* properties = gsub->LookupList.Properties;
- FT_UShort* p_in = in->properties;
- FT_UShort* s_in = in->string;
int nesting_level = 0;
- while ( in->pos < in->length )
+ while ( buffer->in_pos < buffer->in_length )
{
- if ( ~p_in[in->pos] & properties[lookup_index] )
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
{
/* 0xFFFF indicates that we don't have a context length yet */
- error = Do_Glyph_Lookup( gsub, lookup_index, in, out,
+ error = Do_Glyph_Lookup( gsub, lookup_index, buffer,
0xFFFF, nesting_level );
if ( error )
{
@@ -4304,7 +4074,7 @@
error = TTO_Err_Not_Covered;
if ( error == TTO_Err_Not_Covered )
- if ( ADD_String( in, 1, out, 1, &s_in[in->pos], 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), 0xFFFF, 0xFFFF ) )
return error;
}
@@ -4376,148 +4146,24 @@
EXPORT_FUNC
- FT_Error TT_GSUB_String_New( FT_Memory memory,
- TTO_GSUB_String **result )
- {
- FT_Error error;
-
- TTO_GSUB_String *str;
-
- if ( ALLOC( str, sizeof( *str ) ) )
- return error;
-
- str->memory = memory;
-
- str->length = 0;
- str->allocated = 0;
- str->pos = 0;
- str->string = NULL;
- str->properties = NULL;
- str->components = NULL;
- str->max_ligID = 0;
- str->ligIDs = 0;
- str->logClusters = 0;
-
- *result = str;
-
- return TT_Err_Ok;
- }
-
- EXPORT_DEF
- FT_Error TT_GSUB_String_Set_Length( TTO_GSUB_String *str,
- FT_ULong new_length)
- {
- FT_Memory memory = str->memory;
- FT_Error error;
-
- if ( new_length > str->allocated )
- {
- if ( REALLOC_ARRAY( str->string, str->allocated, new_length, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( str->properties, str->allocated, new_length, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( str->components, str->allocated, new_length, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( str->ligIDs, str->allocated, new_length, FT_UShort ) )
- return error;
- if ( REALLOC_ARRAY( str->logClusters, str->allocated, new_length, FT_Int ) )
- return error;
-
- str->allocated = new_length;
- str->length = new_length;
- }
-
- return TT_Err_Ok;
- }
-
- EXPORT_FUNC
- FT_Error TT_GSUB_String_Done( TTO_GSUB_String *str )
- {
- FT_Memory memory = str->memory;
-
- FREE( str->string );
- FREE( str->properties );
- FREE( str->components );
- FREE( str->ligIDs );
- FREE( str->logClusters );
-
- FREE( str );
-
- return TT_Err_Ok;
- }
-
- EXPORT_FUNC
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
- FT_Memory memory = in->memory;
FT_UShort j;
- TTO_GSUB_String tmp1;
- TTO_GSUB_String* ptmp1;
- TTO_GSUB_String tmp2;
- TTO_GSUB_String* ptmp2;
- TTO_GSUB_String* t;
-
FT_UShort* properties;
-
if ( !gsub ||
- !in || !out || in->length == 0 || in->pos >= in->length )
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
return TT_Err_Invalid_Argument;
properties = gsub->LookupList.Properties;
- tmp1.memory = memory;
- tmp1.length = in->length;
- tmp1.allocated = in->length;
- tmp1.pos = in->pos;
- tmp1.max_ligID = 1;
- tmp1.string = NULL;
- tmp1.properties = NULL;
- tmp1.components = NULL;
- tmp1.ligIDs = NULL;
- tmp1.logClusters = NULL;
-
- tmp2.memory = memory;
- tmp2.allocated = 0;
- tmp2.pos = 0;
- tmp2.string = NULL;
- tmp2.properties = NULL;
- tmp2.components = NULL;
- tmp2.ligIDs = NULL;
- tmp2.logClusters = NULL;
-
- ptmp1 = &tmp1;
- ptmp2 = &tmp2;
-
- if ( ALLOC_ARRAY( tmp1.string, tmp1.length, FT_UShort ) )
- return error;
- MEM_Copy( tmp1.string, in->string, in->length * sizeof ( FT_UShort ) );
-
- /* make sure that we always have a `properties', `components', and
- `ligIDs' array in the string object */
-
- if ( ALLOC_ARRAY( tmp1.components, tmp1.length, FT_UShort ) )
- goto End;
- if ( ALLOC_ARRAY( tmp1.ligIDs, tmp1.length, FT_UShort ) )
- goto End;
- if ( ALLOC_ARRAY( tmp1.properties, tmp1.length, FT_UShort ) )
- goto End;
- if ( in->properties )
- MEM_Copy( tmp1.properties, in->properties,
- in->length * sizeof( FT_UShort ) );
- if ( ALLOC_ARRAY( tmp1.logClusters, tmp1.length, FT_Int ) )
- goto End;
- MEM_Copy( tmp1.logClusters, in->logClusters,
- in->length * sizeof( FT_Int ) );
-
for ( j = 0; j < gsub->LookupList.LookupCount; j++ )
if ( properties[j] )
{
- error = Do_String_Lookup( gsub, j, ptmp1, ptmp2 );
+ error = Do_String_Lookup( gsub, j, buffer );
if ( error )
{
if ( error != TTO_Err_Not_Covered )
@@ -4526,56 +4172,15 @@
else
retError = error;
-
- /* flipping `in' and `out', preparing the next loop */
-
- ptmp1->pos = in->pos;
- ptmp2->length = ptmp2->pos;
- ptmp2->pos = in->pos;
- ptmp2->max_ligID = ptmp1->max_ligID;
-
- t = ptmp2;
- ptmp2 = ptmp1;
- ptmp1 = t;
+ error = otl_buffer_swap( buffer );
+ if ( error )
+ goto End;
}
+
+ error = retError;
End:
- FREE( ptmp2->string );
- FREE( ptmp2->properties );
- FREE( ptmp2->components );
- FREE( ptmp2->ligIDs );
- FREE( ptmp2->logClusters );
-
- if ( error && error != TTO_Err_Not_Covered )
- {
- FREE( ptmp1->string );
- FREE( ptmp1->components );
- FREE( ptmp1->ligIDs );
- FREE( ptmp1->properties );
- FREE( ptmp1->logClusters );
-
- return error;
- }
- else
- {
- out->length = ptmp1->length;
- out->pos = 0;
- out->allocated = ptmp1->allocated;
- out->string = ptmp1->string;
- out->components = ptmp1->components;
- out->ligIDs = ptmp1->ligIDs;
- out->logClusters = ptmp1->logClusters;
-
- if ( in->properties )
- out->properties = ptmp1->properties;
- else
- {
- FREE( ptmp1->properties );
- out->properties = NULL;
- }
-
- return retError;
- }
+ return error;
}
diff --git a/pango/opentype/ftxgsub.h b/pango/opentype/ftxgsub.h
index 8951e441..51dda1c1 100644
--- a/pango/opentype/ftxgsub.h
+++ b/pango/opentype/ftxgsub.h
@@ -504,23 +504,6 @@ extern "C" {
TT_Add_String() will also handle allocation; you should use
free() in case you want to destroy the arrays in the object. */
- struct TTO_GSUB_String_
- {
- FT_Memory memory;
-
- FT_ULong length;
- FT_ULong pos;
- FT_ULong allocated;
- FT_UShort* string;
- FT_UShort* properties;
- FT_UShort* components;
- FT_UShort max_ligID;
- FT_UShort* ligIDs;
- FT_Int* logClusters;
- };
-
- typedef struct TTO_GSUB_String_ TTO_GSUB_String;
-
/* finally, the GSUB API */
@@ -578,30 +561,9 @@ extern "C" {
void* data );
EXPORT_DEF
- FT_Error TT_GSUB_String_New( FT_Memory memory,
- TTO_GSUB_String **result );
-
- EXPORT_DEF
- FT_Error TT_GSUB_String_Set_Length( TTO_GSUB_String *str,
- FT_ULong new_length);
-
- EXPORT_DEF
- FT_Error TT_GSUB_String_Done( TTO_GSUB_String *str );
-
-
- EXPORT_DEF
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out );
+ OTL_Buffer buffer );
- EXPORT_DEF
- FT_Error TT_GSUB_Add_String( TTO_GSUB_String* in,
- FT_UShort num_in,
- TTO_GSUB_String* out,
- FT_UShort num_out,
- FT_UShort* glyph_data,
- FT_UShort component,
- FT_UShort ligID );
#ifdef __cplusplus
}
diff --git a/pango/opentype/ftxopen.h b/pango/opentype/ftxopen.h
index 6788dec5..482bcb5d 100644
--- a/pango/opentype/ftxopen.h
+++ b/pango/opentype/ftxopen.h
@@ -280,6 +280,7 @@ extern "C" {
typedef struct TTO_Device_ TTO_Device;
+#include "otlbuffer.h"
#include "ftxgdef.h"
#include "ftxgsub.h"
#include "ftxgpos.h"
diff --git a/pango/opentype/otlbuffer.c b/pango/opentype/otlbuffer.c
new file mode 100644
index 00000000..b35a63fb
--- /dev/null
+++ b/pango/opentype/otlbuffer.c
@@ -0,0 +1,213 @@
+/* otlbuffer.c: Buffer of glyphs for substitution/positioning
+ *
+ * Copyright 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+#include <otlbuffer.h>
+
+#include FT_INTERNAL_MEMORY_H
+
+ static FT_Error
+ otl_buffer_ensure( OTL_Buffer buffer,
+ FT_ULong size )
+ {
+ FT_Memory memory = buffer->memory;
+ FT_ULong new_allocated = buffer->allocated;
+
+ if (size > new_allocated)
+ {
+ FT_Error error;
+
+ while (size > new_allocated)
+ new_allocated += (new_allocated >> 1) + 8;
+
+ if ( FT_REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
+ return error;
+ if ( FT_REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
+ return error;
+ if ( FT_REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, OTL_PositionRec ) )
+ return error;
+
+ buffer->allocated = new_allocated;
+ }
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_new( FT_Memory memory,
+ OTL_Buffer *buffer )
+ {
+ FT_Error error;
+
+ if ( FT_ALLOC( *buffer, sizeof( OTL_BufferRec ) ) )
+ return error;
+
+ (*buffer)->memory = memory;
+ (*buffer)->in_length = 0;
+ (*buffer)->out_length = 0;
+ (*buffer)->allocated = 0;
+ (*buffer)->in_pos = 0;
+ (*buffer)->out_pos = 0;
+
+ (*buffer)->in_string = NULL;
+ (*buffer)->out_string = NULL;
+ (*buffer)->positions = NULL;
+ (*buffer)->max_ligID = 0;
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_swap( OTL_Buffer buffer )
+ {
+ OTL_GlyphItem tmp_string;
+
+ tmp_string = buffer->in_string;
+ buffer->in_string = buffer->out_string;
+ buffer->out_string = tmp_string;
+
+ buffer->in_length = buffer->out_length;
+ buffer->out_length = 0;
+
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_free( OTL_Buffer buffer )
+ {
+ FT_Memory memory = buffer->memory;
+
+ FT_FREE( buffer->in_string );
+ FT_FREE( buffer->out_string );
+ FT_FREE( buffer );
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_clear( OTL_Buffer buffer )
+ {
+ buffer->in_length = 0;
+ buffer->out_length = 0;
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_add_glyph( OTL_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster )
+ {
+ FT_Error error;
+ OTL_GlyphItem glyph;
+
+ error = otl_buffer_ensure( buffer, buffer->in_length + 1 );
+ if ( error != FT_Err_Ok )
+ return error;
+
+ glyph = &buffer->in_string[buffer->in_length];
+ glyph->gindex = glyph_index;
+ glyph->properties = properties;
+ glyph->cluster = cluster;
+ glyph->component = 0;
+ glyph->ligID = 0;
+
+ buffer->in_length++;
+
+ return FT_Err_Ok;
+ }
+
+ /* The following function copies `num_out' elements from `glyph_data'
+ to `buffer->out_string', advancing the in array pointer in the structure
+ by `num_in' elements, and the out array pointer by `num_out' elements.
+ Finally, it sets the `length' field of `out' equal to
+ `pos' of the `out' structure.
+
+ If `component' is 0xFFFF, the component value from buffer->in_pos
+ will copied `num_out' times, otherwise `component' itself will
+ be used to fill the `component' fields.
+
+ If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
+ will copied `num_out' times, otherwise `ligID' itself will
+ be used to fill the `ligID' fields.
+
+ The properties for all replacement glyphs are taken
+ from the glyph at position `buffer->in_pos'.
+
+ The cluster value for the glyph at position buffer->in_pos is used
+ for all replacement glyphs */
+ FT_Error
+ otl_buffer_add_output_glyphs( OTL_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID )
+ {
+ FT_Error error;
+ FT_UShort i;
+ FT_UInt properties;
+ FT_UInt cluster;
+
+ error = otl_buffer_ensure( buffer, buffer->out_pos + num_out );
+ if ( error != FT_Err_Ok )
+ return error;
+
+ properties = buffer->in_string[buffer->in_pos].properties;
+ cluster = buffer->in_string[buffer->in_pos].cluster;
+ if ( component == 0xFFFF )
+ component = buffer->in_string[buffer->in_pos].component;
+ if ( ligID == 0xFFFF )
+ ligID = buffer->in_string[buffer->in_pos].ligID;
+
+ for ( i = 0; i < num_out; i++ )
+ {
+ OTL_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
+
+ item->gindex = glyph_data[i];
+ item->properties = properties;
+ item->cluster = cluster;
+ item->component = component;
+ item->ligID = ligID;
+ }
+
+ buffer->in_pos += num_in;
+ buffer->out_pos += num_out;
+
+ buffer->out_length = buffer->out_pos;
+
+ return FT_Err_Ok;
+ }
+
+ FT_Error
+ otl_buffer_add_output_glyph( OTL_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID )
+ {
+ FT_UShort glyph_data = glyph_index;
+
+ return otl_buffer_add_output_glyphs ( buffer, 1, 1,
+ &glyph_data, component, ligID );
+ }
+
+ FT_UShort
+ otl_buffer_allocate_ligid( OTL_Buffer buffer )
+ {
+ return buffer->max_ligID++;
+ }
diff --git a/pango/opentype/otlbuffer.h b/pango/opentype/otlbuffer.h
new file mode 100644
index 00000000..426b4473
--- /dev/null
+++ b/pango/opentype/otlbuffer.h
@@ -0,0 +1,97 @@
+/* otlbuffer.h: Buffer of glyphs for substitution/positioning
+ *
+ * Copyrigh 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+ typedef struct OTL_GlyphItemRec_ {
+ FT_UInt gindex;
+ FT_UInt properties;
+ FT_UInt cluster;
+ FT_UShort component;
+ FT_UShort ligID;
+ } OTL_GlyphItemRec, *OTL_GlyphItem;
+
+ typedef struct OTL_PositionRec_ {
+ FT_Pos x_pos;
+ FT_Pos y_pos;
+ FT_Pos x_advance;
+ FT_Pos y_advance;
+ FT_UShort back; /* number of glyphs to go back
+ for drawing current glyph */
+ FT_Bool new_advance; /* if set, the advance width values are
+ absolute, i.e., they won't be
+ added to the original glyph's value
+ but rather replace them. */
+ FT_Short cursive_chain; /* character to which this connects,
+ may be positive or negative; used
+ only internally */
+ } OTL_PositionRec, *OTL_Position;
+
+
+ typedef struct OTL_BufferRec_{
+ FT_Memory memory;
+ FT_ULong allocated;
+
+ FT_ULong in_length;
+ FT_ULong out_length;
+ FT_ULong in_pos;
+ FT_ULong out_pos;
+
+ OTL_GlyphItem in_string;
+ OTL_GlyphItem out_string;
+ OTL_Position positions;
+ FT_UShort max_ligID;
+ } OTL_BufferRec, *OTL_Buffer;
+
+ FT_Error
+ otl_buffer_new( FT_Memory memory,
+ OTL_Buffer *buffer );
+
+ FT_Error
+ otl_buffer_swap( OTL_Buffer buffer );
+
+ FT_Error
+ otl_buffer_free( OTL_Buffer buffer );
+
+ FT_Error
+ otl_buffer_clear( OTL_Buffer buffer );
+
+ FT_Error
+ otl_buffer_add_glyph( OTL_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster );
+
+ FT_Error
+ otl_buffer_add_output_glyphs( OTL_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID );
+
+ FT_Error
+ otl_buffer_add_output_glyph ( OTL_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID );
+
+ FT_UShort
+ otl_buffer_allocate_ligid( OTL_Buffer buffer );
+
+G_END_DECLS
diff --git a/pango/opentype/ottest.c b/pango/opentype/ottest.c
index b70f9118..e9a81c9f 100644
--- a/pango/opentype/ottest.c
+++ b/pango/opentype/ottest.c
@@ -145,6 +145,7 @@ add_features (TTO_GSUB gsub)
maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('l', 'i', 'g', 'a'), L);
}
+#if 0
void
dump_string (TTO_GSUB_String *str)
{
@@ -203,6 +204,7 @@ try_string (FT_Library library,
if ((error = TT_GSUB_String_Done (out_str)))
croak ("TT_GSUB_String_New", error);
}
+#endif
int
main (int argc, char **argv)
diff --git a/pango/opentype/pango-ot-buffer.c b/pango/opentype/pango-ot-buffer.c
new file mode 100644
index 00000000..9b548666
--- /dev/null
+++ b/pango/opentype/pango-ot-buffer.c
@@ -0,0 +1,265 @@
+/* Pango
+ * pango-ot-buffer.c: Buffer of glyphs for shaping/positioning
+ *
+ * Copyright (C) 2004 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "pango-ot-private.h"
+
+#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
+#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
+
+PangoOTBuffer *
+pango_ot_buffer_new (PangoFcFont *font)
+{
+ /* We lock the font here immediately for the silly reason
+ * of getting the FT_Memory; otherwise we'd have to
+ * add a new operation to PangoFcFontmap; callers will
+ * probably already have the font locked, however,
+ * so there is little performance penalty.
+ */
+ PangoOTBuffer *buffer = g_new (PangoOTBuffer, 1);
+ FT_Face face = pango_fc_font_lock_face (font);
+
+ if (otl_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok)
+ g_error ("Allocation of OTLBuffer failed");
+
+ buffer->font = g_object_ref (font);
+ buffer->applied_gpos = FALSE;
+ buffer->rtl = FALSE;
+
+ pango_fc_font_unlock_face (font);
+
+ return buffer;
+}
+
+void
+pango_ot_buffer_destroy (PangoOTBuffer *buffer)
+{
+ otl_buffer_free (buffer->buffer);
+ g_object_unref (buffer->font);
+ g_free (buffer);
+}
+
+void
+pango_ot_buffer_clear (PangoOTBuffer *buffer)
+{
+ otl_buffer_clear (buffer->buffer);
+ buffer->applied_gpos = FALSE;
+}
+
+void
+pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
+ guint glyph_index,
+ guint properties,
+ guint cluster)
+{
+ otl_buffer_add_glyph (buffer->buffer,
+ glyph_index, properties, cluster);
+
+}
+
+void
+pango_ot_buffer_set_rtl (PangoOTBuffer *buffer,
+ gboolean rtl)
+{
+ rtl = rtl != FALSE;
+ buffer->rtl = rtl;
+}
+
+void
+pango_ot_buffer_get_glyphs (PangoOTBuffer *buffer,
+ PangoOTGlyph **glyphs,
+ int *n_glyphs)
+{
+ if (glyphs)
+ *glyphs = (PangoOTGlyph *)buffer->buffer->in_string;
+
+ if (n_glyphs)
+ *n_glyphs = buffer->buffer->in_length;
+}
+
+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
+apply_gpos_ltr (PangoGlyphString *glyphs,
+ OTL_Position positions)
+{
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ FT_Pos x_pos = positions[i].x_pos;
+ FT_Pos y_pos = positions[i].y_pos;
+ int back = i;
+ int j;
+
+ while (positions[back].back != 0)
+ {
+ back -= positions[back].back;
+ x_pos += positions[back].x_pos;
+ y_pos += positions[back].y_pos;
+ }
+
+ for (j = back; j < i; j++)
+ glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[j].geometry.width;
+
+ glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
+ glyphs->glyphs[i].geometry.y_offset += PANGO_UNITS_26_6(y_pos);
+
+ if (positions[i].new_advance)
+ glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(positions[i].x_advance);
+ else
+ glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(positions[i].x_advance);
+ }
+}
+
+static void
+apply_gpos_rtl (PangoGlyphString *glyphs,
+ OTL_Position positions)
+{
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ int i_rev = glyphs->num_glyphs - i - 1;
+ int back_rev = i_rev;
+ int back;
+ FT_Pos x_pos = positions[i_rev].x_pos;
+ FT_Pos y_pos = positions[i_rev].y_pos;
+ int j;
+
+ while (positions[back_rev].back != 0)
+ {
+ back_rev -= positions[back_rev].back;
+ x_pos += positions[back_rev].x_pos;
+ y_pos += positions[back_rev].y_pos;
+ }
+
+ back = glyphs->num_glyphs - back_rev - 1;
+
+ for (j = i; j < back; j++)
+ glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[j].geometry.width;
+
+ glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
+ glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
+
+ if (positions[i_rev].new_advance)
+ glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(positions[i_rev].x_advance);
+ else
+ glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(positions[i_rev].x_advance);
+ }
+}
+
+void
+pango_ot_buffer_output (PangoOTBuffer *buffer,
+ PangoGlyphString *glyphs)
+{
+ FT_Face face;
+ PangoOTInfo *info;
+ TTO_GDEF gdef = NULL;
+ int i;
+ int last_cluster;
+
+ face = pango_fc_font_lock_face (buffer->font);
+ g_assert (face);
+
+ /* Copy glyphs into output glyph string */
+ pango_glyph_string_set_size (glyphs, buffer->buffer->in_length);
+
+ last_cluster = -1;
+ for (i = 0; i < buffer->buffer->in_length; i++)
+ {
+ OTL_GlyphItem item = &buffer->buffer->in_string[i];
+
+ glyphs->glyphs[i].glyph = item->gindex;
+
+ glyphs->log_clusters[i] = item->cluster;
+ if (glyphs->log_clusters[i] != last_cluster)
+ glyphs->glyphs[i].attr.is_cluster_start = 1;
+ else
+ glyphs->glyphs[i].attr.is_cluster_start = 0;
+
+ last_cluster = glyphs->log_clusters[i];
+ }
+
+ info = pango_ot_info_get (face);
+ gdef = pango_ot_info_get_gdef (info);
+
+ /* Apply default positioning */
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (glyphs->glyphs[i].glyph)
+ {
+ PangoRectangle logical_rect;
+
+ FT_UShort property;
+
+ if (gdef &&
+ TT_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok &&
+ (property == TTO_MARK || (property & IGNORE_SPECIAL_MARKS) != 0))
+ {
+ glyphs->glyphs[i].geometry.width = 0;
+ }
+ else
+ {
+ pango_font_get_glyph_extents ((PangoFont *)buffer->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 (buffer->rtl)
+ {
+ /* Swap all glyphs */
+ swap_range (glyphs, 0, glyphs->num_glyphs);
+ }
+
+ if (buffer->applied_gpos)
+ {
+ if (buffer->rtl)
+ apply_gpos_rtl (glyphs, buffer->buffer->positions);
+ else
+ apply_gpos_ltr (glyphs, buffer->buffer->positions);
+ }
+
+ pango_fc_font_unlock_face (buffer->font);
+}
diff --git a/pango/opentype/pango-ot-info.c b/pango/opentype/pango-ot-info.c
index 578c95d1..a6baa7fd 100644
--- a/pango/opentype/pango-ot-info.c
+++ b/pango/opentype/pango-ot-info.c
@@ -162,17 +162,31 @@ compare_glyph_info (gconstpointer a,
/* Make a guess at the appropriate class for a glyph given
* a character code that maps to the glyph
*/
-static FT_UShort
-get_glyph_class (gunichar charcode)
+static gboolean
+get_glyph_class (gunichar charcode,
+ FT_UShort *class)
{
+ /* For characters mapped into the Arabic Presentation forms, using properties
+ * derived as we apply GSUB substitutions will be more reliable
+ */
+ if ((charcode >= 0xFB50 && charcode <= 0xFDFF) || /* Arabic Presentation Forms-A */
+ (charcode >= 0xFE70 && charcode <= 0XFEFF)) /* Arabic Presentation Forms-B */
+ return FALSE;
+
switch (g_unichar_type (charcode))
{
case G_UNICODE_COMBINING_MARK:
case G_UNICODE_ENCLOSING_MARK:
case G_UNICODE_NON_SPACING_MARK:
- return 3; /* Mark glyph (non-spacing combining glyph) */
+ *class = 3; /* Mark glyph (non-spacing combining glyph) */
+ return TRUE;
+ case G_UNICODE_UNASSIGNED:
+ case G_UNICODE_PRIVATE_USE:
+ return FALSE; /* Unknown, don't assign a class; classes get
+ * propagated during GSUB application */
default:
- return 1; /* Base glyph (single character, spacing glyph) */
+ *class = 1; /* Base glyph (single character, spacing glyph) */
+ return TRUE;
}
}
@@ -225,9 +239,8 @@ synthesize_class_def (PangoOTInfo *info)
if (glyph <= 65535)
{
glyph_info.glyph = glyph;
- glyph_info.class = get_glyph_class (charcode);
-
- g_array_append_val (glyph_infos, glyph_info);
+ if (get_glyph_class (charcode, &glyph_info.class))
+ g_array_append_val (glyph_infos, glyph_info);
}
charcode = FT_Get_Next_Char (info->face, charcode, &glyph);
diff --git a/pango/opentype/pango-ot-private.h b/pango/opentype/pango-ot-private.h
index 5c27f3a5..9d8f5d0e 100644
--- a/pango/opentype/pango-ot-private.h
+++ b/pango/opentype/pango-ot-private.h
@@ -80,6 +80,14 @@ struct _PangoOTRulesetClass
GObjectClass parent_class;
};
+struct _PangoOTBuffer
+{
+ OTL_Buffer buffer;
+ PangoFcFont *font;
+ gboolean rtl;
+ gboolean applied_gpos;
+};
+
GType pango_ot_info_get_type (void);
TTO_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
diff --git a/pango/opentype/pango-ot-ruleset.c b/pango/opentype/pango-ot-ruleset.c
index bf297f11..47af334b 100644
--- a/pango/opentype/pango-ot-ruleset.c
+++ b/pango/opentype/pango-ot-ruleset.c
@@ -24,9 +24,6 @@
#include FT_INTERNAL_MEMORY_H /* For FT_Free() */
-#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
-#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
-
typedef struct _PangoOTRule PangoOTRule;
struct _PangoOTRule
@@ -139,34 +136,15 @@ pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset,
g_array_append_val (ruleset->rules, tmp_rule);
}
-/**
- * pango_ot_ruleset_shape:
- * @ruleset: a #PangoOTRuleset.
- * @glyphs: a pointer to a #PangoGlyphString.
- * @properties: an array containing one #gulong bitfield for each glyph,
- * which gives the glyph's properties: If a certain bit is set for a glyph,
- * the feature which has the same bit set in its property value is applied.
- *
- * Shapes a string of glyphs with the given properties according to @ruleset.
- **/
void
-pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
- PangoGlyphString *glyphs,
- gulong *properties)
+pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
{
int i;
- int last_cluster;
- int result;
TTO_GSUB gsub = NULL;
- TTO_GPOS gpos = NULL;
- TTO_GSUB_String *in_string = NULL;
- TTO_GSUB_String *out_string = NULL;
- TTO_GSUB_String *result_string = NULL;
-
gboolean need_gsub = FALSE;
- gboolean need_gpos = FALSE;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
@@ -176,26 +154,17 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
if (rule->table_type == PANGO_OT_TABLE_GSUB)
need_gsub = TRUE;
- else
- need_gpos = TRUE;
}
if (need_gsub)
{
+
gsub = pango_ot_info_get_gsub (ruleset->info);
if (gsub)
TT_GSUB_Clear_Features (gsub);
}
- if (need_gpos)
- {
- gpos = pango_ot_info_get_gpos (ruleset->info);
-
- if (gpos)
- TT_GPOS_Clear_Features (gpos);
- }
-
for (i = 0; i < ruleset->rules->len; i++)
{
PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
@@ -205,98 +174,59 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
if (gsub)
TT_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit);
}
- else
- {
- if (gpos)
- TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
- }
}
- if (!gsub && !gpos)
+ if (!gsub)
return;
- result = TT_GSUB_String_New (ruleset->info->face->memory, &in_string);
- g_assert (result == FT_Err_Ok);
-
- result = TT_GSUB_String_Set_Length (in_string, glyphs->num_glyphs);
- g_assert (result == FT_Err_Ok);
+ TT_GSUB_Apply_String (gsub, buffer->buffer);
+}
- for (i = 0; i < glyphs->num_glyphs; i++)
- {
- in_string->string[i] = glyphs->glyphs[i].glyph;
- in_string->properties[i] = properties[i];
- in_string->logClusters[i] = glyphs->log_clusters[i];
- }
- in_string->max_ligID = i;
+void
+pango_ot_ruleset_position (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
+{
+ int i;
+
+ TTO_GPOS gpos = NULL;
- if (gsub)
+ gboolean need_gpos = FALSE;
+
+ g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
+
+ for (i = 0; i < ruleset->rules->len; i++)
{
- result = TT_GSUB_String_New (ruleset->info->face->memory,
- &out_string);
- g_assert (result == FT_Err_Ok);
- result_string = out_string;
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
- TT_GSUB_Apply_String (gsub, in_string, out_string);
+ if (rule->table_type == PANGO_OT_TABLE_GPOS)
+ need_gpos = TRUE;
}
- else
- result_string = in_string;
+
+ if (need_gpos)
+ gpos = pango_ot_info_get_gpos (ruleset->info);
if (gpos)
{
- TTO_GPOS_Data *outgpos = NULL;
+ TT_GPOS_Clear_Features (gpos);
- if (!TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, result_string, &outgpos,
- FALSE /* enable device-dependant values */,
- FALSE /* Even though this might be r2l text, RTL is handled elsewhere */))
+ for (i = 0; i < ruleset->rules->len; i++)
{
- for (i = 0; i < result_string->length; i++)
- {
- FT_Pos x_pos = outgpos[i].x_pos;
- FT_Pos y_pos = outgpos[i].y_pos;
- int back = i;
- int j;
-
- while (outgpos[back].back != 0)
- {
- back -= outgpos[back].back;
- x_pos += outgpos[back].x_pos;
- y_pos += outgpos[back].y_pos;
- }
-
- for (j = back; j < i; j++)
- glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[j].geometry.width;
-
- glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
- glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
-
- if (outgpos[i].new_advance)
- glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(outgpos[i].x_advance);
- else
- glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(outgpos[i].x_advance);
- }
-
- FT_Free(gpos->memory, (void *)outgpos);
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
+
+ if (rule->table_type == PANGO_OT_TABLE_GPOS)
+ TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
}
}
- pango_glyph_string_set_size (glyphs, result_string->length);
-
- last_cluster = -1;
- for (i = 0; i < result_string->length; i++)
+ /* Apply GPOS rules */
+ if (gpos)
{
- glyphs->glyphs[i].glyph = result_string->string[i];
-
- glyphs->log_clusters[i] = result_string->logClusters[i];
- if (glyphs->log_clusters[i] != last_cluster)
- glyphs->glyphs[i].attr.is_cluster_start = 1;
- else
- glyphs->glyphs[i].attr.is_cluster_start = 0;
-
- last_cluster = glyphs->log_clusters[i];
+ if (TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
+ FALSE /* enable device-dependant values */,
+ buffer->rtl) == FT_Err_Ok)
+ {
+ buffer->applied_gpos = TRUE;
+ }
}
-
- if (in_string)
- TT_GSUB_String_Done (in_string);
- if (out_string)
- TT_GSUB_String_Done (out_string);
}
+
diff --git a/pango/pango-ot.h b/pango/pango-ot.h
index 093f2282..4fe693d2 100644
--- a/pango/pango-ot.h
+++ b/pango/pango-ot.h
@@ -22,9 +22,9 @@
#ifndef __PANGO_OT_H__
#define __PANGO_OT_H__
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <pango/pangofc-font.h>
#include <pango/pango-glyph.h>
+#include <pango/pango-font.h>
G_BEGIN_DECLS
@@ -33,6 +33,8 @@ G_BEGIN_DECLS
typedef guint32 PangoOTTag;
typedef struct _PangoOTInfo PangoOTInfo;
+typedef struct _PangoOTBuffer PangoOTBuffer;
+typedef struct _PangoOTGlyph PangoOTGlyph;
typedef struct _PangoOTRuleset PangoOTRuleset;
typedef enum
@@ -41,6 +43,16 @@ typedef enum
PANGO_OT_TABLE_GPOS
} PangoOTTableType;
+/* Note that this much match OTLGlyphItem */
+struct _PangoOTGlyph
+{
+ guint glyph;
+ guint properties;
+ guint cluster;
+ gushort component;
+ gushort ligID;
+};
+
PangoOTInfo *pango_ot_info_get (FT_Face face);
gboolean pango_ot_info_find_script (PangoOTInfo *info,
@@ -72,15 +84,31 @@ PangoOTTag *pango_ot_info_list_features (PangoOTInfo *info,
guint script_index,
guint language_index);
+PangoOTBuffer *pango_ot_buffer_new (PangoFcFont *font);
+void pango_ot_buffer_destroy (PangoOTBuffer *buffer);
+void pango_ot_buffer_clear (PangoOTBuffer *buffer);
+void pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
+ guint glyph_index,
+ guint properties,
+ guint cluster);
+void pango_ot_buffer_set_rtl (PangoOTBuffer *buffer,
+ gboolean rtl);
+void pango_ot_buffer_get_glyphs (PangoOTBuffer *buffer,
+ PangoOTGlyph **glyphs,
+ int *n_glyphs);
+void pango_ot_buffer_output (PangoOTBuffer *buffer,
+ PangoGlyphString *glyphs);
+
PangoOTRuleset *pango_ot_ruleset_new (PangoOTInfo *info);
void pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset,
PangoOTTableType table_type,
guint feature_index,
gulong property_bit);
-void pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
- PangoGlyphString *glyphs,
- gulong *properties);
+void pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer);
+void pango_ot_ruleset_position (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer);
#endif /* PANGO_ENABLE_ENGINE */