Move functions related to TTC creation into separate file.
[ttfautohint.git] / src / taglyf.c
blob38070594c588b8c6fb75e686c5d0856f8b0b4076
1 /* taglyf.c */
3 /*
4 * Copyright (C) 2011 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 FT_Error
20 TA_sfnt_build_glyf_hints(SFNT* sfnt,
21 FONT* font)
23 FT_Face face = sfnt->face;
24 FT_Long idx;
25 FT_Error error;
28 for (idx = 0; idx < face->num_glyphs; idx++)
30 error = TA_sfnt_build_glyph_instructions(sfnt, font, idx);
31 if (error)
32 return error;
33 if (font->progress)
34 font->progress(idx, face->num_glyphs,
35 sfnt - font->sfnts, font->num_sfnts,
36 font->progress_data);
39 return FT_Err_Ok;
43 static FT_Error
44 TA_glyph_parse_composite(GLYPH* glyph,
45 FT_Byte* buf,
46 FT_ULong len)
48 FT_ULong flags_offset; /* after the loop, this is the offset */
49 /* to the last element in the flags array */
50 FT_UShort flags;
52 FT_Byte* p;
53 FT_Byte* endp;
56 p = buf;
57 endp = buf + len;
59 /* skip header */
60 p += 10;
62 /* walk over component records */
65 if (p + 4 > endp)
66 return FT_Err_Invalid_Table;
68 flags_offset = p - buf;
70 flags = *(p++) << 8;
71 flags += *(p++);
73 /* skip glyph component index */
74 p += 2;
76 /* skip scaling and offset arguments */
77 if (flags & ARGS_ARE_WORDS)
78 p += 4;
79 else
80 p += 2;
82 if (flags & WE_HAVE_A_SCALE)
83 p += 2;
84 else if (flags & WE_HAVE_AN_XY_SCALE)
85 p += 4;
86 else if (flags & WE_HAVE_A_2X2)
87 p += 8;
88 } while (flags & MORE_COMPONENTS);
90 glyph->flags_offset = flags_offset;
92 /* adjust glyph record length */
93 len = p - buf;
95 glyph->len1 = len;
96 /* glyph->len2 = 0; */
97 glyph->buf = (FT_Byte*)malloc(len);
98 if (!glyph->buf)
99 return FT_Err_Out_Of_Memory;
101 /* copy record without instructions (if any) */
102 memcpy(glyph->buf, buf, len);
103 glyph->buf[flags_offset] &= ~(WE_HAVE_INSTR >> 8);
105 return TA_Err_Ok;
109 static FT_Error
110 TA_glyph_parse_simple(GLYPH* glyph,
111 FT_Byte* buf,
112 FT_UShort num_contours,
113 FT_ULong len)
115 FT_ULong ins_offset;
116 FT_Byte* flags_start;
118 FT_UShort num_ins;
119 FT_UShort num_pts;
121 FT_ULong flags_size; /* size of the flags array */
122 FT_ULong xy_size; /* size of x and y coordinate arrays together */
124 FT_Byte* p;
125 FT_Byte* endp;
127 FT_UShort i;
130 p = buf;
131 endp = buf + len;
133 ins_offset = 10 + num_contours * 2;
135 p += ins_offset;
137 if (p + 2 > endp)
138 return FT_Err_Invalid_Table;
140 /* get number of instructions */
141 num_ins = *(p++) << 8;
142 num_ins += *(p++);
144 p += num_ins;
146 if (p > endp)
147 return FT_Err_Invalid_Table;
149 /* get number of points from last outline point */
150 num_pts = buf[ins_offset - 2] << 8;
151 num_pts += buf[ins_offset - 1];
152 num_pts++;
154 flags_start = p;
155 xy_size = 0;
156 i = 0;
158 while (i < num_pts)
160 FT_Byte flags;
161 FT_Byte x_short;
162 FT_Byte y_short;
163 FT_Byte have_x;
164 FT_Byte have_y;
165 FT_Byte count;
168 if (p + 1 > endp)
169 return FT_Err_Invalid_Table;
171 flags = *(p++);
173 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
174 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
176 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
177 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
179 count = 1;
181 if (flags & REPEAT)
183 if (p + 1 > endp)
184 return FT_Err_Invalid_Table;
186 count += *(p++);
188 if (i + count > num_pts)
189 return FT_Err_Invalid_Table;
192 xy_size += count * x_short * have_x;
193 xy_size += count * y_short * have_y;
195 i += count;
198 if (p + xy_size > endp)
199 return FT_Err_Invalid_Table;
201 flags_size = p - flags_start;
203 /* store the data before and after the bytecode instructions */
204 /* in the same array */
205 glyph->len1 = ins_offset;
206 glyph->len2 = flags_size + xy_size;
207 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
208 if (!glyph->buf)
209 return FT_Err_Out_Of_Memory;
211 /* now copy everything but the instructions */
212 memcpy(glyph->buf, buf, glyph->len1);
213 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
215 return TA_Err_Ok;
219 FT_Error
220 TA_sfnt_split_glyf_table(SFNT* sfnt,
221 FONT* font)
223 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
224 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
225 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
227 glyf_Data* data;
228 FT_Byte loca_format;
230 FT_ULong offset;
231 FT_ULong offset_next;
233 FT_Byte* p;
234 FT_UShort i;
237 /* in case of success, all allocated arrays are */
238 /* linked and eventually freed in `TA_font_unload' */
240 /* nothing to do if table has already been split */
241 if (glyf_table->data)
242 return TA_Err_Ok;
244 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
245 if (!data)
246 return FT_Err_Out_Of_Memory;
248 glyf_table->data = data;
250 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
252 data->num_glyphs = loca_format ? loca_table->len / 4 - 1
253 : loca_table->len / 2 - 1;
254 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
255 if (!data->glyphs)
256 return FT_Err_Out_Of_Memory;
258 p = loca_table->buf;
260 if (loca_format)
262 offset_next = *(p++) << 24;
263 offset_next += *(p++) << 16;
264 offset_next += *(p++) << 8;
265 offset_next += *(p++);
267 else
269 offset_next = *(p++) << 8;
270 offset_next += *(p++);
271 offset_next <<= 1;
274 /* loop over `loca' and `glyf' data */
275 for (i = 0; i < data->num_glyphs; i++)
277 GLYPH* glyph = &data->glyphs[i];
278 FT_ULong len;
281 offset = offset_next;
283 if (loca_format)
285 offset_next = *(p++) << 24;
286 offset_next += *(p++) << 16;
287 offset_next += *(p++) << 8;
288 offset_next += *(p++);
290 else
292 offset_next = *(p++) << 8;
293 offset_next += *(p++);
294 offset_next <<= 1;
297 if (offset_next < offset
298 || offset_next > glyf_table->len)
299 return FT_Err_Invalid_Table;
301 len = offset_next - offset;
302 if (!len)
303 continue; /* empty glyph */
304 else
306 FT_Byte* buf;
307 FT_Short num_contours;
308 FT_Error error;
311 /* check header size */
312 if (len < 10)
313 return FT_Err_Invalid_Table;
315 buf = glyf_table->buf + offset;
316 num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
318 /* We must parse the rest of the glyph record to get the exact */
319 /* record length. Since the `loca' table rounds record lengths */
320 /* up to multiples of 4 (or 2 for older fonts), and we must round */
321 /* up again after stripping off the instructions, it would be */
322 /* possible otherwise to have more than 4 bytes of padding which */
323 /* is more or less invalid. */
325 if (num_contours < 0)
327 error = TA_glyph_parse_composite(glyph, buf, len);
328 if (error)
329 return error;
331 else
333 error = TA_glyph_parse_simple(glyph, buf, num_contours, len);
334 if (error)
335 return error;
340 return TA_Err_Ok;
344 FT_Error
345 TA_sfnt_build_glyf_table(SFNT* sfnt,
346 FONT* font)
348 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
349 glyf_Data* data = (glyf_Data*)glyf_table->data;
351 GLYPH* glyph;
353 FT_ULong len;
354 FT_Byte* buf_new;
355 FT_Byte* p;
356 FT_UShort i;
359 if (glyf_table->processed)
360 return TA_Err_Ok;
362 /* get table size */
363 len = 0;
364 glyph = data->glyphs;
365 for (i = 0; i < data->num_glyphs; i++, glyph++)
367 /* glyph records should have offsets which are multiples of 4 */
368 len = (len + 3) & ~3;
369 len += glyph->len1 + glyph->len2 + glyph->ins_len;
370 /* add two bytes for the instructionLength field */
371 if (glyph->len2 || glyph->ins_len)
372 len += 2;
375 /* to make the short format of the `loca' table always work, */
376 /* assure an even length of the `glyf' table */
377 glyf_table->len = (len + 1) & ~1;
379 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
380 if (!buf_new)
381 return FT_Err_Out_Of_Memory;
382 else
383 glyf_table->buf = buf_new;
385 p = glyf_table->buf;
386 glyph = data->glyphs;
387 for (i = 0; i < data->num_glyphs; i++, glyph++)
389 len = glyph->len1 + glyph->len2 + glyph->ins_len;
390 if (glyph->len2 || glyph->ins_len)
391 len += 2;
393 if (len)
395 /* copy glyph data and insert new instructions */
396 memcpy(p, glyph->buf, glyph->len1);
398 if (glyph->len2)
400 /* simple glyph */
401 p += glyph->len1;
402 *(p++) = HIGH(glyph->ins_len);
403 *(p++) = LOW(glyph->ins_len);
404 memcpy(p, glyph->ins_buf, glyph->ins_len);
405 p += glyph->ins_len;
406 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
407 p += glyph->len2;
409 else
411 /* composite glyph */
412 if (glyph->ins_len)
414 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
415 p += glyph->len1;
416 *(p++) = HIGH(glyph->ins_len);
417 *(p++) = LOW(glyph->ins_len);
418 memcpy(p, glyph->ins_buf, glyph->ins_len);
419 p += glyph->ins_len;
421 else
422 p += glyph->len1;
425 /* pad with zero bytes to have an offset which is a multiple of 4; */
426 /* this works even for the last glyph record since the `glyf' */
427 /* table length is a multiple of 4 also */
428 switch (len % 4)
430 case 1:
431 *(p++) = 0;
432 case 2:
433 *(p++) = 0;
434 case 3:
435 *(p++) = 0;
436 default:
437 break;
442 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
443 glyf_table->len);
444 glyf_table->processed = 1;
446 return TA_Err_Ok;
449 /* end of taglyf.c */