Add some overflow checks.
[ttfautohint.git] / src / taglyf.c
blobfc55702ceba12c82d94d5eedf60a3a25f28492f6
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 /* this loop doesn't include the artificial `.ttfautohint' glyph */
29 for (idx = 0; idx < face->num_glyphs; idx++)
31 error = TA_sfnt_build_glyph_instructions(sfnt, font, idx);
32 if (error)
33 return error;
34 if (font->progress)
35 font->progress(idx, face->num_glyphs,
36 sfnt - font->sfnts, font->num_sfnts,
37 font->progress_data);
40 return FT_Err_Ok;
44 static FT_Error
45 TA_glyph_get_components(GLYPH* glyph,
46 FT_Byte* buf,
47 FT_ULong len)
49 FT_UShort flags;
50 FT_UShort component;
51 FT_UShort* components_new;
53 FT_Byte* p;
54 FT_Byte* endp;
57 p = buf;
58 endp = buf + len;
60 /* skip header */
61 p += 10;
63 /* walk over component records */
66 if (p + 4 > endp)
67 return FT_Err_Invalid_Table;
69 flags = *(p++) << 8;
70 flags += *(p++);
72 /* add component to list */
73 component = *(p++) << 8;
74 component += *(p++);
76 glyph->num_components++;
77 components_new = (FT_UShort*)realloc(glyph->components,
78 glyph->num_components
79 * sizeof (FT_UShort));
80 if (!components_new)
82 glyph->num_components--;
83 return FT_Err_Out_Of_Memory;
85 else
86 glyph->components = components_new;
88 glyph->components[glyph->num_components - 1] = component;
90 /* skip scaling and offset arguments */
91 if (flags & ARGS_ARE_WORDS)
92 p += 4;
93 else
94 p += 2;
96 if (flags & WE_HAVE_A_SCALE)
97 p += 2;
98 else if (flags & WE_HAVE_AN_XY_SCALE)
99 p += 4;
100 else if (flags & WE_HAVE_A_2X2)
101 p += 8;
102 } while (flags & MORE_COMPONENTS);
104 return TA_Err_Ok;
108 static FT_Error
109 TA_glyph_parse_composite(GLYPH* glyph,
110 FT_Byte* buf,
111 FT_UShort num_glyphs)
113 FT_ULong flags_offset; /* after the loop, this is the offset */
114 /* to the last element in the flags array */
115 FT_UShort flags;
117 FT_Byte* p;
118 FT_ULong new_len;
121 p = buf;
123 /* skip header */
124 p += 10;
126 /* walk over component records */
129 flags_offset = p - buf;
131 flags = *(p++) << 8;
132 flags += *(p++);
134 /* skip component */
135 p += 2;
137 /* skip scaling and offset arguments */
138 if (flags & ARGS_ARE_WORDS)
139 p += 4;
140 else
141 p += 2;
143 /* XXX adjust point indices for !ARGS_ARE_XY_VALUES */
145 if (flags & WE_HAVE_A_SCALE)
146 p += 2;
147 else if (flags & WE_HAVE_AN_XY_SCALE)
148 p += 4;
149 else if (flags & WE_HAVE_A_2X2)
150 p += 8;
151 } while (flags & MORE_COMPONENTS);
153 /* we prepend a composite glyph component to call some bytecode */
154 /* which eventually becomes the last glyph in the `glyf' table; */
155 /* for convenience, however, it is not added to the `components' array */
156 /* (doing so simplifies the conversion of point indices later on) */
158 /* adjust glyph record length (6 bytes for the additional component) */
159 new_len = p - buf + 6;
161 glyph->flags_offset = flags_offset + 6;
163 glyph->len1 = new_len;
164 /* glyph->len2 = 0; */
165 glyph->buf = (FT_Byte*)malloc(new_len);
166 if (!glyph->buf)
167 return FT_Err_Out_Of_Memory;
169 /* copy record without instructions (if any) */
170 /* and construct additional component */
172 memcpy(glyph->buf, buf, 10); /* header */
174 glyph->buf[10] = 0x00; /* additional component */
175 glyph->buf[11] = ARGS_ARE_XY_VALUES | MORE_COMPONENTS;
176 glyph->buf[12] = HIGH(num_glyphs - 1);
177 glyph->buf[13] = LOW(num_glyphs - 1);
178 glyph->buf[14] = 0x00;
179 glyph->buf[15] = 0x00;
181 memcpy(glyph->buf + 16, buf + 10, new_len - 6 - 10); /* the rest */
183 glyph->buf[glyph->flags_offset] &= ~(WE_HAVE_INSTR >> 8);
185 return TA_Err_Ok;
189 static FT_Error
190 TA_glyph_parse_simple(GLYPH* glyph,
191 FT_Byte* buf,
192 FT_ULong len)
194 FT_ULong ins_offset;
195 FT_Byte* flags_start;
197 FT_UShort num_ins;
199 FT_ULong flags_size; /* size of the flags array */
200 FT_ULong xy_size; /* size of x and y coordinate arrays together */
202 FT_Byte* p;
203 FT_Byte* endp;
205 FT_UShort i;
208 p = buf;
209 endp = buf + len;
211 ins_offset = 10 + glyph->num_contours * 2;
213 p += ins_offset;
215 if (p + 2 > endp)
216 return FT_Err_Invalid_Table;
218 /* get number of instructions */
219 num_ins = *(p++) << 8;
220 num_ins += *(p++);
222 p += num_ins;
224 if (p > endp)
225 return FT_Err_Invalid_Table;
227 flags_start = p;
228 xy_size = 0;
229 i = 0;
231 while (i < glyph->num_points)
233 FT_Byte flags;
234 FT_Byte x_short;
235 FT_Byte y_short;
236 FT_Byte have_x;
237 FT_Byte have_y;
238 FT_Byte count;
241 if (p + 1 > endp)
242 return FT_Err_Invalid_Table;
244 flags = *(p++);
246 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
247 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
249 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
250 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
252 count = 1;
254 if (flags & REPEAT)
256 if (p + 1 > endp)
257 return FT_Err_Invalid_Table;
259 count += *(p++);
261 if (i + count > glyph->num_points)
262 return FT_Err_Invalid_Table;
265 xy_size += count * x_short * have_x;
266 xy_size += count * y_short * have_y;
268 i += count;
271 if (p + xy_size > endp)
272 return FT_Err_Invalid_Table;
274 flags_size = p - flags_start;
276 /* store the data before and after the bytecode instructions */
277 /* in the same array */
278 glyph->len1 = ins_offset;
279 glyph->len2 = flags_size + xy_size;
280 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
281 if (!glyph->buf)
282 return FT_Err_Out_Of_Memory;
284 /* now copy everything but the instructions */
285 memcpy(glyph->buf, buf, glyph->len1);
286 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
288 return TA_Err_Ok;
292 static FT_Error
293 TA_iterate_composite_glyph(glyf_Data* data,
294 FT_UShort* components,
295 FT_UShort num_components,
296 FT_UShort** pointsums,
297 FT_UShort* num_pointsums,
298 FT_UShort* num_composite_contours,
299 FT_UShort* num_composite_points)
301 FT_UShort* pointsums_new;
302 FT_UShort i;
305 /* save current state */
307 if (*num_pointsums == 0xFFFF)
308 return FT_Err_Invalid_Table;
310 (*num_pointsums)++;
311 pointsums_new = (FT_UShort*)realloc(*pointsums,
312 *num_pointsums
313 * sizeof (FT_UShort));
314 if (!pointsums_new)
316 (*num_pointsums)--;
317 return FT_Err_Out_Of_Memory;
319 else
320 *pointsums = pointsums_new;
322 (*pointsums)[*num_pointsums - 1] = *num_composite_points;
324 for (i = 0; i < num_components; i++)
326 GLYPH* glyph;
327 FT_UShort component = components[i];
328 FT_Error error;
331 if (component >= data->num_glyphs)
332 return FT_Err_Invalid_Table;
334 glyph = &data->glyphs[component];
336 if (glyph->num_components)
338 error = TA_iterate_composite_glyph(data,
339 glyph->components,
340 glyph->num_components,
341 pointsums,
342 num_pointsums,
343 num_composite_contours,
344 num_composite_points);
345 if (error)
346 return error;
348 else
350 /* no need for checking overflow of the number of contours */
351 /* since the number of points is always larger or equal */
352 if (*num_composite_points > 0xFFFF - glyph->num_points)
353 return FT_Err_Invalid_Table;
355 *num_composite_contours += glyph->num_contours;
356 *num_composite_points += glyph->num_points;
360 return TA_Err_Ok;
364 static FT_Error
365 TA_sfnt_compute_composite_pointsums(SFNT* sfnt,
366 FONT* font)
368 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
369 glyf_Data* data = (glyf_Data*)glyf_table->data;
371 FT_UShort i;
374 for (i = 0; i < data->num_glyphs; i++)
376 GLYPH* glyph = &data->glyphs[i];
379 if (glyph->num_components)
381 FT_Error error;
382 FT_UShort num_composite_contours = 0;
383 FT_UShort num_composite_points = 0;
386 error = TA_iterate_composite_glyph(data,
387 glyph->components,
388 glyph->num_components,
389 &glyph->pointsums,
390 &glyph->num_pointsums,
391 &num_composite_contours,
392 &num_composite_points);
393 if (error)
394 return error;
396 /* update maximum values, */
397 /* including the subglyphs not in `components' array */
398 /* (each of them has a single point in a single contour) */
399 if (num_composite_points + glyph->num_pointsums
400 > sfnt->max_composite_points)
401 sfnt->max_composite_points = num_composite_points
402 + glyph->num_pointsums;
403 if (num_composite_contours + glyph->num_pointsums
404 > sfnt->max_composite_contours)
405 sfnt->max_composite_contours = num_composite_contours
406 + glyph->num_pointsums;
410 return TA_Err_Ok;
414 FT_Error
415 TA_sfnt_split_glyf_table(SFNT* sfnt,
416 FONT* font)
418 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
419 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
420 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
422 glyf_Data* data;
423 FT_Byte loca_format;
425 FT_ULong offset;
426 FT_ULong offset_next;
428 FT_Byte* p;
429 FT_UShort i;
430 FT_UShort loop_count;
432 FT_Error error;
435 /* in case of success, all allocated arrays are */
436 /* linked and eventually freed in `TA_font_unload' */
438 /* nothing to do if table has already been split */
439 if (glyf_table->data)
440 return TA_Err_Ok;
442 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
443 if (!data)
444 return FT_Err_Out_Of_Memory;
446 glyf_table->data = data;
448 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
450 data->num_glyphs = loca_format ? loca_table->len / 4
451 : loca_table->len / 2;
452 loop_count = data->num_glyphs - 1;
454 /* allocate one more glyph slot if we have composite glyphs */
455 if (!sfnt->max_components)
456 data->num_glyphs -= 1;
457 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
458 if (!data->glyphs)
459 return FT_Err_Out_Of_Memory;
461 /* first loop over `loca' and `glyf' data */
463 p = loca_table->buf;
465 if (loca_format)
467 offset_next = *(p++) << 24;
468 offset_next += *(p++) << 16;
469 offset_next += *(p++) << 8;
470 offset_next += *(p++);
472 else
474 offset_next = *(p++) << 8;
475 offset_next += *(p++);
476 offset_next <<= 1;
479 for (i = 0; i < loop_count; i++)
481 GLYPH* glyph = &data->glyphs[i];
482 FT_ULong len;
485 offset = offset_next;
487 if (loca_format)
489 offset_next = *(p++) << 24;
490 offset_next += *(p++) << 16;
491 offset_next += *(p++) << 8;
492 offset_next += *(p++);
494 else
496 offset_next = *(p++) << 8;
497 offset_next += *(p++);
498 offset_next <<= 1;
501 if (offset_next < offset
502 || offset_next > glyf_table->len)
503 return FT_Err_Invalid_Table;
505 len = offset_next - offset;
506 if (!len)
507 continue; /* empty glyph */
508 else
510 FT_Byte* buf;
513 /* check header size */
514 if (len < 10)
515 return FT_Err_Invalid_Table;
517 /* we need the number of contours and points for */
518 /* `TA_sfnt_compute_composite_pointsums' */
519 buf = glyf_table->buf + offset;
520 glyph->num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
522 if (glyph->num_contours < 0)
524 error = TA_glyph_get_components(glyph, buf, len);
525 if (error)
526 return error;
528 else
530 FT_ULong off;
533 /* use the last contour's end point to compute number of points */
534 off = 10 + (glyph->num_contours - 1) * 2;
535 glyph->num_points = buf[off] << 8;
536 glyph->num_points += buf[off + 1] + 1;
541 if (sfnt->max_components)
543 error = TA_sfnt_compute_composite_pointsums(sfnt, font);
544 if (error)
545 return error;
548 /* second loop over `loca' and `glyf' data */
550 p = loca_table->buf;
552 if (loca_format)
554 offset_next = *(p++) << 24;
555 offset_next += *(p++) << 16;
556 offset_next += *(p++) << 8;
557 offset_next += *(p++);
559 else
561 offset_next = *(p++) << 8;
562 offset_next += *(p++);
563 offset_next <<= 1;
566 for (i = 0; i < loop_count; i++)
568 GLYPH* glyph = &data->glyphs[i];
569 FT_ULong len;
572 offset = offset_next;
574 if (loca_format)
576 offset_next = *(p++) << 24;
577 offset_next += *(p++) << 16;
578 offset_next += *(p++) << 8;
579 offset_next += *(p++);
581 else
583 offset_next = *(p++) << 8;
584 offset_next += *(p++);
585 offset_next <<= 1;
588 len = offset_next - offset;
589 if (!len)
590 continue; /* empty glyph */
591 else
593 FT_Byte* buf;
596 buf = glyf_table->buf + offset;
598 /* We must parse the rest of the glyph record to get the exact */
599 /* record length. Since the `loca' table rounds record lengths */
600 /* up to multiples of 4 (or 2 for older fonts), and we must round */
601 /* up again after stripping off the instructions, it would be */
602 /* possible otherwise to have more than 4 bytes of padding which */
603 /* is more or less invalid. */
605 if (glyph->num_contours < 0)
606 error = TA_glyph_parse_composite(glyph, buf, data->num_glyphs);
607 else
608 error = TA_glyph_parse_simple(glyph, buf, len);
609 if (error)
610 return error;
614 if (sfnt->max_components)
616 /* construct and append our special glyph used as a composite element */
617 GLYPH* glyph = &data->glyphs[data->num_glyphs - 1];
618 FT_Byte* buf;
620 FT_Byte bytecode[] = {
622 /* increment `cvtl_is_subglyph' counter */
623 PUSHB_3,
624 cvtl_is_subglyph,
626 cvtl_is_subglyph,
627 RCVT,
628 ADD,
629 WCVTP,
633 glyph->len1 = 12;
634 glyph->len2 = 1;
635 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
636 if (!glyph->buf)
637 return FT_Err_Out_Of_Memory;
639 buf = glyph->buf;
641 buf[0] = 0x00; /* one contour */
642 buf[1] = 0x01;
643 buf[2] = 0x00; /* no dimensions */
644 buf[3] = 0x00;
645 buf[4] = 0x00;
646 buf[5] = 0x00;
647 buf[6] = 0x00;
648 buf[7] = 0x00;
649 buf[8] = 0x00;
650 buf[9] = 0x00;
651 buf[10] = 0x00; /* one contour end point */
652 buf[11] = 0x00;
654 buf[12] = ON_CURVE | SAME_X | SAME_Y; /* the flags for a point at 0,0 */
656 /* add bytecode also; */
657 /* this works because the loop in `TA_sfnt_build_glyf_hints' */
658 /* doesn't include the newly appended glyph */
659 glyph->ins_len = sizeof (bytecode);
660 glyph->ins_buf = (FT_Byte*)malloc(glyph->ins_len);
661 if (!glyph->ins_buf)
662 return FT_Err_Out_Of_Memory;
663 memcpy(glyph->ins_buf, bytecode, glyph->ins_len);
665 sfnt->max_components += 1;
668 return TA_Err_Ok;
672 FT_Error
673 TA_sfnt_build_glyf_table(SFNT* sfnt,
674 FONT* font)
676 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
677 glyf_Data* data = (glyf_Data*)glyf_table->data;
679 GLYPH* glyph;
681 FT_ULong len;
682 FT_Byte* buf_new;
683 FT_Byte* p;
684 FT_UShort i;
687 if (glyf_table->processed)
688 return TA_Err_Ok;
690 /* get table size */
691 len = 0;
692 glyph = data->glyphs;
693 for (i = 0; i < data->num_glyphs; i++, glyph++)
695 /* glyph records should have offsets which are multiples of 4 */
696 len = (len + 3) & ~3;
697 len += glyph->len1 + glyph->len2 + glyph->ins_len;
698 /* add two bytes for the instructionLength field */
699 if (glyph->len2 || glyph->ins_len)
700 len += 2;
703 /* to make the short format of the `loca' table always work, */
704 /* assure an even length of the `glyf' table */
705 glyf_table->len = (len + 1) & ~1;
707 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
708 if (!buf_new)
709 return FT_Err_Out_Of_Memory;
710 else
711 glyf_table->buf = buf_new;
713 p = glyf_table->buf;
714 glyph = data->glyphs;
715 for (i = 0; i < data->num_glyphs; i++, glyph++)
717 len = glyph->len1 + glyph->len2 + glyph->ins_len;
718 if (glyph->len2 || glyph->ins_len)
719 len += 2;
721 if (len)
723 /* copy glyph data and insert new instructions */
724 memcpy(p, glyph->buf, glyph->len1);
726 if (glyph->len2)
728 /* simple glyph */
729 p += glyph->len1;
730 *(p++) = HIGH(glyph->ins_len);
731 *(p++) = LOW(glyph->ins_len);
732 memcpy(p, glyph->ins_buf, glyph->ins_len);
733 p += glyph->ins_len;
734 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
735 p += glyph->len2;
737 else
739 /* composite glyph */
740 if (glyph->ins_len)
742 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
743 p += glyph->len1;
744 *(p++) = HIGH(glyph->ins_len);
745 *(p++) = LOW(glyph->ins_len);
746 memcpy(p, glyph->ins_buf, glyph->ins_len);
747 p += glyph->ins_len;
749 else
750 p += glyph->len1;
753 /* pad with zero bytes to have an offset which is a multiple of 4; */
754 /* this works even for the last glyph record since the `glyf' */
755 /* table length is a multiple of 4 also */
756 switch (len % 4)
758 case 1:
759 *(p++) = 0;
760 case 2:
761 *(p++) = 0;
762 case 3:
763 *(p++) = 0;
764 default:
765 break;
770 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
771 glyf_table->len);
772 glyf_table->processed = 1;
774 return TA_Err_Ok;
778 static FT_Error
779 TA_create_glyph_data(FT_Outline* outline,
780 GLYPH* glyph)
782 FT_Error error = TA_Err_Ok;
784 FT_Pos xmin, ymin;
785 FT_Pos xmax, ymax;
787 FT_Byte header[10];
788 FT_Byte* flags = NULL;
789 FT_Byte* flagsp;
790 FT_Byte oldf, f;
791 FT_Byte* x = NULL;
792 FT_Byte* xp;
793 FT_Byte* y = NULL;
794 FT_Byte* yp;
796 FT_Pos lastx, lasty;
798 FT_Short i;
799 FT_Byte* p;
802 if (!outline->n_contours)
803 return TA_Err_Ok; /* empty glyph */
805 /* in case of success, all non-local allocated arrays are */
806 /* linked and eventually freed in `TA_font_unload' */
808 glyph->buf = NULL;
810 /* we use `calloc' since we rely on the array */
811 /* being initialized to zero; */
812 /* additionally, we need one more byte for a test after the loop */
813 flags = (FT_Byte*)calloc(1, outline->n_points + 1);
814 if (!flags)
816 error = FT_Err_Out_Of_Memory;
817 goto Exit;
820 /* we have either one-byte or two-byte elements */
821 x = (FT_Byte*)malloc(2 * outline->n_points);
822 if (!x)
824 error = FT_Err_Out_Of_Memory;
825 goto Exit;
828 y = (FT_Byte*)malloc(2 * outline->n_points);
829 if (!y)
831 error = FT_Err_Out_Of_Memory;
832 goto Exit;
835 flagsp = flags;
836 xp = x;
837 yp = y;
838 xmin = xmax = (outline->points[0].x + 32) >> 6;
839 ymin = ymax = (outline->points[0].y + 32) >> 6;
840 lastx = 0;
841 lasty = 0;
842 oldf = 0x80; /* start with an impossible value */
844 /* convert the FreeType representation of the glyph's outline */
845 /* into the representation format of the `glyf' table */
846 for (i = 0; i < outline->n_points; i++)
848 FT_Pos xcur = (outline->points[i].x + 32) >> 6;
849 FT_Pos ycur = (outline->points[i].y + 32) >> 6;
851 FT_Pos xdelta = xcur - lastx;
852 FT_Pos ydelta = ycur - lasty;
855 /* we are only interested in bit 0 of the `tags' array */
856 f = outline->tags[i] & ON_CURVE;
858 /* x value */
860 if (xdelta == 0)
861 f |= SAME_X;
862 else
864 if (xdelta < 256 && xdelta > -256)
866 f |= X_SHORT_VECTOR;
868 if (xdelta < 0)
869 xdelta = -xdelta;
870 else
871 f |= SAME_X;
873 *(xp++) = (FT_Byte)xdelta;
875 else
877 *(xp++) = HIGH(xdelta);
878 *(xp++) = LOW(xdelta);
882 /* y value */
884 if (ydelta == 0)
885 f |= SAME_Y;
886 else
888 if (ydelta < 256 && ydelta > -256)
890 f |= Y_SHORT_VECTOR;
892 if (ydelta < 0)
893 ydelta = -ydelta;
894 else
895 f |= SAME_Y;
897 *(yp++) = (FT_Byte)ydelta;
899 else
901 *(yp++) = HIGH(ydelta);
902 *(yp++) = LOW(ydelta);
906 if (f == oldf)
908 /* set repeat flag */
909 *(flagsp - 1) |= REPEAT;
911 if (*flagsp == 255)
913 /* we can only handle 256 repetitions at once, */
914 /* so use a new counter */
915 flagsp++;
916 *(flagsp++) = f;
918 else
919 *flagsp += 1; /* increase repetition counter */
921 else
923 if (*flagsp)
924 flagsp++; /* skip repetition counter */
925 *(flagsp++) = f;
926 oldf = f;
929 if (xcur > xmax)
930 xmax = xcur;
931 if (ycur > ymax)
932 ymax = ycur;
933 if (xcur < xmin)
934 xmin = xcur;
935 if (ycur < ymin)
936 ymin = ycur;
938 lastx = xcur;
939 lasty = ycur;
942 /* if the last byte was a repetition counter, */
943 /* we must increase by one to get the correct array size */
944 if (*flagsp)
945 flagsp++;
947 header[0] = HIGH(outline->n_contours);
948 header[1] = LOW(outline->n_contours);
949 header[2] = HIGH(xmin);
950 header[3] = LOW(xmin);
951 header[4] = HIGH(ymin);
952 header[5] = LOW(ymin);
953 header[6] = HIGH(xmax);
954 header[7] = LOW(xmax);
955 header[8] = HIGH(ymax);
956 header[9] = LOW(ymax);
958 /* concatenate all arrays and fill needed GLYPH structure elements */
960 glyph->len1 = 10 + 2 * outline->n_contours;
961 glyph->len2 = (flagsp - flags) + (xp - x) + (yp - y);
963 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
964 if (!glyph->buf)
966 error = FT_Err_Out_Of_Memory;
967 goto Exit;
970 p = glyph->buf;
971 memcpy(p, header, 10);
972 p += 10;
974 glyph->ins_len = 0;
975 glyph->ins_buf = NULL;
977 for (i = 0; i < outline->n_contours; i++)
979 *(p++) = HIGH(outline->contours[i]);
980 *(p++) = LOW(outline->contours[i]);
983 memcpy(p, flags, flagsp - flags);
984 p += flagsp - flags;
985 memcpy(p, x, xp - x);
986 p += xp - x;
987 memcpy(p, y, yp - y);
989 Exit:
990 free(flags);
991 free(x);
992 free(y);
994 return error;
998 /* We hint each glyph at EM size and construct a new `glyf' table. */
999 /* Some fonts need this; in particular, */
1000 /* there are CJK fonts which use hints to scale and position subglyphs. */
1001 /* As a consequence, there are no longer composite glyphs. */
1003 FT_Error
1004 TA_sfnt_create_glyf_data(SFNT* sfnt,
1005 FONT* font)
1007 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
1008 FT_Face face = sfnt->face;
1009 FT_Error error;
1011 glyf_Data* data;
1013 FT_UShort i;
1016 /* in case of success, all allocated arrays are */
1017 /* linked and eventually freed in `TA_font_unload' */
1019 /* nothing to do if table has already been created */
1020 if (glyf_table->data)
1021 return TA_Err_Ok;
1023 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
1024 if (!data)
1025 return FT_Err_Out_Of_Memory;
1027 glyf_table->data = data;
1029 data->num_glyphs = face->num_glyphs;
1030 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
1031 if (!data->glyphs)
1032 return FT_Err_Out_Of_Memory;
1034 /* XXX: Make size configurable */
1035 /* we use the EM size */
1036 /* so that the resulting coordinates can be used without transformation */
1037 error = FT_Set_Char_Size(face, face->units_per_EM * 64, 0, 72, 0);
1038 if (error)
1039 return error;
1041 /* loop over all glyphs in font face */
1042 for (i = 0; i < data->num_glyphs; i++)
1044 GLYPH* glyph = &data->glyphs[i];
1047 error = FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP | FT_LOAD_NO_AUTOHINT);
1048 if (error)
1049 return error;
1051 error = TA_create_glyph_data(&face->glyph->outline, glyph);
1052 if (error)
1053 return error;
1056 return TA_Err_Ok;
1059 /* end of taglyf.c */