Initial Import
[profile/ivi/pango.git] / modules / thai / thai-fc.c
1 /* Pango
2  * thai-fc.c:
3  *
4  * Copyright (C) 1999, 2007 Red Hat Software
5  * Copyright (C) 2002 NECTEC
6  * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
7  * Authors:
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>
12  *
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.
17  *
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.
22  *
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.
27  */
28
29
30 #include "config.h"
31 #include <string.h>
32
33 #include <glib.h>
34 #include "pango-ot.h"
35
36 #include "pango-engine.h"
37 #include "pangofc-font.h"
38
39 #include "thai-shaper.h"
40
41 /* No extra fields needed */
42 typedef PangoEngineShape      ThaiEngineFc;
43 typedef PangoEngineShapeClass ThaiEngineFcClass ;
44
45 #define SCRIPT_ENGINE_NAME "ThaiScriptEngineFc"
46 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
47
48 /* We handle the range U+0e01 to U+0e5b exactly
49  */
50 static PangoEngineScriptInfo thai_scripts[] = {
51   { PANGO_SCRIPT_THAI, "*" },
52   { PANGO_SCRIPT_LAO,  "*" },
53 };
54
55 static PangoEngineInfo script_engines[] = {
56   {
57     SCRIPT_ENGINE_NAME,
58     PANGO_ENGINE_TYPE_SHAPE,
59     RENDER_TYPE,
60     thai_scripts, G_N_ELEMENTS(thai_scripts)
61   }
62 };
63
64 /* TIS-to-Unicode glyph maps for characters 0x80-0xff
65  */
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
83 };
84
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
102 };
103
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
121 };
122
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
140 };
141 static int
142 contain_glyphs(PangoFont *font, const int glyph_map[128])
143 {
144   PangoFcFont *fc_font = (PangoFcFont *)font;
145   unsigned char c;
146
147   for (c = 0; c < 0x80; c++)
148     {
149       if (glyph_map[c])
150         {
151           if (!pango_fc_font_has_char (fc_font, glyph_map[c]))
152             return 0;
153         }
154     }
155   return 1;
156 }
157
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.
160  */
161 static ThaiFontInfo *
162 thai_get_font_info (PangoFont            *font,
163                     const PangoOTRuleset *ruleset)
164 {
165   ThaiFontInfo *font_info;
166   static GQuark info_id = 0;
167   
168   if (G_UNLIKELY (!info_id))
169     info_id = g_quark_from_string ("thai-font-info");
170
171   font_info = g_object_get_qdata (G_OBJECT (font), info_id);
172
173   if (G_UNLIKELY (!font_info))
174     {
175       /* No cached information not found, so we need to compute it
176        * from scratch
177        */
178       font_info = g_new (ThaiFontInfo, 1);
179       font_info->font = font;
180
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;
188       else
189         font_info->font_set = THAI_FONT_TIS;
190
191       g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free);
192     }
193
194   return font_info;
195 }
196
197 static gunichar
198 get_glyph_index_tis (ThaiFontInfo *font_info, guchar c)
199 {
200   if (!(c & 0x80))
201     return lao_0[c];
202
203   switch (font_info->font_set) {
204     default:
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];
209   }
210 }
211
212 PangoGlyph
213 thai_get_glyph_tis (ThaiFontInfo *font_info, guchar c)
214 {
215   return thai_get_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
216 }
217
218 PangoGlyph
219 thai_make_glyph_tis (ThaiFontInfo *font_info, guchar c)
220 {
221   return thai_make_glyph_uni (font_info, get_glyph_index_tis (font_info, c));
222 }
223
224 PangoGlyph
225 thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
226 {
227   return pango_fc_font_get_glyph ((PangoFcFont *)font_info->font, uc);
228 }
229
230 PangoGlyph
231 thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
232 {
233   PangoGlyph result;
234   PangoFcFont *fc_font = (PangoFcFont *)font_info->font;
235
236   result = pango_fc_font_get_glyph (fc_font, uc);
237   if (result)
238     return result;
239   else
240     return PANGO_GET_UNKNOWN_GLYPH ( uc);
241 }
242
243 static const PangoOTFeatureMap gsub_features[] =
244 {
245   {"ccmp", PANGO_OT_ALL_GLYPHS},
246   {"locl", PANGO_OT_ALL_GLYPHS},
247   {"liga", PANGO_OT_ALL_GLYPHS},
248 };
249
250 static const PangoOTFeatureMap gpos_features[] =
251 {
252   {"kern", PANGO_OT_ALL_GLYPHS},
253   {"mark", PANGO_OT_ALL_GLYPHS},
254   {"mkmk", PANGO_OT_ALL_GLYPHS}
255 };
256
257 static void
258 thai_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
259                    PangoFont        *font,
260                    const char       *text,
261                    gint              length,
262                    const PangoAnalysis *analysis,
263                    PangoGlyphString *glyphs)
264 {
265   PangoFcFont *fc_font;
266   FT_Face face;
267   PangoOTRulesetDescription desc;
268   const PangoOTRuleset *ruleset;
269   PangoOTBuffer *buffer;
270   gint i;
271   ThaiFontInfo *font_info;
272
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);
277
278   fc_font = PANGO_FC_FONT (font);
279   face = pango_fc_font_lock_face (fc_font);
280   if (!face)
281     return;
282
283   desc.script = analysis->script;
284   desc.language = analysis->language;
285
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;
290
291   /* TODO populate other_features from analysis->extra_attrs */
292   desc.n_other_features = 0;
293   desc.other_features = NULL;
294
295   ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
296
297   font_info = thai_get_font_info (font, ruleset);
298
299   thai_set_glyphs (font_info, text, length, analysis->script, glyphs); 
300
301   buffer = pango_ot_buffer_new (PANGO_FC_FONT (font));
302   pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
303
304   for (i = 0; i < glyphs->num_glyphs; i++)
305     pango_ot_buffer_add_glyph (buffer,
306                                glyphs->glyphs[i].glyph,
307                                0,
308                                glyphs->log_clusters[i]);
309
310   pango_ot_ruleset_substitute (ruleset, buffer);
311   pango_ot_ruleset_position (ruleset, buffer);
312
313   pango_ot_buffer_output (buffer, glyphs);
314   pango_ot_buffer_destroy (buffer);
315 }
316
317 PangoGlyph
318 thai_make_unknown_glyph (ThaiFontInfo *font_info G_GNUC_UNUSED, gunichar uc)
319 {
320   return PANGO_GET_UNKNOWN_GLYPH (uc);
321 }
322
323 static void
324 thai_engine_fc_class_init (PangoEngineShapeClass *class)
325 {
326   class->script_shape = thai_engine_shape;
327 }
328
329 PANGO_ENGINE_SHAPE_DEFINE_TYPE (ThaiEngineFc, thai_engine_fc,
330                                 thai_engine_fc_class_init, NULL)
331
332 void
333 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
334 {
335   thai_engine_fc_register_type (module);
336 }
337
338 void
339 PANGO_MODULE_ENTRY(exit) (void)
340 {
341 }
342
343 void
344 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
345                           int              *n_engines)
346 {
347   *engines = script_engines;
348   *n_engines = G_N_ELEMENTS (script_engines);
349 }
350
351 PangoEngine *
352 PANGO_MODULE_ENTRY(create) (const char *id)
353 {
354   if (!strcmp (id, SCRIPT_ENGINE_NAME))
355     return g_object_new (thai_engine_fc_type, NULL);
356   else
357     return NULL;
358 }