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 normal_error
("type 2","the file ended prematurely"); \
45 BYTE get_unsigned_byte
(sfnt
* f
)
48 return
(BYTE) f-
>buffer
[(f-
>loc
++)];
51 ICHAR get_signed_byte
(sfnt
* f
)
54 return
(ICHAR
) f-
>buffer
[(f-
>loc
++)];
57 USHORT get_unsigned_pair
(sfnt
* f
)
61 l
= f-
>buffer
[(f-
>loc
++)];
62 l
= (USHORT
) (l
* 0x100 + f-
>buffer
[(f-
>loc
++)]);
66 SHORT get_signed_pair
(sfnt
* f
)
70 l
= f-
>buffer
[(f-
>loc
++)];
73 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
77 ULONG get_unsigned_quad
(sfnt
* f
)
81 l
= f-
>buffer
[(f-
>loc
++)];
82 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
83 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
84 l
= l
* 0x100 + f-
>buffer
[(f-
>loc
++)];
88 int do_sfnt_read
(unsigned char
*dest
, int len
, sfnt
* f
)
92 for
(i
= 0; i
< len
; i
++) {
93 *(dest
+ i
) = f-
>buffer
[f-
>loc
+ i
];
99 pdf_obj
*pdf_new_stream
(void
)
101 pdf_obj
*stream
= xmalloc
(sizeof
(pdf_obj
));
107 void pdf_add_stream
(pdf_obj
* stream
, unsigned char
*buf
, long len
)
110 assert
(stream
!= NULL);
111 if
(stream-
>data
== NULL) {
112 stream-
>data
= xmalloc
((unsigned
) len
);
115 xrealloc
(stream-
>data
, (unsigned
) len
+ (unsigned
) stream-
>length
);
117 for
(i
= 0; i
< len
; i
++) {
118 *(stream-
>data
+ stream-
>length
+ i
) = *(buf
+ i
);
120 stream-
>length
+= (unsigned
) len
;
123 void pdf_release_obj
(pdf_obj
* stream
)
125 if
(stream
!= NULL) {
126 if
(stream-
>data
!= NULL) {
135 boolean writetype2
(PDF pdf
, fd_entry
* fd
)
143 fd_cur
= fd
; /* |fd_cur| is global inside \.
{writettf.w
} */
144 assert
(fd_cur-
>fm
!= NULL);
145 assert
(is_truetype
(fd_cur-
>fm
));
146 assert
(is_included
(fd_cur-
>fm
));
151 luatex_find_file
(fd_cur-
>fm-
>ff_name
, find_opentype_file_callback
);
152 if
(cur_file_name
== NULL) {
153 formatted_error
("type 2","cannot find file '%s'", fd_cur-
>fm-
>ff_name
);
155 callback_id
= callback_defined
(read_opentype_file_callback
);
156 if
(callback_id
> 0) {
157 if
(run_callback
(callback_id
, "S->bSd", cur_file_name
,
158 &file_opened, &ttf_buffer, &ttf_size) &&
159 file_opened
&& ttf_size > 0) {
161 formatted_error
("type 2","cannot find file '%s'", cur_file_name
);
164 if
(!otf_open
(cur_file_name
)) {
165 formatted_error
("type 2","cannot find file '%s'", cur_file_name
);
171 fd_cur-
>ff_found
= true
;
173 if
(is_subsetted
(fd_cur-
>fm
))
174 report_start_file
(filetype_subset
,cur_file_name
);
176 report_start_file
(filetype_font
,cur_file_name
);
178 /* here is the real work
*/
180 ret
= make_tt_subset
(pdf
, fd
, ttf_buffer
, ttf_size
);
185 if
(is_subsetted
(fd_cur-
>fm
))
186 report_stop_file
(filetype_subset
);
188 report_stop_file
(filetype_font
);
189 cur_file_name
= NULL;
193 @ PDF viewer applications use following tables
(CIDFontType
2)
195 \.
{head
, hhea
, loca
, maxp
, glyf
, hmtx
, fpgm
, cvt\_
, prep
}
197 \rightline
{from PDF Ref. v
.1.3, 2nd ed.
}
199 The \.
{fpgm
}, \.
{cvt\_
} and \.
{prep
} tables appears only when TrueType instructions
200 requires them. Those tables must be preserved if they exist.
201 We use |must_exist| flag to indicate `preserve it if present'
202 and to make sure not to cause an error when it does not exist.
204 \.
{post
} and \.
{name
} table must exist in ordinary TrueType font file
,
205 but when a TrueType font is converted to CIDFontType
2 font
, those tables
206 are no longer required.
208 The OS
/2 table
(required for TrueType font for Windows and OS
/2) contains
209 liscencing information
, but PDF viewers seems not using them.
211 The \.
{name
} table added. See comments in \.
{writettf.w
}.
217 } required_table
[] = {
235 unsigned long ttc_read_offset
(sfnt
* sfont
, int ttc_idx
, fd_entry
* fd
)
238 unsigned long offset
= 0;
239 unsigned long num_dirs
= 0;
241 sfnt_seek_set
(sfont
, 4); /* skip version tag
*/
243 /*version
= */(void
)sfnt_get_ulong
(sfont
);
244 num_dirs
= sfnt_get_ulong
(sfont
);
245 if
(ttc_idx
< 0 || ttc_idx
> (int
) (num_dirs
- 1)) {
246 formatted_error
("type 2","invalid TTC index number %i (0..%i), using index 0 for font %s",
247 ttc_idx
,(int
) (num_dirs
- 1),(fd-
>fm-
>ps_name ? fd-
>fm-
>ps_name
: ""));
250 sfnt_seek_set
(sfont
, 12 + ttc_idx
* 4);
251 offset
= sfnt_get_ulong
(sfont
);
256 @ Creating the subset.
259 boolean make_tt_subset
(PDF pdf
, fd_entry
* fd
, unsigned char
*buff
, int buflen
)
263 unsigned int last_cid
= 0;
265 struct avl_traverser t
;
266 unsigned char
*cidtogidmap
;
267 unsigned short num_glyphs
, gid
;
268 struct tt_glyphs
*glyphs
;
269 char
*used_chars
= NULL;
276 sfont
= sfnt_open
(buff
, buflen
);
278 if
(sfont-
>type
== SFNT_TYPE_TTC
) {
279 i
= ff_get_ttc_index
(fd-
>fm-
>ff_name
, fd-
>fm-
>ps_name
);
280 error
= sfnt_read_table_directory
(sfont
, ttc_read_offset
(sfont
, (int
) i
, fd
));
282 error
= sfnt_read_table_directory
(sfont
, 0);
286 normal_error
("type 2","parsing the TTF directory fails");
289 if
(sfont-
>type
== SFNT_TYPE_TTC
&& sfnt_find_table_pos(sfont, "CFF ")) {
294 if
(is_subsetted
(fd-
>fm
)) {
295 /* rebuild the glyph tables and create a fresh cidmap
*/
296 glyphs
= tt_build_init
();
300 avl_t_init
(&t, fd->gl_tree);
301 for
(found
= (glw_entry
*) avl_t_first
(&t, fd->gl_tree);
302 found
!= NULL; found
= (glw_entry
*) avl_t_next
(&t)) {
303 if
(found-
>id
> last_cid
)
304 last_cid
= found-
>id
;
307 #ifndef NO_GHOSTSCRIPT_BUG
310 cidtogidmap
= xmalloc
(((last_cid
+ 1) * 2) * sizeof
(unsigned char
));
311 memset
(cidtogidmap
, 0, (last_cid
+ 1) * 2);
314 /* fill |used_chars|
*/
315 used_chars
= xmalloc
((last_cid
+ 1) * sizeof
(char
));
316 memset
(used_chars
, 0, (last_cid
+ 1));
317 avl_t_init
(&t, fd->gl_tree);
318 for
(found
= (glw_entry
*) avl_t_first
(&t, fd->gl_tree);
319 found
!= NULL; found
= (glw_entry
*) avl_t_next
(&t)) {
320 used_chars
[found-
>id
] = 1;
323 /* Map CIDs to GIDs.
*/
325 num_glyphs
= 1; /* \.
{.notdef
} */
326 for
(cid
= 1; cid
<= (long
) last_cid
; cid
++) {
327 if
(used_chars
[cid
] == 0)
329 gid
= (short unsigned
) cid
;
332 #ifndef NO_GHOSTSCRIPT_BUG
333 gid
= tt_add_glyph
(glyphs
, (USHORT
) gid
, (USHORT
) cid
);
335 gid
= tt_add_glyph
(glyphs
, (USHORT
) gid
, (USHORT
) num_glyphs
);
336 cidtogidmap
[2 * cid
] = gid
>> 8;
337 cidtogidmap
[2 * cid
+ 1] = gid
& 0xff;
338 #endif
/* |
!NO_GHOSTSCRIPT_BUG|
*/
343 if
(num_glyphs
== 1) {
344 normal_error
("type 2","there are no glyphs in the subset");
347 if
(tt_build_tables
(sfont
, glyphs
) < 0) {
348 normal_error
("type 2","the TTF buffer can't be parsed");
351 tt_build_finish
(glyphs
);
354 /* Create font file
*/
356 for
(i
= 0; required_table
[i
].name
; i
++) {
357 if
(sfnt_require_table
(sfont
,required_table
[i
].name
, required_table
[i
].must_exist
) < 0) {
358 normal_error
("type 2","some required TrueType table does not exist");
362 fontfile
= sfnt_create_FontFile_stream
(sfont
);
364 /* squeeze in the cidgidmap
*/
365 if
(cidtogidmap
!= NULL) {
366 cidtogid_obj
= (unsigned long
) pdf_create_obj
(pdf
, obj_type_others
, 0);
367 pdf_begin_obj
(pdf
, (int
) cidtogid_obj
, OBJSTM_NEVER
);
369 pdf_dict_add_int
(pdf
, "Length", ((last_cid
+ 1) * 2));
371 assert
(0); /* code unused
*/
372 pdf_begin_stream
(pdf
);
373 pdf_room
(pdf
, (int
) ((last_cid
+ 1) * 2));
374 for
(i
= 0; i
< ((int
) (last_cid
+ 1) * 2); i
++) {
375 pdf_quick_out
(pdf
, cidtogidmap
[i
]);
382 for
(i
= 0; i
< (int
) (fontfile-
>length
); i
++)
383 strbuf_putchar
(pdf-
>fb
, fontfile-
>data
[i
]);
385 pdf_release_obj
(fontfile
);
387 /* CIDSet
: a table of bits indexed by cid
, bytes with high order bit first
,
388 each
(set
) bit is a
(present
) CID.
*/
389 if
(is_subsetted
(fd-
>fm
)) {
390 cidset
= pdf_create_obj
(pdf
, obj_type_others
, 0);
392 size_t l
= (last_cid
/ 8) + 1;
393 char
*stream
= xmalloc
(l
);
394 memset
(stream
, 0, l
);
395 for
(cid
= 1; cid
<= (long
) last_cid
; cid
++) {
396 if
(used_chars
[cid
]) {
397 stream
[(cid
/ 8)] |
= (1 << (7 - (cid
% 8)));
400 pdf_begin_obj
(pdf
, cidset
, OBJSTM_NEVER
);
402 pdf_dict_add_streaminfo
(pdf
);
404 pdf_begin_stream
(pdf
);
405 pdf_out_block
(pdf
, stream
, l
);
411 /* TODO other stuff that needs fixing
: */
413 /* DW
, W
, DW2
, and W2
*/
415 if
(opt_flags
& CIDFONT_FORCE_FIXEDPITCH) {
416 pdf_add_dict
(font-
>fontdict
,
417 pdf_new_name
("DW"), pdf_new_number
(1000.0));
419 add_TTCIDHMetrics
(font-
>fontdict
, glyphs
, used_chars
, cidtogidmap
,
422 add_TTCIDVMetrics
(font-
>fontdict
, glyphs
, used_chars
, cidtogidmap
,