Fix incorrect data in `prep' table.
[ttfautohint.git] / lib / tacvt.c
blob2a5448de5cbbc514ce49a3b743c3d26eec0e3332
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 style_idx)
24 FT_Error error;
25 FT_Face face = sfnt->face;
26 FT_ULong glyph_index;
27 FT_Long y_offset;
28 FT_Int32 load_flags;
31 error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
32 if (error)
34 if (font->symbol)
36 error = FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL);
37 if (error)
38 return TA_Err_Missing_Symbol_CMap;
40 else
41 return TA_Err_Missing_Unicode_CMap;
44 if (font->symbol)
45 glyph_index = 0;
46 else
48 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
49 TA_StyleClass style_class = ta_style_classes[style_idx];
50 TA_ScriptClass script_class = ta_script_classes[style_class->script];
52 TA_StyleMetricsRec dummy;
55 /* we don't have a `TA_Loader' object yet */
56 dummy.globals = globals;
57 dummy.style_class = style_class;
59 /* XXX: Extend this with a list of possible standard characters: */
60 /* Especially in non-default coverages, a single standard */
61 /* character may not be available. */
62 ta_get_char_index(&dummy,
63 script_class->standard_char,
64 &glyph_index,
65 &y_offset);
66 if (!glyph_index)
67 return TA_Err_Missing_Glyph;
70 load_flags = 1 << 29; /* vertical hinting only */
71 error = ta_loader_load_glyph(font, face, glyph_index, load_flags);
73 return error;
77 static FT_Error
78 TA_table_build_cvt(FT_Byte** cvt,
79 FT_ULong* cvt_len,
80 SFNT* sfnt,
81 FONT* font)
83 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
84 glyf_Data* data = (glyf_Data*)glyf_table->data;
86 TA_LatinAxis haxis;
87 TA_LatinAxis vaxis;
89 FT_UInt hwidth_count;
90 FT_UInt vwidth_count;
91 FT_UInt blue_count;
93 FT_UInt i, j, i_max;
94 FT_UInt buf_len;
95 FT_UInt len;
96 FT_Byte* buf;
97 FT_Byte* bufp;
98 FT_UInt cvt_offset;
100 FT_Error error;
103 /* checking multiple styles doesn't make sense for symbol fonts */
104 i_max = font->symbol ? 1 : TA_STYLE_MAX;
106 /* loop over all styles and collect the relevant CVT data */
107 /* to compute the necessary array sizes and meta-information */
108 hwidth_count = 0;
109 vwidth_count = 0;
110 blue_count = 0;
112 data->num_used_styles = 0;
114 for (i = 0; i < i_max; i++)
116 error = TA_sfnt_compute_global_hints(sfnt, font, i);
117 if (error == TA_Err_Missing_Glyph)
119 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
120 FT_Byte* gstyles = globals->glyph_styles;
121 FT_Int nn;
124 data->style_ids[i] = 0xFFFFU;
126 /* remove all references to this style; */
127 /* otherwise blue zones are computed later on, which we don't want */
128 for (nn = 0; nn < globals->glyph_count; nn++)
130 if ((gstyles[nn] & ~TA_DIGIT) == i)
132 gstyles[nn] &= ~TA_STYLE_UNASSIGNED;
133 gstyles[nn] |= globals->font->fallback_style;
137 continue;
139 if (error)
140 return error;
142 data->style_ids[i] = data->num_used_styles++;
144 if (font->loader->hints.metrics->style_class == &ta_none_dflt_style_class)
145 continue;
146 else
148 /* XXX: generalize this to handle other metrics also */
149 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
150 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
152 hwidth_count += haxis->width_count;
153 vwidth_count += vaxis->width_count;
154 /* there are two artificial blue zones at the end of the array */
155 /* that are not part of `vaxis->blue_count' */
156 blue_count += vaxis->blue_count + 2;
160 /* exit if the font doesn't contain a single supported style */
161 if (!data->num_used_styles)
162 return TA_Err_Missing_Glyph;
164 buf_len = cvtl_max_runtime /* runtime values 1 */
165 + data->num_used_styles /* runtime values 2 (for scaling) */
166 + 2 * data->num_used_styles /* runtime values 3 (blue data) */
167 + 2 * data->num_used_styles /* vert. and horiz. std. widths */
168 + hwidth_count
169 + vwidth_count
170 + 2 * blue_count; /* round and flat blue zones */
171 buf_len <<= 1; /* we have 16bit values */
173 /* buffer length must be a multiple of four */
174 len = (buf_len + 3) & ~3;
175 buf = (FT_Byte*)malloc(len);
176 if (!buf)
177 return FT_Err_Out_Of_Memory;
179 /* pad end of buffer with zeros */
180 buf[len - 1] = 0x00;
181 buf[len - 2] = 0x00;
182 buf[len - 3] = 0x00;
184 bufp = buf;
187 * some CVT values are initialized (and modified) at runtime:
189 * (1) the `cvtl_xxx' values (see `tabytecode.h')
190 * (2) a scaling value for each style
191 * (3) offset and size of the vertical widths array
192 * (needed by `bci_{smooth,strong}_stem_width') for each style
194 for (i = 0; i < (cvtl_max_runtime
195 + data->num_used_styles
196 + 2 * data->num_used_styles) * 2; i++)
197 *(bufp++) = 0;
199 cvt_offset = bufp - buf;
201 /* loop again over all styles and copy CVT data */
202 for (i = 0; i < i_max; i++)
204 /* collect offsets */
205 data->cvt_offsets[i] = ((FT_UInt)(bufp - buf) - cvt_offset) >> 1;
207 error = TA_sfnt_compute_global_hints(sfnt, font, i);
208 if (error == TA_Err_Missing_Glyph)
209 continue;
210 if (error)
211 return error;
213 if (font->loader->hints.metrics->style_class == &ta_none_dflt_style_class)
215 haxis = NULL;
216 vaxis = NULL;
218 hwidth_count = 0;
219 vwidth_count = 0;
220 blue_count = 0;
222 else
224 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
225 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
227 hwidth_count = haxis->width_count;
228 vwidth_count = vaxis->width_count;
229 blue_count = vaxis->blue_count + 2; /* with artificial blue zones */
232 /* horizontal standard width */
233 if (hwidth_count > 0)
235 *(bufp++) = HIGH(haxis->widths[0].org);
236 *(bufp++) = LOW(haxis->widths[0].org);
238 else
240 *(bufp++) = 0;
241 *(bufp++) = 50;
244 for (j = 0; j < hwidth_count; j++)
246 if (haxis->widths[j].org > 0xFFFF)
247 goto Err;
248 *(bufp++) = HIGH(haxis->widths[j].org);
249 *(bufp++) = LOW(haxis->widths[j].org);
252 /* vertical standard width */
253 if (vwidth_count > 0)
255 *(bufp++) = HIGH(vaxis->widths[0].org);
256 *(bufp++) = LOW(vaxis->widths[0].org);
258 else
260 *(bufp++) = 0;
261 *(bufp++) = 50;
264 for (j = 0; j < vwidth_count; j++)
266 if (vaxis->widths[j].org > 0xFFFF)
267 goto Err;
268 *(bufp++) = HIGH(vaxis->widths[j].org);
269 *(bufp++) = LOW(vaxis->widths[j].org);
272 data->cvt_blue_adjustment_offsets[i] = 0xFFFFU;
274 for (j = 0; j < blue_count; j++)
276 if (vaxis->blues[j].ref.org > 0xFFFF)
277 goto Err;
278 *(bufp++) = HIGH(vaxis->blues[j].ref.org);
279 *(bufp++) = LOW(vaxis->blues[j].ref.org);
282 for (j = 0; j < blue_count; j++)
284 if (vaxis->blues[j].shoot.org > 0xFFFF)
285 goto Err;
286 *(bufp++) = HIGH(vaxis->blues[j].shoot.org);
287 *(bufp++) = LOW(vaxis->blues[j].shoot.org);
289 if (vaxis->blues[j].flags & TA_LATIN_BLUE_ADJUSTMENT)
290 data->cvt_blue_adjustment_offsets[i] = j;
293 data->cvt_horz_width_sizes[i] = hwidth_count;
294 data->cvt_vert_width_sizes[i] = vwidth_count;
295 data->cvt_blue_zone_sizes[i] = blue_count;
298 *cvt = buf;
299 *cvt_len = buf_len;
301 return FT_Err_Ok;
303 Err:
304 free(buf);
305 return TA_Err_Hinter_Overflow;
309 FT_Error
310 TA_sfnt_build_cvt_table(SFNT* sfnt,
311 FONT* font)
313 FT_Error error;
315 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
316 glyf_Data* data = (glyf_Data*)glyf_table->data;
318 FT_Byte* cvt_buf;
319 FT_ULong cvt_len;
322 error = TA_sfnt_add_table_info(sfnt);
323 if (error)
324 goto Exit;
326 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
327 if (glyf_table->processed)
329 sfnt->table_infos[sfnt->num_table_infos - 1] = data->cvt_idx;
330 goto Exit;
333 error = TA_table_build_cvt(&cvt_buf, &cvt_len, sfnt, font);
334 if (error)
335 goto Exit;
337 /* in case of success, `cvt_buf' gets linked */
338 /* and is eventually freed in `TA_font_unload' */
339 error = TA_font_add_table(font,
340 &sfnt->table_infos[sfnt->num_table_infos - 1],
341 TTAG_cvt, cvt_len, cvt_buf);
342 if (error)
343 free(cvt_buf);
344 else
345 data->cvt_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
347 Exit:
348 return error;
351 /* end of tacvt.c */