beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / sfnt.w
blob83e38990dd94464b324a993c0437b454240bb865
1 % sfnt.w
3 % Copyright 2002 by Jin-Hwan Cho and Shunsaku Hirata,
4 % the dvipdfmx project team <dvipdfmx@@project.ktug.or.kr>
5 % Copyright 2006-2008 Taco Hoekwater <taco@@luatex.org>
7 % This file is part of LuaTeX.
9 % LuaTeX is free software; you can redistribute it and/or modify it under
10 % the terms of the GNU General Public License as published by the Free
11 % Software Foundation; either version 2 of the License, or (at your
12 % option) any later version.
14 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
15 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 % License for more details.
19 % You should have received a copy of the GNU General Public License along
20 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
22 @ Based on dvipdfmx-0.13.2c
26 #include "ptexlib.h"
28 #if HAVE_CONFIG_H
29 # include <w2c/config.h>
30 #endif /* |HAVE_CONFIG_H_| */
32 #include <string.h>
34 #include "font/sfnt.h"
36 @ type:
38 `true' (0x74727565): TrueType (Mac)
40 `typ1' (0x74797031) (Mac): PostScript font housed in a sfnt wrapper
42 0x00010000: TrueType (Win)/OpenType
44 `OTTO': PostScript CFF font with OpenType wrapper
46 `ttcf': TrueType Collection
49 #define SFNT_TRUETYPE 0x00010000UL
50 #define SFNT_MAC_TRUE 0x74727565UL
51 #define SFNT_OPENTYPE 0x00010000UL
52 #define SFNT_POSTSCRIPT 0x4f54544fUL
53 #define SFNT_TTC 0x74746366UL
55 sfnt *sfnt_open(unsigned char *buff, int buflen)
57 sfnt *sfont;
58 ULONG type;
60 sfont = xmalloc(sizeof(sfnt));
61 sfont->loc = 0;
62 sfont->buffer = buff;
63 sfont->buflen = buflen;
65 type = sfnt_get_ulong(sfont);
67 if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
68 sfont->type = SFNT_TYPE_TRUETYPE;
69 } else if (type == SFNT_OPENTYPE) {
70 sfont->type = SFNT_TYPE_OPENTYPE;
71 } else if (type == SFNT_POSTSCRIPT) {
72 sfont->type = SFNT_TYPE_POSTSCRIPT;
73 } else if (type == SFNT_TTC) {
74 sfont->type = SFNT_TYPE_TTC;
77 sfont->loc = 0;
78 sfont->directory = NULL;
79 return sfont;
82 static void release_directory(struct sfnt_table_directory *td)
84 long i;
86 if (td) {
87 if (td->tables) {
88 for (i = 0; i < td->num_tables; i++) {
89 if (td->tables[i].data)
90 RELEASE(td->tables[i].data);
92 RELEASE(td->tables);
94 if (td->flags)
95 RELEASE(td->flags);
96 RELEASE(td);
99 return;
102 void sfnt_close(sfnt * sfont)
105 if (sfont) {
106 if (sfont->directory)
107 release_directory(sfont->directory);
108 RELEASE(sfont);
111 return;
114 int put_big_endian(void *s, LONG q, int n)
116 int i;
117 char *p;
119 p = (char *) s;
120 for (i = n - 1; i >= 0; i--) {
121 p[i] = (char) (q & 0xff);
122 q >>= 8;
125 return n;
128 @ Convert four-byte number to big endianess in a machine independent way.
131 static void convert_tag(char *tag, unsigned long u_tag)
133 int i;
135 for (i = 3; i >= 0; i--) {
136 tag[i] = (char) (u_tag % 256);
137 u_tag /= 256;
140 return;
144 @ Computes the max power of 2 <= n
147 static unsigned max2floor(unsigned n)
149 int val = 1;
151 while (n > 1) {
152 n /= 2;
153 val *= 2;
156 return (unsigned) val;
160 @ Computes the log2 of the max power of 2 <= n
163 static unsigned log2floor(unsigned n)
165 unsigned val = 0;
167 while (n > 1) {
168 n /= 2;
169 val++;
172 return val;
175 @ @c
176 static ULONG sfnt_calc_checksum(void *data, ULONG length)
178 ULONG chksum = 0;
179 BYTE *p, *endptr;
180 ULONG count = 0;
182 p = (BYTE *) data;
183 endptr = p + length;
184 while (p < endptr) {
185 chksum = chksum + (ULONG) (p[0] << (8 * (3 - count)));
186 count = ((count + 1) & 3);
187 p++;
190 return chksum;
193 @ @c
194 static int find_table_index(struct sfnt_table_directory *td, const char *tag)
196 int idx;
198 if (!td)
199 return -1;
201 for (idx = 0; idx < td->num_tables; idx++) {
202 if (!memcmp(td->tables[idx].tag, tag, 4))
203 return idx;
206 return -1;
209 @ @c
210 void sfnt_set_table(sfnt * sfont, const char *tag, void *data, ULONG length)
212 struct sfnt_table_directory *td;
213 int idx;
215 ASSERT(sfont);
217 td = sfont->directory;
218 idx = find_table_index(td, tag);
220 if (idx < 0) {
221 idx = td->num_tables;
222 td->num_tables++;
223 td->tables = RENEW(td->tables, td->num_tables, struct sfnt_table);
224 memcpy(td->tables[idx].tag, tag, 4);
227 td->tables[idx].check_sum = sfnt_calc_checksum(data, length);
228 td->tables[idx].offset = 0L;
229 td->tables[idx].length = length;
230 td->tables[idx].data = data;
232 return;
235 @ @c
236 ULONG sfnt_find_table_len(sfnt * sfont, const char *tag)
238 ULONG length;
239 struct sfnt_table_directory *td;
240 int idx;
242 ASSERT(sfont && tag);
244 td = sfont->directory;
245 idx = find_table_index(td, tag);
246 if (idx < 0)
247 length = 0;
248 else {
249 length = td->tables[idx].length;
252 return length;
255 @ @c
256 ULONG sfnt_find_table_pos(sfnt * sfont, const char *tag)
258 ULONG offset;
259 struct sfnt_table_directory *td;
260 int idx;
262 ASSERT(sfont && tag);
264 td = sfont->directory;
265 idx = find_table_index(td, tag);
266 if (idx < 0)
267 offset = 0;
268 else {
269 offset = td->tables[idx].offset;
272 return offset;
275 @ @c
276 ULONG sfnt_locate_table(sfnt * sfont, const char *tag)
278 ULONG offset;
280 ASSERT(sfont && tag);
282 offset = sfnt_find_table_pos(sfont, tag);
283 if (offset == 0)
284 normal_error("ttf","sfnt table not found");
286 sfnt_seek_set(sfont, (long) offset);
288 return offset;
291 @ @c
292 int sfnt_read_table_directory(sfnt * sfont, ULONG offset)
294 struct sfnt_table_directory *td;
295 unsigned long i, u_tag;
297 ASSERT(sfont);
299 if (sfont->directory)
300 release_directory(sfont->directory);
301 sfont->directory = td = NEW(1, struct sfnt_table_directory);
303 ASSERT(sfont->buffer);
304 sfnt_seek_set(sfont, (long) offset);
306 td->version = sfnt_get_ulong(sfont);
307 td->num_tables = sfnt_get_ushort(sfont);
308 td->search_range = sfnt_get_ushort(sfont);
309 td->entry_selector = sfnt_get_ushort(sfont);
310 td->range_shift = sfnt_get_ushort(sfont);
312 td->flags = NEW(td->num_tables, char);
313 td->tables = NEW(td->num_tables, struct sfnt_table);
315 for (i = 0; i < td->num_tables; i++) {
316 u_tag = sfnt_get_ulong(sfont);
318 convert_tag(td->tables[i].tag, u_tag);
319 td->tables[i].check_sum = sfnt_get_ulong(sfont);
320 td->tables[i].offset = sfnt_get_ulong(sfont);
321 td->tables[i].length = sfnt_get_ulong(sfont);
322 td->tables[i].data = NULL;
324 td->flags[i] = 0;
327 td->num_kept_tables = 0;
329 return 0;
332 @ @c
333 int sfnt_require_table(sfnt * sfont, const char *tag, int must_exist)
335 struct sfnt_table_directory *td;
336 int idx;
338 ASSERT(sfont && sfont->directory);
340 td = sfont->directory;
341 idx = find_table_index(td, tag);
342 if (idx < 0) {
343 if (must_exist)
344 return -1;
345 } else {
346 td->flags[idx] |= SFNT_TABLE_REQUIRED;
347 td->num_kept_tables++;
350 return 0;
355 @ All tables begin on four byte boundries, and pad any remaining space
356 between tables with zeros
358 Entries in the Table Directory must be sorted in ascending order by tag
360 The head table contains checksum of the whole font file.
361 To compute: first set it to 0, sum the entire font as ULONG,
362 then store 0xB1B0AFBA - sum.
365 # include "font/luatexfont.h"
366 # undef MIN
367 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
368 # define STREAM_COMPRESS
370 static unsigned char wbuf[1024], padbytes[4] = { 0, 0, 0, 0 };
372 pdf_obj *sfnt_create_FontFile_stream(sfnt * sfont)
374 pdf_obj *stream;
375 struct sfnt_table_directory *td;
376 long offset, nb_read, length;
377 int i, sr;
378 char *p;
380 ASSERT(sfont && sfont->directory);
382 stream = pdf_new_stream(STREAM_COMPRESS);
384 td = sfont->directory;
386 /* Header */
387 p = (char *) wbuf;
388 p += sfnt_put_ulong(p, (LONG) td->version);
389 p += sfnt_put_ushort(p, td->num_kept_tables);
390 sr = (int) (max2floor(td->num_kept_tables) * 16);
391 p += sfnt_put_ushort(p, sr);
392 p += sfnt_put_ushort(p, log2floor(td->num_kept_tables));
393 p += sfnt_put_ushort(p, td->num_kept_tables * 16 - sr);
395 pdf_add_stream(stream, wbuf, 12);
398 Compute start of actual tables (after headers).
400 offset = 12 + 16 * td->num_kept_tables;
401 for (i = 0; i < td->num_tables; i++) {
402 /* This table must exist in FontFile */
403 if (td->flags[i] & SFNT_TABLE_REQUIRED) {
404 if ((offset % 4) != 0) {
405 offset += 4 - (offset % 4);
408 p = (char *) wbuf;
409 memcpy(p, td->tables[i].tag, 4);
410 p += 4;
411 p += sfnt_put_ulong(p, (LONG) td->tables[i].check_sum);
412 p += sfnt_put_ulong(p, offset);
413 p += sfnt_put_ulong(p, (LONG) td->tables[i].length);
414 pdf_add_stream(stream, wbuf, 16);
416 offset = (long) (offset + (long) td->tables[i].length);
420 offset = 12 + 16 * td->num_kept_tables;
421 for (i = 0; i < td->num_tables; i++) {
422 if (td->flags[i] & SFNT_TABLE_REQUIRED) {
423 if ((offset % 4) != 0) {
424 length = 4 - (offset % 4);
425 pdf_add_stream(stream, padbytes, length);
426 offset += length;
428 if (!td->tables[i].data) {
429 if (!sfont->buffer)
431 pdf_release_obj(stream);
432 normal_error("ttf","file not opened or already closed");
433 return NULL;
436 length = (long) td->tables[i].length;
437 sfnt_seek_set(sfont, (long) td->tables[i].offset);
438 while (length > 0) {
439 nb_read = sfnt_read(wbuf, (int) MIN(length, 1024), sfont);
440 if (nb_read < 0) {
441 pdf_release_obj(stream);
442 normal_error("ttf","reading file failed");
443 return NULL;
444 } else if (nb_read > 0) {
445 pdf_add_stream(stream, wbuf, nb_read);
447 length -= nb_read;
449 } else {
450 pdf_add_stream(stream,
451 (unsigned char *) td->tables[i].data,
452 (long) td->tables[i].length);
453 RELEASE(td->tables[i].data);
454 td->tables[i].data = NULL;
456 /* Set offset for next table */
457 offset = (long) (offset + (long) td->tables[i].length);
461 return stream;