Use `Control_Type' to handle different segment directions.
[ttfautohint.git] / lib / tacvt.c
blob6078a691bf457335a5d817007fa245eff49d711f
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 TA_Style 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;
45 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
46 FT_Byte* gstyles = globals->glyph_styles;
48 TA_StyleClass style_class = ta_style_classes[style_idx];
49 TA_ScriptClass script_class = ta_script_classes[style_class->script];
51 TA_StyleMetricsRec dummy;
54 /* we don't have a `TA_Loader' object yet */
55 dummy.globals = globals;
56 dummy.style_class = style_class;
59 * We check more than a single standard character to catch features
60 * like `c2sc' (small caps from caps) that don't contain lowercase
61 * letters by definition, or other features that mainly operate on
62 * numerals.
64 ta_get_char_index(&dummy,
65 script_class->standard_char1,
66 &glyph_index,
67 &y_offset);
68 if (!glyph_index)
70 if (script_class->standard_char2)
72 ta_get_char_index(&dummy,
73 script_class->standard_char2,
74 &glyph_index,
75 &y_offset);
76 if (!glyph_index)
78 if (script_class->standard_char3)
79 ta_get_char_index(&dummy,
80 script_class->standard_char3,
81 &glyph_index,
82 &y_offset);
87 if (!glyph_index)
89 /* in case of a symbol font, */
90 /* we only proceed if a fallback style is set */
91 if (font->symbol
92 && font->fallback_style != TA_STYLE_NONE_DFLT
93 && font->fallback_style == style_idx)
94 goto Symbol;
95 return TA_Err_Missing_Glyph;
99 * We now know that HarfBuzz can access the standard character in the
100 * current OpenType feature. However, this doesn't guarantee that there
101 * actually *is* a standard character in the corresponding coverage,
102 * since glyphs shifted with data from the GPOS table are ignored in the
103 * coverage (but neverless used to derive stem widths). For this
104 * reason, search an arbitrary character from the current coverage to
105 * trigger the coverage's metrics computation.
107 if (gstyles[glyph_index] != style_idx)
109 FT_Int i;
112 for (i = 0; i < globals->glyph_count; i++)
114 if (gstyles[i] == style_idx)
115 break;
118 if (i == globals->glyph_count)
119 return TA_Err_Missing_Glyph;
121 glyph_index = i;
125 Symbol:
126 load_flags = 1 << 29; /* vertical hinting only */
127 error = ta_loader_load_glyph(font, face, glyph_index, load_flags);
129 return error;
133 static FT_Error
134 TA_table_build_cvt(FT_Byte** cvt,
135 FT_ULong* cvt_len,
136 SFNT* sfnt,
137 FONT* font)
139 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
140 glyf_Data* data = (glyf_Data*)glyf_table->data;
142 TA_LatinAxis haxis;
143 TA_LatinAxis vaxis;
145 FT_UInt hwidth_count;
146 FT_UInt vwidth_count;
147 FT_UInt blue_count;
149 FT_UInt i, j;
150 FT_UInt buf_len;
151 FT_UInt len;
152 FT_Byte* buf;
153 FT_Byte* bufp;
154 FT_UInt cvt_offset;
156 FT_Error error;
159 /* loop over all styles and collect the relevant CVT data */
160 /* to compute the necessary array sizes and meta-information */
161 hwidth_count = 0;
162 vwidth_count = 0;
163 blue_count = 0;
165 data->num_used_styles = 0;
167 for (i = 0; i < TA_STYLE_MAX; i++)
169 error = TA_sfnt_compute_global_hints(sfnt, font, (TA_Style)i);
170 if (error == TA_Err_Missing_Glyph)
172 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
173 FT_Byte* gstyles = globals->glyph_styles;
174 FT_Int nn;
177 data->style_ids[i] = 0xFFFFU;
179 /* remove all references to this style; */
180 /* otherwise blue zones are computed later on, which we don't want */
181 for (nn = 0; nn < globals->glyph_count; nn++)
183 if ((gstyles[nn] & ~TA_DIGIT) == i)
185 gstyles[nn] &= ~TA_STYLE_UNASSIGNED;
186 gstyles[nn] |= globals->font->fallback_style;
190 continue;
192 if (error)
193 return error;
195 data->style_ids[i] = data->num_used_styles++;
197 if (i == TA_STYLE_NONE_DFLT)
198 continue;
199 else
201 /* XXX: generalize this to handle other metrics also */
202 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
203 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
205 hwidth_count += haxis->width_count;
206 vwidth_count += vaxis->width_count;
207 /* there are two artificial blue zones at the end of the array */
208 /* that are not part of `vaxis->blue_count' */
209 blue_count += vaxis->blue_count + 2;
213 /* exit if the font doesn't contain a single supported style, */
214 /* and we don't have a symbol font */
215 if (!data->num_used_styles && !font->symbol)
216 return TA_Err_Missing_Glyph;
218 buf_len = cvtl_max_runtime /* runtime values 1 */
219 + data->num_used_styles /* runtime values 2 (for scaling) */
220 + 2 * data->num_used_styles /* runtime values 3 (blue data) */
221 + 2 * data->num_used_styles /* vert. and horiz. std. widths */
222 + hwidth_count
223 + vwidth_count
224 + 2 * blue_count; /* round and flat blue zones */
225 buf_len <<= 1; /* we have 16bit values */
227 /* buffer length must be a multiple of four */
228 len = (buf_len + 3) & ~3;
229 buf = (FT_Byte*)malloc(len);
230 if (!buf)
231 return FT_Err_Out_Of_Memory;
233 /* pad end of buffer with zeros */
234 buf[len - 1] = 0x00;
235 buf[len - 2] = 0x00;
236 buf[len - 3] = 0x00;
238 bufp = buf;
241 * some CVT values are initialized (and modified) at runtime:
243 * (1) the `cvtl_xxx' values (see `tabytecode.h')
244 * (2) a scaling value for each style
245 * (3) offset and size of the vertical widths array
246 * (needed by `bci_{smooth,strong}_stem_width') for each style
248 for (i = 0; i < (cvtl_max_runtime
249 + data->num_used_styles
250 + 2 * data->num_used_styles) * 2; i++)
251 *(bufp++) = 0;
253 cvt_offset = bufp - buf;
255 /* loop again over all styles and copy CVT data */
256 for (i = 0; i < TA_STYLE_MAX; i++)
258 FT_UInt default_width = 50 * sfnt->face->units_per_EM / 2048;
261 /* collect offsets */
262 data->cvt_offsets[i] = ((FT_UInt)(bufp - buf) - cvt_offset) >> 1;
264 error = TA_sfnt_compute_global_hints(sfnt, font, (TA_Style)i);
265 if (error == TA_Err_Missing_Glyph)
266 continue;
267 if (error)
268 return error;
270 if (font->loader->hints.metrics->style_class == &ta_none_dflt_style_class)
272 haxis = NULL;
273 vaxis = NULL;
275 hwidth_count = 0;
276 vwidth_count = 0;
277 blue_count = 0;
279 else
281 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
282 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
284 hwidth_count = haxis->width_count;
285 vwidth_count = vaxis->width_count;
286 blue_count = vaxis->blue_count + 2; /* with artificial blue zones */
289 /* horizontal standard width */
290 if (hwidth_count > 0)
292 *(bufp++) = HIGH(haxis->widths[0].org);
293 *(bufp++) = LOW(haxis->widths[0].org);
295 else
297 *(bufp++) = HIGH(default_width);
298 *(bufp++) = LOW(default_width);
301 for (j = 0; j < hwidth_count; j++)
303 if (haxis->widths[j].org > 0xFFFF)
304 goto Err;
305 *(bufp++) = HIGH(haxis->widths[j].org);
306 *(bufp++) = LOW(haxis->widths[j].org);
309 /* vertical standard width */
310 if (vwidth_count > 0)
312 *(bufp++) = HIGH(vaxis->widths[0].org);
313 *(bufp++) = LOW(vaxis->widths[0].org);
315 else
317 *(bufp++) = HIGH(default_width);
318 *(bufp++) = LOW(default_width);
321 for (j = 0; j < vwidth_count; j++)
323 if (vaxis->widths[j].org > 0xFFFF)
324 goto Err;
325 *(bufp++) = HIGH(vaxis->widths[j].org);
326 *(bufp++) = LOW(vaxis->widths[j].org);
329 data->cvt_blue_adjustment_offsets[i] = 0xFFFFU;
331 for (j = 0; j < blue_count; j++)
333 if (vaxis->blues[j].ref.org > 0xFFFF)
334 goto Err;
335 *(bufp++) = HIGH(vaxis->blues[j].ref.org);
336 *(bufp++) = LOW(vaxis->blues[j].ref.org);
339 for (j = 0; j < blue_count; j++)
341 if (vaxis->blues[j].shoot.org > 0xFFFF)
342 goto Err;
343 *(bufp++) = HIGH(vaxis->blues[j].shoot.org);
344 *(bufp++) = LOW(vaxis->blues[j].shoot.org);
346 if (vaxis->blues[j].flags & TA_LATIN_BLUE_ADJUSTMENT)
347 data->cvt_blue_adjustment_offsets[i] = j;
350 data->cvt_horz_width_sizes[i] = hwidth_count;
351 data->cvt_vert_width_sizes[i] = vwidth_count;
352 data->cvt_blue_zone_sizes[i] = blue_count;
355 *cvt = buf;
356 *cvt_len = buf_len;
358 return FT_Err_Ok;
360 Err:
361 free(buf);
362 return TA_Err_Hinter_Overflow;
366 FT_Error
367 TA_sfnt_build_cvt_table(SFNT* sfnt,
368 FONT* font)
370 FT_Error error;
372 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
373 glyf_Data* data = (glyf_Data*)glyf_table->data;
375 FT_Byte* cvt_buf;
376 FT_ULong cvt_len;
379 error = TA_sfnt_add_table_info(sfnt);
380 if (error)
381 goto Exit;
383 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
384 if (glyf_table->processed)
386 sfnt->table_infos[sfnt->num_table_infos - 1] = data->cvt_idx;
387 goto Exit;
390 error = TA_table_build_cvt(&cvt_buf, &cvt_len, sfnt, font);
391 if (error)
392 goto Exit;
394 /* in case of success, `cvt_buf' gets linked */
395 /* and is eventually freed in `TA_font_unload' */
396 error = TA_font_add_table(font,
397 &sfnt->table_infos[sfnt->num_table_infos - 1],
398 TTAG_cvt, cvt_len, cvt_buf);
399 if (error)
400 free(cvt_buf);
401 else
402 data->cvt_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
404 Exit:
405 return error;
408 /* end of tacvt.c */