summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2004-11-22 20:31:11 +0000
committerOwen Taylor <otaylor@src.gnome.org>2004-11-22 20:31:11 +0000
commitf4bbca78a0c8acc3ce6792532ca1f86663b68d71 (patch)
tree372f3ded7d044af32599ece2167bc600b40b3c99
parent878588edfd26a03c2765024cc38de6f4f16d7e8f (diff)
downloadpango-f4bbca78a0c8acc3ce6792532ca1f86663b68d71.tar.gz
Add Syriac module by Emil Soleyman-Zomalan. (#147779)
Mon Nov 22 15:21:11 2004 Owen Taylor <otaylor@redhat.com> * modules/syriac configure.in modules/Makefile.am modules/makefile.msc: Add Syriac module by Emil Soleyman-Zomalan. (#147779) * examples/Makefile.am examples/syriac.utf: Syriac example text.
-rw-r--r--ChangeLog9
-rw-r--r--ChangeLog.pre-1-109
-rw-r--r--ChangeLog.pre-1-89
-rw-r--r--configure.in6
-rw-r--r--examples/Makefile.am1
-rw-r--r--examples/syriac.utf18
-rw-r--r--modules/Makefile.am3
-rw-r--r--modules/makefile.msc6
-rw-r--r--modules/syriac/.cvsignore6
-rw-r--r--modules/syriac/Makefile.am46
-rw-r--r--modules/syriac/syriac-fc.c372
-rw-r--r--modules/syriac/syriac-ot.c362
-rw-r--r--modules/syriac/syriac-ot.h69
13 files changed, 913 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index e1e56999..a7590b1b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Mon Nov 22 15:21:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/syriac configure.in modules/Makefile.am
+ modules/makefile.msc: Add Syriac module by Emil
+ Soleyman-Zomalan. (#147779)
+
+ * examples/Makefile.am examples/syriac.utf: Syriac
+ example text.
+
2004-11-21 Hans Breuer <hans@breuer.org>
* pango/makefile.msc : updated
diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10
index e1e56999..a7590b1b 100644
--- a/ChangeLog.pre-1-10
+++ b/ChangeLog.pre-1-10
@@ -1,3 +1,12 @@
+Mon Nov 22 15:21:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/syriac configure.in modules/Makefile.am
+ modules/makefile.msc: Add Syriac module by Emil
+ Soleyman-Zomalan. (#147779)
+
+ * examples/Makefile.am examples/syriac.utf: Syriac
+ example text.
+
2004-11-21 Hans Breuer <hans@breuer.org>
* pango/makefile.msc : updated
diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8
index e1e56999..a7590b1b 100644
--- a/ChangeLog.pre-1-8
+++ b/ChangeLog.pre-1-8
@@ -1,3 +1,12 @@
+Mon Nov 22 15:21:11 2004 Owen Taylor <otaylor@redhat.com>
+
+ * modules/syriac configure.in modules/Makefile.am
+ modules/makefile.msc: Add Syriac module by Emil
+ Soleyman-Zomalan. (#147779)
+
+ * examples/Makefile.am examples/syriac.utf: Syriac
+ example text.
+
2004-11-21 Hans Breuer <hans@breuer.org>
* pango/makefile.msc : updated
diff --git a/configure.in b/configure.in
index 5e5f6a34..2756140d 100644
--- a/configure.in
+++ b/configure.in
@@ -348,8 +348,9 @@ hangul_modules="hangul-fc"
hebrew_modules="hebrew-fc"
indic_modules="indic-fc"
thai_modules="thai-fc"
+syriac_modules="syriac-fc"
-all_modules="$arabic_modules,$basic_modules,$hangul_modules,$hebrew_modules,$indic_modules,$thai_modules"
+all_modules="$arabic_modules,$basic_modules,$hangul_modules,$hebrew_modules,$indic_modules,$thai_modules,$syriac_modules"
included_modules=""
if test "x$with_included_modules" != xno || test "x$with_included_modules" = x ; then
@@ -406,6 +407,8 @@ AM_CONDITIONAL(INCLUDE_THAI_FC,echo $included_modules | egrep '(^|,)thai-fc($|,)
AM_CONDITIONAL(INCLUDE_INDIC_FC,echo $included_modules | egrep '(^|,)indic-fc($|,)' > /dev/null)
+AM_CONDITIONAL(INCLUDE_SYRIAC_FC,echo $included_modules | egrep '(^|,)syriac-fc($|,)' > /dev/null)
+
#
# We use flockfile to implement pango_getline() - should be moved to GLib
# strtok_r isn't present on some systems
@@ -662,6 +665,7 @@ modules/hangul/Makefile
modules/indic/Makefile
modules/thai/Makefile
modules/hebrew/Makefile
+modules/syriac/Makefile
examples/Makefile
docs/Makefile
docs/version.xml
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 2286cc71..91ca4b02 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -74,6 +74,7 @@ EXTRA_DIST= \
HELLO.utf8 \
dev-example.utf \
muru.utf \
+ syriac.utf \
pangorc \
pangox.aliases
diff --git a/examples/syriac.utf b/examples/syriac.utf
new file mode 100644
index 00000000..05fedc7b
--- /dev/null
+++ b/examples/syriac.utf
@@ -0,0 +1,18 @@
+ܠܫܢܢ
+ܒܝܕܦܪܝܕܐ ܒܢܝܡܝܢ ܐܕܡ
+
+ܐܬܐܡܘܢ ܥܠܝܡܢ ܘܥܠܝܡܬܢ
+ܠܫܢܢ ܡܪܢܝܐ
+ܦܪܝܣܐ ܡܕܘܪܐ ܩܕܡܝܐ
+
+ܠܫܢܢ ܝܠܗ ܐܝܬܘܬܢ
+ܘܬܘܕܝܬܢ ܘܣܦܪܝܘܬܢ
+ܝܠܦܚܠܗ ܒܟܠ ܫܘܒ݂ܗܪܐ
+
+ܡܒܘܥܐ ܗܘܐ ܕܝܘܠܦܢܐ
+ܚܠܝܐ ܒܪܬܡܐ ܘܩܪܝܢܐ
+ܬܓ݂ܐ ܝܠܗ ܠܪܫܢ ܪܡܐ
+
+ܡܠܦܢܢ ܐܢܝ ܓܢܒܪܐ
+ܡܫܘܬܐܣܠܗܘܢ ܡܕܪܫܝܬܐ
+ܡܫܘܬܐܣܠܗܘܢ ܓܘ ܐܡܘܬܐ
diff --git a/modules/Makefile.am b/modules/Makefile.am
index b4954443..8b67df8b 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -6,7 +6,8 @@ SUBDIRS = \
hangul \
indic \
thai \
- hebrew
+ hebrew \
+ syriac
EXTRA_DIST = \
module.def
diff --git a/modules/makefile.msc b/modules/makefile.msc
index eef35ba9..e56edf6a 100644
--- a/modules/makefile.msc
+++ b/modules/makefile.msc
@@ -1,6 +1,6 @@
# modles for the ft2 backend, don't include 'basic'
# here it is built-in pangoft.dll, see ../pango/makefile.msc
-MODULES = arabic hangul hebrew indic thai
+MODULES = arabic hangul hebrew indic syriac thai
!IFNDEF MODULE
@@ -35,6 +35,10 @@ OBJECTS = hebrew-fc.obj hebrew-shaper.obj
OBJECTS = indic-fc.obj indic-ot.obj indic-ot-class-tables.obj mprefixups.obj
!ENDIF
+!IFDEF OBJ_syriac
+OBJECTS = syriac-fc.obj syriac-ot.obj
+!ENDIF
+
!IFDEF OBJ_thai
OBJECTS = thai-fc.obj thai-shaper.obj
!ENDIF
diff --git a/modules/syriac/.cvsignore b/modules/syriac/.cvsignore
new file mode 100644
index 00000000..6e5ca7ed
--- /dev/null
+++ b/modules/syriac/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.deps
+.libs
+*.lo
+*.la
diff --git a/modules/syriac/Makefile.am b/modules/syriac/Makefile.am
new file mode 100644
index 00000000..2f0630e1
--- /dev/null
+++ b/modules/syriac/Makefile.am
@@ -0,0 +1,46 @@
+## Process this file with automake to create Makefile.in.
+
+pangolibs = $(top_builddir)/pango/libpango-$(PANGO_API_VERSION).la $(GLIB_LIBS)
+pangoft2libs = $(top_builddir)/pango/libpangoft2-$(PANGO_API_VERSION).la $(FREETYPE_LIBS) $(pangolibs)
+
+INCLUDES = \
+ -DPANGO_ENABLE_ENGINE \
+ -DG_DISABLE_DEPRECATED \
+ $(PANGO_DEBUG_FLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/pango/ \
+ $(GLIB_CFLAGS)
+
+moduledir = $(libdir)/pango/$(PANGO_MODULE_VERSION)/modules
+module_LTLIBRARIES =
+noinst_LTLIBRARIES =
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+
+if HAVE_FREETYPE
+INCLUDES += $(FREETYPE_CFLAGS)
+if INCLUDE_SYRIAC_FC
+noinst_LTLIBRARIES += libpango-syriac-fc.la
+else
+module_LTLIBRARIES += pango-syriac-fc.la
+endif
+endif
+
+fc_sources = \
+ syriac-fc.c \
+ syriac-ot.c \
+ syriac-ot.h
+
+pango_syriac_fc_la_LDFLAGS = -export-dynamic -avoid-version -module $(no_undefined)
+pango_syriac_fc_la_LIBADD = $(pangoft2libs)
+pango_syriac_fc_la_SOURCES = $(fc_sources)
+libpango_syriac_fc_la_SOURCES = $(fc_sources)
+libpango_syriac_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_syriac_fc
+
+
+included-modules: $(noinst_LTLIBRARIES)
+
+.PHONY: included-modules
diff --git a/modules/syriac/syriac-fc.c b/modules/syriac/syriac-fc.c
new file mode 100644
index 00000000..59d5bfb7
--- /dev/null
+++ b/modules/syriac/syriac-fc.c
@@ -0,0 +1,372 @@
+/* Pango
+ * syriac-fc.h:
+ *
+ * Copyright (C) 2000, 2003 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+ *
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
+ *
+ * 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 <string.h>
+
+#include "syriac-ot.h"
+
+#include "pango-engine.h"
+#include "pango-utils.h"
+#include "pangofc-font.h"
+
+/* No extra fields needed */
+typedef PangoEngineShape SyriacEngineFc;
+typedef PangoEngineShapeClass SyriacEngineFcClass ;
+
+#define SCRIPT_ENGINE_NAME "SyriacScriptEngineFc"
+#define RENDER_TYPE PANGO_RENDER_TYPE_FC
+
+static PangoEngineScriptInfo syriac_scripts[] = {
+ { PANGO_SCRIPT_SYRIAC, "*" },
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ RENDER_TYPE,
+ syriac_scripts, G_N_ELEMENTS(syriac_scripts)
+ }
+};
+
+static void
+maybe_add_gsub_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_GSUB,
+ tag, script_index, 0xffff, &feature_index))
+ pango_ot_ruleset_add_feature (ruleset, PANGO_OT_TABLE_GSUB, feature_index,
+ property_bit);
+}
+
+static void
+maybe_add_gpos_feature (PangoOTRuleset *ruleset,
+ PangoOTInfo *info,
+ guint script_index,
+ PangoOTTag tag,
+ gulong property_bit)
+{
+ 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)
+{
+ PangoOTRuleset *ruleset;
+ static GQuark ruleset_quark = 0;
+
+ PangoOTInfo *info = pango_ot_info_get (face);
+
+ if (!ruleset_quark)
+ ruleset_quark = g_quark_from_string ("pango-syriac-ruleset");
+
+ if (!info)
+ return NULL;
+
+ ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);
+
+ if (!ruleset)
+ {
+ PangoOTTag syrc_tag = FT_MAKE_TAG ('s', 'y', 'r', 'c');
+ guint script_index;
+
+ ruleset = pango_ot_ruleset_new (info);
+
+#define ALL_GLYPHS ~(gulong)0
+
+ if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB,
+ syrc_tag, &script_index))
+ {
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','c','m','p'), ALL_GLYPHS);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','s','o','l'), isolated);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','a'), final);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','2'), final2);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('f','i','n','3'), final3);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','e','d','i'), medial);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','e','d','2'), medial2);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','n','i','t'), initial);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('r','l','i','g'), ALL_GLYPHS);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','a','l','t'), ALL_GLYPHS);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('l','i','g','a'), ALL_GLYPHS);
+ maybe_add_gsub_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','l','i','g'), ALL_GLYPHS);
+ }
+
+ if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS,
+ syrc_tag, &script_index))
+ {
+ maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('k','e','r','n'), ALL_GLYPHS);
+ maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','a','r','k'), ALL_GLYPHS);
+ maybe_add_gpos_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), ALL_GLYPHS);
+ }
+
+ g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
+ (GDestroyNotify)g_object_unref);
+ }
+
+ return ruleset;
+}
+
+static void
+swap_range (PangoGlyphString *glyphs, int start, int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+static void
+set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
+{
+ glyphs->glyphs[i].glyph = glyph;
+ glyphs->log_clusters[i] = offset;
+}
+
+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;
+
+ wc = g_utf8_get_char (p);
+
+ if ((analysis->level % 2) &&
+ pango_get_mirror_char (wc, &mirrored_ch))
+ wc = mirrored_ch;
+
+ 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
+syriac_engine_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ glong n_chars;
+ gunichar *wcs;
+ int i;
+ const char *p;
+ gulong *properties = NULL;
+ FT_Face face;
+ PangoOTRuleset *ruleset;
+ PangoOTBuffer *buffer;
+ PangoFcFont *fc_font;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ fc_font = PANGO_FC_FONT (font);
+
+ face = pango_fc_font_lock_face (fc_font);
+ g_assert (face);
+
+ ruleset = get_ruleset (face);
+ if (!ruleset)
+ {
+ 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);
+
+ syriac_assign_properties (wcs, properties, n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ gunichar wc;
+ gunichar mirrored_ch;
+ PangoGlyph index;
+ int cluster = 0;
+
+ wc = g_utf8_get_char (p);
+
+ if ((analysis->level % 2) &&
+ pango_get_mirror_char (wc, &mirrored_ch))
+ wc = mirrored_ch;
+
+ if (wc >= 0x200B && wc <= 0x200F) /* Zero-width characters */
+ {
+ pango_ot_buffer_add_glyph (buffer, 0, properties[i], p - text);
+ }
+ else
+ {
+ index = pango_fc_font_get_glyph (fc_font, wc);
+
+ if (!index)
+ {
+ pango_ot_buffer_add_glyph (buffer, pango_fc_font_get_unknown_glyph (fc_font, wc),
+ properties[i], p - text);
+ }
+ else
+ {
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ pango_ot_buffer_add_glyph (buffer, index,
+ properties[i], cluster);
+ }
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ pango_ot_ruleset_substitute (ruleset, buffer);
+ pango_ot_ruleset_position (ruleset, buffer);
+ pango_ot_buffer_output (buffer, glyphs);
+
+ g_free (wcs);
+ g_free (properties);
+ pango_ot_buffer_destroy (buffer);
+
+ out:
+ pango_fc_font_unlock_face (fc_font);
+}
+
+static void
+syriac_engine_fc_class_init (PangoEngineShapeClass *class)
+{
+ class->script_shape = syriac_engine_shape;
+}
+
+PANGO_ENGINE_SHAPE_DEFINE_TYPE (SyriacEngineFc, syriac_engine_fc,
+ syriac_engine_fc_class_init, NULL);
+
+void
+PANGO_MODULE_ENTRY(init) (GTypeModule *module)
+{
+ syriac_engine_fc_register_type (module);
+}
+
+void
+PANGO_MODULE_ENTRY(exit) (void)
+{
+}
+
+void
+PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
+ int *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+PangoEngine *
+PANGO_MODULE_ENTRY(create) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return g_object_new (syriac_engine_fc_type, NULL);
+ else
+ return NULL;
+}
diff --git a/modules/syriac/syriac-ot.c b/modules/syriac/syriac-ot.c
new file mode 100644
index 00000000..6de4aa13
--- /dev/null
+++ b/modules/syriac/syriac-ot.c
@@ -0,0 +1,362 @@
+/* Pango
+ * syriac-ot.h: Determine what OpenType features to apply to characters based
+ * on the rules for Syriac from the OpenType standard.
+ *
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
+ *
+ * This file is based on the Arabic shaping code from FreeType 1 tree; original
+ * copyright notice:
+ *
+ * The FreeType project -- a free and portable quality TrueType renderer.
+ *
+ * Copyright 1996-2000 by
+ * D. Turner, R.Wilhelm, and W. Lemberg
+ *
+ * The code, like the FreeType code it is derived from is dual-licensed
+ * under the GNU Public License and the FreeType license. See see
+ * pango/opentype/FT-license.txt for full details of the FreeType
+ * license.
+ */
+
+#include "syriac-ot.h"
+
+/* Here a table of the joining classes for characters in the range
+ * U+0700 - U+074F.
+ *
+ * The following character also has a joining class:
+ *
+ * U+200C ZERO WIDTH NON-JOINER -> causing
+ *
+ * All other characters are given the joining class `none'.
+ */
+JoiningClass syriac[] =
+{
+ /* U+0700 */
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, none,
+ none, none, none, transparent,
+
+ /* U+0710 */
+ right, none, dual, dual,
+ dual, right, right, right,
+ right, right, dual, dual,
+ dual, dual, right, dual,
+
+ /* U+0720 */
+ dual, dual, dual, dual,
+ dual, dual, dual, dual,
+ right, dual, right, dual,
+ right, none, none, none,
+
+ /* U+0730 */
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+
+ /* U+0740 */
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, transparent,
+ transparent, transparent, transparent, none,
+ none, right, dual, dual
+};
+
+/* `direction' can be -1, 0, or 1 to indicate the last non-transparent
+ * glyph, the current glyph, and the next non-transparent glyph,
+ * respectively.
+ */
+static JoiningClass
+Get_Joining_Class (gunichar* string,
+ int pos,
+ int length,
+ int direction)
+{
+ JoiningClass j;
+
+ while (1)
+ {
+ if (pos == 0 && direction < 0)
+ return none;
+
+ pos += direction;
+
+ if (pos >= length)
+ return none;
+
+ if (string[pos] < 0x0700 ||
+ string[pos] >= 0x074F)
+ {
+ if (string[pos] == 0x200C)
+ return causing;
+ else
+ return none;
+ }
+ else
+ j = syriac[string[pos] - 0x0700];
+
+ if (!direction || j != transparent)
+ return j;
+ }
+}
+
+
+/* The rules here are roughly based on the Arabic rules from the Unicode
+ * 2.0 standard (which differ from the Unicode-4.0 rules), augmented
+ * with the Syriac rules from the Unicode-4.0 standard. The numbers
+ * R1...R11 below do not correspond to either the Arabic or the Syriac
+ * rule numbering from the Unicode standard.
+ *
+ * Characters are here specified as appearing in the byte stream, i.e.
+ * *not* in visual order. Joining classes are given in angle brackets,
+ * glyph forms in square brackets. Glyphs affected by a specific rule are
+ * enclosed with vertical bars.
+ *
+ *
+ * Glyphs: 0x0715 (Dalath), 0x0716 (Dalath Rish), 0x072A (Rish),
+ * 0x0722 (Nun), 0x071F (Kaph)
+ *
+ *
+ * R1: <anything1> <transparent> <anything2>
+ *
+ * apply joining rules for
+ * <anything1> <anything2> -> [shape1] [shape2]
+ * -> [shape1] [isolated] [shape2]
+ *
+ *
+ * R2: <causing|right> <0x0722|0x071F> <!(causing|right|dual)>
+ * -> [isolated]
+ *
+ * The Nun and Kaph characters each have 3 different glyphs
+ * with two of those glyphs coming at the final position.
+ * However, one of those final glyphs should really be of the
+ * isolated glyph form where the preceding character cannot be
+ * joined to and there is no next character.
+ *
+ * This rule exists to combine similar exception for both
+ * characters without increasing the complexity in the other
+ * rules.
+ *
+ *
+ * R3: <causing|right|dual> && <!(0x0715|0x0716|0x072A)> |<alaph>|
+ *
+ * -> [final2]
+ *
+ * If the preceding glyph cannot be joined to the current
+ * glyph and the preceding character is not a Dalath, Rish,
+ * or Dotless Dalath Rish, then the Alaph takes this contextual
+ * position.
+ *
+ * The [final2] joining rule is placed ahead of the [final] to
+ * give it greater precedence when choosing the correct glyph.
+ * If it comes after the [final] rule, the incorrect glyph is
+ * inserted into position.
+ *
+ *
+ * R4: <0x0715|0x0715|0x072A> |<alaph>|
+ *
+ * -> [final3]
+ *
+ * If the previous glyph is a Dalath, Rish, or Dotless Dalath
+ * Rish, then the Alaph takes this contextual position.
+ *
+ * The [final3] joining rule is placed ahead of the [final] to
+ * give it greater precedence when choosing the correct glyph.
+ * If it comes after the [final] rule, the incorrect glyph is
+ * inserted into position.
+ *
+ *
+ * R5: <causing|right|dual> |<right>|
+ *
+ * -> [final]
+ *
+ *
+ * R6: <causing|right|dual> |<dual>| <!(causing|right|dual)>
+ *
+ * -> [final]
+ *
+ *
+ * R7: <causing|left|dual> |<dual>| <causing|right|dual>
+ *
+ * -> [medial]
+ *
+ *
+ * R8: <causing|right> |<alaph>| <causing|right|dual>
+ *
+ * -> [medial2]
+ *
+ * If the Alaph glyph falls in the middle of a Syriac word and
+ * the preceding character cannot be joined to, then the Alaph
+ * takes this contextual position.
+ *
+ *
+ * R9: |<left>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ *
+ * R10: <!(causing|left|dual)> |<dual>| <causing|right|dual>
+ *
+ * -> [initial]
+ *
+ *
+ * R11: <anything> -> [isolated]
+ *
+ * This joining rule is placed at the end of these features
+ * because when it is placed at the beginning of all of them
+ * it tends to break the cursive nature of Syriac writing --
+ * it inserts the isolated glyph of each character into that
+ * position with no joining occurring all throughout a text
+ * document.
+ */
+
+FT_Error
+syriac_assign_properties (gunichar *string,
+ gulong *properties,
+ int length)
+{
+ JoiningClass previous, current, next;
+ int i;
+
+ if (!string || !properties || length == 0)
+ return FT_Err_Invalid_Argument;
+
+ for (i = 0; i < length; i++)
+ {
+ previous = Get_Joining_Class (string, i, length, -1);
+ current = Get_Joining_Class (string, i, length, 0);
+ next = Get_Joining_Class (string, i, length, 1);
+
+ /* R1 */
+
+ if (current == transparent)
+ {
+ properties[i] |= isolated_p;
+ continue;
+ }
+
+ /* R2 */
+
+ if (string[i] == 0x0722 ||
+ string[i] == 0x071F)
+ if (previous == causing ||
+ previous == right)
+ if (!(next == causing ||
+ next == right ||
+ next == dual))
+ {
+ properties[i] |= isolated_p;
+ continue;
+ }
+
+ /* R3 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (!(string[i - 1] == 0x0715 ||
+ string[i - 1] == 0x0716 ||
+ string[i - 1] == 0x072A))
+ {
+ properties[i] |= final2_p;
+ continue;
+ }
+
+ /* R4 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (string[i - 1] == 0x0715 ||
+ string[i - 1] == 0x0716 ||
+ string[i - 1] == 0x072A)
+ {
+ properties[i] |= final3_p;
+ continue;
+ }
+
+ /* R5 */
+
+ if (previous == causing ||
+ previous == right ||
+ previous == dual)
+ if (current == right)
+ {
+ properties[i] |= final_p;
+ continue;
+ }
+
+ /* R6 */
+
+ if (previous == causing ||
+ previous == right ||
+ previous == dual)
+ if (current == dual)
+ if (!(next == causing ||
+ next == right ||
+ next == dual ))
+ {
+ properties[i] |= final_p;
+ continue;
+ }
+
+ /* R7 */
+
+ if (previous == causing ||
+ previous == left ||
+ previous == dual)
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual )
+ {
+ properties[i] |= medial_p;
+ continue;
+ }
+
+ /* R8 */
+
+ if (string[i] == 0x0710)
+ if (previous == causing ||
+ previous == right)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= medial2_p;
+ continue;
+ }
+
+ /* R9 */
+
+ if (current == left)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= initial_p;
+ continue;
+ }
+
+ /* R10 */
+
+ if (!(previous == causing ||
+ previous == left ||
+ previous == dual ))
+ if (current == dual)
+ if (next == causing ||
+ next == right ||
+ next == dual)
+ {
+ properties[i] |= initial_p;
+ continue;
+ }
+
+ /* R11 */
+
+ properties[i] |= isolated_p;
+ }
+
+ return FT_Err_Ok;
+}
diff --git a/modules/syriac/syriac-ot.h b/modules/syriac/syriac-ot.h
new file mode 100644
index 00000000..17efd18e
--- /dev/null
+++ b/modules/syriac/syriac-ot.h
@@ -0,0 +1,69 @@
+/* Pango
+ * syriac-ot.h: Determine what OpenType features to apply to characters based
+ * on the rules for Syriac from the OpenType standard.
+ *
+ * Copyright (C) 2004 Emil Soleyman-Zomalan
+ * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
+ *
+ * This file is based on the Arabic shaping code from FreeType 1 tree; original
+ * copyright notice:
+ *
+ * The FreeType project -- a free and portable quality TrueType renderer.
+ *
+ * Copyright 1996-2000 by
+ * D. Turner, R.Wilhelm, and W. Lemberg
+ *
+ * The code, like the FreeType code it is derived from is dual-licensed
+ * under the GNU Public License and the FreeType license. See see
+ * pango/opentype/FT-license.txt for full details of the FreeType
+ * license.
+ */
+
+#ifndef __SYRIAC_OT_H__
+#define __SYRIAC_OT_H__
+
+#include <pango/pango-ot.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ isolated = 1 << 0, /* nominal */
+ final = 1 << 1, /* right_joining */
+ initial = 1 << 2, /* left_joining */
+ medial = 1 << 3, /* double_joining */
+ medial2 = 1 << 4, /* double_joining, applies to Alaph only */
+ final2 = 1 << 5, /* right_joining, applies to Alaph only */
+ final3 = 1 << 6 /* right_joining, applies to Alaph only */
+} JoiningType;
+
+/* A glyph's property value as needed by e.g. TT_GSUB_Apply_String()
+ specifies which features should *not* be applied */
+typedef enum
+{
+ isolated_p = final | initial | medial | medial2 | final2 | final3,
+ final_p = isolated | initial | medial | medial2 | final2 | final3,
+ initial_p = isolated | final | medial | medial2 | final2 | final3,
+ medial_p = isolated | final | initial | medial2 | final2 | final3,
+ medial2_p = isolated | final | initial | medial | final2 | final3,
+ final2_p = isolated | final | initial | medial | medial2 | final3,
+ final3_p = isolated | final | initial | medial | medial2 | final2
+} SyriacGlyphForm;
+
+typedef enum
+{
+ right,
+ left, /* not used */
+ dual,
+ causing,
+ none,
+ transparent
+} JoiningClass;
+
+FT_Error syriac_assign_properties (gunichar *string,
+ gulong *properties,
+ int length);
+
+G_END_DECLS
+
+#endif /* __SYRIAC_OT_H__ */