3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
5 /* This file needs FreeType 2.4.5 or newer. */
15 TA_font_read(FONT
* font
,
18 fseek(in
, 0, SEEK_END
);
19 font
->in_len
= ftell(in
);
20 fseek(in
, 0, SEEK_SET
);
22 /* a valid TTF can never be that small */
23 if (font
->in_len
< 100)
24 return FT_Err_Invalid_Argument
;
26 font
->in_buf
= (FT_Byte
*)malloc(font
->in_len
);
28 return FT_Err_Out_Of_Memory
;
30 if (fread(font
->in_buf
, 1, font
->in_len
, in
) != font
->in_len
)
31 return FT_Err_Invalid_Stream_Read
;
38 TA_font_init(FONT
* font
)
44 error
= FT_Init_FreeType(&font
->lib
);
48 /* get number of faces (i.e. subfonts) */
49 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
, -1, &f
);
52 font
->num_sfnts
= f
->num_faces
;
55 /* it is a TTC if we have more than a single subfont */
56 font
->sfnts
= (SFNT
*)calloc(1, font
->num_sfnts
* sizeof (SFNT
));
58 return FT_Err_Out_Of_Memory
;
65 TA_sfnt_split_into_SFNT_tables(SFNT
* sfnt
,
72 /* basic check whether font is a TTF or TTC */
73 if (!FT_IS_SFNT(sfnt
->face
))
74 return FT_Err_Invalid_Argument
;
76 error
= FT_Sfnt_Table_Info(sfnt
->face
, 0, NULL
, &sfnt
->num_table_infos
);
80 sfnt
->table_infos
= (SFNT_Table_Info
*)malloc(sfnt
->num_table_infos
81 * sizeof (SFNT_Table_Info
));
82 if (!sfnt
->table_infos
)
83 return FT_Err_Out_Of_Memory
;
85 /* collect SFNT tables and search for `glyf' and `loca' table */
86 sfnt
->glyf_idx
= MISSING
;
87 sfnt
->loca_idx
= MISSING
;
88 sfnt
->head_idx
= MISSING
;
89 sfnt
->maxp_idx
= MISSING
;
91 for (i
= 0; i
< sfnt
->num_table_infos
; i
++)
93 SFNT_Table_Info
* table_info
= &sfnt
->table_infos
[i
];
102 *table_info
= MISSING
;
104 error
= FT_Sfnt_Table_Info(sfnt
->face
, i
, &tag
, &len
);
107 /* this ignores both missing and zero-length tables */
108 if (error
== FT_Err_Table_Missing
)
114 /* ignore tables which we are going to create by ourselves, */
115 /* or which would become invalid otherwise */
116 else if (tag
== TTAG_fpgm
126 /* make the allocated buffer length a multiple of 4 */
127 buf_len
= (len
+ 3) & -3;
128 buf
= (FT_Byte
*)malloc(buf_len
);
130 return FT_Err_Out_Of_Memory
;
132 /* pad end of buffer with zeros */
133 buf
[buf_len
- 1] = 0x00;
134 buf
[buf_len
- 2] = 0x00;
135 buf
[buf_len
- 3] = 0x00;
138 error
= FT_Load_Sfnt_Table(sfnt
->face
, tag
, 0, buf
, &len
);
142 /* check whether we already have this table */
143 for (j
= 0; j
< font
->num_tables
; j
++)
145 SFNT_Table
* table
= &font
->tables
[j
];
148 if (table
->tag
== tag
150 && !memcmp(table
->buf
, buf
, len
))
154 if (tag
== TTAG_head
)
156 else if (tag
== TTAG_glyf
)
158 else if (tag
== TTAG_loca
)
160 else if (tag
== TTAG_maxp
)
163 if (j
== font
->num_tables
)
165 /* add element to table array if it is missing or different; */
166 /* in case of success, `buf' gets linked and is eventually */
167 /* freed in `TA_font_unload' */
168 error
= TA_font_add_table(font
, table_info
, tag
, len
, buf
);
174 /* reuse existing SFNT table */
185 /* no (non-empty) `glyf', `loca', `head', or `maxp' table; */
186 /* this can't be a valid TTF with outlines */
187 if (sfnt
->glyf_idx
== MISSING
188 || sfnt
->loca_idx
== MISSING
189 || sfnt
->head_idx
== MISSING
190 || sfnt
->maxp_idx
== MISSING
)
191 return FT_Err_Invalid_Argument
;
198 TA_glyph_parse_composite(GLYPH
* glyph
,
202 FT_ULong flags_offset
; /* after the loop, this is the offset */
203 /* to the last element in the flags array */
216 /* walk over component records */
220 return FT_Err_Invalid_Table
;
222 flags_offset
= p
- buf
;
227 /* skip glyph component index */
230 /* skip scaling and offset arguments */
231 if (flags
& ARGS_ARE_WORDS
)
236 if (flags
& WE_HAVE_A_SCALE
)
238 else if (flags
& WE_HAVE_AN_XY_SCALE
)
240 else if (flags
& WE_HAVE_A_2X2
)
242 } while (flags
& MORE_COMPONENTS
);
244 glyph
->flags_offset
= flags_offset
;
246 /* adjust glyph record length */
250 /* glyph->len2 = 0; */
251 glyph
->buf
= (FT_Byte
*)malloc(len
);
253 return FT_Err_Out_Of_Memory
;
255 /* copy record without instructions (if any) */
256 memcpy(glyph
->buf
, buf
, len
);
257 glyph
->buf
[flags_offset
] &= ~(WE_HAVE_INSTR
>> 8);
264 TA_glyph_parse_simple(GLYPH
* glyph
,
266 FT_UShort num_contours
,
270 FT_Byte
* flags_start
;
275 FT_ULong flags_size
; /* size of the flags array */
276 FT_ULong xy_size
; /* size of x and y coordinate arrays together */
287 ins_offset
= 10 + num_contours
* 2;
292 return FT_Err_Invalid_Table
;
294 /* get number of instructions */
295 num_ins
= *(p
++) << 8;
301 return FT_Err_Invalid_Table
;
303 /* get number of points from last outline point */
304 num_pts
= buf
[ins_offset
- 2] << 8;
305 num_pts
+= buf
[ins_offset
- 1];
323 return FT_Err_Invalid_Table
;
327 x_short
= (flags
& X_SHORT_VECTOR
) ? 1 : 2;
328 y_short
= (flags
& Y_SHORT_VECTOR
) ? 1 : 2;
330 have_x
= ((flags
& SAME_X
) && !(flags
& X_SHORT_VECTOR
)) ? 0 : 1;
331 have_y
= ((flags
& SAME_Y
) && !(flags
& Y_SHORT_VECTOR
)) ? 0 : 1;
338 return FT_Err_Invalid_Table
;
342 if (i
+ count
> num_pts
)
343 return FT_Err_Invalid_Table
;
346 xy_size
+= count
* x_short
* have_x
;
347 xy_size
+= count
* y_short
* have_y
;
352 if (p
+ xy_size
> endp
)
353 return FT_Err_Invalid_Table
;
355 flags_size
= p
- flags_start
;
357 /* store the data before and after the bytecode instructions */
358 /* in the same array */
359 glyph
->len1
= ins_offset
;
360 glyph
->len2
= flags_size
+ xy_size
;
361 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
363 return FT_Err_Out_Of_Memory
;
365 /* now copy everything but the instructions */
366 memcpy(glyph
->buf
, buf
, glyph
->len1
);
367 memcpy(glyph
->buf
+ glyph
->len1
, flags_start
, glyph
->len2
);
374 TA_sfnt_split_glyf_table(SFNT
* sfnt
,
377 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
378 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
379 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
385 FT_ULong offset_next
;
391 /* in case of success, all allocated arrays are */
392 /* linked and eventually freed in `TA_font_unload' */
394 /* nothing to do if table has already been split */
395 if (glyf_table
->data
)
398 data
= (glyf_Data
*)calloc(1, sizeof (glyf_Data
));
400 return FT_Err_Out_Of_Memory
;
402 glyf_table
->data
= data
;
404 loca_format
= head_table
->buf
[LOCA_FORMAT_OFFSET
];
406 data
->num_glyphs
= loca_format
? loca_table
->len
/ 4 - 1
407 : loca_table
->len
/ 2 - 1;
408 data
->glyphs
= (GLYPH
*)calloc(1, data
->num_glyphs
* sizeof (GLYPH
));
410 return FT_Err_Out_Of_Memory
;
416 offset_next
= *(p
++) << 24;
417 offset_next
+= *(p
++) << 16;
418 offset_next
+= *(p
++) << 8;
419 offset_next
+= *(p
++);
423 offset_next
= *(p
++) << 8;
424 offset_next
+= *(p
++);
428 /* loop over `loca' and `glyf' data */
429 for (i
= 0; i
< data
->num_glyphs
; i
++)
431 GLYPH
* glyph
= &data
->glyphs
[i
];
435 offset
= offset_next
;
439 offset_next
= *(p
++) << 24;
440 offset_next
+= *(p
++) << 16;
441 offset_next
+= *(p
++) << 8;
442 offset_next
+= *(p
++);
446 offset_next
= *(p
++) << 8;
447 offset_next
+= *(p
++);
451 if (offset_next
< offset
452 || offset_next
> glyf_table
->len
)
453 return FT_Err_Invalid_Table
;
455 len
= offset_next
- offset
;
457 continue; /* empty glyph */
461 FT_Short num_contours
;
465 /* check header size */
467 return FT_Err_Invalid_Table
;
469 buf
= glyf_table
->buf
+ offset
;
470 num_contours
= (FT_Short
)((buf
[0] << 8) + buf
[1]);
472 /* We must parse the rest of the glyph record to get the exact */
473 /* record length. Since the `loca' table rounds record lengths */
474 /* up to multiples of 4 (or 2 for older fonts), and we must round */
475 /* up again after stripping off the instructions, it would be */
476 /* possible otherwise to have more than 4 bytes of padding which */
477 /* is more or less invalid. */
479 if (num_contours
< 0)
481 error
= TA_glyph_parse_composite(glyph
, buf
, len
);
487 error
= TA_glyph_parse_simple(glyph
, buf
, num_contours
, len
);
499 TA_sfnt_build_glyf_table(SFNT
* sfnt
,
502 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
503 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
513 if (glyf_table
->processed
)
518 glyph
= data
->glyphs
;
519 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
521 /* glyph records should have offsets which are multiples of 4 */
522 len
= (len
+ 3) & ~3;
523 len
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
524 /* add two bytes for the instructionLength field */
525 if (glyph
->len2
|| glyph
->ins_len
)
529 glyf_table
->len
= len
;
530 buf_new
= (FT_Byte
*)realloc(glyf_table
->buf
, (len
+ 3) & ~3);
532 return FT_Err_Out_Of_Memory
;
534 glyf_table
->buf
= buf_new
;
537 glyph
= data
->glyphs
;
538 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
540 len
= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
541 if (glyph
->len2
|| glyph
->ins_len
)
546 /* copy glyph data and insert new instructions */
547 memcpy(p
, glyph
->buf
, glyph
->len1
);
553 *(p
++) = HIGH(glyph
->ins_len
);
554 *(p
++) = LOW(glyph
->ins_len
);
555 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
557 memcpy(p
, glyph
->buf
+ glyph
->len1
, glyph
->len2
);
562 /* composite glyph */
565 *(p
+ glyph
->flags_offset
) |= (WE_HAVE_INSTR
>> 8);
567 *(p
++) = HIGH(glyph
->ins_len
);
568 *(p
++) = LOW(glyph
->ins_len
);
569 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
576 /* pad with zero bytes to have an offset which is a multiple of 4; */
577 /* this works even for the last glyph record since the `glyf' */
578 /* table length is a multiple of 4 also */
593 glyf_table
->checksum
= TA_table_compute_checksum(glyf_table
->buf
,
595 glyf_table
->processed
= 1;
602 TA_sfnt_build_loca_table(SFNT
* sfnt
,
605 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
606 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
607 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
609 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
619 if (loca_table
->processed
)
622 /* get largest offset */
624 glyph
= data
->glyphs
;
626 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
628 /* glyph records should have offsets which are multiples of 4 */
629 offset
= (offset
+ 3) & ~3;
630 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
631 /* add two bytes for the instructionLength field */
632 if (glyph
->len2
|| glyph
->ins_len
)
636 if (offset
> 0xFFFF * 2)
644 loca_table
->len
= (data
->num_glyphs
+ 1) * 4;
645 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
, loca_table
->len
);
647 return FT_Err_Out_Of_Memory
;
649 loca_table
->buf
= buf_new
;
653 glyph
= data
->glyphs
;
655 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
657 offset
= (offset
+ 3) & ~3;
659 *(p
++) = BYTE1(offset
);
660 *(p
++) = BYTE2(offset
);
661 *(p
++) = BYTE3(offset
);
662 *(p
++) = BYTE4(offset
);
664 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
665 if (glyph
->len2
|| glyph
->ins_len
)
669 /* last element holds the size of the `glyf' table */
670 *(p
++) = BYTE1(offset
);
671 *(p
++) = BYTE2(offset
);
672 *(p
++) = BYTE3(offset
);
673 *(p
++) = BYTE4(offset
);
677 loca_table
->len
= (data
->num_glyphs
+ 1) * 2;
678 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
,
679 (loca_table
->len
+ 3) & ~3);
681 return FT_Err_Out_Of_Memory
;
683 loca_table
->buf
= buf_new
;
687 glyph
= data
->glyphs
;
689 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
691 offset
= (offset
+ 1) & ~1;
693 *(p
++) = HIGH(offset
);
694 *(p
++) = LOW(offset
);
696 offset
+= (glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
+ 1) >> 1;
697 if (glyph
->len2
|| glyph
->ins_len
)
701 /* last element holds the size of the `glyf' table */
702 *(p
++) = HIGH(offset
);
703 *(p
++) = LOW(offset
);
705 /* pad `loca' table to make its length a multiple of 4 */
706 if (loca_table
->len
% 4 == 2)
713 loca_table
->checksum
= TA_table_compute_checksum(loca_table
->buf
,
715 loca_table
->processed
= 1;
717 head_table
->buf
[LOCA_FORMAT_OFFSET
] = loca_format
;
724 TA_sfnt_update_maxp_table(SFNT
* sfnt
,
727 SFNT_Table
* maxp_table
= &font
->tables
[sfnt
->maxp_idx
];
728 FT_Byte
* buf
= maxp_table
->buf
;
731 if (maxp_table
->processed
)
734 if (maxp_table
->len
!= MAXP_LEN
)
735 return FT_Err_Invalid_Table
;
737 buf
[MAXP_MAX_ZONES_OFFSET
] = 0;
738 buf
[MAXP_MAX_ZONES_OFFSET
+ 1] = 2;
739 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
] = 0;
740 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
+ 1] = 0;
741 buf
[MAXP_MAX_STORAGE_OFFSET
] = 0;
742 buf
[MAXP_MAX_STORAGE_OFFSET
+ 1] = 0;
743 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
] = 0;
744 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
+ 1] = NUM_FDEFS
;
745 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
] = 0;
746 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
+ 1] = 0;
747 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
] = 0;
748 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
+ 1] = 0;
749 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
] = 0;
750 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
+ 1] = 0;
752 maxp_table
->checksum
= TA_table_compute_checksum(maxp_table
->buf
,
754 maxp_table
->processed
= 1;
760 /* we build a dummy `DSIG' table only */
763 TA_table_build_DSIG(FT_Byte
** DSIG
)
768 buf
= (FT_Byte
*)malloc(DSIG_LEN
);
770 return FT_Err_Out_Of_Memory
;
778 /* zero signatures */
782 /* permission flags */
793 TA_table_build_gasp(FT_Byte
** gasp
)
798 buf
= (FT_Byte
*)malloc(GASP_LEN
);
800 return FT_Err_Out_Of_Memory
;
810 /* entry valid for all sizes */
814 buf
[7] = 0x0F; /* always use grayscale rendering with grid-fitting, */
815 /* symmetric grid-fitting and symmetric smoothing */
824 TA_sfnt_build_gasp_table(SFNT
* sfnt
,
832 error
= TA_sfnt_add_table_info(sfnt
);
836 error
= TA_table_build_gasp(&gasp_buf
);
840 /* in case of success, `gasp_buf' gets linked */
841 /* and is eventually freed in `TA_font_unload' */
842 error
= TA_font_add_table(font
,
843 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
844 TTAG_gasp
, GASP_LEN
, gasp_buf
);
854 TA_font_compute_table_offsets(FONT
* font
,
858 FT_ULong offset
= start
;
861 for (i
= 0; i
< font
->num_tables
; i
++)
863 SFNT_Table
* table
= &font
->tables
[i
];
866 table
->offset
= offset
;
868 /* table offsets must be multiples of 4; */
869 /* this also fits the actual buffer lengths */
870 offset
+= (table
->len
+ 3) & ~3;
875 /* If `do_complete' is 0, only return `header_len'. */
878 TA_sfnt_build_TTF_header(SFNT
* sfnt
,
880 FT_Byte
** header_buf
,
881 FT_ULong
* header_len
,
884 SFNT_Table
* tables
= font
->tables
;
886 SFNT_Table_Info
* table_infos
= sfnt
->table_infos
;
887 FT_ULong num_table_infos
= sfnt
->num_table_infos
;
892 FT_Byte
* table_record
;
894 FT_Byte
* head_buf
= NULL
; /* pointer to `head' table */
895 FT_ULong head_checksum
; /* checksum in `head' table */
897 FT_ULong num_tables_in_header
;
901 num_tables_in_header
= 0;
902 for (i
= 0; i
< num_table_infos
; i
++)
904 /* ignore empty tables */
905 if (table_infos
[i
] != MISSING
)
906 num_tables_in_header
++;
909 len
= 12 + 16 * num_tables_in_header
;
915 buf
= (FT_Byte
*)malloc(len
);
917 return FT_Err_Out_Of_Memory
;
925 /* number of tables */
926 buf
[4] = HIGH(num_tables_in_header
);
927 buf
[5] = LOW(num_tables_in_header
);
931 FT_ULong search_range
, entry_selector
, range_shift
;
935 for (i
= 1, j
= 2; j
<= num_tables_in_header
; i
++, j
<<= 1)
938 entry_selector
= i
- 1;
939 search_range
= 0x10 << entry_selector
;
940 range_shift
= (num_tables_in_header
<< 4) - search_range
;
942 buf
[6] = HIGH(search_range
);
943 buf
[7] = LOW(search_range
);
944 buf
[8] = HIGH(entry_selector
);
945 buf
[9] = LOW(entry_selector
);
946 buf
[10] = HIGH(range_shift
);
947 buf
[11] = LOW(range_shift
);
950 /* location of the first table info record */
951 table_record
= &buf
[12];
955 /* loop over all tables */
956 for (i
= 0; i
< num_table_infos
; i
++)
958 SFNT_Table_Info table_info
= table_infos
[i
];
962 /* ignore empty slots */
963 if (table_info
== MISSING
)
966 table
= &tables
[table_info
];
968 if (table
->tag
== TTAG_head
)
970 /* we always reach this IF clause since FreeType would */
971 /* have aborted already if the `head' table were missing */
973 head_buf
= table
->buf
;
975 /* reset checksum in `head' table for recalculation */
982 head_checksum
+= table
->checksum
;
984 table_record
[0] = BYTE1(table
->tag
);
985 table_record
[1] = BYTE2(table
->tag
);
986 table_record
[2] = BYTE3(table
->tag
);
987 table_record
[3] = BYTE4(table
->tag
);
989 table_record
[4] = BYTE1(table
->checksum
);
990 table_record
[5] = BYTE2(table
->checksum
);
991 table_record
[6] = BYTE3(table
->checksum
);
992 table_record
[7] = BYTE4(table
->checksum
);
994 table_record
[8] = BYTE1(table
->offset
);
995 table_record
[9] = BYTE2(table
->offset
);
996 table_record
[10] = BYTE3(table
->offset
);
997 table_record
[11] = BYTE4(table
->offset
);
999 table_record
[12] = BYTE1(table
->len
);
1000 table_record
[13] = BYTE2(table
->len
);
1001 table_record
[14] = BYTE3(table
->len
);
1002 table_record
[15] = BYTE4(table
->len
);
1007 /* the font header is complete; compute `head' checksum */
1008 head_checksum
+= TA_table_compute_checksum(buf
, len
);
1009 head_checksum
= 0xB1B0AFBAUL
- head_checksum
;
1011 /* store checksum in `head' table; */
1012 head_buf
[8] = BYTE1(head_checksum
);
1013 head_buf
[9] = BYTE2(head_checksum
);
1014 head_buf
[10] = BYTE3(head_checksum
);
1015 head_buf
[11] = BYTE4(head_checksum
);
1025 TA_font_build_TTF(FONT
* font
)
1027 SFNT
* sfnt
= &font
->sfnts
[0];
1030 FT_ULong num_tables
;
1032 FT_ULong SFNT_offset
;
1036 FT_Byte
* header_buf
;
1037 FT_ULong header_len
;
1043 /* add a dummy `DSIG' table */
1045 error
= TA_sfnt_add_table_info(sfnt
);
1049 error
= TA_table_build_DSIG(&DSIG_buf
);
1053 /* in case of success, `DSIG_buf' gets linked */
1054 /* and is eventually freed in `TA_font_unload' */
1055 error
= TA_font_add_table(font
,
1056 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
1057 TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1064 TA_sfnt_sort_table_info(sfnt
, font
);
1066 /* the first SFNT table immediately follows the header */
1067 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &SFNT_offset
, 0);
1068 TA_font_compute_table_offsets(font
, SFNT_offset
);
1070 error
= TA_sfnt_build_TTF_header(sfnt
, font
,
1071 &header_buf
, &header_len
, 1);
1077 tables
= font
->tables
;
1078 num_tables
= font
->num_tables
;
1080 /* get font length from last SFNT table array element */
1081 font
->out_len
= tables
[num_tables
- 1].offset
1082 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1083 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1086 error
= FT_Err_Out_Of_Memory
;
1090 memcpy(font
->out_buf
, header_buf
, header_len
);
1092 for (i
= 0; i
< num_tables
; i
++)
1094 SFNT_Table
* table
= &tables
[i
];
1097 /* buffer length is a multiple of 4 */
1098 memcpy(font
->out_buf
+ table
->offset
,
1099 table
->buf
, (table
->len
+ 3) & ~3);
1112 TA_font_build_TTC_header(FONT
* font
,
1113 FT_Byte
** header_buf
,
1114 FT_ULong
* header_len
)
1116 SFNT
* sfnts
= font
->sfnts
;
1117 FT_Long num_sfnts
= font
->num_sfnts
;
1119 SFNT_Table
* tables
= font
->tables
;
1120 FT_ULong num_tables
= font
->num_tables
;
1122 FT_ULong TTF_offset
;
1123 FT_ULong DSIG_offset
;
1132 len
= 24 + 4 * num_sfnts
;
1133 buf
= (FT_Byte
*)malloc(len
);
1135 return FT_Err_Out_Of_Memory
;
1145 /* TTC header version */
1151 /* number of subfonts */
1152 *(p
++) = BYTE1(num_sfnts
);
1153 *(p
++) = BYTE2(num_sfnts
);
1154 *(p
++) = BYTE3(num_sfnts
);
1155 *(p
++) = BYTE4(num_sfnts
);
1157 /* the first TTF subfont header immediately follows the TTC header */
1160 /* loop over all subfonts */
1161 for (i
= 0; i
< num_sfnts
; i
++)
1163 SFNT
* sfnt
= &sfnts
[i
];
1167 TA_sfnt_sort_table_info(sfnt
, font
);
1168 /* only get header length */
1169 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &l
, 0);
1171 *(p
++) = BYTE1(TTF_offset
);
1172 *(p
++) = BYTE2(TTF_offset
);
1173 *(p
++) = BYTE3(TTF_offset
);
1174 *(p
++) = BYTE4(TTF_offset
);
1179 /* the first SFNT table immediately follows the subfont TTF headers */
1180 TA_font_compute_table_offsets(font
, TTF_offset
);
1194 /* DSIG offset; in a TTC this is always the last SFNT table */
1195 DSIG_offset
= tables
[num_tables
- 1].offset
;
1197 *(p
++) = BYTE1(DSIG_offset
);
1198 *(p
++) = BYTE2(DSIG_offset
);
1199 *(p
++) = BYTE3(DSIG_offset
);
1200 *(p
++) = BYTE4(DSIG_offset
);
1210 TA_font_build_TTC(FONT
* font
)
1212 SFNT
* sfnts
= font
->sfnts
;
1213 FT_Long num_sfnts
= font
->num_sfnts
;
1216 FT_ULong num_tables
;
1219 SFNT_Table_Info dummy
;
1221 FT_Byte
* TTC_header_buf
;
1222 FT_ULong TTC_header_len
;
1224 FT_Byte
** TTF_header_bufs
;
1225 FT_ULong
* TTF_header_lens
;
1233 /* add a dummy `DSIG' table */
1235 error
= TA_table_build_DSIG(&DSIG_buf
);
1239 /* in case of success, `DSIG_buf' gets linked */
1240 /* and is eventually freed in `TA_font_unload' */
1241 error
= TA_font_add_table(font
, &dummy
, TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1248 /* this also computes the SFNT table offsets */
1249 error
= TA_font_build_TTC_header(font
,
1250 &TTC_header_buf
, &TTC_header_len
);
1254 TTF_header_bufs
= (FT_Byte
**)calloc(1, num_sfnts
* sizeof (FT_Byte
*));
1255 if (!TTF_header_bufs
)
1258 TTF_header_lens
= (FT_ULong
*)malloc(num_sfnts
* sizeof (FT_ULong
));
1259 if (!TTF_header_lens
)
1262 for (i
= 0; i
< num_sfnts
; i
++)
1264 error
= TA_sfnt_build_TTF_header(&sfnts
[i
], font
,
1265 &TTF_header_bufs
[i
],
1266 &TTF_header_lens
[i
], 1);
1273 tables
= font
->tables
;
1274 num_tables
= font
->num_tables
;
1276 /* get font length from last SFNT table array element */
1277 font
->out_len
= tables
[num_tables
- 1].offset
1278 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1279 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1282 error
= FT_Err_Out_Of_Memory
;
1286 memcpy(font
->out_buf
, TTC_header_buf
, TTC_header_len
);
1288 offset
= TTC_header_len
;
1290 for (i
= 0; i
< num_sfnts
; i
++)
1292 memcpy(font
->out_buf
+ offset
,
1293 TTF_header_bufs
[i
], TTF_header_lens
[i
]);
1295 offset
+= TTF_header_lens
[i
];
1298 for (j
= 0; j
< num_tables
; j
++)
1300 SFNT_Table
* table
= &tables
[j
];
1303 /* buffer length is a multiple of 4 */
1304 memcpy(font
->out_buf
+ table
->offset
,
1305 table
->buf
, (table
->len
+ 3) & ~3);
1311 free(TTC_header_buf
);
1312 if (TTF_header_bufs
)
1314 for (i
= 0; i
< font
->num_sfnts
; i
++)
1315 free(TTF_header_bufs
[i
]);
1316 free(TTF_header_bufs
);
1318 free(TTF_header_lens
);
1325 TA_font_write(FONT
* font
,
1328 if (fwrite(font
->out_buf
, 1, font
->out_len
, out
) != font
->out_len
)
1329 return TA_Err_Invalid_Stream_Write
;
1336 TA_font_unload(FONT
* font
)
1338 /* in case of error it is expected that unallocated pointers */
1339 /* are NULL (and counters are zero) */
1345 ta_loader_done(font
->loader
);
1352 for (i
= 0; i
< font
->num_tables
; i
++)
1354 free(font
->tables
[i
].buf
);
1355 if (font
->tables
[i
].data
)
1357 if (font
->tables
[i
].tag
== TTAG_glyf
)
1359 glyf_Data
* data
= (glyf_Data
*)font
->tables
[i
].data
;
1363 for (j
= 0; j
< data
->num_glyphs
; j
++)
1364 free(data
->glyphs
[j
].buf
);
1378 for (i
= 0; i
< font
->num_sfnts
; i
++)
1380 FT_Done_Face(font
->sfnts
[i
].face
);
1381 free(font
->sfnts
[i
].table_infos
);
1386 FT_Done_FreeType(font
->lib
);
1388 free(font
->out_buf
);
1394 TTF_autohint(FILE* in
,
1402 font
= (FONT
*)calloc(1, sizeof (FONT
));
1404 return FT_Err_Out_Of_Memory
;
1406 error
= TA_font_read(font
, in
);
1410 error
= TA_font_init(font
);
1414 /* loop over subfonts */
1415 for (i
= 0; i
< font
->num_sfnts
; i
++)
1417 SFNT
* sfnt
= &font
->sfnts
[i
];
1420 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
1425 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
1429 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
1434 /* build `gasp' table */
1435 error
= TA_sfnt_build_gasp_table(&font
->sfnts
[0], font
);
1439 /* XXX handle subfonts for bytecode tables? */
1441 /* build `cvt ' table */
1442 error
= TA_sfnt_build_cvt_table(&font
->sfnts
[0], font
);
1446 /* build `fpgm' table */
1447 error
= TA_sfnt_build_fpgm_table(&font
->sfnts
[0], font
);
1451 /* build `prep' table */
1452 error
= TA_sfnt_build_prep_table(&font
->sfnts
[0], font
);
1456 /* handle all glyphs in a loop */
1457 /* hint the glyph */
1458 /* build bytecode */
1460 /* adjust `maxp' table */
1462 /* loop again over subfonts */
1463 for (i
= 0; i
< font
->num_sfnts
; i
++)
1465 SFNT
* sfnt
= &font
->sfnts
[i
];
1468 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
1471 error
= TA_sfnt_build_loca_table(sfnt
, font
);
1474 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
1479 if (font
->num_sfnts
== 1)
1480 error
= TA_font_build_TTF(font
);
1482 error
= TA_font_build_TTC(font
);
1486 error
= TA_font_write(font
, out
);
1493 TA_font_unload(font
);
1498 /* end of ttfautohint.c */