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