Fix OTS warning about `maxp.maxSizeOfInstructions`.
[ttfautohint.git] / lib / tacvt.c
blobf0036e2bf9f696c769b23903b580a0e950f99068
1 /* tacvt.c */
3 /*
4 * Copyright (C) 2011-2022 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 TA_Style style_idx)
24 FT_Error error;
25 FT_Face face = sfnt->face;
26 FT_Int32 load_flags;
28 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
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 (!globals->sample_glyphs[style_idx])
45 return TA_Err_Missing_Glyph;
47 /* trigger computation of the current coverage's metrics */
48 load_flags = 1 << 29; /* vertical hinting only */
49 return ta_loader_load_glyph(font,
50 face,
51 globals->sample_glyphs[style_idx],
52 load_flags);
56 static FT_Error
57 TA_table_build_cvt(FT_Byte** cvt,
58 FT_ULong* cvt_len,
59 SFNT* sfnt,
60 FONT* font)
62 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
63 glyf_Data* data = (glyf_Data*)glyf_table->data;
65 TA_LatinAxis haxis;
66 TA_LatinAxis vaxis;
68 FT_UInt hwidth_count;
69 FT_UInt vwidth_count;
70 FT_UInt blue_count;
72 FT_UInt i, j;
73 FT_UInt buf_len;
74 FT_UInt len;
75 FT_Byte* buf;
76 FT_Byte* bufp;
77 FT_UInt cvt_offset;
79 FT_Error error;
82 /* loop over all styles and collect the relevant CVT data */
83 /* to compute the necessary array sizes and meta-information */
84 hwidth_count = 0;
85 vwidth_count = 0;
86 blue_count = 0;
88 data->num_used_styles = 0;
90 for (i = 0; i < TA_STYLE_MAX; i++)
92 error = TA_sfnt_compute_global_hints(sfnt, font, (TA_Style)i);
93 if (error == TA_Err_Missing_Glyph)
95 data->style_ids[i] = 0xFFFFU;
96 continue;
98 else if (error)
99 return error;
101 /* XXX: generalize this to handle other metrics also */
102 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
103 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
105 if (!vaxis->blue_count)
107 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
108 FT_UShort* gstyles = globals->glyph_styles;
109 FT_Int nn;
112 data->style_ids[i] = 0xFFFFU;
113 globals->sample_glyphs[i] = 0;
115 /* remove all references to this style; we have no blue zone data */
116 for (nn = 0; nn < globals->glyph_count; nn++)
118 if ((gstyles[nn] & TA_STYLE_MASK) == i)
120 gstyles[nn] &= ~TA_STYLE_MASK;
121 gstyles[nn] |= globals->font->fallback_style;
125 continue;
128 data->style_ids[i] = data->num_used_styles++;
130 hwidth_count += haxis->width_count;
131 vwidth_count += vaxis->width_count;
133 blue_count += vaxis->blue_count;
134 /* if windows compatibility mode is active */
135 /* we add two artificial blue zones at the end of the array */
136 /* that are not part of `vaxis->blue_count' */
137 if (font->windows_compatibility)
138 blue_count += 2;
141 /* exit if the font doesn't contain a single supported style, */
142 /* and we don't have a symbol font */
143 if (!data->num_used_styles && !font->symbol)
144 return TA_Err_Missing_Glyph;
146 buf_len = cvtl_max_runtime /* runtime values 1 */
147 + data->num_used_styles /* runtime values 2 (for scaling) */
148 + 2 * data->num_used_styles /* runtime values 3 (blue data) */
149 + 2 * data->num_used_styles /* vert. and horiz. std. widths */
150 + hwidth_count
151 + vwidth_count
152 + 2 * blue_count; /* round and flat blue zones */
153 buf_len <<= 1; /* we have 16bit values */
155 /* buffer length must be a multiple of four */
156 len = (buf_len + 3) & ~3U;
157 buf = (FT_Byte*)malloc(len);
158 if (!buf)
159 return FT_Err_Out_Of_Memory;
161 /* pad end of buffer with zeros */
162 buf[len - 1] = 0x00;
163 buf[len - 2] = 0x00;
164 buf[len - 3] = 0x00;
166 bufp = buf;
169 * some CVT values are initialized (and modified) at runtime:
171 * (1) the `cvtl_xxx' values (see `tabytecode.h')
172 * (2) a scaling value for each style
173 * (3) offset and size of the vertical widths array
174 * (needed by `bci_{smooth,strong}_stem_width') for each style
176 for (i = 0; i < (cvtl_max_runtime
177 + data->num_used_styles
178 + 2 * data->num_used_styles) * 2; i++)
179 *(bufp++) = 0;
181 cvt_offset = (FT_UInt)(bufp - buf);
183 /* loop again over all styles and copy CVT data */
184 for (i = 0; i < TA_STYLE_MAX; i++)
186 FT_UInt default_width = 50 * sfnt->face->units_per_EM / 2048;
189 /* collect offsets */
190 data->cvt_offsets[i] = ((FT_UInt)(bufp - buf) - cvt_offset) >> 1;
192 error = TA_sfnt_compute_global_hints(sfnt, font, (TA_Style)i);
193 if (error == TA_Err_Missing_Glyph)
194 continue;
195 else if (error)
196 return error;
198 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
199 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
201 if (!vaxis->blue_count)
202 continue;
204 hwidth_count = haxis->width_count;
205 vwidth_count = vaxis->width_count;
207 blue_count = vaxis->blue_count;
208 if (font->windows_compatibility)
209 blue_count += 2; /* with artificial blue zones */
211 /* horizontal standard width */
212 if (hwidth_count > 0)
214 *(bufp++) = HIGH(haxis->widths[0].org);
215 *(bufp++) = LOW(haxis->widths[0].org);
217 else
219 *(bufp++) = HIGH(default_width);
220 *(bufp++) = LOW(default_width);
223 for (j = 0; j < hwidth_count; j++)
225 if (haxis->widths[j].org > 0xFFFF)
226 goto Err;
227 *(bufp++) = HIGH(haxis->widths[j].org);
228 *(bufp++) = LOW(haxis->widths[j].org);
231 /* vertical standard width */
232 if (vwidth_count > 0)
234 *(bufp++) = HIGH(vaxis->widths[0].org);
235 *(bufp++) = LOW(vaxis->widths[0].org);
237 else
239 *(bufp++) = HIGH(default_width);
240 *(bufp++) = LOW(default_width);
243 for (j = 0; j < vwidth_count; j++)
245 if (vaxis->widths[j].org > 0xFFFF)
246 goto Err;
247 *(bufp++) = HIGH(vaxis->widths[j].org);
248 *(bufp++) = LOW(vaxis->widths[j].org);
251 data->cvt_blue_adjustment_offsets[i] = 0xFFFFU;
253 for (j = 0; j < blue_count; j++)
255 if (vaxis->blues[j].ref.org > 0xFFFF)
256 goto Err;
257 *(bufp++) = HIGH(vaxis->blues[j].ref.org);
258 *(bufp++) = LOW(vaxis->blues[j].ref.org);
261 for (j = 0; j < blue_count; j++)
263 if (vaxis->blues[j].shoot.org > 0xFFFF)
264 goto Err;
265 *(bufp++) = HIGH(vaxis->blues[j].shoot.org);
266 *(bufp++) = LOW(vaxis->blues[j].shoot.org);
268 if (vaxis->blues[j].flags & TA_LATIN_BLUE_ADJUSTMENT)
269 data->cvt_blue_adjustment_offsets[i] = j;
272 data->cvt_horz_width_sizes[i] = hwidth_count;
273 data->cvt_vert_width_sizes[i] = vwidth_count;
274 data->cvt_blue_zone_sizes[i] = blue_count;
277 *cvt = buf;
278 *cvt_len = buf_len;
280 return FT_Err_Ok;
282 Err:
283 free(buf);
284 return TA_Err_Hinter_Overflow;
288 FT_Error
289 TA_sfnt_build_cvt_table(SFNT* sfnt,
290 FONT* font)
292 FT_Error error;
294 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
295 glyf_Data* data = (glyf_Data*)glyf_table->data;
297 FT_Byte* cvt_buf;
298 FT_ULong cvt_len;
301 error = TA_sfnt_add_table_info(sfnt);
302 if (error)
303 goto Exit;
305 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
306 if (glyf_table->processed)
308 sfnt->table_infos[sfnt->num_table_infos - 1] = data->cvt_idx;
309 goto Exit;
312 error = TA_table_build_cvt(&cvt_buf, &cvt_len, sfnt, font);
313 if (error)
314 goto Exit;
316 /* in case of success, `cvt_buf' gets linked */
317 /* and is eventually freed in `TA_font_unload' */
318 error = TA_font_add_table(font,
319 &sfnt->table_infos[sfnt->num_table_infos - 1],
320 TTAG_cvt, cvt_len, cvt_buf);
321 if (error)
322 free(cvt_buf);
323 else
324 data->cvt_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
326 Exit:
327 return error;
330 /* end of tacvt.c */