diff options
author | Owen Taylor <otaylor@src.gnome.org> | 2002-07-26 23:14:03 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-07-26 23:14:03 +0000 |
commit | 06aab38b27870d0026903de80e2e687ade30a915 (patch) | |
tree | 972b5c5e6121a73bd6665f5c43954c13ad54a88b /modules/thai | |
parent | cb4479a9348f90c2b8cbbdc2de8d1d88eb788d34 (diff) | |
download | pango-06aab38b27870d0026903de80e2e687ade30a915.tar.gz |
ri Jul 26 18:48:49 2002 Owen Taylor <otaylor@redhat.com>
* configure.in modules/thai/Makefile.am
modules/thai/thai-shaper.[ch]
modules/thai/thai-xft.c modules/thai/thai-x.c:
Patch from Theppitak Karoonboonyanan that factors
out common code from thai-x.c and adds a new
Xft shaper for Thai. (#78346)
Diffstat (limited to 'modules/thai')
-rw-r--r-- | modules/thai/thai-fc.c | 239 | ||||
-rw-r--r-- | modules/thai/thai-shaper.c | 720 | ||||
-rw-r--r-- | modules/thai/thai-shaper.h | 55 | ||||
-rw-r--r-- | modules/thai/thai-xft.c | 239 |
4 files changed, 1253 insertions, 0 deletions
diff --git a/modules/thai/thai-fc.c b/modules/thai/thai-fc.c new file mode 100644 index 00000000..6b9d7aaf --- /dev/null +++ b/modules/thai/thai-fc.c @@ -0,0 +1,239 @@ +/* Pango + * thai-xft.c: + * + * Copyright (C) 1999 Red Hat Software + * Author: Owen Taylor <otaylor@redhat.com> + * + * Copyright (C) 2002 NECTEC + * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th> + * + * Copyright (c) 1996-2000 by Sun Microsystems, Inc. + * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.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 <glib.h> +#include "pango-engine.h" +#include "thai-shaper.h" + +#define SCRIPT_ENGINE_NAME "ThaiScriptEngineXft" + +/* We handle the range U+0e01 to U+0e5b exactly + */ +static PangoEngineRange thai_ranges[] = { + { 0x0e01, 0x0e5b, "*" }, /* Thai */ +}; + +static PangoEngineInfo script_engines[] = { + { + SCRIPT_ENGINE_NAME, + PANGO_ENGINE_TYPE_SHAPE, + PANGO_RENDER_TYPE_XFT, + thai_ranges, G_N_ELEMENTS(thai_ranges) + } +}; + +/* TIS-to-Unicode glyph maps for characters 0x80-0xff + */ +static int tis620_0[128] = { + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + 0x0020, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0, 0, 0, 0 +}; + +static int tis620_1[128] = { + 0x00ab, 0x00bb, 0x2026, 0xf88c, 0xf88f, 0xf892, 0xf895, 0xf898, + 0xf88b, 0xf88e, 0xf891, 0xf894, 0xf897, 0x201c, 0x201d, 0xf899, + /**/ 0, 0x2022, 0xf884, 0xf889, 0xf885, 0xf886, 0xf887, 0xf888, + 0xf88a, 0xf88d, 0xf890, 0xf893, 0xf896, 0x2018, 0x2019, 0, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0xfeff, 0x200b, 0x2013, 0x2014, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x2122, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x00ae, 0x00a9, 0, 0, 0, 0 +}; + +static int tis620_2[128] = { + 0xf700, 0xf701, 0xf702, 0xf703, 0xf704, 0x2026, 0xf705, 0xf706, + 0xf707, 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e, + 0xf70f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, + 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf718, 0xf719, 0xf71a, 0 +}; + +static int +contain_glyphs(PangoFont *font, const int glyph_map[128]) +{ + unsigned char c; + + for (c = 0; c < 0x80; c++) + { + if (glyph_map[c]) + { + if (!pango_xft_font_has_char (font, glyph_map[c])) + return 0; + } + } + return 1; +} + +/* Returns a structure with information we will use to rendering given the + * #PangoFont. This is computed once per font and cached for later retrieval. + */ +ThaiFontInfo * +get_font_info (PangoFont *font) +{ + ThaiFontInfo *font_info; + GQuark info_id = g_quark_from_string ("thai-font-info"); + + font_info = g_object_get_qdata (G_OBJECT (font), info_id); + + if (!font_info) + { + /* No cached information not found, so we need to compute it + * from scratch + */ + font_info = g_new (ThaiFontInfo, 1); + font_info->font = font; + + /* detect font set by determining availibility of glyphs */ + if (contain_glyphs(font, tis620_2)) + font_info->font_set = THAI_FONT_TIS_WIN; + else if (contain_glyphs(font, tis620_1)) + font_info->font_set = THAI_FONT_TIS_MAC; + else if (contain_glyphs(font, tis620_0)) + font_info->font_set = THAI_FONT_TIS; + else + font_info->font_set = THAI_FONT_ISO10646; + + g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free); + } + + return font_info; +} + +PangoGlyph +make_glyph (ThaiFontInfo *font_info, unsigned char c) +{ + int index; + + switch (font_info->font_set) { + case THAI_FONT_ISO10646: + case THAI_FONT_TIS: index = (c & 0x80) ? tis620_0[c & 0x7f] : c; break; + case THAI_FONT_TIS_MAC: index = (c & 0x80) ? tis620_1[c & 0x7f] : c; break; + case THAI_FONT_TIS_WIN: index = (c & 0x80) ? tis620_2[c & 0x7f] : c; break; + default: index = 0; break; + } + + return pango_xft_font_get_glyph (font_info->font, index); +} + +static PangoCoverage * +thai_engine_get_coverage (PangoFont *font, + PangoLanguage *lang) +{ + return pango_font_get_coverage (font, lang); +} + +static PangoEngine * +thai_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 = thai_engine_shape; + result->get_coverage = thai_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_thai_xft_ + */ +#ifdef XFT_MODULE_PREFIX +#define MODULE_ENTRY(func) _pango_thai_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 thai_engine_xft_new (); + else + return NULL; +} + +void +MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) +{ +} + diff --git a/modules/thai/thai-shaper.c b/modules/thai/thai-shaper.c new file mode 100644 index 00000000..1c1a9785 --- /dev/null +++ b/modules/thai/thai-shaper.c @@ -0,0 +1,720 @@ +/* Pango + * thai-shaper.c: + * + * Copyright (C) 1999 Red Hat Software + * Author: Owen Taylor <otaylor@redhat.com> + * + * Software and Language Engineering Laboratory, NECTEC + * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th> + * + * Copyright (c) 1996-2000 by Sun Microsystems, Inc. + * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.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 <glib.h> +#include "pangoxft.h" +#include "pango-engine.h" +#include "thai-shaper.h" + +#define MAX_CLUSTER_CHRS 256 +#define MAX_GLYPHS 256 + +/* Define TACTIS character classes */ +#define CTRL 0 +#define NON 1 +#define CONS 2 +#define LV 3 +#define FV1 4 +#define FV2 5 +#define FV3 6 +#define BV1 7 +#define BV2 8 +#define BD 9 +#define TONE 10 +#define AD1 11 +#define AD2 12 +#define AD3 13 +#define AV1 14 +#define AV2 15 +#define AV3 16 + +#define _ND 0 +#define _NC 1 +#define _UC (1<<1) +#define _BC (1<<2) +#define _SC (1<<3) +#define _AV (1<<4) +#define _BV (1<<5) +#define _TN (1<<6) +#define _AD (1<<7) +#define _BD (1<<8) +#define _AM (1<<9) + +#define NoTailCons _NC +#define UpTailCons _UC +#define BotTailCons _BC +#define SpltTailCons _SC +#define Cons (NoTailCons|UpTailCons|BotTailCons|SpltTailCons) +#define AboveVowel _AV +#define BelowVowel _BV +#define Tone _TN +#define AboveDiac _AD +#define BelowDiac _BD +#define SaraAm _AM + +#define char_class(wc) TAC_char_class[(unsigned int)(wc)] +#define is_char_type(wc, mask) (char_type_table[ucs2tis ((wc))] & (mask)) + +/* All combining marks for Thai fall in the range U+0E30-U+0E50, + * so we confine our data tables to that range, and use + * default values for characters outside those ranges. + */ + +/* Map from code point to group used for rendering with XTIS fonts + * (0 == base character) + */ +static const char groups[32] = { + 0, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 1, 0 +}; + +/* Map from code point to index within group 1 + * (0 == no combining mark from group 1) + */ +static const char group1_map[32] = { + 0, 1, 0, 0, 2, 3, 4, 5, + 6, 7, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* Map from code point to index within group 2 + * (0 == no combining mark from group 2) + */ +static const char group2_map[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + 2, 3, 4, 5, 6, 7, 1, 0 +}; + +static const gint char_type_table[256] = { + /* 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, A, B, C, D, E, F */ + + /*00*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*10*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*20*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*30*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*40*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*50*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*60*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*70*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*80*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + /*90*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + + /*A0*/ _ND, _NC, _NC, _NC, _NC, _NC, _NC, _NC, + _NC, _NC, _NC, _NC, _NC, _SC, _BC, _BC, + /*B0*/ _SC, _NC, _NC, _NC, _NC, _NC, _NC, _NC, + _NC, _NC, _NC, _UC, _NC, _UC, _NC, _UC, + /*C0*/ _NC, _NC, _NC, _NC, _ND, _NC, _ND, _NC, + _NC, _NC, _NC, _NC, _UC, _NC, _NC, _ND, + /*D0*/ _ND, _AV, _ND, _AM, _AV, _AV, _AV, _AV, + _BV, _BV, _BD, _ND, _ND, _ND, _ND, _ND, + /*E0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _AD, + _TN, _TN, _TN, _TN, _AD, _AD, _AD, _ND, + /*F0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, + _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND, +}; + +static const gint TAC_char_class[256] = { + /* 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, A, B, C, D, E, F */ + + /*00*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + /*10*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + /*20*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON, NON, + /*30*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON, NON, + /*40*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON, NON, + /*50*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON, NON, + /*60*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON, NON, + /*70*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON,CTRL, + /*80*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + /*90*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL, + /*A0*/ NON,CONS,CONS,CONS,CONS,CONS,CONS,CONS, + CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS, + /*B0*/ CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS, + CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS, + /*C0*/ CONS,CONS,CONS,CONS, FV3,CONS, FV3,CONS, + CONS,CONS,CONS,CONS,CONS,CONS,CONS, NON, + /*D0*/ FV1, AV2, FV1, FV1, AV1, AV3, AV2, AV3, + BV1, BV2, BD, NON, NON, NON, NON, NON, + /*E0*/ LV, LV, LV, LV, LV, FV2, NON, AD2, + TONE,TONE,TONE,TONE, AD1, AD1, AD3, NON, + /*F0*/ NON, NON, NON, NON, NON, NON, NON, NON, + NON, NON, NON, NON, NON, NON, NON,CTRL, +}; + +static const gchar TAC_compose_and_input_check_type_table[17][17] = { + /* Cn */ /* 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, A, B, C, D, E, F */ + /* Cn-1 00 */ { 'X', 'A', 'A', 'A', 'A', 'A', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 10 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 20 */ { 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'C', + 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C' }, + /* 30 */ {'X', 'S', 'A', 'S', 'S', 'S', 'S', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 40 */ { 'X', 'S', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 50 */ { 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 60 */ { 'X', 'A', 'A', 'A', 'S', 'A', 'S', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 70 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'C', 'C', 'R', 'R', 'R', 'R', 'R' }, + /* 80 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'C', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* 90 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* A0 */ { 'X', 'A', 'A', 'A', 'A', 'A', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* B0 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* C0 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* D0 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, + /* E0 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'C', 'C', 'R', 'R', 'R', 'R', 'R' }, + /* F0 */ { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'C', 'R', 'R', 'R', 'R', 'R', 'R' }, + { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', + 'R', 'R', 'C', 'R', 'C', 'R', 'R', 'R', 'R' } +}; + +typedef struct { + gint ShiftDown_TONE_AD[8]; + gint ShiftDownLeft_TONE_AD[8]; + gint ShiftLeft_TONE_AD[8]; + gint ShiftLeft_AV[7]; + gint ShiftDown_BV_BD[3]; + gint TailCutCons[4]; +} ThaiShapeTable; + +#define shiftdown_tone_ad(c,tbl) ((tbl)->ShiftDown_TONE_AD[(c)-0xE7]) +#define shiftdownleft_tone_ad(c,tbl) ((tbl)->ShiftDownLeft_TONE_AD[(c)-0xE7]) +#define shiftleft_tone_ad(c,tbl) ((tbl)->ShiftLeft_TONE_AD[(c)-0xE7]) +#define shiftleft_av(c,tbl) ((tbl)->ShiftLeft_AV[(c)-0xD1]) +#define shiftdown_bv_bd(c,tbl) ((tbl)->ShiftDown_BV_BD[(c)-0xD8]) +#define tailcutcons(c,tbl) ((tbl)->TailCutCons[(c)-0xAD]) + +/* No adjusted vowel/tonemark glyphs (tis620-0) + */ +static const ThaiShapeTable tis620_0_shape_table = { + { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE }, + { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE }, + { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE }, + { 0xD1, 0x00, 0x00, 0xD4, 0xD5, 0xD6, 0xD7 }, + { 0xD8, 0xD9, 0xDA }, + { 0xAD, 0x00, 0x00, 0xB0 } +}; + +/* Macintosh + */ +static const ThaiShapeTable Mac_shape_table = { + { 0xE7, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0xED, 0xEE }, + { 0x93, 0x83, 0x84, 0x85, 0x86, 0x87, 0x8F, 0xEE }, + { 0x93, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x8F, 0xEE }, + { 0x92, 0x00, 0x00, 0x94, 0x95, 0x96, 0x97 }, + { 0xD8, 0xD9, 0xDA }, + { 0xAD, 0x00, 0x00, 0xB0 } +}; + +/* Microsoft Window + */ +static const ThaiShapeTable Win_shape_table = { + { 0xE7, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0xED, 0xEE }, + { 0x9A, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x99, 0xEE }, + { 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x99, 0xEE }, + { 0x98, 0x00, 0x00, 0x81, 0x82, 0x83, 0x84 }, + { 0xFC, 0xFD, 0xFE }, + { 0x90, 0x00, 0x00, 0x80 } +}; + +static void +add_glyph (ThaiFontInfo *font_info, + PangoGlyphString *glyphs, + gint cluster_start, + PangoGlyph glyph, + gboolean combining) +{ + PangoRectangle ink_rect, logical_rect; + gint index = glyphs->num_glyphs; + + pango_glyph_string_set_size (glyphs, index + 1); + + glyphs->glyphs[index].glyph = glyph; + glyphs->glyphs[index].attr.is_cluster_start = combining ? 0 : 1; + + glyphs->log_clusters[index] = cluster_start; + + pango_font_get_glyph_extents (font_info->font, + glyphs->glyphs[index].glyph, &ink_rect, &logical_rect); + + if (combining) + { + glyphs->glyphs[index].geometry.x_offset = + glyphs->glyphs[index - 1].geometry.width; + glyphs->glyphs[index].geometry.width = + logical_rect.width + glyphs->glyphs[index - 1].geometry.width; + glyphs->glyphs[index - 1].geometry.width = 0; + } + else + { + if (logical_rect.width > 0) + { + glyphs->glyphs[index].geometry.x_offset = 0; + glyphs->glyphs[index].geometry.width = logical_rect.width; + } + else + { + glyphs->glyphs[index].geometry.x_offset = ink_rect.width; + glyphs->glyphs[index].geometry.width = ink_rect.width; + } + } + glyphs->glyphs[index].geometry.y_offset = 0; +} + +static gint +get_adjusted_glyphs_list (ThaiFontInfo *font_info, + gunichar *cluster, + gint num_chrs, + PangoGlyph *glyph_lists, + const ThaiShapeTable *shaping_table) +{ + switch (num_chrs) + { + case 1: + if (is_char_type (cluster[0], BelowVowel|BelowDiac|AboveVowel|AboveDiac|Tone)) + { + if (font_info->font_set == THAI_FONT_TIS) + glyph_lists[0] = make_glyph (font_info, 0x20); + else + glyph_lists[0] = make_glyph (font_info, 0x7F); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[0])); + return 2; + } + else + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + return 1; + } + break; + + case 2: + if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) && + is_char_type (cluster[1], SaraAm)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, 0xED); + glyph_lists[2] = make_glyph (font_info, 0xD2); + return 3; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], SaraAm)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftleft_tone_ad (0xED, shaping_table)); + glyph_lists[2] = make_glyph (font_info, 0xD2); + return 3; + } + else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) && + is_char_type (cluster[1], AboveVowel)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + return 2; + } + else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) && + is_char_type (cluster[1], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftdown_tone_ad (ucs2tis (cluster[1]), shaping_table)); + return 2; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], AboveVowel)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftleft_av (ucs2tis (cluster[1]), shaping_table)); + return 2; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftdownleft_tone_ad (ucs2tis (cluster[1]), shaping_table)); + return 2; + } + else if (is_char_type (cluster[0], NoTailCons|UpTailCons) && + is_char_type (cluster[1], BelowVowel|BelowDiac)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + return 2; + } + else if (is_char_type (cluster[0], BotTailCons) && + is_char_type (cluster[1], BelowVowel|BelowDiac)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, + shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table)); + return 2; + } + else if (is_char_type (cluster[0], SpltTailCons) && + is_char_type (cluster[1], BelowVowel|BelowDiac)) + { + glyph_lists[0] = make_glyph (font_info, + tailcutcons (ucs2tis (cluster[0]), shaping_table)); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + return 2; + } + else + { + if (font_info->font_set == THAI_FONT_TIS) + glyph_lists[0] = make_glyph (font_info, 0x20); + else + glyph_lists[0] = make_glyph (font_info, 0x7F); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[2] = + make_glyph (font_info, ucs2tis (cluster[1])); + return 3; + } + break; + + case 3: + if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) && + is_char_type (cluster[1], Tone) && + is_char_type (cluster[2], SaraAm)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, 0xED); + glyph_lists[2] = + make_glyph (font_info, ucs2tis (cluster[1])); + glyph_lists[3] = make_glyph (font_info, 0xD2); + return 4; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], Tone) && + is_char_type (cluster[2], SaraAm)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftleft_tone_ad (0xED, shaping_table)); + glyph_lists[2] = make_glyph (font_info, + shiftleft_tone_ad (ucs2tis (cluster[1]), shaping_table)); + glyph_lists[3] = make_glyph (font_info, 0xD2); + return 4; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], AboveVowel) && + is_char_type (cluster[2], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftleft_av (ucs2tis (cluster[1]), shaping_table)); + glyph_lists[2] = make_glyph (font_info, + shiftleft_tone_ad (ucs2tis (cluster[2]), shaping_table)); + return 3; + } + else if (is_char_type (cluster[0], UpTailCons) && + is_char_type (cluster[1], BelowVowel) && + is_char_type (cluster[2], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + glyph_lists[2] = make_glyph (font_info, + shiftdownleft_tone_ad (ucs2tis (cluster[2]), shaping_table)); + return 3; + } + else if (is_char_type (cluster[0], NoTailCons) && + is_char_type (cluster[1], BelowVowel) && + is_char_type (cluster[2], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + glyph_lists[2] = + make_glyph (font_info, + shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table)); + return 3; + } + else if (is_char_type (cluster[0], SpltTailCons) && + is_char_type (cluster[1], BelowVowel) && + is_char_type (cluster[2], AboveDiac|Tone)) + { + glyph_lists[0] = make_glyph (font_info, + tailcutcons (ucs2tis (cluster[0]), shaping_table)); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + glyph_lists[2] = make_glyph (font_info, + shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table)); + return 3; + } + else if (is_char_type (cluster[0], BotTailCons) && + is_char_type (cluster[1], BelowVowel) && + is_char_type (cluster[2], AboveDiac|Tone)) + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = make_glyph (font_info, + shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table)); + glyph_lists[2] = make_glyph (font_info, + shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table)); + return 3; + } + else + { + glyph_lists[0] = + make_glyph (font_info, ucs2tis (cluster[0])); + glyph_lists[1] = + make_glyph (font_info, ucs2tis (cluster[1])); + glyph_lists[2] = + make_glyph (font_info, ucs2tis (cluster[2])); + return 3; + } + break; + } + + return 0; +} + +static gint +get_glyphs_list (ThaiFontInfo *font_info, + gunichar *cluster, + gint num_chrs, + PangoGlyph *glyph_lists) +{ + PangoGlyph glyph; + gint xtis_index; + gint i; + + switch (font_info->font_set) + { + case THAI_FONT_NONE: + for (i=0; i < num_chrs; i++) + glyph_lists[i] = pango_xft_font_get_unknown_glyph (font_info->font, glyph_lists[i]); + return num_chrs; + + case THAI_FONT_XTIS: + /* If we are rendering with an XTIS font, we try to find a precomposed + * glyph for the cluster. + */ + xtis_index = 0x100 * (cluster[0] - 0xe00 + 0x20) + 0x30; + if (cluster[1]) + xtis_index +=8 * group1_map[cluster[1] - 0xe30]; + if (cluster[2]) + xtis_index += group2_map[cluster[2] - 0xe30]; + glyph = make_glyph (font_info, xtis_index); + if (pango_x_has_glyph (font_info->font, glyph)) { + glyph_lists[0] = glyph; + return 1; + } + for (i=0; i < num_chrs; i++) + glyph_lists[i] = + make_glyph (font_info, + 0x100 * (cluster[i] - 0xe00 + 0x20) + 0x30); + return num_chrs; + + case THAI_FONT_TIS: + /* TIS620-0 + Wtt2.0 Extension + */ + return get_adjusted_glyphs_list (font_info, cluster, + num_chrs, glyph_lists, &tis620_0_shape_table); + + case THAI_FONT_TIS_MAC: + /* MacIntosh Extension + */ + return get_adjusted_glyphs_list (font_info, cluster, + num_chrs, glyph_lists, &Mac_shape_table); + + case THAI_FONT_TIS_WIN: + /* Microsoft Extension + */ + return get_adjusted_glyphs_list (font_info, cluster, + num_chrs, glyph_lists, &Win_shape_table); + + case THAI_FONT_ISO10646: + for (i=0; i < num_chrs; i++) + glyph_lists[i] = make_glyph (font_info, cluster[i]); + return num_chrs; + } + + return 0; /* Quiet GCC */ +} + +static void +add_cluster (ThaiFontInfo *font_info, + PangoGlyphString *glyphs, + gint cluster_start, + gunichar *cluster, + gint num_chrs) +{ + PangoGlyph glyphs_list[MAX_GLYPHS]; + gint num_glyphs; + gint i; + + num_glyphs = get_glyphs_list(font_info, cluster, num_chrs, glyphs_list); + for (i=0; i<num_glyphs; i++) + add_glyph (font_info, glyphs, cluster_start, glyphs_list[i], + i == 0 ? FALSE : TRUE); +} + +static gboolean +is_wtt_composible (gunichar cur_wc, gunichar nxt_wc) +{ + switch (TAC_compose_and_input_check_type_table[char_class (ucs2tis (cur_wc))] + [char_class (ucs2tis (nxt_wc))]) + { + case 'A': + case 'S': + case 'R': + case 'X': + return FALSE; + + case 'C': + return TRUE; + } + + g_assert_not_reached (); + return FALSE; +} + +static const char * +get_next_cluster(const char *text, + gint length, + gunichar *cluster, + gint *num_chrs) +{ + const char *p; + gint n_chars = 0; + + p = text; + while (p < text + length && n_chars < 3) + { + gunichar current = g_utf8_get_char (p); + + if (n_chars == 0 || + is_wtt_composible ((gunichar)(cluster[n_chars - 1]), current) || + (n_chars == 1 && + is_char_type (cluster[0], Cons) && + is_char_type (current, SaraAm)) || + (n_chars == 2 && + is_char_type (cluster[0], Cons) && + is_char_type (cluster[1], Tone) && + is_char_type (current, SaraAm))) + { + cluster[n_chars++] = current; + p = g_utf8_next_char (p); + } + else + break; + } + + *num_chrs = n_chars; + return p; +} + +void +thai_engine_shape (PangoFont *font, + const char *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs) +{ + ThaiFontInfo *font_info; + const char *p; + const char *log_cluster; + gunichar cluster[MAX_CLUSTER_CHRS]; + gint num_chrs; + + pango_glyph_string_set_size (glyphs, 0); + + font_info = get_font_info (font); + + p = text; + while (p < text + length) + { + log_cluster = p; + p = get_next_cluster (p, text + length - p, cluster, &num_chrs); + add_cluster (font_info, glyphs, log_cluster - text, cluster, num_chrs); + } +} + diff --git a/modules/thai/thai-shaper.h b/modules/thai/thai-shaper.h new file mode 100644 index 00000000..7d465d5e --- /dev/null +++ b/modules/thai/thai-shaper.h @@ -0,0 +1,55 @@ +#ifndef __THAI_SHAPER_H__ +#define __THAI_SHAPER_H__ + +#include "pangox.h" +#include "pangoxft.h" + +#define ucs2tis(wc) (unsigned int)((unsigned int)(wc) - 0x0E00 + 0xA0) +#define tis2uni(c) ((gunichar)(c) - 0xA0 + 0x0E00) + +typedef struct _ThaiFontInfo ThaiFontInfo; + +/* Font encodings we will use + */ +typedef enum { + THAI_FONT_NONE, + THAI_FONT_XTIS, + THAI_FONT_TIS, + THAI_FONT_TIS_MAC, + THAI_FONT_TIS_WIN, + THAI_FONT_ISO10646 +} ThaiFontSet; + +typedef enum { + THAI_FONTINFO_X, + THAI_FONTINFO_XFT +} ThaiFontInfoType; + +struct _ThaiFontInfo +{ + PangoFont *font; + ThaiFontSet font_set; + PangoXSubfont subfont; /* For X backend */ +}; + +/* + * Abstract methods + */ +ThaiFontInfo * +get_font_info (PangoFont *font); + +PangoGlyph +make_glyph (ThaiFontInfo *font_info, unsigned char c); + +/* + * Public functions + */ +void +thai_engine_shape (PangoFont *font, + const char *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs); + +#endif /* __THAI_SHAPER_H__ */ + diff --git a/modules/thai/thai-xft.c b/modules/thai/thai-xft.c new file mode 100644 index 00000000..6b9d7aaf --- /dev/null +++ b/modules/thai/thai-xft.c @@ -0,0 +1,239 @@ +/* Pango + * thai-xft.c: + * + * Copyright (C) 1999 Red Hat Software + * Author: Owen Taylor <otaylor@redhat.com> + * + * Copyright (C) 2002 NECTEC + * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th> + * + * Copyright (c) 1996-2000 by Sun Microsystems, Inc. + * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.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 <glib.h> +#include "pango-engine.h" +#include "thai-shaper.h" + +#define SCRIPT_ENGINE_NAME "ThaiScriptEngineXft" + +/* We handle the range U+0e01 to U+0e5b exactly + */ +static PangoEngineRange thai_ranges[] = { + { 0x0e01, 0x0e5b, "*" }, /* Thai */ +}; + +static PangoEngineInfo script_engines[] = { + { + SCRIPT_ENGINE_NAME, + PANGO_ENGINE_TYPE_SHAPE, + PANGO_RENDER_TYPE_XFT, + thai_ranges, G_N_ELEMENTS(thai_ranges) + } +}; + +/* TIS-to-Unicode glyph maps for characters 0x80-0xff + */ +static int tis620_0[128] = { + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + /**/ 0, 0, 0, 0, 0, 0, 0, 0, + 0x0020, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0, 0, 0, 0 +}; + +static int tis620_1[128] = { + 0x00ab, 0x00bb, 0x2026, 0xf88c, 0xf88f, 0xf892, 0xf895, 0xf898, + 0xf88b, 0xf88e, 0xf891, 0xf894, 0xf897, 0x201c, 0x201d, 0xf899, + /**/ 0, 0x2022, 0xf884, 0xf889, 0xf885, 0xf886, 0xf887, 0xf888, + 0xf88a, 0xf88d, 0xf890, 0xf893, 0xf896, 0x2018, 0x2019, 0, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0xfeff, 0x200b, 0x2013, 0x2014, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x2122, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x00ae, 0x00a9, 0, 0, 0, 0 +}; + +static int tis620_2[128] = { + 0xf700, 0xf701, 0xf702, 0xf703, 0xf704, 0x2026, 0xf705, 0xf706, + 0xf707, 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e, + 0xf70f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, + 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf718, 0xf719, 0xf71a, 0 +}; + +static int +contain_glyphs(PangoFont *font, const int glyph_map[128]) +{ + unsigned char c; + + for (c = 0; c < 0x80; c++) + { + if (glyph_map[c]) + { + if (!pango_xft_font_has_char (font, glyph_map[c])) + return 0; + } + } + return 1; +} + +/* Returns a structure with information we will use to rendering given the + * #PangoFont. This is computed once per font and cached for later retrieval. + */ +ThaiFontInfo * +get_font_info (PangoFont *font) +{ + ThaiFontInfo *font_info; + GQuark info_id = g_quark_from_string ("thai-font-info"); + + font_info = g_object_get_qdata (G_OBJECT (font), info_id); + + if (!font_info) + { + /* No cached information not found, so we need to compute it + * from scratch + */ + font_info = g_new (ThaiFontInfo, 1); + font_info->font = font; + + /* detect font set by determining availibility of glyphs */ + if (contain_glyphs(font, tis620_2)) + font_info->font_set = THAI_FONT_TIS_WIN; + else if (contain_glyphs(font, tis620_1)) + font_info->font_set = THAI_FONT_TIS_MAC; + else if (contain_glyphs(font, tis620_0)) + font_info->font_set = THAI_FONT_TIS; + else + font_info->font_set = THAI_FONT_ISO10646; + + g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free); + } + + return font_info; +} + +PangoGlyph +make_glyph (ThaiFontInfo *font_info, unsigned char c) +{ + int index; + + switch (font_info->font_set) { + case THAI_FONT_ISO10646: + case THAI_FONT_TIS: index = (c & 0x80) ? tis620_0[c & 0x7f] : c; break; + case THAI_FONT_TIS_MAC: index = (c & 0x80) ? tis620_1[c & 0x7f] : c; break; + case THAI_FONT_TIS_WIN: index = (c & 0x80) ? tis620_2[c & 0x7f] : c; break; + default: index = 0; break; + } + + return pango_xft_font_get_glyph (font_info->font, index); +} + +static PangoCoverage * +thai_engine_get_coverage (PangoFont *font, + PangoLanguage *lang) +{ + return pango_font_get_coverage (font, lang); +} + +static PangoEngine * +thai_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 = thai_engine_shape; + result->get_coverage = thai_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_thai_xft_ + */ +#ifdef XFT_MODULE_PREFIX +#define MODULE_ENTRY(func) _pango_thai_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 thai_engine_xft_new (); + else + return NULL; +} + +void +MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) +{ +} + |