s/lower_upper/upper_lower/.
[ttfautohint.git] / lib / taglyf.c
blob5a15c246333b561028188b794e94f7af91481e71
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)
121 FT_ULong flags_offset; /* after the loop, this is the offset */
122 /* to the last element in the flags array */
123 FT_UShort flags;
125 FT_Byte* p;
126 FT_Byte* q;
129 /* we allocate too large a buffer */
130 /* (including space for the new component */
131 /* and possible argument size changes for shifted point indices) */
132 /* and reallocate it later to its real size */
133 glyph->buf = (FT_Byte*)malloc(len + 8 + glyph->num_components * 2);
134 if (!glyph->buf)
135 return FT_Err_Out_Of_Memory;
137 p = buf;
138 q = glyph->buf;
140 /* copy header */
141 memcpy(q, p, 10);
142 p += 10;
143 q += 10;
145 /* if the composite glyph contains one or more contours, */
146 /* we prepend a composite glyph component to call some bytecode */
147 /* which eventually becomes the last glyph in the `glyf' table; */
148 /* for convenience, however, it is not added to the `components' array */
149 /* (doing so simplifies the conversion of point indices later on) */
150 if (glyph->num_composite_contours)
152 FT_Short x_min;
153 FT_Short x_max;
154 FT_Short y_min;
155 FT_Short y_max;
156 FT_Short x_offset;
157 FT_Short y_offset;
160 /* the composite glyph's bounding box */
161 x_min = (FT_Short)((buf[2] << 8) + buf[3]);
162 y_min = (FT_Short)((buf[4] << 8) + buf[5]);
163 x_max = (FT_Short)((buf[6] << 8) + buf[7]);
164 y_max = (FT_Short)((buf[8] << 8) + buf[9]);
166 /* use ARGS_ARE_WORDS only if necessary; */
167 /* note that the offset value of the component doesn't matter */
168 /* as long as it stays within the bounding box */
169 if (x_min <= 0 && x_max >= 0)
170 x_offset = 0;
171 else if (x_max < 0)
172 x_offset = x_max;
173 else
174 x_offset = x_min;
176 if (y_min <= 0 && y_max >= 0)
177 y_offset = 0;
178 else if (y_max < 0)
179 y_offset = y_max;
180 else
181 y_offset = y_min;
183 if (x_offset >= -128 && x_offset <= 127
184 && y_offset >= -128 && y_offset <= 127)
186 *(q++) = 0x00;
187 *(q++) = ARGS_ARE_XY_VALUES | MORE_COMPONENTS;
188 *(q++) = HIGH(num_glyphs - 1);
189 *(q++) = LOW(num_glyphs - 1);
190 *(q++) = x_offset;
191 *(q++) = y_offset;
193 else
195 *(q++) = 0x00;
196 *(q++) = ARGS_ARE_WORDS | ARGS_ARE_XY_VALUES | MORE_COMPONENTS;
197 *(q++) = HIGH(num_glyphs - 1);
198 *(q++) = LOW(num_glyphs - 1);
199 *(q++) = HIGH(x_offset);
200 *(q++) = LOW(x_offset);
201 *(q++) = HIGH(y_offset);
202 *(q++) = LOW(y_offset);
206 /* walk over component records */
209 flags_offset = q - glyph->buf;
211 *(q++) = *p;
212 flags = *(p++) << 8;
213 *(q++) = *p;
214 flags += *(p++);
216 /* copy component */
217 *(q++) = *(p++);
218 *(q++) = *(p++);
220 if (flags & ARGS_ARE_XY_VALUES)
222 /* copy offsets */
223 *(q++) = *(p++);
224 *(q++) = *(p++);
226 if (flags & ARGS_ARE_WORDS)
228 *(q++) = *(p++);
229 *(q++) = *(p++);
232 else
234 /* handle point numbers */
235 FT_UShort arg1;
236 FT_UShort arg2;
237 FT_UShort i;
240 if (flags & ARGS_ARE_WORDS)
242 arg1 = *(p++) >> 8;
243 arg1 += *(p++);
244 arg2 = *(p++) >> 8;
245 arg2 += *(p++);
247 else
249 arg1 = *(p++);
250 arg2 = *(p++);
253 /* adjust point numbers */
254 /* (see `TA_adjust_point_index' in `tabytecode.c' for more) */
255 for (i = 0; i < glyph->num_pointsums; i++)
256 if (arg1 < glyph->pointsums[i])
257 break;
258 arg1 += i;
260 for (i = 0; i < glyph->num_pointsums; i++)
261 if (arg2 < glyph->pointsums[i])
262 break;
263 arg2 += i;
265 if (arg1 <= 0xFF && arg2 <= 0xFF)
267 glyph->buf[flags_offset + 1] &= ~ARGS_ARE_WORDS;
269 *(q++) = arg1;
270 *(q++) = arg2;
272 else
274 glyph->buf[flags_offset + 1] |= ARGS_ARE_WORDS;
276 *(q++) = HIGH(arg1);
277 *(q++) = LOW(arg1);
278 *(q++) = HIGH(arg2);
279 *(q++) = LOW(arg2);
283 /* copy scaling arguments */
284 if (flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_XY_SCALE | WE_HAVE_A_2X2))
286 *(q++) = *(p++);
287 *(q++) = *(p++);
289 if (flags & (WE_HAVE_AN_XY_SCALE | WE_HAVE_A_2X2))
291 *(q++) = *(p++);
292 *(q++) = *(p++);
294 if (flags & WE_HAVE_A_2X2)
296 *(q++) = *(p++);
297 *(q++) = *(p++);
298 *(q++) = *(p++);
299 *(q++) = *(p++);
301 } while (flags & MORE_COMPONENTS);
303 glyph->len1 = q - glyph->buf;
304 /* glyph->len2 = 0; */
305 glyph->flags_offset = flags_offset;
306 glyph->buf = (FT_Byte*)realloc(glyph->buf, glyph->len1);
308 /* we discard instructions (if any) */
309 glyph->buf[glyph->flags_offset] &= ~(WE_HAVE_INSTR >> 8);
311 return TA_Err_Ok;
315 static FT_Error
316 TA_glyph_parse_simple(GLYPH* glyph,
317 FT_Byte* buf,
318 FT_ULong len)
320 FT_ULong ins_offset;
321 FT_Byte* flags_start;
323 FT_UShort num_ins;
325 FT_ULong flags_size; /* size of the flags array */
326 FT_ULong xy_size; /* size of x and y coordinate arrays together */
328 FT_Byte* p;
329 FT_Byte* endp;
331 FT_UShort i;
334 p = buf;
335 endp = buf + len;
337 ins_offset = 10 + glyph->num_contours * 2;
339 p += ins_offset;
341 if (p + 2 > endp)
342 return FT_Err_Invalid_Table;
344 /* get number of instructions */
345 num_ins = *(p++) << 8;
346 num_ins += *(p++);
348 p += num_ins;
350 if (p > endp)
351 return FT_Err_Invalid_Table;
353 flags_start = p;
354 xy_size = 0;
355 i = 0;
357 while (i < glyph->num_points)
359 FT_Byte flags;
360 FT_Byte x_short;
361 FT_Byte y_short;
362 FT_Byte have_x;
363 FT_Byte have_y;
364 FT_Byte count;
367 if (p + 1 > endp)
368 return FT_Err_Invalid_Table;
370 flags = *(p++);
372 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
373 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
375 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
376 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
378 count = 1;
380 if (flags & REPEAT)
382 if (p + 1 > endp)
383 return FT_Err_Invalid_Table;
385 count += *(p++);
387 if (i + count > glyph->num_points)
388 return FT_Err_Invalid_Table;
391 xy_size += count * x_short * have_x;
392 xy_size += count * y_short * have_y;
394 i += count;
397 if (p + xy_size > endp)
398 return FT_Err_Invalid_Table;
400 flags_size = p - flags_start;
402 /* store the data before and after the bytecode instructions */
403 /* in the same array */
404 glyph->len1 = ins_offset;
405 glyph->len2 = flags_size + xy_size;
406 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
407 if (!glyph->buf)
408 return FT_Err_Out_Of_Memory;
410 /* now copy everything but the instructions */
411 memcpy(glyph->buf, buf, glyph->len1);
412 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
414 return TA_Err_Ok;
418 static FT_Error
419 TA_iterate_composite_glyph(glyf_Data* data,
420 FT_UShort* components,
421 FT_UShort num_components,
422 FT_UShort** pointsums,
423 FT_UShort* num_pointsums,
424 FT_UShort* num_composite_contours,
425 FT_UShort* num_composite_points)
427 FT_UShort* pointsums_new;
428 FT_UShort i;
431 /* save current state */
433 if (*num_pointsums == 0xFFFF)
434 return FT_Err_Invalid_Table;
436 (*num_pointsums)++;
437 pointsums_new = (FT_UShort*)realloc(*pointsums,
438 *num_pointsums
439 * sizeof (FT_UShort));
440 if (!pointsums_new)
442 (*num_pointsums)--;
443 return FT_Err_Out_Of_Memory;
445 else
446 *pointsums = pointsums_new;
448 (*pointsums)[*num_pointsums - 1] = *num_composite_points;
450 for (i = 0; i < num_components; i++)
452 GLYPH* glyph;
453 FT_UShort component = components[i];
454 FT_Error error;
457 if (component >= data->num_glyphs)
458 return FT_Err_Invalid_Table;
460 glyph = &data->glyphs[component];
462 if (glyph->num_components)
464 error = TA_iterate_composite_glyph(data,
465 glyph->components,
466 glyph->num_components,
467 pointsums,
468 num_pointsums,
469 num_composite_contours,
470 num_composite_points);
471 if (error)
472 return error;
474 else
476 /* no need for checking overflow of the number of contours */
477 /* since the number of points is always larger or equal */
478 if (*num_composite_points > 0xFFFF - glyph->num_points)
479 return FT_Err_Invalid_Table;
481 *num_composite_contours += glyph->num_contours;
482 *num_composite_points += glyph->num_points;
486 return TA_Err_Ok;
490 static FT_Error
491 TA_sfnt_compute_composite_pointsums(SFNT* sfnt,
492 FONT* font)
494 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
495 glyf_Data* data = (glyf_Data*)glyf_table->data;
497 FT_UShort i;
500 for (i = 0; i < data->num_glyphs; i++)
502 GLYPH* glyph = &data->glyphs[i];
505 if (glyph->num_components)
507 FT_Error error;
508 FT_UShort num_composite_contours = 0;
509 FT_UShort num_composite_points = 0;
512 error = TA_iterate_composite_glyph(data,
513 glyph->components,
514 glyph->num_components,
515 &glyph->pointsums,
516 &glyph->num_pointsums,
517 &num_composite_contours,
518 &num_composite_points);
519 if (error)
520 return error;
522 glyph->num_composite_contours = num_composite_contours;
524 /* update maximum values, */
525 /* including the subglyphs not in `components' array */
526 /* (each of them has a single point in a single contour) */
527 if (num_composite_points + glyph->num_pointsums
528 > sfnt->max_composite_points)
529 sfnt->max_composite_points = num_composite_points
530 + glyph->num_pointsums;
531 if (num_composite_contours + glyph->num_pointsums
532 > sfnt->max_composite_contours)
533 sfnt->max_composite_contours = num_composite_contours
534 + glyph->num_pointsums;
538 return TA_Err_Ok;
542 FT_Error
543 TA_sfnt_split_glyf_table(SFNT* sfnt,
544 FONT* font)
546 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
547 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
548 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
550 glyf_Data* data;
551 FT_Byte loca_format;
553 FT_ULong offset;
554 FT_ULong offset_next;
556 FT_Byte* p;
557 FT_UShort i;
558 FT_UShort loop_count;
560 FT_Error error;
563 /* in case of success, all allocated arrays are */
564 /* linked and eventually freed in `TA_font_unload' */
566 /* nothing to do if table has already been split */
567 if (glyf_table->data)
568 return TA_Err_Ok;
570 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
571 if (!data)
572 return FT_Err_Out_Of_Memory;
574 glyf_table->data = data;
576 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
578 data->num_glyphs = loca_format ? loca_table->len / 4
579 : loca_table->len / 2;
580 loop_count = data->num_glyphs - 1;
582 /* allocate one more glyph slot if we have composite glyphs */
583 if (!sfnt->max_components)
584 data->num_glyphs -= 1;
585 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
586 if (!data->glyphs)
587 return FT_Err_Out_Of_Memory;
589 /* first loop over `loca' and `glyf' data */
591 p = loca_table->buf;
593 if (loca_format)
595 offset_next = *(p++) << 24;
596 offset_next += *(p++) << 16;
597 offset_next += *(p++) << 8;
598 offset_next += *(p++);
600 else
602 offset_next = *(p++) << 8;
603 offset_next += *(p++);
604 offset_next <<= 1;
607 for (i = 0; i < loop_count; i++)
609 GLYPH* glyph = &data->glyphs[i];
610 FT_ULong len;
613 offset = offset_next;
615 if (loca_format)
617 offset_next = *(p++) << 24;
618 offset_next += *(p++) << 16;
619 offset_next += *(p++) << 8;
620 offset_next += *(p++);
622 else
624 offset_next = *(p++) << 8;
625 offset_next += *(p++);
626 offset_next <<= 1;
629 if (offset_next < offset
630 || offset_next > glyf_table->len)
631 return FT_Err_Invalid_Table;
633 len = offset_next - offset;
634 if (!len)
635 continue; /* empty glyph */
636 else
638 FT_Byte* buf;
641 /* check header size */
642 if (len < 10)
643 return FT_Err_Invalid_Table;
645 /* we need the number of contours and points for */
646 /* `TA_sfnt_compute_composite_pointsums' */
647 buf = glyf_table->buf + offset;
648 glyph->num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
650 if (glyph->num_contours < 0)
652 error = TA_glyph_get_components(glyph, buf, len);
653 if (error)
654 return error;
656 else
658 FT_ULong off;
661 /* use the last contour's end point to compute number of points */
662 off = 10 + (glyph->num_contours - 1) * 2;
663 if (off >= len - 1)
664 return FT_Err_Invalid_Table;
666 glyph->num_points = buf[off] << 8;
667 glyph->num_points += buf[off + 1] + 1;
672 if (sfnt->max_components)
674 error = TA_sfnt_compute_composite_pointsums(sfnt, font);
675 if (error)
676 return error;
679 /* second loop over `loca' and `glyf' data */
681 p = loca_table->buf;
683 if (loca_format)
685 offset_next = *(p++) << 24;
686 offset_next += *(p++) << 16;
687 offset_next += *(p++) << 8;
688 offset_next += *(p++);
690 else
692 offset_next = *(p++) << 8;
693 offset_next += *(p++);
694 offset_next <<= 1;
697 for (i = 0; i < loop_count; i++)
699 GLYPH* glyph = &data->glyphs[i];
700 FT_ULong len;
703 offset = offset_next;
705 if (loca_format)
707 offset_next = *(p++) << 24;
708 offset_next += *(p++) << 16;
709 offset_next += *(p++) << 8;
710 offset_next += *(p++);
712 else
714 offset_next = *(p++) << 8;
715 offset_next += *(p++);
716 offset_next <<= 1;
719 len = offset_next - offset;
720 if (!len)
721 continue; /* empty glyph */
722 else
724 FT_Byte* buf;
727 buf = glyf_table->buf + offset;
729 /* We must parse the rest of the glyph record to get the exact */
730 /* record length. Since the `loca' table rounds record lengths */
731 /* up to multiples of 4 (or 2 for older fonts), and we must round */
732 /* up again after stripping off the instructions, it would be */
733 /* possible otherwise to have more than 4 bytes of padding which */
734 /* is more or less invalid. */
736 if (glyph->num_contours < 0)
737 error = TA_glyph_parse_composite(glyph, buf, len, data->num_glyphs);
738 else
739 error = TA_glyph_parse_simple(glyph, buf, len);
740 if (error)
741 return error;
745 if (sfnt->max_components)
747 /* construct and append our special glyph used as a composite element */
748 GLYPH* glyph = &data->glyphs[data->num_glyphs - 1];
749 FT_Byte* buf;
751 FT_Byte bytecode[] =
754 /* increment `cvtl_is_subglyph' counter */
755 PUSHB_3,
756 cvtl_is_subglyph,
758 cvtl_is_subglyph,
759 RCVT,
760 ADD,
761 WCVTP,
765 glyph->len1 = 12;
766 glyph->len2 = 1;
767 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
768 if (!glyph->buf)
769 return FT_Err_Out_Of_Memory;
771 buf = glyph->buf;
773 buf[0] = 0x00; /* one contour */
774 buf[1] = 0x01;
775 buf[2] = 0x00; /* no dimensions */
776 buf[3] = 0x00;
777 buf[4] = 0x00;
778 buf[5] = 0x00;
779 buf[6] = 0x00;
780 buf[7] = 0x00;
781 buf[8] = 0x00;
782 buf[9] = 0x00;
783 buf[10] = 0x00; /* one contour end point */
784 buf[11] = 0x00;
786 buf[12] = ON_CURVE | SAME_X | SAME_Y; /* the flags for a point at 0,0 */
788 /* add bytecode also; */
789 /* this works because the loop in `TA_sfnt_build_glyf_hints' */
790 /* doesn't include the newly appended glyph */
791 glyph->ins_len = sizeof (bytecode);
792 glyph->ins_buf = (FT_Byte*)malloc(glyph->ins_len);
793 if (!glyph->ins_buf)
794 return FT_Err_Out_Of_Memory;
795 memcpy(glyph->ins_buf, bytecode, glyph->ins_len);
797 sfnt->max_components += 1;
800 return TA_Err_Ok;
804 FT_Error
805 TA_sfnt_build_glyf_table(SFNT* sfnt,
806 FONT* font)
808 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
809 glyf_Data* data = (glyf_Data*)glyf_table->data;
811 GLYPH* glyph;
813 FT_ULong len;
814 FT_Byte* buf_new;
815 FT_Byte* p;
816 FT_UShort i;
819 if (glyf_table->processed)
820 return TA_Err_Ok;
822 /* get table size */
823 len = 0;
824 glyph = data->glyphs;
825 for (i = 0; i < data->num_glyphs; i++, glyph++)
827 /* glyph records should have offsets which are multiples of 4 */
828 len = (len + 3) & ~3;
829 len += glyph->len1 + glyph->len2 + glyph->ins_len;
830 /* add two bytes for the instructionLength field */
831 if (glyph->len2 || glyph->ins_len)
832 len += 2;
835 /* to make the short format of the `loca' table always work, */
836 /* assure an even length of the `glyf' table */
837 glyf_table->len = (len + 1) & ~1;
839 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
840 if (!buf_new)
841 return FT_Err_Out_Of_Memory;
842 else
843 glyf_table->buf = buf_new;
845 p = glyf_table->buf;
846 glyph = data->glyphs;
847 for (i = 0; i < data->num_glyphs; i++, glyph++)
849 len = glyph->len1 + glyph->len2 + glyph->ins_len;
850 if (glyph->len2 || glyph->ins_len)
851 len += 2;
853 if (len)
855 /* copy glyph data and insert new instructions */
856 memcpy(p, glyph->buf, glyph->len1);
858 if (glyph->len2)
860 /* simple glyph */
861 p += glyph->len1;
862 *(p++) = HIGH(glyph->ins_len);
863 *(p++) = LOW(glyph->ins_len);
864 memcpy(p, glyph->ins_buf, glyph->ins_len);
865 p += glyph->ins_len;
866 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
867 p += glyph->len2;
869 else
871 /* composite glyph */
872 if (glyph->ins_len)
874 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
875 p += glyph->len1;
876 *(p++) = HIGH(glyph->ins_len);
877 *(p++) = LOW(glyph->ins_len);
878 memcpy(p, glyph->ins_buf, glyph->ins_len);
879 p += glyph->ins_len;
881 else
882 p += glyph->len1;
885 /* pad with zero bytes to have an offset which is a multiple of 4; */
886 /* this works even for the last glyph record since the `glyf' */
887 /* table length is a multiple of 4 also */
888 switch (len % 4)
890 case 1:
891 *(p++) = 0;
892 case 2:
893 *(p++) = 0;
894 case 3:
895 *(p++) = 0;
896 default:
897 break;
902 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
903 glyf_table->len);
904 glyf_table->processed = 1;
906 return TA_Err_Ok;
910 static FT_Error
911 TA_create_glyph_data(FT_Outline* outline,
912 GLYPH* glyph)
914 FT_Error error = TA_Err_Ok;
916 FT_Pos xmin, ymin;
917 FT_Pos xmax, ymax;
919 FT_Byte header[10];
920 FT_Byte* flags = NULL;
921 FT_Byte* flagsp;
922 FT_Byte oldf, f;
923 FT_Byte* x = NULL;
924 FT_Byte* xp;
925 FT_Byte* y = NULL;
926 FT_Byte* yp;
928 FT_Pos lastx, lasty;
930 FT_Short i;
931 FT_Byte* p;
934 if (!outline->n_contours)
935 return TA_Err_Ok; /* empty glyph */
937 /* in case of success, all non-local allocated arrays are */
938 /* linked and eventually freed in `TA_font_unload' */
940 glyph->buf = NULL;
942 /* we use `calloc' since we rely on the array */
943 /* being initialized to zero; */
944 /* additionally, we need one more byte for a test after the loop */
945 flags = (FT_Byte*)calloc(1, outline->n_points + 1);
946 if (!flags)
948 error = FT_Err_Out_Of_Memory;
949 goto Exit;
952 /* we have either one-byte or two-byte elements */
953 x = (FT_Byte*)malloc(2 * outline->n_points);
954 if (!x)
956 error = FT_Err_Out_Of_Memory;
957 goto Exit;
960 y = (FT_Byte*)malloc(2 * outline->n_points);
961 if (!y)
963 error = FT_Err_Out_Of_Memory;
964 goto Exit;
967 flagsp = flags;
968 xp = x;
969 yp = y;
970 xmin = xmax = (outline->points[0].x + 32) >> 6;
971 ymin = ymax = (outline->points[0].y + 32) >> 6;
972 lastx = 0;
973 lasty = 0;
974 oldf = 0x80; /* start with an impossible value */
976 /* convert the FreeType representation of the glyph's outline */
977 /* into the representation format of the `glyf' table */
978 for (i = 0; i < outline->n_points; i++)
980 FT_Pos xcur = (outline->points[i].x + 32) >> 6;
981 FT_Pos ycur = (outline->points[i].y + 32) >> 6;
983 FT_Pos xdelta = xcur - lastx;
984 FT_Pos ydelta = ycur - lasty;
987 /* we are only interested in bit 0 of the `tags' array */
988 f = outline->tags[i] & ON_CURVE;
990 /* x value */
992 if (xdelta == 0)
993 f |= SAME_X;
994 else
996 if (xdelta < 256 && xdelta > -256)
998 f |= X_SHORT_VECTOR;
1000 if (xdelta < 0)
1001 xdelta = -xdelta;
1002 else
1003 f |= SAME_X;
1005 *(xp++) = (FT_Byte)xdelta;
1007 else
1009 *(xp++) = HIGH(xdelta);
1010 *(xp++) = LOW(xdelta);
1014 /* y value */
1016 if (ydelta == 0)
1017 f |= SAME_Y;
1018 else
1020 if (ydelta < 256 && ydelta > -256)
1022 f |= Y_SHORT_VECTOR;
1024 if (ydelta < 0)
1025 ydelta = -ydelta;
1026 else
1027 f |= SAME_Y;
1029 *(yp++) = (FT_Byte)ydelta;
1031 else
1033 *(yp++) = HIGH(ydelta);
1034 *(yp++) = LOW(ydelta);
1038 if (f == oldf)
1040 /* set repeat flag */
1041 *(flagsp - 1) |= REPEAT;
1043 if (*flagsp == 255)
1045 /* we can only handle 256 repetitions at once, */
1046 /* so use a new counter */
1047 flagsp++;
1048 *(flagsp++) = f;
1050 else
1051 *flagsp += 1; /* increase repetition counter */
1053 else
1055 if (*flagsp)
1056 flagsp++; /* skip repetition counter */
1057 *(flagsp++) = f;
1058 oldf = f;
1061 if (xcur > xmax)
1062 xmax = xcur;
1063 if (ycur > ymax)
1064 ymax = ycur;
1065 if (xcur < xmin)
1066 xmin = xcur;
1067 if (ycur < ymin)
1068 ymin = ycur;
1070 lastx = xcur;
1071 lasty = ycur;
1074 /* if the last byte was a repetition counter, */
1075 /* we must increase by one to get the correct array size */
1076 if (*flagsp)
1077 flagsp++;
1079 header[0] = HIGH(outline->n_contours);
1080 header[1] = LOW(outline->n_contours);
1081 header[2] = HIGH(xmin);
1082 header[3] = LOW(xmin);
1083 header[4] = HIGH(ymin);
1084 header[5] = LOW(ymin);
1085 header[6] = HIGH(xmax);
1086 header[7] = LOW(xmax);
1087 header[8] = HIGH(ymax);
1088 header[9] = LOW(ymax);
1090 /* concatenate all arrays and fill needed GLYPH structure elements */
1092 glyph->len1 = 10 + 2 * outline->n_contours;
1093 glyph->len2 = (flagsp - flags) + (xp - x) + (yp - y);
1095 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
1096 if (!glyph->buf)
1098 error = FT_Err_Out_Of_Memory;
1099 goto Exit;
1102 p = glyph->buf;
1103 memcpy(p, header, 10);
1104 p += 10;
1106 glyph->ins_len = 0;
1107 glyph->ins_buf = NULL;
1109 for (i = 0; i < outline->n_contours; i++)
1111 *(p++) = HIGH(outline->contours[i]);
1112 *(p++) = LOW(outline->contours[i]);
1115 memcpy(p, flags, flagsp - flags);
1116 p += flagsp - flags;
1117 memcpy(p, x, xp - x);
1118 p += xp - x;
1119 memcpy(p, y, yp - y);
1121 Exit:
1122 free(flags);
1123 free(x);
1124 free(y);
1126 return error;
1130 /* We hint each glyph at EM size and construct a new `glyf' table. */
1131 /* Some fonts need this; in particular, */
1132 /* there are CJK fonts which use hints to scale and position subglyphs. */
1133 /* As a consequence, there are no longer composite glyphs. */
1135 FT_Error
1136 TA_sfnt_create_glyf_data(SFNT* sfnt,
1137 FONT* font)
1139 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
1140 FT_Face face = sfnt->face;
1141 FT_Error error;
1143 glyf_Data* data;
1145 FT_UShort i;
1148 /* in case of success, all allocated arrays are */
1149 /* linked and eventually freed in `TA_font_unload' */
1151 /* nothing to do if table has already been created */
1152 if (glyf_table->data)
1153 return TA_Err_Ok;
1155 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
1156 if (!data)
1157 return FT_Err_Out_Of_Memory;
1159 glyf_table->data = data;
1161 data->num_glyphs = face->num_glyphs;
1162 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
1163 if (!data->glyphs)
1164 return FT_Err_Out_Of_Memory;
1166 /* XXX: Make size configurable */
1167 /* we use the EM size */
1168 /* so that the resulting coordinates can be used without transformation */
1169 error = FT_Set_Char_Size(face, face->units_per_EM * 64, 0, 72, 0);
1170 if (error)
1171 return error;
1173 /* loop over all glyphs in font face */
1174 for (i = 0; i < data->num_glyphs; i++)
1176 GLYPH* glyph = &data->glyphs[i];
1179 error = FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP | FT_LOAD_NO_AUTOHINT);
1180 if (error)
1181 return error;
1183 error = TA_create_glyph_data(&face->glyph->outline, glyph);
1184 if (error)
1185 return error;
1188 return TA_Err_Ok;
1191 /* end of taglyf.c */