3 % Copyright
2006-2012 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
24 #include
"font/writettf.h"
25 #include
"font/writecff.h"
26 #include
"lua/luatex-api.h"
28 #include
"font/sfnt.h"
29 #include
"font/tt_glyf.h"
33 boolean make_tt_subset
(PDF pdf
, fd_entry
* fd
, unsigned char
*buff
, int buflen
);
36 unsigned long cidtogid_obj
= 0;
41 if
((f-
>loc
+ l
) > f-
>buflen
) { \
42 fprintf
(stderr
, "File ended prematurely\n"); \
47 BYTE get_unsigned_byte
(sfnt
* f
)
50 return
(BYTE) f-
>buffer
[(f-
>loc
++)];
53 ICHAR get_signed_byte
(sfnt
* f
)
56 return
(ICHAR
) f-
>buffer
[(f-
>loc
++)];
59 USHORT get_unsigned_pair
(sfnt
* f
)
63 l
= f-
>buffer
[(f-
>loc
++)];
64 l
= (USHORT
) (l
* 0x100 + f-
>buffer
[(f-
>loc
++)]);
68 SHORT get_signed_pair
(sfnt
* f
)
72 l
= f-
>buffer
[(f-
>loc
++)];
75 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
79 ULONG get_unsigned_quad
(sfnt
* f
)
83 l
= f-
>buffer
[(f-
>loc
++)];
84 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
85 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
86 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
90 int do_sfnt_read
(unsigned char
*dest
, int len
, sfnt
* f
)
94 for
(i
= 0; i
< len
; i
++) {
95 *(dest
+ i
) = f-
>buffer
[f-
>loc
+ i
];
101 pdf_obj
*pdf_new_stream
(void
)
103 pdf_obj
*stream
= xmalloc
(sizeof
(pdf_obj
));
109 void pdf_add_stream
(pdf_obj
* stream
, unsigned char
*buf
, long len
)
112 assert
(stream
!= NULL);
113 if
(stream-
>data
== NULL) {
114 stream-
>data
= xmalloc
((unsigned
) len
);
117 xrealloc
(stream-
>data
, (unsigned
) len
+ (unsigned
) stream-
>length
);
119 for
(i
= 0; i
< len
; i
++) {
120 *(stream-
>data
+ stream-
>length
+ i
) = *(buf
+ i
);
122 stream-
>length
+= (unsigned
) len
;
125 void pdf_release_obj
(pdf_obj
* stream
)
127 if
(stream
!= NULL) {
128 if
(stream-
>data
!= NULL) {
137 boolean writetype2
(PDF pdf
, fd_entry
* fd
)
145 fd_cur
= fd
; /* |fd_cur| is global inside \.
{writettf.w
} */
146 assert
(fd_cur-
>fm
!= NULL);
147 assert
(is_truetype
(fd_cur-
>fm
));
148 assert
(is_included
(fd_cur-
>fm
));
153 luatex_find_file
(fd_cur-
>fm-
>ff_name
, find_opentype_file_callback
);
154 if
(cur_file_name
== NULL) {
155 formatted_error
("type 2","cannot find file '%s'", fd_cur-
>fm-
>ff_name
);
157 callback_id
= callback_defined
(read_opentype_file_callback
);
158 if
(callback_id
> 0) {
159 if
(run_callback
(callback_id
, "S->bSd", cur_file_name
,
160 &file_opened, &ttf_buffer, &ttf_size) &&
161 file_opened
&& ttf_size > 0) {
163 formatted_error
("type 2","cannot find file '%s'", cur_file_name
);
166 if
(!otf_open
(cur_file_name
)) {
167 formatted_error
("type 2","cannot find file '%s'", cur_file_name
);
173 fd_cur-
>ff_found
= true
;
175 if
(is_subsetted
(fd_cur-
>fm
))
176 report_start_file
(filetype_subset
,cur_file_name
);
178 report_start_file
(filetype_font
,cur_file_name
);
180 /* here is the real work
*/
182 ret
= make_tt_subset
(pdf
, fd
, ttf_buffer
, ttf_size
);
187 if
(is_subsetted
(fd_cur-
>fm
))
188 report_stop_file
(filetype_subset
);
190 report_stop_file
(filetype_font
);
191 cur_file_name
= NULL;
195 @ PDF viewer applications use following tables
(CIDFontType
2)
197 \.
{head
, hhea
, loca
, maxp
, glyf
, hmtx
, fpgm
, cvt\_
, prep
}
199 \rightline
{from PDF Ref. v
.1.3, 2nd ed.
}
201 The \.
{fpgm
}, \.
{cvt\_
} and \.
{prep
} tables appears only when TrueType instructions
202 requires them. Those tables must be preserved if they exist.
203 We use |must_exist| flag to indicate `preserve it if present'
204 and to make sure not to cause an error when it does not exist.
206 \.
{post
} and \.
{name
} table must exist in ordinary TrueType font file
,
207 but when a TrueType font is converted to CIDFontType
2 font
, those tables
208 are no longer required.
210 The OS
/2 table
(required for TrueType font for Windows and OS
/2) contains
211 liscencing information
, but PDF viewers seems not using them.
213 The \.
{name
} table added. See comments in \.
{writettf.w
}.
219 } required_table
[] = {
237 unsigned long ttc_read_offset
(sfnt
* sfont
, int ttc_idx
, fd_entry
* fd
)
240 unsigned long offset
= 0;
241 unsigned long num_dirs
= 0;
243 sfnt_seek_set
(sfont
, 4); /* skip version tag
*/
245 /*version
= */(void
)sfnt_get_ulong
(sfont
);
246 num_dirs
= sfnt_get_ulong
(sfont
);
247 if
(ttc_idx
< 0 || ttc_idx
> (int
) (num_dirs
- 1)) {
248 fprintf
(stderr
, "Invalid TTC index number %i (0..%i), using index 0 for font %s\n",
249 ttc_idx
,(int
) (num_dirs
- 1),(fd-
>fm-
>ps_name ? fd-
>fm-
>ps_name
: ""));
252 sfnt_seek_set
(sfont
, 12 + ttc_idx
* 4);
253 offset
= sfnt_get_ulong
(sfont
);
258 @ Creating the subset.
261 boolean make_tt_subset
(PDF pdf
, fd_entry
* fd
, unsigned char
*buff
, int buflen
)
265 unsigned int last_cid
= 0;
267 struct avl_traverser t
;
268 unsigned char
*cidtogidmap
;
269 unsigned short num_glyphs
, gid
;
270 struct tt_glyphs
*glyphs
;
271 char
*used_chars
= NULL;
274 int verbose
= 0, error
= 0;
278 sfont
= sfnt_open
(buff
, buflen
);
280 if
(sfont-
>type
== SFNT_TYPE_TTC
) {
281 i
= ff_get_ttc_index
(fd-
>fm-
>ff_name
, fd-
>fm-
>ps_name
);
282 error
= sfnt_read_table_directory
(sfont
, ttc_read_offset
(sfont
, (int
) i
, fd
));
284 error
= sfnt_read_table_directory
(sfont
, 0);
288 fprintf
(stderr
, "Could not parse the ttf directory.\n");
292 if
(sfont-
>type
== SFNT_TYPE_TTC
&& sfnt_find_table_pos(sfont, "CFF ")) {
297 if
(is_subsetted
(fd-
>fm
)) {
298 /* rebuild the glyph tables and create a fresh cidmap
*/
299 glyphs
= tt_build_init
();
303 avl_t_init
(&t, fd->gl_tree);
304 for
(found
= (glw_entry
*) avl_t_first
(&t, fd->gl_tree);
305 found
!= NULL; found
= (glw_entry
*) avl_t_next
(&t)) {
306 if
(found-
>id
> last_cid
)
307 last_cid
= found-
>id
;
310 #ifndef NO_GHOSTSCRIPT_BUG
313 cidtogidmap
= xmalloc
(((last_cid
+ 1) * 2) * sizeof
(unsigned char
));
314 memset
(cidtogidmap
, 0, (last_cid
+ 1) * 2);
317 /* fill |used_chars|
*/
318 used_chars
= xmalloc
((last_cid
+ 1) * sizeof
(char
));
319 memset
(used_chars
, 0, (last_cid
+ 1));
320 avl_t_init
(&t, fd->gl_tree);
321 for
(found
= (glw_entry
*) avl_t_first
(&t, fd->gl_tree);
322 found
!= NULL; found
= (glw_entry
*) avl_t_next
(&t)) {
323 used_chars
[found-
>id
] = 1;
326 /* Map CIDs to GIDs.
*/
328 num_glyphs
= 1; /* \.
{.notdef
} */
329 for
(cid
= 1; cid
<= (long
) last_cid
; cid
++) {
330 if
(used_chars
[cid
] == 0)
332 gid
= (short unsigned
) cid
;
335 #ifndef NO_GHOSTSCRIPT_BUG
336 gid
= tt_add_glyph
(glyphs
, (USHORT
) gid
, (USHORT
) cid
);
338 gid
= tt_add_glyph
(glyphs
, (USHORT
) gid
, (USHORT
) num_glyphs
);
339 cidtogidmap
[2 * cid
] = gid
>> 8;
340 cidtogidmap
[2 * cid
+ 1] = gid
& 0xff;
341 #endif
/* |
!NO_GHOSTSCRIPT_BUG|
*/
346 if
(num_glyphs
== 1) {
347 fprintf
(stderr
, "No glyphs in subset?.\n");
351 if
(tt_build_tables
(sfont
, glyphs
) < 0) {
352 fprintf
(stderr
, "Could not parse the ttf buffer.\n");
357 fprintf
(stdout
, "[%u glyphs (Max CID: %u)]", glyphs-
>num_glyphs
,
361 tt_build_finish
(glyphs
);
364 /* Create font file
*/
366 for
(i
= 0; required_table
[i
].name
; i
++) {
367 if
(sfnt_require_table
(sfont
,
368 required_table
[i
].name
,
369 required_table
[i
].must_exist
) < 0) {
370 fprintf
(stderr
, "Some required TrueType table does not exist.");
375 fontfile
= sfnt_create_FontFile_stream
(sfont
);
378 fprintf
(stdout
, "[%ld bytes]", fontfile-
>length
);
381 /* squeeze in the cidgidmap
*/
382 if
(cidtogidmap
!= NULL) {
383 cidtogid_obj
= (unsigned long
) pdf_create_obj
(pdf
, obj_type_others
, 0);
384 pdf_begin_obj
(pdf
, (int
) cidtogid_obj
, OBJSTM_NEVER
);
386 pdf_dict_add_int
(pdf
, "Length", ((last_cid
+ 1) * 2));
388 assert
(0); /* code unused
*/
389 pdf_begin_stream
(pdf
);
390 pdf_room
(pdf
, (int
) ((last_cid
+ 1) * 2));
391 for
(i
= 0; i
< ((int
) (last_cid
+ 1) * 2); i
++) {
392 pdf_quick_out
(pdf
, cidtogidmap
[i
]);
399 for
(i
= 0; i
< (int
) (fontfile-
>length
); i
++)
400 strbuf_putchar
(pdf-
>fb
, fontfile-
>data
[i
]);
402 pdf_release_obj
(fontfile
);
404 /* CIDSet
: a table of bits indexed by cid
, bytes with high order bit first
,
405 each
(set
) bit is a
(present
) CID.
*/
406 if
(is_subsetted
(fd-
>fm
)) {
407 cidset
= pdf_create_obj
(pdf
, obj_type_others
, 0);
409 size_t l
= (last_cid
/ 8) + 1;
410 char
*stream
= xmalloc
(l
);
411 memset
(stream
, 0, l
);
412 for
(cid
= 1; cid
<= (long
) last_cid
; cid
++) {
413 if
(used_chars
[cid
]) {
414 stream
[(cid
/ 8)] |
= (1 << (7 - (cid
% 8)));
417 pdf_begin_obj
(pdf
, cidset
, OBJSTM_NEVER
);
419 pdf_dict_add_streaminfo
(pdf
);
421 pdf_begin_stream
(pdf
);
422 pdf_out_block
(pdf
, stream
, l
);
428 /* TODO other stuff that needs fixing
: */
430 /* DW
, W
, DW2
, and W2
*/
432 if
(opt_flags
& CIDFONT_FORCE_FIXEDPITCH) {
433 pdf_add_dict
(font-
>fontdict
,
434 pdf_new_name
("DW"), pdf_new_number
(1000.0));
436 add_TTCIDHMetrics
(font-
>fontdict
, glyphs
, used_chars
, cidtogidmap
,
439 add_TTCIDVMetrics
(font-
>fontdict
, glyphs
, used_chars
, cidtogidmap
,