4 * Copyright (C) 1999, 2007 Red Hat Software
5 * Copyright (C) 2002 NECTEC
6 * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
8 * Owen Taylor <otaylor@redhat.com>
9 * Theppitak Karoonboonyanan <thep@links.nectec.or.th>
10 * Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
11 * Behdad Esfahbod <behdad@behdad.org>
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public
24 * License along with this library; if not, write to the
25 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 * Boston, MA 02111-1307, USA.
35 #include "pango-engine.h"
36 #include "pangofc-font.h"
38 #include "thai-shaper.h"
40 /* No extra fields needed */
41 typedef PangoEngineShape ThaiEngineFc;
42 typedef PangoEngineShapeClass ThaiEngineFcClass ;
44 #define SCRIPT_ENGINE_NAME "ThaiScriptEngineFc"
45 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
47 /* We handle the range U+0e01 to U+0e5b exactly
49 static PangoEngineScriptInfo thai_scripts[] = {
50 { PANGO_SCRIPT_THAI, "*" },
51 { PANGO_SCRIPT_LAO, "*" },
54 static PangoEngineInfo script_engines[] = {
57 PANGO_ENGINE_TYPE_SHAPE,
59 thai_scripts, G_N_ELEMENTS(thai_scripts)
63 /* TIS-to-Unicode glyph maps for characters 0x80-0xff
65 static const int tis620_0[128] = {
66 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
67 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
68 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
69 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
70 0x0020, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
71 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
72 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
73 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
74 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
75 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
76 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
77 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
78 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
79 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
80 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
81 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0, 0, 0, 0
84 static const int tis620_1[128] = {
85 0xf89e, 0, 0, 0xf88c, 0xf88f, 0xf892, 0xf895, 0xf898,
86 0xf88b, 0xf88e, 0xf891, 0xf894, 0xf897, 0, 0, 0xf899,
87 0xf89a, 0, 0xf884, 0xf889, 0xf885, 0xf886, 0xf887, 0xf888,
88 0xf88a, 0xf88d, 0xf890, 0xf893, 0xf896, 0, 0, 0,
89 /**/ 0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
90 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
91 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
92 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
93 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
94 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
95 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
96 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
97 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
98 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0, 0x0e4f,
99 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
100 0x0e58, 0x0e59, 0, 0, 0xf89b, 0xf89c, 0xf89d, 0
103 static const int tis620_2[128] = {
104 0xf700, 0xf701, 0xf702, 0xf703, 0xf704, 0x2026, 0xf705, 0xf706,
105 0xf707, 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e,
106 0xf70f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
107 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717,
108 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
109 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
110 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
111 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
112 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
113 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
114 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
115 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
116 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
117 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
118 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
119 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf718, 0xf719, 0xf71a, 0
122 static const int lao_0[128] = {
123 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
124 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
125 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
126 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
127 0x0020, 0x0e81, 0x0e82, 0, 0x0e84, 0, 0, 0x0e87,
128 0x0e88, 0, 0x0e8a, 0, 0, 0x0e8d, 0, 0,
129 0, 0, 0, 0, 0x0e94, 0x0e95, 0x0e96, 0x0e97,
130 /**/ 0, 0x0e99, 0x0e9a, 0x0e9b, 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f,
131 /**/ 0, 0x0ea1, 0x0ea2, 0x0ea3, 0, 0x0ea5, 0, 0x0ea7,
132 /**/ 0, 0, 0x0eaa, 0x0eab, 0, 0x0ead, 0x0eae, 0x0eaf,
133 0x0eb0, 0x0eb1, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7,
134 0x0eb8, 0x0eb9, 0, 0x0ebb, 0x0ebc, 0x0ebd, 0, 0,
135 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0, 0x0ec6, 0,
136 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0, 0,
137 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7,
138 0x0ed8, 0x0ed9, 0, 0, 0x0edc, 0x0edd, 0, 0
141 contain_glyphs(PangoFont *font, const int glyph_map[128])
143 PangoFcFont *fc_font = (PangoFcFont *)font;
146 for (c = 0; c < 0x80; c++)
150 if (!pango_fc_font_has_char (fc_font, glyph_map[c]))
157 /* Returns a structure with information we will use to rendering given the
158 * #PangoFont. This is computed once per font and cached for later retrieval.
160 static ThaiFontInfo *
161 thai_get_font_info (PangoFont *font,
162 const PangoOTRuleset *ruleset)
164 ThaiFontInfo *font_info;
165 static GQuark info_id = 0;
167 if (G_UNLIKELY (!info_id))
168 info_id = g_quark_from_string ("thai-font-info");
170 font_info = g_object_get_qdata (G_OBJECT (font), info_id);
172 if (G_UNLIKELY (!font_info))
174 /* No cached information not found, so we need to compute it
177 font_info = g_new (ThaiFontInfo, 1);
178 font_info->font = font;
180 /* detect font set by determining availibility of OT ruleset & glyphs */
181 if (pango_ot_ruleset_get_feature_count (ruleset, NULL, NULL))
182 font_info->font_set = THAI_FONT_TIS;
183 else if (contain_glyphs(font, tis620_2))
184 font_info->font_set = THAI_FONT_TIS_WIN;
185 else if (contain_glyphs(font, tis620_1))
186 font_info->font_set = THAI_FONT_TIS_MAC;
188 font_info->font_set = THAI_FONT_TIS;
190 g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free);
197 get_glyph_index_tis (ThaiFontInfo *font_info, guchar c)
202 switch (font_info->font_set) {
204 case THAI_FONT_NONE: return 0;
205 case THAI_FONT_TIS: return tis620_0[c & 0x7f];
206 case THAI_FONT_TIS_MAC: return tis620_1[c & 0x7f];
207 case THAI_FONT_TIS_WIN: return tis620_2[c & 0x7f];
212 thai_get_glyph_tis (ThaiFontInfo *font_info, guchar c)
214 return thai_get_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
218 thai_make_glyph_tis (ThaiFontInfo *font_info, guchar c)
220 return thai_make_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
224 thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
226 return pango_fc_font_get_glyph ((PangoFcFont *)font_info->font, uc);
230 thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
233 PangoFcFont *fc_font = (PangoFcFont *)font_info->font;
235 result = pango_fc_font_get_glyph (fc_font, uc);
239 return PANGO_GET_UNKNOWN_GLYPH ( uc);
242 static const PangoOTFeatureMap gsub_features[] =
244 {"ccmp", PANGO_OT_ALL_GLYPHS},
245 {"locl", PANGO_OT_ALL_GLYPHS},
246 {"liga", PANGO_OT_ALL_GLYPHS},
249 static const PangoOTFeatureMap gpos_features[] =
251 {"kern", PANGO_OT_ALL_GLYPHS},
252 {"mark", PANGO_OT_ALL_GLYPHS},
253 {"mkmk", PANGO_OT_ALL_GLYPHS}
257 thai_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
261 const PangoAnalysis *analysis,
262 PangoGlyphString *glyphs)
264 PangoFcFont *fc_font;
266 PangoOTRulesetDescription desc;
267 const PangoOTRuleset *ruleset;
268 PangoOTBuffer *buffer;
270 ThaiFontInfo *font_info;
272 g_return_if_fail (font != NULL);
273 g_return_if_fail (text != NULL);
274 g_return_if_fail (length >= 0);
275 g_return_if_fail (analysis != NULL);
277 fc_font = PANGO_FC_FONT (font);
278 face = pango_fc_font_lock_face (fc_font);
282 desc.script = analysis->script;
283 desc.language = analysis->language;
285 desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
286 desc.static_gsub_features = gsub_features;
287 desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
288 desc.static_gpos_features = gpos_features;
290 /* TODO populate other_features from analysis->extra_attrs */
291 desc.n_other_features = 0;
292 desc.other_features = NULL;
294 ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
296 font_info = thai_get_font_info (font, ruleset);
298 thai_set_glyphs (font_info, text, length, analysis->script, glyphs);
300 buffer = pango_ot_buffer_new (PANGO_FC_FONT (font));
301 pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
303 for (i = 0; i < glyphs->num_glyphs; i++)
304 pango_ot_buffer_add_glyph (buffer,
305 glyphs->glyphs[i].glyph,
307 glyphs->log_clusters[i]);
309 pango_ot_ruleset_substitute (ruleset, buffer);
310 pango_ot_ruleset_position (ruleset, buffer);
312 pango_ot_buffer_output (buffer, glyphs);
313 pango_ot_buffer_destroy (buffer);
317 thai_make_unknown_glyph (ThaiFontInfo *font_info G_GNUC_UNUSED, gunichar uc)
319 return PANGO_GET_UNKNOWN_GLYPH (uc);
323 thai_engine_fc_class_init (PangoEngineShapeClass *class)
325 class->script_shape = thai_engine_shape;
328 PANGO_ENGINE_SHAPE_DEFINE_TYPE (ThaiEngineFc, thai_engine_fc,
329 thai_engine_fc_class_init, NULL)
332 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
334 thai_engine_fc_register_type (module);
338 PANGO_MODULE_ENTRY(exit) (void)
343 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
346 *engines = script_engines;
347 *n_engines = G_N_ELEMENTS (script_engines);
351 PANGO_MODULE_ENTRY(create) (const char *id)
353 if (!strcmp (id, SCRIPT_ENGINE_NAME))
354 return g_object_new (thai_engine_fc_type, NULL);