4 * Copyright (C) 1999 Red Hat Software
5 * Author: Owen Taylor <otaylor@redhat.com>
7 * Copyright (C) 2005 Theppitak Karoonboonyanan
8 * Copyright (C) 2002 Software and Language Engineering Laboratory, NECTEC
9 * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th>
11 * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
12 * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Library General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with this library; if not, write to the
26 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 * Boston, MA 02111-1307, USA.
33 #include "pango-engine.h"
34 #include "thai-charprop.h"
35 #include "thai-shaper.h"
37 #define MAX_CLUSTER_CHRS 256
38 #define MAX_GLYPHS 256
42 guchar Start_TONE_AD, Start_AV, Start_BV_BD, Start_TailCutCons;
44 guchar ShiftDown_TONE_AD[8];
45 guchar ShiftDownLeft_TONE_AD[8];
46 guchar ShiftLeft_TONE_AD[8];
47 guchar ShiftLeft_AV[7];
48 guchar ShiftDown_BV_BD[3];
49 guchar TailCutCons[4];
51 guchar AmComp[2]; /* Sara Am components */
54 #define shiftdown_tone_ad(c,tbl) \
55 ((tbl)->ShiftDown_TONE_AD[(c)-(tbl)->Start_TONE_AD])
56 #define shiftdownleft_tone_ad(c,tbl) \
57 ((tbl)->ShiftDownLeft_TONE_AD[(c)-(tbl)->Start_TONE_AD])
58 #define shiftleft_tone_ad(c,tbl) \
59 ((tbl)->ShiftLeft_TONE_AD[(c)-(tbl)->Start_TONE_AD])
60 #define shiftleft_av(c,tbl) \
61 ((tbl)->ShiftLeft_AV[(c)-(tbl)->Start_AV])
62 #define shiftdown_bv_bd(c,tbl) \
63 ((tbl)->ShiftDown_BV_BD[(c)-(tbl)->Start_BV_BD])
64 #define tailcutcons(c,tbl) \
65 ((tbl)->TailCutCons[(c)-(tbl)->Start_TailCutCons])
67 /* No adjusted vowel/tonemark glyphs (tis620-0)
69 static const ThaiShapeTable tis620_0_shape_table = {
70 0xE7, 0xD1, 0xD8, 0xAD,
71 { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
72 { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
73 { 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE },
74 { 0xD1, 0x00, 0x00, 0xD4, 0xD5, 0xD6, 0xD7 },
76 { 0xAD, 0x00, 0x00, 0xB0 },
82 static const ThaiShapeTable Mac_shape_table = {
83 0xE7, 0xD1, 0xD8, 0xAD,
84 { 0xE7, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0xED, 0xEE },
85 { 0x93, 0x83, 0x84, 0x85, 0x86, 0x87, 0x8F, 0xEE },
86 { 0x93, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x8F, 0xEE },
87 { 0x92, 0x00, 0x00, 0x94, 0x95, 0x96, 0x97 },
89 { 0x90, 0x00, 0x00, 0x80 },
95 static const ThaiShapeTable Win_shape_table = {
96 0xE7, 0xD1, 0xD8, 0xAD,
97 { 0xE7, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0xED, 0xEE },
98 { 0x9A, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x99, 0xEE },
99 { 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x99, 0xEE },
100 { 0x98, 0x00, 0x00, 0x81, 0x82, 0x83, 0x84 },
101 { 0xFC, 0xFD, 0xFE },
102 { 0x90, 0x00, 0x00, 0x80 },
106 static const ThaiShapeTable Lao_shape_table = {
107 0x67, 0x51, 0x58, 0x2D,
108 { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
109 { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
110 { 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E },
111 { 0x51, 0x00, 0x00, 0x54, 0x55, 0x56, 0x57 },
112 { 0x58, 0x59, 0x00 },
113 { 0x2D, 0x00, 0x00, 0x30 },
118 add_glyph (ThaiFontInfo *font_info,
119 PangoGlyphString *glyphs,
124 PangoRectangle ink_rect, logical_rect;
125 gint index = glyphs->num_glyphs;
127 pango_glyph_string_set_size (glyphs, index + 1);
129 glyphs->glyphs[index].glyph = glyph;
130 glyphs->glyphs[index].attr.is_cluster_start = combining ? 0 : 1;
132 glyphs->log_clusters[index] = cluster_start;
134 pango_font_get_glyph_extents (font_info->font,
135 glyphs->glyphs[index].glyph, &ink_rect, &logical_rect);
137 if (combining || logical_rect.width > 0)
139 glyphs->glyphs[index].geometry.x_offset = 0;
140 glyphs->glyphs[index].geometry.width = logical_rect.width;
144 glyphs->glyphs[index].geometry.x_offset = ink_rect.width;
145 glyphs->glyphs[index].geometry.width = ink_rect.width;
147 glyphs->glyphs[index].geometry.y_offset = 0;
151 get_null_base_glyph (ThaiFontInfo *font_info)
153 return thai_get_glyph_uni (font_info, 0x25cc);
157 get_adjusted_glyphs_list (ThaiFontInfo *font_info,
160 PangoGlyph *glyph_lists,
161 const ThaiShapeTable *shaping_table)
166 if (is_char_type (cluster[0],
167 BelowVowel|BelowDiac|AboveVowel|AboveDiac|Tone|SaraAm))
170 glyph_lists[0] = get_null_base_glyph (font_info);
171 n = glyph_lists[0] ? 1 : 0;
173 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
179 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
185 if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
186 is_char_type (cluster[1], SaraAm))
189 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
190 glyph_lists[1] = thai_make_glyph_tis (font_info, shaping_table->AmComp[0]);
191 glyph_lists[2] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
194 else if (is_char_type (cluster[0], UpTailCons) &&
195 is_char_type (cluster[1], SaraAm))
198 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
199 glyph_lists[1] = thai_make_glyph_tis (font_info,
200 shiftleft_tone_ad (shaping_table->AmComp[0], shaping_table));
201 glyph_lists[2] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
204 else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
205 is_char_type (cluster[1], AboveVowel))
208 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
210 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
213 else if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
214 is_char_type (cluster[1], AboveDiac|Tone))
217 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
218 glyph_lists[1] = thai_make_glyph_tis (font_info,
219 shiftdown_tone_ad (ucs2tis (cluster[1]), shaping_table));
222 else if (is_char_type (cluster[0], UpTailCons) &&
223 is_char_type (cluster[1], AboveVowel))
226 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
227 glyph_lists[1] = thai_make_glyph_tis (font_info,
228 shiftleft_av (ucs2tis (cluster[1]), shaping_table));
231 else if (is_char_type (cluster[0], UpTailCons) &&
232 is_char_type (cluster[1], AboveDiac|Tone))
235 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
236 glyph_lists[1] = thai_make_glyph_tis (font_info,
237 shiftdownleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
240 else if (is_char_type (cluster[0], NoTailCons|UpTailCons) &&
241 is_char_type (cluster[1], BelowVowel|BelowDiac))
244 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
246 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
249 else if (is_char_type (cluster[0], BotTailCons) &&
250 is_char_type (cluster[1], BelowVowel|BelowDiac))
253 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
255 thai_make_glyph_tis (font_info,
256 shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
259 else if (is_char_type (cluster[0], SpltTailCons) &&
260 is_char_type (cluster[1], BelowVowel|BelowDiac))
262 glyph_lists[0] = thai_make_glyph_tis (font_info,
263 tailcutcons (ucs2tis (cluster[0]), shaping_table));
265 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
271 glyph_lists[0] = get_null_base_glyph (font_info);
272 n = glyph_lists[0] ? 1 : 0;
274 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
276 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
282 if (is_char_type (cluster[0], NoTailCons|BotTailCons|SpltTailCons) &&
283 is_char_type (cluster[1], Tone) &&
284 is_char_type (cluster[2], SaraAm))
287 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
288 glyph_lists[1] = thai_make_glyph_tis (font_info, shaping_table->AmComp[0]);
290 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
291 glyph_lists[3] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
294 else if (is_char_type (cluster[0], UpTailCons) &&
295 is_char_type (cluster[1], Tone) &&
296 is_char_type (cluster[2], SaraAm))
299 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
300 glyph_lists[1] = thai_make_glyph_tis (font_info,
301 shiftleft_tone_ad (shaping_table->AmComp[0], shaping_table));
302 glyph_lists[2] = thai_make_glyph_tis (font_info,
303 shiftleft_tone_ad (ucs2tis (cluster[1]), shaping_table));
304 glyph_lists[3] = thai_make_glyph_tis (font_info, shaping_table->AmComp[1]);
307 else if (is_char_type (cluster[0], UpTailCons) &&
308 is_char_type (cluster[1], AboveVowel) &&
309 is_char_type (cluster[2], AboveDiac|Tone))
312 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
313 glyph_lists[1] = thai_make_glyph_tis (font_info,
314 shiftleft_av (ucs2tis (cluster[1]), shaping_table));
315 glyph_lists[2] = thai_make_glyph_tis (font_info,
316 shiftleft_tone_ad (ucs2tis (cluster[2]), shaping_table));
319 else if (is_char_type (cluster[0], UpTailCons) &&
320 is_char_type (cluster[1], BelowVowel) &&
321 is_char_type (cluster[2], AboveDiac|Tone))
324 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
326 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
327 glyph_lists[2] = thai_make_glyph_tis (font_info,
328 shiftdownleft_tone_ad (ucs2tis (cluster[2]), shaping_table));
331 else if (is_char_type (cluster[0], NoTailCons) &&
332 is_char_type (cluster[1], BelowVowel) &&
333 is_char_type (cluster[2], AboveDiac|Tone))
336 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
338 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
340 thai_make_glyph_tis (font_info,
341 shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
344 else if (is_char_type (cluster[0], SpltTailCons) &&
345 is_char_type (cluster[1], BelowVowel) &&
346 is_char_type (cluster[2], AboveDiac|Tone))
348 glyph_lists[0] = thai_make_glyph_tis (font_info,
349 tailcutcons (ucs2tis (cluster[0]), shaping_table));
351 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
352 glyph_lists[2] = thai_make_glyph_tis (font_info,
353 shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
356 else if (is_char_type (cluster[0], BotTailCons) &&
357 is_char_type (cluster[1], BelowVowel) &&
358 is_char_type (cluster[2], AboveDiac|Tone))
361 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
362 glyph_lists[1] = thai_make_glyph_tis (font_info,
363 shiftdown_bv_bd (ucs2tis (cluster[1]), shaping_table));
364 glyph_lists[2] = thai_make_glyph_tis (font_info,
365 shiftdown_tone_ad (ucs2tis (cluster[2]), shaping_table));
371 thai_make_glyph_tis (font_info, ucs2tis (cluster[0]));
373 thai_make_glyph_tis (font_info, ucs2tis (cluster[1]));
375 thai_make_glyph_tis (font_info, ucs2tis (cluster[2]));
380 default: /* e.g. Lao cluster with below cons + upper/lower vowel + tone */
383 for (i = 0; i < num_chrs; i++)
384 glyph_lists[i] = thai_make_glyph_tis (font_info, ucs2tis (cluster[i]));
393 get_glyphs_list (ThaiFontInfo *font_info,
397 PangoGlyph *glyph_lists)
401 switch ((int) script)
403 case PANGO_SCRIPT_THAI:
404 switch (font_info->font_set)
408 for (i=0; i < num_chrs; i++)
409 glyph_lists[i] = thai_make_unknown_glyph (font_info, cluster[i]);
413 /* TIS620-0 + Wtt2.0 Extension
415 return get_adjusted_glyphs_list (font_info, cluster,
416 num_chrs, glyph_lists, &tis620_0_shape_table);
418 case THAI_FONT_TIS_MAC:
419 /* MacIntosh Extension
421 return get_adjusted_glyphs_list (font_info, cluster,
422 num_chrs, glyph_lists, &Mac_shape_table);
424 case THAI_FONT_TIS_WIN:
425 /* Microsoft Extension
427 return get_adjusted_glyphs_list (font_info, cluster,
428 num_chrs, glyph_lists, &Win_shape_table);
432 case PANGO_SCRIPT_LAO:
433 return get_adjusted_glyphs_list (font_info, cluster,
434 num_chrs, glyph_lists, &Lao_shape_table);
437 for (i=0; i < num_chrs; i++)
438 glyph_lists[i] = thai_make_unknown_glyph (font_info, cluster[i]);
442 return 0; /* Quiet GCC */
446 add_cluster (ThaiFontInfo *font_info,
448 PangoGlyphString *glyphs,
453 PangoGlyph glyphs_list[MAX_GLYPHS];
457 if (isthai (cluster[0]))
459 num_glyphs = get_glyphs_list(font_info, script, cluster, num_chrs, glyphs_list);
460 for (i=0; i<num_glyphs; i++)
461 add_glyph (font_info, glyphs, cluster_start, glyphs_list[i],
462 i == 0 ? FALSE : TRUE);
464 else if (islao (cluster[0]))
466 num_glyphs = get_glyphs_list(font_info, script, cluster, num_chrs, glyphs_list);
467 for (i=0; i<num_glyphs; i++)
468 add_glyph (font_info, glyphs, cluster_start, glyphs_list[i],
469 i == 0 ? FALSE : TRUE);
473 g_assert (num_chrs == 1);
474 add_glyph (font_info, glyphs, cluster_start,
475 thai_make_glyph_uni (font_info, cluster[0]),
481 is_wtt_composible (gunichar cur_wc, gunichar nxt_wc)
483 switch (TAC_compose_input(cur_wc, nxt_wc))
495 g_assert_not_reached ();
500 get_next_cluster(const char *text,
505 PangoScript cluster_script = PANGO_SCRIPT_INVALID_CODE, cur_script;
510 for (p = text; p < text + length; p = g_utf8_next_char (p))
512 current = g_utf8_get_char (p);
513 cur_script = pango_script_for_unichar (current);
514 if (cluster_script == PANGO_SCRIPT_INVALID_CODE)
515 cluster_script = cur_script;
516 if (cur_script != cluster_script ||
518 !is_wtt_composible (cluster[n_chars - 1], current)))
520 cluster[n_chars++] = current;
528 thai_set_glyphs (ThaiFontInfo *font_info,
532 PangoGlyphString *glyphs)
536 const char *log_cluster;
537 gunichar cluster[MAX_CLUSTER_CHRS];
539 pango_glyph_string_set_size (glyphs, 0);
542 while (p < text + length)
545 p = get_next_cluster (p, text + length - p, cluster, &n_chars);
546 add_cluster (font_info, script, glyphs, log_cluster - text, cluster, n_chars);