Implement option `process_with_components'.
[ttfautohint.git] / lib / taglyf.c
blob3a72cae5b213efa8b884f77fba854b730be78354
1 /* taglyf.c */
3 /*
4 * Copyright (C) 2011-2012 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)
36 FT_Int ret;
39 ret = font->progress(idx, face->num_glyphs,
40 sfnt - font->sfnts, font->num_sfnts,
41 font->progress_data);
42 if (ret)
43 return TA_Err_Canceled;
47 return FT_Err_Ok;
51 static FT_Error
52 TA_glyph_get_components(GLYPH* glyph,
53 FT_Byte* buf,
54 FT_ULong len)
56 FT_UShort flags;
57 FT_UShort component;
58 FT_UShort* components_new;
60 FT_Byte* p;
61 FT_Byte* endp;
64 p = buf;
65 endp = buf + len;
67 /* skip header */
68 p += 10;
70 /* walk over component records */
73 if (p + 4 > endp)
74 return FT_Err_Invalid_Table;
76 flags = *(p++) << 8;
77 flags += *(p++);
79 /* add component to list */
80 component = *(p++) << 8;
81 component += *(p++);
83 glyph->num_components++;
84 components_new = (FT_UShort*)realloc(glyph->components,
85 glyph->num_components
86 * sizeof (FT_UShort));
87 if (!components_new)
89 glyph->num_components--;
90 return FT_Err_Out_Of_Memory;
92 else
93 glyph->components = components_new;
95 glyph->components[glyph->num_components - 1] = component;
97 /* skip scaling and offset arguments */
98 if (flags & ARGS_ARE_WORDS)
99 p += 4;
100 else
101 p += 2;
103 if (flags & WE_HAVE_A_SCALE)
104 p += 2;
105 else if (flags & WE_HAVE_AN_XY_SCALE)
106 p += 4;
107 else if (flags & WE_HAVE_A_2X2)
108 p += 8;
109 } while (flags & MORE_COMPONENTS);
111 return TA_Err_Ok;
115 static FT_Error
116 TA_glyph_parse_composite(GLYPH* glyph,
117 FT_Byte* buf,
118 FT_ULong len,
119 FT_UShort num_glyphs,
120 FT_Bool hint_with_components)
122 FT_ULong flags_offset; /* after the loop, this is the offset */
123 /* to the last element in the flags array */
124 FT_UShort flags;
126 FT_Byte* p;
127 FT_Byte* q;
130 /* we allocate too large a buffer */
131 /* (including space for the new component */
132 /* and possible argument size changes for shifted point indices) */
133 /* and reallocate it later to its real size */
134 glyph->buf = (FT_Byte*)malloc(len + 8 + glyph->num_components * 2);
135 if (!glyph->buf)
136 return FT_Err_Out_Of_Memory;
138 p = buf;
139 q = glyph->buf;
141 /* copy header */
142 memcpy(q, p, 10);
143 p += 10;
144 q += 10;
146 /* if the composite glyph contains one or more contours, */
147 /* we prepend a composite glyph component to call some bytecode */
148 /* which eventually becomes the last glyph in the `glyf' table; */
149 /* for convenience, however, it is not added to the `components' array */
150 /* (doing so simplifies the conversion of point indices later on) */
151 if (glyph->num_composite_contours && hint_with_components)
153 FT_Short x_min;
154 FT_Short x_max;
155 FT_Short y_min;
156 FT_Short y_max;
157 FT_Short x_offset;
158 FT_Short y_offset;
161 /* the composite glyph's bounding box */
162 x_min = (FT_Short)((buf[2] << 8) + buf[3]);
163 y_min = (FT_Short)((buf[4] << 8) + buf[5]);
164 x_max = (FT_Short)((buf[6] << 8) + buf[7]);
165 y_max = (FT_Short)((buf[8] << 8) + buf[9]);
167 /* use ARGS_ARE_WORDS only if necessary; */
168 /* note that the offset value of the component doesn't matter */
169 /* as long as it stays within the bounding box */
170 if (x_min <= 0 && x_max >= 0)
171 x_offset = 0;
172 else if (x_max < 0)
173 x_offset = x_max;
174 else
175 x_offset = x_min;
177 if (y_min <= 0 && y_max >= 0)
178 y_offset = 0;
179 else if (y_max < 0)
180 y_offset = y_max;
181 else
182 y_offset = y_min;
184 if (x_offset >= -128 && x_offset <= 127
185 && y_offset >= -128 && y_offset <= 127)
187 *(q++) = 0x00;
188 *(q++) = ARGS_ARE_XY_VALUES | MORE_COMPONENTS;
189 *(q++) = HIGH(num_glyphs - 1);
190 *(q++) = LOW(num_glyphs - 1);
191 *(q++) = x_offset;
192 *(q++) = y_offset;
194 else
196 *(q++) = 0x00;
197 *(q++) = ARGS_ARE_WORDS | ARGS_ARE_XY_VALUES | MORE_COMPONENTS;
198 *(q++) = HIGH(num_glyphs - 1);
199 *(q++) = LOW(num_glyphs - 1);
200 *(q++) = HIGH(x_offset);
201 *(q++) = LOW(x_offset);
202 *(q++) = HIGH(y_offset);
203 *(q++) = LOW(y_offset);
207 /* walk over component records */
210 flags_offset = q - glyph->buf;
212 *(q++) = *p;
213 flags = *(p++) << 8;
214 *(q++) = *p;
215 flags += *(p++);
217 /* copy component */
218 *(q++) = *(p++);
219 *(q++) = *(p++);
221 if (flags & ARGS_ARE_XY_VALUES)
223 /* copy offsets */
224 *(q++) = *(p++);
225 *(q++) = *(p++);
227 if (flags & ARGS_ARE_WORDS)
229 *(q++) = *(p++);
230 *(q++) = *(p++);
233 else
235 /* handle point numbers */
236 FT_UShort arg1;
237 FT_UShort arg2;
238 FT_UShort i;
241 if (flags & ARGS_ARE_WORDS)
243 arg1 = *(p++) >> 8;
244 arg1 += *(p++);
245 arg2 = *(p++) >> 8;
246 arg2 += *(p++);
248 else
250 arg1 = *(p++);
251 arg2 = *(p++);
254 /* adjust point numbers */
255 /* (see `TA_adjust_point_index' in `tabytecode.c' for more) */
256 for (i = 0; i < glyph->num_pointsums; i++)
257 if (arg1 < glyph->pointsums[i])
258 break;
259 arg1 += i;
261 for (i = 0; i < glyph->num_pointsums; i++)
262 if (arg2 < glyph->pointsums[i])
263 break;
264 arg2 += i;
266 if (arg1 <= 0xFF && arg2 <= 0xFF)
268 glyph->buf[flags_offset + 1] &= ~ARGS_ARE_WORDS;
270 *(q++) = arg1;
271 *(q++) = arg2;
273 else
275 glyph->buf[flags_offset + 1] |= ARGS_ARE_WORDS;
277 *(q++) = HIGH(arg1);
278 *(q++) = LOW(arg1);
279 *(q++) = HIGH(arg2);
280 *(q++) = LOW(arg2);
284 /* copy scaling arguments */
285 if (flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_XY_SCALE | WE_HAVE_A_2X2))
287 *(q++) = *(p++);
288 *(q++) = *(p++);
290 if (flags & (WE_HAVE_AN_XY_SCALE | WE_HAVE_A_2X2))
292 *(q++) = *(p++);
293 *(q++) = *(p++);
295 if (flags & WE_HAVE_A_2X2)
297 *(q++) = *(p++);
298 *(q++) = *(p++);
299 *(q++) = *(p++);
300 *(q++) = *(p++);
302 } while (flags & MORE_COMPONENTS);
304 glyph->len1 = q - glyph->buf;
305 /* glyph->len2 = 0; */
306 glyph->flags_offset = flags_offset;
307 glyph->buf = (FT_Byte*)realloc(glyph->buf, glyph->len1);
309 /* we discard instructions (if any) */
310 glyph->buf[glyph->flags_offset] &= ~(WE_HAVE_INSTR >> 8);
312 return TA_Err_Ok;
316 static FT_Error
317 TA_glyph_parse_simple(GLYPH* glyph,
318 FT_Byte* buf,
319 FT_ULong len)
321 FT_ULong ins_offset;
322 FT_Byte* flags_start;
324 FT_UShort num_ins;
326 FT_ULong flags_size; /* size of the flags array */
327 FT_ULong xy_size; /* size of x and y coordinate arrays together */
329 FT_Byte* p;
330 FT_Byte* endp;
332 FT_UShort i;
335 p = buf;
336 endp = buf + len;
338 ins_offset = 10 + glyph->num_contours * 2;
340 p += ins_offset;
342 if (p + 2 > endp)
343 return FT_Err_Invalid_Table;
345 /* get number of instructions */
346 num_ins = *(p++) << 8;
347 num_ins += *(p++);
349 p += num_ins;
351 if (p > endp)
352 return FT_Err_Invalid_Table;
354 flags_start = p;
355 xy_size = 0;
356 i = 0;
358 while (i < glyph->num_points)
360 FT_Byte flags;
361 FT_Byte x_short;
362 FT_Byte y_short;
363 FT_Byte have_x;
364 FT_Byte have_y;
365 FT_UInt count;
368 if (p + 1 > endp)
369 return FT_Err_Invalid_Table;
371 flags = *(p++);
373 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
374 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
376 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
377 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
379 count = 1;
381 if (flags & REPEAT)
383 if (p + 1 > endp)
384 return FT_Err_Invalid_Table;
386 count += *(p++);
388 if (i + count > glyph->num_points)
389 return FT_Err_Invalid_Table;
392 xy_size += count * x_short * have_x;
393 xy_size += count * y_short * have_y;
395 i += count;
398 if (p + xy_size > endp)
399 return FT_Err_Invalid_Table;
401 flags_size = p - flags_start;
403 /* store the data before and after the bytecode instructions */
404 /* in the same array */
405 glyph->len1 = ins_offset;
406 glyph->len2 = flags_size + xy_size;
407 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
408 if (!glyph->buf)
409 return FT_Err_Out_Of_Memory;
411 /* now copy everything but the instructions */
412 memcpy(glyph->buf, buf, glyph->len1);
413 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
415 return TA_Err_Ok;
419 static FT_Error
420 TA_iterate_composite_glyph(glyf_Data* data,
421 FT_UShort* components,
422 FT_UShort num_components,
423 FT_UShort** pointsums,
424 FT_UShort* num_pointsums,
425 FT_UShort* num_composite_contours,
426 FT_UShort* num_composite_points)
428 FT_UShort* pointsums_new;
429 FT_UShort i;
432 /* save current state */
434 if (*num_pointsums == 0xFFFF)
435 return FT_Err_Invalid_Table;
437 (*num_pointsums)++;
438 pointsums_new = (FT_UShort*)realloc(*pointsums,
439 *num_pointsums
440 * sizeof (FT_UShort));
441 if (!pointsums_new)
443 (*num_pointsums)--;
444 return FT_Err_Out_Of_Memory;
446 else
447 *pointsums = pointsums_new;
449 (*pointsums)[*num_pointsums - 1] = *num_composite_points;
451 for (i = 0; i < num_components; i++)
453 GLYPH* glyph;
454 FT_UShort component = components[i];
455 FT_Error error;
458 if (component >= data->num_glyphs)
459 return FT_Err_Invalid_Table;
461 glyph = &data->glyphs[component];
463 if (glyph->num_components)
465 error = TA_iterate_composite_glyph(data,
466 glyph->components,
467 glyph->num_components,
468 pointsums,
469 num_pointsums,
470 num_composite_contours,
471 num_composite_points);
472 if (error)
473 return error;
475 else
477 /* no need for checking overflow of the number of contours */
478 /* since the number of points is always larger or equal */
479 if (*num_composite_points > 0xFFFF - glyph->num_points)
480 return FT_Err_Invalid_Table;
482 *num_composite_contours += glyph->num_contours;
483 *num_composite_points += glyph->num_points;
487 return TA_Err_Ok;
491 static FT_Error
492 TA_sfnt_compute_composite_pointsums(SFNT* sfnt,
493 FONT* font)
495 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
496 glyf_Data* data = (glyf_Data*)glyf_table->data;
498 FT_UShort i;
501 for (i = 0; i < data->num_glyphs; i++)
503 GLYPH* glyph = &data->glyphs[i];
506 if (glyph->num_components)
508 FT_Error error;
509 FT_UShort num_composite_contours = 0;
510 FT_UShort num_composite_points = 0;
513 error = TA_iterate_composite_glyph(data,
514 glyph->components,
515 glyph->num_components,
516 &glyph->pointsums,
517 &glyph->num_pointsums,
518 &num_composite_contours,
519 &num_composite_points);
520 if (error)
521 return error;
523 glyph->num_composite_contours = num_composite_contours;
525 if (font->hint_with_components)
527 /* update maximum values, */
528 /* including the subglyphs not in `components' array */
529 /* (each of them has a single point in a single contour) */
530 if (num_composite_points + glyph->num_pointsums
531 > sfnt->max_composite_points)
532 sfnt->max_composite_points = num_composite_points
533 + glyph->num_pointsums;
534 if (num_composite_contours + glyph->num_pointsums
535 > sfnt->max_composite_contours)
536 sfnt->max_composite_contours = num_composite_contours
537 + glyph->num_pointsums;
542 return TA_Err_Ok;
546 FT_Error
547 TA_sfnt_split_glyf_table(SFNT* sfnt,
548 FONT* font)
550 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
551 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
552 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
554 glyf_Data* data;
555 FT_Byte loca_format;
557 FT_ULong offset;
558 FT_ULong offset_next;
560 FT_Byte* p;
561 FT_UShort i;
562 FT_UShort loop_count;
564 FT_Error error;
567 /* in case of success, all allocated arrays are */
568 /* linked and eventually freed in `TA_font_unload' */
570 /* nothing to do if table has already been split */
571 if (glyf_table->data)
572 return TA_Err_Ok;
574 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
575 if (!data)
576 return FT_Err_Out_Of_Memory;
578 glyf_table->data = data;
580 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
582 data->num_glyphs = loca_format ? loca_table->len / 4
583 : loca_table->len / 2;
584 loop_count = data->num_glyphs - 1;
586 /* allocate one more glyph slot if we have composite glyphs */
587 if (!sfnt->max_components || !font->hint_with_components)
588 data->num_glyphs -= 1;
589 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
590 if (!data->glyphs)
591 return FT_Err_Out_Of_Memory;
593 /* first loop over `loca' and `glyf' data */
595 p = loca_table->buf;
597 if (loca_format)
599 offset_next = *(p++) << 24;
600 offset_next += *(p++) << 16;
601 offset_next += *(p++) << 8;
602 offset_next += *(p++);
604 else
606 offset_next = *(p++) << 8;
607 offset_next += *(p++);
608 offset_next <<= 1;
611 for (i = 0; i < loop_count; i++)
613 GLYPH* glyph = &data->glyphs[i];
614 FT_ULong len;
617 offset = offset_next;
619 if (loca_format)
621 offset_next = *(p++) << 24;
622 offset_next += *(p++) << 16;
623 offset_next += *(p++) << 8;
624 offset_next += *(p++);
626 else
628 offset_next = *(p++) << 8;
629 offset_next += *(p++);
630 offset_next <<= 1;
633 if (offset_next < offset
634 || offset_next > glyf_table->len)
635 return FT_Err_Invalid_Table;
637 len = offset_next - offset;
638 if (!len)
639 continue; /* empty glyph */
640 else
642 FT_Byte* buf;
645 /* check header size */
646 if (len < 10)
647 return FT_Err_Invalid_Table;
649 /* we need the number of contours and points for */
650 /* `TA_sfnt_compute_composite_pointsums' */
651 buf = glyf_table->buf + offset;
652 glyph->num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
654 if (glyph->num_contours < 0)
656 error = TA_glyph_get_components(glyph, buf, len);
657 if (error)
658 return error;
660 else
662 FT_ULong off;
665 /* use the last contour's end point to compute number of points */
666 off = 10 + (glyph->num_contours - 1) * 2;
667 if (off >= len - 1)
668 return FT_Err_Invalid_Table;
670 glyph->num_points = buf[off] << 8;
671 glyph->num_points += buf[off + 1] + 1;
676 if (sfnt->max_components && font->hint_with_components)
678 error = TA_sfnt_compute_composite_pointsums(sfnt, font);
679 if (error)
680 return error;
683 /* second loop over `loca' and `glyf' data */
685 p = loca_table->buf;
687 if (loca_format)
689 offset_next = *(p++) << 24;
690 offset_next += *(p++) << 16;
691 offset_next += *(p++) << 8;
692 offset_next += *(p++);
694 else
696 offset_next = *(p++) << 8;
697 offset_next += *(p++);
698 offset_next <<= 1;
701 for (i = 0; i < loop_count; i++)
703 GLYPH* glyph = &data->glyphs[i];
704 FT_ULong len;
707 offset = offset_next;
709 if (loca_format)
711 offset_next = *(p++) << 24;
712 offset_next += *(p++) << 16;
713 offset_next += *(p++) << 8;
714 offset_next += *(p++);
716 else
718 offset_next = *(p++) << 8;
719 offset_next += *(p++);
720 offset_next <<= 1;
723 len = offset_next - offset;
724 if (!len)
725 continue; /* empty glyph */
726 else
728 FT_Byte* buf;
731 buf = glyf_table->buf + offset;
733 /* We must parse the rest of the glyph record to get the exact */
734 /* record length. Since the `loca' table rounds record lengths */
735 /* up to multiples of 4 (or 2 for older fonts), and we must round */
736 /* up again after stripping off the instructions, it would be */
737 /* possible otherwise to have more than 4 bytes of padding which */
738 /* is more or less invalid. */
740 if (glyph->num_contours < 0)
741 error = TA_glyph_parse_composite(glyph, buf, len,
742 data->num_glyphs,
743 font->hint_with_components);
744 else
745 error = TA_glyph_parse_simple(glyph, buf, len);
746 if (error)
747 return error;
751 if (sfnt->max_components && font->hint_with_components)
753 /* construct and append our special glyph used as a composite element */
754 GLYPH* glyph = &data->glyphs[data->num_glyphs - 1];
755 FT_Byte* buf;
757 FT_Byte bytecode[] =
760 /* increment `cvtl_is_subglyph' counter */
761 PUSHB_3,
762 cvtl_is_subglyph,
764 cvtl_is_subglyph,
765 RCVT,
766 ADD,
767 WCVTP,
771 glyph->len1 = 12;
772 glyph->len2 = 1;
773 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
774 if (!glyph->buf)
775 return FT_Err_Out_Of_Memory;
777 buf = glyph->buf;
779 buf[0] = 0x00; /* one contour */
780 buf[1] = 0x01;
781 buf[2] = 0x00; /* no dimensions */
782 buf[3] = 0x00;
783 buf[4] = 0x00;
784 buf[5] = 0x00;
785 buf[6] = 0x00;
786 buf[7] = 0x00;
787 buf[8] = 0x00;
788 buf[9] = 0x00;
789 buf[10] = 0x00; /* one contour end point */
790 buf[11] = 0x00;
792 buf[12] = ON_CURVE | SAME_X | SAME_Y; /* the flags for a point at 0,0 */
794 /* add bytecode also; */
795 /* this works because the loop in `TA_sfnt_build_glyf_hints' */
796 /* doesn't include the newly appended glyph */
797 glyph->ins_len = sizeof (bytecode);
798 glyph->ins_buf = (FT_Byte*)malloc(glyph->ins_len);
799 if (!glyph->ins_buf)
800 return FT_Err_Out_Of_Memory;
801 memcpy(glyph->ins_buf, bytecode, glyph->ins_len);
803 sfnt->max_components += 1;
806 return TA_Err_Ok;
810 FT_Error
811 TA_sfnt_build_glyf_table(SFNT* sfnt,
812 FONT* font)
814 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
815 glyf_Data* data = (glyf_Data*)glyf_table->data;
817 GLYPH* glyph;
819 FT_ULong len;
820 FT_Byte* buf_new;
821 FT_Byte* p;
822 FT_UShort i;
825 if (glyf_table->processed)
826 return TA_Err_Ok;
828 /* get table size */
829 len = 0;
830 glyph = data->glyphs;
831 for (i = 0; i < data->num_glyphs; i++, glyph++)
833 /* glyph records should have offsets which are multiples of 4 */
834 len = (len + 3) & ~3;
835 len += glyph->len1 + glyph->len2 + glyph->ins_len;
836 /* add two bytes for the instructionLength field */
837 if (glyph->len2 || glyph->ins_len)
838 len += 2;
841 /* to make the short format of the `loca' table always work, */
842 /* assure an even length of the `glyf' table */
843 glyf_table->len = (len + 1) & ~1;
845 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
846 if (!buf_new)
847 return FT_Err_Out_Of_Memory;
848 else
849 glyf_table->buf = buf_new;
851 p = glyf_table->buf;
852 glyph = data->glyphs;
853 for (i = 0; i < data->num_glyphs; i++, glyph++)
855 len = glyph->len1 + glyph->len2 + glyph->ins_len;
856 if (glyph->len2 || glyph->ins_len)
857 len += 2;
859 if (len)
861 /* copy glyph data and insert new instructions */
862 memcpy(p, glyph->buf, glyph->len1);
864 if (glyph->len2)
866 /* simple glyph */
867 p += glyph->len1;
868 *(p++) = HIGH(glyph->ins_len);
869 *(p++) = LOW(glyph->ins_len);
870 memcpy(p, glyph->ins_buf, glyph->ins_len);
871 p += glyph->ins_len;
872 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
873 p += glyph->len2;
875 else
877 /* composite glyph */
878 if (glyph->ins_len)
880 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
881 p += glyph->len1;
882 *(p++) = HIGH(glyph->ins_len);
883 *(p++) = LOW(glyph->ins_len);
884 memcpy(p, glyph->ins_buf, glyph->ins_len);
885 p += glyph->ins_len;
887 else
888 p += glyph->len1;
891 /* pad with zero bytes to have an offset which is a multiple of 4; */
892 /* this works even for the last glyph record since the `glyf' */
893 /* table length is a multiple of 4 also */
894 switch (len % 4)
896 case 1:
897 *(p++) = 0;
898 case 2:
899 *(p++) = 0;
900 case 3:
901 *(p++) = 0;
902 default:
903 break;
908 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
909 glyf_table->len);
910 glyf_table->processed = 1;
912 return TA_Err_Ok;
916 static FT_Error
917 TA_create_glyph_data(FT_Outline* outline,
918 GLYPH* glyph)
920 FT_Error error = TA_Err_Ok;
922 FT_Pos xmin, ymin;
923 FT_Pos xmax, ymax;
925 FT_Byte header[10];
926 FT_Byte* flags = NULL;
927 FT_Byte* flagsp;
928 FT_Byte oldf, f;
929 FT_Byte* x = NULL;
930 FT_Byte* xp;
931 FT_Byte* y = NULL;
932 FT_Byte* yp;
934 FT_Pos lastx, lasty;
936 FT_Short i;
937 FT_Byte* p;
940 if (!outline->n_contours)
941 return TA_Err_Ok; /* empty glyph */
943 /* in case of success, all non-local allocated arrays are */
944 /* linked and eventually freed in `TA_font_unload' */
946 glyph->buf = NULL;
948 /* we use `calloc' since we rely on the array */
949 /* being initialized to zero; */
950 /* additionally, we need one more byte for a test after the loop */
951 flags = (FT_Byte*)calloc(1, outline->n_points + 1);
952 if (!flags)
954 error = FT_Err_Out_Of_Memory;
955 goto Exit;
958 /* we have either one-byte or two-byte elements */
959 x = (FT_Byte*)malloc(2 * outline->n_points);
960 if (!x)
962 error = FT_Err_Out_Of_Memory;
963 goto Exit;
966 y = (FT_Byte*)malloc(2 * outline->n_points);
967 if (!y)
969 error = FT_Err_Out_Of_Memory;
970 goto Exit;
973 flagsp = flags;
974 xp = x;
975 yp = y;
976 xmin = xmax = (outline->points[0].x + 32) >> 6;
977 ymin = ymax = (outline->points[0].y + 32) >> 6;
978 lastx = 0;
979 lasty = 0;
980 oldf = 0x80; /* start with an impossible value */
982 /* convert the FreeType representation of the glyph's outline */
983 /* into the representation format of the `glyf' table */
984 for (i = 0; i < outline->n_points; i++)
986 FT_Pos xcur = (outline->points[i].x + 32) >> 6;
987 FT_Pos ycur = (outline->points[i].y + 32) >> 6;
989 FT_Pos xdelta = xcur - lastx;
990 FT_Pos ydelta = ycur - lasty;
993 /* we are only interested in bit 0 of the `tags' array */
994 f = outline->tags[i] & ON_CURVE;
996 /* x value */
998 if (xdelta == 0)
999 f |= SAME_X;
1000 else
1002 if (xdelta < 256 && xdelta > -256)
1004 f |= X_SHORT_VECTOR;
1006 if (xdelta < 0)
1007 xdelta = -xdelta;
1008 else
1009 f |= SAME_X;
1011 *(xp++) = (FT_Byte)xdelta;
1013 else
1015 *(xp++) = HIGH(xdelta);
1016 *(xp++) = LOW(xdelta);
1020 /* y value */
1022 if (ydelta == 0)
1023 f |= SAME_Y;
1024 else
1026 if (ydelta < 256 && ydelta > -256)
1028 f |= Y_SHORT_VECTOR;
1030 if (ydelta < 0)
1031 ydelta = -ydelta;
1032 else
1033 f |= SAME_Y;
1035 *(yp++) = (FT_Byte)ydelta;
1037 else
1039 *(yp++) = HIGH(ydelta);
1040 *(yp++) = LOW(ydelta);
1044 if (f == oldf)
1046 /* set repeat flag */
1047 *(flagsp - 1) |= REPEAT;
1049 if (*flagsp == 255)
1051 /* we can only handle 256 repetitions at once, */
1052 /* so use a new counter */
1053 flagsp++;
1054 *(flagsp++) = f;
1056 else
1057 *flagsp += 1; /* increase repetition counter */
1059 else
1061 if (*flagsp)
1062 flagsp++; /* skip repetition counter */
1063 *(flagsp++) = f;
1064 oldf = f;
1067 if (xcur > xmax)
1068 xmax = xcur;
1069 if (ycur > ymax)
1070 ymax = ycur;
1071 if (xcur < xmin)
1072 xmin = xcur;
1073 if (ycur < ymin)
1074 ymin = ycur;
1076 lastx = xcur;
1077 lasty = ycur;
1080 /* if the last byte was a repetition counter, */
1081 /* we must increase by one to get the correct array size */
1082 if (*flagsp)
1083 flagsp++;
1085 header[0] = HIGH(outline->n_contours);
1086 header[1] = LOW(outline->n_contours);
1087 header[2] = HIGH(xmin);
1088 header[3] = LOW(xmin);
1089 header[4] = HIGH(ymin);
1090 header[5] = LOW(ymin);
1091 header[6] = HIGH(xmax);
1092 header[7] = LOW(xmax);
1093 header[8] = HIGH(ymax);
1094 header[9] = LOW(ymax);
1096 /* concatenate all arrays and fill needed GLYPH structure elements */
1098 glyph->len1 = 10 + 2 * outline->n_contours;
1099 glyph->len2 = (flagsp - flags) + (xp - x) + (yp - y);
1101 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
1102 if (!glyph->buf)
1104 error = FT_Err_Out_Of_Memory;
1105 goto Exit;
1108 p = glyph->buf;
1109 memcpy(p, header, 10);
1110 p += 10;
1112 glyph->ins_len = 0;
1113 glyph->ins_buf = NULL;
1115 for (i = 0; i < outline->n_contours; i++)
1117 *(p++) = HIGH(outline->contours[i]);
1118 *(p++) = LOW(outline->contours[i]);
1121 memcpy(p, flags, flagsp - flags);
1122 p += flagsp - flags;
1123 memcpy(p, x, xp - x);
1124 p += xp - x;
1125 memcpy(p, y, yp - y);
1127 Exit:
1128 free(flags);
1129 free(x);
1130 free(y);
1132 return error;
1136 /* We hint each glyph at EM size and construct a new `glyf' table. */
1137 /* Some fonts need this; in particular, */
1138 /* there are CJK fonts which use hints to scale and position subglyphs. */
1139 /* As a consequence, there are no longer composite glyphs. */
1141 FT_Error
1142 TA_sfnt_create_glyf_data(SFNT* sfnt,
1143 FONT* font)
1145 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
1146 FT_Face face = sfnt->face;
1147 FT_Error error;
1149 glyf_Data* data;
1151 FT_UShort i;
1154 /* in case of success, all allocated arrays are */
1155 /* linked and eventually freed in `TA_font_unload' */
1157 /* nothing to do if table has already been created */
1158 if (glyf_table->data)
1159 return TA_Err_Ok;
1161 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
1162 if (!data)
1163 return FT_Err_Out_Of_Memory;
1165 glyf_table->data = data;
1167 data->num_glyphs = face->num_glyphs;
1168 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
1169 if (!data->glyphs)
1170 return FT_Err_Out_Of_Memory;
1172 /* XXX: Make size configurable */
1173 /* we use the EM size */
1174 /* so that the resulting coordinates can be used without transformation */
1175 error = FT_Set_Char_Size(face, face->units_per_EM * 64, 0, 72, 0);
1176 if (error)
1177 return error;
1179 /* loop over all glyphs in font face */
1180 for (i = 0; i < data->num_glyphs; i++)
1182 GLYPH* glyph = &data->glyphs[i];
1185 error = FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP | FT_LOAD_NO_AUTOHINT);
1186 if (error)
1187 return error;
1189 error = TA_create_glyph_data(&face->glyph->outline, glyph);
1190 if (error)
1191 return error;
1194 return TA_Err_Ok;
1197 /* end of taglyf.c */