Fix OTS warning about `maxp.maxSizeOfInstructions`.
[ttfautohint.git] / lib / tattc.c
blobc3f2b69c216c4a409ef7d377a172374a7d0d7da6
1 /* tattc.c */
3 /*
4 * Copyright (C) 2011-2022 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 static FT_Error
20 TA_font_build_TTC_header(FONT* font,
21 FT_Byte** header_buf,
22 FT_ULong* header_len)
24 SFNT* sfnts = font->sfnts;
25 FT_Long num_sfnts = font->num_sfnts;
27 SFNT_Table* tables = font->tables;
28 FT_ULong num_tables = font->num_tables;
30 FT_ULong TTF_offset;
31 FT_ULong DSIG_offset;
33 FT_Byte* buf;
34 FT_ULong len;
36 FT_Long i;
37 FT_Byte* p;
40 len = (FT_ULong)((font->have_DSIG ? 24 : 12) + 4 * num_sfnts);
41 buf = (FT_Byte*)malloc(len);
42 if (!buf)
43 return FT_Err_Out_Of_Memory;
45 p = buf;
47 /* TTC ID string */
48 *(p++) = 't';
49 *(p++) = 't';
50 *(p++) = 'c';
51 *(p++) = 'f';
53 /* TTC header version */
54 *(p++) = 0x00;
55 *(p++) = font->have_DSIG ? 0x02 : 0x01;
56 *(p++) = 0x00;
57 *(p++) = 0x00;
59 /* number of subfonts */
60 *(p++) = BYTE1(num_sfnts);
61 *(p++) = BYTE2(num_sfnts);
62 *(p++) = BYTE3(num_sfnts);
63 *(p++) = BYTE4(num_sfnts);
65 /* the first TTF subfont header immediately follows the TTC header */
66 TTF_offset = len;
68 /* loop over all subfonts */
69 for (i = 0; i < num_sfnts; i++)
71 SFNT* sfnt = &sfnts[i];
72 FT_ULong l;
75 TA_sfnt_sort_table_info(sfnt, font);
76 /* only get header length */
77 (void)TA_sfnt_build_TTF_header(sfnt, font, NULL, &l, 0);
79 *(p++) = BYTE1(TTF_offset);
80 *(p++) = BYTE2(TTF_offset);
81 *(p++) = BYTE3(TTF_offset);
82 *(p++) = BYTE4(TTF_offset);
84 TTF_offset += l;
87 /* the first SFNT table immediately follows the subfont TTF headers */
88 TA_font_compute_table_offsets(font, TTF_offset);
90 if (font->have_DSIG)
92 /* DSIG tag */
93 *(p++) = 'D';
94 *(p++) = 'S';
95 *(p++) = 'I';
96 *(p++) = 'G';
98 /* DSIG length */
99 *(p++) = 0x00;
100 *(p++) = 0x00;
101 *(p++) = 0x00;
102 *(p++) = 0x08;
104 /* DSIG offset; in a TTC this is always the last SFNT table */
105 DSIG_offset = tables[num_tables - 1].offset;
107 *(p++) = BYTE1(DSIG_offset);
108 *(p++) = BYTE2(DSIG_offset);
109 *(p++) = BYTE3(DSIG_offset);
110 *(p++) = BYTE4(DSIG_offset);
113 *header_buf = buf;
114 *header_len = len;
116 return TA_Err_Ok;
120 FT_Error
121 TA_font_build_TTC(FONT* font)
123 SFNT* sfnts = font->sfnts;
124 FT_Long num_sfnts = font->num_sfnts;
126 SFNT_Table* tables;
127 FT_ULong num_tables;
129 FT_Byte* TTC_header_buf;
130 FT_ULong TTC_header_len;
132 FT_Byte** TTF_header_bufs = NULL;
133 FT_ULong* TTF_header_lens = NULL;
135 FT_ULong offset;
136 FT_Long i;
137 FT_ULong j;
138 FT_Error error;
141 /* add our information table to first subfont; */
142 /* this is enforced by the TTC structure, */
143 /* which only allows `DSIG' to be not related to a subfont */
145 if (font->TTFA_info)
147 SFNT* sfnt0 = &sfnts[0];
149 FT_Byte* TTFA_buf;
150 FT_ULong TTFA_len;
153 error = TA_sfnt_add_table_info(sfnt0);
154 if (error)
155 return error;
157 error = TA_table_build_TTFA(&TTFA_buf, &TTFA_len, font);
158 if (error)
159 return error;
161 /* in case of success, `TTFA_buf' gets linked */
162 /* and is eventually freed in `TA_font_unload' */
163 error = TA_font_add_table(font,
164 &sfnt0->table_infos[sfnt0->num_table_infos - 1],
165 TTAG_TTFA, TTFA_len, TTFA_buf);
166 if (error)
168 free(TTFA_buf);
169 return error;
173 /* replace an existing `DSIG' table with a dummy */
175 if (font->have_DSIG)
177 FT_Byte* DSIG_buf;
178 SFNT_Table_Info dummy;
181 error = TA_table_build_DSIG(&DSIG_buf);
182 if (error)
183 return error;
185 /* in case of success, `DSIG_buf' gets linked */
186 /* and is eventually freed in `TA_font_unload' */
187 error = TA_font_add_table(font, &dummy, TTAG_DSIG, DSIG_LEN, DSIG_buf);
188 if (error)
190 free(DSIG_buf);
191 return error;
195 /* this also computes the SFNT table offsets */
196 error = TA_font_build_TTC_header(font,
197 &TTC_header_buf, &TTC_header_len);
198 if (error)
199 return error;
201 TTF_header_bufs = (FT_Byte**)calloc(1, (size_t)num_sfnts * sizeof (FT_Byte*));
202 if (!TTF_header_bufs)
203 goto Err;
205 TTF_header_lens = (FT_ULong*)malloc((size_t)num_sfnts * sizeof (FT_ULong));
206 if (!TTF_header_lens)
207 goto Err;
209 for (i = 0; i < num_sfnts; i++)
211 error = TA_sfnt_build_TTF_header(&sfnts[i], font,
212 &TTF_header_bufs[i],
213 &TTF_header_lens[i], 1);
214 if (error)
215 goto Err;
218 /* build font */
220 tables = font->tables;
221 num_tables = font->num_tables;
223 /* get font length from last SFNT table array element */
224 font->out_len = tables[num_tables - 1].offset
225 + ((tables[num_tables - 1].len + 3) & ~3U);
226 /* if `out-buffer' is set, this buffer gets returned to the user, */
227 /* thus we use the customized allocator function */
228 font->out_buf = (FT_Byte*)font->allocate(font->out_len);
229 if (!font->out_buf)
231 error = FT_Err_Out_Of_Memory;
232 goto Err;
235 memcpy(font->out_buf, TTC_header_buf, TTC_header_len);
237 offset = TTC_header_len;
239 for (i = 0; i < num_sfnts; i++)
241 memcpy(font->out_buf + offset,
242 TTF_header_bufs[i], TTF_header_lens[i]);
244 offset += TTF_header_lens[i];
247 for (j = 0; j < num_tables; j++)
249 SFNT_Table* table = &tables[j];
252 /* buffer length is a multiple of 4 */
253 memcpy(font->out_buf + table->offset,
254 table->buf, (table->len + 3) & ~3U);
257 error = TA_Err_Ok;
259 Err:
260 free(TTC_header_buf);
261 if (TTF_header_bufs)
263 for (i = 0; i < font->num_sfnts; i++)
264 free(TTF_header_bufs[i]);
265 free(TTF_header_bufs);
267 free(TTF_header_lens);
269 return error;
273 /* end of tattc.c */