4 * Copyright (C) 2001, 2002 IBM Corporation
5 * Author: Eric Mader <mader@jtcsv.com>
6 * Based on arabic-xft.c by Owen Taylor <otaylor@redhat.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
30 #include "pango-engine.h"
32 #include "pango-utils.h"
33 #include "pangofc-font.h"
35 typedef struct _PangoIndicInfo PangoIndicInfo;
37 typedef struct _IndicEngineFc IndicEngineFc;
38 typedef PangoEngineShapeClass IndicEngineFcClass ; /* No extra fields needed */
42 PangoEngineShape shapeEngine;
43 const IndicOTClassTable *classTable;
46 #define ENGINE_SUFFIX "ScriptEngineFc"
47 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
49 #define INDIC_ENGINE_INFO(script) {#script ENGINE_SUFFIX, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, script##_scripts, G_N_ELEMENTS(script##_scripts)}
51 #define INDIC_OT_CLASS_TABLE(script) &script##_class_table
53 static PangoEngineScriptInfo deva_scripts[] = {
54 { PANGO_SCRIPT_DEVANAGARI, "*" }
57 static PangoEngineScriptInfo beng_scripts[] = {
58 {PANGO_SCRIPT_BENGALI, "*" }
61 static PangoEngineScriptInfo guru_scripts[] = {
62 { PANGO_SCRIPT_GURMUKHI, "*" }
65 static PangoEngineScriptInfo gujr_scripts[] = {
66 { PANGO_SCRIPT_GUJARATI, "*" }
69 static PangoEngineScriptInfo orya_scripts[] = {
70 { PANGO_SCRIPT_ORIYA, "*" }
73 static PangoEngineScriptInfo taml_scripts[] = {
74 { PANGO_SCRIPT_TAMIL, "*" }
77 static PangoEngineScriptInfo telu_scripts[] = {
78 { PANGO_SCRIPT_TELUGU, "*" }
81 static PangoEngineScriptInfo knda_scripts[] = {
82 { PANGO_SCRIPT_KANNADA, "*" }
85 static PangoEngineScriptInfo mlym_scripts[] = {
86 { PANGO_SCRIPT_MALAYALAM, "*" }
89 static PangoEngineScriptInfo sinh_scripts[] = {
90 { PANGO_SCRIPT_SINHALA, "*" }
93 static PangoEngineInfo script_engines[] = {
94 INDIC_ENGINE_INFO(deva), INDIC_ENGINE_INFO(beng), INDIC_ENGINE_INFO(guru),
95 INDIC_ENGINE_INFO(gujr), INDIC_ENGINE_INFO(orya), INDIC_ENGINE_INFO(taml),
96 INDIC_ENGINE_INFO(telu), INDIC_ENGINE_INFO(knda), INDIC_ENGINE_INFO(mlym),
97 INDIC_ENGINE_INFO(sinh)
101 * WARNING: These entries need to be in the same order as the entries
102 * in script_engines[].
104 * FIXME: remove this requirement, either by encapsulating the order
105 * in a macro that calls a body macro that can be redefined, or by
106 * putting the pointers to the PangoEngineInfo in PangoIndicInfo...
108 static const IndicOTClassTable *indic_ot_class_tables[] = {
109 INDIC_OT_CLASS_TABLE(deva), INDIC_OT_CLASS_TABLE(beng), INDIC_OT_CLASS_TABLE(guru),
110 INDIC_OT_CLASS_TABLE(gujr), INDIC_OT_CLASS_TABLE(orya), INDIC_OT_CLASS_TABLE(taml),
111 INDIC_OT_CLASS_TABLE(telu), INDIC_OT_CLASS_TABLE(knda), INDIC_OT_CLASS_TABLE(mlym),
112 INDIC_OT_CLASS_TABLE(sinh)
115 static const PangoOTFeatureMap gsub_features[] =
117 {"ccmp", PANGO_OT_ALL_GLYPHS},
118 {"locl", PANGO_OT_ALL_GLYPHS},
132 {"calt", PANGO_OT_ALL_GLYPHS}
135 static const PangoOTFeatureMap gpos_features[] =
140 {"kern", PANGO_OT_ALL_GLYPHS},
141 {"mark", PANGO_OT_ALL_GLYPHS},
142 {"mkmk", PANGO_OT_ALL_GLYPHS}
146 set_glyphs (PangoFont *font,
150 PangoOTBuffer *buffer,
151 gboolean process_zwj)
154 PangoFcFont *fc_font;
158 fc_font = PANGO_FC_FONT (font);
160 for (i = 0; i < n_glyphs; i++)
164 if (pango_is_zero_width (wcs[i]) &&
165 (!process_zwj || wcs[i] != 0x200D))
166 glyph = PANGO_GLYPH_EMPTY;
169 glyph = pango_fc_font_get_glyph (fc_font, wcs[i]);
172 glyph = PANGO_GET_UNKNOWN_GLYPH ( wcs[i]);
174 pango_ot_buffer_add_glyph (buffer, glyph, tags[i], i);
179 * FIXME: should this check for null pointers, etc.?
182 expand_text(const gchar *text, glong length, glong **offsets, glong *n_chars)
188 *n_chars = g_utf8_strlen (text, length);
189 wcs = g_new (gunichar, *n_chars);
190 *offsets = g_new (glong, *n_chars + 1);
195 for (i = 0; i < *n_chars; i++)
197 *wco++ = g_utf8_get_char (p);
200 p = g_utf8_next_char (p);
209 /* analysis->shape_engine has the PangoEngine... */
211 indic_engine_shape (PangoEngineShape *engine,
215 const PangoAnalysis *analysis,
216 PangoGlyphString *glyphs)
218 PangoFcFont *fc_font;
220 PangoOTRulesetDescription desc;
221 const PangoOTRuleset *ruleset;
222 PangoOTBuffer *buffer;
223 glong i, n_chars, n_glyphs;
225 gunichar *wc_in = NULL, *wc_out = NULL;
226 glong *utf8_offsets = NULL;
227 glong *indices = NULL;
228 IndicEngineFc *indic_shape_engine = NULL;
229 MPreFixups *mprefixups;
231 g_return_if_fail (font != NULL);
232 g_return_if_fail (text != NULL);
233 g_return_if_fail (length >= 0);
234 g_return_if_fail (analysis != NULL);
236 fc_font = PANGO_FC_FONT (font);
237 face = pango_fc_font_lock_face (fc_font);
241 indic_shape_engine = (IndicEngineFc *) engine;
243 wc_in = expand_text (text, length, &utf8_offsets, &n_chars);
245 n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_shape_engine->classTable, NULL, NULL, NULL, NULL);
247 wc_out = g_new (gunichar, n_glyphs);
248 indices = g_new (glong, n_glyphs);
249 tags = g_new (gulong, n_glyphs);
251 n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_shape_engine->classTable, wc_out, indices, tags, &mprefixups);
253 pango_glyph_string_set_size (glyphs, n_glyphs);
254 buffer = pango_ot_buffer_new (fc_font);
255 pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
257 set_glyphs(font, wc_out, tags, n_glyphs, buffer,
258 (indic_shape_engine->classTable->scriptFlags & SF_PROCESS_ZWJ) != 0);
260 desc.script = analysis->script;
261 desc.language = analysis->language;
263 desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
264 desc.static_gsub_features = gsub_features;
265 desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
266 desc.static_gpos_features = gpos_features;
268 /* TODO populate other_features from analysis->extra_attrs */
269 desc.n_other_features = 0;
270 desc.other_features = NULL;
272 ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
274 /* do gsub processing */
275 pango_ot_ruleset_substitute (ruleset, buffer);
277 /* Fix pre-modifiers for some scripts before base consonant */
280 indic_mprefixups_apply (mprefixups, buffer);
281 indic_mprefixups_free (mprefixups);
284 /* do gpos processing */
285 pango_ot_ruleset_position (ruleset, buffer);
287 pango_ot_buffer_output (buffer, glyphs);
289 /* Get the right log_clusters values */
290 for (i = 0; i < glyphs->num_glyphs; i += 1)
291 glyphs->log_clusters[i] = indices[glyphs->log_clusters[i]];
293 pango_fc_font_unlock_face (fc_font);
295 pango_ot_buffer_destroy (buffer);
300 g_free (utf8_offsets);
304 indic_engine_fc_class_init (PangoEngineShapeClass *class)
306 class->script_shape = indic_engine_shape;
309 PANGO_ENGINE_SHAPE_DEFINE_TYPE (IndicEngineFc, indic_engine_fc,
310 indic_engine_fc_class_init, NULL)
313 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
315 indic_engine_fc_register_type (module);
319 PANGO_MODULE_ENTRY(exit) (void)
324 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
327 *engines = script_engines;
328 *n_engines = G_N_ELEMENTS (script_engines);
332 PANGO_MODULE_ENTRY(create) (const char *id)
336 for (i = 0; i < G_N_ELEMENTS(script_engines); i += 1)
338 if (!strcmp(id, script_engines[i].id))
340 IndicEngineFc *engine = g_object_new (indic_engine_fc_type, NULL);
341 engine->classTable = indic_ot_class_tables[i];
343 return (PangoEngine *)engine;