Git init
[external/pango1.0.git] / modules / basic / basic-fc.c
1 /* Pango
2  * basic-fc.c: Basic shaper for FreeType-based backends
3  *
4  * Copyright (C) 2000, 2007 Red Hat Software
5  * Authors:
6  *   Owen Taylor <otaylor@redhat.com>
7  *   Behdad Esfahbod <behdad@behdad.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26 #include <string.h>
27
28 #include <glib/gprintf.h>
29 #include "pango-engine.h"
30 #include "pango-utils.h"
31 #include "pangofc-font.h"
32 #include "pango-ot.h"
33
34 /* No extra fields needed */
35 typedef PangoEngineShape      BasicEngineFc;
36 typedef PangoEngineShapeClass BasicEngineFcClass;
37
38 #define SCRIPT_ENGINE_NAME "BasicScriptEngineFc"
39 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
40
41 static PangoEngineScriptInfo basic_scripts[] = {
42   /* Listed in OpenType "Standard scripts" standard */
43   { PANGO_SCRIPT_LATIN,    "*" },
44   { PANGO_SCRIPT_CYRILLIC, "*" },
45   { PANGO_SCRIPT_GREEK,    "*" },
46   { PANGO_SCRIPT_ARMENIAN, "*" },
47   { PANGO_SCRIPT_GEORGIAN, "*" },
48   { PANGO_SCRIPT_RUNIC,    "*" },
49   { PANGO_SCRIPT_OGHAM,    "*" },
50
51   /* The following are simple and can be shaped easily too */
52
53   { PANGO_SCRIPT_BOPOMOFO, "*" },
54   { PANGO_SCRIPT_CHEROKEE, "*" },
55   { PANGO_SCRIPT_COPTIC,   "*" },
56   { PANGO_SCRIPT_DESERET,  "*" },
57   { PANGO_SCRIPT_ETHIOPIC, "*" },
58   { PANGO_SCRIPT_GOTHIC,   "*" },
59   { PANGO_SCRIPT_HAN,      "*" },
60   { PANGO_SCRIPT_HIRAGANA, "*" },
61   { PANGO_SCRIPT_KATAKANA, "*" },
62   { PANGO_SCRIPT_OLD_ITALIC, "*" },
63   { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
64   { PANGO_SCRIPT_YI,       "*" },
65
66   /* Unicode-4.0 additions */
67   { PANGO_SCRIPT_BRAILLE,  "*" },
68   { PANGO_SCRIPT_CYPRIOT,  "*" },
69   { PANGO_SCRIPT_LIMBU,    "*" },
70   { PANGO_SCRIPT_OSMANYA,  "*" },
71   { PANGO_SCRIPT_SHAVIAN,  "*" },
72   { PANGO_SCRIPT_LINEAR_B, "*" },
73   { PANGO_SCRIPT_UGARITIC, "*" },
74
75   /* Unicode-4.1 additions */
76   { PANGO_SCRIPT_GLAGOLITIC, "*" },
77
78   /* Unicode-5.0 additions */
79   { PANGO_SCRIPT_CUNEIFORM,  "*" },
80   { PANGO_SCRIPT_PHOENICIAN, "*" },
81
82   /* In fact any script we don't know how to shape can go here */
83   { PANGO_SCRIPT_COMMON,   "" }
84 };
85
86 static PangoEngineInfo script_engines[] = {
87   {
88     SCRIPT_ENGINE_NAME,
89     PANGO_ENGINE_TYPE_SHAPE,
90     RENDER_TYPE,
91     basic_scripts, G_N_ELEMENTS(basic_scripts)
92   }
93 };
94
95 static const PangoOTFeatureMap gsub_features[] =
96 {
97   {"ccmp", PANGO_OT_ALL_GLYPHS},
98   {"locl", PANGO_OT_ALL_GLYPHS},
99   {"liga", PANGO_OT_ALL_GLYPHS},
100   {"clig", PANGO_OT_ALL_GLYPHS}
101 };
102
103 static const PangoOTFeatureMap gpos_features[] =
104 {
105   {"kern", PANGO_OT_ALL_GLYPHS},
106   {"mark", PANGO_OT_ALL_GLYPHS},
107   {"mkmk", PANGO_OT_ALL_GLYPHS}
108 };
109
110 static const PangoOTFeatureMap vertical_gsub_features[] =
111 {
112   {"ccmp", PANGO_OT_ALL_GLYPHS},
113   {"locl", PANGO_OT_ALL_GLYPHS},
114   {"vert", PANGO_OT_ALL_GLYPHS}
115 };
116
117 static const PangoOTFeatureMap vertical_gpos_features[] =
118 {
119   {"vkrn", PANGO_OT_ALL_GLYPHS}
120 };
121
122 static void
123 basic_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
124                     PangoFont        *font,
125                     const char       *text,
126                     gint              length,
127                     const PangoAnalysis *analysis,
128                     PangoGlyphString *glyphs)
129 {
130   PangoFcFont *fc_font;
131   FT_Face face;
132   PangoOTRulesetDescription desc;
133   const PangoOTRuleset *ruleset;
134   PangoOTBuffer *buffer;
135   glong n_chars;
136   const char *p;
137   int cluster = 0;
138   int i;
139
140   g_return_if_fail (font != NULL);
141   g_return_if_fail (text != NULL);
142   g_return_if_fail (length >= 0);
143   g_return_if_fail (analysis != NULL);
144
145   fc_font = PANGO_FC_FONT (font);
146   face = pango_fc_font_lock_face (fc_font);
147   if (!face)
148     return;
149
150   buffer = pango_ot_buffer_new (fc_font);
151   pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
152
153   n_chars = g_utf8_strlen (text, length);
154   pango_glyph_string_set_size (glyphs, n_chars);
155
156   p = text;
157   for (i=0; i < n_chars; i++)
158     {
159       gunichar wc;
160       PangoGlyph glyph;
161
162       wc = g_utf8_get_char (p);
163
164       if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
165         cluster = p - text;
166
167       if (pango_is_zero_width (wc))
168         glyph = PANGO_GLYPH_EMPTY;
169       else
170         {
171           gunichar c = wc;
172
173           if (analysis->level % 2)
174             g_unichar_get_mirror_char (c, &c);
175
176           glyph = pango_fc_font_get_glyph (fc_font, c);
177         }
178
179       if (!glyph)
180         glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
181
182       pango_ot_buffer_add_glyph (buffer, glyph, 0, cluster);
183
184       p = g_utf8_next_char (p);
185     }
186
187   desc.script = analysis->script;
188   desc.language = analysis->language;
189
190   if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
191     {
192       desc.n_static_gsub_features = G_N_ELEMENTS (vertical_gsub_features);
193       desc.static_gsub_features = vertical_gsub_features;
194       desc.n_static_gpos_features = G_N_ELEMENTS (vertical_gpos_features);
195       desc.static_gpos_features = vertical_gpos_features;
196     }
197   else
198     {
199       desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
200       desc.static_gsub_features = gsub_features;
201       desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
202       desc.static_gpos_features = gpos_features;
203     }
204
205   /* TODO populate other_features from analysis->extra_attrs */
206   desc.n_other_features = 0;
207   desc.other_features = NULL;
208
209   ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);
210
211   pango_ot_ruleset_substitute (ruleset, buffer);
212   pango_ot_ruleset_position (ruleset, buffer);
213   pango_ot_buffer_output (buffer, glyphs);
214
215   pango_ot_buffer_destroy (buffer);
216
217   pango_fc_font_unlock_face (fc_font);
218 }
219
220 static void
221 basic_engine_fc_class_init (PangoEngineShapeClass *class)
222 {
223   class->script_shape = basic_engine_shape;
224 }
225
226 PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineFc, basic_engine_fc,
227                                 basic_engine_fc_class_init, NULL)
228
229 void
230 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
231 {
232   basic_engine_fc_register_type (module);
233 }
234
235 void
236 PANGO_MODULE_ENTRY(exit) (void)
237 {
238 }
239
240 void
241 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
242                           int              *n_engines)
243 {
244   *engines = script_engines;
245   *n_engines = G_N_ELEMENTS (script_engines);
246 }
247
248 PangoEngine *
249 PANGO_MODULE_ENTRY(create) (const char *id)
250 {
251   if (!strcmp (id, SCRIPT_ENGINE_NAME))
252     return g_object_new (basic_engine_fc_type, NULL);
253   else
254     return NULL;
255 }