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.
36 #include "pango-engine.h"
37 #include "pangofc-font.h"
39 #include "thai-shaper.h"
41 /* No extra fields needed */
42 typedef PangoEngineShape ThaiEngineFc;
43 typedef PangoEngineShapeClass ThaiEngineFcClass ;
45 #define SCRIPT_ENGINE_NAME "ThaiScriptEngineFc"
46 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
48 /* We handle the range U+0e01 to U+0e5b exactly
50 static PangoEngineScriptInfo thai_scripts[] = {
51 { PANGO_SCRIPT_THAI, "*" },
52 { PANGO_SCRIPT_LAO, "*" },
55 static PangoEngineInfo script_engines[] = {
58 PANGO_ENGINE_TYPE_SHAPE,
60 thai_scripts, G_N_ELEMENTS(thai_scripts)
64 /* TIS-to-Unicode glyph maps for characters 0x80-0xff
66 static const int tis620_0[128] = {
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 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
71 0x0020, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
72 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
73 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
74 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
75 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
76 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
77 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
78 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
79 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
80 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
81 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
82 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0, 0, 0, 0
85 static const int tis620_1[128] = {
86 0xf89e, 0, 0, 0xf88c, 0xf88f, 0xf892, 0xf895, 0xf898,
87 0xf88b, 0xf88e, 0xf891, 0xf894, 0xf897, 0, 0, 0xf899,
88 0xf89a, 0, 0xf884, 0xf889, 0xf885, 0xf886, 0xf887, 0xf888,
89 0xf88a, 0xf88d, 0xf890, 0xf893, 0xf896, 0, 0, 0,
90 /**/ 0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
91 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
92 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
93 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
94 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
95 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
96 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
97 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
98 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
99 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0, 0x0e4f,
100 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
101 0x0e58, 0x0e59, 0, 0, 0xf89b, 0xf89c, 0xf89d, 0
104 static const int tis620_2[128] = {
105 0xf700, 0xf701, 0xf702, 0xf703, 0xf704, 0x2026, 0xf705, 0xf706,
106 0xf707, 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e,
107 0xf70f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
108 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717,
109 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
110 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
111 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
112 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
113 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
114 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
115 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
116 0x0e38, 0x0e39, 0x0e3a, 0, 0, 0, 0, 0x0e3f,
117 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
118 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
119 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
120 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf718, 0xf719, 0xf71a, 0
123 static const int lao_0[128] = {
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 /**/ 0, 0, 0, 0, 0, 0, 0, 0,
128 0x0020, 0x0e81, 0x0e82, 0, 0x0e84, 0, 0, 0x0e87,
129 0x0e88, 0, 0x0e8a, 0, 0, 0x0e8d, 0, 0,
130 0, 0, 0, 0, 0x0e94, 0x0e95, 0x0e96, 0x0e97,
131 /**/ 0, 0x0e99, 0x0e9a, 0x0e9b, 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f,
132 /**/ 0, 0x0ea1, 0x0ea2, 0x0ea3, 0, 0x0ea5, 0, 0x0ea7,
133 /**/ 0, 0, 0x0eaa, 0x0eab, 0, 0x0ead, 0x0eae, 0x0eaf,
134 0x0eb0, 0x0eb1, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7,
135 0x0eb8, 0x0eb9, 0, 0x0ebb, 0x0ebc, 0x0ebd, 0, 0,
136 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0, 0x0ec6, 0,
137 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0, 0,
138 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7,
139 0x0ed8, 0x0ed9, 0, 0, 0x0edc, 0x0edd, 0, 0
142 contain_glyphs(PangoFont *font, const int glyph_map[128])
144 PangoFcFont *fc_font = (PangoFcFont *)font;
147 for (c = 0; c < 0x80; c++)
151 if (!pango_fc_font_has_char (fc_font, glyph_map[c]))
158 /* Returns a structure with information we will use to rendering given the
159 * #PangoFont. This is computed once per font and cached for later retrieval.
161 static ThaiFontInfo *
162 thai_get_font_info (PangoFont *font,
163 const PangoOTRuleset *ruleset)
165 ThaiFontInfo *font_info;
166 static GQuark info_id = 0;
168 if (G_UNLIKELY (!info_id))
169 info_id = g_quark_from_string ("thai-font-info");
171 font_info = g_object_get_qdata (G_OBJECT (font), info_id);
173 if (G_UNLIKELY (!font_info))
175 /* No cached information not found, so we need to compute it
178 font_info = g_new (ThaiFontInfo, 1);
179 font_info->font = font;
181 /* detect font set by determining availibility of OT ruleset & glyphs */
182 if (pango_ot_ruleset_get_feature_count (ruleset, NULL, NULL))
183 font_info->font_set = THAI_FONT_TIS;
184 else if (contain_glyphs(font, tis620_2))
185 font_info->font_set = THAI_FONT_TIS_WIN;
186 else if (contain_glyphs(font, tis620_1))
187 font_info->font_set = THAI_FONT_TIS_MAC;
189 font_info->font_set = THAI_FONT_TIS;
191 g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free);
198 get_glyph_index_tis (ThaiFontInfo *font_info, guchar c)
203 switch (font_info->font_set) {
205 case THAI_FONT_NONE: return 0;
206 case THAI_FONT_TIS: return tis620_0[c & 0x7f];
207 case THAI_FONT_TIS_MAC: return tis620_1[c & 0x7f];
208 case THAI_FONT_TIS_WIN: return tis620_2[c & 0x7f];
213 thai_get_glyph_tis (ThaiFontInfo *font_info, guchar c)
215 return thai_get_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
219 thai_make_glyph_tis (ThaiFontInfo *font_info, guchar c)
221 return thai_make_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
225 thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
227 return pango_fc_font_get_glyph ((PangoFcFont *)font_info->font, uc);
231 thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
234 PangoFcFont *fc_font = (PangoFcFont *)font_info->font;
236 result = pango_fc_font_get_glyph (fc_font, uc);
240 return PANGO_GET_UNKNOWN_GLYPH ( uc);
243 static const PangoOTFeatureMap gsub_features[] =
245 {"ccmp", PANGO_OT_ALL_GLYPHS},
246 {"locl", PANGO_OT_ALL_GLYPHS},
247 {"liga", PANGO_OT_ALL_GLYPHS},
250 static const PangoOTFeatureMap gpos_features[] =
252 {"kern", PANGO_OT_ALL_GLYPHS},
253 {"mark", PANGO_OT_ALL_GLYPHS},
254 {"mkmk", PANGO_OT_ALL_GLYPHS}
258 thai_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
262 const PangoAnalysis *analysis,
263 PangoGlyphString *glyphs)
265 PangoFcFont *fc_font;
267 PangoOTRulesetDescription desc;
268 const PangoOTRuleset *ruleset;
269 PangoOTBuffer *buffer;
271 ThaiFontInfo *font_info;
273 g_return_if_fail (font != NULL);
274 g_return_if_fail (text != NULL);
275 g_return_if_fail (length >= 0);
276 g_return_if_fail (analysis != NULL);
278 fc_font = PANGO_FC_FONT (font);
279 face = pango_fc_font_lock_face (fc_font);
283 desc.script = analysis->script;
284 desc.language = analysis->language;
286 desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
287 desc.static_gsub_features = gsub_features;
288 desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
289 desc.static_gpos_features = gpos_features;
291 /* TODO populate other_features from analysis->extra_attrs */
292 desc.n_other_features = 0;
293 desc.other_features = NULL;
295 ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
297 font_info = thai_get_font_info (font, ruleset);
299 thai_set_glyphs (font_info, text, length, analysis->script, glyphs);
301 buffer = pango_ot_buffer_new (PANGO_FC_FONT (font));
302 pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
304 for (i = 0; i < glyphs->num_glyphs; i++)
305 pango_ot_buffer_add_glyph (buffer,
306 glyphs->glyphs[i].glyph,
308 glyphs->log_clusters[i]);
310 pango_ot_ruleset_substitute (ruleset, buffer);
311 pango_ot_ruleset_position (ruleset, buffer);
313 pango_ot_buffer_output (buffer, glyphs);
314 pango_ot_buffer_destroy (buffer);
318 thai_make_unknown_glyph (ThaiFontInfo *font_info G_GNUC_UNUSED, gunichar uc)
320 return PANGO_GET_UNKNOWN_GLYPH (uc);
324 thai_engine_fc_class_init (PangoEngineShapeClass *class)
326 class->script_shape = thai_engine_shape;
329 PANGO_ENGINE_SHAPE_DEFINE_TYPE (ThaiEngineFc, thai_engine_fc,
330 thai_engine_fc_class_init, NULL)
333 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
335 thai_engine_fc_register_type (module);
339 PANGO_MODULE_ENTRY(exit) (void)
344 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
347 *engines = script_engines;
348 *n_engines = G_N_ELEMENTS (script_engines);
352 PANGO_MODULE_ENTRY(create) (const char *id)
354 if (!strcmp (id, SCRIPT_ENGINE_NAME))
355 return g_object_new (thai_engine_fc_type, NULL);