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
29 # include
<w2c
/config.h
>
30 #endif
/* |HAVE_CONFIG_H_|
*/
34 #include
"font/sfnt.h"
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
)
60 sfont
= xmalloc
(sizeof
(sfnt
));
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
;
78 sfont-
>directory
= NULL;
82 static void release_directory
(struct sfnt_table_directory
*td
)
88 for
(i
= 0; i
< td-
>num_tables
; i
++) {
89 if
(td-
>tables
[i
].data
)
90 RELEASE(td-
>tables
[i
].data
);
102 void sfnt_close
(sfnt
* sfont
)
106 if
(sfont-
>directory
)
107 release_directory
(sfont-
>directory
);
114 int put_big_endian
(void
*s
, LONG q
, int n
)
120 for
(i
= n
- 1; i
>= 0; i--
) {
121 p
[i
] = (char
) (q
& 0xff);
128 @ Convert four-byte number to big endianess in a machine independent way.
131 static void convert_tag
(char
*tag
, unsigned long u_tag
)
135 for
(i
= 3; i
>= 0; i--
) {
136 tag
[i
] = (char
) (u_tag
% 256);
144 @ Computes the max power of
2 <= n
147 static unsigned max2floor
(unsigned n
)
156 return
(unsigned
) val
;
160 @ Computes the log2 of the max power of
2 <= n
163 static unsigned log2floor
(unsigned n
)
176 static ULONG sfnt_calc_checksum
(void
*data
, ULONG length
)
185 chksum
= chksum
+ (ULONG
) (p
[0] << (8 * (3 - count
)));
186 count
= ((count
+ 1) & 3);
194 static int find_table_index
(struct sfnt_table_directory
*td
, const char
*tag
)
201 for
(idx
= 0; idx
< td-
>num_tables
; idx
++) {
202 if
(!memcmp
(td-
>tables
[idx
].tag
, tag
, 4))
210 void sfnt_set_table
(sfnt
* sfont
, const char
*tag
, void
*data
, ULONG length
)
212 struct sfnt_table_directory
*td
;
217 td
= sfont-
>directory
;
218 idx
= find_table_index
(td
, tag
);
221 idx
= 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
;
236 ULONG sfnt_find_table_len
(sfnt
* sfont
, const char
*tag
)
239 struct sfnt_table_directory
*td
;
242 ASSERT
(sfont
&& tag);
244 td
= sfont-
>directory
;
245 idx
= find_table_index
(td
, tag
);
249 length
= td-
>tables
[idx
].length
;
256 ULONG sfnt_find_table_pos
(sfnt
* sfont
, const char
*tag
)
259 struct sfnt_table_directory
*td
;
262 ASSERT
(sfont
&& tag);
264 td
= sfont-
>directory
;
265 idx
= find_table_index
(td
, tag
);
269 offset
= td-
>tables
[idx
].offset
;
276 ULONG sfnt_locate_table
(sfnt
* sfont
, const char
*tag
)
280 ASSERT
(sfont
&& tag);
282 offset
= sfnt_find_table_pos
(sfont
, tag
);
284 normal_error
("ttf","sfnt table not found");
286 sfnt_seek_set
(sfont
, (long
) offset
);
292 int sfnt_read_table_directory
(sfnt
* sfont
, ULONG offset
)
294 struct sfnt_table_directory
*td
;
295 unsigned long i
, u_tag
;
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;
327 td-
>num_kept_tables
= 0;
333 int sfnt_require_table
(sfnt
* sfont
, const char
*tag
, int must_exist
)
335 struct sfnt_table_directory
*td
;
338 ASSERT
(sfont
&& sfont->directory);
340 td
= sfont-
>directory
;
341 idx
= find_table_index
(td
, tag
);
346 td-
>flags
[idx
] |
= SFNT_TABLE_REQUIRED
;
347 td-
>num_kept_tables
++;
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"
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
)
375 struct sfnt_table_directory
*td
;
376 long offset
, nb_read
, length
;
380 ASSERT
(sfont
&& sfont->directory);
382 stream
= pdf_new_stream
(STREAM_COMPRESS
);
384 td
= sfont-
>directory
;
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);
409 memcpy
(p
, td-
>tables
[i
].tag
, 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
);
428 if
(!td-
>tables
[i
].data
) {
431 pdf_release_obj
(stream
);
432 normal_error
("ttf","file not opened or already closed");
436 length
= (long
) td-
>tables
[i
].length
;
437 sfnt_seek_set
(sfont
, (long
) td-
>tables
[i
].offset
);
439 nb_read
= sfnt_read
(wbuf
, (int
) MIN(length
, 1024), sfont
);
441 pdf_release_obj
(stream
);
442 normal_error
("ttf","reading file failed");
444 } else if
(nb_read
> 0) {
445 pdf_add_stream
(stream
, wbuf
, nb_read
);
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
);