1% texfont.w
2%
3% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
4%
5% This file is part of LuaTeX.
6%
7% LuaTeX is free software; you can redistribute it and/or modify it under
8% the terms of the GNU General Public License as published by the Free
9% Software Foundation; either version 2 of the License, or (at your
10% option) any later version.
11%
12% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15% License for more details.
16%
17% You should have received a copy of the GNU General Public License along
18% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19
20@* Main font API implementation for the original pascal parts.
21
22Stuff to watch out for:
23
24\item{} Knuth had a |'null_character'| that was used when a character could
25not be found by the |fetch()| routine, to signal an error. This has
26been deleted, but it may mean that the output of luatex is
27incompatible with TeX after |fetch()| has detected an error condition.
28
29\item{} Knuth also had a |font_glue()| optimization. I've removed that
30because it was a bit of dirty programming and it also was
31problematic |if 0 != null|.
32
33@c
34
35
36#include "ptexlib.h"
37#include "lua/luatex-api.h"
38
39@ @c
40#define noDEBUG
41
42#define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f))
43#define do_realloc(a,b,d)    a = xrealloc(a,(unsigned)((unsigned)(b)*sizeof(d)))
44
45texfont **font_tables = NULL;
46
47static int font_arr_max = 0;
48static int font_id_maxval = 0;
49
50@ @c
51static void grow_font_table(int id)
52{
53    int j;
54    if (id >= font_arr_max) {
55        font_bytes +=
56            (int) (((id + 8 - font_arr_max) * (int) sizeof(texfont *)));
57        font_tables =
58            xrealloc(font_tables,
59                     (unsigned) (((unsigned) id + 8) * sizeof(texfont *)));
60        j = 8;
61        while (j--) {
62            font_tables[id + j] = NULL;
63        }
64        font_arr_max = id + 8;
65    }
66}
67
68int new_font_id(void)
69{
70    int i;
71    for (i = 0; i < font_arr_max; i++) {
72        if (font_tables[i] == NULL) {
73            break;
74        }
75    }
76    if (i >= font_arr_max)
77        grow_font_table(i);
78    if (i > font_id_maxval)
79        font_id_maxval = i;
80    return i;
81}
82
83int max_font_id(void)
84{
85    return font_id_maxval;
86}
87
88void set_max_font_id(int i)
89{
90    font_id_maxval = i;
91}
92
93@ @c
94int new_font(void)
95{
96    int k;
97    int id;
98    charinfo *ci;
99    id = new_font_id();
100    font_bytes += (int) sizeof(texfont);
101    /* most stuff is zero */
102    font_tables[id] = xcalloc(1, sizeof(texfont));
103    font_tables[id]->_font_name = NULL;
104    font_tables[id]->_font_area = NULL;
105    font_tables[id]->_font_filename = NULL;
106    font_tables[id]->_font_fullname = NULL;
107    font_tables[id]->_font_psname = NULL;
108    font_tables[id]->_font_encodingname = NULL;
109    font_tables[id]->_font_cidregistry = NULL;
110    font_tables[id]->_font_cidordering = NULL;
111    font_tables[id]->_left_boundary = NULL;
112    font_tables[id]->_right_boundary = NULL;
113    font_tables[id]->_param_base = NULL;
114    font_tables[id]->_math_param_base = NULL;
115
116    set_font_bc(id, 1);         /* ec = 0 */
117    set_hyphen_char(id, '-');
118    set_skew_char(id, -1);
119    font_slant(id) = 0;         /* vertical */
120    font_extend(id) = 1000;     /* normal width */
121
122    /* allocate eight values including 0 */
123    set_font_params(id, 7);
124    for (k = 0; k <= 7; k++) {
125        set_font_param(id, k, 0);
126    }
127    /* character info zero is reserved for notdef */
128    font_tables[id]->characters = new_sa_tree(1, 0);    /* stack size 1, default item value 0 */
129
130    ci = xcalloc(1, sizeof(charinfo));
131    set_charinfo_name(ci, xstrdup(".notdef"));
132    font_tables[id]->charinfo = ci;
133    font_tables[id]->charinfo_size = 1;
134    font_tables[id]->charinfo_cache = NULL;
135
136    return id;
137}
138
139@ @c
140void font_malloc_charinfo(internal_font_number f, int num)
141{
142    int glyph = font_tables[f]->charinfo_size;
143    font_bytes += (int) (num * (int) sizeof(charinfo));
144    do_realloc(font_tables[f]->charinfo, (unsigned) (glyph + num), charinfo);
145    memset(&(font_tables[f]->charinfo[glyph]), 0,
146           (size_t) (num * (int) sizeof(charinfo)));
147    font_tables[f]->charinfo_size += num;
148}
149
150@ @c
151#define find_charinfo_id(f,c) get_sa_item(font_tables[f]->characters,c)
152
153charinfo *get_charinfo(internal_font_number f, int c)
154{
155    sa_tree_item glyph;
156    charinfo *ci;
157    if (proper_char_index(c)) {
158        glyph = get_sa_item(font_tables[f]->characters, c);
159        if (!glyph) {
160
161            int tglyph = ++font_tables[f]->charinfo_count;
162            if (tglyph >= font_tables[f]->charinfo_size) {
163                font_malloc_charinfo(f, 256);
164            }
165            font_tables[f]->charinfo[tglyph].ef = 1000; /* init */
166            set_sa_item(font_tables[f]->characters, c, (sa_tree_item) tglyph, 1);       /* 1= global */
167            glyph = (sa_tree_item) tglyph;
168        }
169        return &(font_tables[f]->charinfo[glyph]);
170    } else if (c == left_boundarychar) {
171        if (left_boundary(f) == NULL) {
172            ci = xcalloc(1, sizeof(charinfo));
173            font_bytes += (int) sizeof(charinfo);
174            set_left_boundary(f, ci);
175        }
176        return left_boundary(f);
177    } else if (c == right_boundarychar) {
178        if (right_boundary(f) == NULL) {
179            ci = xcalloc(1, sizeof(charinfo));
180            font_bytes += (int) sizeof(charinfo);
181            set_right_boundary(f, ci);
182        }
183        return right_boundary(f);
184    }
185    return &(font_tables[f]->charinfo[0]);
186}
187
188@ @c
189static void set_charinfo(internal_font_number f, int c, charinfo * ci)
190{
191    sa_tree_item glyph;
192    if (proper_char_index(c)) {
193        glyph = get_sa_item(font_tables[f]->characters, c);
194        if (glyph) {
195            font_tables[f]->charinfo[glyph] = *ci;
196        } else {
197            luatex_fail("font: %s", "character insertion failed");
198        }
199    } else if (c == left_boundarychar) {
200        set_left_boundary(f, ci);
201    } else if (c == right_boundarychar) {
202        set_right_boundary(f, ci);
203    }
204}
205
206@ @c
207charinfo *copy_charinfo(charinfo * ci)
208{
209    int x, k;
210    kerninfo *kern;
211    liginfo *lig;
212    eight_bits *packet;
213    charinfo *co = NULL;
214    if (ci == NULL)
215        return NULL;
216    co = xmalloc(sizeof(charinfo));
217    memcpy(co, ci, sizeof(charinfo));
218    set_charinfo_used(co, false);
219    co->name = NULL;
220    co->tounicode = NULL;
221    co->packets = NULL;
222    co->ligatures = NULL;
223    co->kerns = NULL;
224    co->vert_variants = NULL;
225    co->hor_variants = NULL;
226    if (ci->name != NULL) {
227        co->name = xstrdup(ci->name);
228    }
229    if (ci->tounicode != NULL) {
230        co->tounicode = xstrdup(ci->tounicode);
231    }
232    /* kerns */
233    if ((kern = get_charinfo_kerns(ci)) != NULL) {
234        x = 0;
235        while (!kern_end(kern[x])) {
236            x++;
237        }
238        x++;
239        co->kerns = xmalloc((unsigned) (x * (int) sizeof(kerninfo)));
240        memcpy(co->kerns, ci->kerns, (size_t) (x * (int) sizeof(kerninfo)));
241    }
242    /* ligs */
243    if ((lig = get_charinfo_ligatures(ci)) != NULL) {
244        x = 0;
245        while (!lig_end(lig[x])) {
246            x++;
247        }
248        x++;
249        co->ligatures = xmalloc((unsigned) (x * (int) sizeof(liginfo)));
250        memcpy(co->ligatures, ci->ligatures,
251               (size_t) (x * (int) sizeof(liginfo)));
252    }
253    /* packets */
254    if ((packet = get_charinfo_packets(ci)) != NULL) {
255        x = vf_packet_bytes(ci);
256        co->packets = xmalloc((unsigned) x);
257        memcpy(co->packets, ci->packets, (size_t) x);
258    }
259
260    /* horizontal and vertical extenders */
261    if (get_charinfo_vert_variants(ci) != NULL) {
262        set_charinfo_vert_variants(co,
263                                   copy_variants(get_charinfo_vert_variants
264                                                 (ci)));
265    }
266    if (get_charinfo_hor_variants(ci) != NULL) {
267        set_charinfo_hor_variants(co,
268                                  copy_variants(get_charinfo_hor_variants(ci)));
269    }
270    x = ci->top_left_math_kerns;
271    co->top_left_math_kerns = x;
272    if (x > 0) {
273        co->top_left_math_kern_array =
274            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
275        for (k = 0; k < co->top_left_math_kerns; k++) {
276            co->top_left_math_kern_array[(2 * k)] =
277                ci->top_left_math_kern_array[(2 * k)];
278            co->top_left_math_kern_array[(2 * k) + 1] =
279                ci->top_left_math_kern_array[(2 * k) + 1];
280        }
281    }
282    x = ci->top_right_math_kerns;
283    co->top_right_math_kerns = x;
284    if (x > 0) {
285        co->top_right_math_kern_array =
286            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
287        for (k = 0; k < co->top_right_math_kerns; k++) {
288            co->top_right_math_kern_array[(2 * k)] =
289                ci->top_right_math_kern_array[(2 * k)];
290            co->top_right_math_kern_array[(2 * k) + 1] =
291                ci->top_right_math_kern_array[(2 * k) + 1];
292        }
293    }
294    x = ci->bottom_right_math_kerns;
295    co->bottom_right_math_kerns = x;
296    if (x > 0) {
297        co->bottom_right_math_kern_array =
298            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
299        for (k = 0; k < co->bottom_right_math_kerns; k++) {
300            co->bottom_right_math_kern_array[(2 * k)] =
301                ci->bottom_right_math_kern_array[(2 * k)];
302            co->bottom_right_math_kern_array[(2 * k) + 1] =
303                ci->bottom_right_math_kern_array[(2 * k) + 1];
304        }
305    }
306    x = ci->bottom_left_math_kerns;
307    co->bottom_left_math_kerns = x;
308    if (x > 0) {
309        co->bottom_left_math_kern_array =
310            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
311        for (k = 0; k < co->bottom_left_math_kerns; k++) {
312            co->bottom_left_math_kern_array[(2 * k)] =
313                ci->bottom_left_math_kern_array[(2 * k)];
314            co->bottom_left_math_kern_array[(2 * k) + 1] =
315                ci->bottom_left_math_kern_array[(2 * k) + 1];
316        }
317    }
318
319
320    return co;
321}
322
323charinfo *char_info(internal_font_number f, int c)
324{
325    if (f > font_id_maxval)
326        return 0;
327    if (proper_char_index(c)) {
328        register int glyph = (int) find_charinfo_id(f, c);
329        return &(font_tables[f]->charinfo[glyph]);
330    } else if (c == left_boundarychar && left_boundary(f) != NULL) {
331        return left_boundary(f);
332    } else if (c == right_boundarychar && right_boundary(f) != NULL) {
333        return right_boundary(f);
334    }
335    return &(font_tables[f]->charinfo[0]);
336}
337
338@ @c
339scaled_whd get_charinfo_whd(internal_font_number f, int c)
340{
341    scaled_whd s;
342    charinfo *i;
343    i = char_info(f, c);
344    s.wd = i->width;
345    s.dp = i->depth;
346    s.ht = i->height;
347    return s;
348}
349
350@ @c
351int char_exists(internal_font_number f, int c)
352{
353    if (f > font_id_maxval)
354        return 0;
355    if (proper_char_index(c)) {
356        return (int) find_charinfo_id(f, c);
357    } else if ((c == left_boundarychar) && has_left_boundary(f)) {
358        return 1;
359    } else if ((c == right_boundarychar) && has_right_boundary(f)) {
360        return 1;
361    }
362    return 0;
363}
364
365@ @c
366#if 0
367static int lua_char_exists_callback(internal_font_number f, int c)
368{
369    int callback_id;
370    lua_State *L = Luas;
371    int ret = 0;
372    callback_id = callback_defined(char_exists_callback);
373    if (callback_id != 0) {
374        if (!get_callback(L, callback_id)) {
375            lua_pop(L, 2);
376            return 0;
377        }
378        lua_pushnumber(L, f);
379        lua_pushnumber(L, c);
380        if (lua_pcall(L, 2, 1, 0) != 0) {       /* two args, 1 result */
381            fprintf(stdout, "error: %s\n", lua_tostring(L, -1));
382            lua_pop(L, 2);
383            error();
384        } else {
385            ret = lua_toboolean(L, -1);
386        }
387    }
388    return ret;
389}
390#endif
391
392@ @c
393extinfo *new_variant(int glyph, int startconnect, int endconnect,
394                     int advance, int repeater)
395{
396    extinfo *ext;
397    ext = xmalloc(sizeof(extinfo));
398    ext->next = NULL;
399    ext->glyph = glyph;
400    ext->start_overlap = startconnect;
401    ext->end_overlap = endconnect;
402    ext->advance = advance;
403    ext->extender = repeater;
404    return ext;
405}
406
407
408@ @c
409static extinfo *copy_variant(extinfo * old)
410{
411    extinfo *ext;
412    ext = xmalloc(sizeof(extinfo));
413    ext->next = NULL;
414    ext->glyph = old->glyph;
415    ext->start_overlap = old->start_overlap;
416    ext->end_overlap = old->end_overlap;
417    ext->advance = old->advance;
418    ext->extender = old->extender;
419    return ext;
420}
421
422@ @c
423static void dump_variant(extinfo * ext)
424{
425    dump_int(ext->glyph);
426    dump_int(ext->start_overlap);
427    dump_int(ext->end_overlap);
428    dump_int(ext->advance);
429    dump_int(ext->extender);
430    return;
431}
432
433
434@ @c
435static extinfo *undump_variant(void)
436{
437    int x;
438    extinfo *ext;
439    undump_int(x);
440    if (x == 0)
441        return NULL;
442    ext = xmalloc(sizeof(extinfo));
443    ext->next = NULL;
444    ext->glyph = x;
445    undump_int(x);
446    ext->start_overlap = x;
447    undump_int(x);
448    ext->end_overlap = x;
449    undump_int(x);
450    ext->advance = x;
451    undump_int(x);
452    ext->extender = x;
453    return ext;
454}
455
456@ @c
457void add_charinfo_vert_variant(charinfo * ci, extinfo * ext)
458{
459    if (ci->vert_variants == NULL) {
460        ci->vert_variants = ext;
461    } else {
462        extinfo *lst = ci->vert_variants;
463        while (lst->next != NULL)
464            lst = lst->next;
465        lst->next = ext;
466    }
467
468}
469
470@ @c
471void add_charinfo_hor_variant(charinfo * ci, extinfo * ext)
472{
473    if (ci->hor_variants == NULL) {
474        ci->hor_variants = ext;
475    } else {
476        extinfo *lst = ci->hor_variants;
477        while (lst->next != NULL)
478            lst = lst->next;
479        lst->next = ext;
480    }
481
482}
483
484@ @c
485extinfo *copy_variants(extinfo * o)
486{
487    extinfo *c, *t = NULL, *h = NULL;
488    while (o != NULL) {
489        c = copy_variant(o);
490        if (h == null)
491            h = c;
492        else
493            t->next = c;
494        t = c;
495        o = o->next;
496    }
497
498    return h;
499}
500
501
502@ @c
503static void dump_charinfo_variants(extinfo * o)
504{
505    while (o != NULL) {
506        dump_variant(o);
507        o = o->next;
508    }
509    dump_int(0);
510    return;
511}
512
513@ @c
514static extinfo *undump_charinfo_variants(void)
515{
516    extinfo *c, *t = NULL, *h = NULL;
517    c = undump_variant();
518    while (c != NULL) {
519        if (h == null)
520            h = c;
521        else
522            t->next = c;
523        t = c;
524        c = undump_variant();
525    }
526    return h;
527}
528
529
530@ Note that mant more small things like this are implemented
531as macros in the header file.
532@c
533void set_charinfo_width(charinfo * ci, scaled val)
534{
535    ci->width = val;
536}
537
538void set_charinfo_height(charinfo * ci, scaled val)
539{
540    ci->height = val;
541}
542
543void set_charinfo_depth(charinfo * ci, scaled val)
544{
545    ci->depth = val;
546}
547
548void set_charinfo_italic(charinfo * ci, scaled val)
549{
550    ci->italic = val;
551}
552
553void set_charinfo_top_accent(charinfo * ci, scaled val)
554{
555    ci->top_accent = val;
556}
557
558void set_charinfo_bot_accent(charinfo * ci, scaled val)
559{
560    ci->bot_accent = val;
561}
562
563void set_charinfo_tag(charinfo * ci, scaled val)
564{
565    ci->tag = (char) val;
566}
567
568void set_charinfo_remainder(charinfo * ci, scaled val)
569{
570    ci->remainder = val;
571}
572
573void set_charinfo_used(charinfo * ci, scaled val)
574{
575    ci->used = (char) val;
576}
577
578void set_charinfo_index(charinfo * ci, scaled val)
579{
580    ci->index = (unsigned short) val;
581}
582
583void set_charinfo_name(charinfo * ci, char *val)
584{
585    xfree(ci->name);
586    ci->name = val;
587}
588
589void set_charinfo_tounicode(charinfo * ci, char *val)
590{
591    xfree(ci->tounicode);
592    ci->tounicode = val;
593}
594
595void set_charinfo_ligatures(charinfo * ci, liginfo * val)
596{
597    dxfree(ci->ligatures, val);
598}
599
600void set_charinfo_kerns(charinfo * ci, kerninfo * val)
601{
602    dxfree(ci->kerns, val);
603}
604
605void set_charinfo_packets(charinfo * ci, eight_bits * val)
606{
607    dxfree(ci->packets, val);
608}
609
610void set_charinfo_ef(charinfo * ci, scaled val)
611{
612    ci->ef = val;
613}
614
615void set_charinfo_lp(charinfo * ci, scaled val)
616{
617    ci->lp = val;
618}
619
620void set_charinfo_rp(charinfo * ci, scaled val)
621{
622    ci->rp = val;
623}
624
625@ @c
626void set_charinfo_vert_variants(charinfo * ci, extinfo * ext)
627{
628    extinfo *c, *lst;
629    if (ci->vert_variants != NULL) {
630        lst = ci->vert_variants;
631        while (lst != NULL) {
632            c = lst->next;
633            free(lst);
634            lst = c;
635        }
636    }
637    ci->vert_variants = ext;
638}
639
640@ @c
641void set_charinfo_hor_variants(charinfo * ci, extinfo * ext)
642{
643    extinfo *c, *lst;
644    if (ci->hor_variants != NULL) {
645        lst = ci->hor_variants;
646        while (lst != NULL) {
647            c = lst->next;
648            free(lst);
649            lst = c;
650        }
651    }
652    ci->hor_variants = ext;
653
654}
655
656@ @c
657int get_charinfo_math_kerns(charinfo * ci, int id)
658{
659
660    int k = 0;                  /* all callers check for |result>0| */
661    if (id == top_left_kern) {
662        k = ci->top_left_math_kerns;
663    } else if (id == bottom_left_kern) {
664        k = ci->bottom_left_math_kerns;
665    } else if (id == bottom_right_kern) {
666        k = ci->bottom_right_math_kerns;
667    } else if (id == top_right_kern) {
668        k = ci->top_right_math_kerns;
669    } else {
670        confusion("get_charinfo_math_kerns");
671    }
672    return k;
673}
674
675@ @c
676void add_charinfo_math_kern(charinfo * ci, int id, scaled ht, scaled krn)
677{
678    int k;
679    if (id == top_left_kern) {
680        k = ci->top_left_math_kerns;
681        do_realloc(ci->top_left_math_kern_array, ((k + 1) * 2), sizeof(scaled));
682        ci->top_left_math_kern_array[(2 * (k))] = ht;
683        ci->top_left_math_kern_array[((2 * (k)) + 1)] = krn;
684        ci->top_left_math_kerns++;
685    } else if (id == bottom_left_kern) {
686        k = ci->bottom_left_math_kerns;
687        do_realloc(ci->bottom_left_math_kern_array, ((k + 1) * 2),
688                   sizeof(scaled));
689        ci->bottom_left_math_kern_array[(2 * (k))] = ht;
690        ci->bottom_left_math_kern_array[(2 * (k)) + 1] = krn;
691        ci->bottom_left_math_kerns++;
692    } else if (id == bottom_right_kern) {
693        k = ci->bottom_right_math_kerns;
694        do_realloc(ci->bottom_right_math_kern_array, ((k + 1) * 2),
695                   sizeof(scaled));
696        ci->bottom_right_math_kern_array[(2 * (k))] = ht;
697        ci->bottom_right_math_kern_array[(2 * (k)) + 1] = krn;
698        ci->bottom_right_math_kerns++;
699    } else if (id == top_right_kern) {
700        k = ci->top_right_math_kerns;
701        do_realloc(ci->top_right_math_kern_array, ((k + 1) * 2),
702                   sizeof(scaled));
703        ci->top_right_math_kern_array[(2 * (k))] = ht;
704        ci->top_right_math_kern_array[(2 * (k)) + 1] = krn;
705        ci->top_right_math_kerns++;
706    } else {
707        confusion("add_charinfo_math_kern");
708    }
709}
710
711
712@ @c
713static void dump_math_kerns(charinfo * ci)
714{
715    int k, l;
716    l = ci->top_left_math_kerns;
717    dump_int(l);
718    for (k = 0; k < l; k++) {
719        dump_int(ci->top_left_math_kern_array[(2 * k)]);
720        dump_int(ci->top_left_math_kern_array[(2 * k) + 1]);
721    }
722    l = ci->bottom_left_math_kerns;
723    dump_int(l);
724    for (k = 0; k < l; k++) {
725        dump_int(ci->bottom_left_math_kern_array[(2 * k)]);
726        dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]);
727    }
728    l = ci->bottom_right_math_kerns;
729    dump_int(l);
730    for (k = 0; k < l; k++) {
731        dump_int(ci->bottom_right_math_kern_array[(2 * k)]);
732        dump_int(ci->bottom_right_math_kern_array[(2 * k) + 1]);
733    }
734    l = ci->top_right_math_kerns;
735    dump_int(l);
736    for (k = 0; k < l; k++) {
737        dump_int(ci->bottom_left_math_kern_array[(2 * k)]);
738        dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]);
739    }
740}
741
742@ @c
743static void undump_math_kerns(charinfo * ci)
744{
745    int k;
746    int x;
747    undump_int(x);
748    ci->top_left_math_kerns = x;
749    if (x > 0)
750        ci->top_left_math_kern_array =
751            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
752    for (k = 0; k < ci->top_left_math_kerns; k++) {
753        undump_int(x);
754        ci->top_left_math_kern_array[(2 * k)] = (scaled) x;
755        undump_int(x);
756        ci->top_left_math_kern_array[(2 * k) + 1] = (scaled) x;
757    }
758    undump_int(x);
759    ci->bottom_left_math_kerns = x;
760    if (x > 0)
761        ci->bottom_left_math_kern_array =
762            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
763    for (k = 0; k < ci->bottom_left_math_kerns; k++) {
764        undump_int(x);
765        ci->bottom_left_math_kern_array[(2 * k)] = (scaled) x;
766        undump_int(x);
767        ci->bottom_left_math_kern_array[(2 * k) + 1] = (scaled) x;
768    }
769    undump_int(x);
770    ci->bottom_right_math_kerns = x;
771    if (x > 0)
772        ci->bottom_right_math_kern_array =
773            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
774    for (k = 0; k < ci->bottom_right_math_kerns; k++) {
775        undump_int(x);
776        ci->bottom_right_math_kern_array[(2 * k)] = (scaled) x;
777        undump_int(x);
778        ci->bottom_right_math_kern_array[(2 * k) + 1] = (scaled) x;
779    }
780    undump_int(x);
781    ci->top_right_math_kerns = x;
782    if (x > 0)
783        ci->top_right_math_kern_array =
784            xmalloc((unsigned) (2 * (int) sizeof(scaled) * x));
785    for (k = 0; k < ci->top_right_math_kerns; k++) {
786        undump_int(x);
787        ci->top_right_math_kern_array[(2 * k)] = (scaled) x;
788        undump_int(x);
789        ci->top_right_math_kern_array[(2 * k) + 1] = (scaled) x;
790    }
791}
792
793
794@ In TeX, extensibles were fairly simple things.
795   This function squeezes a TFM extensible into the vertical extender structures.
796   |advance==0| is a special case for TFM fonts, because finding the proper
797   advance width during tfm reading can be tricky
798
799
800  a small complication arises if |rep| is the only non-zero: it needs to be
801  doubled as a non-repeatable to avoid mayhem */
802
803@c
804void set_charinfo_extensible(charinfo * ci, int top, int bot, int mid, int rep)
805{
806    extinfo *ext;
807    set_charinfo_vert_variants(ci, NULL);       /* clear old */
808    if (bot == 0 && top == 0 && mid == 0 && rep != 0) {
809        ext = new_variant(rep, 0, 0, 0, EXT_NORMAL);
810        add_charinfo_vert_variant(ci, ext);
811        ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
812        add_charinfo_vert_variant(ci, ext);
813        return;
814    }
815    if (bot != 0) {
816        ext = new_variant(bot, 0, 0, 0, EXT_NORMAL);
817        add_charinfo_vert_variant(ci, ext);
818    }
819    if (rep != 0) {
820        ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
821        add_charinfo_vert_variant(ci, ext);
822    }
823    if (mid != 0) {
824        ext = new_variant(mid, 0, 0, 0, EXT_NORMAL);
825        add_charinfo_vert_variant(ci, ext);
826        if (rep != 0) {
827            ext = new_variant(rep, 0, 0, 0, EXT_REPEAT);
828            add_charinfo_vert_variant(ci, ext);
829        }
830    }
831    if (top != 0) {
832        ext = new_variant(top, 0, 0, 0, EXT_NORMAL);
833        add_charinfo_vert_variant(ci, ext);
834    }
835}
836
837@ Note that many more simple things like this are implemented as macros
838in the header file.
839
840@c
841scaled get_charinfo_width(charinfo * ci)
842{
843    return ci->width;
844}
845
846scaled get_charinfo_height(charinfo * ci)
847{
848    return ci->height;
849}
850
851scaled get_charinfo_depth(charinfo * ci)
852{
853    return ci->depth;
854}
855
856scaled get_charinfo_italic(charinfo * ci)
857{
858    return ci->italic;
859}
860
861scaled get_charinfo_top_accent(charinfo * ci)
862{
863    return ci->top_accent;
864}
865
866scaled get_charinfo_bot_accent(charinfo * ci)
867{
868    return ci->bot_accent;
869}
870
871char get_charinfo_tag(charinfo * ci)
872{
873    return ci->tag;
874}
875
876int get_charinfo_remainder(charinfo * ci)
877{
878    return ci->remainder;
879}
880
881char get_charinfo_used(charinfo * ci)
882{
883    return ci->used;
884}
885
886int get_charinfo_index(charinfo * ci)
887{
888    return ci->index;
889}
890
891char *get_charinfo_name(charinfo * ci)
892{
893    return ci->name;
894}
895
896char *get_charinfo_tounicode(charinfo * ci)
897{
898    return ci->tounicode;
899}
900
901liginfo *get_charinfo_ligatures(charinfo * ci)
902{
903    return ci->ligatures;
904}
905
906kerninfo *get_charinfo_kerns(charinfo * ci)
907{
908    return ci->kerns;
909}
910
911eight_bits *get_charinfo_packets(charinfo * ci)
912{
913    return ci->packets;
914}
915
916int get_charinfo_ef(charinfo * ci)
917{
918    return ci->ef;
919}
920
921int get_charinfo_rp(charinfo * ci)
922{
923    return ci->rp;
924}
925
926int get_charinfo_lp(charinfo * ci)
927{
928    return ci->lp;
929}
930
931extinfo *get_charinfo_vert_variants(charinfo * ci)
932{
933    extinfo *w = NULL;
934    if (ci->vert_variants != NULL)
935        w = ci->vert_variants;
936    return w;
937}
938
939extinfo *get_charinfo_hor_variants(charinfo * ci)
940{
941    extinfo *w = NULL;
942    if (ci->hor_variants != NULL)
943        w = ci->hor_variants;
944    return w;
945}
946
947
948scaled char_width(internal_font_number f, int c)
949{
950    charinfo *ci = char_info(f, c);
951    scaled w = get_charinfo_width(ci);
952    return w;
953}
954
955scaled calc_char_width(internal_font_number f, int c, int ex)
956{
957    charinfo *ci = char_info(f, c);
958    scaled w = get_charinfo_width(ci);
959    //printf("ex=%d\n",ex);
960    if (ex != 0)
961        w = round_xn_over_d(w, 1000 + ex, 1000);
962    return w;
963}
964
965scaled char_depth(internal_font_number f, int c)
966{
967    charinfo *ci = char_info(f, c);
968    scaled w = get_charinfo_depth(ci);
969    return w;
970}
971
972scaled char_height(internal_font_number f, int c)
973{
974    charinfo *ci = char_info(f, c);
975    scaled w = get_charinfo_height(ci);
976    return w;
977}
978
979scaled char_italic(internal_font_number f, int c)
980{
981    charinfo *ci = char_info(f, c);
982    return get_charinfo_italic(ci);
983}
984
985scaled char_top_accent(internal_font_number f, int c)
986{
987    charinfo *ci = char_info(f, c);
988    return get_charinfo_top_accent(ci);
989}
990
991scaled char_bot_accent(internal_font_number f, int c)
992{
993    charinfo *ci = char_info(f, c);
994    return get_charinfo_bot_accent(ci);
995}
996
997
998int char_remainder(internal_font_number f, int c)
999{
1000    charinfo *ci = char_info(f, c);
1001    return get_charinfo_remainder(ci);
1002}
1003
1004char char_tag(internal_font_number f, int c)
1005{
1006    charinfo *ci = char_info(f, c);
1007    return get_charinfo_tag(ci);
1008}
1009
1010char char_used(internal_font_number f, int c)
1011{
1012    charinfo *ci = char_info(f, c);
1013    return get_charinfo_used(ci);
1014}
1015
1016char *char_name(internal_font_number f, int c)
1017{
1018    charinfo *ci = char_info(f, c);
1019    return get_charinfo_name(ci);
1020}
1021
1022int char_index(internal_font_number f, int c)
1023{
1024    charinfo *ci = char_info(f, c);
1025    return get_charinfo_index(ci);
1026}
1027
1028liginfo *char_ligatures(internal_font_number f, int c)
1029{
1030    charinfo *ci = char_info(f, c);
1031    return get_charinfo_ligatures(ci);
1032}
1033
1034kerninfo *char_kerns(internal_font_number f, int c)
1035{
1036    charinfo *ci = char_info(f, c);
1037    return get_charinfo_kerns(ci);
1038}
1039
1040eight_bits *char_packets(internal_font_number f, int c)
1041{
1042    charinfo *ci = char_info(f, c);
1043    return get_charinfo_packets(ci);
1044}
1045
1046@ @c
1047void set_font_params(internal_font_number f, int b)
1048{
1049    int i;
1050    i = font_params(f);
1051    if (i != b) {
1052        font_bytes +=
1053            (int) ((b - (int) font_params(f) + 1) * (int) sizeof(scaled));
1054        do_realloc(param_base(f), (b + 2), int);
1055        font_params(f) = b;
1056        if (b > i) {
1057            while (i < b) {
1058                i++;
1059                set_font_param(f, i, 0);
1060            }
1061        }
1062    }
1063}
1064
1065@ @c
1066void set_font_math_params(internal_font_number f, int b)
1067{
1068    int i;
1069    i = font_math_params(f);
1070    if (i != b) {
1071        font_bytes +=
1072            ((b - (int) font_math_params(f) + 1) * (int) sizeof(scaled));
1073        do_realloc(math_param_base(f), (b + 2), int);
1074        font_math_params(f) = b;
1075        if (b > i) {
1076            while (i < b) {
1077                i++;
1078                set_font_math_param(f, i, undefined_math_parameter);
1079            }
1080        }
1081    }
1082}
1083
1084
1085@ @c
1086int copy_font(int f)
1087{
1088    int i, ci_cnt, ci_size;
1089    charinfo *ci;
1090    int k = new_font();
1091
1092    {
1093        ci = font_tables[k]->charinfo;
1094        ci_cnt = font_tables[k]->charinfo_count;
1095        ci_size = font_tables[k]->charinfo_size;
1096        memcpy(font_tables[k], font_tables[f], sizeof(texfont));
1097        font_tables[k]->charinfo = ci;
1098        font_tables[k]->charinfo_count = ci_cnt;
1099        font_tables[k]->charinfo_size = ci_size;
1100    }
1101
1102    font_malloc_charinfo(k, font_tables[f]->charinfo_count);
1103    set_font_cache_id(k, 0);
1104    set_font_used(k, 0);
1105    set_font_touched(k, 0);
1106
1107    font_tables[k]->_font_name = NULL;
1108    font_tables[k]->_font_filename = NULL;
1109    font_tables[k]->_font_fullname = NULL;
1110    font_tables[k]->_font_psname = NULL;
1111    font_tables[k]->_font_encodingname = NULL;
1112    font_tables[k]->_font_area = NULL;
1113    font_tables[k]->_font_cidregistry = NULL;
1114    font_tables[k]->_font_cidordering = NULL;
1115    font_tables[k]->_left_boundary = NULL;
1116    font_tables[k]->_right_boundary = NULL;
1117
1118    set_font_name(k, xstrdup(font_name(f)));
1119    if (font_filename(f) != NULL)
1120        set_font_filename(k, xstrdup(font_filename(f)));
1121    if (font_fullname(f) != NULL)
1122        set_font_fullname(k, xstrdup(font_fullname(f)));
1123    if (font_psname(f) != NULL)
1124        set_font_psname(k, xstrdup(font_psname(f)));
1125    if (font_encodingname(f) != NULL)
1126        set_font_encodingname(k, xstrdup(font_encodingname(f)));
1127    if (font_area(f) != NULL)
1128        set_font_area(k, xstrdup(font_area(f)));
1129    if (font_cidregistry(f) != NULL)
1130        set_font_cidregistry(k, xstrdup(font_cidregistry(f)));
1131    if (font_cidordering(f) != NULL)
1132        set_font_cidordering(k, xstrdup(font_cidordering(f)));
1133
1134    i = (int) (sizeof(*param_base(f)) * (unsigned) (font_params(f)+1));
1135    font_bytes += i;
1136    param_base(k) = xmalloc((unsigned) (i+1));
1137    memcpy(param_base(k), param_base(f), (size_t) (i));
1138
1139    if (font_math_params(f) > 0) {
1140        i = (int) (sizeof(*math_param_base(f)) *
1141                   (unsigned) font_math_params(f));
1142        font_bytes += i;
1143        math_param_base(k) = xmalloc((unsigned) i);
1144        memcpy(math_param_base(k), math_param_base(f), (size_t) i);
1145    }
1146
1147    for (i = 0; i <= font_tables[f]->charinfo_count; i++) {
1148        ci = copy_charinfo(&font_tables[f]->charinfo[i]);
1149        font_tables[k]->charinfo[i] = *ci;
1150    }
1151
1152    if (left_boundary(f) != NULL) {
1153        ci = copy_charinfo(left_boundary(f));
1154        set_charinfo(k, left_boundarychar, ci);
1155    }
1156
1157    if (right_boundary(f) != NULL) {
1158        ci = copy_charinfo(right_boundary(f));
1159        set_charinfo(k, right_boundarychar, ci);
1160    }
1161    /* not updated yet: */
1162    font_tables[k]->charinfo_count = font_tables[f]->charinfo_count;
1163    return k;
1164}
1165
1166@ @c
1167void delete_font(int f)
1168{
1169    int i;
1170    charinfo *co;
1171    assert(f > 0);
1172    if (font_tables[f] != NULL) {
1173        set_font_name(f, NULL);
1174        set_font_filename(f, NULL);
1175        set_font_fullname(f, NULL);
1176        set_font_psname(f, NULL);
1177        set_font_encodingname(f, NULL);
1178        set_font_area(f, NULL);
1179        set_font_cidregistry(f, NULL);
1180        set_font_cidordering(f, NULL);
1181        set_left_boundary(f, NULL);
1182        set_right_boundary(f, NULL);
1183
1184        for (i = font_bc(f); i <= font_ec(f); i++) {
1185            if (quick_char_exists(f, i)) {
1186                co = char_info(f, i);
1187                set_charinfo_name(co, NULL);
1188                set_charinfo_tounicode(co, NULL);
1189                set_charinfo_packets(co, NULL);
1190                set_charinfo_ligatures(co, NULL);
1191                set_charinfo_kerns(co, NULL);
1192                set_charinfo_vert_variants(co, NULL);
1193                set_charinfo_hor_variants(co, NULL);
1194            }
1195        }
1196        /* free .notdef */
1197        set_charinfo_name(font_tables[f]->charinfo + 0, NULL);
1198        free(font_tables[f]->charinfo);
1199        destroy_sa_tree(font_tables[f]->characters);
1200
1201        free(param_base(f));
1202        if (math_param_base(f) != NULL)
1203            free(math_param_base(f));
1204        free(font_tables[f]);
1205        font_tables[f] = NULL;
1206
1207        if (font_id_maxval == f) {
1208            font_id_maxval--;
1209        }
1210    }
1211}
1212
1213@ @c
1214void create_null_font(void)
1215{
1216    int i = new_font();
1217    assert(i == 0);
1218    set_font_name(i, xstrdup("nullfont"));
1219    set_font_area(i, xstrdup(""));
1220    set_font_touched(i, 1);
1221}
1222
1223@ @c
1224boolean is_valid_font(int id)
1225{
1226    int ret = 0;
1227    if (id >= 0 && id <= font_id_maxval && font_tables[id] != NULL)
1228        ret = 1;
1229    return ret;
1230}
1231
1232@ @c
1233boolean cmp_font_area(int id, str_number t)
1234{
1235    char *tt = NULL;
1236    char *tid = font_area(id);
1237    if (t == 0) {
1238        if (tid == NULL || strlen(tid) == 0)
1239            return 1;
1240        else
1241            return 0;
1242    }
1243    tt = makecstring(t);
1244    if ((tt == NULL || strlen(tt) == 0) && (tid == NULL || strlen(tid) == 0))
1245        return 1;
1246    if (tt == NULL || strcmp(tid, tt) != 0)
1247        return 0;
1248    free(tt);
1249    return 1;
1250}
1251
1252@ @c
1253int test_no_ligatures(internal_font_number f)
1254{
1255    int c;
1256    for (c = font_bc(f); c <= font_ec(f); c++) {
1257        if (has_lig(f, c))      /* |char_exists(f,c)| */
1258            return 0;
1259    }
1260    return 1;
1261}
1262
1263@ @c
1264int get_tag_code(internal_font_number f, int c)
1265{
1266    small_number i;
1267    if (char_exists(f, c)) {
1268        i = char_tag(f, c);
1269        if (i == lig_tag)
1270            return 1;
1271        else if (i == list_tag)
1272            return 2;
1273        else if (i == ext_tag)
1274            return 4;
1275        else
1276            return 0;
1277    }
1278    return -1;
1279}
1280
1281@ @c
1282int get_lp_code(internal_font_number f, int c)
1283{
1284    charinfo *ci = char_info(f, c);
1285    return get_charinfo_lp(ci);
1286}
1287
1288int get_rp_code(internal_font_number f, int c)
1289{
1290    charinfo *ci = char_info(f, c);
1291    return get_charinfo_rp(ci);
1292}
1293
1294int get_ef_code(internal_font_number f, int c)
1295{
1296    charinfo *ci = char_info(f, c);
1297    return get_charinfo_ef(ci);
1298}
1299
1300@ @c
1301void set_tag_code(internal_font_number f, int c, int i)
1302{
1303    int fixedi;
1304    charinfo *co;
1305    if (char_exists(f, c)) {
1306        /* |abs(fix_int(i-7,0))| */
1307        fixedi = -(i < -7 ? -7 : (i > 0 ? 0 : i));
1308        co = char_info(f, c);
1309        if (fixedi >= 4) {
1310            if (char_tag(f, c) == ext_tag)
1311                set_charinfo_tag(co, (char_tag(f, c) - ext_tag));
1312            fixedi = fixedi - 4;
1313        }
1314        if (fixedi >= 2) {
1315            if (char_tag(f, c) == list_tag)
1316                set_charinfo_tag(co, (char_tag(f, c) - list_tag));
1317            fixedi = fixedi - 2;
1318        };
1319        if (fixedi >= 1) {
1320            if (has_lig(f, c))
1321                set_charinfo_ligatures(co, NULL);
1322            if (has_kern(f, c))
1323                set_charinfo_kerns(co, NULL);
1324        }
1325    }
1326}
1327
1328
1329@ @c
1330void set_lp_code(internal_font_number f, int c, int i)
1331{
1332    charinfo *co;
1333    if (char_exists(f, c)) {
1334        co = char_info(f, c);
1335        set_charinfo_lp(co, i);
1336    }
1337}
1338
1339void set_rp_code(internal_font_number f, int c, int i)
1340{
1341    charinfo *co;
1342    if (char_exists(f, c)) {
1343        co = char_info(f, c);
1344        set_charinfo_rp(co, i);
1345    }
1346}
1347
1348void set_ef_code(internal_font_number f, int c, int i)
1349{
1350    charinfo *co;
1351    if (char_exists(f, c)) {
1352        co = char_info(f, c);
1353        set_charinfo_ef(co, i);
1354    }
1355}
1356
1357@ @c
1358void set_no_ligatures(internal_font_number f)
1359{
1360    int c;
1361    charinfo *co;
1362
1363    if (font_tables[f]->ligatures_disabled)
1364        return;
1365
1366    co = char_info(f, left_boundarychar);
1367    set_charinfo_ligatures(co, NULL);
1368    co = char_info(f, right_boundarychar);      /* this is weird */
1369    set_charinfo_ligatures(co, NULL);
1370    for (c = 0; c < font_tables[f]->charinfo_count; c++) {
1371        co = font_tables[f]->charinfo + c;
1372        set_charinfo_ligatures(co, NULL);
1373    }
1374    font_tables[f]->ligatures_disabled = 1;
1375}
1376
1377@ @c
1378liginfo get_ligature(internal_font_number f, int lc, int rc)
1379{
1380    int k;
1381    liginfo t, u;
1382    charinfo *co;
1383    t.lig = 0;
1384    t.type = 0;
1385    t.adj = 0;
1386    if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f, lc)))
1387        return t;
1388    k = 0;
1389    co = char_info(f, lc);
1390    while (1) {
1391        u = charinfo_ligature(co, k);
1392        if (lig_end(u))
1393            break;
1394        if (lig_char(u) == rc) {
1395            if (lig_disabled(u)) {
1396                return t;
1397            } else {
1398                return u;
1399            }
1400        }
1401        k++;
1402    }
1403    return t;
1404}
1405
1406
1407@ @c
1408scaled raw_get_kern(internal_font_number f, int lc, int rc)
1409{
1410    int k;
1411    kerninfo u;
1412    charinfo *co;
1413    if (lc == non_boundarychar || rc == non_boundarychar)
1414        return 0;
1415    k = 0;
1416    co = char_info(f, lc);
1417    while (1) {
1418        u = charinfo_kern(co, k);
1419        if (kern_end(u))
1420            break;
1421        if (kern_char(u) == rc) {
1422            if (kern_disabled(u))
1423                return 0;
1424            else
1425                return kern_kern(u);
1426        }
1427        k++;
1428    }
1429    return 0;
1430}
1431
1432
1433@ @c
1434scaled get_kern(internal_font_number f, int lc, int rc)
1435{
1436    if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f, lc)))
1437        return 0;
1438    return raw_get_kern(f, lc, rc);
1439}
1440
1441
1442@ dumping and undumping fonts
1443
1444@c
1445#define dump_string(a)			\
1446    if (a!=NULL) {			\
1447      x = (int)(strlen(a)+1);		\
1448      dump_int(x);  dump_things(*a, x);	\
1449    } else {				\
1450	x = 0; dump_int(x);		\
1451    }
1452
1453static void dump_charinfo(int f, int c)
1454{
1455    charinfo *co;
1456    int x;
1457    liginfo *lig;
1458    kerninfo *kern;
1459    dump_int(c);
1460    co = char_info(f, c);
1461    set_charinfo_used(co, 0);
1462    dump_int(get_charinfo_width(co));
1463    dump_int(get_charinfo_height(co));
1464    dump_int(get_charinfo_depth(co));
1465    dump_int(get_charinfo_italic(co));
1466    dump_int(get_charinfo_top_accent(co));
1467    dump_int(get_charinfo_bot_accent(co));
1468    dump_int(get_charinfo_tag(co));
1469    dump_int(get_charinfo_ef(co));
1470    dump_int(get_charinfo_rp(co));
1471    dump_int(get_charinfo_lp(co));
1472    dump_int(get_charinfo_remainder(co));
1473    dump_int(get_charinfo_used(co));
1474    dump_int(get_charinfo_index(co));
1475    dump_string(get_charinfo_name(co));
1476    dump_string(get_charinfo_tounicode(co));
1477
1478    /* ligatures */
1479    x = 0;
1480    if ((lig = get_charinfo_ligatures(co)) != NULL) {
1481        while (!lig_end(lig[x])) {
1482            x++;
1483        }
1484        x++;
1485        dump_int(x);
1486        dump_things(*lig, x);
1487    } else {
1488        dump_int(x);
1489    }
1490    /* kerns */
1491    x = 0;
1492    if ((kern = get_charinfo_kerns(co)) != NULL) {
1493        while (!kern_end(kern[x])) {
1494            x++;
1495        }
1496        x++;
1497        dump_int(x);
1498        dump_things(*kern, x);
1499    } else {
1500        dump_int(x);
1501    }
1502    /* packets */
1503    x = vf_packet_bytes(co);
1504    dump_int(x);
1505    if (x > 0) {
1506        dump_things(*get_charinfo_packets(co), x);
1507    }
1508
1509    if (get_charinfo_tag(co) == ext_tag) {
1510        dump_charinfo_variants(get_charinfo_vert_variants(co));
1511        dump_charinfo_variants(get_charinfo_hor_variants(co));
1512    }
1513    dump_math_kerns(co);
1514}
1515
1516static void dump_font_entry(texfont * f)
1517{
1518    int x;
1519    dump_int(f->_font_size);
1520    dump_int(f->_font_dsize);
1521    dump_int(f->_font_cidversion);
1522    dump_int(f->_font_cidsupplement);
1523    dump_int(f->_font_ec);
1524    x = (int) f->_font_checksum;
1525    dump_int(x);
1526    dump_int(f->_font_used);
1527    dump_int(f->_font_touched);
1528    dump_int(f->_font_cache_id);
1529    dump_int(f->_font_encodingbytes);
1530    dump_int(f->_font_slant);
1531    dump_int(f->_font_extend);
1532    dump_int(f->font_max_shrink);
1533    dump_int(f->font_max_stretch);
1534    dump_int(f->_font_step);
1535    dump_int(f->_font_auto_expand);
1536    dump_int(f->_font_tounicode);
1537    dump_int(f->_font_type);
1538    dump_int(f->_font_format);
1539    dump_int(f->_font_embedding);
1540    dump_int(f->_font_bc);
1541    dump_int(f->_hyphen_char);
1542    dump_int(f->_skew_char);
1543    dump_int(f->_font_natural_dir);
1544    dump_int(f->_font_params);
1545    dump_int(f->_font_math_params);
1546    dump_int(f->ligatures_disabled);
1547    dump_int(f->_pdf_font_num);
1548    dump_int(f->_pdf_font_attr);
1549}
1550
1551void dump_font(int f)
1552{
1553    int i, x;
1554
1555    set_font_used(f, 0);
1556    font_tables[f]->charinfo_cache = NULL;
1557    dump_font_entry(font_tables[f]);
1558    dump_string(font_name(f));
1559    dump_string(font_area(f));
1560    dump_string(font_filename(f));
1561    dump_string(font_fullname(f));
1562    dump_string(font_psname(f));
1563    dump_string(font_encodingname(f));
1564    dump_string(font_cidregistry(f));
1565    dump_string(font_cidordering(f));
1566
1567    dump_things(*param_base(f), (font_params(f) + 1));
1568
1569    if (font_math_params(f) > 0) {
1570        dump_things(*math_param_base(f), (font_math_params(f) + 1 ));
1571    }
1572    if (has_left_boundary(f)) {
1573        dump_int(1);
1574        dump_charinfo(f, left_boundarychar);
1575    } else {
1576        dump_int(0);
1577    }
1578    if (has_right_boundary(f)) {
1579        dump_int(1);
1580        dump_charinfo(f, right_boundarychar);
1581    } else {
1582        dump_int(0);
1583    }
1584
1585    for (i = font_bc(f); i <= font_ec(f); i++) {
1586        if (quick_char_exists(f, i)) {
1587            dump_charinfo(f, i);
1588        }
1589    }
1590}
1591
1592@ @c
1593static int undump_charinfo(int f)
1594{
1595    charinfo *co;
1596    int x, i;
1597    char *s = NULL;
1598    liginfo *lig = NULL;
1599    kerninfo *kern = NULL;
1600    eight_bits *packet = NULL;
1601
1602    undump_int(i);
1603    co = get_charinfo(f, i);
1604    undump_int(x);
1605    set_charinfo_width(co, x);
1606    undump_int(x);
1607    set_charinfo_height(co, x);
1608    undump_int(x);
1609    set_charinfo_depth(co, x);
1610    undump_int(x);
1611    set_charinfo_italic(co, x);
1612    undump_int(x);
1613    set_charinfo_top_accent(co, x);
1614    undump_int(x);
1615    set_charinfo_bot_accent(co, x);
1616    undump_int(x);
1617    set_charinfo_tag(co, x);
1618    undump_int(x);
1619    set_charinfo_ef(co, x);
1620    undump_int(x);
1621    set_charinfo_rp(co, x);
1622    undump_int(x);
1623    set_charinfo_lp(co, x);
1624    undump_int(x);
1625    set_charinfo_remainder(co, x);
1626    undump_int(x);
1627    set_charinfo_used(co, x);
1628    undump_int(x);
1629    set_charinfo_index(co, x);
1630
1631    /* name */
1632    undump_int(x);
1633    if (x > 0) {
1634        font_bytes += x;
1635        s = xmalloc((unsigned) x);
1636        undump_things(*s, x);
1637    }
1638    set_charinfo_name(co, s);
1639    /* tounicode */
1640    undump_int(x);
1641    if (x > 0) {
1642        font_bytes += x;
1643        s = xmalloc((unsigned) x);
1644        undump_things(*s, x);
1645    }
1646    set_charinfo_tounicode(co, s);
1647    /* ligatures */
1648    undump_int(x);
1649    if (x > 0) {
1650        font_bytes += (int) ((unsigned) x * sizeof(liginfo));
1651        lig = xmalloc((unsigned) ((unsigned) x * sizeof(liginfo)));
1652        undump_things(*lig, x);
1653    }
1654    set_charinfo_ligatures(co, lig);
1655    /* kerns */
1656    undump_int(x);
1657    if (x > 0) {
1658        font_bytes += (int) ((unsigned) x * sizeof(kerninfo));
1659        kern = xmalloc((unsigned) ((unsigned) x * sizeof(kerninfo)));
1660        undump_things(*kern, x);
1661    }
1662    set_charinfo_kerns(co, kern);
1663
1664    /* packets */
1665    undump_int(x);
1666    if (x > 0) {
1667        font_bytes += x;
1668        packet = xmalloc((unsigned) x);
1669        undump_things(*packet, x);
1670    }
1671    set_charinfo_packets(co, packet);
1672
1673    if (get_charinfo_tag(co) == ext_tag) {
1674        set_charinfo_vert_variants(co, undump_charinfo_variants());
1675        set_charinfo_hor_variants(co, undump_charinfo_variants());
1676    }
1677    undump_math_kerns(co);
1678    return i;
1679}
1680
1681#define undump_font_string(a)   undump_int (x);		\
1682    if (x>0) {						\
1683	font_bytes += x;				\
1684    s = xmalloc((unsigned)x); undump_things(*s,x);	\
1685    a(f,s); }
1686
1687
1688static void undump_font_entry(texfont * f)
1689{
1690    int x = 0;
1691    /* *INDENT-OFF* */
1692    undump_int(x); f->_font_size = x;
1693    undump_int(x); f->_font_dsize = x;
1694    undump_int(x); f->_font_cidversion = x;
1695    undump_int(x); f->_font_cidsupplement = x;
1696    undump_int(x); f->_font_ec = x;
1697    undump_int(x); f->_font_checksum = (unsigned)x;
1698    undump_int(x); f->_font_used = (char)x;
1699    undump_int(x); f->_font_touched = (char)x;
1700    undump_int(x); f->_font_cache_id = x;
1701    undump_int(x); f->_font_encodingbytes = (char)x;
1702    undump_int(x); f->_font_slant = x;
1703    undump_int(x); f->_font_extend = x;
1704    undump_int(x); f->font_max_shrink = x;
1705    undump_int(x); f->font_max_stretch = x;
1706    undump_int(x); f->_font_step = x;
1707    undump_int(x); f->_font_auto_expand = x;
1708    undump_int(x); f->_font_tounicode = (char)x;
1709    undump_int(x); f->_font_type = x;
1710    undump_int(x); f->_font_format = x;
1711    undump_int(x); f->_font_embedding = x;
1712    undump_int(x); f->_font_bc = x;
1713    undump_int(x); f->_hyphen_char = x;
1714    undump_int(x); f->_skew_char = x;
1715    undump_int(x); f->_font_natural_dir = x;
1716    undump_int(x); f->_font_params = x;
1717    undump_int(x); f->_font_math_params = x;
1718    undump_int(x); f->ligatures_disabled = x;
1719    undump_int(x); f->_pdf_font_num = x;
1720    undump_int(x); f->_pdf_font_attr = x;
1721    /* *INDENT-ON* */
1722}
1723
1724
1725
1726void undump_font(int f)
1727{
1728    int x, i;
1729    texfont *tt;
1730    charinfo *ci;
1731    char *s;
1732    grow_font_table(f);
1733    tt = xmalloc(sizeof(texfont));
1734    memset(tt, 0, sizeof(texfont));
1735    font_bytes += (int) sizeof(texfont);
1736    undump_font_entry(tt);
1737    font_tables[f] = tt;
1738
1739    undump_font_string(set_font_name);
1740    undump_font_string(set_font_area);
1741    undump_font_string(set_font_filename);
1742    undump_font_string(set_font_fullname);
1743    undump_font_string(set_font_psname);
1744    undump_font_string(set_font_encodingname);
1745    undump_font_string(set_font_cidregistry);
1746    undump_font_string(set_font_cidordering);
1747
1748    i = (int) (sizeof(*param_base(f)) * ((unsigned) font_params(f) + 1));
1749    font_bytes += i;
1750    param_base(f) = xmalloc((unsigned) i);
1751    undump_things(*param_base(f), (font_params(f) + 1));
1752
1753    if (font_math_params(f) > 0) {
1754        i = (int) (sizeof(*math_param_base(f)) *
1755                   ((unsigned) font_math_params(f) + 1));
1756        font_bytes += i;
1757        math_param_base(f) = xmalloc((unsigned) i);
1758        undump_things(*math_param_base(f), (font_math_params(f) + 1));
1759    }
1760
1761    font_tables[f]->characters = new_sa_tree(1, 0);     /* stack size 1, default item value 0 */
1762    ci = xcalloc(1, sizeof(charinfo));
1763    set_charinfo_name(ci, xstrdup(".notdef"));
1764    font_tables[f]->charinfo = ci;
1765    undump_int(x);
1766    if (x) {
1767        i = undump_charinfo(f);
1768    }                           /* left boundary */
1769    undump_int(x);
1770    if (x) {
1771        i = undump_charinfo(f);
1772    }                           /* right boundary */
1773
1774    i = font_bc(f);
1775    while (i < font_ec(f)) {
1776        i = undump_charinfo(f);
1777    }
1778}
1779