fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / font / writetype2.w
blob950af9998799821a7cf0546973988205c7295636
1 % writetype2.w
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/>.
20 @ @c
23 #include "ptexlib.h"
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"
31 @ forward declaration
33 boolean make_tt_subset(PDF pdf, fd_entry * fd, unsigned char *buff, int buflen);
35 @ @c
36 unsigned long cidtogid_obj = 0;
38 @ low-level helpers
40 #define test_loc(l) \
41 if ((f->loc + l) > f->buflen) { \
42 normal_error("type 2","the file ended prematurely"); \
45 BYTE get_unsigned_byte(sfnt * f)
47 test_loc(1);
48 return (BYTE) f->buffer[(f->loc++)];
51 ICHAR get_signed_byte(sfnt * f)
53 test_loc(1);
54 return (ICHAR) f->buffer[(f->loc++)];
57 USHORT get_unsigned_pair(sfnt * f)
59 USHORT l;
60 test_loc(2);
61 l = f->buffer[(f->loc++)];
62 l = (USHORT) (l * 0x100 + f->buffer[(f->loc++)]);
63 return l;
66 SHORT get_signed_pair(sfnt * f)
68 long l;
69 test_loc(2);
70 l = f->buffer[(f->loc++)];
71 if (l > 0x80)
72 l -= 0x100;
73 l = l * 0x100 + f->buffer[(f->loc++)];
74 return (SHORT) l;
77 ULONG get_unsigned_quad(sfnt * f)
79 ULONG l;
80 test_loc(4);
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++)];
85 return l;
88 int do_sfnt_read(unsigned char *dest, int len, sfnt * f)
90 int i;
91 test_loc(len);
92 for (i = 0; i < len; i++) {
93 *(dest + i) = f->buffer[f->loc + i];
95 f->loc += len;
96 return len;
99 pdf_obj *pdf_new_stream(void)
101 pdf_obj *stream = xmalloc(sizeof(pdf_obj));
102 stream->length = 0;
103 stream->data = NULL;
104 return stream;
107 void pdf_add_stream(pdf_obj * stream, unsigned char *buf, long len)
109 int i;
110 assert(stream != NULL);
111 if (stream->data == NULL) {
112 stream->data = xmalloc((unsigned) len);
113 } else {
114 stream->data =
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) {
127 xfree(stream->data);
129 xfree(stream);
133 @ The main function.
135 boolean writetype2(PDF pdf, fd_entry * fd)
137 int callback_id;
138 int file_opened = 0;
139 boolean ret;
141 glyph_tab = NULL;
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));
148 ttf_curbyte = 0;
149 ttf_size = 0;
150 cur_file_name =
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) {
160 } else {
161 formatted_error("type 2","cannot find file '%s'", cur_file_name);
163 } else {
164 if (!otf_open(cur_file_name)) {
165 formatted_error("type 2","cannot find file '%s'", cur_file_name);
167 ttf_read_file();
168 ttf_close();
171 fd_cur->ff_found = true;
173 if (is_subsetted(fd_cur->fm))
174 report_start_file(filetype_subset,cur_file_name);
175 else
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);
181 #if 0
182 xfree (dir_tab);
183 #endif
184 xfree(ttf_buffer);
185 if (is_subsetted(fd_cur->fm))
186 report_stop_file(filetype_subset);
187 else
188 report_stop_file(filetype_font);
189 cur_file_name = NULL;
190 return ret;
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}.
214 static struct {
215 const char *name;
216 int must_exist;
217 } required_table[] = {
219 "OS/2", 0}, {
220 "cmap", 0}, {
221 "head", 1}, {
222 "hhea", 1}, {
223 "loca", 1}, {
224 "maxp", 0}, {
225 "name", 1}, {
226 "glyf", 1}, {
227 "hmtx", 1}, {
228 "fpgm", 0}, {
229 "cvt ", 0}, {
230 "prep", 0}, {
231 NULL, 0}
235 unsigned long ttc_read_offset(sfnt * sfont, int ttc_idx, fd_entry * fd)
237 /*ULONG version;*/
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 : ""));
248 return 0 ;
250 sfnt_seek_set(sfont, 12 + ttc_idx * 4);
251 offset = sfnt_get_ulong(sfont);
253 return offset;
256 @ Creating the subset.
258 extern int cidset;
259 boolean make_tt_subset(PDF pdf, fd_entry * fd, unsigned char *buff, int buflen)
262 long i, cid;
263 unsigned int last_cid = 0;
264 glw_entry *found;
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;
270 sfnt *sfont;
271 pdf_obj *fontfile;
272 int error = 0;
274 cidtogidmap = 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));
281 } else {
282 error = sfnt_read_table_directory(sfont, 0);
285 if (error < 0) {
286 normal_error("type 2","parsing the TTF directory fails");
289 if (sfont->type == SFNT_TYPE_TTC && sfnt_find_table_pos(sfont, "CFF ")) {
290 sfnt_close(sfont);
291 return false;
294 if (is_subsetted(fd->fm)) {
295 /* rebuild the glyph tables and create a fresh cidmap */
296 glyphs = tt_build_init();
298 last_cid = 0;
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
308 cidtogidmap = NULL;
309 #else
310 cidtogidmap = xmalloc(((last_cid + 1) * 2) * sizeof(unsigned char));
311 memset(cidtogidmap, 0, (last_cid + 1) * 2);
312 #endif
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)
328 continue;
329 gid = (short unsigned) cid;
332 #ifndef NO_GHOSTSCRIPT_BUG
333 gid = tt_add_glyph(glyphs, (USHORT) gid, (USHORT) cid);
334 #else
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| */
340 num_glyphs++;
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);
368 pdf_begin_dict(pdf);
369 pdf_dict_add_int(pdf, "Length", ((last_cid + 1) * 2));
370 pdf_end_dict(pdf);
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]);
377 pdf_end_stream(pdf);
378 pdf_end_obj(pdf);
381 /* the tff subset */
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);
391 if (cidset != 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);
401 pdf_begin_dict(pdf);
402 pdf_dict_add_streaminfo(pdf);
403 pdf_end_dict(pdf);
404 pdf_begin_stream(pdf);
405 pdf_out_block(pdf, stream, l);
406 pdf_end_stream(pdf);
407 pdf_end_obj(pdf);
411 /* TODO other stuff that needs fixing: */
413 /* DW, W, DW2, and W2 */
414 #if 0
415 if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
416 pdf_add_dict(font->fontdict,
417 pdf_new_name("DW"), pdf_new_number(1000.0));
418 } else {
419 add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap,
420 last_cid);
421 if (v_used_chars)
422 add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap,
423 last_cid);
425 #endif
427 xfree(used_chars);
428 sfnt_close(sfont);
429 return true;