Synchronize with FreeType.
[ttfautohint.git] / lib / taglobal.c
blob2a8c7072dba9ca838cc7df8920e8daad52cb04a5
1 /* taglobal.c */
3 /*
4 * Copyright (C) 2011-2012 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
16 /* originally file `afglobal.c' (2011-Mar-28) from FreeType */
18 /* heavily modified 2011 by Werner Lemberg <wl@gnu.org> */
20 #include <stdlib.h>
22 #include "taglobal.h"
24 #include "tadummy.h"
25 #include "talatin.h"
27 #if 0
28 #include "tacjk.h"
29 #include "taindic.h"
31 #ifdef FT_OPTION_AUTOFIT2
32 #include "talatin2.h"
33 #endif
34 #endif /* 0 */
36 /* populate this list when you add new scripts */
37 static TA_ScriptClass const ta_script_classes[] =
39 &ta_dummy_script_class,
40 #ifdef FT_OPTION_AUTOFIT2
41 &ta_latin2_script_class,
42 #endif
43 &ta_latin_script_class,
44 #if 0
45 &ta_cjk_script_class,
46 &ta_indic_script_class,
47 #endif
48 NULL /* do not remove */
52 /* Compute the script index of each glyph within a given face. */
54 static FT_Error
55 ta_face_globals_compute_script_coverage(TA_FaceGlobals globals)
57 FT_Error error = FT_Err_Ok;
58 FT_Face face = globals->face;
59 FT_CharMap old_charmap = face->charmap;
60 FT_Byte* gscripts = globals->glyph_scripts;
61 FT_UInt ss;
62 FT_UInt i;
65 /* the value TA_SCRIPT_NONE means `uncovered glyph' */
66 memset(globals->glyph_scripts, TA_SCRIPT_NONE, globals->glyph_count);
68 error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
69 if (error)
71 /* ignore this error; we simply use the fallback script */
72 /* XXX: Shouldn't we rather disable hinting? */
73 error = FT_Err_Ok;
74 goto Exit;
77 /* scan each script in a Unicode charmap */
78 for (ss = 0; ta_script_classes[ss]; ss++)
80 TA_ScriptClass clazz = ta_script_classes[ss];
81 TA_Script_UniRange range;
84 if (clazz->script_uni_ranges == NULL)
85 continue;
87 /* scan all Unicode points in the range and */
88 /* set the corresponding glyph script index */
89 for (range = clazz->script_uni_ranges; range->first != 0; range++)
91 FT_ULong charcode = range->first;
92 FT_UInt gindex;
95 gindex = FT_Get_Char_Index(face, charcode);
97 if (gindex != 0
98 && gindex < (FT_ULong)globals->glyph_count
99 && gscripts[gindex] == TA_SCRIPT_NONE)
100 gscripts[gindex] = (FT_Byte)ss;
102 for (;;)
104 charcode = FT_Get_Next_Char(face, charcode, &gindex);
106 if (gindex == 0 || charcode > range->last)
107 break;
109 if (gindex < (FT_ULong)globals->glyph_count
110 && gscripts[gindex] == TA_SCRIPT_NONE)
111 gscripts[gindex] = (FT_Byte)ss;
116 /* mark ASCII digits */
117 for (i = 0x30; i <= 0x39; i++)
119 FT_UInt gindex = FT_Get_Char_Index(face, i);
122 if (gindex != 0
123 && gindex < (FT_ULong)globals->glyph_count)
124 gscripts[gindex] |= TA_DIGIT;
127 Exit:
128 /* by default, all uncovered glyphs are set to the fallback script */
129 /* XXX: Shouldn't we disable hinting or do something similar? */
130 if (globals->font->fallback_script != TA_SCRIPT_NONE)
132 FT_Long nn;
135 for (nn = 0; nn < globals->glyph_count; nn++)
137 if ((gscripts[nn] & ~TA_DIGIT) == TA_SCRIPT_NONE)
139 gscripts[nn] &= ~TA_SCRIPT_NONE;
140 gscripts[nn] |= globals->font->fallback_script;
145 FT_Set_Charmap(face, old_charmap);
146 return error;
150 FT_Error
151 ta_face_globals_new(FT_Face face,
152 TA_FaceGlobals *aglobals,
153 FONT* font)
155 FT_Error error;
156 TA_FaceGlobals globals;
159 globals = (TA_FaceGlobals)calloc(1, sizeof (TA_FaceGlobalsRec) +
160 face->num_glyphs * sizeof (FT_Byte));
161 if (!globals)
163 error = FT_Err_Out_Of_Memory;
164 goto Err;
167 globals->face = face;
168 globals->glyph_count = face->num_glyphs;
169 globals->glyph_scripts = (FT_Byte*)(globals + 1);
170 globals->font = font;
172 error = ta_face_globals_compute_script_coverage(globals);
173 if (error)
175 ta_face_globals_free(globals);
176 globals = NULL;
179 globals->increase_x_height = TA_PROP_INCREASE_X_HEIGHT_MAX;
181 Err:
182 *aglobals = globals;
183 return error;
187 void
188 ta_face_globals_free(TA_FaceGlobals globals)
190 if (globals)
192 FT_UInt nn;
195 for (nn = 0; nn < TA_SCRIPT_MAX; nn++)
197 if (globals->metrics[nn])
199 TA_ScriptClass clazz = ta_script_classes[nn];
202 #if 0
203 FT_ASSERT(globals->metrics[nn]->clazz == clazz);
204 #endif
206 if (clazz->script_metrics_done)
207 clazz->script_metrics_done(globals->metrics[nn]);
209 free(globals->metrics[nn]);
210 globals->metrics[nn] = NULL;
214 globals->glyph_count = 0;
215 globals->glyph_scripts = NULL; /* no need to free this one! */
216 globals->face = NULL;
218 free(globals);
219 globals = NULL;
224 FT_Error
225 ta_face_globals_get_metrics(TA_FaceGlobals globals,
226 FT_UInt gindex,
227 FT_UInt options,
228 TA_ScriptMetrics *ametrics)
230 TA_ScriptMetrics metrics = NULL;
231 FT_UInt gidx;
232 TA_ScriptClass clazz;
233 FT_UInt script = options & 15;
234 const FT_Offset script_max = sizeof (ta_script_classes)
235 / sizeof (ta_script_classes[0]);
236 FT_Error error = FT_Err_Ok;
239 if (gindex >= (FT_ULong)globals->glyph_count)
241 error = FT_Err_Invalid_Argument;
242 goto Exit;
245 gidx = script;
246 if (gidx == 0
247 || gidx + 1 >= script_max)
248 gidx = globals->glyph_scripts[gindex] & TA_SCRIPT_NONE;
250 clazz = ta_script_classes[gidx];
251 if (script == 0)
252 script = clazz->script;
254 metrics = globals->metrics[clazz->script];
255 if (metrics == NULL)
257 /* create the global metrics object if necessary */
258 metrics = (TA_ScriptMetrics)calloc(1, clazz->script_metrics_size);
259 if (!metrics)
261 error = FT_Err_Out_Of_Memory;
262 goto Exit;
265 metrics->clazz = clazz;
266 metrics->globals = globals;
268 if (clazz->script_metrics_init)
270 error = clazz->script_metrics_init(metrics, globals->face);
271 if (error)
273 if (clazz->script_metrics_done)
274 clazz->script_metrics_done(metrics);
276 free(metrics);
277 metrics = NULL;
278 goto Exit;
282 globals->metrics[clazz->script] = metrics;
285 Exit:
286 *ametrics = metrics;
288 return error;
292 FT_Bool
293 ta_face_globals_is_digit(TA_FaceGlobals globals,
294 FT_UInt gindex)
296 if (gindex < (FT_ULong)globals->glyph_count)
297 return (FT_Bool)(globals->glyph_scripts[gindex] & TA_DIGIT);
299 return (FT_Bool)0;
302 /* end of taglobal.c */