Fix thinko in handling composite glyphs.
[ttfautohint.git] / src / taglyf.c
blob92030814de5dba03b9b0ba608ddf99e7901f95b8
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;
51 FT_UShort component;
52 FT_UShort* components_new;
54 FT_Byte* p;
55 FT_Byte* endp;
58 p = buf;
59 endp = buf + len;
61 /* skip header */
62 p += 10;
64 /* walk over component records */
67 if (p + 4 > endp)
68 return FT_Err_Invalid_Table;
70 flags_offset = p - buf;
72 flags = *(p++) << 8;
73 flags += *(p++);
75 /* add component to list */
76 component = *(p++) << 8;
77 component += *(p++);
79 glyph->num_components++;
80 components_new = (FT_UShort*)realloc(glyph->components,
81 glyph->num_components
82 * sizeof (FT_UShort));
83 if (!components_new)
85 glyph->num_components--;
86 return FT_Err_Out_Of_Memory;
88 else
89 glyph->components = components_new;
91 glyph->components[glyph->num_components - 1] = component;
93 /* skip scaling and offset arguments */
94 if (flags & ARGS_ARE_WORDS)
95 p += 4;
96 else
97 p += 2;
99 if (flags & WE_HAVE_A_SCALE)
100 p += 2;
101 else if (flags & WE_HAVE_AN_XY_SCALE)
102 p += 4;
103 else if (flags & WE_HAVE_A_2X2)
104 p += 8;
105 } while (flags & MORE_COMPONENTS);
107 glyph->flags_offset = flags_offset;
109 /* adjust glyph record length */
110 len = p - buf;
112 glyph->len1 = len;
113 /* glyph->len2 = 0; */
114 glyph->buf = (FT_Byte*)malloc(len);
115 if (!glyph->buf)
116 return FT_Err_Out_Of_Memory;
118 /* copy record without instructions (if any) */
119 memcpy(glyph->buf, buf, len);
120 glyph->buf[flags_offset] &= ~(WE_HAVE_INSTR >> 8);
122 return TA_Err_Ok;
126 static FT_Error
127 TA_glyph_parse_simple(GLYPH* glyph,
128 FT_Byte* buf,
129 FT_UShort num_contours,
130 FT_ULong len)
132 FT_ULong ins_offset;
133 FT_Byte* flags_start;
135 FT_UShort num_ins;
136 FT_UShort num_pts;
138 FT_ULong flags_size; /* size of the flags array */
139 FT_ULong xy_size; /* size of x and y coordinate arrays together */
141 FT_Byte* p;
142 FT_Byte* endp;
144 FT_UShort i;
147 p = buf;
148 endp = buf + len;
150 ins_offset = 10 + num_contours * 2;
152 p += ins_offset;
154 if (p + 2 > endp)
155 return FT_Err_Invalid_Table;
157 /* get number of instructions */
158 num_ins = *(p++) << 8;
159 num_ins += *(p++);
161 p += num_ins;
163 if (p > endp)
164 return FT_Err_Invalid_Table;
166 /* get number of points from last outline point */
167 num_pts = buf[ins_offset - 2] << 8;
168 num_pts += buf[ins_offset - 1];
169 num_pts++;
171 flags_start = p;
172 xy_size = 0;
173 i = 0;
175 while (i < num_pts)
177 FT_Byte flags;
178 FT_Byte x_short;
179 FT_Byte y_short;
180 FT_Byte have_x;
181 FT_Byte have_y;
182 FT_Byte count;
185 if (p + 1 > endp)
186 return FT_Err_Invalid_Table;
188 flags = *(p++);
190 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
191 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
193 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
194 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
196 count = 1;
198 if (flags & REPEAT)
200 if (p + 1 > endp)
201 return FT_Err_Invalid_Table;
203 count += *(p++);
205 if (i + count > num_pts)
206 return FT_Err_Invalid_Table;
209 xy_size += count * x_short * have_x;
210 xy_size += count * y_short * have_y;
212 i += count;
215 if (p + xy_size > endp)
216 return FT_Err_Invalid_Table;
218 flags_size = p - flags_start;
220 /* store the data before and after the bytecode instructions */
221 /* in the same array */
222 glyph->len1 = ins_offset;
223 glyph->len2 = flags_size + xy_size;
224 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
225 if (!glyph->buf)
226 return FT_Err_Out_Of_Memory;
228 /* now copy everything but the instructions */
229 memcpy(glyph->buf, buf, glyph->len1);
230 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
232 return TA_Err_Ok;
236 static FT_Error
237 TA_iterate_composite_glyph(glyf_Data* data,
238 FT_UShort* components,
239 FT_UShort num_components,
240 FT_UShort** endpoints,
241 FT_UShort* num_endpoints)
243 FT_UShort i;
246 for (i = 0; i < num_components; i++)
248 GLYPH* glyph;
249 FT_UShort component = components[i];
250 FT_Error error;
253 if (component >= data->num_glyphs)
254 return FT_Err_Invalid_Table;
256 glyph = &data->glyphs[component];
258 if (glyph->num_components)
260 error = TA_iterate_composite_glyph(data,
261 glyph->components,
262 glyph->num_components,
263 endpoints,
264 num_endpoints);
265 if (error)
266 return error;
268 else
270 FT_UShort num_contours;
271 FT_UShort endpoint;
272 FT_UShort* endpoints_new;
275 /* collect end points of simple glyphs */
277 num_contours = glyph->buf[0] << 8;
278 num_contours += glyph->buf[1];
279 endpoint = glyph->buf[10 + (num_contours - 1) * 2] << 8;
280 endpoint += glyph->buf[10 + (num_contours - 1) * 2 + 1];
282 (*num_endpoints)++;
283 endpoints_new = (FT_UShort*)realloc(*endpoints,
284 *num_endpoints
285 * sizeof (FT_UShort));
286 if (!endpoints_new)
288 (*num_endpoints)--;
289 return FT_Err_Out_Of_Memory;
291 else
292 *endpoints = endpoints_new;
294 (*endpoints)[*num_endpoints - 1] = endpoint;
295 if (*num_endpoints > 1)
296 (*endpoints)[*num_endpoints - 1] += (*endpoints)[*num_endpoints - 2] + 1;
300 return TA_Err_Ok;
304 static FT_Error
305 TA_compute_composite_endpoints(glyf_Data* data)
307 FT_UShort i;
310 for (i = 0; i < data->num_glyphs; i++)
312 GLYPH* glyph = &data->glyphs[i];
315 if (glyph->num_components)
317 FT_Error error;
320 error = TA_iterate_composite_glyph(data,
321 glyph->components,
322 glyph->num_components,
323 &glyph->endpoints,
324 &glyph->num_endpoints);
325 if (error)
326 return error;
330 return TA_Err_Ok;
334 FT_Error
335 TA_sfnt_split_glyf_table(SFNT* sfnt,
336 FONT* font)
338 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
339 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
340 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
342 glyf_Data* data;
343 FT_Byte loca_format;
345 FT_ULong offset;
346 FT_ULong offset_next;
348 FT_Byte* p;
349 FT_UShort i;
351 FT_Error error;
354 /* in case of success, all allocated arrays are */
355 /* linked and eventually freed in `TA_font_unload' */
357 /* nothing to do if table has already been split */
358 if (glyf_table->data)
359 return TA_Err_Ok;
361 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
362 if (!data)
363 return FT_Err_Out_Of_Memory;
365 glyf_table->data = data;
367 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
369 data->num_glyphs = loca_format ? loca_table->len / 4 - 1
370 : loca_table->len / 2 - 1;
371 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
372 if (!data->glyphs)
373 return FT_Err_Out_Of_Memory;
375 p = loca_table->buf;
377 if (loca_format)
379 offset_next = *(p++) << 24;
380 offset_next += *(p++) << 16;
381 offset_next += *(p++) << 8;
382 offset_next += *(p++);
384 else
386 offset_next = *(p++) << 8;
387 offset_next += *(p++);
388 offset_next <<= 1;
391 /* loop over `loca' and `glyf' data */
392 for (i = 0; i < data->num_glyphs; i++)
394 GLYPH* glyph = &data->glyphs[i];
395 FT_ULong len;
398 offset = offset_next;
400 if (loca_format)
402 offset_next = *(p++) << 24;
403 offset_next += *(p++) << 16;
404 offset_next += *(p++) << 8;
405 offset_next += *(p++);
407 else
409 offset_next = *(p++) << 8;
410 offset_next += *(p++);
411 offset_next <<= 1;
414 if (offset_next < offset
415 || offset_next > glyf_table->len)
416 return FT_Err_Invalid_Table;
418 len = offset_next - offset;
419 if (!len)
420 continue; /* empty glyph */
421 else
423 FT_Byte* buf;
424 FT_Short num_contours;
427 /* check header size */
428 if (len < 10)
429 return FT_Err_Invalid_Table;
431 buf = glyf_table->buf + offset;
432 num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
434 /* We must parse the rest of the glyph record to get the exact */
435 /* record length. Since the `loca' table rounds record lengths */
436 /* up to multiples of 4 (or 2 for older fonts), and we must round */
437 /* up again after stripping off the instructions, it would be */
438 /* possible otherwise to have more than 4 bytes of padding which */
439 /* is more or less invalid. */
441 if (num_contours < 0)
442 error = TA_glyph_parse_composite(glyph, buf, len);
443 else
444 error = TA_glyph_parse_simple(glyph, buf, num_contours, len);
445 if (error)
446 return error;
450 error = TA_compute_composite_endpoints(data);
451 if (error)
452 return error;
454 return TA_Err_Ok;
458 FT_Error
459 TA_sfnt_build_glyf_table(SFNT* sfnt,
460 FONT* font)
462 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
463 glyf_Data* data = (glyf_Data*)glyf_table->data;
465 GLYPH* glyph;
467 FT_ULong len;
468 FT_Byte* buf_new;
469 FT_Byte* p;
470 FT_UShort i;
473 if (glyf_table->processed)
474 return TA_Err_Ok;
476 /* get table size */
477 len = 0;
478 glyph = data->glyphs;
479 for (i = 0; i < data->num_glyphs; i++, glyph++)
481 /* glyph records should have offsets which are multiples of 4 */
482 len = (len + 3) & ~3;
483 len += glyph->len1 + glyph->len2 + glyph->ins_len;
484 /* add two bytes for the instructionLength field */
485 if (glyph->len2 || glyph->ins_len)
486 len += 2;
489 /* to make the short format of the `loca' table always work, */
490 /* assure an even length of the `glyf' table */
491 glyf_table->len = (len + 1) & ~1;
493 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
494 if (!buf_new)
495 return FT_Err_Out_Of_Memory;
496 else
497 glyf_table->buf = buf_new;
499 p = glyf_table->buf;
500 glyph = data->glyphs;
501 for (i = 0; i < data->num_glyphs; i++, glyph++)
503 len = glyph->len1 + glyph->len2 + glyph->ins_len;
504 if (glyph->len2 || glyph->ins_len)
505 len += 2;
507 if (len)
509 /* copy glyph data and insert new instructions */
510 memcpy(p, glyph->buf, glyph->len1);
512 if (glyph->len2)
514 /* simple glyph */
515 p += glyph->len1;
516 *(p++) = HIGH(glyph->ins_len);
517 *(p++) = LOW(glyph->ins_len);
518 memcpy(p, glyph->ins_buf, glyph->ins_len);
519 p += glyph->ins_len;
520 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
521 p += glyph->len2;
523 else
525 /* composite glyph */
526 if (glyph->ins_len)
528 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
529 p += glyph->len1;
530 *(p++) = HIGH(glyph->ins_len);
531 *(p++) = LOW(glyph->ins_len);
532 memcpy(p, glyph->ins_buf, glyph->ins_len);
533 p += glyph->ins_len;
535 else
536 p += glyph->len1;
539 /* pad with zero bytes to have an offset which is a multiple of 4; */
540 /* this works even for the last glyph record since the `glyf' */
541 /* table length is a multiple of 4 also */
542 switch (len % 4)
544 case 1:
545 *(p++) = 0;
546 case 2:
547 *(p++) = 0;
548 case 3:
549 *(p++) = 0;
550 default:
551 break;
556 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
557 glyf_table->len);
558 glyf_table->processed = 1;
560 return TA_Err_Ok;
564 static FT_Error
565 TA_create_glyph_data(FT_Outline* outline,
566 GLYPH* glyph)
568 FT_Error error = TA_Err_Ok;
570 FT_Pos xmin, ymin;
571 FT_Pos xmax, ymax;
573 FT_Byte header[10];
574 FT_Byte* flags = NULL;
575 FT_Byte* flagsp;
576 FT_Byte oldf, f;
577 FT_Byte* x = NULL;
578 FT_Byte* xp;
579 FT_Byte* y = NULL;
580 FT_Byte* yp;
582 FT_Pos lastx, lasty;
584 FT_Short i;
585 FT_Byte* p;
588 if (!outline->n_contours)
589 return TA_Err_Ok; /* empty glyph */
591 /* in case of success, all non-local allocated arrays are */
592 /* linked and eventually freed in `TA_font_unload' */
594 glyph->buf = NULL;
596 /* we use `calloc' since we rely on the array */
597 /* being initialized to zero; */
598 /* additionally, we need one more byte for a test after the loop */
599 flags = (FT_Byte*)calloc(1, outline->n_points + 1);
600 if (!flags)
602 error = FT_Err_Out_Of_Memory;
603 goto Exit;
606 /* we have either one-byte or two-byte elements */
607 x = (FT_Byte*)malloc(2 * outline->n_points);
608 if (!x)
610 error = FT_Err_Out_Of_Memory;
611 goto Exit;
614 y = (FT_Byte*)malloc(2 * outline->n_points);
615 if (!y)
617 error = FT_Err_Out_Of_Memory;
618 goto Exit;
621 flagsp = flags;
622 xp = x;
623 yp = y;
624 xmin = xmax = (outline->points[0].x + 32) >> 6;
625 ymin = ymax = (outline->points[0].y + 32) >> 6;
626 lastx = 0;
627 lasty = 0;
628 oldf = 0x80; /* start with an impossible value */
630 /* convert the FreeType representation of the glyph's outline */
631 /* into the representation format of the `glyf' table */
632 for (i = 0; i < outline->n_points; i++)
634 FT_Pos xcur = (outline->points[i].x + 32) >> 6;
635 FT_Pos ycur = (outline->points[i].y + 32) >> 6;
637 FT_Pos xdelta = xcur - lastx;
638 FT_Pos ydelta = ycur - lasty;
641 /* we are only interested in bit 0 of the `tags' array */
642 f = outline->tags[i] & ON_CURVE;
644 /* x value */
646 if (xdelta == 0)
647 f |= SAME_X;
648 else
650 if (xdelta < 256 && xdelta > -256)
652 f |= X_SHORT_VECTOR;
654 if (xdelta < 0)
655 xdelta = -xdelta;
656 else
657 f |= SAME_X;
659 *(xp++) = (FT_Byte)xdelta;
661 else
663 *(xp++) = HIGH(xdelta);
664 *(xp++) = LOW(xdelta);
668 /* y value */
670 if (ydelta == 0)
671 f |= SAME_Y;
672 else
674 if (ydelta < 256 && ydelta > -256)
676 f |= Y_SHORT_VECTOR;
678 if (ydelta < 0)
679 ydelta = -ydelta;
680 else
681 f |= SAME_Y;
683 *(yp++) = (FT_Byte)ydelta;
685 else
687 *(yp++) = HIGH(ydelta);
688 *(yp++) = LOW(ydelta);
692 if (f == oldf)
694 /* set repeat flag */
695 *(flagsp - 1) |= REPEAT;
697 if (*flagsp == 255)
699 /* we can only handle 256 repetitions at once, */
700 /* so use a new counter */
701 flagsp++;
702 *(flagsp++) = f;
704 else
705 *flagsp += 1; /* increase repetition counter */
707 else
709 if (*flagsp)
710 flagsp++; /* skip repetition counter */
711 *(flagsp++) = f;
712 oldf = f;
715 if (xcur > xmax)
716 xmax = xcur;
717 if (ycur > ymax)
718 ymax = ycur;
719 if (xcur < xmin)
720 xmin = xcur;
721 if (ycur < ymin)
722 ymin = ycur;
724 lastx = xcur;
725 lasty = ycur;
728 /* if the last byte was a repetition counter, */
729 /* we must increase by one to get the correct array size */
730 if (*flagsp)
731 flagsp++;
733 header[0] = HIGH(outline->n_contours);
734 header[1] = LOW(outline->n_contours);
735 header[2] = HIGH(xmin);
736 header[3] = LOW(xmin);
737 header[4] = HIGH(ymin);
738 header[5] = LOW(ymin);
739 header[6] = HIGH(xmax);
740 header[7] = LOW(xmax);
741 header[8] = HIGH(ymax);
742 header[9] = LOW(ymax);
744 /* concatenate all arrays and fill needed GLYPH structure elements */
746 glyph->len1 = 10 + 2 * outline->n_contours;
747 glyph->len2 = (flagsp - flags) + (xp - x) + (yp - y);
749 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
750 if (!glyph->buf)
752 error = FT_Err_Out_Of_Memory;
753 goto Exit;
756 p = glyph->buf;
757 memcpy(p, header, 10);
758 p += 10;
760 glyph->ins_len = 0;
761 glyph->ins_buf = NULL;
763 for (i = 0; i < outline->n_contours; i++)
765 *(p++) = HIGH(outline->contours[i]);
766 *(p++) = LOW(outline->contours[i]);
769 memcpy(p, flags, flagsp - flags);
770 p += flagsp - flags;
771 memcpy(p, x, xp - x);
772 p += xp - x;
773 memcpy(p, y, yp - y);
775 Exit:
776 free(flags);
777 free(x);
778 free(y);
780 return error;
784 /* We hint each glyph at EM size and construct a new `glyf' table. */
785 /* Some fonts need this; in particular, */
786 /* there are CJK fonts which use hints to scale and position subglyphs. */
787 /* As a consequence, there are no longer composite glyphs. */
789 FT_Error
790 TA_sfnt_create_glyf_data(SFNT* sfnt,
791 FONT* font)
793 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
794 FT_Face face = sfnt->face;
795 FT_Error error;
797 glyf_Data* data;
799 FT_UShort i;
802 /* in case of success, all allocated arrays are */
803 /* linked and eventually freed in `TA_font_unload' */
805 /* nothing to do if table has already been created */
806 if (glyf_table->data)
807 return TA_Err_Ok;
809 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
810 if (!data)
811 return FT_Err_Out_Of_Memory;
813 glyf_table->data = data;
815 data->num_glyphs = face->num_glyphs;
816 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
817 if (!data->glyphs)
818 return FT_Err_Out_Of_Memory;
820 /* XXX: Make size configurable */
821 /* we use the EM size */
822 /* so that the resulting coordinates can be used without transformation */
823 error = FT_Set_Char_Size(face, face->units_per_EM * 64, 0, 72, 0);
824 if (error)
825 return error;
827 /* loop over all glyphs in font face */
828 for (i = 0; i < data->num_glyphs; i++)
830 GLYPH* glyph = &data->glyphs[i];
833 error = FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP | FT_LOAD_NO_AUTOHINT);
834 if (error)
835 return error;
837 error = TA_create_glyph_data(&face->glyph->outline, glyph);
838 if (error)
839 return error;
842 return TA_Err_Ok;
845 /* end of taglyf.c */