3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
5 /* This file needs FreeType 2.4.5 or newer. */
16 TA_font_file_read(FONT
* font
,
19 fseek(in_file
, 0, SEEK_END
);
20 font
->in_len
= ftell(in_file
);
21 fseek(in_file
, 0, SEEK_SET
);
23 /* a valid TTF can never be that small */
24 if (font
->in_len
< 100)
25 return FT_Err_Invalid_Argument
;
27 font
->in_buf
= (FT_Byte
*)malloc(font
->in_len
);
29 return FT_Err_Out_Of_Memory
;
31 if (fread(font
->in_buf
, 1, font
->in_len
, in_file
) != font
->in_len
)
32 return FT_Err_Invalid_Stream_Read
;
39 TA_font_init(FONT
* font
)
45 error
= FT_Init_FreeType(&font
->lib
);
49 /* get number of faces (i.e. subfonts) */
50 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
, -1, &f
);
53 font
->num_sfnts
= f
->num_faces
;
56 /* it is a TTC if we have more than a single subfont */
57 font
->sfnts
= (SFNT
*)calloc(1, font
->num_sfnts
* sizeof (SFNT
));
59 return FT_Err_Out_Of_Memory
;
66 TA_sfnt_split_into_SFNT_tables(SFNT
* sfnt
,
73 /* basic check whether font is a TTF or TTC */
74 if (!FT_IS_SFNT(sfnt
->face
))
75 return FT_Err_Invalid_Argument
;
77 error
= FT_Sfnt_Table_Info(sfnt
->face
, 0, NULL
, &sfnt
->num_table_infos
);
81 sfnt
->table_infos
= (SFNT_Table_Info
*)malloc(sfnt
->num_table_infos
82 * sizeof (SFNT_Table_Info
));
83 if (!sfnt
->table_infos
)
84 return FT_Err_Out_Of_Memory
;
86 /* collect SFNT tables and search for `glyf' and `loca' table */
87 sfnt
->glyf_idx
= MISSING
;
88 sfnt
->loca_idx
= MISSING
;
89 sfnt
->head_idx
= MISSING
;
90 sfnt
->maxp_idx
= MISSING
;
92 for (i
= 0; i
< sfnt
->num_table_infos
; i
++)
94 SFNT_Table_Info
* table_info
= &sfnt
->table_infos
[i
];
103 *table_info
= MISSING
;
105 error
= FT_Sfnt_Table_Info(sfnt
->face
, i
, &tag
, &len
);
108 /* this ignores both missing and zero-length tables */
109 if (error
== FT_Err_Table_Missing
)
115 /* ignore tables which we are going to create by ourselves, */
116 /* or which would become invalid otherwise */
117 else if (tag
== TTAG_fpgm
127 /* make the allocated buffer length a multiple of 4 */
128 buf_len
= (len
+ 3) & -3;
129 buf
= (FT_Byte
*)malloc(buf_len
);
131 return FT_Err_Out_Of_Memory
;
133 /* pad end of buffer with zeros */
134 buf
[buf_len
- 1] = 0x00;
135 buf
[buf_len
- 2] = 0x00;
136 buf
[buf_len
- 3] = 0x00;
139 error
= FT_Load_Sfnt_Table(sfnt
->face
, tag
, 0, buf
, &len
);
143 /* check whether we already have this table */
144 for (j
= 0; j
< font
->num_tables
; j
++)
146 SFNT_Table
* table
= &font
->tables
[j
];
149 if (table
->tag
== tag
151 && !memcmp(table
->buf
, buf
, len
))
155 if (tag
== TTAG_head
)
157 else if (tag
== TTAG_glyf
)
159 else if (tag
== TTAG_loca
)
161 else if (tag
== TTAG_maxp
)
164 if (j
== font
->num_tables
)
166 /* add element to table array if it is missing or different; */
167 /* in case of success, `buf' gets linked and is eventually */
168 /* freed in `TA_font_unload' */
169 error
= TA_font_add_table(font
, table_info
, tag
, len
, buf
);
175 /* reuse existing SFNT table */
186 /* no (non-empty) `glyf', `loca', `head', or `maxp' table; */
187 /* this can't be a valid TTF with outlines */
188 if (sfnt
->glyf_idx
== MISSING
189 || sfnt
->loca_idx
== MISSING
190 || sfnt
->head_idx
== MISSING
191 || sfnt
->maxp_idx
== MISSING
)
192 return FT_Err_Invalid_Argument
;
199 TA_glyph_parse_composite(GLYPH
* glyph
,
203 FT_ULong flags_offset
; /* after the loop, this is the offset */
204 /* to the last element in the flags array */
217 /* walk over component records */
221 return FT_Err_Invalid_Table
;
223 flags_offset
= p
- buf
;
228 /* skip glyph component index */
231 /* skip scaling and offset arguments */
232 if (flags
& ARGS_ARE_WORDS
)
237 if (flags
& WE_HAVE_A_SCALE
)
239 else if (flags
& WE_HAVE_AN_XY_SCALE
)
241 else if (flags
& WE_HAVE_A_2X2
)
243 } while (flags
& MORE_COMPONENTS
);
245 glyph
->flags_offset
= flags_offset
;
247 /* adjust glyph record length */
251 /* glyph->len2 = 0; */
252 glyph
->buf
= (FT_Byte
*)malloc(len
);
254 return FT_Err_Out_Of_Memory
;
256 /* copy record without instructions (if any) */
257 memcpy(glyph
->buf
, buf
, len
);
258 glyph
->buf
[flags_offset
] &= ~(WE_HAVE_INSTR
>> 8);
265 TA_glyph_parse_simple(GLYPH
* glyph
,
267 FT_UShort num_contours
,
271 FT_Byte
* flags_start
;
276 FT_ULong flags_size
; /* size of the flags array */
277 FT_ULong xy_size
; /* size of x and y coordinate arrays together */
288 ins_offset
= 10 + num_contours
* 2;
293 return FT_Err_Invalid_Table
;
295 /* get number of instructions */
296 num_ins
= *(p
++) << 8;
302 return FT_Err_Invalid_Table
;
304 /* get number of points from last outline point */
305 num_pts
= buf
[ins_offset
- 2] << 8;
306 num_pts
+= buf
[ins_offset
- 1];
324 return FT_Err_Invalid_Table
;
328 x_short
= (flags
& X_SHORT_VECTOR
) ? 1 : 2;
329 y_short
= (flags
& Y_SHORT_VECTOR
) ? 1 : 2;
331 have_x
= ((flags
& SAME_X
) && !(flags
& X_SHORT_VECTOR
)) ? 0 : 1;
332 have_y
= ((flags
& SAME_Y
) && !(flags
& Y_SHORT_VECTOR
)) ? 0 : 1;
339 return FT_Err_Invalid_Table
;
343 if (i
+ count
> num_pts
)
344 return FT_Err_Invalid_Table
;
347 xy_size
+= count
* x_short
* have_x
;
348 xy_size
+= count
* y_short
* have_y
;
353 if (p
+ xy_size
> endp
)
354 return FT_Err_Invalid_Table
;
356 flags_size
= p
- flags_start
;
358 /* store the data before and after the bytecode instructions */
359 /* in the same array */
360 glyph
->len1
= ins_offset
;
361 glyph
->len2
= flags_size
+ xy_size
;
362 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
364 return FT_Err_Out_Of_Memory
;
366 /* now copy everything but the instructions */
367 memcpy(glyph
->buf
, buf
, glyph
->len1
);
368 memcpy(glyph
->buf
+ glyph
->len1
, flags_start
, glyph
->len2
);
375 TA_sfnt_split_glyf_table(SFNT
* sfnt
,
378 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
379 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
380 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
386 FT_ULong offset_next
;
392 /* in case of success, all allocated arrays are */
393 /* linked and eventually freed in `TA_font_unload' */
395 /* nothing to do if table has already been split */
396 if (glyf_table
->data
)
399 data
= (glyf_Data
*)calloc(1, sizeof (glyf_Data
));
401 return FT_Err_Out_Of_Memory
;
403 glyf_table
->data
= data
;
405 loca_format
= head_table
->buf
[LOCA_FORMAT_OFFSET
];
407 data
->num_glyphs
= loca_format
? loca_table
->len
/ 4 - 1
408 : loca_table
->len
/ 2 - 1;
409 data
->glyphs
= (GLYPH
*)calloc(1, data
->num_glyphs
* sizeof (GLYPH
));
411 return FT_Err_Out_Of_Memory
;
417 offset_next
= *(p
++) << 24;
418 offset_next
+= *(p
++) << 16;
419 offset_next
+= *(p
++) << 8;
420 offset_next
+= *(p
++);
424 offset_next
= *(p
++) << 8;
425 offset_next
+= *(p
++);
429 /* loop over `loca' and `glyf' data */
430 for (i
= 0; i
< data
->num_glyphs
; i
++)
432 GLYPH
* glyph
= &data
->glyphs
[i
];
436 offset
= offset_next
;
440 offset_next
= *(p
++) << 24;
441 offset_next
+= *(p
++) << 16;
442 offset_next
+= *(p
++) << 8;
443 offset_next
+= *(p
++);
447 offset_next
= *(p
++) << 8;
448 offset_next
+= *(p
++);
452 if (offset_next
< offset
453 || offset_next
> glyf_table
->len
)
454 return FT_Err_Invalid_Table
;
456 len
= offset_next
- offset
;
458 continue; /* empty glyph */
462 FT_Short num_contours
;
466 /* check header size */
468 return FT_Err_Invalid_Table
;
470 buf
= glyf_table
->buf
+ offset
;
471 num_contours
= (FT_Short
)((buf
[0] << 8) + buf
[1]);
473 /* We must parse the rest of the glyph record to get the exact */
474 /* record length. Since the `loca' table rounds record lengths */
475 /* up to multiples of 4 (or 2 for older fonts), and we must round */
476 /* up again after stripping off the instructions, it would be */
477 /* possible otherwise to have more than 4 bytes of padding which */
478 /* is more or less invalid. */
480 if (num_contours
< 0)
482 error
= TA_glyph_parse_composite(glyph
, buf
, len
);
488 error
= TA_glyph_parse_simple(glyph
, buf
, num_contours
, len
);
500 TA_sfnt_build_glyf_table(SFNT
* sfnt
,
503 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
504 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
514 if (glyf_table
->processed
)
519 glyph
= data
->glyphs
;
520 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
522 /* glyph records should have offsets which are multiples of 4 */
523 len
= (len
+ 3) & ~3;
524 len
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
525 /* add two bytes for the instructionLength field */
526 if (glyph
->len2
|| glyph
->ins_len
)
530 glyf_table
->len
= len
;
531 buf_new
= (FT_Byte
*)realloc(glyf_table
->buf
, (len
+ 3) & ~3);
533 return FT_Err_Out_Of_Memory
;
535 glyf_table
->buf
= buf_new
;
538 glyph
= data
->glyphs
;
539 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
541 len
= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
542 if (glyph
->len2
|| glyph
->ins_len
)
547 /* copy glyph data and insert new instructions */
548 memcpy(p
, glyph
->buf
, glyph
->len1
);
554 *(p
++) = HIGH(glyph
->ins_len
);
555 *(p
++) = LOW(glyph
->ins_len
);
556 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
558 memcpy(p
, glyph
->buf
+ glyph
->len1
, glyph
->len2
);
563 /* composite glyph */
566 *(p
+ glyph
->flags_offset
) |= (WE_HAVE_INSTR
>> 8);
568 *(p
++) = HIGH(glyph
->ins_len
);
569 *(p
++) = LOW(glyph
->ins_len
);
570 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
577 /* pad with zero bytes to have an offset which is a multiple of 4; */
578 /* this works even for the last glyph record since the `glyf' */
579 /* table length is a multiple of 4 also */
594 glyf_table
->checksum
= TA_table_compute_checksum(glyf_table
->buf
,
596 glyf_table
->processed
= 1;
603 TA_sfnt_build_loca_table(SFNT
* sfnt
,
606 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
607 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
608 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
610 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
620 if (loca_table
->processed
)
623 /* get largest offset */
625 glyph
= data
->glyphs
;
627 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
629 /* glyph records should have offsets which are multiples of 4 */
630 offset
= (offset
+ 3) & ~3;
631 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
632 /* add two bytes for the instructionLength field */
633 if (glyph
->len2
|| glyph
->ins_len
)
637 if (offset
> 0xFFFF * 2)
645 loca_table
->len
= (data
->num_glyphs
+ 1) * 4;
646 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
, loca_table
->len
);
648 return FT_Err_Out_Of_Memory
;
650 loca_table
->buf
= buf_new
;
654 glyph
= data
->glyphs
;
656 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
658 offset
= (offset
+ 3) & ~3;
660 *(p
++) = BYTE1(offset
);
661 *(p
++) = BYTE2(offset
);
662 *(p
++) = BYTE3(offset
);
663 *(p
++) = BYTE4(offset
);
665 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
666 if (glyph
->len2
|| glyph
->ins_len
)
670 /* last element holds the size of the `glyf' table */
671 *(p
++) = BYTE1(offset
);
672 *(p
++) = BYTE2(offset
);
673 *(p
++) = BYTE3(offset
);
674 *(p
++) = BYTE4(offset
);
678 loca_table
->len
= (data
->num_glyphs
+ 1) * 2;
679 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
,
680 (loca_table
->len
+ 3) & ~3);
682 return FT_Err_Out_Of_Memory
;
684 loca_table
->buf
= buf_new
;
688 glyph
= data
->glyphs
;
690 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
692 offset
= (offset
+ 1) & ~1;
694 *(p
++) = HIGH(offset
);
695 *(p
++) = LOW(offset
);
697 offset
+= (glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
+ 1) >> 1;
698 if (glyph
->len2
|| glyph
->ins_len
)
702 /* last element holds the size of the `glyf' table */
703 *(p
++) = HIGH(offset
);
704 *(p
++) = LOW(offset
);
706 /* pad `loca' table to make its length a multiple of 4 */
707 if (loca_table
->len
% 4 == 2)
714 loca_table
->checksum
= TA_table_compute_checksum(loca_table
->buf
,
716 loca_table
->processed
= 1;
718 head_table
->buf
[LOCA_FORMAT_OFFSET
] = loca_format
;
725 TA_sfnt_update_maxp_table(SFNT
* sfnt
,
728 SFNT_Table
* maxp_table
= &font
->tables
[sfnt
->maxp_idx
];
729 FT_Byte
* buf
= maxp_table
->buf
;
732 if (maxp_table
->processed
)
735 if (maxp_table
->len
!= MAXP_LEN
)
736 return FT_Err_Invalid_Table
;
738 buf
[MAXP_MAX_ZONES_OFFSET
] = 0;
739 buf
[MAXP_MAX_ZONES_OFFSET
+ 1] = 2;
740 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
] = HIGH(sfnt
->max_twilight_points
);
741 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
+ 1] = LOW(sfnt
->max_twilight_points
);
742 buf
[MAXP_MAX_STORAGE_OFFSET
] = HIGH(sfnt
->max_storage
);
743 buf
[MAXP_MAX_STORAGE_OFFSET
+ 1] = LOW(sfnt
->max_storage
);
744 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
] = 0;
745 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
+ 1] = NUM_FDEFS
;
746 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
] = 0;
747 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
+ 1] = 0;
748 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
] = HIGH(sfnt
->max_stack_elements
);
749 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
+ 1] = LOW(sfnt
->max_stack_elements
);
750 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
] = HIGH(sfnt
->max_instructions
);
751 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
+ 1] = LOW(sfnt
->max_instructions
);
753 maxp_table
->checksum
= TA_table_compute_checksum(maxp_table
->buf
,
755 maxp_table
->processed
= 1;
761 /* we build a dummy `DSIG' table only */
764 TA_table_build_DSIG(FT_Byte
** DSIG
)
769 buf
= (FT_Byte
*)malloc(DSIG_LEN
);
771 return FT_Err_Out_Of_Memory
;
779 /* zero signatures */
783 /* permission flags */
794 TA_table_build_gasp(FT_Byte
** gasp
)
799 buf
= (FT_Byte
*)malloc(GASP_LEN
);
801 return FT_Err_Out_Of_Memory
;
811 /* entry valid for all sizes */
815 buf
[7] = 0x0F; /* always use grayscale rendering with grid-fitting, */
816 /* symmetric grid-fitting and symmetric smoothing */
825 TA_sfnt_build_gasp_table(SFNT
* sfnt
,
833 error
= TA_sfnt_add_table_info(sfnt
);
837 error
= TA_table_build_gasp(&gasp_buf
);
841 /* in case of success, `gasp_buf' gets linked */
842 /* and is eventually freed in `TA_font_unload' */
843 error
= TA_font_add_table(font
,
844 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
845 TTAG_gasp
, GASP_LEN
, gasp_buf
);
857 TA_font_compute_table_offsets(FONT
* font
,
861 FT_ULong offset
= start
;
864 for (i
= 0; i
< font
->num_tables
; i
++)
866 SFNT_Table
* table
= &font
->tables
[i
];
869 table
->offset
= offset
;
871 /* table offsets must be multiples of 4; */
872 /* this also fits the actual buffer lengths */
873 offset
+= (table
->len
+ 3) & ~3;
878 /* If `do_complete' is 0, only return `header_len'. */
881 TA_sfnt_build_TTF_header(SFNT
* sfnt
,
883 FT_Byte
** header_buf
,
884 FT_ULong
* header_len
,
887 SFNT_Table
* tables
= font
->tables
;
889 SFNT_Table_Info
* table_infos
= sfnt
->table_infos
;
890 FT_ULong num_table_infos
= sfnt
->num_table_infos
;
895 FT_Byte
* table_record
;
897 FT_Byte
* head_buf
= NULL
; /* pointer to `head' table */
898 FT_ULong head_checksum
; /* checksum in `head' table */
900 FT_ULong num_tables_in_header
;
904 num_tables_in_header
= 0;
905 for (i
= 0; i
< num_table_infos
; i
++)
907 /* ignore empty tables */
908 if (table_infos
[i
] != MISSING
)
909 num_tables_in_header
++;
912 len
= 12 + 16 * num_tables_in_header
;
918 buf
= (FT_Byte
*)malloc(len
);
920 return FT_Err_Out_Of_Memory
;
928 /* number of tables */
929 buf
[4] = HIGH(num_tables_in_header
);
930 buf
[5] = LOW(num_tables_in_header
);
934 FT_ULong search_range
, entry_selector
, range_shift
;
938 for (i
= 1, j
= 2; j
<= num_tables_in_header
; i
++, j
<<= 1)
941 entry_selector
= i
- 1;
942 search_range
= 0x10 << entry_selector
;
943 range_shift
= (num_tables_in_header
<< 4) - search_range
;
945 buf
[6] = HIGH(search_range
);
946 buf
[7] = LOW(search_range
);
947 buf
[8] = HIGH(entry_selector
);
948 buf
[9] = LOW(entry_selector
);
949 buf
[10] = HIGH(range_shift
);
950 buf
[11] = LOW(range_shift
);
953 /* location of the first table info record */
954 table_record
= &buf
[12];
958 /* loop over all tables */
959 for (i
= 0; i
< num_table_infos
; i
++)
961 SFNT_Table_Info table_info
= table_infos
[i
];
965 /* ignore empty slots */
966 if (table_info
== MISSING
)
969 table
= &tables
[table_info
];
971 if (table
->tag
== TTAG_head
)
973 /* we always reach this IF clause since FreeType would */
974 /* have aborted already if the `head' table were missing */
976 head_buf
= table
->buf
;
978 /* reset checksum in `head' table for recalculation */
985 head_checksum
+= table
->checksum
;
987 table_record
[0] = BYTE1(table
->tag
);
988 table_record
[1] = BYTE2(table
->tag
);
989 table_record
[2] = BYTE3(table
->tag
);
990 table_record
[3] = BYTE4(table
->tag
);
992 table_record
[4] = BYTE1(table
->checksum
);
993 table_record
[5] = BYTE2(table
->checksum
);
994 table_record
[6] = BYTE3(table
->checksum
);
995 table_record
[7] = BYTE4(table
->checksum
);
997 table_record
[8] = BYTE1(table
->offset
);
998 table_record
[9] = BYTE2(table
->offset
);
999 table_record
[10] = BYTE3(table
->offset
);
1000 table_record
[11] = BYTE4(table
->offset
);
1002 table_record
[12] = BYTE1(table
->len
);
1003 table_record
[13] = BYTE2(table
->len
);
1004 table_record
[14] = BYTE3(table
->len
);
1005 table_record
[15] = BYTE4(table
->len
);
1010 /* the font header is complete; compute `head' checksum */
1011 head_checksum
+= TA_table_compute_checksum(buf
, len
);
1012 head_checksum
= 0xB1B0AFBAUL
- head_checksum
;
1014 /* store checksum in `head' table; */
1015 head_buf
[8] = BYTE1(head_checksum
);
1016 head_buf
[9] = BYTE2(head_checksum
);
1017 head_buf
[10] = BYTE3(head_checksum
);
1018 head_buf
[11] = BYTE4(head_checksum
);
1028 TA_font_build_TTF(FONT
* font
)
1030 SFNT
* sfnt
= &font
->sfnts
[0];
1033 FT_ULong num_tables
;
1035 FT_ULong SFNT_offset
;
1039 FT_Byte
* header_buf
;
1040 FT_ULong header_len
;
1046 /* add a dummy `DSIG' table */
1048 error
= TA_sfnt_add_table_info(sfnt
);
1052 error
= TA_table_build_DSIG(&DSIG_buf
);
1056 /* in case of success, `DSIG_buf' gets linked */
1057 /* and is eventually freed in `TA_font_unload' */
1058 error
= TA_font_add_table(font
,
1059 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
1060 TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1067 TA_sfnt_sort_table_info(sfnt
, font
);
1069 /* the first SFNT table immediately follows the header */
1070 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &SFNT_offset
, 0);
1071 TA_font_compute_table_offsets(font
, SFNT_offset
);
1073 error
= TA_sfnt_build_TTF_header(sfnt
, font
,
1074 &header_buf
, &header_len
, 1);
1080 tables
= font
->tables
;
1081 num_tables
= font
->num_tables
;
1083 /* get font length from last SFNT table array element */
1084 font
->out_len
= tables
[num_tables
- 1].offset
1085 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1086 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1089 error
= FT_Err_Out_Of_Memory
;
1093 memcpy(font
->out_buf
, header_buf
, header_len
);
1095 for (i
= 0; i
< num_tables
; i
++)
1097 SFNT_Table
* table
= &tables
[i
];
1100 /* buffer length is a multiple of 4 */
1101 memcpy(font
->out_buf
+ table
->offset
,
1102 table
->buf
, (table
->len
+ 3) & ~3);
1115 TA_font_build_TTC_header(FONT
* font
,
1116 FT_Byte
** header_buf
,
1117 FT_ULong
* header_len
)
1119 SFNT
* sfnts
= font
->sfnts
;
1120 FT_Long num_sfnts
= font
->num_sfnts
;
1122 SFNT_Table
* tables
= font
->tables
;
1123 FT_ULong num_tables
= font
->num_tables
;
1125 FT_ULong TTF_offset
;
1126 FT_ULong DSIG_offset
;
1135 len
= 24 + 4 * num_sfnts
;
1136 buf
= (FT_Byte
*)malloc(len
);
1138 return FT_Err_Out_Of_Memory
;
1148 /* TTC header version */
1154 /* number of subfonts */
1155 *(p
++) = BYTE1(num_sfnts
);
1156 *(p
++) = BYTE2(num_sfnts
);
1157 *(p
++) = BYTE3(num_sfnts
);
1158 *(p
++) = BYTE4(num_sfnts
);
1160 /* the first TTF subfont header immediately follows the TTC header */
1163 /* loop over all subfonts */
1164 for (i
= 0; i
< num_sfnts
; i
++)
1166 SFNT
* sfnt
= &sfnts
[i
];
1170 TA_sfnt_sort_table_info(sfnt
, font
);
1171 /* only get header length */
1172 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &l
, 0);
1174 *(p
++) = BYTE1(TTF_offset
);
1175 *(p
++) = BYTE2(TTF_offset
);
1176 *(p
++) = BYTE3(TTF_offset
);
1177 *(p
++) = BYTE4(TTF_offset
);
1182 /* the first SFNT table immediately follows the subfont TTF headers */
1183 TA_font_compute_table_offsets(font
, TTF_offset
);
1197 /* DSIG offset; in a TTC this is always the last SFNT table */
1198 DSIG_offset
= tables
[num_tables
- 1].offset
;
1200 *(p
++) = BYTE1(DSIG_offset
);
1201 *(p
++) = BYTE2(DSIG_offset
);
1202 *(p
++) = BYTE3(DSIG_offset
);
1203 *(p
++) = BYTE4(DSIG_offset
);
1213 TA_font_build_TTC(FONT
* font
)
1215 SFNT
* sfnts
= font
->sfnts
;
1216 FT_Long num_sfnts
= font
->num_sfnts
;
1219 FT_ULong num_tables
;
1222 SFNT_Table_Info dummy
;
1224 FT_Byte
* TTC_header_buf
;
1225 FT_ULong TTC_header_len
;
1227 FT_Byte
** TTF_header_bufs
= NULL
;
1228 FT_ULong
* TTF_header_lens
= NULL
;
1236 /* add a dummy `DSIG' table */
1238 error
= TA_table_build_DSIG(&DSIG_buf
);
1242 /* in case of success, `DSIG_buf' gets linked */
1243 /* and is eventually freed in `TA_font_unload' */
1244 error
= TA_font_add_table(font
, &dummy
, TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1251 /* this also computes the SFNT table offsets */
1252 error
= TA_font_build_TTC_header(font
,
1253 &TTC_header_buf
, &TTC_header_len
);
1257 TTF_header_bufs
= (FT_Byte
**)calloc(1, num_sfnts
* sizeof (FT_Byte
*));
1258 if (!TTF_header_bufs
)
1261 TTF_header_lens
= (FT_ULong
*)malloc(num_sfnts
* sizeof (FT_ULong
));
1262 if (!TTF_header_lens
)
1265 for (i
= 0; i
< num_sfnts
; i
++)
1267 error
= TA_sfnt_build_TTF_header(&sfnts
[i
], font
,
1268 &TTF_header_bufs
[i
],
1269 &TTF_header_lens
[i
], 1);
1276 tables
= font
->tables
;
1277 num_tables
= font
->num_tables
;
1279 /* get font length from last SFNT table array element */
1280 font
->out_len
= tables
[num_tables
- 1].offset
1281 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1282 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1285 error
= FT_Err_Out_Of_Memory
;
1289 memcpy(font
->out_buf
, TTC_header_buf
, TTC_header_len
);
1291 offset
= TTC_header_len
;
1293 for (i
= 0; i
< num_sfnts
; i
++)
1295 memcpy(font
->out_buf
+ offset
,
1296 TTF_header_bufs
[i
], TTF_header_lens
[i
]);
1298 offset
+= TTF_header_lens
[i
];
1301 for (j
= 0; j
< num_tables
; j
++)
1303 SFNT_Table
* table
= &tables
[j
];
1306 /* buffer length is a multiple of 4 */
1307 memcpy(font
->out_buf
+ table
->offset
,
1308 table
->buf
, (table
->len
+ 3) & ~3);
1314 free(TTC_header_buf
);
1315 if (TTF_header_bufs
)
1317 for (i
= 0; i
< font
->num_sfnts
; i
++)
1318 free(TTF_header_bufs
[i
]);
1319 free(TTF_header_bufs
);
1321 free(TTF_header_lens
);
1328 TA_font_file_write(FONT
* font
,
1331 if (fwrite(font
->out_buf
, 1, font
->out_len
, out_file
) != font
->out_len
)
1332 return TA_Err_Invalid_Stream_Write
;
1339 TA_font_unload(FONT
* font
,
1343 /* in case of error it is expected that unallocated pointers */
1344 /* are NULL (and counters are zero) */
1350 ta_loader_done(font
->loader
);
1357 for (i
= 0; i
< font
->num_tables
; i
++)
1359 free(font
->tables
[i
].buf
);
1360 if (font
->tables
[i
].data
)
1362 if (font
->tables
[i
].tag
== TTAG_glyf
)
1364 glyf_Data
* data
= (glyf_Data
*)font
->tables
[i
].data
;
1368 for (j
= 0; j
< data
->num_glyphs
; j
++)
1370 free(data
->glyphs
[j
].buf
);
1371 free(data
->glyphs
[j
].ins_buf
);
1386 for (i
= 0; i
< font
->num_sfnts
; i
++)
1388 FT_Done_Face(font
->sfnts
[i
].face
);
1389 free(font
->sfnts
[i
].table_infos
);
1394 FT_Done_FreeType(font
->lib
);
1398 free(font
->out_buf
);
1403 #define COMPARE(str) (len == (sizeof (str) - 1) \
1404 && !strncmp(start, str, sizeof (str) - 1))
1408 TTF_autohint(const char* options
,
1417 FILE* in_file
= NULL
;
1418 FILE* out_file
= NULL
;
1420 const char* in_buf
= NULL
;
1422 char** out_bufp
= NULL
;
1423 size_t* out_lenp
= NULL
;
1425 FT_Long hinting_range_min
= -1;
1426 FT_Long hinting_range_max
= -1;
1428 TA_Progress_Func progress
;
1429 void* progress_data
;
1434 if (!options
|| !*options
)
1435 return FT_Err_Invalid_Argument
;
1438 va_start(ap
, options
);
1451 while (*op
&& *op
!= ',')
1454 /* remove leading whitespace */
1455 while (isspace(*start
))
1458 /* check for empty option */
1464 /* the `COMPARE' macro uses `len' and `start' */
1467 if (COMPARE("in-file"))
1469 in_file
= va_arg(ap
, FILE*);
1473 else if (COMPARE("in-buffer"))
1476 in_buf
= va_arg(ap
, const char*);
1478 else if (COMPARE("in-buffer-len"))
1481 in_len
= va_arg(ap
, size_t);
1483 else if (COMPARE("out-file"))
1485 out_file
= va_arg(ap
, FILE*);
1489 else if (COMPARE("out-buffer"))
1492 out_bufp
= va_arg(ap
, char**);
1494 else if (COMPARE("out-buffer-len"))
1497 out_lenp
= va_arg(ap
, size_t*);
1499 else if (COMPARE("hinting-range-min"))
1500 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
1501 else if (COMPARE("hinting-range-max"))
1502 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
1503 else if (COMPARE("progress-callback"))
1504 progress
= (TA_Progress_Func
)va_arg(ap
, void*);
1505 else if (COMPARE("progress-callback-data"))
1506 progress_data
= va_arg(ap
, void*);
1510 x-height-snapping-exceptions
1526 || (in_buf
&& in_len
)))
1527 return FT_Err_Invalid_Argument
;
1530 || (out_bufp
&& out_lenp
)))
1531 return FT_Err_Invalid_Argument
;
1533 font
= (FONT
*)calloc(1, sizeof (FONT
));
1535 return FT_Err_Out_Of_Memory
;
1537 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
1538 return FT_Err_Invalid_Argument
;
1539 if (hinting_range_min
< 0)
1540 hinting_range_min
= 8;
1542 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
1543 return FT_Err_Invalid_Argument
;
1544 if (hinting_range_max
< 0)
1545 hinting_range_max
= 1000;
1547 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
1548 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
1550 font
->progress
= progress
;
1551 font
->progress_data
= progress_data
;
1553 /* now start with processing the data */
1557 error
= TA_font_file_read(font
, in_file
);
1563 /* a valid TTF can never be that small */
1565 return FT_Err_Invalid_Argument
;
1566 font
->in_buf
= (FT_Byte
*)in_buf
;
1567 font
->in_len
= in_len
;
1570 error
= TA_font_init(font
);
1574 /* loop over subfonts */
1575 for (i
= 0; i
< font
->num_sfnts
; i
++)
1577 SFNT
* sfnt
= &font
->sfnts
[i
];
1580 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
1585 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
1589 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
1594 /* build `gasp' table */
1595 error
= TA_sfnt_build_gasp_table(&font
->sfnts
[0], font
);
1599 /* XXX handle subfonts for bytecode tables */
1601 /* build `cvt ' table */
1602 error
= TA_sfnt_build_cvt_table(&font
->sfnts
[0], font
);
1606 /* build `fpgm' table */
1607 error
= TA_sfnt_build_fpgm_table(&font
->sfnts
[0], font
);
1611 /* build `prep' table */
1612 error
= TA_sfnt_build_prep_table(&font
->sfnts
[0], font
);
1616 /* hint the glyphs and build bytecode */
1617 error
= TA_sfnt_build_glyf_hints(&font
->sfnts
[0], font
);
1621 /* loop again over subfonts */
1622 for (i
= 0; i
< font
->num_sfnts
; i
++)
1624 SFNT
* sfnt
= &font
->sfnts
[i
];
1627 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
1630 error
= TA_sfnt_build_loca_table(sfnt
, font
);
1633 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
1638 if (font
->num_sfnts
== 1)
1639 error
= TA_font_build_TTF(font
);
1641 error
= TA_font_build_TTC(font
);
1647 error
= TA_font_file_write(font
, out_file
);
1653 *out_bufp
= (char*)font
->out_buf
;
1654 *out_lenp
= font
->out_len
;
1660 TA_font_unload(font
, in_buf
, out_bufp
);
1665 /* end of ttfautohint.c */