Add code to adjust `hmtx' table.
[ttfautohint.git] / src / tasfnt.c
blob2c27b5f4e18e9b811bc5e9de95e61acd5f92db11
1 /* tasfnt.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_split_into_SFNT_tables(SFNT* sfnt,
21 FONT* font)
23 FT_Error error;
24 FT_ULong i;
27 /* basic check whether font is a TTF or TTC */
28 if (!FT_IS_SFNT(sfnt->face))
29 return FT_Err_Invalid_Argument;
31 error = FT_Sfnt_Table_Info(sfnt->face, 0, NULL, &sfnt->num_table_infos);
32 if (error)
33 return error;
35 sfnt->table_infos = (SFNT_Table_Info*)malloc(sfnt->num_table_infos
36 * sizeof (SFNT_Table_Info));
37 if (!sfnt->table_infos)
38 return FT_Err_Out_Of_Memory;
40 /* collect SFNT tables and trace some of them */
41 sfnt->glyf_idx = MISSING;
42 sfnt->loca_idx = MISSING;
43 sfnt->head_idx = MISSING;
44 sfnt->hmtx_idx = MISSING;
45 sfnt->maxp_idx = MISSING;
46 sfnt->OS2_idx = MISSING;
47 sfnt->GPOS_idx = MISSING;
49 for (i = 0; i < sfnt->num_table_infos; i++)
51 SFNT_Table_Info* table_info = &sfnt->table_infos[i];
52 FT_ULong tag;
53 FT_ULong len;
54 FT_Byte* buf;
56 FT_ULong buf_len;
57 FT_ULong j;
60 *table_info = MISSING;
62 error = FT_Sfnt_Table_Info(sfnt->face, i, &tag, &len);
63 if (error)
65 /* this ignores both missing and zero-length tables */
66 if (error == FT_Err_Table_Missing)
67 continue;
68 else
69 return error;
72 /* ignore tables which we are going to create by ourselves, */
73 /* or which would become invalid otherwise */
74 else if (tag == TTAG_fpgm
75 || tag == TTAG_prep
76 || tag == TTAG_cvt
77 || tag == TTAG_hdmx
78 || tag == TTAG_VDMX
79 || tag == TTAG_LTSH
80 || tag == TTAG_gasp)
81 continue;
83 else if (tag == TTAG_DSIG)
85 font->have_DSIG = 1;
86 continue;
89 /* make the allocated buffer length a multiple of 4 */
90 buf_len = (len + 3) & ~3;
91 buf = (FT_Byte*)malloc(buf_len);
92 if (!buf)
93 return FT_Err_Out_Of_Memory;
95 /* pad end of buffer with zeros */
96 buf[buf_len - 1] = 0x00;
97 buf[buf_len - 2] = 0x00;
98 buf[buf_len - 3] = 0x00;
100 /* load table */
101 error = FT_Load_Sfnt_Table(sfnt->face, tag, 0, buf, &len);
102 if (error)
103 goto Err;
105 /* check whether we already have this table */
106 for (j = 0; j < font->num_tables; j++)
108 SFNT_Table* table = &font->tables[j];
111 if (table->tag == tag
112 && table->len == len
113 && !memcmp(table->buf, buf, len))
114 break;
117 if (tag == TTAG_head)
118 sfnt->head_idx = j;
119 else if (tag == TTAG_glyf)
120 sfnt->glyf_idx = j;
121 else if (tag == TTAG_hmtx)
122 sfnt->hmtx_idx = j;
123 else if (tag == TTAG_loca)
124 sfnt->loca_idx = j;
125 else if (tag == TTAG_maxp)
127 sfnt->maxp_idx = j;
129 sfnt->max_components = buf[MAXP_MAX_COMPONENTS_OFFSET] << 8;
130 sfnt->max_components += buf[MAXP_MAX_COMPONENTS_OFFSET + 1];
132 else if (tag == TTAG_OS2)
133 sfnt->OS2_idx = j;
134 else if (tag == TTAG_GPOS)
135 sfnt->GPOS_idx = j;
137 if (j == font->num_tables)
139 /* add element to table array if it is missing or different; */
140 /* in case of success, `buf' gets linked and is eventually */
141 /* freed in `TA_font_unload' */
142 error = TA_font_add_table(font, table_info, tag, len, buf);
143 if (error)
144 goto Err;
146 else
148 /* reuse existing SFNT table */
149 free(buf);
150 *table_info = j;
152 continue;
154 Err:
155 free(buf);
156 return error;
159 /* no (non-empty) `glyf', `loca', `head', or `maxp' table; */
160 /* this can't be a valid TTF with outlines */
161 if (sfnt->glyf_idx == MISSING
162 || sfnt->loca_idx == MISSING
163 || sfnt->head_idx == MISSING
164 || sfnt->maxp_idx == MISSING)
165 return FT_Err_Invalid_Argument;
167 return TA_Err_Ok;
170 /* end of tasfnt.c */