1% writettf.w
2%
3% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
5%
6% This file is part of LuaTeX.
7%
8% LuaTeX is free software; you can redistribute it and/or modify it under
9% the terms of the GNU General Public License as published by the Free
10% Software Foundation; either version 2 of the License, or (at your
11% option) any later version.
12%
13% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16% License for more details.
17%
18% You should have received a copy of the GNU General Public License along
19% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20
21@ @c
22
23
24#include "ptexlib.h"
25#include "font/writettf.h"
26#include <string.h>
27
28#define DEFAULT_NTABS       14
29#define NEW_CMAP_SIZE       2
30
31#define ttf_putchar(A)     strbuf_putchar(pdf->fb, (A))
32#define ttf_offset()       strbuf_offset(pdf->fb)
33#define ttf_seek_outbuf(A) strbuf_seek(pdf->fb, (A))
34
35unsigned char *ttf_buffer = NULL;
36int ttf_size = 0;
37int ttf_curbyte = 0;
38
39typedef struct {
40    char *name;                 /* name of glyph */
41    long code;                  /* charcode in case of subfonts */
42    long newindex;              /* new index of glyph in output file */
43
44} ttfenc_entry;
45
46typedef struct {
47    TTF_USHORT platform_id;
48    TTF_USHORT encoding_id;
49    TTF_USHORT language_id;
50    TTF_USHORT name_id;
51    TTF_USHORT length;
52    TTF_USHORT offset;
53    TTF_USHORT new_offset;
54    TTF_USHORT new_length;
55} name_record;
56
57typedef struct {
58    char *ttf_name;
59    TTF_USHORT pid;
60    TTF_USHORT eid;
61    long *table;
62} ttf_cmap_entry;
63
64static TTF_USHORT ntabs;
65static TTF_USHORT upem;
66static TTF_FIXED post_format;
67static TTF_SHORT loca_format;
68static TTF_ULONG last_glyf_offset;
69static TTF_USHORT glyphs_count;
70static TTF_USHORT new_glyphs_count;
71static TTF_USHORT nhmtxs;
72static TTF_USHORT new_ntabs;
73
74glyph_entry *glyph_tab;
75dirtab_entry *dir_tab;
76
77static long *glyph_index;
78static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
79static name_record *name_tab;
80static int name_record_num;
81static char *name_buf;
82static int name_buf_size;
83static char *glyph_name_buf;
84static TTF_ULONG checksum;
85static TTF_ULONG tab_length;
86static TTF_ULONG tmp_ulong;
87static TTF_ULONG checkSumAdjustment_offset;
88FILE *ttf_file;
89static ttfenc_entry ttfenc_tab[256];
90
91fd_entry *fd_cur;               /* pointer to the current font descriptor */
92
93static struct avl_table *ttf_cmap_tree = NULL;
94
95int ttf_length;
96
97@ This used to be macnames.c
98
99@c
100char notdef[] = ".notdef";
101
102const char *mac_glyph_names[] = {
103/* 0x00 */
104    notdef,
105    ".null",
106    "CR",
107    "space",
108    "exclam",
109    "quotedbl",
110    "numbersign",
111    "dollar",
112    "percent",
113    "ampersand",
114    "quotesingle",
115    "parenleft",
116    "parenright",
117    "asterisk",
118    "plus",
119    "comma",
120/* 0x10 */
121    "hyphen",
122    "period",
123    "slash",
124    "zero",
125    "one",
126    "two",
127    "three",
128    "four",
129    "five",
130    "six",
131    "seven",
132    "eight",
133    "nine",
134    "colon",
135    "semicolon",
136    "less",
137/* 0x20 */
138    "equal",
139    "greater",
140    "question",
141    "at",
142    "A",
143    "B",
144    "C",
145    "D",
146    "E",
147    "F",
148    "G",
149    "H",
150    "I",
151    "J",
152    "K",
153    "L",
154/* 0x30 */
155    "M",
156    "N",
157    "O",
158    "P",
159    "Q",
160    "R",
161    "S",
162    "T",
163    "U",
164    "V",
165    "W",
166    "X",
167    "Y",
168    "Z",
169    "bracketleft",
170    "backslash",
171/* 0x40 */
172    "bracketright",
173    "asciicircum",
174    "underscore",
175    "grave",
176    "a",
177    "b",
178    "c",
179    "d",
180    "e",
181    "f",
182    "g",
183    "h",
184    "i",
185    "j",
186    "k",
187    "l",
188/* 0x50 */
189    "m",
190    "n",
191    "o",
192    "p",
193    "q",
194    "r",
195    "s",
196    "t",
197    "u",
198    "v",
199    "w",
200    "x",
201    "y",
202    "z",
203    "braceleft",
204    "bar",
205/* 0x60 */
206    "braceright",
207    "asciitilde",
208    "Adieresis",
209    "Aring",
210    "Ccedilla",
211    "Eacute",
212    "Ntilde",
213    "Odieresis",
214    "Udieresis",
215    "aacute",
216    "agrave",
217    "acircumflex",
218    "adieresis",
219    "atilde",
220    "aring",
221    "ccedilla",
222/* 0x70 */
223    "eacute",
224    "egrave",
225    "ecircumflex",
226    "edieresis",
227    "iacute",
228    "igrave",
229    "icircumflex",
230    "idieresis",
231    "ntilde",
232    "oacute",
233    "ograve",
234    "ocircumflex",
235    "odieresis",
236    "otilde",
237    "uacute",
238    "ugrave",
239/* 0x80 */
240    "ucircumflex",
241    "udieresis",
242    "dagger",
243    "degree",
244    "cent",
245    "sterling",
246    "section",
247    "bullet",
248    "paragraph",
249    "germandbls",
250    "registered",
251    "copyright",
252    "trademark",
253    "acute",
254    "dieresis",
255    "notequal",
256/* 0x90 */
257    "AE",
258    "Oslash",
259    "infinity",
260    "plusminus",
261    "lessequal",
262    "greaterequal",
263    "yen",
264    "mu",
265    "partialdiff",
266    "Sigma",
267    "Pi",
268    "pi",
269    "integral",
270    "ordfeminine",
271    "ordmasculine",
272    "Omega",
273/* 0xa0 */
274    "ae",
275    "oslash",
276    "questiondown",
277    "exclamdown",
278    "logicalnot",
279    "radical",
280    "florin",
281    "approxequal",
282    "Delta",
283    "guillemotleft",
284    "guillemotright",
285    "ellipsis",
286    "nbspace",
287    "Agrave",
288    "Atilde",
289    "Otilde",
290/* 0xb0 */
291    "OE",
292    "oe",
293    "endash",
294    "emdash",
295    "quotedblleft",
296    "quotedblright",
297    "quoteleft",
298    "quoteright",
299    "divide",
300    "lozenge",
301    "ydieresis",
302    "Ydieresis",
303    "fraction",
304    "currency",
305    "guilsinglleft",
306    "guilsinglright",
307/* 0xc0 */
308    "fi",
309    "fl",
310    "daggerdbl",
311    "periodcentered",
312    "quotesinglbase",
313    "quotedblbase",
314    "perthousand",
315    "Acircumflex",
316    "Ecircumflex",
317    "Aacute",
318    "Edieresis",
319    "Egrave",
320    "Iacute",
321    "Icircumflex",
322    "Idieresis",
323    "Igrave",
324/* 0xd0 */
325    "Oacute",
326    "Ocircumflex",
327    "applelogo",
328    "Ograve",
329    "Uacute",
330    "Ucircumflex",
331    "Ugrave",
332    "dotlessi",
333    "circumflex",
334    "tilde",
335    "macron",
336    "breve",
337    "dotaccent",
338    "ring",
339    "cedilla",
340    "hungarumlaut",
341/* 0xe0 */
342    "ogonek",
343    "caron",
344    "Lslash",
345    "lslash",
346    "Scaron",
347    "scaron",
348    "Zcaron",
349    "zcaron",
350    "brokenbar",
351    "Eth",
352    "eth",
353    "Yacute",
354    "yacute",
355    "Thorn",
356    "thorn",
357    "minus",
358/* 0xf0 */
359    "multiply",
360    "onesuperior",
361    "twosuperior",
362    "threesuperior",
363    "onehalf",
364    "onequarter",
365    "threequarters",
366    "franc",
367    "Gbreve",
368    "gbreve",
369    "Idot",
370    "Scedilla",
371    "scedilla",
372    "Cacute",
373    "cacute",
374    "Ccaron",
375/* 0x100 */
376    "ccaron",
377    "dmacron"
378};
379
380const char *ambiguous_names[] = {
381    "Delta",                    /*   increment   */
382    "Omega",                    /*   Ohm         */
383    "Pi",                       /*   product     */
384    "Sigma",                    /*   summation   */
385    "dmacron",                  /*   dslash      */
386    "macron",                   /*   overscore   */
387    "periodcentered",           /*   middot      */
388    NULL
389};
390
391static const char *newtabnames[] = {
392    "OS/2",
393    "PCLT",
394    "cmap",
395    "cvt ",
396    "fpgm",
397    "glyf",
398    "head",
399    "hhea",
400    "hmtx",
401    "loca",
402    "maxp",
403    "name",
404    "post",
405    "prep"
406};
407
408@ Back to code. Low-level helpers first.
409
410@c
411static ttf_cmap_entry *new_ttf_cmap_entry(void)
412{
413    ttf_cmap_entry *e;
414    e = xtalloc(1, ttf_cmap_entry);
415    e->ttf_name = NULL;
416    e->table = NULL;
417    return e;
418}
419
420static void destroy_ttf_cmap_entry(void *pa, void *pb)
421{
422    ttf_cmap_entry *p;
423    (void) pb;
424    p = (ttf_cmap_entry *) pa;
425    xfree(p->ttf_name);
426    xfree(p->table);
427    xfree(p);
428}
429
430void ttf_free(void)
431{
432    if (ttf_cmap_tree != NULL)
433        avl_destroy(ttf_cmap_tree, destroy_ttf_cmap_entry);
434}
435
436static int comp_ttf_cmap_entry(const void *pa, const void *pb, void *p)
437{
438    const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa,
439        *p2 = (const ttf_cmap_entry *) pb;
440    int i;
441    (void) p;
442    assert(p1->ttf_name != NULL && p2->ttf_name != NULL);
443    if ((i = strcmp(p1->ttf_name, p2->ttf_name)) != 0)
444        return i;
445    cmp_return(p1->pid, p2->pid);
446    cmp_return(p1->eid, p2->eid);
447    return 0;
448}
449
450static unsigned char ttf_addchksm(unsigned char b)
451{
452    tmp_ulong = (tmp_ulong << 8) + b;
453    tab_length++;
454    if (tab_length % 4 == 0) {
455        checksum += tmp_ulong;
456        tmp_ulong = 0;
457    }
458    return b;
459}
460
461static TTF_ULONG ttf_getchksm(PDF pdf)
462{
463    while (tab_length % 4 != 0)
464        ttf_putchar(ttf_addchksm(0));   /* |ttf_addchksm| updates |tab_length| */
465    return checksum;
466}
467
468long ttf_putnum(PDF pdf, int s, long n)
469{
470    long i = n;
471    char buf[TTF_LONG_SIZE + 1], *p = buf;
472    while (s-- > 0) {
473        *p++ = (char) (i & 0xFF);
474        i >>= 8;
475    }
476    p--;
477    while (p >= buf)
478        ttf_putchar(ttf_addchksm((unsigned char) (*p--)));
479    return n;
480}
481
482long ttf_getnum(int s)
483{
484    long i = 0;
485    int c;
486    while (s > 0) {
487        if (ttf_eof())
488            luatex_fail("unexpected EOF");
489        c = ttf_getchar();
490        i = (i << 8) + c;
491        s--;
492    }
493    return i;
494}
495
496static long ttf_funit(long n)
497{
498    if (n < 0)
499        return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem);
500    else
501        return (n / upem) * 1000 + ((n % upem) * 1000) / upem;
502}
503
504static void ttf_ncopy(PDF pdf, int n)
505{
506    while (n-- > 0)
507        copy_byte();
508}
509
510dirtab_entry *ttf_name_lookup(const char *s, boolean required)
511{
512    dirtab_entry *tab;
513    for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
514        if (strncmp(tab->tag, s, 4) == 0)
515            break;
516    if (tab - dir_tab == ntabs) {
517        if (required)
518            luatex_fail("can't find table `%s'", s);
519        else
520            tab = NULL;
521    }
522    return tab;
523}
524
525dirtab_entry *ttf_seek_tab(const char *name, TTF_LONG offset)
526{
527    dirtab_entry *tab = ttf_name_lookup(name, true);
528    ttf_curbyte = (int) (tab->offset + (unsigned long) offset);
529    return tab;
530}
531
532static void ttf_seek_off(TTF_LONG offset)
533{
534    ttf_curbyte = (int) offset;
535}
536
537static void ttf_copy_encoding(void)
538{
539    int i, *q;
540    void **aa;
541    char **glyph_names;
542    long *charcodes;
543    static char buf[SMALL_BUF_SIZE];
544    struct avl_traverser t;
545    ttfenc_entry *e = ttfenc_tab;
546
547    assert(fd_cur->tx_tree != NULL);    /* this must be set in |create_fontdictionary| */
548
549    if (fd_cur->fe != NULL) {
550        glyph_names = fd_cur->fe->glyph_names;
551        assert(glyph_names != NULL);
552
553        for (i = 0; i < 256; i++)
554            ttfenc_tab[i].name = (char *) notdef;
555
556        /* a workaround for a bug of AcroReader 4.0 */
557        if (strcmp(glyph_names[97], "a") == 0) {
558            q = xtalloc(1, int);
559            *q = 'a';
560            aa = avl_probe(fd_cur->tx_tree, q);
561            assert(aa != NULL);
562        }
563        /* end of workaround */
564
565        /* take over collected characters from \TeX, reencode them */
566        avl_t_init(&t, fd_cur->tx_tree);
567        for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
568             q = (int *) avl_t_next(&t)) {
569            assert(*q >= 0 && *q < 256);
570            ttfenc_tab[*q].name = glyph_names[*q];
571        }
572        make_subset_tag(fd_cur);
573    } else if (is_subfont(fd_cur->fm)) {
574        charcodes = fd_cur->fm->subfont->charcodes;
575        assert(charcodes != NULL);
576
577        for (i = 0; i < 256; i++)
578            ttfenc_tab[i].code = -1;
579
580        /* take over collected characters from \TeX */
581        avl_t_init(&t, fd_cur->tx_tree);
582        for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
583             q = (int *) avl_t_next(&t)) {
584            assert(*q >= 0 && *q < 256);
585            e = ttfenc_tab + *q;
586            e->code = charcodes[*q];
587            if (e->code == -1)
588                luatex_warn
589                    ("character %i in subfont %s is not mapped to any charcode",
590                     *q, fd_cur->fm->tfm_name);
591            else {
592                assert(e->code < 0x10000);
593                sprintf(buf, "/c%4.4X", (int) e->code);
594                aa = avl_probe(fd_cur->gl_tree, xstrdup(buf));
595                assert(aa != NULL);
596            }
597        }
598        make_subset_tag(fd_cur);
599    } else
600        assert(0);
601}
602
603@
604@c
605#define ttf_append_byte(B)\
606do {\
607    if (name_tab[i].platform_id == 3)\
608        *q++ = 0;\
609    *q++ = B;\
610} while (0)
611
612static char *strip_spaces_and_delims(char *s, int l)
613{
614    static char buf[SMALL_BUF_SIZE];
615    char *p = buf;
616    int i;
617
618    assert(l >= 0 && l < (int) sizeof(buf));
619
620    for (i = 0; i < l; s++, i++) {
621        if (*s == '(' || *s == ')' || *s == '<' || *s == '>' ||
622            *s == '[' || *s == ']' || *s == '{' || *s == '}' ||
623            *s == '/' || *s == '%' || isspace((unsigned char)*s))
624            continue;
625        *p++ = *s;
626    }
627    *p = 0;
628    return buf;
629}
630
631static void ttf_read_name(void)
632{
633    int i, j;
634    dirtab_entry *tab = ttf_seek_tab("name", TTF_USHORT_SIZE);
635    char *p, buf[SMALL_BUF_SIZE];
636    name_record_num = get_ushort();
637    name_tab = xtalloc((unsigned) name_record_num, name_record);
638    name_buf_size = (int) ((unsigned) tab->length -
639                           (3 * TTF_USHORT_SIZE +
640                            (TTF_ULONG) name_record_num * 6 * TTF_USHORT_SIZE));
641    name_buf = xtalloc((unsigned) name_buf_size, char);
642    ttf_skip(TTF_USHORT_SIZE);
643    for (i = 0; i < name_record_num; i++) {
644        name_tab[i].platform_id = get_ushort();
645        name_tab[i].encoding_id = get_ushort();
646        name_tab[i].language_id = get_ushort();
647        name_tab[i].name_id = get_ushort();
648        name_tab[i].length = get_ushort();
649        name_tab[i].offset = get_ushort();
650    }
651    for (p = name_buf; p - name_buf < name_buf_size; p++)
652        *p = get_char();
653    /* look for PS font name */
654    for (i = 0; i < name_record_num; i++) {
655        if (name_tab[i].platform_id == 1 &&
656            name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) {
657            xfree(fd_cur->fontname);
658            fd_cur->fontname =
659                xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset,
660                                                name_tab[i].length));
661            fd_cur->font_dim[FONTNAME_CODE].set = true;
662            break;
663        }
664    }
665    if (!fd_cur->font_dim[FONTNAME_CODE].set) {
666        for (i = 0; i < name_record_num; i++) {
667            if (name_tab[i].platform_id == 3 &&
668                (name_tab[i].encoding_id == 0 || name_tab[i].encoding_id == 1)
669                && name_tab[i].name_id == 6) {
670                xfree(fd_cur->fontname);
671                assert(name_tab[i].length < sizeof(buf));
672                for (j = 0, p = buf; j < name_tab[i].length; j += 2)
673                    *p++ = name_buf[name_tab[i].offset + j + 1];
674                *p = 0;
675                fd_cur->fontname =
676                    xstrdup(strip_spaces_and_delims(buf, (int) strlen(buf)));
677                fd_cur->font_dim[FONTNAME_CODE].set = true;
678                break;
679            }
680        }
681    }
682}
683
684static void ttf_read_mapx(void)
685{
686    glyph_entry *glyph;
687    ttf_seek_tab("maxp", TTF_FIXED_SIZE);
688    glyph_tab =
689        xtalloc((unsigned) (1 + (glyphs_count = get_ushort())), glyph_entry);
690    for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
691        glyph->newindex = -1;
692        glyph->newoffset = 0;
693        glyph->name_index = 0;
694        glyph->name = (char *) notdef;
695    }
696    glyph_index = xtalloc((unsigned) (glyphs_count + 1), long);
697    glyph_index[0] = 0;         /* index of ".notdef" glyph */
698    glyph_index[1] = 1;         /* index of ".null" glyph */
699}
700
701void ttf_read_head(void)
702{
703    ttf_seek_tab("head",
704                 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
705    upem = get_ushort();
706    ttf_skip(16);
707    fd_cur->font_dim[FONTBBOX1_CODE].val = (int) ttf_funit(get_fword());
708    fd_cur->font_dim[FONTBBOX2_CODE].val = (int) ttf_funit(get_fword());
709    fd_cur->font_dim[FONTBBOX3_CODE].val = (int) ttf_funit(get_fword());
710    fd_cur->font_dim[FONTBBOX4_CODE].val = (int) ttf_funit(get_fword());
711    fd_cur->font_dim[FONTBBOX1_CODE].set = true;
712    fd_cur->font_dim[FONTBBOX2_CODE].set = true;
713    fd_cur->font_dim[FONTBBOX3_CODE].set = true;
714    fd_cur->font_dim[FONTBBOX4_CODE].set = true;
715    ttf_skip(2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
716    loca_format = get_short();
717}
718
719void ttf_read_hhea(void)
720{
721    ttf_seek_tab("hhea", TTF_FIXED_SIZE);
722    fd_cur->font_dim[ASCENT_CODE].val = (int) ttf_funit(get_fword());
723    fd_cur->font_dim[DESCENT_CODE].val = (int) ttf_funit(get_fword());
724    fd_cur->font_dim[ASCENT_CODE].set = true;
725    fd_cur->font_dim[DESCENT_CODE].set = true;
726    ttf_skip(TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
727             8 * TTF_SHORT_SIZE);
728    nhmtxs = get_ushort();
729}
730
731void ttf_read_pclt(void)
732{
733    if (ttf_name_lookup("PCLT", false) == NULL)
734        return;
735    ttf_seek_tab("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
736    fd_cur->font_dim[XHEIGHT_CODE].val = (int) ttf_funit(get_ushort());
737    ttf_skip(2 * TTF_USHORT_SIZE);
738    fd_cur->font_dim[CAPHEIGHT_CODE].val = (int) ttf_funit(get_ushort());
739    fd_cur->font_dim[XHEIGHT_CODE].set = true;
740    fd_cur->font_dim[CAPHEIGHT_CODE].set = true;
741}
742
743static void ttf_read_hmtx(void)
744{
745    glyph_entry *glyph;
746    TTF_UFWORD last_advWidth;
747    ttf_seek_tab("hmtx", 0);
748    for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
749        glyph->advWidth = get_ufword();
750        glyph->lsb = (TTF_FWORD) get_ufword();
751    }
752    if (nhmtxs < glyphs_count) {
753        last_advWidth = glyph[-1].advWidth;
754        for (; glyph - glyph_tab < glyphs_count; glyph++) {
755            glyph->advWidth = last_advWidth;
756            glyph->lsb = (TTF_FWORD) get_ufword();
757        }
758    }
759}
760
761void ttf_read_post(void)
762{
763    int k, nnames;
764    long length;
765    long int_part, frac_part;
766    int sign = 1;
767    TTF_FIXED italic_angle;
768    char *p;
769    glyph_entry *glyph;
770    const dirtab_entry *tab = ttf_seek_tab("post", 0);
771    post_format = get_fixed();
772    italic_angle = get_fixed();
773    int_part = (long) (italic_angle >> 16);
774    if (int_part > 0x7FFF) {    /* a negative number */
775        int_part = 0x10000 - int_part;
776        sign = -1;
777    }
778    frac_part = (long) (italic_angle % 0x10000);
779    fd_cur->font_dim[ITALIC_ANGLE_CODE].val =
780        (int) (sign * ((double) int_part + (double) frac_part * 1.0 / 0x10000));
781    fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
782    if (glyph_tab == NULL)
783        return;                 /* being called from writeotf() */
784    ttf_skip(2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
785    switch (post_format) {
786    case 0x10000:
787        for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
788            glyph->name = (const char *) mac_glyph_names[glyph - glyph_tab];
789            glyph->name_index = (TTF_USHORT) (glyph - glyph_tab);
790        }
791        break;
792    case 0x20000:
793        nnames = get_ushort();  /* some fonts have this value different from nglyphs */
794        for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
795            glyph->name_index = get_ushort();
796        length =
797            (long) ((long) tab->length -
798                    (long) ((long) ttf_curbyte - (long) tab->offset));
799        glyph_name_buf = xtalloc((unsigned) length, char);
800        for (p = glyph_name_buf; p - glyph_name_buf < length;) {
801            for (k = get_byte(); k > 0; k--)
802                *p++ = get_char();
803            *p++ = 0;
804        }
805        for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
806            if (glyph->name_index < NMACGLYPHS)
807                glyph->name = mac_glyph_names[glyph->name_index];
808            else {
809                p = glyph_name_buf;
810                k = glyph->name_index - NMACGLYPHS;
811                for (; k > 0; k--)
812                    p = strend(p) + 1;
813                glyph->name = p;
814            }
815        }
816        break;
817    default:
818        luatex_warn("unsupported format (%.8X) of `post' table, assuming 3.0",
819                    (unsigned int) post_format);
820    case 0x00030000:
821        for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
822            glyph->name_index = (TTF_USHORT) (glyph - glyph_tab);
823        }
824    }
825}
826
827static void ttf_read_loca(void)
828{
829    glyph_entry *glyph;
830    ttf_seek_tab("loca", 0);
831    if (loca_format != 0)
832        for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
833            glyph->offset = (TTF_LONG) get_ulong();
834    else
835        for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
836            glyph->offset = get_ushort() << 1;
837}
838
839void ttf_read_tabdir(void)
840{
841    int i;
842    dirtab_entry *tab;
843    ttf_skip(TTF_FIXED_SIZE);   /* ignore the sfnt number */
844    dir_tab = xtalloc(ntabs = get_ushort(), dirtab_entry);
845    ttf_skip(3 * TTF_USHORT_SIZE);
846    for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
847        for (i = 0; i < 4; i++)
848            tab->tag[i] = get_char();
849        tab->checksum = get_ulong();
850        tab->offset = get_ulong();
851        tab->length = get_ulong();
852    }
853}
854
855static ttf_cmap_entry *ttf_read_cmap(char *ttf_name, int pid, int eid,
856                                     boolean warn)
857{
858    seg_entry *seg_tab, *s;
859    TTF_USHORT *glyphId, format, segCount;
860    TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid;
861    TTF_ULONG cmap_offset, tmp_offset;
862    long n, i, k, length, index;
863    ttf_cmap_entry tmp_e, *p;
864    void **aa;
865
866    /* look up in |ttf_cmap_tree| first, return if found */
867    tmp_e.ttf_name = ttf_name;
868    tmp_e.pid = (TTF_USHORT) pid;
869    tmp_e.eid = (TTF_USHORT) eid;
870    if (ttf_cmap_tree == NULL) {
871        ttf_cmap_tree = avl_create(comp_ttf_cmap_entry, NULL, &avl_xallocator);
872        assert(ttf_cmap_tree != NULL);
873    }
874    p = (ttf_cmap_entry *) avl_find(ttf_cmap_tree, &tmp_e);
875    if (p != NULL)
876        return p;
877
878    /* not found, have to read it */
879    ttf_seek_tab("cmap", TTF_USHORT_SIZE);      /* skip the table version number (=0) */
880    ncmapsubtabs = get_ushort();
881    cmap_offset = (TTF_ULONG) (ttf_curbyte - 2 * TTF_USHORT_SIZE);
882    cmap_tab = xtalloc(ncmapsubtabs, cmap_entry);
883    for (i = 0; i < ncmapsubtabs; ++i) {
884        tmp_pid = get_ushort();
885        tmp_eid = get_ushort();
886        tmp_offset = get_ulong();
887        if (tmp_pid == pid && tmp_eid == eid) {
888            ttf_seek_off((TTF_LONG) (cmap_offset + tmp_offset));
889            format = get_ushort();
890            if (format == 4)
891                goto read_cmap_format_4;
892            else {
893                if (warn)
894                    luatex_warn("cmap format %i unsupported", format);
895                return NULL;
896            }
897        }
898    }
899    if (warn)
900        luatex_warn("cannot find cmap subtable for (pid,eid) = (%i, %i)",
901                    pid, eid);
902    return NULL;
903  read_cmap_format_4:
904    /* initialize the new entry */
905    p = new_ttf_cmap_entry();
906    p->ttf_name = xstrdup(ttf_name);
907    p->pid = (TTF_USHORT) pid;
908    p->eid = (TTF_USHORT) eid;
909    p->table = xtalloc(0x10000, long);
910    for (i = 0; i < 0x10000; ++i)
911        p->table[i] = -1;       /* unassigned yet */
912
913    /* read the subtable */
914    length = get_ushort();      /* length of subtable */
915    (void) get_ushort();        /* skip the version number */
916    segCount = get_ushort() / 2;
917    (void) get_ushort();        /* skip searchRange */
918    (void) get_ushort();        /* skip entrySelector */
919    (void) get_ushort();        /* skip rangeShift */
920    seg_tab = xtalloc(segCount, seg_entry);
921    for (s = seg_tab; s - seg_tab < segCount; s++)
922        s->endCode = get_ushort();
923    (void) get_ushort();        /* skip reversedPad */
924    for (s = seg_tab; s - seg_tab < segCount; s++)
925        s->startCode = get_ushort();
926    for (s = seg_tab; s - seg_tab < segCount; s++)
927        s->idDelta = get_ushort();
928    for (s = seg_tab; s - seg_tab < segCount; s++)
929        s->idRangeOffset = get_ushort();
930    length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
931    n = length / TTF_USHORT_SIZE;       /* number of glyphID's */
932    glyphId = xtalloc((unsigned) n, TTF_USHORT);
933    for (i = 0; i < n; i++)
934        glyphId[i] = get_ushort();
935    for (s = seg_tab; s - seg_tab < segCount; s++) {
936        for (i = s->startCode; i <= s->endCode; i++) {
937            if (i == 0xFFFF)
938                break;
939            if (s->idRangeOffset != 0xFFFF) {
940                if (s->idRangeOffset == 0)
941                    index = (s->idDelta + i) & 0xFFFF;
942                else {
943                    k = (i - s->startCode) + s->idRangeOffset / 2 +
944                        (s - seg_tab) - segCount;
945                    assert(k >= 0 && k < n);
946                    index = glyphId[k];
947                    if (index != 0)
948                        index = (index + s->idDelta) & 0xFFFF;
949                }
950                if (index >= glyphs_count)
951                    luatex_fail("cmap: glyph index %li out of range [0..%i)",
952                                index, glyphs_count);
953                if (p->table[i] != -1)
954                    luatex_warn
955                        ("cmap: multiple glyphs are mapped to unicode %.4lX, "
956                         "only %li will be used (glyph %li being ignored)", i,
957                         p->table[i], index);
958                else
959                    p->table[i] = index;
960            }
961        }
962    }
963    xfree(seg_tab);
964    xfree(glyphId);
965    aa = avl_probe(ttf_cmap_tree, p);
966    assert(aa != NULL);
967    return p;
968}
969
970@
971@c
972static void ttf_read_font(void)
973{
974    ttf_read_tabdir();
975    if (ttf_name_lookup("PCLT", false) == NULL)
976        new_ntabs--;
977    if (ttf_name_lookup("fpgm", false) == NULL)
978        new_ntabs--;
979    if (ttf_name_lookup("cvt ", false) == NULL)
980        new_ntabs--;
981    if (ttf_name_lookup("prep", false) == NULL)
982        new_ntabs--;
983    ttf_read_mapx();
984    ttf_read_head();
985    ttf_read_hhea();
986    ttf_read_pclt();
987    ttf_read_hmtx();
988    ttf_read_post();
989    ttf_read_loca();
990    ttf_read_name();
991}
992
993static void ttf_reset_chksm(PDF pdf, dirtab_entry * tab)
994{
995    checksum = 0;
996    tab_length = 0;
997    tmp_ulong = 0;
998    tab->offset = (TTF_ULONG) ttf_offset();
999    if (tab->offset % 4 != 0)
1000        luatex_warn("offset of `%4.4s' is not a multiple of 4", tab->tag);
1001}
1002
1003
1004static void ttf_set_chksm(PDF pdf, dirtab_entry * tab)
1005{
1006    tab->length = (TTF_ULONG) ttf_offset() - tab->offset;
1007    tab->checksum = ttf_getchksm(pdf);
1008}
1009
1010static void ttf_copytab(PDF pdf, const char *name)
1011{
1012    long i;
1013    dirtab_entry *tab = ttf_seek_tab(name, 0);
1014    ttf_reset_chksm(pdf, tab);
1015    for (i = (long) tab->length; i > 0; i--)
1016        copy_char();
1017    ttf_set_chksm(pdf, tab);
1018}
1019
1020@
1021@c
1022#define BYTE_ENCODING_LENGTH  \
1023    ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
1024
1025static void ttf_byte_encoding(PDF pdf)
1026{
1027    ttfenc_entry *e;
1028    (void) put_ushort(0);       /* format number (0: byte encoding table) */
1029    (void) put_ushort(BYTE_ENCODING_LENGTH);    /* length of table */
1030    (void) put_ushort(0);       /* version number */
1031    for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1032        if (e->newindex < 256) {
1033            put_byte(e->newindex);
1034        } else {
1035            if (e->name != notdef)
1036                luatex_warn
1037                    ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
1038                     e->name, notdef);
1039            put_byte(0);        /* notdef */
1040        }
1041}
1042
1043@
1044@c
1045#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256)))
1046
1047static void ttf_trimmed_table_map(PDF pdf)
1048{
1049    ttfenc_entry *e;
1050    (void) put_ushort(6);       /* format number (6): trimmed table mapping */
1051    (void) put_ushort(TRIMMED_TABLE_MAP_LENGTH);
1052    (void) put_ushort(0);       /* version number (0) */
1053    (void) put_ushort(0);       /* first character code */
1054    (void) put_ushort(256);     /* number of character code in table */
1055    for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1056        (void) put_ushort(e->newindex);
1057}
1058
1059@
1060@c
1061#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE)
1062
1063static void ttf_seg_map_delta(PDF pdf)
1064{
1065    ttfenc_entry *e;
1066    (void) put_ushort(4);       /* format number (4: segment mapping to delta values) */
1067    (void) put_ushort(SEG_MAP_DELTA_LENGTH);
1068    (void) put_ushort(0);       /* version number */
1069    (void) put_ushort(4);       /* 2*segCount */
1070    (void) put_ushort(4);       /* searchRange */
1071    (void) put_ushort(1);       /* entrySelector */
1072    (void) put_ushort(0);       /* rangeShift */
1073    (void) put_ushort(0xF0FF);  /* endCount[0] */
1074    (void) put_ushort(0xFFFF);  /* endCount[1] */
1075    (void) put_ushort(0);       /* reversedPad */
1076    (void) put_ushort(0xF000);  /* startCount[0] */
1077    (void) put_ushort(0xFFFF);  /* startCount[1] */
1078    (void) put_ushort(0);       /* idDelta[0] */
1079    (void) put_ushort(1);       /* idDelta[1] */
1080    (void) put_ushort(2 * TTF_USHORT_SIZE);     /* idRangeOffset[0] */
1081    (void) put_ushort(0);       /* idRangeOffset[1] */
1082    for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
1083        (void) put_ushort(e->newindex);
1084}
1085
1086@
1087@c
1088#define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
1089
1090static void ttf_select_cmap(void)
1091{
1092    assert(sizeof(new_cmap_tab) <= NEW_CMAP_SIZE * sizeof(cmap_entry));
1093    new_cmap_tab[0].platform_id = 1;    /* Macintosh */
1094    new_cmap_tab[0].encoding_id = 0;    /* Symbol; ignore code page */
1095    new_cmap_tab[0].format = (TTF_USHORT) (new_glyphs_count < 256 ? 0   /* byte encoding */
1096                                           : 6);        /* trimmed table mapping */
1097    new_cmap_tab[1].platform_id = 3;    /* Microsoft */
1098    new_cmap_tab[1].encoding_id = 0;    /* Symbol; ignore code page */
1099    new_cmap_tab[1].format = 4; /* segment mapping to delta */
1100}
1101
1102static void ttf_write_cmap(PDF pdf)
1103{
1104    cmap_entry *ce;
1105    long offset;
1106    dirtab_entry *tab = ttf_name_lookup("cmap", true);
1107    ttf_select_cmap();
1108    ttf_reset_chksm(pdf, tab);
1109    (void) put_ushort(0);       /* table version number (0) */
1110    (void) put_ushort(NEW_CMAP_SIZE);   /* number of encoding tables */
1111    offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH;
1112    for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
1113        ce->offset = (TTF_ULONG) offset;
1114        switch (ce->format) {
1115        case 0:
1116            offset += BYTE_ENCODING_LENGTH;
1117            break;
1118        case 4:
1119            offset += SEG_MAP_DELTA_LENGTH;
1120            break;
1121        case 6:
1122            offset += TRIMMED_TABLE_MAP_LENGTH;
1123            break;
1124        default:
1125            luatex_fail("invalid format (it should not have happened)");
1126        }
1127        (void) put_ushort(ce->platform_id);
1128        (void) put_ushort(ce->encoding_id);
1129        put_ulong((long) ce->offset);
1130    }
1131    for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
1132        switch (ce->format) {
1133        case 0:
1134            ttf_byte_encoding(pdf);
1135            break;
1136        case 4:
1137            ttf_seg_map_delta(pdf);
1138            break;
1139        case 6:
1140            ttf_trimmed_table_map(pdf);
1141            break;
1142        }
1143    }
1144    ttf_set_chksm(pdf, tab);
1145}
1146
1147@
1148@c
1149static int prepend_subset_tags(int index, char *p)
1150{
1151    boolean is_unicode;
1152    int i;
1153    assert(index >= 0 && index < name_record_num && fd_cur->subset_tag != NULL);
1154    is_unicode = (name_tab[index].platform_id == 3);
1155    if (is_unicode) {
1156        for (i = 0; i < 6; ++i) {
1157            *p++ = 0;
1158            *p++ = fd_cur->subset_tag[i];
1159        }
1160        *p++ = 0;
1161        *p++ = '+';
1162        return 14;
1163    } else {
1164        strncpy(p, fd_cur->subset_tag, 6);
1165        p += 6;
1166        *p++ = '+';
1167        return 7;
1168    }
1169}
1170
1171
1172static void ttf_write_name(PDF pdf)
1173{
1174    int i, l;
1175    char *p;
1176    int new_name_buf_size;
1177    char *new_name_buf;
1178    name_record *n;
1179    dirtab_entry *tab = ttf_name_lookup("name", true);
1180    if (is_subsetted(fd_cur->fm)) {
1181        l = 0;
1182        for (i = 0; i < name_record_num; i++)
1183            l += name_tab[i].length + 14;       /* maximum lengh of new stogare area */
1184        new_name_buf = xtalloc((unsigned) l, char);
1185        /* additional space for subset tags */
1186        p = new_name_buf;
1187        for (i = 0; i < name_record_num; i++) {
1188            n = name_tab + i;
1189            n->new_offset = (TTF_USHORT) (p - new_name_buf);
1190            if ((n->name_id == 1 || n->name_id == 3 ||
1191                 n->name_id == 4 || n->name_id == 6) &&
1192                ((n->platform_id == 1 && n->encoding_id == 0) ||
1193                 (n->platform_id == 3 && n->encoding_id == 0) ||
1194                 (n->platform_id == 3 && n->encoding_id == 1))) {
1195                l = prepend_subset_tags(i, p);
1196                p += l;
1197            } else
1198                l = 0;
1199            memcpy(p, name_buf + n->offset, n->length);
1200            p += n->length;
1201            n->new_length = (TTF_USHORT) (n->length + l);
1202        }
1203        new_name_buf_size = (int) (p - new_name_buf);
1204    } else {
1205        new_name_buf = name_buf;
1206        new_name_buf_size = name_buf_size;
1207    }
1208    ttf_reset_chksm(pdf, tab);
1209    (void) put_ushort(0);       /* Format selector */
1210    (void) put_ushort(name_record_num);
1211    (void) put_ushort(3 * TTF_USHORT_SIZE +
1212                      name_record_num * 6 * TTF_USHORT_SIZE);
1213    for (i = 0; i < name_record_num; i++) {
1214        (void) put_ushort(name_tab[i].platform_id);
1215        (void) put_ushort(name_tab[i].encoding_id);
1216        (void) put_ushort(name_tab[i].language_id);
1217        (void) put_ushort(name_tab[i].name_id);
1218        (void) put_ushort(name_tab[i].new_length);
1219        (void) put_ushort(name_tab[i].new_offset);
1220    }
1221    for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
1222        put_char(*p);
1223    ttf_set_chksm(pdf, tab);
1224    if (new_name_buf != name_buf)
1225        xfree(new_name_buf);
1226}
1227
1228@
1229@c
1230static void ttf_write_dirtab(PDF pdf)
1231{
1232    dirtab_entry *tab;
1233    TTF_ULONG i, k;
1234    char *p;
1235    const int save_offset = ttf_offset();
1236    ttf_seek_outbuf(TABDIR_OFF);
1237    if (is_subsetted(fd_cur->fm)) {
1238        for (i = 0; i < DEFAULT_NTABS; i++) {
1239            tab = ttf_name_lookup(newtabnames[i], false);
1240            if (tab == NULL)
1241                continue;
1242            for (k = 0; k < 4; k++)
1243                put_char(tab->tag[k]);
1244            put_ulong((long) tab->checksum);
1245            put_ulong((long) tab->offset);
1246            put_ulong((long) tab->length);
1247        }
1248    } else {
1249        for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
1250            for (k = 0; k < 4; k++)
1251                put_char(tab->tag[k]);
1252            put_ulong((long) tab->checksum);
1253            put_ulong((long) tab->offset);
1254            put_ulong((long) tab->length);
1255        }
1256    }
1257    /* adjust checkSumAdjustment */
1258    tmp_ulong = 0;
1259    checksum = 0;
1260    for (p = (char *) pdf->fb->data, i = 0; i < (unsigned) save_offset;) {
1261        tmp_ulong = (tmp_ulong << 8) + (TTF_ULONG) * p++;
1262        i++;
1263        if (i % 4 == 0) {
1264            checksum += tmp_ulong;
1265            tmp_ulong = 0;
1266        }
1267    }
1268    if (i % 4 != 0) {
1269        luatex_warn("font length is not a multiple of 4 (%li)", i);
1270        checksum <<= 8 * (4 - i % 4);
1271    }
1272    k = 0xB1B0AFBA - checksum;
1273    ttf_seek_outbuf((int) checkSumAdjustment_offset);
1274    put_ulong((long) k);
1275    ttf_seek_outbuf(save_offset);
1276}
1277
1278@
1279@c
1280static void ttf_write_glyf(PDF pdf)
1281{
1282    long *id, k;
1283    TTF_USHORT idx;
1284    TTF_USHORT flags;
1285    dirtab_entry *tab = ttf_name_lookup("glyf", true);
1286    const long glyf_offset = (long) tab->offset;
1287    const long new_glyf_offset = ttf_offset();
1288    ttf_reset_chksm(pdf, tab);
1289    for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1290        glyph_tab[*id].newoffset = ttf_offset() - new_glyf_offset;
1291        if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
1292            ttf_seek_off(glyf_offset + glyph_tab[*id].offset);
1293            k = copy_short();
1294            ttf_ncopy(pdf, 4 * TTF_FWORD_SIZE);
1295            if (k < 0) {
1296                do {
1297                    flags = copy_ushort();
1298                    idx = get_ushort();
1299                    if (glyph_tab[idx].newindex < 0) {
1300                        glyph_tab[idx].newindex = (TTF_SHORT) new_glyphs_count;
1301                        glyph_index[new_glyphs_count++] = idx;
1302                        /*
1303                           N.B.: Here we change |new_glyphs_count|,
1304                           which appears in the condition of the |for| loop
1305                         */
1306                    }
1307                    (void) put_ushort(glyph_tab[idx].newindex);
1308                    if (flags & ARG_1_AND_2_ARE_WORDS)
1309                        ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE);
1310                    else
1311                        ttf_ncopy(pdf, TTF_USHORT_SIZE);
1312                    if (flags & WE_HAVE_A_SCALE)
1313                        ttf_ncopy(pdf, TTF_F2DOT14_SIZE);
1314                    else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
1315                        ttf_ncopy(pdf, 2 * TTF_F2DOT14_SIZE);
1316                    else if (flags & WE_HAVE_A_TWO_BY_TWO)
1317                        ttf_ncopy(pdf, 4 * TTF_F2DOT14_SIZE);
1318                } while (flags & MORE_COMPONENTS);
1319                if (flags & WE_HAVE_INSTRUCTIONS)
1320                    ttf_ncopy(pdf, copy_ushort());
1321            } else
1322                ttf_ncopy(pdf, (int)
1323                          (glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
1324                           TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE));
1325        }
1326    }
1327    last_glyf_offset = (TTF_ULONG) ttf_offset() - (TTF_ULONG) new_glyf_offset;
1328    ttf_set_chksm(pdf, tab);
1329}
1330
1331@ Reindexing glyphs: we append index of used glyphs to |glyph_index|
1332 while going through |ttfenc_tab|. After appending a new entry to
1333 |glyph_index| we set field |newindex| of corresponding entries in both
1334 |glyph_tab| and |ttfenc_tab| to the newly created index.
1335
1336@c
1337static void ttf_reindex_glyphs(void)
1338{
1339    ttfenc_entry *e;
1340    glyph_entry *glyph;
1341    int index;
1342    long *t;
1343    ttf_cmap_entry *cmap = NULL;
1344    boolean cmap_not_found = false;
1345
1346    for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) {
1347        e->newindex = 0;        /* index of ".notdef" glyph */
1348
1349        /* handle case of subfonts first */
1350        if (is_subfont(fd_cur->fm)) {
1351            if (e->code == -1)
1352                continue;
1353            assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1);
1354            if (cmap == NULL && !cmap_not_found) {
1355                cmap =
1356                    ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid,
1357                                  fd_cur->fm->eid, true);
1358                if (cmap == NULL)
1359                    cmap_not_found = true;
1360            }
1361            if (cmap == NULL)
1362                continue;
1363            t = cmap->table;
1364            assert(t != NULL && e->code < 0x10000);
1365            if (t[e->code] < 0) {
1366                luatex_warn
1367                    ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef",
1368                     fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code);
1369                continue;
1370            }
1371            assert(t[e->code] >= 0 && t[e->code] < glyphs_count);       /* t has been read from ttf */
1372            glyph = glyph_tab + t[e->code];
1373            goto append_new_glyph;
1374        }
1375
1376        /* handle case of reencoded fonts */
1377        if (e->name == notdef)
1378            continue;
1379        /* scan form `index123' */
1380        if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) {
1381            if (index >= glyphs_count) {
1382                luatex_warn("`%s' out of valid range [0..%i)",
1383                            e->name, glyphs_count);
1384                continue;
1385            }
1386            glyph = glyph_tab + index;
1387            goto append_new_glyph;
1388        }
1389        /* scan form `uniABCD' */
1390        if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
1391            if (cmap == NULL && !cmap_not_found) {
1392                /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */
1393                cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false);
1394                if (cmap == NULL)
1395                    cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false);
1396                if (cmap == NULL) {
1397                    luatex_warn
1398                        ("no unicode mapping found, all `uniXXXX' names will be ignored");
1399                    cmap_not_found = true;      /* once only */
1400                }
1401            }
1402            if (cmap == NULL)
1403                continue;
1404            t = cmap->table;
1405            assert(t != NULL);
1406            if (t[index] != -1) {
1407                if (t[index] >= glyphs_count) {
1408                    luatex_warn
1409                        ("`%s' is mapped to index %li which is out of valid range [0..%i)",
1410                         e->name, t[index], glyphs_count);
1411                    continue;
1412                }
1413                glyph = glyph_tab + t[index];
1414                goto append_new_glyph;
1415            } else {
1416                luatex_warn("`unicode %s%.4X' is not mapped to any glyph",
1417                            GLYPH_PREFIX_UNICODE, index);
1418                continue;
1419            }
1420        }
1421        /* look up by name */
1422        for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
1423            if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
1424                break;
1425        if (!(glyph - glyph_tab < glyphs_count)) {
1426            luatex_warn("glyph `%s' not found", e->name);
1427            continue;
1428        }
1429      append_new_glyph:
1430        assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count);
1431        if (glyph->newindex < 0) {
1432            glyph_index[new_glyphs_count] = (short) (glyph - glyph_tab);
1433            glyph->newindex = (TTF_SHORT) new_glyphs_count;
1434            new_glyphs_count++;
1435        }
1436        e->newindex = glyph->newindex;
1437    }
1438}
1439
1440@  To calculate the checkSum for the 'head' table which itself includes the
1441   checkSumAdjustment entry for the entire font, do the following:
1442
1443     \item Set the checkSumAdjustment to 0.
1444     \item  Calculate the checksum for all the tables including the 'head' table
1445       and enter that value into the table directory.
1446     \item  Calculate the checksum for the entire font.
1447     \item  Subtract that value from the hex value B1B0AFBA.
1448     \item  Store the result in checkSumAdjustment.
1449
1450   The checkSum for the 'head table which includes the checkSumAdjustment
1451   entry for the entire font is now incorrect. That is not a problem. Do not
1452   change it. An application attempting to verify that the 'head' table has
1453   not changed should calculate the checkSum for that table by not including
1454   the checkSumAdjustment value, and compare the result with the entry in the
1455   table directory.
1456
1457   The table directory also includes the offset of the associated tagged
1458   table from the beginning of the font file and the length of that table.
1459
1460
1461@c
1462static void ttf_write_head(PDF pdf)
1463{
1464    dirtab_entry *tab;
1465    tab = ttf_seek_tab("head", 0);
1466    ttf_reset_chksm(pdf, tab);
1467    ttf_ncopy(pdf, 2 * TTF_FIXED_SIZE);
1468    checkSumAdjustment_offset = (TTF_ULONG) ttf_offset();
1469    put_ulong(0);
1470    ttf_skip(TTF_ULONG_SIZE);   /* skip checkSumAdjustment */
1471    ttf_ncopy(pdf, TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 +
1472              4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
1473    if (is_subsetted(fd_cur->fm)) {
1474        (void) put_short(loca_format);
1475        (void) put_short(0);
1476    } else
1477        ttf_ncopy(pdf, 2 * TTF_SHORT_SIZE);
1478    ttf_set_chksm(pdf, tab);
1479}
1480
1481@
1482@c
1483static void ttf_write_hhea(PDF pdf)
1484{
1485    dirtab_entry *tab;
1486    tab = ttf_seek_tab("hhea", 0);
1487    ttf_reset_chksm(pdf, tab);
1488    ttf_ncopy(pdf, TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE +
1489              3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE);
1490    (void) put_ushort(new_glyphs_count);
1491    ttf_set_chksm(pdf, tab);
1492}
1493
1494@
1495@c
1496static void ttf_write_htmx(PDF pdf)
1497{
1498    long *id;
1499    dirtab_entry *tab = ttf_seek_tab("hmtx", 0);
1500    ttf_reset_chksm(pdf, tab);
1501    for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1502        put_ufword(glyph_tab[*id].advWidth);
1503        put_ufword(glyph_tab[*id].lsb);
1504    }
1505    ttf_set_chksm(pdf, tab);
1506}
1507
1508@
1509@c
1510static void ttf_write_loca(PDF pdf)
1511{
1512    long *id;
1513    dirtab_entry *tab = ttf_seek_tab("loca", 0);
1514    ttf_reset_chksm(pdf, tab);
1515    loca_format = 0;
1516    if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
1517        loca_format = 1;
1518    else
1519        for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1520            if (glyph_tab[*id].newoffset & 1) {
1521                loca_format = 1;
1522                break;
1523            }
1524    if (loca_format != 0) {
1525        for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1526            put_ulong(glyph_tab[*id].newoffset);
1527        put_ulong((long) last_glyf_offset);
1528    } else {
1529        for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
1530            (void) put_ushort(glyph_tab[*id].newoffset / 2);
1531        (void) put_ushort((long) (last_glyf_offset / 2));
1532    }
1533    ttf_set_chksm(pdf, tab);
1534}
1535
1536@
1537@c
1538static void ttf_write_mapx(PDF pdf)
1539{
1540    dirtab_entry *tab = ttf_seek_tab("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
1541    ttf_reset_chksm(pdf, tab);
1542    put_fixed(0x00010000);
1543    (void) put_ushort(new_glyphs_count);
1544    ttf_ncopy(pdf, 13 * TTF_USHORT_SIZE);
1545    ttf_set_chksm(pdf, tab);
1546}
1547
1548@
1549@c
1550static void ttf_write_OS2(PDF pdf)
1551{
1552    dirtab_entry *tab = ttf_seek_tab("OS/2", 0);
1553    TTF_USHORT version;
1554    ttf_reset_chksm(pdf, tab);
1555    version = get_ushort();
1556    if (version > 3)
1557        luatex_fail("unknown version of OS/2 table (%.4X)", version);
1558    (void) put_ushort(0x0001);  /* fix version to 1 */
1559    ttf_ncopy(pdf,
1560              2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE);
1561    ttf_skip(4 * TTF_ULONG_SIZE);       /* ulUnicodeRange 1--4 */
1562    put_ulong(0x00000003);      /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
1563    put_ulong(0x10000000);      /* Private Use (0xE000--0xF8FF) */
1564    put_ulong(0x00000000);
1565    put_ulong(0x00000000);
1566    ttf_ncopy(pdf, 4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE);        /* achVendID + fsSelection */
1567    ttf_skip(2 * TTF_USHORT_SIZE);
1568    (void) put_ushort(0x0000);  /* usFirstCharIndex */
1569    (void) put_ushort(0xF0FF);  /* usLastCharIndex */
1570    ttf_ncopy(pdf, 5 * TTF_USHORT_SIZE);
1571    /* for version 0 the OS/2 table ends here, the rest is for version 1 */
1572    put_ulong(0x80000000);      /* Symbol Character Set---don't use any code page */
1573    put_ulong(0x00000000);
1574    ttf_set_chksm(pdf, tab);
1575}
1576
1577@
1578@c
1579static boolean unsafe_name(const char *s)
1580{
1581    const char **p;
1582    for (p = ambiguous_names; *p != NULL; p++)
1583        if (strcmp(s, *p) == 0)
1584            return true;
1585    return false;
1586}
1587
1588static void ttf_write_post(PDF pdf)
1589{
1590    dirtab_entry *tab = ttf_seek_tab("post", TTF_FIXED_SIZE);
1591    glyph_entry *glyph;
1592    const char *s;
1593    long *id;
1594    int k, l;
1595    ttf_reset_chksm(pdf, tab);
1596    if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) {
1597        put_fixed(0x00030000);
1598        ttf_ncopy(pdf,
1599                  TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1600    } else {
1601        put_fixed(0x00020000);
1602        ttf_ncopy(pdf,
1603                  TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
1604        (void) put_ushort(new_glyphs_count);
1605        k = 0;
1606        for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1607            glyph = glyph_tab + *id;
1608            if (glyph->name_index >= NMACGLYPHS || unsafe_name(glyph->name))
1609                glyph->name_index = (TTF_USHORT) (NMACGLYPHS + k++);
1610            (void) put_ushort(glyph->name_index);
1611        }
1612        for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
1613            glyph = glyph_tab + *id;
1614            if (glyph->name_index >= NMACGLYPHS) {
1615                s = glyph->name;
1616                l = (int) strlen(s);
1617                put_byte(l);
1618                while (l-- > 0)
1619                    put_char(*s++);
1620            }
1621        }
1622    }
1623    ttf_set_chksm(pdf, tab);
1624}
1625
1626@
1627@c
1628static void ttf_init_font(PDF pdf, int n)
1629{
1630    int i, k;
1631    for (i = 1, k = 0; i <= n; i <<= 1, k++);
1632    put_fixed(0x00010000);      /* font version */
1633    (void) put_ushort(n);       /* number of tables */
1634    (void) put_ushort(i << 3);  /* search range */
1635    (void) put_ushort(k - 1);   /* entry selector */
1636    (void) put_ushort((n << 4) - (i << 3));     /* range shift */
1637    ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE);
1638}
1639
1640@
1641@c
1642static void ttf_subset_font(PDF pdf)
1643{
1644    ttf_init_font(pdf, new_ntabs);
1645    if (ttf_name_lookup("PCLT", false) != NULL)
1646        ttf_copytab(pdf, "PCLT");
1647    if (ttf_name_lookup("fpgm", false) != NULL)
1648        ttf_copytab(pdf, "fpgm");
1649    if (ttf_name_lookup("cvt ", false) != NULL)
1650        ttf_copytab(pdf, "cvt ");
1651    if (ttf_name_lookup("prep", false) != NULL)
1652        ttf_copytab(pdf, "prep");
1653    ttf_reindex_glyphs();
1654    ttf_write_glyf(pdf);
1655    ttf_write_loca(pdf);
1656    ttf_write_OS2(pdf);
1657    ttf_write_head(pdf);
1658    ttf_write_hhea(pdf);
1659    ttf_write_htmx(pdf);
1660    ttf_write_mapx(pdf);
1661    ttf_write_name(pdf);
1662    ttf_write_post(pdf);
1663    ttf_write_cmap(pdf);
1664    ttf_write_dirtab(pdf);
1665}
1666
1667@
1668@c
1669static void ttf_copy_font(PDF pdf)
1670{
1671    dirtab_entry *tab;
1672    ttf_init_font(pdf, ntabs);
1673    for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
1674        if (strncmp(tab->tag, "head", 4) == 0)
1675            ttf_write_head(pdf);
1676        else
1677            ttf_copytab(pdf, tab->tag);
1678    }
1679    ttf_write_dirtab(pdf);
1680}
1681
1682@
1683@c
1684void writettf(PDF pdf, fd_entry * fd)
1685{
1686    int callback_id;
1687    int file_opened = 0;
1688    fd_cur = fd;                /* |fd_cur| is global inside \.{writettf.w} */
1689    assert(fd_cur->fm != NULL);
1690    assert(is_truetype(fd_cur->fm));
1691    assert(is_included(fd_cur->fm));
1692
1693    if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL)
1694        && !is_subfont(fd_cur->fm)) {
1695        luatex_fail("Subset TrueType must be a reencoded or a subfont");
1696    }
1697    ttf_curbyte = 0;
1698    ttf_size = 0;
1699
1700    cur_file_name =
1701        luatex_find_file(fd_cur->fm->ff_name, find_truetype_file_callback);
1702    if (cur_file_name == NULL) {
1703        luatex_fail("cannot find TrueType font file for reading (%s)", fd_cur->fm->ff_name);
1704    }
1705    callback_id = callback_defined(read_truetype_file_callback);
1706    if (callback_id > 0) {
1707        if (run_callback(callback_id, "S->bSd", cur_file_name,
1708                         &file_opened, &ttf_buffer, &ttf_size) &&
1709            file_opened && ttf_size > 0) {
1710        } else {
1711            luatex_fail("cannot open TrueType font file for reading (%s)", cur_file_name);
1712        }
1713    } else {
1714        if (!ttf_open(cur_file_name)) {
1715            luatex_fail("cannot open TrueType font file for reading (%s)", cur_file_name);
1716        }
1717        ttf_read_file();
1718        ttf_close();
1719    }
1720    if (tracefilenames) {
1721        if (is_subsetted(fd_cur->fm))
1722            tex_printf("<%s", cur_file_name);
1723        else
1724            tex_printf("<<%s", cur_file_name);
1725    }
1726    fd_cur->ff_found = true;
1727    new_glyphs_count = 2;
1728    new_ntabs = DEFAULT_NTABS;
1729    dir_tab = NULL;
1730    glyph_tab = NULL;
1731    glyph_index = NULL;
1732    glyph_name_buf = NULL;
1733    name_tab = NULL;
1734    name_buf = NULL;
1735    ttf_read_font();
1736
1737    pdf_save_offset(pdf);
1738    pdf_flush(pdf);
1739
1740    if (is_subsetted(fd_cur->fm)) {
1741        ttf_copy_encoding();
1742        ttf_subset_font(pdf);
1743    } else
1744        ttf_copy_font(pdf);
1745    ttf_length = ttf_offset();
1746
1747    xfree(dir_tab);
1748    xfree(glyph_tab);
1749    xfree(glyph_index);
1750    xfree(glyph_name_buf);
1751    xfree(name_tab);
1752    xfree(name_buf);
1753    if (tracefilenames) {
1754        if (is_subsetted(fd_cur->fm))
1755            tex_printf(">");
1756        else
1757            tex_printf(">>");
1758    }
1759    xfree(ttf_buffer);
1760    cur_file_name = NULL;
1761}
1762
1763static void do_writeotf(PDF pdf, fd_entry * fd)
1764{
1765    long i;
1766    dirtab_entry *tab;
1767    (void) fd;
1768    dir_tab = NULL;
1769    glyph_tab = NULL;
1770    if (tracefilenames)
1771        tex_printf("<<%s", cur_file_name);
1772    ttf_read_tabdir();
1773    /* read font parameters */
1774    if (ttf_name_lookup("head", false) != NULL)
1775        ttf_read_head();
1776    if (ttf_name_lookup("hhea", false) != NULL)
1777        ttf_read_hhea();
1778    if (ttf_name_lookup("PCLT", false) != NULL)
1779        ttf_read_pclt();
1780    if (ttf_name_lookup("post", false) != NULL)
1781        ttf_read_post();
1782    /* copy font file */
1783    tab = ttf_seek_tab("CFF ", 0);
1784    for (i = (long) tab->length; i > 0; i--)
1785        copy_char();
1786    xfree(dir_tab);
1787    if (tracefilenames)
1788        tex_printf(">>");
1789}
1790
1791@
1792@c
1793void writeotf(PDF pdf, fd_entry * fd)
1794{
1795    int callback_id;
1796    int file_opened = 0;
1797
1798    fd_cur = fd;
1799    assert(fd_cur->fm != NULL);
1800    assert(is_opentype(fd_cur->fm));
1801    assert(is_included(fd_cur->fm));
1802
1803    ttf_curbyte = 0;
1804    ttf_size = 0;
1805    cur_file_name =
1806        luatex_find_file(fd_cur->fm->ff_name, find_opentype_file_callback);
1807    if (cur_file_name == NULL) {
1808        luatex_fail("cannot find OpenType font file for reading (%s)", fd_cur->fm->ff_name);
1809    }
1810    callback_id = callback_defined(read_opentype_file_callback);
1811    if (callback_id > 0) {
1812        if (run_callback(callback_id, "S->bSd", cur_file_name,
1813                         &file_opened, &ttf_buffer, &ttf_size) &&
1814            file_opened && ttf_size > 0) {
1815        } else {
1816            luatex_fail("cannot open OpenType font file for reading (%s)", cur_file_name);
1817        }
1818    } else {
1819        if (!otf_open(cur_file_name)) {
1820            luatex_fail("cannot open OpenType font file for reading (%s)", cur_file_name);
1821        }
1822        ttf_read_file();
1823        ttf_close();
1824    }
1825
1826    fd_cur->ff_found = true;
1827    do_writeotf(pdf, fd);
1828    xfree(ttf_buffer);
1829    cur_file_name = NULL;
1830}
1831
1832