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.
20 TA_sfnt_build_glyf_hints(SFNT
* sfnt
,
23 FT_Face face
= sfnt
->face
;
28 for (idx
= 0; idx
< face
->num_glyphs
; idx
++)
30 error
= TA_sfnt_build_glyph_instructions(sfnt
, font
, idx
);
34 font
->progress(idx
, face
->num_glyphs
,
35 sfnt
- font
->sfnts
, font
->num_sfnts
,
44 TA_glyph_parse_composite(GLYPH
* glyph
,
48 FT_ULong flags_offset
; /* after the loop, this is the offset */
49 /* to the last element in the flags array */
62 /* walk over component records */
66 return FT_Err_Invalid_Table
;
68 flags_offset
= p
- buf
;
73 /* skip glyph component index */
76 /* skip scaling and offset arguments */
77 if (flags
& ARGS_ARE_WORDS
)
82 if (flags
& WE_HAVE_A_SCALE
)
84 else if (flags
& WE_HAVE_AN_XY_SCALE
)
86 else if (flags
& WE_HAVE_A_2X2
)
88 } while (flags
& MORE_COMPONENTS
);
90 glyph
->flags_offset
= flags_offset
;
92 /* adjust glyph record length */
96 /* glyph->len2 = 0; */
97 glyph
->buf
= (FT_Byte
*)malloc(len
);
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);
110 TA_glyph_parse_simple(GLYPH
* glyph
,
112 FT_UShort num_contours
,
116 FT_Byte
* flags_start
;
121 FT_ULong flags_size
; /* size of the flags array */
122 FT_ULong xy_size
; /* size of x and y coordinate arrays together */
133 ins_offset
= 10 + num_contours
* 2;
138 return FT_Err_Invalid_Table
;
140 /* get number of instructions */
141 num_ins
= *(p
++) << 8;
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];
169 return FT_Err_Invalid_Table
;
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;
184 return FT_Err_Invalid_Table
;
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
;
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
);
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
);
220 TA_sfnt_split_glyf_table(SFNT
* sfnt
,
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
];
231 FT_ULong offset_next
;
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
)
244 data
= (glyf_Data
*)calloc(1, sizeof (glyf_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
));
256 return FT_Err_Out_Of_Memory
;
262 offset_next
= *(p
++) << 24;
263 offset_next
+= *(p
++) << 16;
264 offset_next
+= *(p
++) << 8;
265 offset_next
+= *(p
++);
269 offset_next
= *(p
++) << 8;
270 offset_next
+= *(p
++);
274 /* loop over `loca' and `glyf' data */
275 for (i
= 0; i
< data
->num_glyphs
; i
++)
277 GLYPH
* glyph
= &data
->glyphs
[i
];
281 offset
= offset_next
;
285 offset_next
= *(p
++) << 24;
286 offset_next
+= *(p
++) << 16;
287 offset_next
+= *(p
++) << 8;
288 offset_next
+= *(p
++);
292 offset_next
= *(p
++) << 8;
293 offset_next
+= *(p
++);
297 if (offset_next
< offset
298 || offset_next
> glyf_table
->len
)
299 return FT_Err_Invalid_Table
;
301 len
= offset_next
- offset
;
303 continue; /* empty glyph */
307 FT_Short num_contours
;
311 /* check header size */
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
);
333 error
= TA_glyph_parse_simple(glyph
, buf
, num_contours
, len
);
345 TA_sfnt_build_glyf_table(SFNT
* sfnt
,
348 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
349 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
359 if (glyf_table
->processed
)
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
)
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);
381 return FT_Err_Out_Of_Memory
;
383 glyf_table
->buf
= buf_new
;
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
)
395 /* copy glyph data and insert new instructions */
396 memcpy(p
, glyph
->buf
, glyph
->len1
);
402 *(p
++) = HIGH(glyph
->ins_len
);
403 *(p
++) = LOW(glyph
->ins_len
);
404 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
406 memcpy(p
, glyph
->buf
+ glyph
->len1
, glyph
->len2
);
411 /* composite glyph */
414 *(p
+ glyph
->flags_offset
) |= (WE_HAVE_INSTR
>> 8);
416 *(p
++) = HIGH(glyph
->ins_len
);
417 *(p
++) = LOW(glyph
->ins_len
);
418 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
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 */
442 glyf_table
->checksum
= TA_table_compute_checksum(glyf_table
->buf
,
444 glyf_table
->processed
= 1;
449 /* end of taglyf.c */