summaryrefslogtreecommitdiff
path: root/modules/thai
diff options
context:
space:
mode:
authorChookij Vanatham <chookij@src.gnome.org>2000-11-20 22:29:02 +0000
committerChookij Vanatham <chookij@src.gnome.org>2000-11-20 22:29:02 +0000
commit7c0ba0994df80590bb268c8449eb34350cffa6e4 (patch)
treec6e7bbbf12d7ba39125387ca69a73df672e3dd5d /modules/thai
parent4cd0ea80ed9b8d768eb4e736403ae195f18eaccd (diff)
downloadpango-7c0ba0994df80590bb268c8449eb34350cffa6e4.tar.gz
Added wtt clustering rule and supported Thai MS/MAC font layout.
Diffstat (limited to 'modules/thai')
-rw-r--r--modules/thai/thai-x.c692
-rw-r--r--modules/thai/thai.c692
2 files changed, 1192 insertions, 192 deletions
diff --git a/modules/thai/thai-x.c b/modules/thai/thai-x.c
index 6547250a..d6b2c44c 100644
--- a/modules/thai/thai-x.c
+++ b/modules/thai/thai-x.c
@@ -1,7 +1,14 @@
-/* Pango
+/* pANGO
* thai.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
@@ -19,10 +26,63 @@
* Boston, MA 02111-1307, USA.
*/
+
#include <glib.h>
#include "pango.h"
#include "pangox.h"
+#define ucs2tis(wc) (unsigned int)((unsigned int)(wc) - 0x0E00 + 0xA0)
+#define tis2uni(c) ((gunichar)(c) - 0xA0 + 0x0E00)
+
+#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))
+
/* We handle the range U+0e01 to U+0e5b exactly
*/
static PangoEngineRange thai_ranges[] = {
@@ -83,6 +143,8 @@ typedef enum {
THAI_FONT_NONE,
THAI_FONT_XTIS,
THAI_FONT_TIS,
+ THAI_FONT_TIS_MAC,
+ THAI_FONT_TIS_WIN,
THAI_FONT_ISO10646
} ThaiFontType;
@@ -128,6 +190,160 @@ static const char group2_map[32] = {
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])
+
+/* Macintosh
+ */
+static const ThaiShapeTable Mac_shape_table = {
+ { 0xE7, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0xED, 0xEE },
+ { 0xE7, 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 },
+ { 0xE7, 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 }
+};
+
/* Returns a structure with information we will use to rendering given the
* #PangoFont. This is computed once per font and cached for later retrieval.
*/
@@ -135,24 +351,26 @@ static ThaiFontInfo *
get_font_info (PangoFont *font)
{
static const char *charsets[] = {
+ "tis620-2",
+ "tis620-1",
+ "tis620-0",
"xtis620.2529-1",
"xtis-0",
- "tis620.2533-0",
"tis620.2533-1",
- "tis620.2529-0",
"tis620.2529-1",
"iso8859-11",
"iso10646-1",
};
static const int charset_types[] = {
+ THAI_FONT_TIS_WIN,
+ THAI_FONT_TIS_MAC,
+ THAI_FONT_TIS,
THAI_FONT_XTIS,
THAI_FONT_XTIS,
THAI_FONT_TIS,
THAI_FONT_TIS,
THAI_FONT_TIS,
- THAI_FONT_TIS,
- THAI_FONT_TIS,
THAI_FONT_ISO10646
};
@@ -160,14 +378,15 @@ get_font_info (PangoFont *font)
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
*/
PangoXSubfont *subfont_ids;
- int *subfont_charsets;
- int n_subfonts, i;
+ gint *subfont_charsets;
+ gint n_subfonts, i;
font_info = g_new (ThaiFontInfo, 1);
font_info->font = font;
@@ -202,12 +421,12 @@ get_font_info (PangoFont *font)
static void
add_glyph (ThaiFontInfo *font_info,
PangoGlyphString *glyphs,
- int cluster_start,
+ gint cluster_start,
PangoGlyph glyph,
gboolean combining)
{
PangoRectangle ink_rect, logical_rect;
- int index = glyphs->num_glyphs;
+ gint index = glyphs->num_glyphs;
pango_glyph_string_set_size (glyphs, index + 1);
@@ -221,10 +440,25 @@ add_glyph (ThaiFontInfo *font_info,
if (combining)
{
- glyphs->glyphs[index].geometry.width =
- MAX (logical_rect.width, glyphs->glyphs[index - 1].geometry.width);
- glyphs->glyphs[index - 1].geometry.width = 0;
- glyphs->glyphs[index].geometry.x_offset = 0;
+ if (font_info->type == THAI_FONT_TIS ||
+ font_info->type == THAI_FONT_TIS_MAC ||
+ font_info->type == THAI_FONT_TIS_WIN)
+ {
+ glyphs->glyphs[index].geometry.width =
+ logical_rect.width + glyphs->glyphs[index - 1].geometry.width;
+ if (logical_rect.width > 0)
+ glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index - 1].geometry.width;
+ else
+ glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index].geometry.width;
+ glyphs->glyphs[index - 1].geometry.width = 0;
+ }
+ else
+ {
+ glyphs->glyphs[index].geometry.width =
+ MAX (logical_rect.width, glyphs->glyphs[index - 1].geometry.width);
+ glyphs->glyphs[index - 1].geometry.width = 0;
+ glyphs->glyphs[index].geometry.x_offset = 0;
+ }
}
else
{
@@ -235,63 +469,362 @@ add_glyph (ThaiFontInfo *font_info,
glyphs->glyphs[index].geometry.y_offset = 0;
}
-/* Return the glyph code within the font for the given Unicode Thai
- * code pointer
- */
-static int
-get_glyph (ThaiFontInfo *font_info, gunichar wc)
+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))
+ {
+ glyph_lists[0] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0x7F);
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ return 2;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xED);
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xD2);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], SaraAm))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (0xED, shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xD2);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], AboveVowel))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], BotTailCons) &&
+ is_char_type (cluster[1], BelowVowel|BelowDiac))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 0x7F);
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[2]));
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xED);
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[3] = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (0xED, shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[3] = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_av (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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->type)
{
- case THAI_FONT_NONE:
- return pango_x_get_unknown_glyph (font_info->font);
- case THAI_FONT_XTIS:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, 0x100 * (wc - 0xe00 + 0x20) + 0x30);
- case THAI_FONT_TIS:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, wc - 0xe00 + 0xA0);
- case THAI_FONT_ISO10646:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, wc);
+ case THAI_FONT_NONE:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] = pango_x_get_unknown_glyph (font_info->font);
+ 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 = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 0x100 * (cluster[i] - 0xe00 + 0x20) + 0x30);
+ return num_chrs;
+
+ case THAI_FONT_TIS:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[i]));
+ return num_chrs;
+
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont, cluster[i]);
+ return num_chrs;
}
+
return 0; /* Quiet GCC */
}
static void
-add_cluster (ThaiFontInfo *font_info,
- PangoGlyphString *glyphs,
- int cluster_start,
- gunichar base,
- gunichar group1,
- gunichar group2)
+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)
{
- /* If we are rendering with an XTIS font, we try to find a precomposed
- * glyph for the cluster.
- */
- if (font_info->type == THAI_FONT_XTIS)
+ switch (TAC_compose_and_input_check_type_table[char_class (ucs2tis (cur_wc))]
+ [char_class (ucs2tis (nxt_wc))])
{
- PangoGlyph glyph;
- int xtis_index = 0x100 * (base - 0xe00 + 0x20) + 0x30;
- if (group1)
- xtis_index +=8 * group1_map[group1 - 0xe30];
- if (group2)
- xtis_index += group2_map[group2 - 0xe30];
-
- glyph = PANGO_X_MAKE_GLYPH (font_info->subfont, xtis_index);
+ case 'A':
+ case 'S':
+ case 'R':
+ case 'X':
+ return FALSE;
+
+ case 'C':
+ return TRUE;
+ }
+}
- if (pango_x_has_glyph (font_info->font, glyph))
+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)))
{
- add_glyph (font_info, glyphs, cluster_start, glyph, FALSE);
- return;
+ cluster[n_chars++] = current;
+ p = g_utf8_next_char (p);
}
+ else
+ break;
}
- /* If that failed, then we add compose the cluster out of three
- * individual glyphs
- */
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, base), FALSE);
- if (group1)
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, group1), TRUE);
- if (group2)
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, group2), TRUE);
+ *num_chrs = n_chars;
+ return p;
}
static void
@@ -303,54 +836,21 @@ thai_engine_shape (PangoFont *font,
{
ThaiFontInfo *font_info;
const char *p;
-
- gunichar base = 0;
- gunichar group1 = 0;
- gunichar group2 = 0;
- int cluster_start = 0;
+ 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)
{
- int group;
- gunichar wc;
-
- wc = g_utf8_get_char (p);
-
- if (wc >= 0xe30 && wc < 0xe50)
- group = groups[wc - 0xe30];
- else
- group = 0;
-
- switch (group)
- {
- case 0:
- if (base)
- {
- add_cluster (font_info, glyphs, cluster_start, base, group1, group2);
- group1 = 0;
- group2 = 0;
- }
- cluster_start = p - text;
- base = wc;
- break;
- case 1:
- group1 = wc;
- break;
- case 2:
- group2 = wc;
- break;
- }
-
- p = g_utf8_next_char (p);
+ 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);
}
-
- if (base)
- add_cluster (font_info, glyphs, cluster_start, base, group1, group2);
}
static PangoCoverage *
@@ -382,7 +882,7 @@ thai_engine_x_new ()
result = g_new (PangoEngineShape, 1);
result->engine.id = "ThaiScriptEngine";
- result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ 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;
diff --git a/modules/thai/thai.c b/modules/thai/thai.c
index 6547250a..d6b2c44c 100644
--- a/modules/thai/thai.c
+++ b/modules/thai/thai.c
@@ -1,7 +1,14 @@
-/* Pango
+/* pANGO
* thai.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
@@ -19,10 +26,63 @@
* Boston, MA 02111-1307, USA.
*/
+
#include <glib.h>
#include "pango.h"
#include "pangox.h"
+#define ucs2tis(wc) (unsigned int)((unsigned int)(wc) - 0x0E00 + 0xA0)
+#define tis2uni(c) ((gunichar)(c) - 0xA0 + 0x0E00)
+
+#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))
+
/* We handle the range U+0e01 to U+0e5b exactly
*/
static PangoEngineRange thai_ranges[] = {
@@ -83,6 +143,8 @@ typedef enum {
THAI_FONT_NONE,
THAI_FONT_XTIS,
THAI_FONT_TIS,
+ THAI_FONT_TIS_MAC,
+ THAI_FONT_TIS_WIN,
THAI_FONT_ISO10646
} ThaiFontType;
@@ -128,6 +190,160 @@ static const char group2_map[32] = {
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])
+
+/* Macintosh
+ */
+static const ThaiShapeTable Mac_shape_table = {
+ { 0xE7, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0xED, 0xEE },
+ { 0xE7, 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 },
+ { 0xE7, 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 }
+};
+
/* Returns a structure with information we will use to rendering given the
* #PangoFont. This is computed once per font and cached for later retrieval.
*/
@@ -135,24 +351,26 @@ static ThaiFontInfo *
get_font_info (PangoFont *font)
{
static const char *charsets[] = {
+ "tis620-2",
+ "tis620-1",
+ "tis620-0",
"xtis620.2529-1",
"xtis-0",
- "tis620.2533-0",
"tis620.2533-1",
- "tis620.2529-0",
"tis620.2529-1",
"iso8859-11",
"iso10646-1",
};
static const int charset_types[] = {
+ THAI_FONT_TIS_WIN,
+ THAI_FONT_TIS_MAC,
+ THAI_FONT_TIS,
THAI_FONT_XTIS,
THAI_FONT_XTIS,
THAI_FONT_TIS,
THAI_FONT_TIS,
THAI_FONT_TIS,
- THAI_FONT_TIS,
- THAI_FONT_TIS,
THAI_FONT_ISO10646
};
@@ -160,14 +378,15 @@ get_font_info (PangoFont *font)
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
*/
PangoXSubfont *subfont_ids;
- int *subfont_charsets;
- int n_subfonts, i;
+ gint *subfont_charsets;
+ gint n_subfonts, i;
font_info = g_new (ThaiFontInfo, 1);
font_info->font = font;
@@ -202,12 +421,12 @@ get_font_info (PangoFont *font)
static void
add_glyph (ThaiFontInfo *font_info,
PangoGlyphString *glyphs,
- int cluster_start,
+ gint cluster_start,
PangoGlyph glyph,
gboolean combining)
{
PangoRectangle ink_rect, logical_rect;
- int index = glyphs->num_glyphs;
+ gint index = glyphs->num_glyphs;
pango_glyph_string_set_size (glyphs, index + 1);
@@ -221,10 +440,25 @@ add_glyph (ThaiFontInfo *font_info,
if (combining)
{
- glyphs->glyphs[index].geometry.width =
- MAX (logical_rect.width, glyphs->glyphs[index - 1].geometry.width);
- glyphs->glyphs[index - 1].geometry.width = 0;
- glyphs->glyphs[index].geometry.x_offset = 0;
+ if (font_info->type == THAI_FONT_TIS ||
+ font_info->type == THAI_FONT_TIS_MAC ||
+ font_info->type == THAI_FONT_TIS_WIN)
+ {
+ glyphs->glyphs[index].geometry.width =
+ logical_rect.width + glyphs->glyphs[index - 1].geometry.width;
+ if (logical_rect.width > 0)
+ glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index - 1].geometry.width;
+ else
+ glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index].geometry.width;
+ glyphs->glyphs[index - 1].geometry.width = 0;
+ }
+ else
+ {
+ glyphs->glyphs[index].geometry.width =
+ MAX (logical_rect.width, glyphs->glyphs[index - 1].geometry.width);
+ glyphs->glyphs[index - 1].geometry.width = 0;
+ glyphs->glyphs[index].geometry.x_offset = 0;
+ }
}
else
{
@@ -235,63 +469,362 @@ add_glyph (ThaiFontInfo *font_info,
glyphs->glyphs[index].geometry.y_offset = 0;
}
-/* Return the glyph code within the font for the given Unicode Thai
- * code pointer
- */
-static int
-get_glyph (ThaiFontInfo *font_info, gunichar wc)
+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))
+ {
+ glyph_lists[0] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0x7F);
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ return 2;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xED);
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xD2);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], UpTailCons) &&
+ is_char_type (cluster[1], SaraAm))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (0xED, shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xD2);
+ return 3;
+ }
+ else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
+ is_char_type (cluster[1], AboveVowel))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else if (is_char_type (cluster[0], BotTailCons) &&
+ is_char_type (cluster[1], BelowVowel|BelowDiac))
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ return 2;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 0x7F);
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[2]));
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0xED);
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[3] = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (0xED, shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[3] = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftleft_av (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ tailcutcons (ucs2tis (cluster[0]), shaping_table));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
+ glyph_lists[2] = PANGO_X_MAKE_GLYPH (font_info->subfont,
+ shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
+ return 3;
+ }
+ else
+ {
+ glyph_lists[0] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[0]));
+ glyph_lists[1] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[1]));
+ glyph_lists[2] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, 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->type)
{
- case THAI_FONT_NONE:
- return pango_x_get_unknown_glyph (font_info->font);
- case THAI_FONT_XTIS:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, 0x100 * (wc - 0xe00 + 0x20) + 0x30);
- case THAI_FONT_TIS:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, wc - 0xe00 + 0xA0);
- case THAI_FONT_ISO10646:
- return PANGO_X_MAKE_GLYPH (font_info->subfont, wc);
+ case THAI_FONT_NONE:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] = pango_x_get_unknown_glyph (font_info->font);
+ 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 = PANGO_X_MAKE_GLYPH (font_info->subfont, 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] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont,
+ 0x100 * (cluster[i] - 0xe00 + 0x20) + 0x30);
+ return num_chrs;
+
+ case THAI_FONT_TIS:
+ for (i=0; i < num_chrs; i++)
+ glyph_lists[i] =
+ PANGO_X_MAKE_GLYPH (font_info->subfont, ucs2tis (cluster[i]));
+ return num_chrs;
+
+ 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] = PANGO_X_MAKE_GLYPH (font_info->subfont, cluster[i]);
+ return num_chrs;
}
+
return 0; /* Quiet GCC */
}
static void
-add_cluster (ThaiFontInfo *font_info,
- PangoGlyphString *glyphs,
- int cluster_start,
- gunichar base,
- gunichar group1,
- gunichar group2)
+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)
{
- /* If we are rendering with an XTIS font, we try to find a precomposed
- * glyph for the cluster.
- */
- if (font_info->type == THAI_FONT_XTIS)
+ switch (TAC_compose_and_input_check_type_table[char_class (ucs2tis (cur_wc))]
+ [char_class (ucs2tis (nxt_wc))])
{
- PangoGlyph glyph;
- int xtis_index = 0x100 * (base - 0xe00 + 0x20) + 0x30;
- if (group1)
- xtis_index +=8 * group1_map[group1 - 0xe30];
- if (group2)
- xtis_index += group2_map[group2 - 0xe30];
-
- glyph = PANGO_X_MAKE_GLYPH (font_info->subfont, xtis_index);
+ case 'A':
+ case 'S':
+ case 'R':
+ case 'X':
+ return FALSE;
+
+ case 'C':
+ return TRUE;
+ }
+}
- if (pango_x_has_glyph (font_info->font, glyph))
+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)))
{
- add_glyph (font_info, glyphs, cluster_start, glyph, FALSE);
- return;
+ cluster[n_chars++] = current;
+ p = g_utf8_next_char (p);
}
+ else
+ break;
}
- /* If that failed, then we add compose the cluster out of three
- * individual glyphs
- */
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, base), FALSE);
- if (group1)
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, group1), TRUE);
- if (group2)
- add_glyph (font_info, glyphs, cluster_start, get_glyph (font_info, group2), TRUE);
+ *num_chrs = n_chars;
+ return p;
}
static void
@@ -303,54 +836,21 @@ thai_engine_shape (PangoFont *font,
{
ThaiFontInfo *font_info;
const char *p;
-
- gunichar base = 0;
- gunichar group1 = 0;
- gunichar group2 = 0;
- int cluster_start = 0;
+ 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)
{
- int group;
- gunichar wc;
-
- wc = g_utf8_get_char (p);
-
- if (wc >= 0xe30 && wc < 0xe50)
- group = groups[wc - 0xe30];
- else
- group = 0;
-
- switch (group)
- {
- case 0:
- if (base)
- {
- add_cluster (font_info, glyphs, cluster_start, base, group1, group2);
- group1 = 0;
- group2 = 0;
- }
- cluster_start = p - text;
- base = wc;
- break;
- case 1:
- group1 = wc;
- break;
- case 2:
- group2 = wc;
- break;
- }
-
- p = g_utf8_next_char (p);
+ 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);
}
-
- if (base)
- add_cluster (font_info, glyphs, cluster_start, base, group1, group2);
}
static PangoCoverage *
@@ -382,7 +882,7 @@ thai_engine_x_new ()
result = g_new (PangoEngineShape, 1);
result->engine.id = "ThaiScriptEngine";
- result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ 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;