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 /* This file needs FreeType 2.4.5 or newer. */
27 TA_font_file_read(FONT
* font
,
30 fseek(in_file
, 0, SEEK_END
);
31 font
->in_len
= ftell(in_file
);
32 fseek(in_file
, 0, SEEK_SET
);
34 /* a valid TTF can never be that small */
35 if (font
->in_len
< 100)
36 return FT_Err_Invalid_Argument
;
38 font
->in_buf
= (FT_Byte
*)malloc(font
->in_len
);
40 return FT_Err_Out_Of_Memory
;
42 if (fread(font
->in_buf
, 1, font
->in_len
, in_file
) != font
->in_len
)
43 return FT_Err_Invalid_Stream_Read
;
50 TA_font_init(FONT
* font
)
54 FT_Int major
, minor
, patch
;
57 error
= FT_Init_FreeType(&font
->lib
);
61 /* assure correct FreeType version to avoid using the wrong DLL */
62 FT_Library_Version(font
->lib
, &major
, &minor
, &patch
);
63 if (((major
*1000 + minor
)*1000 + patch
) < 2004005)
64 return TA_Err_Invalid_FreeType_Version
;
66 /* get number of faces (i.e. subfonts) */
67 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
, -1, &f
);
70 font
->num_sfnts
= f
->num_faces
;
73 /* it is a TTC if we have more than a single subfont */
74 font
->sfnts
= (SFNT
*)calloc(1, font
->num_sfnts
* sizeof (SFNT
));
76 return FT_Err_Out_Of_Memory
;
83 TA_sfnt_split_into_SFNT_tables(SFNT
* sfnt
,
90 /* basic check whether font is a TTF or TTC */
91 if (!FT_IS_SFNT(sfnt
->face
))
92 return FT_Err_Invalid_Argument
;
94 error
= FT_Sfnt_Table_Info(sfnt
->face
, 0, NULL
, &sfnt
->num_table_infos
);
98 sfnt
->table_infos
= (SFNT_Table_Info
*)malloc(sfnt
->num_table_infos
99 * sizeof (SFNT_Table_Info
));
100 if (!sfnt
->table_infos
)
101 return FT_Err_Out_Of_Memory
;
103 /* collect SFNT tables and search for `glyf' and `loca' table */
104 sfnt
->glyf_idx
= MISSING
;
105 sfnt
->loca_idx
= MISSING
;
106 sfnt
->head_idx
= MISSING
;
107 sfnt
->maxp_idx
= MISSING
;
108 sfnt
->OS2_idx
= MISSING
;
110 for (i
= 0; i
< sfnt
->num_table_infos
; i
++)
112 SFNT_Table_Info
* table_info
= &sfnt
->table_infos
[i
];
121 *table_info
= MISSING
;
123 error
= FT_Sfnt_Table_Info(sfnt
->face
, i
, &tag
, &len
);
126 /* this ignores both missing and zero-length tables */
127 if (error
== FT_Err_Table_Missing
)
133 /* ignore tables which we are going to create by ourselves, */
134 /* or which would become invalid otherwise */
135 else if (tag
== TTAG_fpgm
145 /* make the allocated buffer length a multiple of 4 */
146 buf_len
= (len
+ 3) & ~3;
147 buf
= (FT_Byte
*)malloc(buf_len
);
149 return FT_Err_Out_Of_Memory
;
151 /* pad end of buffer with zeros */
152 buf
[buf_len
- 1] = 0x00;
153 buf
[buf_len
- 2] = 0x00;
154 buf
[buf_len
- 3] = 0x00;
157 error
= FT_Load_Sfnt_Table(sfnt
->face
, tag
, 0, buf
, &len
);
161 /* check whether we already have this table */
162 for (j
= 0; j
< font
->num_tables
; j
++)
164 SFNT_Table
* table
= &font
->tables
[j
];
167 if (table
->tag
== tag
169 && !memcmp(table
->buf
, buf
, len
))
173 if (tag
== TTAG_head
)
175 else if (tag
== TTAG_glyf
)
177 else if (tag
== TTAG_loca
)
179 else if (tag
== TTAG_maxp
)
181 else if (tag
== TTAG_OS2
)
184 if (j
== font
->num_tables
)
186 /* add element to table array if it is missing or different; */
187 /* in case of success, `buf' gets linked and is eventually */
188 /* freed in `TA_font_unload' */
189 error
= TA_font_add_table(font
, table_info
, tag
, len
, buf
);
195 /* reuse existing SFNT table */
206 /* no (non-empty) `glyf', `loca', `head', or `maxp' table; */
207 /* this can't be a valid TTF with outlines */
208 if (sfnt
->glyf_idx
== MISSING
209 || sfnt
->loca_idx
== MISSING
210 || sfnt
->head_idx
== MISSING
211 || sfnt
->maxp_idx
== MISSING
)
212 return FT_Err_Invalid_Argument
;
219 TA_glyph_parse_composite(GLYPH
* glyph
,
223 FT_ULong flags_offset
; /* after the loop, this is the offset */
224 /* to the last element in the flags array */
237 /* walk over component records */
241 return FT_Err_Invalid_Table
;
243 flags_offset
= p
- buf
;
248 /* skip glyph component index */
251 /* skip scaling and offset arguments */
252 if (flags
& ARGS_ARE_WORDS
)
257 if (flags
& WE_HAVE_A_SCALE
)
259 else if (flags
& WE_HAVE_AN_XY_SCALE
)
261 else if (flags
& WE_HAVE_A_2X2
)
263 } while (flags
& MORE_COMPONENTS
);
265 glyph
->flags_offset
= flags_offset
;
267 /* adjust glyph record length */
271 /* glyph->len2 = 0; */
272 glyph
->buf
= (FT_Byte
*)malloc(len
);
274 return FT_Err_Out_Of_Memory
;
276 /* copy record without instructions (if any) */
277 memcpy(glyph
->buf
, buf
, len
);
278 glyph
->buf
[flags_offset
] &= ~(WE_HAVE_INSTR
>> 8);
285 TA_glyph_parse_simple(GLYPH
* glyph
,
287 FT_UShort num_contours
,
291 FT_Byte
* flags_start
;
296 FT_ULong flags_size
; /* size of the flags array */
297 FT_ULong xy_size
; /* size of x and y coordinate arrays together */
308 ins_offset
= 10 + num_contours
* 2;
313 return FT_Err_Invalid_Table
;
315 /* get number of instructions */
316 num_ins
= *(p
++) << 8;
322 return FT_Err_Invalid_Table
;
324 /* get number of points from last outline point */
325 num_pts
= buf
[ins_offset
- 2] << 8;
326 num_pts
+= buf
[ins_offset
- 1];
344 return FT_Err_Invalid_Table
;
348 x_short
= (flags
& X_SHORT_VECTOR
) ? 1 : 2;
349 y_short
= (flags
& Y_SHORT_VECTOR
) ? 1 : 2;
351 have_x
= ((flags
& SAME_X
) && !(flags
& X_SHORT_VECTOR
)) ? 0 : 1;
352 have_y
= ((flags
& SAME_Y
) && !(flags
& Y_SHORT_VECTOR
)) ? 0 : 1;
359 return FT_Err_Invalid_Table
;
363 if (i
+ count
> num_pts
)
364 return FT_Err_Invalid_Table
;
367 xy_size
+= count
* x_short
* have_x
;
368 xy_size
+= count
* y_short
* have_y
;
373 if (p
+ xy_size
> endp
)
374 return FT_Err_Invalid_Table
;
376 flags_size
= p
- flags_start
;
378 /* store the data before and after the bytecode instructions */
379 /* in the same array */
380 glyph
->len1
= ins_offset
;
381 glyph
->len2
= flags_size
+ xy_size
;
382 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
384 return FT_Err_Out_Of_Memory
;
386 /* now copy everything but the instructions */
387 memcpy(glyph
->buf
, buf
, glyph
->len1
);
388 memcpy(glyph
->buf
+ glyph
->len1
, flags_start
, glyph
->len2
);
395 TA_sfnt_split_glyf_table(SFNT
* sfnt
,
398 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
399 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
400 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
406 FT_ULong offset_next
;
412 /* in case of success, all allocated arrays are */
413 /* linked and eventually freed in `TA_font_unload' */
415 /* nothing to do if table has already been split */
416 if (glyf_table
->data
)
419 data
= (glyf_Data
*)calloc(1, sizeof (glyf_Data
));
421 return FT_Err_Out_Of_Memory
;
423 glyf_table
->data
= data
;
425 loca_format
= head_table
->buf
[LOCA_FORMAT_OFFSET
];
427 data
->num_glyphs
= loca_format
? loca_table
->len
/ 4 - 1
428 : loca_table
->len
/ 2 - 1;
429 data
->glyphs
= (GLYPH
*)calloc(1, data
->num_glyphs
* sizeof (GLYPH
));
431 return FT_Err_Out_Of_Memory
;
437 offset_next
= *(p
++) << 24;
438 offset_next
+= *(p
++) << 16;
439 offset_next
+= *(p
++) << 8;
440 offset_next
+= *(p
++);
444 offset_next
= *(p
++) << 8;
445 offset_next
+= *(p
++);
449 /* loop over `loca' and `glyf' data */
450 for (i
= 0; i
< data
->num_glyphs
; i
++)
452 GLYPH
* glyph
= &data
->glyphs
[i
];
456 offset
= offset_next
;
460 offset_next
= *(p
++) << 24;
461 offset_next
+= *(p
++) << 16;
462 offset_next
+= *(p
++) << 8;
463 offset_next
+= *(p
++);
467 offset_next
= *(p
++) << 8;
468 offset_next
+= *(p
++);
472 if (offset_next
< offset
473 || offset_next
> glyf_table
->len
)
474 return FT_Err_Invalid_Table
;
476 len
= offset_next
- offset
;
478 continue; /* empty glyph */
482 FT_Short num_contours
;
486 /* check header size */
488 return FT_Err_Invalid_Table
;
490 buf
= glyf_table
->buf
+ offset
;
491 num_contours
= (FT_Short
)((buf
[0] << 8) + buf
[1]);
493 /* We must parse the rest of the glyph record to get the exact */
494 /* record length. Since the `loca' table rounds record lengths */
495 /* up to multiples of 4 (or 2 for older fonts), and we must round */
496 /* up again after stripping off the instructions, it would be */
497 /* possible otherwise to have more than 4 bytes of padding which */
498 /* is more or less invalid. */
500 if (num_contours
< 0)
502 error
= TA_glyph_parse_composite(glyph
, buf
, len
);
508 error
= TA_glyph_parse_simple(glyph
, buf
, num_contours
, len
);
520 TA_sfnt_build_glyf_table(SFNT
* sfnt
,
523 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
524 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
534 if (glyf_table
->processed
)
539 glyph
= data
->glyphs
;
540 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
542 /* glyph records should have offsets which are multiples of 4 */
543 len
= (len
+ 3) & ~3;
544 len
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
545 /* add two bytes for the instructionLength field */
546 if (glyph
->len2
|| glyph
->ins_len
)
550 /* to make the short format of the `loca' table always work, */
551 /* assure an even length of the `glyf' table */
552 glyf_table
->len
= (len
+ 1) & ~1;
554 buf_new
= (FT_Byte
*)realloc(glyf_table
->buf
, (len
+ 3) & ~3);
556 return FT_Err_Out_Of_Memory
;
558 glyf_table
->buf
= buf_new
;
561 glyph
= data
->glyphs
;
562 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
564 len
= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
565 if (glyph
->len2
|| glyph
->ins_len
)
570 /* copy glyph data and insert new instructions */
571 memcpy(p
, glyph
->buf
, glyph
->len1
);
577 *(p
++) = HIGH(glyph
->ins_len
);
578 *(p
++) = LOW(glyph
->ins_len
);
579 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
581 memcpy(p
, glyph
->buf
+ glyph
->len1
, glyph
->len2
);
586 /* composite glyph */
589 *(p
+ glyph
->flags_offset
) |= (WE_HAVE_INSTR
>> 8);
591 *(p
++) = HIGH(glyph
->ins_len
);
592 *(p
++) = LOW(glyph
->ins_len
);
593 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
600 /* pad with zero bytes to have an offset which is a multiple of 4; */
601 /* this works even for the last glyph record since the `glyf' */
602 /* table length is a multiple of 4 also */
617 glyf_table
->checksum
= TA_table_compute_checksum(glyf_table
->buf
,
619 glyf_table
->processed
= 1;
626 TA_sfnt_build_loca_table(SFNT
* sfnt
,
629 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
630 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
631 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
633 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
643 if (loca_table
->processed
)
646 /* get largest offset */
648 glyph
= data
->glyphs
;
650 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
652 /* glyph records should have offsets which are multiples of 4 */
653 offset
= (offset
+ 3) & ~3;
654 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
655 /* add two bytes for the instructionLength field */
656 if (glyph
->len2
|| glyph
->ins_len
)
660 if (offset
> 0xFFFF * 2)
668 loca_table
->len
= (data
->num_glyphs
+ 1) * 4;
669 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
, loca_table
->len
);
671 return FT_Err_Out_Of_Memory
;
673 loca_table
->buf
= buf_new
;
677 glyph
= data
->glyphs
;
679 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
681 offset
= (offset
+ 3) & ~3;
683 *(p
++) = BYTE1(offset
);
684 *(p
++) = BYTE2(offset
);
685 *(p
++) = BYTE3(offset
);
686 *(p
++) = BYTE4(offset
);
688 offset
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
689 if (glyph
->len2
|| glyph
->ins_len
)
693 /* last element holds the size of the `glyf' table */
694 *(p
++) = BYTE1(offset
);
695 *(p
++) = BYTE2(offset
);
696 *(p
++) = BYTE3(offset
);
697 *(p
++) = BYTE4(offset
);
701 loca_table
->len
= (data
->num_glyphs
+ 1) * 2;
702 buf_new
= (FT_Byte
*)realloc(loca_table
->buf
,
703 (loca_table
->len
+ 3) & ~3);
705 return FT_Err_Out_Of_Memory
;
707 loca_table
->buf
= buf_new
;
711 glyph
= data
->glyphs
;
713 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
715 offset
= (offset
+ 1) & ~1;
717 *(p
++) = HIGH(offset
);
718 *(p
++) = LOW(offset
);
720 offset
+= (glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
+ 1) >> 1;
721 if (glyph
->len2
|| glyph
->ins_len
)
725 /* last element holds the size of the `glyf' table */
726 *(p
++) = HIGH(offset
);
727 *(p
++) = LOW(offset
);
729 /* pad `loca' table to make its length a multiple of 4 */
730 if (loca_table
->len
% 4 == 2)
737 loca_table
->checksum
= TA_table_compute_checksum(loca_table
->buf
,
739 loca_table
->processed
= 1;
741 head_table
->buf
[LOCA_FORMAT_OFFSET
] = loca_format
;
748 TA_sfnt_update_maxp_table(SFNT
* sfnt
,
751 SFNT_Table
* maxp_table
= &font
->tables
[sfnt
->maxp_idx
];
752 FT_Byte
* buf
= maxp_table
->buf
;
755 if (maxp_table
->processed
)
758 if (maxp_table
->len
!= MAXP_LEN
)
759 return FT_Err_Invalid_Table
;
761 buf
[MAXP_MAX_ZONES_OFFSET
] = 0;
762 buf
[MAXP_MAX_ZONES_OFFSET
+ 1] = 2;
763 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
] = HIGH(sfnt
->max_twilight_points
);
764 buf
[MAXP_MAX_TWILIGHT_POINTS_OFFSET
+ 1] = LOW(sfnt
->max_twilight_points
);
765 buf
[MAXP_MAX_STORAGE_OFFSET
] = HIGH(sfnt
->max_storage
);
766 buf
[MAXP_MAX_STORAGE_OFFSET
+ 1] = LOW(sfnt
->max_storage
);
767 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
] = 0;
768 buf
[MAXP_MAX_FUNCTION_DEFS_OFFSET
+ 1] = NUM_FDEFS
;
769 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
] = 0;
770 buf
[MAXP_MAX_INSTRUCTION_DEFS_OFFSET
+ 1] = 0;
771 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
] = HIGH(sfnt
->max_stack_elements
);
772 buf
[MAXP_MAX_STACK_ELEMENTS_OFFSET
+ 1] = LOW(sfnt
->max_stack_elements
);
773 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
] = HIGH(sfnt
->max_instructions
);
774 buf
[MAXP_MAX_INSTRUCTIONS_OFFSET
+ 1] = LOW(sfnt
->max_instructions
);
776 maxp_table
->checksum
= TA_table_compute_checksum(maxp_table
->buf
,
778 maxp_table
->processed
= 1;
784 /* we build a dummy `DSIG' table only */
787 TA_table_build_DSIG(FT_Byte
** DSIG
)
792 buf
= (FT_Byte
*)malloc(DSIG_LEN
);
794 return FT_Err_Out_Of_Memory
;
802 /* zero signatures */
806 /* permission flags */
817 TA_table_build_gasp(FT_Byte
** gasp
)
822 buf
= (FT_Byte
*)malloc(GASP_LEN
);
824 return FT_Err_Out_Of_Memory
;
834 /* entry valid for all sizes */
838 buf
[7] = 0x0F; /* always use grayscale rendering with grid-fitting, */
839 /* symmetric grid-fitting and symmetric smoothing */
848 TA_sfnt_build_gasp_table(SFNT
* sfnt
,
856 error
= TA_sfnt_add_table_info(sfnt
);
860 error
= TA_table_build_gasp(&gasp_buf
);
864 /* in case of success, `gasp_buf' gets linked */
865 /* and is eventually freed in `TA_font_unload' */
866 error
= TA_font_add_table(font
,
867 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
868 TTAG_gasp
, GASP_LEN
, gasp_buf
);
880 TA_font_compute_table_offsets(FONT
* font
,
884 FT_ULong offset
= start
;
887 for (i
= 0; i
< font
->num_tables
; i
++)
889 SFNT_Table
* table
= &font
->tables
[i
];
892 table
->offset
= offset
;
894 /* table offsets must be multiples of 4; */
895 /* this also fits the actual buffer lengths */
896 offset
+= (table
->len
+ 3) & ~3;
901 /* If `do_complete' is 0, only return `header_len'. */
904 TA_sfnt_build_TTF_header(SFNT
* sfnt
,
906 FT_Byte
** header_buf
,
907 FT_ULong
* header_len
,
910 SFNT_Table
* tables
= font
->tables
;
912 SFNT_Table_Info
* table_infos
= sfnt
->table_infos
;
913 FT_ULong num_table_infos
= sfnt
->num_table_infos
;
918 FT_Byte
* table_record
;
920 FT_Byte
* head_buf
= NULL
; /* pointer to `head' table */
921 FT_ULong head_checksum
; /* checksum in `head' table */
923 FT_ULong num_tables_in_header
;
927 num_tables_in_header
= 0;
928 for (i
= 0; i
< num_table_infos
; i
++)
930 /* ignore empty tables */
931 if (table_infos
[i
] != MISSING
)
932 num_tables_in_header
++;
935 len
= 12 + 16 * num_tables_in_header
;
941 buf
= (FT_Byte
*)malloc(len
);
943 return FT_Err_Out_Of_Memory
;
951 /* number of tables */
952 buf
[4] = HIGH(num_tables_in_header
);
953 buf
[5] = LOW(num_tables_in_header
);
957 FT_ULong search_range
, entry_selector
, range_shift
;
961 for (i
= 1, j
= 2; j
<= num_tables_in_header
; i
++, j
<<= 1)
964 entry_selector
= i
- 1;
965 search_range
= 0x10 << entry_selector
;
966 range_shift
= (num_tables_in_header
<< 4) - search_range
;
968 buf
[6] = HIGH(search_range
);
969 buf
[7] = LOW(search_range
);
970 buf
[8] = HIGH(entry_selector
);
971 buf
[9] = LOW(entry_selector
);
972 buf
[10] = HIGH(range_shift
);
973 buf
[11] = LOW(range_shift
);
976 /* location of the first table info record */
977 table_record
= &buf
[12];
981 /* loop over all tables */
982 for (i
= 0; i
< num_table_infos
; i
++)
984 SFNT_Table_Info table_info
= table_infos
[i
];
988 /* ignore empty slots */
989 if (table_info
== MISSING
)
992 table
= &tables
[table_info
];
994 if (table
->tag
== TTAG_head
)
996 /* we always reach this IF clause since FreeType would */
997 /* have aborted already if the `head' table were missing */
999 head_buf
= table
->buf
;
1001 /* reset checksum in `head' table for recalculation */
1004 head_buf
[10] = 0x00;
1005 head_buf
[11] = 0x00;
1008 head_checksum
+= table
->checksum
;
1010 table_record
[0] = BYTE1(table
->tag
);
1011 table_record
[1] = BYTE2(table
->tag
);
1012 table_record
[2] = BYTE3(table
->tag
);
1013 table_record
[3] = BYTE4(table
->tag
);
1015 table_record
[4] = BYTE1(table
->checksum
);
1016 table_record
[5] = BYTE2(table
->checksum
);
1017 table_record
[6] = BYTE3(table
->checksum
);
1018 table_record
[7] = BYTE4(table
->checksum
);
1020 table_record
[8] = BYTE1(table
->offset
);
1021 table_record
[9] = BYTE2(table
->offset
);
1022 table_record
[10] = BYTE3(table
->offset
);
1023 table_record
[11] = BYTE4(table
->offset
);
1025 table_record
[12] = BYTE1(table
->len
);
1026 table_record
[13] = BYTE2(table
->len
);
1027 table_record
[14] = BYTE3(table
->len
);
1028 table_record
[15] = BYTE4(table
->len
);
1033 /* the font header is complete; compute `head' checksum */
1034 head_checksum
+= TA_table_compute_checksum(buf
, len
);
1035 head_checksum
= 0xB1B0AFBAUL
- head_checksum
;
1037 /* store checksum in `head' table; */
1038 head_buf
[8] = BYTE1(head_checksum
);
1039 head_buf
[9] = BYTE2(head_checksum
);
1040 head_buf
[10] = BYTE3(head_checksum
);
1041 head_buf
[11] = BYTE4(head_checksum
);
1051 TA_font_build_TTF(FONT
* font
)
1053 SFNT
* sfnt
= &font
->sfnts
[0];
1056 FT_ULong num_tables
;
1058 FT_ULong SFNT_offset
;
1062 FT_Byte
* header_buf
;
1063 FT_ULong header_len
;
1069 /* add a dummy `DSIG' table */
1071 error
= TA_sfnt_add_table_info(sfnt
);
1075 error
= TA_table_build_DSIG(&DSIG_buf
);
1079 /* in case of success, `DSIG_buf' gets linked */
1080 /* and is eventually freed in `TA_font_unload' */
1081 error
= TA_font_add_table(font
,
1082 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
1083 TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1090 TA_sfnt_sort_table_info(sfnt
, font
);
1092 /* the first SFNT table immediately follows the header */
1093 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &SFNT_offset
, 0);
1094 TA_font_compute_table_offsets(font
, SFNT_offset
);
1096 error
= TA_sfnt_build_TTF_header(sfnt
, font
,
1097 &header_buf
, &header_len
, 1);
1103 tables
= font
->tables
;
1104 num_tables
= font
->num_tables
;
1106 /* get font length from last SFNT table array element */
1107 font
->out_len
= tables
[num_tables
- 1].offset
1108 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1109 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1112 error
= FT_Err_Out_Of_Memory
;
1116 memcpy(font
->out_buf
, header_buf
, header_len
);
1118 for (i
= 0; i
< num_tables
; i
++)
1120 SFNT_Table
* table
= &tables
[i
];
1123 /* buffer length is a multiple of 4 */
1124 memcpy(font
->out_buf
+ table
->offset
,
1125 table
->buf
, (table
->len
+ 3) & ~3);
1138 TA_font_build_TTC_header(FONT
* font
,
1139 FT_Byte
** header_buf
,
1140 FT_ULong
* header_len
)
1142 SFNT
* sfnts
= font
->sfnts
;
1143 FT_Long num_sfnts
= font
->num_sfnts
;
1145 SFNT_Table
* tables
= font
->tables
;
1146 FT_ULong num_tables
= font
->num_tables
;
1148 FT_ULong TTF_offset
;
1149 FT_ULong DSIG_offset
;
1158 len
= 24 + 4 * num_sfnts
;
1159 buf
= (FT_Byte
*)malloc(len
);
1161 return FT_Err_Out_Of_Memory
;
1171 /* TTC header version */
1177 /* number of subfonts */
1178 *(p
++) = BYTE1(num_sfnts
);
1179 *(p
++) = BYTE2(num_sfnts
);
1180 *(p
++) = BYTE3(num_sfnts
);
1181 *(p
++) = BYTE4(num_sfnts
);
1183 /* the first TTF subfont header immediately follows the TTC header */
1186 /* loop over all subfonts */
1187 for (i
= 0; i
< num_sfnts
; i
++)
1189 SFNT
* sfnt
= &sfnts
[i
];
1193 TA_sfnt_sort_table_info(sfnt
, font
);
1194 /* only get header length */
1195 (void)TA_sfnt_build_TTF_header(sfnt
, font
, NULL
, &l
, 0);
1197 *(p
++) = BYTE1(TTF_offset
);
1198 *(p
++) = BYTE2(TTF_offset
);
1199 *(p
++) = BYTE3(TTF_offset
);
1200 *(p
++) = BYTE4(TTF_offset
);
1205 /* the first SFNT table immediately follows the subfont TTF headers */
1206 TA_font_compute_table_offsets(font
, TTF_offset
);
1220 /* DSIG offset; in a TTC this is always the last SFNT table */
1221 DSIG_offset
= tables
[num_tables
- 1].offset
;
1223 *(p
++) = BYTE1(DSIG_offset
);
1224 *(p
++) = BYTE2(DSIG_offset
);
1225 *(p
++) = BYTE3(DSIG_offset
);
1226 *(p
++) = BYTE4(DSIG_offset
);
1236 TA_font_build_TTC(FONT
* font
)
1238 SFNT
* sfnts
= font
->sfnts
;
1239 FT_Long num_sfnts
= font
->num_sfnts
;
1242 FT_ULong num_tables
;
1245 SFNT_Table_Info dummy
;
1247 FT_Byte
* TTC_header_buf
;
1248 FT_ULong TTC_header_len
;
1250 FT_Byte
** TTF_header_bufs
= NULL
;
1251 FT_ULong
* TTF_header_lens
= NULL
;
1259 /* add a dummy `DSIG' table */
1261 error
= TA_table_build_DSIG(&DSIG_buf
);
1265 /* in case of success, `DSIG_buf' gets linked */
1266 /* and is eventually freed in `TA_font_unload' */
1267 error
= TA_font_add_table(font
, &dummy
, TTAG_DSIG
, DSIG_LEN
, DSIG_buf
);
1274 /* this also computes the SFNT table offsets */
1275 error
= TA_font_build_TTC_header(font
,
1276 &TTC_header_buf
, &TTC_header_len
);
1280 TTF_header_bufs
= (FT_Byte
**)calloc(1, num_sfnts
* sizeof (FT_Byte
*));
1281 if (!TTF_header_bufs
)
1284 TTF_header_lens
= (FT_ULong
*)malloc(num_sfnts
* sizeof (FT_ULong
));
1285 if (!TTF_header_lens
)
1288 for (i
= 0; i
< num_sfnts
; i
++)
1290 error
= TA_sfnt_build_TTF_header(&sfnts
[i
], font
,
1291 &TTF_header_bufs
[i
],
1292 &TTF_header_lens
[i
], 1);
1299 tables
= font
->tables
;
1300 num_tables
= font
->num_tables
;
1302 /* get font length from last SFNT table array element */
1303 font
->out_len
= tables
[num_tables
- 1].offset
1304 + ((tables
[num_tables
- 1].len
+ 3) & ~3);
1305 font
->out_buf
= (FT_Byte
*)malloc(font
->out_len
);
1308 error
= FT_Err_Out_Of_Memory
;
1312 memcpy(font
->out_buf
, TTC_header_buf
, TTC_header_len
);
1314 offset
= TTC_header_len
;
1316 for (i
= 0; i
< num_sfnts
; i
++)
1318 memcpy(font
->out_buf
+ offset
,
1319 TTF_header_bufs
[i
], TTF_header_lens
[i
]);
1321 offset
+= TTF_header_lens
[i
];
1324 for (j
= 0; j
< num_tables
; j
++)
1326 SFNT_Table
* table
= &tables
[j
];
1329 /* buffer length is a multiple of 4 */
1330 memcpy(font
->out_buf
+ table
->offset
,
1331 table
->buf
, (table
->len
+ 3) & ~3);
1337 free(TTC_header_buf
);
1338 if (TTF_header_bufs
)
1340 for (i
= 0; i
< font
->num_sfnts
; i
++)
1341 free(TTF_header_bufs
[i
]);
1342 free(TTF_header_bufs
);
1344 free(TTF_header_lens
);
1351 TA_font_file_write(FONT
* font
,
1354 if (fwrite(font
->out_buf
, 1, font
->out_len
, out_file
) != font
->out_len
)
1355 return TA_Err_Invalid_Stream_Write
;
1362 TA_font_unload(FONT
* font
,
1366 /* in case of error it is expected that unallocated pointers */
1367 /* are NULL (and counters are zero) */
1373 ta_loader_done(font
->loader
);
1380 for (i
= 0; i
< font
->num_tables
; i
++)
1382 free(font
->tables
[i
].buf
);
1383 if (font
->tables
[i
].data
)
1385 if (font
->tables
[i
].tag
== TTAG_glyf
)
1387 glyf_Data
* data
= (glyf_Data
*)font
->tables
[i
].data
;
1391 for (j
= 0; j
< data
->num_glyphs
; j
++)
1393 free(data
->glyphs
[j
].buf
);
1394 free(data
->glyphs
[j
].ins_buf
);
1409 for (i
= 0; i
< font
->num_sfnts
; i
++)
1411 FT_Done_Face(font
->sfnts
[i
].face
);
1412 free(font
->sfnts
[i
].table_infos
);
1417 FT_Done_FreeType(font
->lib
);
1421 free(font
->out_buf
);
1426 #define COMPARE(str) (len == (sizeof (str) - 1) \
1427 && !strncmp(start, str, sizeof (str) - 1))
1431 TTF_autohint(const char* options
,
1440 FILE* in_file
= NULL
;
1441 FILE* out_file
= NULL
;
1443 const char* in_buf
= NULL
;
1445 char** out_bufp
= NULL
;
1446 size_t* out_lenp
= NULL
;
1448 FT_Long hinting_range_min
= -1;
1449 FT_Long hinting_range_max
= -1;
1451 TA_Progress_Func progress
;
1452 void* progress_data
;
1454 FT_Bool ignore_permissions
= 0;
1455 FT_UInt fallback_script
= 0;
1460 if (!options
|| !*options
)
1461 return FT_Err_Invalid_Argument
;
1464 va_start(ap
, options
);
1477 while (*op
&& *op
!= ',')
1480 /* remove leading whitespace */
1481 while (isspace(*start
))
1484 /* check for empty option */
1490 /* the `COMPARE' macro uses `len' and `start' */
1493 if (COMPARE("in-file"))
1495 in_file
= va_arg(ap
, FILE*);
1499 else if (COMPARE("in-buffer"))
1502 in_buf
= va_arg(ap
, const char*);
1504 else if (COMPARE("in-buffer-len"))
1507 in_len
= va_arg(ap
, size_t);
1509 else if (COMPARE("out-file"))
1511 out_file
= va_arg(ap
, FILE*);
1515 else if (COMPARE("out-buffer"))
1518 out_bufp
= va_arg(ap
, char**);
1520 else if (COMPARE("out-buffer-len"))
1523 out_lenp
= va_arg(ap
, size_t*);
1525 else if (COMPARE("hinting-range-min"))
1526 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
1527 else if (COMPARE("hinting-range-max"))
1528 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
1529 else if (COMPARE("progress-callback"))
1530 progress
= va_arg(ap
, TA_Progress_Func
);
1531 else if (COMPARE("progress-callback-data"))
1532 progress_data
= va_arg(ap
, void*);
1533 else if (COMPARE("ignore-permissions"))
1534 ignore_permissions
= (FT_Bool
)va_arg(ap
, FT_Int
);
1535 else if (COMPARE("fallback-script"))
1536 fallback_script
= va_arg(ap
, FT_UInt
);
1540 x-height-snapping-exceptions
1554 || (in_buf
&& in_len
)))
1555 return FT_Err_Invalid_Argument
;
1558 || (out_bufp
&& out_lenp
)))
1559 return FT_Err_Invalid_Argument
;
1561 font
= (FONT
*)calloc(1, sizeof (FONT
));
1563 return FT_Err_Out_Of_Memory
;
1565 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
1566 return FT_Err_Invalid_Argument
;
1567 if (hinting_range_min
< 0)
1568 hinting_range_min
= 8;
1570 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
1571 return FT_Err_Invalid_Argument
;
1572 if (hinting_range_max
< 0)
1573 hinting_range_max
= 1000;
1575 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
1576 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
1578 font
->progress
= progress
;
1579 font
->progress_data
= progress_data
;
1581 font
->ignore_permissions
= ignore_permissions
;
1582 /* restrict value to two bits */
1583 font
->fallback_script
= fallback_script
& 3;
1585 /* now start with processing the data */
1589 error
= TA_font_file_read(font
, in_file
);
1595 /* a valid TTF can never be that small */
1597 return FT_Err_Invalid_Argument
;
1598 font
->in_buf
= (FT_Byte
*)in_buf
;
1599 font
->in_len
= in_len
;
1602 error
= TA_font_init(font
);
1606 /* loop over subfonts */
1607 for (i
= 0; i
< font
->num_sfnts
; i
++)
1609 SFNT
* sfnt
= &font
->sfnts
[i
];
1612 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
1617 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
1621 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
1625 /* check permission */
1626 if (sfnt
->OS2_idx
!= MISSING
)
1628 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
1631 /* check lower byte of the `fsType' field */
1632 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
1633 && !font
->ignore_permissions
)
1635 error
= TA_Err_Missing_Legal_Permission
;
1641 /* build `gasp' table */
1642 error
= TA_sfnt_build_gasp_table(&font
->sfnts
[0], font
);
1646 /* XXX handle subfonts for bytecode tables */
1648 /* build `cvt ' table */
1649 error
= TA_sfnt_build_cvt_table(&font
->sfnts
[0], font
);
1653 /* build `fpgm' table */
1654 error
= TA_sfnt_build_fpgm_table(&font
->sfnts
[0], font
);
1658 /* build `prep' table */
1659 error
= TA_sfnt_build_prep_table(&font
->sfnts
[0], font
);
1663 /* hint the glyphs and build bytecode */
1664 error
= TA_sfnt_build_glyf_hints(&font
->sfnts
[0], font
);
1668 /* loop again over subfonts */
1669 for (i
= 0; i
< font
->num_sfnts
; i
++)
1671 SFNT
* sfnt
= &font
->sfnts
[i
];
1674 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
1677 error
= TA_sfnt_build_loca_table(sfnt
, font
);
1680 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
1685 if (font
->num_sfnts
== 1)
1686 error
= TA_font_build_TTF(font
);
1688 error
= TA_font_build_TTC(font
);
1694 error
= TA_font_file_write(font
, out_file
);
1700 *out_bufp
= (char*)font
->out_buf
;
1701 *out_lenp
= font
->out_len
;
1707 TA_font_unload(font
, in_buf
, out_bufp
);
1712 /* end of ttfautohint.c */