1 /*
2 Copyright 1996-2014 Han The Thanh, <thanh@pdftex.org>
3
4 This file is part of pdfTeX.
5
6 pdfTeX is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 pdfTeX is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "ptexlib.h"
21 #include "writettf.h"
22 #include <string.h>
23
24 #define DEFAULT_NTABS 14
25 #define NEW_CMAP_SIZE 2
26
27 #define ttf_putchar fb_putchar
28 #define ttf_offset fb_offset
29 #define ttf_seek_outbuf fb_seek
30
31 #define INFILE ttf_file
32
33 #define ttf_open() \
34 open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
35 #define ttf_close() xfclose(ttf_file, cur_file_name)
36 #define ttf_getchar() xgetc(ttf_file)
37 #define ttf_eof() feof(ttf_file)
38
39 typedef struct {
40 TTF_LONG offset;
41 TTF_LONG newoffset;
42 TTF_UFWORD advWidth;
43 TTF_FWORD lsb;
44 const char *name; /* name of glyph */
45 TTF_SHORT newindex; /* new index of glyph in output file */
46 TTF_USHORT name_index; /* index of name as read from font file */
47 } glyph_entry;
48
49 typedef struct {
50 const char *name; /* name of glyph */
51 long code; /* charcode in case of subfonts */
52 long newindex; /* new index of glyph in output file */
53 } ttfenc_entry;
54
55 typedef struct {
56 TTF_USHORT platform_id;
57 TTF_USHORT encoding_id;
58 TTF_USHORT language_id;
59 TTF_USHORT name_id;
60 TTF_USHORT length;
61 TTF_USHORT offset;
62 TTF_USHORT new_offset;
63 TTF_USHORT new_length;
64 } name_record;
65
66 typedef struct {
67 char *ttf_name;
68 TTF_USHORT pid;
69 TTF_USHORT eid;
70 long *table;
71 } ttf_cmap_entry;
72
73 static TTF_USHORT ntabs;
74 static TTF_USHORT upem;
75 static TTF_FIXED post_format;
76 static TTF_SHORT loca_format;
77 static TTF_ULONG last_glyf_offset;
78 static TTF_USHORT glyphs_count;
79 static TTF_USHORT new_glyphs_count;
80 static TTF_USHORT nhmtxs;
81 static TTF_USHORT new_ntabs;
82
83 static glyph_entry *glyph_tab;
84 static long *glyph_index;
85 static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
86 static name_record *name_tab;
87 static int name_record_num;
88 static char *name_buf;
89 static int name_buf_size;
90 static dirtab_entry *dir_tab;
91 static char *glyph_name_buf;
92 static TTF_ULONG checksum;
93 static TTF_ULONG tab_length;
94 static TTF_ULONG tmp_ulong;
95 static TTF_ULONG checkSumAdjustment_offset;
96 static FILE *ttf_file;
97 static ttfenc_entry ttfenc_tab[256];
98
99 static fd_entry *fd_cur; /* pointer to the current font descriptor */
100
101 static struct avl_table *ttf_cmap_tree = NULL;
102
103 integer ttf_length;
104
105 #include "macnames.c"
106
107 static const char *newtabnames[] = {
108 "OS/2",
109 "PCLT",
110 "cmap",
111 "cvt ",
112 "fpgm",
113 "glyf",
114 "head",
115 "hhea",
116 "hmtx",
117 "loca",
118 "maxp",
119 "name",
120 "post",
121 "prep"
122 };
123
new_ttf_cmap_entry(void)124 static ttf_cmap_entry *new_ttf_cmap_entry(void)
125 {
126 ttf_cmap_entry *e;
127 e = xtalloc(1, ttf_cmap_entry);
128 e->ttf_name = NULL;
129 e->table = NULL;
130 return e;
131 }
132
destroy_ttf_cmap_entry(void * pa,void * pb)133 static void destroy_ttf_cmap_entry(void *pa, void *pb)
134 {
135 ttf_cmap_entry *p;
136 p = (ttf_cmap_entry *) pa;
137 xfree(p->ttf_name);
138 xfree(p->table);
139 xfree(p);
140 }
141
ttf_free(void)142 void ttf_free(void)
143 {
144 if (ttf_cmap_tree != NULL)
145 avl_destroy(ttf_cmap_tree, destroy_ttf_cmap_entry);
146 }
147
comp_ttf_cmap_entry(const void * pa,const void * pb,void * p)148 static int comp_ttf_cmap_entry(const void *pa, const void *pb, void *p)
149 {
150 const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa,
151 *p2 = (const ttf_cmap_entry *) pb;
152 int i;
153 assert(p1->ttf_name != NULL && p2->ttf_name != NULL);
154 if ((i = strcmp(p1->ttf_name, p2->ttf_name)) != 0)
155 return i;
156 cmp_return(p1->pid, p2->pid);
157 cmp_return(p1->eid, p2->eid);
158 return 0;
159 }
160
ttf_addchksm(unsigned char b)161 static unsigned char ttf_addchksm(unsigned char b)
162 {
163 tmp_ulong = (tmp_ulong << 8) + b;
164 tab_length++;
165 if (tab_length % 4 == 0) {
166 checksum += tmp_ulong;
167 tmp_ulong = 0;
168 }
169 return b;
170 }
171
ttf_getchksm(void)172 static TTF_ULONG ttf_getchksm(void)
173 {
174 while (tab_length % 4 != 0)
175 ttf_putchar(ttf_addchksm(0)); /* ttf_addchksm updates tab_length */
176 return checksum;
177 }
178
ttf_putnum(int s,long n)179 static long ttf_putnum(int s, long n)
180 {
181 long i = n;
182 char buf[TTF_LONG_SIZE + 1], *p = buf;
183 while (s-- > 0) {
184 *p++ = i & 0xFF;
185 i >>= 8;
186 }
187 p--;
188 while (p >= buf)
189 ttf_putchar(ttf_addchksm(*p--));
190 return n;
191 }
192
ttf_getnum(int s)193 static long ttf_getnum(int s)
194 {
195 long i = 0;
196 int c;
197 while (s > 0) {
198 if ((c = ttf_getchar()) < 0)
199 pdftex_fail("unexpected EOF");
200 i = (i << 8) + c;
201 s--;
202 }
203 return i;
204 }
205
ttf_funit(long n)206 static long ttf_funit(long n)
207 {
208 if (n < 0)
209 return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem);
210 else
211 return (n / upem) * 1000 + ((n % upem) * 1000) / upem;
212 }
213
ttf_ncopy(int n)214 static void ttf_ncopy(int n)
215 {
216 while (n-- > 0)
217 copy_byte();
218 }
219
ttf_name_lookup(const char * s,boolean required)220 static dirtab_entry *ttf_name_lookup(const char *s, boolean required)
221 {
222 dirtab_entry *tab;
223 for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
224 if (strncmp(tab->tag, s, 4) == 0)
225 break;
226 if (tab - dir_tab == ntabs) {
227 if (required)
228 pdftex_fail("can't find table `%s'", s);
229 else
230 tab = NULL;
231 }
232 return tab;
233 }
234
ttf_seek_tab(const char * name,TTF_LONG offset)235 static dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
236 {
237 dirtab_entry *tab = ttf_name_lookup(name, true);
238 xfseek(INFILE, tab->offset + offset, SEEK_SET, cur_file_name);
239 return tab;
240 }
241
ttf_seek_off(TTF_LONG offset)242 static void ttf_seek_off(TTF_LONG offset)
243 {
244 xfseek(INFILE, offset, SEEK_SET, cur_file_name);
245 }
246
ttf_copy_encoding(void)247 static void ttf_copy_encoding(void)
248 {
249 int i, *q;
250 void **aa;
251 char **glyph_names;
252 long *charcodes;
253 static char buf[SMALL_BUF_SIZE];
254 struct avl_traverser t;
255 ttfenc_entry *e = ttfenc_tab;
256
257 assert(fd_cur->tx_tree != NULL); /* this must be set in create_fontdictionary */
258
259 if (fd_cur->fe != NULL) {
260 glyph_names = fd_cur->fe->glyph_names;
261 assert(glyph_names != NULL);
262
263 for (i = 0; i < 256; i++)
264 ttfenc_tab[i].name = notdef;
265
266 /* a workaround for a bug of AcroReader 4.0 */
267 if (strcmp(glyph_names[97], "a") == 0) {
268 q = xtalloc(1, int);
269 *q = 'a';
270 aa = avl_probe(fd_cur->tx_tree, q);
271 assert(aa != NULL);
272 }
273 /* end of workaround */
274
275 /* take over collected characters from TeX, reencode them */
276 avl_t_init(&t, fd_cur->tx_tree);
277 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
278 q = (int *) avl_t_next(&t)) {
279 assert(*q >= 0 && *q < 256);
280 ttfenc_tab[*q].name = glyph_names[*q];
281 }
282 make_subset_tag(fd_cur);
283 } else if (is_subfont(fd_cur->fm)) {
284 charcodes = fd_cur->fm->subfont->charcodes;
285 assert(charcodes != NULL);
286
287 for (i = 0; i < 256; i++)
288 ttfenc_tab[i].code = -1;
289
290 /* take over collected characters from TeX */
291 avl_t_init(&t, fd_cur->tx_tree);
292 for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
293 q = (int *) avl_t_next(&t)) {
294 assert(*q >= 0 && *q < 256);
295 e = ttfenc_tab + *q;
296 e->code = charcodes[*q];
297 if (e->code == -1)
298 pdftex_warn
299 ("character %i in subfont %s is not mapped to any charcode",
300 *q, fd_cur->fm->tfm_name);
301 else {
302 assert(e->code < 0x10000);
303 sprintf(buf, "/c%4.4X", (int) e->code);
304 aa = avl_probe(fd_cur->gl_tree, xstrdup(buf));
305 assert(aa != NULL);
306 }
307 }
308 make_subset_tag(fd_cur);
309 } else
310 assert(0);
311 }
312
313 #define ttf_append_byte(B)\
314 do {\
315 if (name_tab[i].platform_id == 3)\
316 *q++ = 0;\
317 *q++ = B;\
318 } while (0)
319
strip_spaces_and_delims(char * s,int l)320 static char *strip_spaces_and_delims(char *s, int l)
321 {
322 static char buf[SMALL_BUF_SIZE];
323 char *p = buf;
324 int i;
325
326 assert(l >= 0 && l < (int) sizeof(buf));
327
328 for (i = 0; i < l; s++, i++) {
329 if (*s == '(' || *s == ')' || *s == '<' || *s == '>' ||
330 *s == '[' || *s == ']' || *s == '{' || *s == '}' ||
331 *s == '/' || *s == '%' || isspace((unsigned char)*s))
332 continue;
333 *p++ = *s;
334 }
335 *p = 0;
336 return buf;
337 }
338
ttf_read_name(void)339 static void ttf_read_name(void)
340 {
341 int i, j;
342 dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
343 char *p, buf[SMALL_BUF_SIZE];
344 name_record_num = get_ushort();
345 name_tab = xtalloc(name_record_num, name_record);
346 name_buf_size = tab->length -
347 (3 * TTF_USHORT_SIZE + name_record_num * 6 * TTF_USHORT_SIZE);
348 name_buf = xtalloc(name_buf_size, char);
349 ttf_skip(TTF_USHORT_SIZE);
350 for (i = 0; i < name_record_num; i++) {
351 name_tab[i].platform_id = get_ushort();
352 name_tab[i].encoding_id = get_ushort();
353 name_tab[i].language_id = get_ushort();
354 name_tab[i].name_id = get_ushort();
355 name_tab[i].length = get_ushort();
356 name_tab[i].offset = get_ushort();
357 }
358 for (p = name_buf; p - name_buf < name_buf_size; p++)
359 *p = get_char();
360 /* look for PS font name */
361 for (i = 0; i < name_record_num; i++) {
362 if (name_tab[i].platform_id == 1 &&
363 name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) {
364 xfree(fd_cur->fontname);
365 fd_cur->fontname =
366 xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset,
367 name_tab[i].length));
368 fd_cur->font_dim[FONTNAME_CODE].set = true;
369 break;
370 }
371 }
372 if (!fd_cur->font_dim[FONTNAME_CODE].set) {
373 for (i = 0; i < name_record_num; i++) {
374 if (name_tab[i].platform_id == 3 &&
375 (name_tab[i].encoding_id == 0 || name_tab[i].encoding_id == 1) &&
376 name_tab[i].name_id == 6) {
377 xfree(fd_cur->fontname);
378 assert(name_tab[i].length < sizeof(buf));
379 for (j = 0, p = buf; j < name_tab[i].length; j += 2)
380 *p++ = name_buf[name_tab[i].offset + j + 1];
381 *p = 0;
382 fd_cur->fontname = xstrdup(strip_spaces_and_delims(buf, strlen(buf)));
383 fd_cur->font_dim[FONTNAME_CODE].set = true;
384 break;
385 }
386 }
387 }
388 }
389
ttf_read_mapx(void)390 static void ttf_read_mapx(void)
391 {
392 glyph_entry *glyph;
393 ttf_seek_tab("maxp", TTF_FIXED_SIZE);
394 glyph_tab = xtalloc(1 + (glyphs_count = get_ushort()), glyph_entry);
395 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
396 glyph->newindex = -1;
397 glyph->newoffset = 0;
398 glyph->name_index = 0;
399 glyph->name = notdef;
400 }
401 glyph_index = xtalloc(glyphs_count + 1, long);
402 glyph_index[0] = 0; /* index of ".notdef" glyph */
403 glyph_index[1] = 1; /* index of ".null" glyph */
404 }
405
ttf_read_head(void)406 static void ttf_read_head(void)
407 {
408 ttf_seek_tab("head",
409 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
410 upem = get_ushort();
411 ttf_skip(16);
412 fd_cur->font_dim[FONTBBOX1_CODE].val = ttf_funit(get_fword());
413 fd_cur->font_dim[FONTBBOX2_CODE].val = ttf_funit(get_fword());
414 fd_cur->font_dim[FONTBBOX3_CODE].val = ttf_funit(get_fword());
415 fd_cur->font_dim[FONTBBOX4_CODE].val = ttf_funit(get_fword());
416 fd_cur->font_dim[FONTBBOX1_CODE].set = true;
417 fd_cur->font_dim[FONTBBOX2_CODE].set = true;
418 fd_cur->font_dim[FONTBBOX3_CODE].set = true;
419 fd_cur->font_dim[FONTBBOX4_CODE].set = true;
420 ttf_skip(2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
421 loca_format = get_short();
422 }
423
ttf_read_hhea(void)424 static void ttf_read_hhea(void)
425 {
426 ttf_seek_tab("hhea", TTF_FIXED_SIZE);
427 fd_cur->font_dim[ASCENT_CODE].val = ttf_funit(get_fword());
428 fd_cur->font_dim[DESCENT_CODE].val = ttf_funit(get_fword());
429 fd_cur->font_dim[ASCENT_CODE].set = true;
430 fd_cur->font_dim[DESCENT_CODE].set = true;
431 ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
432 8 * TTF_SHORT_SIZE);
433 nhmtxs = get_ushort();
434 }
435
ttf_read_pclt(void)436 static void ttf_read_pclt(void)
437 {
438 if (ttf_name_lookup("PCLT", false) == NULL)
439 return;
440 ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
441 fd_cur->font_dim[XHEIGHT_CODE].val = ttf_funit(get_ushort());
442 ttf_skip(2 * TTF_USHORT_SIZE);
443 fd_cur->font_dim[CAPHEIGHT_CODE].val = ttf_funit(get_ushort());
444 fd_cur->font_dim[XHEIGHT_CODE].set = true;
445 fd_cur->font_dim[CAPHEIGHT_CODE].set = true;
446 }
447
ttf_read_hmtx(void)448 static void ttf_read_hmtx(void)
449 {
450 glyph_entry *glyph;
451 TTF_UFWORD last_advWidth;
452 ttf_seek_tab("hmtx", 0);
453 for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
454 glyph->advWidth = get_ufword();
455 glyph->lsb = get_ufword();
456 }
457 if (nhmtxs < glyphs_count) {
458 last_advWidth = glyph[-1].advWidth;
459 for (; glyph - glyph_tab < glyphs_count; glyph++) {
460 glyph->advWidth = last_advWidth;
461 glyph->lsb = get_ufword();
462 }
463 }
464 }
465
ttf_read_post(void)466 static void ttf_read_post(void)
467 {
468 int k, nnames;
469 long length;
470 long int_part, frac_part;
471 int sign = 1;
472 TTF_FIXED italic_angle;
473 char *p;
474 glyph_entry *glyph;
475 const dirtab_entry *tab = ttf_seek_tab("post", 0);
476 post_format = get_fixed();
477 italic_angle = get_fixed();
478 int_part = italic_angle >> 16;
479 if (int_part > 0x7FFF) { /* a negative number */
480 int_part = 0x10000 - int_part;
481 sign = -1;
482 }
483 frac_part = italic_angle % 0x10000;
484 fd_cur->font_dim[ITALIC_ANGLE_CODE].val =
485 sign * (int_part + frac_part * 1.0 / 0x10000);
486 fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
487 if (glyph_tab == NULL)
488 return; /* being called from writeotf() */
489 ttf_skip(2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
490 switch (post_format) {
491 case 0x10000:
492 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
493 glyph->name = mac_glyph_names[glyph - glyph_tab];
494 glyph->name_index = glyph - glyph_tab;
495 }
496 break;
497 case 0x20000:
498 nnames = get_ushort(); /* some fonts have this value different from nglyphs */
499 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
500 glyph->name_index = get_ushort();
501 length = tab->length - (xftell(INFILE, cur_file_name) - tab->offset);
502 glyph_name_buf = xtalloc(length, char);
503 for (p = glyph_name_buf; p - glyph_name_buf < length;) {
504 for (k = get_byte(); k > 0; k--)
505 *p++ = get_char();
506 *p++ = 0;
507 }
508 for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
509 if (glyph->name_index < NMACGLYPHS)
510 glyph->name = mac_glyph_names[glyph->name_index];
511 else {
512 p = glyph_name_buf;
513 k = glyph->name_index - NMACGLYPHS;
514 for (; k > 0; k--)
515 p = strend(p) + 1;
516 glyph->name = p;
517 }
518 }
519 break;
520 default:
521 pdftex_warn("unsupported format (%.8X) of `post' table, assuming 3.0",
522 (unsigned int) post_format);
523 case 0x00030000:
524 for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
525 glyph->name_index = glyph - glyph_tab;
526 }
527 }
528 }
529
ttf_read_loca(void)530 static void ttf_read_loca(void)
531 {
532 glyph_entry *glyph;
533 ttf_seek_tab("loca", 0);
534 if (loca_format != 0)
535 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
536 glyph->offset = get_ulong();
537 else
538 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
539 glyph->offset = get_ushort() << 1;
540 }
541
ttf_read_tabdir(void)542 static void ttf_read_tabdir(void)
543 {
544 int i;
545 dirtab_entry *tab;
546 ttf_skip(TTF_FIXED_SIZE); /* ignore the sfnt number */
547 dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
548 ttf_skip(3 * TTF_USHORT_SIZE);
549 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
550 for (i = 0; i < 4; i++)
551 tab->tag[i] = get_char();
552 tab->checksum = get_ulong();
553 tab->offset = get_ulong();
554 tab->length = get_ulong();
555 }
556 }
557
ttf_read_cmap(char * ttf_name,int pid,int eid,boolean warn)558 static ttf_cmap_entry *ttf_read_cmap(char *ttf_name, int pid, int eid,
559 boolean warn)
560 {
561 seg_entry *seg_tab, *s;
562 TTF_USHORT *glyphId, format, segCount;
563 TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid;
564 TTF_ULONG cmap_offset, tmp_offset;
565 long n, i, k, length, index;
566 ttf_cmap_entry tmp_e, *p;
567 void **aa;
568
569 /* loop up in ttf_cmap_tree first, return if found */
570 tmp_e.ttf_name = ttf_name;
571 tmp_e.pid = pid;
572 tmp_e.eid = eid;
573 if (ttf_cmap_tree == NULL) {
574 ttf_cmap_tree = avl_create(comp_ttf_cmap_entry, NULL, &avl_xallocator);
575 assert(ttf_cmap_tree != NULL);
576 }
577 p = (ttf_cmap_entry *) avl_find(ttf_cmap_tree, &tmp_e);
578 if (p != NULL)
579 return p;
580
581 /* not found, have to read it */
582 ttf_seek_tab("cmap", TTF_USHORT_SIZE); /* skip the table version number (=0) */
583 ncmapsubtabs = get_ushort();
584 cmap_offset = xftell(INFILE, cur_file_name) - 2 * TTF_USHORT_SIZE;
585 cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
586 for (i = 0; i < ncmapsubtabs; ++i) {
587 tmp_pid = get_ushort();
588 tmp_eid = get_ushort();
589 tmp_offset = get_ulong();
590 if (tmp_pid == pid && tmp_eid == eid) {
591 ttf_seek_off(cmap_offset + tmp_offset);
592 format = get_ushort();
593 if (format == 4)
594 goto read_cmap_format_4;
595 else {
596 if (warn)
597 pdftex_warn("cmap format %i unsupported", format);
598 return NULL;
599 }
600 }
601 }
602 if (warn)
603 pdftex_warn("cannot find cmap subtable for (pid,eid) = (%i, %i)",
604 pid, eid);
605 return NULL;
606 read_cmap_format_4:
607 /* initialize the new entry */
608 p = new_ttf_cmap_entry();
609 p->ttf_name = xstrdup(ttf_name);
610 p->pid = pid;
611 p->eid = eid;
612 p->table = xtalloc(0x10000, long);
613 for (i = 0; i < 0x10000; ++i)
614 p->table[i] = -1; /* unassigned yet */
615
616 /* read the subtable */
617 length = get_ushort(); /* length of subtable */
618 (void) get_ushort(); /* skip the version number */
619 segCount = get_ushort() / 2;
620 (void) get_ushort(); /* skip searchRange */
621 (void) get_ushort(); /* skip entrySelector */
622 (void) get_ushort(); /* skip rangeShift */
623 seg_tab = xtalloc(segCount, seg_entry);
624 for (s = seg_tab; s - seg_tab < segCount; s++)
625 s->endCode = get_ushort();
626 (void) get_ushort(); /* skip reversedPad */
627 for (s = seg_tab; s - seg_tab < segCount; s++)
628 s->startCode = get_ushort();
629 for (s = seg_tab; s - seg_tab < segCount; s++)
630 s->idDelta = get_ushort();
631 for (s = seg_tab; s - seg_tab < segCount; s++)
632 s->idRangeOffset = get_ushort();
633 length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
634 n = length / TTF_USHORT_SIZE; /* number of glyphID's */
635 glyphId = xtalloc(n, TTF_USHORT);
636 for (i = 0; i < n; i++)
637 glyphId[i] = get_ushort();
638 for (s = seg_tab; s - seg_tab < segCount; s++) {
639 for (i = s->startCode; i <= s->endCode; i++) {
640 if (i == 0xFFFF)
641 break;
642 if (s->idRangeOffset != 0xFFFF) {
643 if (s->idRangeOffset == 0)
644 index = (s->idDelta + i) & 0xFFFF;
645 else {
646 k = (i - s->startCode) + s->idRangeOffset / 2 +
647 (s - seg_tab) - segCount;
648 assert(k >= 0 && k < n);
649 index = glyphId[k];
650 if (index != 0)
651 index = (index + s->idDelta) & 0xFFFF;
652 }
653 if (index >= glyphs_count)
654 pdftex_fail("cmap: glyph index %li out of range [0..%i)",
655 index, glyphs_count);
656 if (p->table[i] != -1)
657 pdftex_warn
658 ("cmap: multiple glyphs are mapped to unicode %.4lX, "
659 "only %li will be used (glyph %li being ignored)", i,
660 p->table[i], index);
661 else
662 p->table[i] = index;
663 }
664 }
665 }
666 xfree(seg_tab);
667 xfree(glyphId);
668 aa = avl_probe(ttf_cmap_tree, p);
669 assert(aa != NULL);
670 return p;
671 }
672
ttf_read_font(void)673 static void ttf_read_font(void)
674 {
675 ttf_read_tabdir();
676 if (ttf_name_lookup("PCLT", false) == NULL)
677 new_ntabs--;
678 if (ttf_name_lookup("fpgm", false) == NULL)
679 new_ntabs--;
680 if (ttf_name_lookup("cvt ", false) == NULL)
681 new_ntabs--;
682 if (ttf_name_lookup("prep", false) == NULL)
683 new_ntabs--;
684 ttf_read_mapx();
685 ttf_read_head();
686 ttf_read_hhea();
687 ttf_read_pclt();
688 ttf_read_hmtx();
689 ttf_read_post();
690 ttf_read_loca();
691 ttf_read_name();
692 }
693
ttf_reset_chksm(dirtab_entry * tab)694 static void ttf_reset_chksm(dirtab_entry * tab)
695 {
696 checksum = 0;
697 tab_length = 0;
698 tmp_ulong = 0;
699 tab->offset = ttf_offset();
700 if (tab->offset % 4 != 0)
701 pdftex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag);
702 }
703
704
ttf_set_chksm(dirtab_entry * tab)705 static void ttf_set_chksm(dirtab_entry * tab)
706 {
707 tab->length = ttf_offset() - tab->offset;
708 tab->checksum = ttf_getchksm();
709 }
710
ttf_copytab(const char * name)711 static void ttf_copytab(const char *name)
712 {
713 long i;
714 dirtab_entry *tab = ttf_seek_tab(name, 0);
715 ttf_reset_chksm(tab);
716 for (i = tab->length; i > 0; i--)
717 copy_char();
718 ttf_set_chksm(tab);
719 }
720
721 #define BYTE_ENCODING_LENGTH \
722 ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
723
ttf_byte_encoding(void)724 static void ttf_byte_encoding(void)
725 {
726 ttfenc_entry *e;
727 (void) put_ushort(0); /* format number (0: byte encoding table) */
728 (void) put_ushort(BYTE_ENCODING_LENGTH); /* length of table */
729 (void) put_ushort(0); /* version number */
730 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
731 if (e->newindex < 256) {
732 put_byte(e->newindex);
733 } else {
734 if (e->name != notdef)
735 pdftex_warn
736 ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
737 e->name, notdef);
738 put_byte(0); /* notdef */
739 }
740 }
741
742 #define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256)))
743
ttf_trimmed_table_map(void)744 static void ttf_trimmed_table_map(void)
745 {
746 ttfenc_entry *e;
747 (void) put_ushort(6); /* format number (6): trimmed table mapping */
748 (void) put_ushort(TRIMMED_TABLE_MAP_LENGTH);
749 (void) put_ushort(0); /* version number (0) */
750 (void) put_ushort(0); /* first character code */
751 (void) put_ushort(256); /* number of character code in table */
752 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
753 (void) put_ushort(e->newindex);
754 }
755
756 #define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE)
757
ttf_seg_map_delta(void)758 static void ttf_seg_map_delta(void)
759 {
760 ttfenc_entry *e;
761 (void) put_ushort(4); /* format number (4: segment mapping to delta values) */
762 (void) put_ushort(SEG_MAP_DELTA_LENGTH);
763 (void) put_ushort(0); /* version number */
764 (void) put_ushort(4); /* 2*segCount */
765 (void) put_ushort(4); /* searchRange */
766 (void) put_ushort(1); /* entrySelector */
767 (void) put_ushort(0); /* rangeShift */
768 (void) put_ushort(0xF0FF); /* endCount[0] */
769 (void) put_ushort(0xFFFF); /* endCount[1] */
770 (void) put_ushort(0); /* reversedPad */
771 (void) put_ushort(0xF000); /* startCount[0] */
772 (void) put_ushort(0xFFFF); /* startCount[1] */
773 (void) put_ushort(0); /* idDelta[0] */
774 (void) put_ushort(1); /* idDelta[1] */
775 (void) put_ushort(2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */
776 (void) put_ushort(0); /* idRangeOffset[1] */
777 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
778 (void) put_ushort(e->newindex);
779 }
780
781 #define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
782
ttf_select_cmap(void)783 static void ttf_select_cmap(void)
784 {
785 assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE * sizeof(cmap_entry));
786 new_cmap_tab[0].platform_id = 1; /* Macintosh */
787 new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */
788 new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */
789 : 6; /* trimmed table mapping */
790 new_cmap_tab[1].platform_id = 3; /* Microsoft */
791 new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */
792 new_cmap_tab[1].format = 4; /* segment mapping to delta */
793 }
794
ttf_write_cmap(void)795 static void ttf_write_cmap(void)
796 {
797 cmap_entry *ce;
798 long offset;
799 dirtab_entry *tab = ttf_name_lookup("cmap", true);
800 ttf_select_cmap();
801 ttf_reset_chksm(tab);
802 (void) put_ushort(0); /* table version number (0) */
803 (void) put_ushort(NEW_CMAP_SIZE); /* number of encoding tables */
804 offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH;
805 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
806 ce->offset = offset;
807 switch (ce->format) {
808 case 0:
809 offset += BYTE_ENCODING_LENGTH;
810 break;
811 case 4:
812 offset += SEG_MAP_DELTA_LENGTH;
813 break;
814 case 6:
815 offset += TRIMMED_TABLE_MAP_LENGTH;
816 break;
817 default:
818 pdftex_fail("invalid format (it should not have happened)");
819 }
820 (void) put_ushort(ce->platform_id);
821 (void) put_ushort(ce->encoding_id);
822 put_ulong(ce->offset);
823 }
824 for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
825 switch (ce->format) {
826 case 0:
827 ttf_byte_encoding();
828 break;
829 case 4:
830 ttf_seg_map_delta();
831 break;
832 case 6:
833 ttf_trimmed_table_map();
834 break;
835 }
836 }
837 ttf_set_chksm(tab);
838 }
839
prepend_subset_tags(int index,char * p)840 static int prepend_subset_tags(int index, char *p)
841 {
842 boolean is_unicode;
843 int i;
844 assert(index >= 0 && index < name_record_num && fd_cur->subset_tag != NULL);
845 is_unicode = (name_tab[index].platform_id == 3);
846 if (is_unicode) {
847 for (i = 0; i < 6; ++i) {
848 *p++ = 0;
849 *p++ = fd_cur->subset_tag[i];
850 }
851 *p++ = 0;
852 *p++ = '+';
853 return 14;
854 } else {
855 strncpy(p, fd_cur->subset_tag, 6);
856 p += 6;
857 *p++ = '+';
858 return 7;
859 }
860 }
861
862
ttf_write_name(void)863 static void ttf_write_name(void)
864 {
865 int i, l;
866 char *p;
867 int new_name_buf_size;
868 char *new_name_buf;
869 name_record *n;
870 dirtab_entry *tab = ttf_name_lookup("name", true);
871 if (is_subsetted(fd_cur->fm)) {
872 l = 0;
873 for (i = 0; i < name_record_num; i++)
874 l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
875 new_name_buf = xtalloc(l, char);
876 /* additional space for subset tags */
877 p = new_name_buf;
878 for (i = 0; i < name_record_num; i++) {
879 n = name_tab + i;
880 n->new_offset = p - new_name_buf;
881 if ((n->name_id == 1 || n->name_id == 3 ||
882 n->name_id == 4 || n->name_id == 6) &&
883 ((n->platform_id == 1 && n->encoding_id == 0) ||
884 (n->platform_id == 3 && n->encoding_id == 0) ||
885 (n->platform_id == 3 && n->encoding_id == 1))) {
886 l = prepend_subset_tags(i, p);
887 p += l;
888 } else
889 l = 0;
890 memcpy(p, name_buf + n->offset, n->length);
891 p += n->length;
892 n->new_length = n->length + l;
893 }
894 new_name_buf_size = p - new_name_buf;
895 } else {
896 new_name_buf = name_buf;
897 new_name_buf_size = name_buf_size;
898 }
899 ttf_reset_chksm(tab);
900 (void) put_ushort(0); /* Format selector */
901 (void) put_ushort(name_record_num);
902 (void) put_ushort(3 * TTF_USHORT_SIZE +
903 name_record_num * 6 * TTF_USHORT_SIZE);
904 for (i = 0; i < name_record_num; i++) {
905 (void) put_ushort(name_tab[i].platform_id);
906 (void) put_ushort(name_tab[i].encoding_id);
907 (void) put_ushort(name_tab[i].language_id);
908 (void) put_ushort(name_tab[i].name_id);
909 (void) put_ushort(name_tab[i].new_length);
910 (void) put_ushort(name_tab[i].new_offset);
911 }
912 for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
913 put_char(*p);
914 ttf_set_chksm(tab);
915 if (new_name_buf != name_buf)
916 xfree(new_name_buf);
917 }
918
ttf_write_dirtab(void)919 static void ttf_write_dirtab(void)
920 {
921 dirtab_entry *tab;
922 TTF_ULONG i, k;
923 char *p;
924 const integer save_offset = ttf_offset();
925 ttf_seek_outbuf(TABDIR_OFF);
926 if (is_subsetted(fd_cur->fm)) {
927 for (i = 0; i < DEFAULT_NTABS; i++) {
928 tab = ttf_name_lookup(newtabnames[i], false);
929 if (tab == NULL)
930 continue;
931 for (k = 0; k < 4; k++)
932 put_char(tab->tag[k]);
933 put_ulong(tab->checksum);
934 put_ulong(tab->offset);
935 put_ulong(tab->length);
936 }
937 } else {
938 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
939 for (k = 0; k < 4; k++)
940 put_char(tab->tag[k]);
941 put_ulong(tab->checksum);
942 put_ulong(tab->offset);
943 put_ulong(tab->length);
944 }
945 }
946 /* adjust checkSumAdjustment */
947 tmp_ulong = 0;
948 checksum = 0;
949 for (p = fb_array, i = 0; i < (unsigned) save_offset;) {
950 tmp_ulong = (tmp_ulong << 8) + *p++;
951 i++;
952 if (i % 4 == 0) {
953 checksum += tmp_ulong;
954 tmp_ulong = 0;
955 }
956 }
957 if (i % 4 != 0) {
958 pdftex_warn("font length is not a multiple of 4 (%li)", i);
959 checksum <<= 8 * (4 - i % 4);
960 }
961 k = 0xB1B0AFBA - checksum;
962 ttf_seek_outbuf(checkSumAdjustment_offset);
963 put_ulong(k);
964 ttf_seek_outbuf(save_offset);
965 }
966
ttf_write_glyf(void)967 static void ttf_write_glyf(void)
968 {
969 long *id, k;
970 TTF_USHORT idx;
971 TTF_USHORT flags;
972 dirtab_entry *tab = ttf_name_lookup("glyf", true);
973 const long glyf_offset = tab->offset;
974 const long new_glyf_offset = ttf_offset();
975 ttf_reset_chksm(tab);
976 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
977 glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset;
978 if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
979 ttf_seek_off(glyf_offset + glyph_tab[*id].offset);
980 k = copy_short();
981 ttf_ncopy(4 * TTF_FWORD_SIZE);
982 if (k < 0) {
983 do {
984 flags = copy_ushort();
985 idx = get_ushort();
986 if (glyph_tab[idx].newindex < 0) {
987 glyph_tab[idx].newindex = new_glyphs_count;
988 glyph_index[new_glyphs_count++] = idx;
989 /*
990 N.B.: Here we change `new_glyphs_count',
991 which appears in the condition of the `for' loop
992 */
993 }
994 (void) put_ushort(glyph_tab[idx].newindex);
995 if (flags & ARG_1_AND_2_ARE_WORDS)
996 ttf_ncopy(2 * TTF_SHORT_SIZE);
997 else
998 ttf_ncopy(TTF_USHORT_SIZE);
999 if (flags & WE_HAVE_A_SCALE)
1000 ttf_ncopy(TTF_F2DOT14_SIZE);
1001 else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
1002 ttf_ncopy(2 * TTF_F2DOT14_SIZE);
1003 else if (flags & WE_HAVE_A_TWO_BY_TWO)
1004 ttf_ncopy(4 * TTF_F2DOT14_SIZE);
1005 } while (flags & MORE_COMPONENTS);
1006 if (flags & WE_HAVE_INSTRUCTIONS)
1007 ttf_ncopy(copy_ushort());
1008 } else
1009 ttf_ncopy(glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
1010 TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE);
1011 }
1012 }
1013 last_glyf_offset = ttf_offset() - new_glyf_offset;
1014 ttf_set_chksm(tab);
1015 }
1016
ttf_reindex_glyphs(void)1017 static void ttf_reindex_glyphs(void)
1018 {
1019 ttfenc_entry *e;
1020 glyph_entry *glyph;
1021 int index;
1022 int n;
1023 long *t;
1024 ttf_cmap_entry *cmap = NULL;
1025 boolean cmap_not_found = false;
1026
1027 /*
1028 * reindexing glyphs: we append index of used glyphs to `glyph_index'
1029 * while going through `ttfenc_tab'. After appending a new entry to
1030 * `glyph_index' we set field `newindex' of corresponding entries in both
1031 * `glyph_tab' and `ttfenc_tab' to the newly created index
1032 */
1033 for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) {
1034 e->newindex = 0; /* index of ".notdef" glyph */
1035
1036 /* handle case of subfonts first */
1037 if (is_subfont(fd_cur->fm)) {
1038 if (e->code == -1)
1039 continue;
1040 assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1);
1041 if (cmap == NULL && !cmap_not_found) {
1042 cmap =
1043 ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid,
1044 fd_cur->fm->eid, true);
1045 if (cmap == NULL)
1046 cmap_not_found = true;
1047 }
1048 if (cmap == NULL)
1049 continue;
1050 t = cmap->table;
1051 assert(t != NULL && e->code < 0x10000);
1052 if (t[e->code] < 0) {
1053 pdftex_warn
1054 ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef",
1055 fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code);
1056 continue;
1057 }
1058 assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */
1059 glyph = glyph_tab + t[e->code];
1060 goto append_new_glyph;
1061 }
1062
1063 /* handle case of reencoded fonts */
1064 if (e->name == notdef)
1065 continue;
1066
1067 /* look up by name first */
1068 for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
1069 if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
1070 goto append_new_glyph;
1071
1072 /* scan form `uniABCD' */
1073 n = -1;
1074 sscanf(e->name, GLYPH_PREFIX_UNICODE "%X%n", &index, &n);
1075 if (n == strlen(e->name)) {
1076 if (cmap == NULL && !cmap_not_found) {
1077 /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */
1078 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false);
1079 if (cmap == NULL)
1080 cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false);
1081 if (cmap == NULL) {
1082 pdftex_warn
1083 ("no unicode mapping found, all `uniXXXX' names will be ignored");
1084 cmap_not_found = true; /* once only */
1085 }
1086 }
1087 if (cmap == NULL)
1088 continue;
1089 t = cmap->table;
1090 assert(t != NULL);
1091 if (t[index] != -1) {
1092 if (t[index] >= glyphs_count) {
1093 pdftex_warn
1094 ("`%s' is mapped to index %li which is out of valid range [0..%i)",
1095 e->name, t[index], glyphs_count);
1096 continue;
1097 }
1098 glyph = glyph_tab + t[index];
1099 goto append_new_glyph;
1100 } else {
1101 pdftex_warn("`unicode %s%.4X' is not mapped to any glyph",
1102 GLYPH_PREFIX_UNICODE, index);
1103 continue;
1104 }
1105 }
1106
1107 /* scan form `index123' */
1108 n = -1;
1109 sscanf(e->name, GLYPH_PREFIX_INDEX "%i%n", &index, &n);
1110 if (n == strlen(e->name)) {
1111 if (index >= glyphs_count) {
1112 pdftex_warn("`%s' out of valid range [0..%i)",
1113 e->name, glyphs_count);
1114 continue;
1115 }
1116 glyph = glyph_tab + index;
1117 goto append_new_glyph;
1118 }
1119
1120 /* not found */
1121 pdftex_warn("glyph `%s' not found", e->name);
1122 continue;
1123
1124 append_new_glyph:
1125 assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count);
1126 if (glyph->newindex < 0) {
1127 glyph_index[new_glyphs_count] = glyph - glyph_tab;
1128 glyph->newindex = new_glyphs_count;
1129 new_glyphs_count++;
1130 }
1131 e->newindex = glyph->newindex;
1132 }
1133 }
1134
ttf_write_head(void)1135 static void ttf_write_head(void)
1136 {
1137 dirtab_entry *tab;
1138 tab = ttf_seek_tab("head", 0);
1139 ttf_reset_chksm(tab);
1140 ttf_ncopy(2 * TTF_FIXED_SIZE);
1141 checkSumAdjustment_offset = ttf_offset();
1142 put_ulong(0);
1143 ttf_skip(TTF_ULONG_SIZE); /* skip checkSumAdjustment */
1144 ttf_ncopy(TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 +
1145 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
1146 if (is_subsetted(fd_cur->fm)) {
1147 (void) put_short(loca_format);
1148 (void) put_short(0);
1149 } else
1150 ttf_ncopy(2 * TTF_SHORT_SIZE);
1151 ttf_set_chksm(tab);
1152 }
1153
ttf_write_hhea(void)1154 static void ttf_write_hhea(void)
1155 {
1156 dirtab_entry *tab;
1157 tab = ttf_seek_tab("hhea", 0);
1158 ttf_reset_chksm(tab);
1159 ttf_ncopy(TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE +
1160 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE);
1161 (void) put_ushort(new_glyphs_count);
1162 ttf_set_chksm(tab);
1163 }
1164
ttf_write_htmx(void)1165 static void ttf_write_htmx(void)
1166 {
1167 long *id;
1168 dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
1169 ttf_reset_chksm(tab);
1170 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1171 put_ufword(glyph_tab[*id].advWidth);
1172 put_ufword(glyph_tab[*id].lsb);
1173 }
1174 ttf_set_chksm(tab);
1175 }
1176
ttf_write_loca(void)1177 static void ttf_write_loca(void)
1178 {
1179 long *id;
1180 dirtab_entry *tab = ttf_seek_tab("loca", 0);
1181 ttf_reset_chksm(tab);
1182 loca_format = 0;
1183 if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
1184 loca_format = 1;
1185 else
1186 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1187 if (glyph_tab[*id].newoffset & 1) {
1188 loca_format = 1;
1189 break;
1190 }
1191 if (loca_format != 0) {
1192 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1193 put_ulong(glyph_tab[*id].newoffset);
1194 put_ulong(last_glyf_offset);
1195 } else {
1196 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1197 (void) put_ushort(glyph_tab[*id].newoffset / 2);
1198 (void) put_ushort(last_glyf_offset / 2);
1199 }
1200 ttf_set_chksm(tab);
1201 }
1202
ttf_write_mapx(void)1203 static void ttf_write_mapx(void)
1204 {
1205 dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
1206 ttf_reset_chksm(tab);
1207 put_fixed(0x00010000);
1208 (void) put_ushort(new_glyphs_count);
1209 ttf_ncopy(13 * TTF_USHORT_SIZE);
1210 ttf_set_chksm(tab);
1211 }
1212
ttf_write_OS2(void)1213 static void ttf_write_OS2(void)
1214 {
1215 dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
1216 TTF_USHORT version;
1217 ttf_reset_chksm(tab);
1218 version = get_ushort();
1219 if (version > 3)
1220 pdftex_fail("unknown version of OS/2 table (%.4X)", version);
1221 (void) put_ushort(0x0001); /* fix version to 1 */
1222 ttf_ncopy(2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE);
1223 ttf_skip(4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
1224 put_ulong(0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
1225 put_ulong(0x10000000); /* Private Use (0xE000--0xF8FF) */
1226 put_ulong(0x00000000);
1227 put_ulong(0x00000000);
1228 ttf_ncopy(4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
1229 ttf_skip(2 * TTF_USHORT_SIZE);
1230 (void) put_ushort(0x0000); /* usFirstCharIndex */
1231 (void) put_ushort(0xF0FF); /* usLastCharIndex */
1232 ttf_ncopy(5 * TTF_USHORT_SIZE);
1233 /* for version 0 the OS/2 table ends here, the rest is for version 1 */
1234 put_ulong(0x80000000); /* Symbol Character Set---don't use any code page */
1235 put_ulong(0x00000000);
1236 ttf_set_chksm(tab);
1237 }
1238
unsafe_name(const char * s)1239 static boolean unsafe_name(const char *s)
1240 {
1241 const char **p;
1242 for (p = ambiguous_names; *p != NULL; p++)
1243 if (strcmp(s, *p) == 0)
1244 return true;
1245 return false;
1246 }
1247
ttf_write_post(void)1248 static void ttf_write_post(void)
1249 {
1250 dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
1251 glyph_entry *glyph;
1252 const char *s;
1253 long *id;
1254 int l;
1255 ttf_reset_chksm(tab);
1256 if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) {
1257 put_fixed(0x00030000);
1258 ttf_ncopy(TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1259 } else {
1260 put_fixed(0x00020000);
1261 ttf_ncopy(TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1262 (void) put_ushort(new_glyphs_count);
1263 k = 0;
1264 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1265 glyph = glyph_tab + *id;
1266 if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name))
1267 glyph->name_index = NMACGLYPHS + k++;
1268 (void) put_ushort(glyph->name_index);
1269 }
1270 for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1271 glyph = glyph_tab + *id;
1272 if (glyph->name_index >= NMACGLYPHS) {
1273 s = glyph->name;
1274 l = strlen(s);
1275 put_byte(l);
1276 while (l-- > 0)
1277 put_char(*s++);
1278 }
1279 }
1280 }
1281 ttf_set_chksm(tab);
1282 }
1283
ttf_init_font(int n)1284 static void ttf_init_font(int n)
1285 {
1286 int i, k;
1287 for (i = 1, k = 0; i <= n; i <<= 1, k++);
1288 put_fixed(0x00010000); /* font version */
1289 (void) put_ushort(n); /* number of tables */
1290 (void) put_ushort(i << 3); /* search range */
1291 (void) put_ushort(k - 1); /* entry selector */
1292 (void) put_ushort((n << 4) - (i << 3)); /* range shift */
1293 ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE);
1294 }
1295
ttf_subset_font(void)1296 static void ttf_subset_font(void)
1297 {
1298 ttf_init_font(new_ntabs);
1299 if (ttf_name_lookup("PCLT", false) != NULL)
1300 ttf_copytab("PCLT");
1301 if (ttf_name_lookup("fpgm", false) != NULL)
1302 ttf_copytab("fpgm");
1303 if (ttf_name_lookup("cvt ", false) != NULL)
1304 ttf_copytab("cvt ");
1305 if (ttf_name_lookup("prep", false) != NULL)
1306 ttf_copytab("prep");
1307 ttf_reindex_glyphs();
1308 ttf_write_glyf();
1309 ttf_write_loca();
1310 ttf_write_OS2();
1311 ttf_write_head();
1312 ttf_write_hhea();
1313 ttf_write_htmx();
1314 ttf_write_mapx();
1315 ttf_write_name();
1316 ttf_write_post();
1317 ttf_write_cmap();
1318 ttf_write_dirtab();
1319 }
1320
ttf_copy_font(void)1321 static void ttf_copy_font(void)
1322 {
1323 dirtab_entry *tab;
1324 ttf_init_font(ntabs);
1325 for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
1326 if (strncmp(tab->tag, "head", 4) == 0)
1327 ttf_write_head();
1328 else
1329 ttf_copytab(tab->tag);
1330 }
1331 ttf_write_dirtab();
1332 }
1333
writettf(fd_entry * fd)1334 void writettf(fd_entry * fd)
1335 {
1336 fd_cur = fd; /* fd_cur is global inside writettf.c */
1337 assert(fd_cur->fm != NULL);
1338 assert(is_truetype(fd_cur->fm));
1339 assert(is_included(fd_cur->fm));
1340
1341 set_cur_file_name(fd_cur->fm->ff_name);
1342 if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL)
1343 && !is_subfont(fd_cur->fm)) {
1344 pdftex_fail("Subset TrueType must be a reencoded or a subfont");
1345 }
1346 if (!ttf_open()) {
1347 pdftex_fail("cannot open TrueType font file for reading");
1348 }
1349 cur_file_name = (char *) nameoffile + 1;
1350
1351 /* skip ttc header, prepare for reading first font */
1352 if (strcasecmp(strchr(cur_file_name, 0) - 4, ".ttc") == 0) {
1353 if (get_ulong() != 0x74746366 /* ttcf */) {
1354 xfseek(INFILE, 0, SEEK_SET, cur_file_name);
1355 } else {
1356 ttf_skip(TTF_FIXED_SIZE); /* ignore the version */
1357 ttf_skip(TTF_ULONG_SIZE); /* ignore the numFonts */
1358
1359 /* goto first font */
1360 xfseek(INFILE, get_ulong(), SEEK_SET, cur_file_name);
1361 }
1362 }
1363
1364 if (is_subsetted(fd_cur->fm))
1365 tex_printf("<%s", cur_file_name);
1366 else
1367 tex_printf("<<%s", cur_file_name);
1368 fd_cur->ff_found = true;
1369 new_glyphs_count = 2;
1370 new_ntabs = DEFAULT_NTABS;
1371 dir_tab = NULL;
1372 glyph_tab = NULL;
1373 glyph_index = NULL;
1374 glyph_name_buf = NULL;
1375 name_tab = NULL;
1376 name_buf = NULL;
1377 ttf_read_font();
1378
1379 pdfsaveoffset = pdfoffset();
1380 pdfflush();
1381 if (is_subsetted(fd_cur->fm)) {
1382 ttf_copy_encoding();
1383 ttf_subset_font();
1384 } else
1385 ttf_copy_font();
1386 ttf_length = ttf_offset();
1387
1388 xfree(dir_tab);
1389 xfree(glyph_tab);
1390 xfree(glyph_index);
1391 xfree(glyph_name_buf);
1392 xfree(name_tab);
1393 xfree(name_buf);
1394 ttf_close();
1395 if (is_subsetted(fd_cur->fm))
1396 tex_printf(">");
1397 else
1398 tex_printf(">>");
1399 cur_file_name = NULL;
1400 }
1401
writeotf(fd_entry * fd)1402 void writeotf(fd_entry * fd)
1403 {
1404 dirtab_entry *tab;
1405 long i;
1406
1407 fd_cur = fd; /* fd_cur is global inside writettf.c */
1408 assert(fd_cur->fm != NULL);
1409 assert(is_opentype(fd_cur->fm));
1410 assert(is_included(fd_cur->fm));
1411
1412 set_cur_file_name(fd_cur->fm->ff_name);
1413 if (is_subsetted(fd_cur->fm))
1414 pdftex_fail("OTF fonts must be included entirely");
1415 if (!open_input(&ttf_file, kpse_opentype_format, FOPEN_RBIN_MODE)) {
1416 pdftex_fail("cannot open OpenType font file for reading");
1417 }
1418 cur_file_name = (char *) nameoffile + 1;
1419 tex_printf("<<%s", cur_file_name);
1420 fd_cur->ff_found = true;
1421 dir_tab = NULL;
1422 glyph_tab = NULL;
1423 ttf_read_tabdir();
1424 /* read font parameters */
1425 if (ttf_name_lookup("head", false) != NULL)
1426 ttf_read_head();
1427 if (ttf_name_lookup("hhea", false) != NULL)
1428 ttf_read_hhea();
1429 if (ttf_name_lookup("PCLT", false) != NULL)
1430 ttf_read_pclt();
1431 if (ttf_name_lookup("post", false) != NULL)
1432 ttf_read_post();
1433 /* copy font file */
1434 tab = ttf_seek_tab("CFF ", 0);
1435 for (i = tab->length; i > 0; i--)
1436 copy_char();
1437 xfree(dir_tab);
1438 ttf_close();
1439 tex_printf(">>");
1440 cur_file_name = NULL;
1441 }
1442
1443 /*
1444 To calculate the checkSum for the 'head' table which itself includes the
1445 checkSumAdjustment entry for the entire font, do the following:
1446
1447 * Set the checkSumAdjustment to 0.
1448 * Calculate the checksum for all the tables including the 'head' table
1449 and enter that value into the table directory.
1450 * Calculate the checksum for the entire font.
1451 * Subtract that value from the hex value B1B0AFBA.
1452 * Store the result in checkSumAdjustment.
1453
1454 The checkSum for the 'head table which includes the checkSumAdjustment
1455 entry for the entire font is now incorrect. That is not a problem. Do not
1456 change it. An application attempting to verify that the 'head' table has
1457 not changed should calculate the checkSum for that table by not including
1458 the checkSumAdjustment value, and compare the result with the entry in the
1459 table directory.
1460
1461 The table directory also includes the offset of the associated tagged
1462 table from the beginning of the font file and the length of that table.
1463 */
1464