Reduce memory consumption.
[ttfautohint.git] / lib / tattf.c
blob15ec2124e1af006d5274e7d5e0ef769448aab381
1 /* tattf.c */
3 /*
4 * Copyright (C) 2011-2012 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 /* If `do_complete' is 0, only return `header_len'. */
21 FT_Error
22 TA_sfnt_build_TTF_header(SFNT* sfnt,
23 FONT* font,
24 FT_Byte** header_buf,
25 FT_ULong* header_len,
26 FT_Int do_complete)
28 SFNT_Table* tables = font->tables;
30 SFNT_Table_Info* table_infos = sfnt->table_infos;
31 FT_ULong num_table_infos = sfnt->num_table_infos;
33 FT_Byte* buf;
34 FT_ULong len;
36 FT_Byte* table_record;
38 FT_Byte* head_buf = NULL; /* pointer to `head' table */
39 FT_ULong head_checksum; /* checksum in `head' table */
41 FT_ULong num_tables_in_header;
42 FT_ULong i;
45 num_tables_in_header = 0;
46 for (i = 0; i < num_table_infos; i++)
48 /* ignore empty tables */
49 if (table_infos[i] != MISSING)
50 num_tables_in_header++;
53 len = 12 + 16 * num_tables_in_header;
54 if (!do_complete)
56 *header_len = len;
57 return TA_Err_Ok;
59 buf = (FT_Byte*)malloc(len);
60 if (!buf)
61 return FT_Err_Out_Of_Memory;
63 /* SFNT version */
64 buf[0] = 0x00;
65 buf[1] = 0x01;
66 buf[2] = 0x00;
67 buf[3] = 0x00;
69 /* number of tables */
70 buf[4] = HIGH(num_tables_in_header);
71 buf[5] = LOW(num_tables_in_header);
73 /* auxiliary data */
75 FT_ULong search_range, entry_selector, range_shift;
76 FT_ULong i, j;
79 for (i = 1, j = 2; j <= num_tables_in_header; i++, j <<= 1)
82 entry_selector = i - 1;
83 search_range = 0x10 << entry_selector;
84 range_shift = (num_tables_in_header << 4) - search_range;
86 buf[6] = HIGH(search_range);
87 buf[7] = LOW(search_range);
88 buf[8] = HIGH(entry_selector);
89 buf[9] = LOW(entry_selector);
90 buf[10] = HIGH(range_shift);
91 buf[11] = LOW(range_shift);
94 /* location of the first table info record */
95 table_record = &buf[12];
97 head_checksum = 0;
99 /* loop over all tables */
100 for (i = 0; i < num_table_infos; i++)
102 SFNT_Table_Info table_info = table_infos[i];
103 SFNT_Table* table;
106 /* ignore empty slots */
107 if (table_info == MISSING)
108 continue;
110 table = &tables[table_info];
112 if (table->tag == TTAG_head)
114 FT_ULong date_high;
115 FT_ULong date_low;
118 /* we always reach this IF clause since FreeType would */
119 /* have aborted already if the `head' table were missing */
121 head_buf = table->buf;
123 /* reset checksum in `head' table for recalculation */
124 head_buf[8] = 0x00;
125 head_buf[9] = 0x00;
126 head_buf[10] = 0x00;
127 head_buf[11] = 0x00;
129 /* update modification time */
130 TA_get_current_time(&date_high, &date_low);
132 head_buf[28] = BYTE1(date_high);
133 head_buf[29] = BYTE2(date_high);
134 head_buf[30] = BYTE3(date_high);
135 head_buf[31] = BYTE4(date_high);
137 head_buf[32] = BYTE1(date_low);
138 head_buf[33] = BYTE2(date_low);
139 head_buf[34] = BYTE3(date_low);
140 head_buf[35] = BYTE4(date_low);
142 table->checksum = TA_table_compute_checksum(table->buf, table->len);
145 head_checksum += table->checksum;
147 table_record[0] = BYTE1(table->tag);
148 table_record[1] = BYTE2(table->tag);
149 table_record[2] = BYTE3(table->tag);
150 table_record[3] = BYTE4(table->tag);
152 table_record[4] = BYTE1(table->checksum);
153 table_record[5] = BYTE2(table->checksum);
154 table_record[6] = BYTE3(table->checksum);
155 table_record[7] = BYTE4(table->checksum);
157 table_record[8] = BYTE1(table->offset);
158 table_record[9] = BYTE2(table->offset);
159 table_record[10] = BYTE3(table->offset);
160 table_record[11] = BYTE4(table->offset);
162 table_record[12] = BYTE1(table->len);
163 table_record[13] = BYTE2(table->len);
164 table_record[14] = BYTE3(table->len);
165 table_record[15] = BYTE4(table->len);
167 table_record += 16;
170 /* the font header is complete; compute `head' checksum */
171 head_checksum += TA_table_compute_checksum(buf, len);
172 head_checksum = 0xB1B0AFBAUL - head_checksum;
174 /* store checksum in `head' table; */
175 head_buf[8] = BYTE1(head_checksum);
176 head_buf[9] = BYTE2(head_checksum);
177 head_buf[10] = BYTE3(head_checksum);
178 head_buf[11] = BYTE4(head_checksum);
180 *header_buf = buf;
181 *header_len = len;
183 return TA_Err_Ok;
187 FT_Error
188 TA_font_build_TTF(FONT* font)
190 SFNT* sfnt = &font->sfnts[0];
192 SFNT_Table* tables;
193 FT_ULong num_tables;
195 FT_ULong SFNT_offset;
197 FT_Byte* DSIG_buf;
199 FT_Byte* header_buf;
200 FT_ULong header_len;
202 FT_ULong i;
203 FT_Error error;
206 /* replace an existing `DSIG' table with a dummy */
208 if (font->have_DSIG)
210 error = TA_sfnt_add_table_info(sfnt);
211 if (error)
212 return error;
214 error = TA_table_build_DSIG(&DSIG_buf);
215 if (error)
216 return error;
218 /* in case of success, `DSIG_buf' gets linked */
219 /* and is eventually freed in `TA_font_unload' */
220 error = TA_font_add_table(font,
221 &sfnt->table_infos[sfnt->num_table_infos - 1],
222 TTAG_DSIG, DSIG_LEN, DSIG_buf);
223 if (error)
225 free(DSIG_buf);
226 return error;
230 TA_sfnt_sort_table_info(sfnt, font);
232 /* the first SFNT table immediately follows the header */
233 (void)TA_sfnt_build_TTF_header(sfnt, font, NULL, &SFNT_offset, 0);
234 TA_font_compute_table_offsets(font, SFNT_offset);
236 error = TA_sfnt_build_TTF_header(sfnt, font,
237 &header_buf, &header_len, 1);
238 if (error)
239 return error;
241 /* build font */
243 tables = font->tables;
244 num_tables = font->num_tables;
246 /* get font length from last SFNT table array element */
247 font->out_len = tables[num_tables - 1].offset
248 + ((tables[num_tables - 1].len + 3) & ~3);
249 font->out_buf = (FT_Byte*)malloc(font->out_len);
250 if (!font->out_buf)
252 error = FT_Err_Out_Of_Memory;
253 goto Err;
256 memcpy(font->out_buf, header_buf, header_len);
258 for (i = 0; i < num_tables; i++)
260 SFNT_Table* table = &tables[i];
263 /* buffer length is a multiple of 4 */
264 memcpy(font->out_buf + table->offset,
265 table->buf, (table->len + 3) & ~3);
268 error = TA_Err_Ok;
270 Err:
271 free(header_buf);
273 return error;
276 /* end of tattf.c */