Remove limits of `increase-x-height' option.
[ttfautohint.git] / lib / taglobal.c
blobf9a8a13376147b961c4dcf70e67c465bd71d706f
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 globals->increase_x_height = TA_PROP_INCREASE_X_HEIGHT_MAX;
180 Err:
181 *aglobals = globals;
182 return error;
186 void
187 ta_face_globals_free(TA_FaceGlobals globals)
189 if (globals)
191 FT_UInt nn;
194 for (nn = 0; nn < TA_SCRIPT_MAX; nn++)
196 if (globals->metrics[nn])
198 TA_ScriptClass clazz = ta_script_classes[nn];
201 #if 0
202 FT_ASSERT(globals->metrics[nn]->clazz == clazz);
203 #endif
205 if (clazz->script_metrics_done)
206 clazz->script_metrics_done(globals->metrics[nn]);
208 free(globals->metrics[nn]);
209 globals->metrics[nn] = NULL;
213 globals->glyph_count = 0;
214 globals->glyph_scripts = NULL; /* no need to free this one! */
215 globals->face = NULL;
217 free(globals);
218 globals = NULL;
223 FT_Error
224 ta_face_globals_get_metrics(TA_FaceGlobals globals,
225 FT_UInt gindex,
226 FT_UInt options,
227 TA_ScriptMetrics *ametrics)
229 TA_ScriptMetrics metrics = NULL;
230 FT_UInt gidx;
231 TA_ScriptClass clazz;
232 FT_UInt script = options & 15;
233 const FT_Offset script_max = sizeof (ta_script_classes)
234 / sizeof (ta_script_classes[0]);
235 FT_Error error = FT_Err_Ok;
238 if (gindex >= (FT_ULong)globals->glyph_count)
240 error = FT_Err_Invalid_Argument;
241 goto Exit;
244 gidx = script;
245 if (gidx == 0
246 || gidx + 1 >= script_max)
247 gidx = globals->glyph_scripts[gindex] & TA_SCRIPT_NONE;
249 clazz = ta_script_classes[gidx];
250 if (script == 0)
251 script = clazz->script;
253 metrics = globals->metrics[clazz->script];
254 if (metrics == NULL)
256 /* create the global metrics object if necessary */
257 metrics = (TA_ScriptMetrics)calloc(1, clazz->script_metrics_size);
258 if (!metrics)
260 error = FT_Err_Out_Of_Memory;
261 goto Exit;
264 metrics->clazz = clazz;
265 metrics->globals = globals;
267 if (clazz->script_metrics_init)
269 error = clazz->script_metrics_init(metrics, globals->face);
270 if (error)
272 if (clazz->script_metrics_done)
273 clazz->script_metrics_done(metrics);
275 free(metrics);
276 metrics = NULL;
277 goto Exit;
281 globals->metrics[clazz->script] = metrics;
284 Exit:
285 *ametrics = metrics;
287 return error;
291 FT_Bool
292 ta_face_globals_is_digit(TA_FaceGlobals globals,
293 FT_UInt gindex)
295 if (gindex < (FT_ULong)globals->glyph_count)
296 return (FT_Bool)(globals->glyph_scripts[gindex] & TA_DIGIT);
298 return (FT_Bool)0;
301 /* end of taglobal.c */