diff options
author | Owen Taylor <otaylor@redhat.com> | 2003-04-14 23:48:34 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2003-04-14 23:48:34 +0000 |
commit | 402f2625c2c779df20470ed0f758999db494e4dc (patch) | |
tree | 6667e384ed0c39a22a6e3f731c062311fa7b3e9a /modules/arabic | |
parent | f6fdd34661bd9fe23452b5eb98ece8488a12ce8f (diff) | |
download | pango-402f2625c2c779df20470ed0f758999db494e4dc.tar.gz |
Switch over the way that module entry points work, taking advantage of the
Mon Apr 14 06:02:34 2003 Owen Taylor <otaylor@redhat.com>
* modules/thai/{thai-fc.c,thai-shaper.c,thai-x.c}:
* modules/*/*-{xft,x,win32.c} pango/pango-engine.h
modules/*/Makefile.am: Switch over the way that
module entry points work, taking advantage of the
new automake capability for per-target CFLAGS for
shared sources.
* pango/pangofc-font.[ch] pango/pangoxft-font.c
pango/pangoft2.c: Add a base class for
PangoXft and PangoFT2 font classes so code can
be shared between FT2 and Xft backends.
* configure.in modules/*/Makefile.am
modules/{arabic,basic,hangul,hebrew,indic,thai}: Move
*-xft.c to *-fc.c and share between Xft and FT2 backends;
adds FT2 backend capabilities for hangul/indic/thai.
* pango/pangoxft.h pango/pangoft2.h: Deprecate
APIs that moved into PangoFcFont
* modules/basic/basic-fc.c (set_glyph): Add kerning
handling from FT2 backend.
Diffstat (limited to 'modules/arabic')
-rw-r--r-- | modules/arabic/Makefile.am | 12 | ||||
-rw-r--r-- | modules/arabic/arabic-fc.c | 62 | ||||
-rw-r--r-- | modules/arabic/arabic-ft2.c | 408 | ||||
-rw-r--r-- | modules/arabic/arabic-x.c | 16 | ||||
-rw-r--r-- | modules/arabic/arabic-xft.c | 352 |
5 files changed, 41 insertions, 809 deletions
diff --git a/modules/arabic/Makefile.am b/modules/arabic/Makefile.am index 3aeafb90..683ac140 100644 --- a/modules/arabic/Makefile.am +++ b/modules/arabic/Makefile.am @@ -26,7 +26,6 @@ if HAVE_X INCLUDES += $(X_CFLAGS) if INCLUDE_ARABIC_X noinst_LTLIBRARIES += libpango-arabic-x.la -INCLUDES += -DX_MODULE_PREFIX else module_LTLIBRARIES += pango-arabic-x.la endif @@ -47,48 +46,51 @@ pango_arabic_x_la_LDFLAGS = -export-dynamic -avoid-version -module pango_arabic_x_la_LIBADD = $(pangoxlibs) pango_arabic_x_la_SOURCES = $(x_sources) libpango_arabic_x_la_SOURCES = $(x_sources) +libpango_arabic_x_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_arabic_x if HAVE_XFT INCLUDES += $(XFT_CFLAGS) if INCLUDE_ARABIC_XFT noinst_LTLIBRARIES += libpango-arabic-xft.la -INCLUDES += -DXFT_MODULE_PREFIX else module_LTLIBRARIES += pango-arabic-xft.la endif endif xft_sources = \ - arabic-xft.c \ + arabic-fc.c \ arabic-ot.c \ arabic-ot.h pango_arabic_xft_la_LDFLAGS = -export-dynamic -avoid-version -module pango_arabic_xft_la_LIBADD = $(pangoxftlibs) pango_arabic_xft_la_SOURCES = $(xft_sources) +pango_arabic_xft_la_CFLAGS = -DBUILD_XFT libpango_arabic_xft_la_SOURCES = $(xft_sources) +libpango_arabic_xft_la_CFLAGS = -DBUILD_XFT -DPANGO_MODULE_PREFIX=_pango_arabic_xft if HAVE_FREETYPE INCLUDES += $(FREETYPE_CFLAGS) if INCLUDE_ARABIC_FT2 noinst_LTLIBRARIES += libpango-arabic-ft2.la -INCLUDES += -DFT2_MODULE_PREFIX else module_LTLIBRARIES += pango-arabic-ft2.la endif endif ft2_sources = \ - arabic-ft2.c \ + arabic-fc.c \ arabic-ot.c \ arabic-ot.h pango_arabic_ft2_la_LDFLAGS = -export-dynamic -avoid-version -module $(no_undefined) pango_arabic_ft2_la_LIBADD = $(pangoft2libs) pango_arabic_ft2_la_SOURCES = $(ft2_sources) +pango_arabic_ft2_la_CFLAGS = -DBUILD_FT2 libpango_arabic_ft2_la_SOURCES = $(ft2_sources) +libpango_arabic_ft2_la_CFLAGS = -DBUILD_FT2 -DPANGO_MODULE_PREFIX=_pango_arabic_ft2 included-modules: $(noinst_LTLIBRARIES) diff --git a/modules/arabic/arabic-fc.c b/modules/arabic/arabic-fc.c index f4a63c0a..c94b2626 100644 --- a/modules/arabic/arabic-fc.c +++ b/modules/arabic/arabic-fc.c @@ -1,7 +1,7 @@ /* Pango - * arabic-xft.h: + * arabic-fc.h: * - * Copyright (C) 2000 Red Hat Software + * Copyright (C) 2000, 2003 Red Hat Software * Author: Owen Taylor <otaylor@redhat.com> * * This library is free software; you can redistribute it and/or @@ -24,11 +24,18 @@ #include "arabic-ot.h" -#include "pangoxft.h" #include "pango-engine.h" #include "pango-utils.h" +#ifdef BUILD_XFT +#include "pangoxft.h" #define SCRIPT_ENGINE_NAME "ArabicScriptEngineXft" +#define RENDER_TYPE PANGO_RENDER_TYPE_XFT +#else +#include "pangoft2.h" +#define SCRIPT_ENGINE_NAME "ArabicScriptEngineFt2" +#define RENDER_TYPE PANGO_RENDER_TYPE_FT2 +#endif static PangoEngineRange arabic_ranges[] = { /* Language characters */ @@ -39,7 +46,7 @@ static PangoEngineInfo script_engines[] = { { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, - PANGO_RENDER_TYPE_XFT, + RENDER_TYPE, arabic_ranges, G_N_ELEMENTS(arabic_ranges) } }; @@ -129,10 +136,10 @@ set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGl static void arabic_engine_shape (PangoFont *font, - const char *text, - gint length, - PangoAnalysis *analysis, - PangoGlyphString *glyphs) + const char *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs) { int n_chars; int i; @@ -141,13 +148,16 @@ arabic_engine_shape (PangoFont *font, gunichar *wcs = NULL; FT_Face face; PangoOTRuleset *ruleset; + 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); - face = pango_xft_font_lock_face (font); + fc_font = PANGO_FC_FONT (font); + + face = pango_fc_font_lock_face (fc_font); g_assert (face); n_chars = g_utf8_strlen (text, length); @@ -198,12 +208,12 @@ arabic_engine_shape (PangoFont *font, ((properties[i] & (initial | medial)) != (initial | medial))) wc = 0x64a; - index = pango_xft_font_get_glyph (font, wc); + index = pango_fc_font_get_glyph (fc_font, wc); if (!index) { set_glyph (font, glyphs, i, p - text, - pango_xft_font_get_unknown_glyph (font, wc)); + pango_fc_font_get_unknown_glyph (fc_font, wc)); } else { @@ -287,18 +297,18 @@ arabic_engine_shape (PangoFont *font, } } - pango_xft_font_unlock_face (font); + pango_fc_font_unlock_face (fc_font); } static PangoCoverage * -arabic_engine_get_coverage (PangoFont *font, - PangoLanguage *lang) +arabic_engine_get_coverage (PangoFont *font, + PangoLanguage *lang) { return pango_font_get_coverage (font, lang); } static PangoEngine * -arabic_engine_xft_new () +arabic_engine_fc_new () { PangoEngineShape *result; @@ -313,23 +323,11 @@ arabic_engine_xft_new () return (PangoEngine *)result; } -/* The following three functions provide the public module API for - * Pango. If we are compiling it is a module, then we name the - * entry points script_engine_list, etc. But if we are compiling - * it for inclusion directly in Pango, then we need them to - * to have distinct names for this module, so we prepend - * _pango_arabic_ - */ -#ifdef XFT_MODULE_PREFIX -#define MODULE_ENTRY(func) _pango_arabic_xft_##func -#else -#define MODULE_ENTRY(func) func -#endif - /* List the engines contained within this module */ void -MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines) +PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines, + int *n_engines) { *engines = script_engines; *n_engines = G_N_ELEMENTS (script_engines); @@ -338,15 +336,15 @@ MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines) /* Load a particular engine given the ID for the engine */ PangoEngine * -MODULE_ENTRY(script_engine_load) (const char *id) +PANGO_MODULE_ENTRY(load) (const char *id) { if (!strcmp (id, SCRIPT_ENGINE_NAME)) - return arabic_engine_xft_new (); + return arabic_engine_fc_new (); else return NULL; } void -MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) +PANGO_MODULE_ENTRY(unload) (PangoEngine *engine) { } diff --git a/modules/arabic/arabic-ft2.c b/modules/arabic/arabic-ft2.c deleted file mode 100644 index cb817e33..00000000 --- a/modules/arabic/arabic-ft2.c +++ /dev/null @@ -1,408 +0,0 @@ -/* Pango - * arabic-ft2.c: - * - * Copyright (C) 2001 convergence integrated media GmbH - * Author: Andreas Bogk <andreas@convergence.de> - * - * Based on xft code for arabic: - * - * Copyright (C) 2000 Red Hat Software - * Author: Owen Taylor <otaylor@redhat.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 "arabic-ot.h" - -#include "pangoft2.h" -#include "pango-engine.h" -#include "pango-utils.h" - -#define SCRIPT_ENGINE_NAME "ArabicScriptEngineFt2" - -static PangoEngineRange arabic_ranges[] = { - /* Language characters */ - { 0x060c, 0x06f9, "*" }, /* Arabic */ -}; - -static PangoEngineInfo script_engines[] = { - { - SCRIPT_ENGINE_NAME, - PANGO_ENGINE_TYPE_SHAPE, - PANGO_RENDER_TYPE_FT2, - arabic_ranges, G_N_ELEMENTS(arabic_ranges) - } -}; - -static void -maybe_add_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 PangoOTRuleset * -get_ruleset (PangoFont *font) -{ - PangoOTRuleset *ruleset; - static GQuark ruleset_quark = 0; - PangoOTInfo *info; - - if (!ruleset_quark) - ruleset_quark = g_quark_from_string ("pango-arabic-ruleset"); - - ruleset = g_object_get_qdata (G_OBJECT (font), ruleset_quark); - - if (!ruleset) - { - PangoOTTag arab_tag = FT_MAKE_TAG ('a', 'r', 'a', 'b'); - guint script_index; - FT_Face face; - - face = pango_ft2_font_get_face (font); - if (!face) - { - g_warning ("Couldn't get face for font"); - return NULL; - } - - info = pango_ot_info_get (face); - ruleset = pango_ot_ruleset_new (info); - - if (!info) - return NULL; - - 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); - - g_object_set_qdata_full (G_OBJECT (font), ruleset_quark, ruleset, - (GDestroyNotify) g_object_unref); - } - else - { - g_object_unref (ruleset); - ruleset = NULL; - } - } - - return ruleset; -} - -/* - * FT2 system script engine portion - */ - -static PangoGlyph -find_char (PangoFont *font, - gunichar wc) -{ - FT_Face face; - FT_UInt index; - - face = pango_ft2_font_get_face (font); - index = FT_Get_Char_Index (face, wc); - if (index && index <= face->num_glyphs) - return index; - - return 0; -} - -static void -swap_range (PangoGlyphString *glyphs, int start, int end) -{ - int i, j; - - for (i = start, j = end - 1; i < j; i++, j--) - { - PangoGlyphInfo glyph_info; - gint log_cluster; - - glyph_info = glyphs->glyphs[i]; - glyphs->glyphs[i] = glyphs->glyphs[j]; - glyphs->glyphs[j] = glyph_info; - - log_cluster = glyphs->log_clusters[i]; - glyphs->log_clusters[i] = glyphs->log_clusters[j]; - glyphs->log_clusters[j] = log_cluster; - } -} - -static void -set_glyph (PangoFont *font, - PangoGlyphString *glyphs, - int i, - int offset, - PangoGlyph glyph) -{ - PangoRectangle logical_rect; - - glyphs->glyphs[i].glyph = glyph; - - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - - glyphs->log_clusters[i] = offset; - - pango_font_get_glyph_extents (font, - glyphs->glyphs[i].glyph, NULL, &logical_rect); - glyphs->glyphs[i].geometry.width = logical_rect.width; - - if (i > 0) - { - glyphs->glyphs[i-1].geometry.width += - pango_ft2_font_get_kerning (font, - glyphs->glyphs[i-1].glyph, - glyphs->glyphs[i].glyph); - } -} - -static void -arabic_engine_shape (PangoFont *font, - const char *text, - gint length, - PangoAnalysis *analysis, - PangoGlyphString *glyphs) -{ - int n_chars; - int i; - const char *p; - gulong *properties = NULL; - gunichar *wcs = NULL; - PangoOTRuleset *ruleset; - - g_return_if_fail (font != NULL); - g_return_if_fail (text != NULL); - g_return_if_fail (length >= 0); - g_return_if_fail (analysis != NULL); - - n_chars = g_utf8_strlen (text, length); - pango_glyph_string_set_size (glyphs, n_chars); - - ruleset = get_ruleset (font); - if (ruleset) - { - wcs = g_utf8_to_ucs4_fast (text, length, NULL); - properties = g_new0 (gulong, n_chars); - - Arabic_Assign_Properties (wcs, properties, 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 - { - /* Hack - Microsoft fonts are strange and don't contain the - * correct rules to shape ARABIC LETTER FARSI YEH in - * medial/initial position. It looks identical to ARABIC LETTER - * YEH in these positions, so we substitute - */ - if (wc == 0x6cc && ruleset && - ((properties[i] & (initial | medial)) != (initial | medial))) - wc = 0x64a; - - index = find_char (font, wc); - - if (!index) - { - set_glyph (font, glyphs, i, p - text, - pango_ft2_get_unknown_glyph (font)); - } - else - { - set_glyph (font, glyphs, i, p - text, index); - - 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 - } - } - } - } - - p = g_utf8_next_char (p); - } - - ruleset = get_ruleset (font); - - 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; - - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - } - - /* Simple bidi support */ - - if (analysis->level % 2) - { - int start, end; - - /* 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; - } - } -} - -static PangoCoverage * -arabic_engine_get_coverage (PangoFont *font, - PangoLanguage *lang) -{ - return pango_font_get_coverage (font, lang); -} - -static PangoEngine * -arabic_engine_ft2_new () -{ - PangoEngineShape *result; - - result = g_new (PangoEngineShape, 1); - - result->engine.id = SCRIPT_ENGINE_NAME; - result->engine.type = PANGO_ENGINE_TYPE_SHAPE; - result->engine.length = sizeof (result); - result->script_shape = arabic_engine_shape; - result->get_coverage = arabic_engine_get_coverage; - - return (PangoEngine *)result; -} - -/* The following three functions provide the public module API for - * Pango. If we are compiling it is a module, then we name the - * entry points script_engine_list, etc. But if we are compiling - * it for inclusion directly in Pango, then we need them to - * to have distinct names for this module, so we prepend - * _pango_arabic_ - */ -#ifdef FT2_MODULE_PREFIX -#define MODULE_ENTRY(func) _pango_arabic_ft2_##func -#else -#define MODULE_ENTRY(func) func -#endif - -/* List the engines contained within this module - */ -void -MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines) -{ - *engines = script_engines; - *n_engines = G_N_ELEMENTS (script_engines); -} - -/* Load a particular engine given the ID for the engine - */ -PangoEngine * -MODULE_ENTRY(script_engine_load) (const char *id) -{ - if (!strcmp (id, SCRIPT_ENGINE_NAME)) - return arabic_engine_ft2_new (); - else - return NULL; -} - -void -MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) -{ -} diff --git a/modules/arabic/arabic-x.c b/modules/arabic/arabic-x.c index ccd84a91..3c3b9689 100644 --- a/modules/arabic/arabic-x.c +++ b/modules/arabic/arabic-x.c @@ -331,24 +331,16 @@ arabic_engine_x_new () -/* The following three functions provide the public module API for - * Pango - */ -#ifdef X_MODULE_PREFIX -#define MODULE_ENTRY(func) _pango_arabic_x_##func -#else -#define MODULE_ENTRY(func) func -#endif - void -MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, int *n_engines) +PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines, + int *n_engines) { *engines = script_engines; *n_engines = n_script_engines; } PangoEngine * -MODULE_ENTRY(script_engine_load) (const char *id) +PANGO_MODULE_ENTRY(load) (const char *id) { if (!strcmp (id, SCRIPT_ENGINE_NAME)) return arabic_engine_x_new (); @@ -357,6 +349,6 @@ MODULE_ENTRY(script_engine_load) (const char *id) } void -MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) +PANGO_MODULE_ENTRY(unload) (PangoEngine *engine) { } diff --git a/modules/arabic/arabic-xft.c b/modules/arabic/arabic-xft.c deleted file mode 100644 index f4a63c0a..00000000 --- a/modules/arabic/arabic-xft.c +++ /dev/null @@ -1,352 +0,0 @@ -/* Pango - * arabic-xft.h: - * - * Copyright (C) 2000 Red Hat Software - * Author: Owen Taylor <otaylor@redhat.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 "arabic-ot.h" - -#include "pangoxft.h" -#include "pango-engine.h" -#include "pango-utils.h" - -#define SCRIPT_ENGINE_NAME "ArabicScriptEngineXft" - -static PangoEngineRange arabic_ranges[] = { - /* Language characters */ - { 0x060c, 0x06f9, "*" }, /* Arabic */ -}; - -static PangoEngineInfo script_engines[] = { - { - SCRIPT_ENGINE_NAME, - PANGO_ENGINE_TYPE_SHAPE, - PANGO_RENDER_TYPE_XFT, - arabic_ranges, G_N_ELEMENTS(arabic_ranges) - } -}; - -static void -maybe_add_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 PangoOTRuleset * -get_ruleset (FT_Face face) -{ - PangoOTRuleset *ruleset; - static GQuark ruleset_quark = 0; - - PangoOTInfo *info = pango_ot_info_get (face); - - if (!ruleset_quark) - ruleset_quark = g_quark_from_string ("pango-arabic-ruleset"); - - if (!info) - return NULL; - - ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark); - - if (!ruleset) - { - PangoOTTag arab_tag = FT_MAKE_TAG ('a', 'r', 'a', 'b'); - guint script_index; - - ruleset = pango_ot_ruleset_new (info); - - 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); - } - - 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 -arabic_engine_shape (PangoFont *font, - const char *text, - gint length, - PangoAnalysis *analysis, - PangoGlyphString *glyphs) -{ - int n_chars; - int i; - const char *p; - gulong *properties = NULL; - gunichar *wcs = NULL; - FT_Face face; - PangoOTRuleset *ruleset; - - g_return_if_fail (font != NULL); - g_return_if_fail (text != NULL); - g_return_if_fail (length >= 0); - g_return_if_fail (analysis != NULL); - - face = pango_xft_font_lock_face (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) - { - wcs = g_utf8_to_ucs4_fast (text, length, NULL); - properties = g_new0 (gulong, n_chars); - - Arabic_Assign_Properties (wcs, properties, 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 - { - /* Hack - Microsoft fonts are strange and don't contain the - * correct rules to shape ARABIC LETTER FARSI YEH in - * medial/initial position. It looks identical to ARABIC LETTER - * YEH in these positions, so we substitute - */ - if (wc == 0x6cc && ruleset && - ((properties[i] & (initial | medial)) != (initial | medial))) - wc = 0x64a; - - index = pango_xft_font_get_glyph (font, wc); - - if (!index) - { - set_glyph (font, glyphs, i, p - text, - pango_xft_font_get_unknown_glyph (font, wc)); - } - else - { - set_glyph (font, glyphs, i, p - text, index); - - 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 - } - } - } - } - - 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; - - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - } - - /* Simple bidi support */ - - if (analysis->level % 2) - { - int start, end; - - /* 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; - } - } - - pango_xft_font_unlock_face (font); -} - -static PangoCoverage * -arabic_engine_get_coverage (PangoFont *font, - PangoLanguage *lang) -{ - return pango_font_get_coverage (font, lang); -} - -static PangoEngine * -arabic_engine_xft_new () -{ - PangoEngineShape *result; - - result = g_new (PangoEngineShape, 1); - - result->engine.id = SCRIPT_ENGINE_NAME; - result->engine.type = PANGO_ENGINE_TYPE_SHAPE; - result->engine.length = sizeof (result); - result->script_shape = arabic_engine_shape; - result->get_coverage = arabic_engine_get_coverage; - - return (PangoEngine *)result; -} - -/* The following three functions provide the public module API for - * Pango. If we are compiling it is a module, then we name the - * entry points script_engine_list, etc. But if we are compiling - * it for inclusion directly in Pango, then we need them to - * to have distinct names for this module, so we prepend - * _pango_arabic_ - */ -#ifdef XFT_MODULE_PREFIX -#define MODULE_ENTRY(func) _pango_arabic_xft_##func -#else -#define MODULE_ENTRY(func) func -#endif - -/* List the engines contained within this module - */ -void -MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines) -{ - *engines = script_engines; - *n_engines = G_N_ELEMENTS (script_engines); -} - -/* Load a particular engine given the ID for the engine - */ -PangoEngine * -MODULE_ENTRY(script_engine_load) (const char *id) -{ - if (!strcmp (id, SCRIPT_ENGINE_NAME)) - return arabic_engine_xft_new (); - else - return NULL; -} - -void -MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) -{ -} |