Synchronize with FreeType.
[ttfautohint.git] / lib / taglobal.c
bloba8ef573ce3195b0804c3ad4dad03bb7cfa528ec6
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? */
131 FT_Long nn;
134 for (nn = 0; nn < globals->glyph_count; nn++)
136 if ((gscripts[nn] & ~TA_DIGIT) == TA_SCRIPT_NONE)
138 gscripts[nn] &= ~TA_SCRIPT_NONE;
139 gscripts[nn] |= globals->font->fallback_script;
144 FT_Set_Charmap(face, old_charmap);
145 return error;
149 FT_Error
150 ta_face_globals_new(FT_Face face,
151 TA_FaceGlobals *aglobals,
152 FONT* font)
154 FT_Error error;
155 TA_FaceGlobals globals;
158 globals = (TA_FaceGlobals)calloc(1, sizeof (TA_FaceGlobalsRec) +
159 face->num_glyphs * sizeof (FT_Byte));
160 if (!globals)
162 error = FT_Err_Out_Of_Memory;
163 goto Err;
166 globals->face = face;
167 globals->glyph_count = face->num_glyphs;
168 globals->glyph_scripts = (FT_Byte*)(globals + 1);
169 globals->font = font;
171 error = ta_face_globals_compute_script_coverage(globals);
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;
263 metrics->globals = globals;
265 if (clazz->script_metrics_init)
267 error = clazz->script_metrics_init(metrics, globals->face);
268 if (error)
270 if (clazz->script_metrics_done)
271 clazz->script_metrics_done(metrics);
273 free(metrics);
274 metrics = NULL;
275 goto Exit;
279 globals->metrics[clazz->script] = metrics;
282 Exit:
283 *ametrics = metrics;
285 return error;
289 FT_Bool
290 ta_face_globals_is_digit(TA_FaceGlobals globals,
291 FT_UInt gindex)
293 if (gindex < (FT_ULong)globals->glyph_count)
294 return (FT_Bool)(globals->glyph_scripts[gindex] & TA_DIGIT);
296 return (FT_Bool)0;
299 /* end of taglobal.c */