Synchronize with FreeType.
[ttfautohint.git] / lib / taglobal.c
blob1a767e58eb21bffd47ac03e1caaf6e31074938ba
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,
56 FT_UInt fallback_script)
58 FT_Error error = FT_Err_Ok;
59 FT_Face face = globals->face;
60 FT_CharMap old_charmap = face->charmap;
61 FT_Byte* gscripts = globals->glyph_scripts;
62 FT_UInt ss;
63 FT_UInt i;
66 /* the value TA_SCRIPT_NONE means `uncovered glyph' */
67 memset(globals->glyph_scripts, TA_SCRIPT_NONE, globals->glyph_count);
69 error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
70 if (error)
72 /* ignore this error; we simply use the fallback script */
73 /* XXX: Shouldn't we rather disable hinting? */
74 error = FT_Err_Ok;
75 goto Exit;
78 /* scan each script in a Unicode charmap */
79 for (ss = 0; ta_script_classes[ss]; ss++)
81 TA_ScriptClass clazz = ta_script_classes[ss];
82 TA_Script_UniRange range;
85 if (clazz->script_uni_ranges == NULL)
86 continue;
88 /* scan all Unicode points in the range and */
89 /* set the corresponding glyph script index */
90 for (range = clazz->script_uni_ranges; range->first != 0; range++)
92 FT_ULong charcode = range->first;
93 FT_UInt gindex;
96 gindex = FT_Get_Char_Index(face, charcode);
98 if (gindex != 0
99 && gindex < (FT_ULong)globals->glyph_count
100 && gscripts[gindex] == TA_SCRIPT_NONE)
101 gscripts[gindex] = (FT_Byte)ss;
103 for (;;)
105 charcode = FT_Get_Next_Char(face, charcode, &gindex);
107 if (gindex == 0 || charcode > range->last)
108 break;
110 if (gindex < (FT_ULong)globals->glyph_count
111 && gscripts[gindex] == TA_SCRIPT_NONE)
112 gscripts[gindex] = (FT_Byte)ss;
117 /* mark ASCII digits */
118 for (i = 0x30; i <= 0x39; i++)
120 FT_UInt gindex = FT_Get_Char_Index(face, i);
123 if (gindex != 0
124 && gindex < (FT_ULong)globals->glyph_count)
125 gscripts[gindex] |= TA_DIGIT;
128 Exit:
129 /* by default, all uncovered glyphs are set to the fallback script */
130 /* XXX: Shouldn't we disable hinting or do something similar? */
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] |= 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 FT_UInt fallback_script)
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);
171 error = ta_face_globals_compute_script_coverage(globals, fallback_script);
172 if (error)
174 ta_face_globals_free(globals);
175 globals = NULL;
178 Err:
179 *aglobals = globals;
180 return error;
184 void
185 ta_face_globals_free(TA_FaceGlobals globals)
187 if (globals)
189 FT_UInt nn;
192 for (nn = 0; nn < TA_SCRIPT_MAX; nn++)
194 if (globals->metrics[nn])
196 TA_ScriptClass clazz = ta_script_classes[nn];
199 #if 0
200 FT_ASSERT(globals->metrics[nn]->clazz == clazz);
201 #endif
203 if (clazz->script_metrics_done)
204 clazz->script_metrics_done(globals->metrics[nn]);
206 free(globals->metrics[nn]);
207 globals->metrics[nn] = NULL;
211 globals->glyph_count = 0;
212 globals->glyph_scripts = NULL; /* no need to free this one! */
213 globals->face = NULL;
215 free(globals);
216 globals = NULL;
221 FT_Error
222 ta_face_globals_get_metrics(TA_FaceGlobals globals,
223 FT_UInt gindex,
224 FT_UInt options,
225 TA_ScriptMetrics *ametrics)
227 TA_ScriptMetrics metrics = NULL;
228 FT_UInt gidx;
229 TA_ScriptClass clazz;
230 FT_UInt script = options & 15;
231 const FT_Offset script_max = sizeof (ta_script_classes)
232 / sizeof (ta_script_classes[0]);
233 FT_Error error = FT_Err_Ok;
236 if (gindex >= (FT_ULong)globals->glyph_count)
238 error = FT_Err_Invalid_Argument;
239 goto Exit;
242 gidx = script;
243 if (gidx == 0
244 || gidx + 1 >= script_max)
245 gidx = globals->glyph_scripts[gindex] & TA_SCRIPT_NONE;
247 clazz = ta_script_classes[gidx];
248 if (script == 0)
249 script = clazz->script;
251 metrics = globals->metrics[clazz->script];
252 if (metrics == NULL)
254 /* create the global metrics object if necessary */
255 metrics = (TA_ScriptMetrics)calloc(1, clazz->script_metrics_size);
256 if (!metrics)
258 error = FT_Err_Out_Of_Memory;
259 goto Exit;
262 metrics->clazz = clazz;
264 if (clazz->script_metrics_init)
266 error = clazz->script_metrics_init(metrics, globals->face);
267 if (error)
269 if (clazz->script_metrics_done)
270 clazz->script_metrics_done(metrics);
272 free(metrics);
273 metrics = NULL;
274 goto Exit;
278 globals->metrics[clazz->script] = metrics;
281 Exit:
282 *ametrics = metrics;
284 return error;
288 FT_Bool
289 ta_face_globals_is_digit(TA_FaceGlobals globals,
290 FT_UInt gindex)
292 if (gindex < (FT_ULong)globals->glyph_count)
293 return (FT_Bool)(globals->glyph_scripts[gindex] & TA_DIGIT);
295 return (FT_Bool)0;
298 /* end of taglobal.c */