Call `TA_sfnt_compute_composite_endpoints' earlier.
[ttfautohint.git] / src / taglyf.c
blob47ffce89eda81b4e213b59260ada5cea8015f7ca
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;
198 FT_UShort num_pts;
200 FT_ULong flags_size; /* size of the flags array */
201 FT_ULong xy_size; /* size of x and y coordinate arrays together */
203 FT_Byte* p;
204 FT_Byte* endp;
206 FT_UShort i;
209 p = buf;
210 endp = buf + len;
212 ins_offset = 10 + glyph->num_contours * 2;
214 p += ins_offset;
216 if (p + 2 > endp)
217 return FT_Err_Invalid_Table;
219 /* get number of instructions */
220 num_ins = *(p++) << 8;
221 num_ins += *(p++);
223 p += num_ins;
225 if (p > endp)
226 return FT_Err_Invalid_Table;
228 num_pts = glyph->endpoint + 1;
230 flags_start = p;
231 xy_size = 0;
232 i = 0;
234 while (i < num_pts)
236 FT_Byte flags;
237 FT_Byte x_short;
238 FT_Byte y_short;
239 FT_Byte have_x;
240 FT_Byte have_y;
241 FT_Byte count;
244 if (p + 1 > endp)
245 return FT_Err_Invalid_Table;
247 flags = *(p++);
249 x_short = (flags & X_SHORT_VECTOR) ? 1 : 2;
250 y_short = (flags & Y_SHORT_VECTOR) ? 1 : 2;
252 have_x = ((flags & SAME_X) && !(flags & X_SHORT_VECTOR)) ? 0 : 1;
253 have_y = ((flags & SAME_Y) && !(flags & Y_SHORT_VECTOR)) ? 0 : 1;
255 count = 1;
257 if (flags & REPEAT)
259 if (p + 1 > endp)
260 return FT_Err_Invalid_Table;
262 count += *(p++);
264 if (i + count > num_pts)
265 return FT_Err_Invalid_Table;
268 xy_size += count * x_short * have_x;
269 xy_size += count * y_short * have_y;
271 i += count;
274 if (p + xy_size > endp)
275 return FT_Err_Invalid_Table;
277 flags_size = p - flags_start;
279 /* store the data before and after the bytecode instructions */
280 /* in the same array */
281 glyph->len1 = ins_offset;
282 glyph->len2 = flags_size + xy_size;
283 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
284 if (!glyph->buf)
285 return FT_Err_Out_Of_Memory;
287 /* now copy everything but the instructions */
288 memcpy(glyph->buf, buf, glyph->len1);
289 memcpy(glyph->buf + glyph->len1, flags_start, glyph->len2);
291 return TA_Err_Ok;
295 static FT_Error
296 TA_iterate_composite_glyph(glyf_Data* data,
297 FT_UShort* components,
298 FT_UShort num_components,
299 FT_UShort** endpoints,
300 FT_UShort* num_endpoints,
301 FT_UShort* num_composite_contours,
302 FT_UShort* num_composite_points)
304 FT_UShort* endpoints_new;
305 FT_UShort i;
308 /* save current state */
310 (*num_endpoints)++;
311 endpoints_new = (FT_UShort*)realloc(*endpoints,
312 *num_endpoints
313 * sizeof (FT_UShort));
314 if (!endpoints_new)
316 (*num_endpoints)--;
317 return FT_Err_Out_Of_Memory;
319 else
320 *endpoints = endpoints_new;
322 (*endpoints)[*num_endpoints - 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 endpoints,
342 num_endpoints,
343 num_composite_contours,
344 num_composite_points);
345 if (error)
346 return error;
348 else
350 *num_composite_contours += glyph->num_contours;
351 *num_composite_points += glyph->endpoint + 1;
355 return TA_Err_Ok;
359 /* this function actually stores `endpoint + 1' values */
361 static FT_Error
362 TA_sfnt_compute_composite_endpoints(SFNT* sfnt,
363 FONT* font)
365 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
366 glyf_Data* data = (glyf_Data*)glyf_table->data;
368 FT_UShort i;
371 for (i = 0; i < data->num_glyphs; i++)
373 GLYPH* glyph = &data->glyphs[i];
376 if (glyph->num_components)
378 FT_Error error;
379 FT_UShort num_composite_contours = 0;
380 FT_UShort num_composite_points = 0;
383 error = TA_iterate_composite_glyph(data,
384 glyph->components,
385 glyph->num_components,
386 &glyph->endpoints,
387 &glyph->num_endpoints,
388 &num_composite_contours,
389 &num_composite_points);
390 if (error)
391 return error;
393 /* update maximum values, */
394 /* including the subglyphs not in `components' array */
395 /* (each of them has a single point in a single contour) */
396 if (num_composite_points + glyph->num_endpoints
397 > sfnt->max_composite_points)
398 sfnt->max_composite_points = num_composite_points
399 + glyph->num_endpoints;
400 if (num_composite_contours + glyph->num_endpoints
401 > sfnt->max_composite_contours)
402 sfnt->max_composite_contours = num_composite_contours
403 + glyph->num_endpoints;
407 return TA_Err_Ok;
411 FT_Error
412 TA_sfnt_split_glyf_table(SFNT* sfnt,
413 FONT* font)
415 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
416 SFNT_Table* loca_table = &font->tables[sfnt->loca_idx];
417 SFNT_Table* head_table = &font->tables[sfnt->head_idx];
419 glyf_Data* data;
420 FT_Byte loca_format;
422 FT_ULong offset;
423 FT_ULong offset_next;
425 FT_Byte* p;
426 FT_UShort i;
427 FT_UShort loop_count;
429 FT_Error error;
432 /* in case of success, all allocated arrays are */
433 /* linked and eventually freed in `TA_font_unload' */
435 /* nothing to do if table has already been split */
436 if (glyf_table->data)
437 return TA_Err_Ok;
439 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
440 if (!data)
441 return FT_Err_Out_Of_Memory;
443 glyf_table->data = data;
445 loca_format = head_table->buf[LOCA_FORMAT_OFFSET];
447 data->num_glyphs = loca_format ? loca_table->len / 4
448 : loca_table->len / 2;
449 loop_count = data->num_glyphs - 1;
451 /* allocate one more glyph slot if we have composite glyphs */
452 if (!sfnt->max_components)
453 data->num_glyphs -= 1;
454 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
455 if (!data->glyphs)
456 return FT_Err_Out_Of_Memory;
458 /* first loop over `loca' and `glyf' data */
460 p = loca_table->buf;
462 if (loca_format)
464 offset_next = *(p++) << 24;
465 offset_next += *(p++) << 16;
466 offset_next += *(p++) << 8;
467 offset_next += *(p++);
469 else
471 offset_next = *(p++) << 8;
472 offset_next += *(p++);
473 offset_next <<= 1;
476 for (i = 0; i < loop_count; i++)
478 GLYPH* glyph = &data->glyphs[i];
479 FT_ULong len;
482 offset = offset_next;
484 if (loca_format)
486 offset_next = *(p++) << 24;
487 offset_next += *(p++) << 16;
488 offset_next += *(p++) << 8;
489 offset_next += *(p++);
491 else
493 offset_next = *(p++) << 8;
494 offset_next += *(p++);
495 offset_next <<= 1;
498 if (offset_next < offset
499 || offset_next > glyf_table->len)
500 return FT_Err_Invalid_Table;
502 len = offset_next - offset;
503 if (!len)
504 continue; /* empty glyph */
505 else
507 FT_Byte* buf;
510 /* check header size */
511 if (len < 10)
512 return FT_Err_Invalid_Table;
514 /* we need number of contours and the last point for */
515 /* `TA_sfnt_compute_composite_endpoints' */
516 buf = glyf_table->buf + offset;
517 glyph->num_contours = (FT_Short)((buf[0] << 8) + buf[1]);
519 if (glyph->num_contours < 0)
521 error = TA_glyph_get_components(glyph, buf, len);
522 if (error)
523 return error;
525 else
527 FT_ULong off;
530 off = 10 + (glyph->num_contours - 1) * 2;
531 glyph->endpoint = buf[off] << 8;
532 glyph->endpoint += buf[off + 1];
537 if (sfnt->max_components)
539 error = TA_sfnt_compute_composite_endpoints(sfnt, font);
540 if (error)
541 return error;
544 /* second loop over `loca' and `glyf' data */
546 p = loca_table->buf;
548 if (loca_format)
550 offset_next = *(p++) << 24;
551 offset_next += *(p++) << 16;
552 offset_next += *(p++) << 8;
553 offset_next += *(p++);
555 else
557 offset_next = *(p++) << 8;
558 offset_next += *(p++);
559 offset_next <<= 1;
562 for (i = 0; i < loop_count; i++)
564 GLYPH* glyph = &data->glyphs[i];
565 FT_ULong len;
568 offset = offset_next;
570 if (loca_format)
572 offset_next = *(p++) << 24;
573 offset_next += *(p++) << 16;
574 offset_next += *(p++) << 8;
575 offset_next += *(p++);
577 else
579 offset_next = *(p++) << 8;
580 offset_next += *(p++);
581 offset_next <<= 1;
584 len = offset_next - offset;
585 if (!len)
586 continue; /* empty glyph */
587 else
589 FT_Byte* buf;
592 buf = glyf_table->buf + offset;
594 /* We must parse the rest of the glyph record to get the exact */
595 /* record length. Since the `loca' table rounds record lengths */
596 /* up to multiples of 4 (or 2 for older fonts), and we must round */
597 /* up again after stripping off the instructions, it would be */
598 /* possible otherwise to have more than 4 bytes of padding which */
599 /* is more or less invalid. */
601 if (glyph->num_contours < 0)
602 error = TA_glyph_parse_composite(glyph, buf, data->num_glyphs);
603 else
604 error = TA_glyph_parse_simple(glyph, buf, len);
605 if (error)
606 return error;
610 if (sfnt->max_components)
612 /* construct and append our special glyph used as a composite element */
613 GLYPH* glyph = &data->glyphs[data->num_glyphs - 1];
614 FT_Byte* buf;
616 FT_Byte bytecode[] = {
618 /* increment `cvtl_is_subglyph' counter */
619 PUSHB_3,
620 cvtl_is_subglyph,
622 cvtl_is_subglyph,
623 RCVT,
624 ADD,
625 WCVTP,
629 glyph->len1 = 12;
630 glyph->len2 = 1;
631 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
632 if (!glyph->buf)
633 return FT_Err_Out_Of_Memory;
635 buf = glyph->buf;
637 buf[0] = 0x00; /* one contour */
638 buf[1] = 0x01;
639 buf[2] = 0x00; /* no dimensions */
640 buf[3] = 0x00;
641 buf[4] = 0x00;
642 buf[5] = 0x00;
643 buf[6] = 0x00;
644 buf[7] = 0x00;
645 buf[8] = 0x00;
646 buf[9] = 0x00;
647 buf[10] = 0x00; /* one contour end point */
648 buf[11] = 0x00;
650 buf[12] = ON_CURVE | SAME_X | SAME_Y; /* the flags for a point at 0,0 */
652 /* add bytecode also; */
653 /* this works because the loop in `TA_sfnt_build_glyf_hints' */
654 /* doesn't include the newly appended glyph */
655 glyph->ins_len = sizeof (bytecode);
656 glyph->ins_buf = (FT_Byte*)malloc(glyph->ins_len);
657 if (!glyph->ins_buf)
658 return FT_Err_Out_Of_Memory;
659 memcpy(glyph->ins_buf, bytecode, glyph->ins_len);
661 sfnt->max_components += 1;
664 return TA_Err_Ok;
668 FT_Error
669 TA_sfnt_build_glyf_table(SFNT* sfnt,
670 FONT* font)
672 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
673 glyf_Data* data = (glyf_Data*)glyf_table->data;
675 GLYPH* glyph;
677 FT_ULong len;
678 FT_Byte* buf_new;
679 FT_Byte* p;
680 FT_UShort i;
683 if (glyf_table->processed)
684 return TA_Err_Ok;
686 /* get table size */
687 len = 0;
688 glyph = data->glyphs;
689 for (i = 0; i < data->num_glyphs; i++, glyph++)
691 /* glyph records should have offsets which are multiples of 4 */
692 len = (len + 3) & ~3;
693 len += glyph->len1 + glyph->len2 + glyph->ins_len;
694 /* add two bytes for the instructionLength field */
695 if (glyph->len2 || glyph->ins_len)
696 len += 2;
699 /* to make the short format of the `loca' table always work, */
700 /* assure an even length of the `glyf' table */
701 glyf_table->len = (len + 1) & ~1;
703 buf_new = (FT_Byte*)realloc(glyf_table->buf, (len + 3) & ~3);
704 if (!buf_new)
705 return FT_Err_Out_Of_Memory;
706 else
707 glyf_table->buf = buf_new;
709 p = glyf_table->buf;
710 glyph = data->glyphs;
711 for (i = 0; i < data->num_glyphs; i++, glyph++)
713 len = glyph->len1 + glyph->len2 + glyph->ins_len;
714 if (glyph->len2 || glyph->ins_len)
715 len += 2;
717 if (len)
719 /* copy glyph data and insert new instructions */
720 memcpy(p, glyph->buf, glyph->len1);
722 if (glyph->len2)
724 /* simple glyph */
725 p += glyph->len1;
726 *(p++) = HIGH(glyph->ins_len);
727 *(p++) = LOW(glyph->ins_len);
728 memcpy(p, glyph->ins_buf, glyph->ins_len);
729 p += glyph->ins_len;
730 memcpy(p, glyph->buf + glyph->len1, glyph->len2);
731 p += glyph->len2;
733 else
735 /* composite glyph */
736 if (glyph->ins_len)
738 *(p + glyph->flags_offset) |= (WE_HAVE_INSTR >> 8);
739 p += glyph->len1;
740 *(p++) = HIGH(glyph->ins_len);
741 *(p++) = LOW(glyph->ins_len);
742 memcpy(p, glyph->ins_buf, glyph->ins_len);
743 p += glyph->ins_len;
745 else
746 p += glyph->len1;
749 /* pad with zero bytes to have an offset which is a multiple of 4; */
750 /* this works even for the last glyph record since the `glyf' */
751 /* table length is a multiple of 4 also */
752 switch (len % 4)
754 case 1:
755 *(p++) = 0;
756 case 2:
757 *(p++) = 0;
758 case 3:
759 *(p++) = 0;
760 default:
761 break;
766 glyf_table->checksum = TA_table_compute_checksum(glyf_table->buf,
767 glyf_table->len);
768 glyf_table->processed = 1;
770 return TA_Err_Ok;
774 static FT_Error
775 TA_create_glyph_data(FT_Outline* outline,
776 GLYPH* glyph)
778 FT_Error error = TA_Err_Ok;
780 FT_Pos xmin, ymin;
781 FT_Pos xmax, ymax;
783 FT_Byte header[10];
784 FT_Byte* flags = NULL;
785 FT_Byte* flagsp;
786 FT_Byte oldf, f;
787 FT_Byte* x = NULL;
788 FT_Byte* xp;
789 FT_Byte* y = NULL;
790 FT_Byte* yp;
792 FT_Pos lastx, lasty;
794 FT_Short i;
795 FT_Byte* p;
798 if (!outline->n_contours)
799 return TA_Err_Ok; /* empty glyph */
801 /* in case of success, all non-local allocated arrays are */
802 /* linked and eventually freed in `TA_font_unload' */
804 glyph->buf = NULL;
806 /* we use `calloc' since we rely on the array */
807 /* being initialized to zero; */
808 /* additionally, we need one more byte for a test after the loop */
809 flags = (FT_Byte*)calloc(1, outline->n_points + 1);
810 if (!flags)
812 error = FT_Err_Out_Of_Memory;
813 goto Exit;
816 /* we have either one-byte or two-byte elements */
817 x = (FT_Byte*)malloc(2 * outline->n_points);
818 if (!x)
820 error = FT_Err_Out_Of_Memory;
821 goto Exit;
824 y = (FT_Byte*)malloc(2 * outline->n_points);
825 if (!y)
827 error = FT_Err_Out_Of_Memory;
828 goto Exit;
831 flagsp = flags;
832 xp = x;
833 yp = y;
834 xmin = xmax = (outline->points[0].x + 32) >> 6;
835 ymin = ymax = (outline->points[0].y + 32) >> 6;
836 lastx = 0;
837 lasty = 0;
838 oldf = 0x80; /* start with an impossible value */
840 /* convert the FreeType representation of the glyph's outline */
841 /* into the representation format of the `glyf' table */
842 for (i = 0; i < outline->n_points; i++)
844 FT_Pos xcur = (outline->points[i].x + 32) >> 6;
845 FT_Pos ycur = (outline->points[i].y + 32) >> 6;
847 FT_Pos xdelta = xcur - lastx;
848 FT_Pos ydelta = ycur - lasty;
851 /* we are only interested in bit 0 of the `tags' array */
852 f = outline->tags[i] & ON_CURVE;
854 /* x value */
856 if (xdelta == 0)
857 f |= SAME_X;
858 else
860 if (xdelta < 256 && xdelta > -256)
862 f |= X_SHORT_VECTOR;
864 if (xdelta < 0)
865 xdelta = -xdelta;
866 else
867 f |= SAME_X;
869 *(xp++) = (FT_Byte)xdelta;
871 else
873 *(xp++) = HIGH(xdelta);
874 *(xp++) = LOW(xdelta);
878 /* y value */
880 if (ydelta == 0)
881 f |= SAME_Y;
882 else
884 if (ydelta < 256 && ydelta > -256)
886 f |= Y_SHORT_VECTOR;
888 if (ydelta < 0)
889 ydelta = -ydelta;
890 else
891 f |= SAME_Y;
893 *(yp++) = (FT_Byte)ydelta;
895 else
897 *(yp++) = HIGH(ydelta);
898 *(yp++) = LOW(ydelta);
902 if (f == oldf)
904 /* set repeat flag */
905 *(flagsp - 1) |= REPEAT;
907 if (*flagsp == 255)
909 /* we can only handle 256 repetitions at once, */
910 /* so use a new counter */
911 flagsp++;
912 *(flagsp++) = f;
914 else
915 *flagsp += 1; /* increase repetition counter */
917 else
919 if (*flagsp)
920 flagsp++; /* skip repetition counter */
921 *(flagsp++) = f;
922 oldf = f;
925 if (xcur > xmax)
926 xmax = xcur;
927 if (ycur > ymax)
928 ymax = ycur;
929 if (xcur < xmin)
930 xmin = xcur;
931 if (ycur < ymin)
932 ymin = ycur;
934 lastx = xcur;
935 lasty = ycur;
938 /* if the last byte was a repetition counter, */
939 /* we must increase by one to get the correct array size */
940 if (*flagsp)
941 flagsp++;
943 header[0] = HIGH(outline->n_contours);
944 header[1] = LOW(outline->n_contours);
945 header[2] = HIGH(xmin);
946 header[3] = LOW(xmin);
947 header[4] = HIGH(ymin);
948 header[5] = LOW(ymin);
949 header[6] = HIGH(xmax);
950 header[7] = LOW(xmax);
951 header[8] = HIGH(ymax);
952 header[9] = LOW(ymax);
954 /* concatenate all arrays and fill needed GLYPH structure elements */
956 glyph->len1 = 10 + 2 * outline->n_contours;
957 glyph->len2 = (flagsp - flags) + (xp - x) + (yp - y);
959 glyph->buf = (FT_Byte*)malloc(glyph->len1 + glyph->len2);
960 if (!glyph->buf)
962 error = FT_Err_Out_Of_Memory;
963 goto Exit;
966 p = glyph->buf;
967 memcpy(p, header, 10);
968 p += 10;
970 glyph->ins_len = 0;
971 glyph->ins_buf = NULL;
973 for (i = 0; i < outline->n_contours; i++)
975 *(p++) = HIGH(outline->contours[i]);
976 *(p++) = LOW(outline->contours[i]);
979 memcpy(p, flags, flagsp - flags);
980 p += flagsp - flags;
981 memcpy(p, x, xp - x);
982 p += xp - x;
983 memcpy(p, y, yp - y);
985 Exit:
986 free(flags);
987 free(x);
988 free(y);
990 return error;
994 /* We hint each glyph at EM size and construct a new `glyf' table. */
995 /* Some fonts need this; in particular, */
996 /* there are CJK fonts which use hints to scale and position subglyphs. */
997 /* As a consequence, there are no longer composite glyphs. */
999 FT_Error
1000 TA_sfnt_create_glyf_data(SFNT* sfnt,
1001 FONT* font)
1003 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
1004 FT_Face face = sfnt->face;
1005 FT_Error error;
1007 glyf_Data* data;
1009 FT_UShort i;
1012 /* in case of success, all allocated arrays are */
1013 /* linked and eventually freed in `TA_font_unload' */
1015 /* nothing to do if table has already been created */
1016 if (glyf_table->data)
1017 return TA_Err_Ok;
1019 data = (glyf_Data*)calloc(1, sizeof (glyf_Data));
1020 if (!data)
1021 return FT_Err_Out_Of_Memory;
1023 glyf_table->data = data;
1025 data->num_glyphs = face->num_glyphs;
1026 data->glyphs = (GLYPH*)calloc(1, data->num_glyphs * sizeof (GLYPH));
1027 if (!data->glyphs)
1028 return FT_Err_Out_Of_Memory;
1030 /* XXX: Make size configurable */
1031 /* we use the EM size */
1032 /* so that the resulting coordinates can be used without transformation */
1033 error = FT_Set_Char_Size(face, face->units_per_EM * 64, 0, 72, 0);
1034 if (error)
1035 return error;
1037 /* loop over all glyphs in font face */
1038 for (i = 0; i < data->num_glyphs; i++)
1040 GLYPH* glyph = &data->glyphs[i];
1043 error = FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP | FT_LOAD_NO_AUTOHINT);
1044 if (error)
1045 return error;
1047 error = TA_create_glyph_data(&face->glyph->outline, glyph);
1048 if (error)
1049 return error;
1052 return TA_Err_Ok;
1055 /* end of taglyf.c */