Synchronize with FreeType, part 2.
[ttfautohint.git] / lib / tacvt.c
blob32b90686b14e760522f5e63300c658d06885b72f
1 /* tacvt.c */
3 /*
4 * Copyright (C) 2011-2014 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 #include "ta.h"
19 static FT_Error
20 TA_sfnt_compute_global_hints(SFNT* sfnt,
21 FONT* font,
22 FT_UInt script_idx)
24 FT_Error error;
25 FT_Face face = sfnt->face;
26 FT_UInt idx;
27 FT_Int32 load_flags;
30 error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
31 if (error)
33 if (font->symbol)
35 error = FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL);
36 if (error)
37 return TA_Err_Missing_Symbol_CMap;
39 else
40 return TA_Err_Missing_Unicode_CMap;
43 if (font->symbol)
44 idx = 0;
45 else
47 /* load standard character to trigger script initializations */
48 /* XXX make this configurable to use a different letter */
49 idx = FT_Get_Char_Index(face,
50 ta_script_classes[script_idx]->standard_char);
51 if (!idx)
52 return TA_Err_Missing_Glyph;
55 load_flags = 1 << 29; /* vertical hinting only */
56 error = ta_loader_load_glyph(font, face, idx, load_flags);
58 return error;
62 static FT_Error
63 TA_table_build_cvt(FT_Byte** cvt,
64 FT_ULong* cvt_len,
65 SFNT* sfnt,
66 FONT* font)
68 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
69 glyf_Data* data = (glyf_Data*)glyf_table->data;
71 TA_LatinAxis haxis;
72 TA_LatinAxis vaxis;
74 FT_UInt hwidth_count;
75 FT_UInt vwidth_count;
76 FT_UInt blue_count;
78 FT_UInt i, j, i_max;
79 FT_UInt buf_len;
80 FT_UInt len;
81 FT_Byte* buf;
82 FT_Byte* bufp;
83 FT_UInt cvt_offset;
85 FT_Error error;
88 /* checking multiple scripts doesn't make sense for symbol fonts */
89 i_max = font->symbol ? 1 : TA_SCRIPT_MAX;
91 /* loop over all scripts and collect the relevant CVT data */
92 /* to compute the necessary array sizes and meta-information */
93 hwidth_count = 0;
94 vwidth_count = 0;
95 blue_count = 0;
97 data->num_used_scripts = 0;
99 for (i = 0; i < i_max; i++)
101 error = TA_sfnt_compute_global_hints(sfnt, font, i);
102 if (error == TA_Err_Missing_Glyph)
104 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
105 FT_Byte* gscripts = globals->glyph_scripts;
106 FT_Int nn;
109 data->script_ids[i] = 0xFFFFU;
111 /* remove all references to this script; */
112 /* otherwise blue zones are computed later on, which we don't want */
113 for (nn = 0; nn < globals->glyph_count; nn++)
115 if ((gscripts[nn] & ~TA_DIGIT) == i)
117 gscripts[nn] &= ~TA_SCRIPT_UNASSIGNED;
118 gscripts[nn] |= globals->font->fallback_script;
122 continue;
124 if (error)
125 return error;
127 data->script_ids[i] = data->num_used_scripts++;
129 if (font->loader->hints.metrics->script_class->script == TA_SCRIPT_NONE)
130 continue;
131 else
133 /* XXX: generalize this to handle other metrics also */
134 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
135 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
137 hwidth_count += haxis->width_count;
138 vwidth_count += vaxis->width_count;
139 /* there are two artificial blue zones at the end of the array */
140 /* that are not part of `vaxis->blue_count' */
141 blue_count += vaxis->blue_count + 2;
145 /* exit if the font doesn't contain a single supported script */
146 if (!data->num_used_scripts)
147 return TA_Err_Missing_Glyph;
149 buf_len = cvtl_max_runtime /* runtime values 1 */
150 + data->num_used_scripts /* runtime values 2 (for scaling) */
151 + 2 * data->num_used_scripts /* runtime values 3 (blue data) */
152 + 2 * data->num_used_scripts /* vert. and horiz. std. widths */
153 + hwidth_count
154 + vwidth_count
155 + 2 * blue_count; /* round and flat blue zones */
156 buf_len <<= 1; /* we have 16bit values */
158 /* buffer length must be a multiple of four */
159 len = (buf_len + 3) & ~3;
160 buf = (FT_Byte*)malloc(len);
161 if (!buf)
162 return FT_Err_Out_Of_Memory;
164 /* pad end of buffer with zeros */
165 buf[len - 1] = 0x00;
166 buf[len - 2] = 0x00;
167 buf[len - 3] = 0x00;
169 bufp = buf;
172 * some CVT values are initialized (and modified) at runtime:
174 * (1) the `cvtl_xxx' values (see `tabytecode.h')
175 * (2) a scaling value for each script
176 * (3) offset and size of the vertical widths array
177 * (needed by `bci_{smooth,strong}_stem_width') for each script
179 for (i = 0; i < (cvtl_max_runtime
180 + data->num_used_scripts
181 + 2 * data->num_used_scripts) * 2; i++)
182 *(bufp++) = 0;
184 cvt_offset = bufp - buf;
186 /* loop again over all scripts and copy CVT data */
187 for (i = 0; i < i_max; i++)
189 /* collect offsets */
190 data->cvt_offsets[i] = ((FT_UInt)(bufp - buf) - cvt_offset) >> 1;
192 error = TA_sfnt_compute_global_hints(sfnt, font, i);
193 if (error == TA_Err_Missing_Glyph)
194 continue;
195 if (error)
196 return error;
198 if (font->loader->hints.metrics->script_class->script == TA_SCRIPT_NONE)
200 haxis = NULL;
201 vaxis = NULL;
203 hwidth_count = 0;
204 vwidth_count = 0;
205 blue_count = 0;
207 else
209 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
210 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
212 hwidth_count = haxis->width_count;
213 vwidth_count = vaxis->width_count;
214 blue_count = vaxis->blue_count + 2; /* with artificial blue zones */
217 /* horizontal standard width */
218 if (hwidth_count > 0)
220 *(bufp++) = HIGH(haxis->widths[0].org);
221 *(bufp++) = LOW(haxis->widths[0].org);
223 else
225 *(bufp++) = 0;
226 *(bufp++) = 50;
229 for (j = 0; j < hwidth_count; j++)
231 if (haxis->widths[j].org > 0xFFFF)
232 goto Err;
233 *(bufp++) = HIGH(haxis->widths[j].org);
234 *(bufp++) = LOW(haxis->widths[j].org);
237 /* vertical standard width */
238 if (vwidth_count > 0)
240 *(bufp++) = HIGH(vaxis->widths[0].org);
241 *(bufp++) = LOW(vaxis->widths[0].org);
243 else
245 *(bufp++) = 0;
246 *(bufp++) = 50;
249 for (j = 0; j < vwidth_count; j++)
251 if (vaxis->widths[j].org > 0xFFFF)
252 goto Err;
253 *(bufp++) = HIGH(vaxis->widths[j].org);
254 *(bufp++) = LOW(vaxis->widths[j].org);
257 data->cvt_blue_adjustment_offsets[i] = 0xFFFFU;
259 for (j = 0; j < blue_count; j++)
261 if (vaxis->blues[j].ref.org > 0xFFFF)
262 goto Err;
263 *(bufp++) = HIGH(vaxis->blues[j].ref.org);
264 *(bufp++) = LOW(vaxis->blues[j].ref.org);
267 for (j = 0; j < blue_count; j++)
269 if (vaxis->blues[j].shoot.org > 0xFFFF)
270 goto Err;
271 *(bufp++) = HIGH(vaxis->blues[j].shoot.org);
272 *(bufp++) = LOW(vaxis->blues[j].shoot.org);
274 if (vaxis->blues[j].flags & TA_LATIN_BLUE_ADJUSTMENT)
275 data->cvt_blue_adjustment_offsets[i] = j;
278 data->cvt_horz_width_sizes[i] = hwidth_count;
279 data->cvt_vert_width_sizes[i] = vwidth_count;
280 data->cvt_blue_zone_sizes[i] = blue_count;
283 *cvt = buf;
284 *cvt_len = buf_len;
286 return FT_Err_Ok;
288 Err:
289 free(buf);
290 return TA_Err_Hinter_Overflow;
294 FT_Error
295 TA_sfnt_build_cvt_table(SFNT* sfnt,
296 FONT* font)
298 FT_Error error;
300 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
301 glyf_Data* data = (glyf_Data*)glyf_table->data;
303 FT_Byte* cvt_buf;
304 FT_ULong cvt_len;
307 error = TA_sfnt_add_table_info(sfnt);
308 if (error)
309 goto Exit;
311 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
312 if (glyf_table->processed)
314 sfnt->table_infos[sfnt->num_table_infos - 1] = data->cvt_idx;
315 goto Exit;
318 error = TA_table_build_cvt(&cvt_buf, &cvt_len, sfnt, font);
319 if (error)
320 goto Exit;
322 /* in case of success, `cvt_buf' gets linked */
323 /* and is eventually freed in `TA_font_unload' */
324 error = TA_font_add_table(font,
325 &sfnt->table_infos[sfnt->num_table_infos - 1],
326 TTAG_cvt, cvt_len, cvt_buf);
327 if (error)
328 free(cvt_buf);
329 else
330 data->cvt_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
332 Exit:
333 return error;
336 /* end of tacvt.c */