Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pl/plfont.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* plfont.c */
18
/* PCL font handling library -- operations on entire fonts */
19
#include "memory_.h"
20
#include "stdio_.h"
21
#include "gdebug.h"
22
#include "gp.h"
23
#include "gserrors.h"
24
#include "gstypes.h"
25
#include "gsmemory.h"
26
#include "gsstruct.h"
27
#include "gsmatrix.h"
28
#include "gsstate.h"
29
#include "gschar.h"
30
#include "gsimage.h"
31
#include "gsutil.h"
32
#include "gxfcache.h"
33
#include "gxfont.h"
34
#include "gxfont42.h"
35
#include "gzstate.h"
36
#include "plfont.h"
37
#include "plvalue.h"
38
#include "plchar.h"
39
#include "strmio.h"
40
#include "stream.h"
41
42
#include "plfapi.h"
43
44
/* Structure descriptors */
45
private_st_pl_font();
46
47
/* Define accessors for unaligned, big-endian quantities. */
48
39.2k
#define u16(bptr) pl_get_uint16(bptr)
49
#define s16(bptr) pl_get_int16(bptr)
50
/**** ASSUME uint >= 32 BITS ****/
51
39.1k
#define u32(bptr) (uint)pl_get_uint32(bptr)
52
53
/* ---------------- Utilities ---------------- */
54
/* Free a font.  This is the freeing procedure in the font dictionary. */
55
void
56
pl_free_font(gs_memory_t * mem, void *plf, client_name_t cname)
57
2.02M
{
58
2.02M
    pl_font_t *plfont = plf;
59
60
    /* Free the characters. */
61
2.02M
    if (!plfont->data_are_permanent) {
62
2.00M
        if (plfont->glyphs.table) {
63
431
            uint i;
64
65
124k
            for (i = plfont->glyphs.size; i > 0;) {
66
123k
                void *data = (void *)plfont->glyphs.table[--i].data;
67
68
123k
                if (data)
69
1.90k
                    gs_free_object(mem, data, cname);
70
123k
            }
71
431
        }
72
2.00M
        gs_free_object(mem, (void *)plfont->header, cname);
73
2.00M
        plfont->header = 0;     /* see hack note above */
74
2.00M
    }
75
76
    /* free any nodes in the widths cache */
77
2.02M
    pl_font_glyph_width_cache_remove_nodes(plfont);
78
79
    /* Free the font data itself. */
80
2.02M
    gs_free_object(mem, (void *)plfont->char_glyphs.table, cname);
81
2.02M
    gs_free_object(mem, (void *)plfont->glyphs.table, cname);
82
2.02M
    if (plfont->pfont) {        /* might be only partially constructed */
83
2.02M
        gs_purge_font_from_char_caches_completely(plfont->pfont);
84
2.02M
        (void)gs_purge_font(plfont->pfont);
85
2.02M
        gs_free_object(mem, plfont->pfont, cname);
86
2.02M
    }
87
2.02M
    if (plfont->font_file) {
88
1.63M
        gs_free_object(mem, plfont->font_file, cname);
89
1.63M
        plfont->font_file = 0;
90
1.63M
    }
91
2.02M
    if (plfont->names != NULL) {
92
0
        int i = 0;
93
0
        for (i = 0;i < plfont->next_name_index; i++)
94
0
            gs_free_object(mem, plfont->names[i], "freeing names table");
95
0
        gs_free_object(mem, plfont->names, "free names table");
96
0
        plfont->names = NULL;
97
0
        plfont->max_name_index = plfont->next_name_index = 0;
98
0
    }
99
2.02M
    gs_free_object(mem, plf, cname);
100
2.02M
}
101
102
/* ---------------- Library callbacks ---------------- */
103
104
const char *pl_mac_names[258] = {
105
    ".notdef",
106
    ".null",
107
    "nonmarkingreturn",
108
    "space",
109
    "exclam",
110
    "quotedbl",
111
    "numbersign",
112
    "dollar",
113
    "percent",
114
    "ampersand",
115
    "quotesingle",
116
    "parenleft",
117
    "parenright",
118
    "asterisk",
119
    "plus",
120
    "comma",
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
    "equal",
138
    "greater",
139
    "question",
140
    "at",
141
    "A",
142
    "B",
143
    "C",
144
    "D",
145
    "E",
146
    "F",
147
    "G",
148
    "H",
149
    "I",
150
    "J",
151
    "K",
152
    "L",
153
    "M",
154
    "N",
155
    "O",
156
    "P",
157
    "Q",
158
    "R",
159
    "S",
160
    "T",
161
    "U",
162
    "V",
163
    "W",
164
    "X",
165
    "Y",
166
    "Z",
167
    "bracketleft",
168
    "backslash",
169
    "bracketright",
170
    "asciicircum",
171
    "underscore",
172
    "grave",
173
    "a",
174
    "b",
175
    "c",
176
    "d",
177
    "e",
178
    "f",
179
    "g",
180
    "h",
181
    "i",
182
    "j",
183
    "k",
184
    "l",
185
    "m",
186
    "n",
187
    "o",
188
    "p",
189
    "q",
190
    "r",
191
    "s",
192
    "t",
193
    "u",
194
    "v",
195
    "w",
196
    "x",
197
    "y",
198
    "z",
199
    "braceleft",
200
    "bar",
201
    "braceright",
202
    "asciitilde",
203
    "Adieresis",
204
    "Aring",
205
    "Ccedilla",
206
    "Eacute",
207
    "Ntilde",
208
    "Odieresis",
209
    "Udieresis",
210
    "aacute",
211
    "agrave",
212
    "acircumflex",
213
    "adieresis",
214
    "atilde",
215
    "aring",
216
    "ccedilla",
217
    "eacute",
218
    "egrave",
219
    "ecircumflex",
220
    "edieresis",
221
    "iacute",
222
    "igrave",
223
    "icircumflex",
224
    "idieresis",
225
    "ntilde",
226
    "oacute",
227
    "ograve",
228
    "ocircumflex",
229
    "odieresis",
230
    "otilde",
231
    "uacute",
232
    "ugrave",
233
    "ucircumflex",
234
    "udieresis",
235
    "dagger",
236
    "degree",
237
    "cent",
238
    "sterling",
239
    "section",
240
    "bullet",
241
    "paragraph",
242
    "germandbls",
243
    "registered",
244
    "copyright",
245
    "trademark",
246
    "acute",
247
    "dieresis",
248
    "notequal",
249
    "AE",
250
    "Oslash",
251
    "infinity",
252
    "plusminus",
253
    "lessequal",
254
    "greaterequal",
255
    "yen",
256
    "mu",
257
    "partialdiff",
258
    "summation",
259
    "product",
260
    "pi",
261
    "integral",
262
    "ordfeminine",
263
    "ordmasculine",
264
    "Omega",
265
    "ae",
266
    "oslash",
267
    "questiondown",
268
    "exclamdown",
269
    "logicalnot",
270
    "radical",
271
    "florin",
272
    "approxequal",
273
    "Delta",
274
    "guillemotleft",
275
    "guillemotright",
276
    "ellipsis",
277
    "nonbreakingspace",
278
    "Agrave",
279
    "Atilde",
280
    "Otilde",
281
    "OE",
282
    "oe",
283
    "endash",
284
    "emdash",
285
    "quotedblleft",
286
    "quotedblright",
287
    "quoteleft",
288
    "quoteright",
289
    "divide",
290
    "lozenge",
291
    "ydieresis",
292
    "Ydieresis",
293
    "fraction",
294
    "currency",
295
    "guilsinglleft",
296
    "guilsinglright",
297
    "fi",
298
    "fl",
299
    "daggerdbl",
300
    "periodcentered",
301
    "quotesinglbase",
302
    "quotedblbase",
303
    "perthousand",
304
    "Acircumflex",
305
    "Ecircumflex",
306
    "Aacute",
307
    "Edieresis",
308
    "Egrave",
309
    "Iacute",
310
    "Icircumflex",
311
    "Idieresis",
312
    "Igrave",
313
    "Oacute",
314
    "Ocircumflex",
315
    "apple",
316
    "Ograve",
317
    "Uacute",
318
    "Ucircumflex",
319
    "Ugrave",
320
    "dotlessi",
321
    "circumflex",
322
    "tilde",
323
    "macron",
324
    "breve",
325
    "dotaccent",
326
    "ring",
327
    "cedilla",
328
    "hungarumlaut",
329
    "ogonek",
330
    "caron",
331
    "Lslash",
332
    "lslash",
333
    "Scaron",
334
    "scaron",
335
    "Zcaron",
336
    "zcaron",
337
    "brokenbar",
338
    "Eth",
339
    "eth",
340
    "Yacute",
341
    "yacute",
342
    "Thorn",
343
    "thorn",
344
    "minus",
345
    "multiply",
346
    "onesuperior",
347
    "twosuperior",
348
    "threesuperior",
349
    "onehalf",
350
    "onequarter",
351
    "threequarters",
352
    "franc",
353
    "Gbreve",
354
    "gbreve",
355
    "Idotaccent",
356
    "Scedilla",
357
    "scedilla",
358
    "Cacute",
359
    "cacute",
360
    "Ccaron",
361
    "ccaron",
362
    "dcroat"
363
};
364
365
static int
366
pl_glyph_name(gs_font * pfont, gs_glyph glyph, gs_const_string * pstr)
367
0
{
368
0
    uint table_length;
369
0
    ulong table_offset;
370
0
    pl_font_t * plfont = (pl_font_t *)pfont->client_data;
371
372
0
    if (glyph >= GS_MIN_GLYPH_INDEX)
373
0
        glyph -= GS_MIN_GLYPH_INDEX;
374
375
    /* guess if the font type is not truetype */
376
0
    if (pfont->FontType != ft_TrueType) {
377
0
        glyph -= 29;
378
0
        if (glyph < 258) {
379
0
            pstr->data = (const byte *)pl_mac_names[glyph];
380
0
            pstr->size = strlen((const char *)pstr->data);
381
0
            return 0;
382
0
        } else {
383
0
            if_debug1m('=', pfont->memory,
384
0
                       "[=]glyph index %lx out of range\n", (ulong) glyph);
385
0
            return -1;
386
0
        }
387
0
    }
388
389
0
    table_offset =
390
0
        tt_find_table((gs_font_type42 *) pfont, "post", &table_length);
391
    /* no post table */
392
0
    if (table_offset == 0)
393
0
        return -1;
394
    /* this shoudn't happen but... */
395
    /* 32 byte offset, plus 2 bytes for number of glyphs
396
       less than that is deifnitely an invalid table.
397
     */
398
0
    if (table_length < 34)
399
0
        return -1;
400
401
0
    {
402
0
        ulong format;
403
0
        int numGlyphs;
404
0
        int code;
405
0
        uint glyph_name_index;
406
0
        const byte *postp;      /* post table pointer */
407
408
0
        code = ((gs_font_type42 *) pfont)->data.string_proc((gs_font_type42 *) pfont,
409
0
                                                     table_offset,
410
0
                                                     table_length, &postp);
411
0
        if (code < 0)
412
0
            return -1;
413
414
0
        format = u32(postp);
415
0
        if (format != 0x20000) {
416
            /* format 1.0 (mac encoding) is a simple table see the TT
417
               spec.  We don't implement this because we don't see it
418
               in practice */
419
0
            dmprintf1(pfont->memory, "unknown post table format %lX\n",
420
0
                      format);
421
0
            return -1;
422
0
        }
423
        /* skip over the post header */
424
0
        numGlyphs = (int)u16(postp + 32);
425
0
        if ((int)glyph > numGlyphs - 1) {
426
0
            if_debug1m('=', pfont->memory,
427
0
                       "[=]glyph index %lx out of range\n", glyph);
428
0
            return -1;
429
0
        }
430
        /* glyph name index starts at post + 34 each entry is 2 bytes */
431
0
        if (postp + 34 + (glyph * 2) + 2 > postp + table_length)
432
0
            return -1;
433
434
0
        glyph_name_index = u16(postp + 34 + (glyph * 2));
435
        /* this shouldn't happen */
436
0
        if (glyph_name_index > 0x7fff)
437
0
            return -1;
438
        /* mac easy */
439
0
        if (glyph_name_index < 258) {
440
441
0
            pstr->data = (const byte *)pl_mac_names[glyph_name_index];
442
0
            pstr->size = strlen((const char *)pstr->data);
443
0
            return 0;
444
            /* not mac */
445
0
        } else {
446
0
            byte *mydata;
447
            /* and here's the tricky part */
448
0
            const byte *pascal_stringp = postp + 34 + (numGlyphs * 2);
449
            /* 0 - 257 lives in the mac table above */
450
0
            glyph_name_index -= 258;
451
            /* The string we want is the index'th pascal string,
452
               so we "hop" to each length byte "index" times. */
453
0
            while (glyph_name_index > 0) {
454
0
                pascal_stringp += ((int)(*pascal_stringp) + 1);
455
0
                glyph_name_index--;
456
0
            }
457
            /* length byte */
458
0
            pstr->size = (int)(*pascal_stringp);
459
            /* + 1 is for the length byte */
460
0
            pstr->data = pascal_stringp + 1;
461
            /* sanity check */
462
0
            if (pstr->data + pstr->size > postp + table_length ||
463
0
                pstr->data - 1 < postp) {
464
0
                dmprintf(pfont->memory, "data out of range\n");
465
0
                return -1;
466
0
            }
467
            /* sigh - we have to allocate a copy of the data - by the
468
               time a high level device makes use of it the font data
469
               may be freed.  Track the allocated memory in our
470
               font 'wrapper' so we can free it when we free tha font wrapper.
471
             */
472
0
            mydata =
473
0
                gs_alloc_bytes(pfont->memory, pstr->size + 1,
474
0
                               "glyph to name");
475
0
            if (mydata == 0)
476
0
                return -1;
477
0
            memcpy(mydata, pascal_stringp + 1, pstr->size);
478
0
            pstr->data = mydata;
479
0
            if (plfont->names == NULL) {
480
0
                plfont->names = (char **)gs_alloc_bytes(pfont->memory, 256 * sizeof (char *), "names storage");
481
0
                if (plfont->names == NULL) {
482
0
                    gs_free_object(pfont->memory, (byte *)pstr->data, "free string on error");
483
0
                    pstr->data = NULL;
484
0
                    pstr->size = 0;
485
0
                    return -1;
486
0
                }
487
0
                plfont->max_name_index = 255;
488
0
                plfont->next_name_index = 0;
489
0
                memset(plfont->names, 0x00, 256 * sizeof (char *));
490
0
            }
491
0
            if (plfont->next_name_index > plfont->max_name_index) {
492
0
                char **temp = NULL;
493
0
                temp = (char **)gs_alloc_bytes(pfont->memory, (size_t)(plfont->max_name_index + 256) * sizeof (char *), "names storage");
494
0
                if (temp == NULL) {
495
0
                    gs_free_object(pfont->memory, (byte *)pstr->data, "free string on error");
496
0
                    pstr->data = NULL;
497
0
                    pstr->size = 0;
498
0
                    return -1;
499
0
                }
500
0
                memset(temp, 0x00, (plfont->max_name_index + 256) * sizeof (char *));
501
0
                memcpy(temp, plfont->names, plfont->max_name_index * sizeof(char *));
502
0
                gs_free_object(pfont->memory, (void *)plfont->names, "realloc names storage");
503
0
                plfont->names = temp;
504
0
                plfont->max_name_index += 256;
505
0
            }
506
0
            plfont->names[plfont->next_name_index++] = (char *)pstr->data;
507
0
            return 0;
508
0
        }
509
0
    }
510
0
    return 0;
511
0
}
512
513
/* Get the unicode valude for a glyph */
514
static int
515
pl_decode_glyph(gs_font * font, gs_glyph glyph, int ch, ushort *unicode_return, unsigned int length)
516
0
{
517
0
    unsigned char *ucode = (unsigned char *)unicode_return;
518
519
0
    if (ch < 0 || ch > 255)
520
0
        return (int) GS_NO_CHAR;
521
522
0
    if (length == 0)
523
0
        return 2;
524
525
#if ARCH_IS_BIG_ENDIAN
526
    *unicode_return = (ushort)ch;
527
#else
528
0
    ucode[0] = 0x00;
529
0
    ucode[1] = ch & 0xff;
530
0
#endif
531
0
    return 2;
532
0
}
533
534
/* ---------------- Width cache ---------------- */
535
static int
536
pl_font_glyph_width_cache_node_add(pl_font_t *plfont,
537
                              uint char_code, gs_point * pwidth)
538
1.71M
{
539
1.71M
    pl_glyph_width_node_t *node;
540
541
    /* We can't safely cache widths for bitmap fonts */
542
1.71M
    if (plfont->scaling_technology == plfst_bitmap) {
543
0
        return(0);
544
0
    }
545
546
1.71M
    if (plfont->widths_cache_nitems > PL_MAX_WIDTHS_CACHE_NITEMS) {
547
370
        pl_font_glyph_width_cache_remove_nodes(plfont);
548
370
    }
549
550
1.71M
    node = (pl_glyph_width_node_t *) gs_alloc_bytes(plfont->pfont->memory,
551
1.71M
                                                 sizeof
552
1.71M
                                                 (pl_glyph_width_node_t),
553
1.71M
                                                 "pl_glyph_width_cache_node_add");
554
555
1.71M
    if (node == NULL) {
556
        /* if we couldn't allocate a node, it probably doesn't hurt
557
         * to get rid of all the nodes we have.
558
         */
559
0
        pl_font_glyph_width_cache_remove_nodes(plfont);
560
0
        return -1;
561
0
    }
562
563
1.71M
    node->next = plfont->widths_cache;
564
1.71M
    plfont->widths_cache = node;
565
1.71M
    plfont->widths_cache_nitems++;
566
567
1.71M
    node->char_code = char_code;
568
1.71M
    node->font_id = plfont->pfont->id;
569
1.71M
    node->width = *pwidth;
570
571
1.71M
    return 0;
572
1.71M
}
573
574
575
static int
576
pl_font_glyph_width_cache_node_search(const pl_font_t *plfont, uint char_code,
577
                                 gs_point * pwidth)
578
34.8M
{
579
34.8M
    pl_glyph_width_node_t *current = plfont->widths_cache;
580
581
1.95G
    while (current) {
582
1.95G
        if (char_code == current->char_code) {
583
32.4M
            *pwidth = current->width;
584
32.4M
            return 0;
585
32.4M
        }
586
1.92G
        current = current->next;
587
1.92G
    }
588
2.39M
    return -1;
589
34.8M
}
590
591
592
/* ---------------- Public procedures ---------------- */
593
/* character width */
594
595
void
596
pl_font_glyph_width_cache_remove_nodes(pl_font_t *plfont)
597
2.36M
{
598
2.36M
    pl_glyph_width_node_t *current = plfont->widths_cache;
599
600
4.08M
    while (current) {
601
1.71M
        pl_glyph_width_node_t *next = current->next;
602
603
1.71M
        gs_free_object(plfont->pfont->memory, current, "pl_glyph_width_list_remove");
604
1.71M
        current = next;
605
1.71M
    }
606
2.36M
    plfont->widths_cache = NULL;
607
2.36M
    plfont->widths_cache_nitems = 0;
608
2.36M
    return;
609
2.36M
}
610
611
int
612
pl_font_char_width(const pl_font_t * plfont, const void *pgs,
613
                   gs_char char_code, gs_point * pwidth)
614
34.8M
{
615
34.8M
    int code = 0;
616
617
34.8M
    if (pl_font_glyph_width_cache_node_search(plfont, char_code, pwidth) >= 0) {
618
32.4M
        return(code);
619
32.4M
    }
620
621
2.39M
    if ((code = (*(plfont)->char_width) (plfont, pgs, char_code, pwidth)) == 0) {
622
623
        /* at least here, ignore the return value - if we fail to add a node
624
         * to the cache, we can reasonably attempt to carry on without it
625
         */
626
1.71M
        (void)pl_font_glyph_width_cache_node_add((pl_font_t *)plfont, char_code, pwidth);
627
1.71M
    }
628
2.39M
    return code;
629
34.8M
}
630
631
/* character width */
632
int
633
pl_font_char_metrics(const pl_font_t * plfont, const void *pgs,
634
                     gs_char char_code, float metrics[4])
635
1.04M
{
636
1.04M
    return (*(plfont)->char_metrics) (plfont, pgs, char_code, metrics);
637
1.04M
}
638
639
/* Allocate a font. */
640
pl_font_t *
641
pl_alloc_font(gs_memory_t * mem, client_name_t cname)
642
2.02M
{
643
2.02M
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
644
645
2.02M
    if (plfont) {               /* Initialize pointers. */
646
2.02M
        plfont->pfont = 0;
647
2.02M
        plfont->header = 0;
648
2.02M
        plfont->glyphs.table = 0;
649
2.02M
        plfont->char_glyphs.table = 0;
650
        /* Initialize other defaults. */
651
2.02M
        plfont->orient = 0;
652
2.02M
        plfont->allow_vertical_substitutes = false;
653
2.02M
        plfont->bold_fraction = 0;
654
2.02M
        plfont->font_file = 0;
655
2.02M
        plfont->resolution.x = plfont->resolution.y = 0;
656
2.02M
        plfont->params.proportional_spacing = true;
657
2.02M
        memset(plfont->character_complement, 0xff, 8);
658
2.02M
        plfont->offsets.GC = plfont->offsets.GT = plfont->offsets.VT = -1;
659
2.02M
        plfont->pts_per_inch = 72.0;    /* normal value */
660
2.02M
        plfont->widths_cache = NULL;
661
2.02M
        plfont->widths_cache_nitems = 0;
662
2.02M
        plfont->names = NULL;
663
2.02M
        plfont->max_name_index = 0;
664
2.02M
        plfont->next_name_index = 0;
665
2.02M
    }
666
2.02M
    return plfont;
667
2.02M
}
668
669
/* Structure descriptors for cloning fonts */
670
gs_private_st_ptrs1(st_pl_font_glyph_f, pl_font_glyph_t, "pl_font_glyph_t",
671
                    pl_font_glyph_enum_ptrs_f, pl_font_glyph_reloc_ptrs_f,
672
                    data);
673
gs_private_st_element(st_pl_font_glyph_element_f, pl_font_glyph_t,
674
                      "pl_font_glyph_t[]", pl_font_glyph_elt_enum_ptrs_f,
675
                      pl_font_glyph_elt_reloc_ptrs_f, st_pl_font_glyph_f);
676
677
pl_font_t *
678
pl_clone_font(const pl_font_t * src, gs_memory_t * mem, client_name_t cname)
679
0
{
680
0
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
681
682
0
    if (plfont == 0)
683
0
        return 0;
684
    /* copy technology common parts */
685
0
    plfont->storage = src->storage;
686
0
    plfont->header_size = src->header_size;
687
0
    plfont->scaling_technology = src->scaling_technology;
688
0
    plfont->is_xl_format = src->is_xl_format;
689
0
    plfont->allow_vertical_substitutes = src->allow_vertical_substitutes;
690
0
    plfont->font_type = src->font_type;
691
0
    plfont->char_width = src->char_width;
692
0
    plfont->char_metrics = src->char_metrics;
693
0
    plfont->large_sizes = src->large_sizes;
694
0
    plfont->resolution = src->resolution;
695
0
    plfont->params = src->params;
696
0
    plfont->pts_per_inch = src->pts_per_inch;
697
0
    plfont->font_file_loaded = src->font_file_loaded;
698
0
    plfont->orient = src->orient;
699
0
    plfont->bold_fraction = src->bold_fraction;
700
0
    plfont->widths_cache = NULL;
701
0
    plfont->widths_cache_nitems = 0;
702
0
    {
703
0
        int i;
704
705
0
        for (i = 0; i < sizeof(src->character_complement); i++)
706
0
            plfont->character_complement[i] = src->character_complement[i];
707
0
    }
708
0
    plfont->offsets = src->offsets;
709
0
    plfont->header = gs_alloc_bytes(mem, src->header_size, cname);
710
0
    if (plfont->header == 0)
711
0
        return 0;
712
0
    memcpy(plfont->header, src->header, src->header_size);
713
714
0
    plfont->names = NULL;
715
0
    plfont->max_name_index = 0;
716
0
    plfont->next_name_index = 0;
717
718
0
    if (src->font_file) {
719
0
        plfont->font_file =
720
0
            (char *)gs_alloc_bytes(mem, strlen(src->font_file) + 1,
721
0
                                   "pl_clone_font");
722
0
        if (plfont->font_file == 0)
723
0
            return 0;           /* #NB errors!!! */
724
0
        strcpy(plfont->font_file, src->font_file);
725
0
    } else
726
0
        plfont->font_file = 0;
727
    /* technology specific setup */
728
0
    switch (plfont->scaling_technology) {
729
0
        case plfst_bitmap:
730
0
            {
731
0
                gs_font_base *pfont =
732
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
733
0
                                    cname);
734
0
                if (pfont == 0)
735
0
                    return 0;
736
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
737
0
                                mem, "nameless_font");
738
0
                pl_fill_in_bitmap_font(pfont, gs_next_ids(mem, 1));
739
0
                break;
740
0
            }
741
0
        case plfst_Intellifont:
742
0
            {
743
0
                gs_font_base *pfont =
744
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
745
0
                                    cname);
746
0
                if (pfont == 0)
747
0
                    return 0;
748
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
749
0
                                mem, "nameless_font");
750
0
                pl_fill_in_intelli_font(pfont, gs_next_ids(mem, 1));
751
0
                break;
752
0
            }
753
0
        case plfst_TrueType:
754
0
            {
755
0
                {
756
0
                    gs_font_type42 *pfont =
757
0
                        gs_alloc_struct(mem, gs_font_type42,
758
0
                                        &st_gs_font_type42, cname);
759
                    /* detect if a truetype font is downloaded or
760
                       internal.  There must be a better way... */
761
0
                    gs_font_type42 *pfont_src = (gs_font_type42 *) src->pfont;
762
0
                    bool downloaded =
763
0
                        (pfont_src->data.get_outline == pl_tt_get_outline);
764
0
                    if (pfont == 0)
765
0
                        return 0;
766
0
                    pl_fill_in_font((gs_font *) pfont, plfont,
767
0
                                    src->pfont->dir, mem, "nameless_font");
768
0
                    pl_fill_in_tt_font(pfont, downloaded ? NULL : src->header,
769
0
                                       gs_next_ids(mem, 1));
770
0
                }
771
0
                break;
772
0
            }
773
0
        default:
774
0
            return 0;
775
0
    }
776
0
    if (src->char_glyphs.table != 0) {
777
        /* HAS may gs_alloc_struct_array() here but this is
778
           consistant with pl_tt_alloc_char_glyphs() */
779
0
        pl_tt_char_glyph_t *char_glyphs =
780
0
            (pl_tt_char_glyph_t *) gs_alloc_byte_array(mem,
781
0
                                                       src->char_glyphs.size,
782
0
                                                       sizeof
783
0
                                                       (pl_tt_char_glyph_t),
784
0
                                                       cname);
785
0
        int i;
786
787
0
        if (char_glyphs == 0)
788
0
            return 0;
789
0
        for (i = 0; i < src->char_glyphs.size; i++)
790
0
            char_glyphs[i] = src->char_glyphs.table[i];
791
        /* once again a copy struct shortcut and then are restore
792
           of the char_glyphs.table pointer */
793
0
        plfont->char_glyphs = src->char_glyphs;
794
0
        plfont->char_glyphs.table = char_glyphs;
795
0
    } else                      /* no character glyph table data */
796
0
        plfont->char_glyphs = src->char_glyphs;
797
798
0
    if (src->glyphs.table != 0) {
799
0
        int i;
800
801
0
        plfont->glyphs.table =
802
0
            gs_alloc_struct_array(mem, src->glyphs.size, pl_font_glyph_t,
803
0
                                  &st_pl_font_glyph_element_f, cname);
804
0
        if (plfont->glyphs.table == NULL)
805
0
            return 0;
806
0
        plfont->glyphs.used = src->glyphs.used;
807
0
        plfont->glyphs.limit = src->glyphs.limit;
808
0
        plfont->glyphs.size = src->glyphs.size;
809
0
        plfont->glyphs.skip = src->glyphs.skip;
810
0
        for (i = 0; i < src->glyphs.size; i++) {
811
0
            const byte *data = src->glyphs.table[i].data;
812
0
            byte *char_data;
813
814
0
            plfont->glyphs.table[i].glyph = src->glyphs.table[i].glyph;
815
0
            plfont->glyphs.table[i].data = 0;
816
0
            if (data) {
817
0
                uint size = src->glyphs.table[i].data_len;
818
0
                char_data = gs_alloc_bytes(mem, size, cname);
819
0
                if (char_data == 0)
820
0
                    return 0;
821
0
                memcpy(char_data, data, size);
822
0
                plfont->glyphs.table[i].data = char_data;
823
0
                plfont->glyphs.table[i].data_len = size;
824
0
            }
825
826
0
        }
827
0
    } else                      /* no glyph table */
828
0
        plfont->glyphs = src->glyphs;
829
0
    return plfont;
830
0
}
831
832
/* Fill in generic font boilerplate. NB TODO examine duplication with
833
   gs_font_alloc().  The font name must not contain spaces.  It is
834
   used for PDF output and Acrobat (some versions) do not process the
835
   file correctly with spaces in the name. */
836
int
837
pl_fill_in_font(gs_font * pfont, pl_font_t * plfont, gs_font_dir * pdir,
838
                gs_memory_t * mem, const char *font_name)
839
2.10M
{
840
2.10M
    gs_font_base *pbfont = (gs_font_base *) pfont;
841
842
2.10M
    plfont->pfont = pfont;
843
    /* Initialize generic font data. */
844
2.10M
    gs_make_identity(&pbfont->orig_FontMatrix);
845
2.10M
    gs_make_identity(&pbfont->FontMatrix);
846
2.10M
    pbfont->next = pbfont->prev = 0;
847
2.10M
    pbfont->memory = mem;
848
2.10M
    pbfont->dir = pdir;
849
2.10M
    pbfont->is_resource = false;
850
2.10M
    gs_notify_init(&pbfont->notify_list, gs_memory_stable(mem));
851
2.10M
    pbfont->base = (gs_font *) pbfont;
852
2.10M
    pbfont->client_data = plfont;
853
2.10M
    pbfont->WMode = 0;
854
2.10M
    pbfont->PaintType = 0;
855
2.10M
    pbfont->StrokeWidth = 0;
856
2.10M
    pbfont->is_cached = 0;
857
2.10M
    pbfont->procs.init_fstack = gs_default_init_fstack;
858
2.10M
    pbfont->procs.next_char_glyph = gs_default_next_char_glyph;
859
2.10M
    pbfont->FAPI = NULL;
860
2.10M
    pbfont->FAPI_font_data = NULL;
861
862
2.10M
    pbfont->procs.glyph_name = pl_glyph_name;
863
2.10M
    pbfont->procs.decode_glyph = pl_decode_glyph;
864
    /* NB pbfont->procs.callbacks.known_encode = pl_known_encode; */
865
2.10M
    pbfont->procs.define_font = gs_no_define_font;
866
2.10M
    pbfont->procs.make_font = gs_no_make_font;
867
2.10M
    pbfont->procs.font_info = gs_default_font_info;
868
2.10M
    pbfont->procs.glyph_info = gs_default_glyph_info;
869
2.10M
    pbfont->procs.glyph_outline = gs_no_glyph_outline;
870
2.10M
    pbfont->id = gs_next_ids(mem, 1);
871
2.10M
    {
872
2.10M
        size_t sz = strlen(font_name);
873
2.10M
        gs_font_name *fnm = &pbfont->font_name;
874
2.10M
        gs_font_name *knm = &pbfont->key_name;
875
876
2.10M
        if (sz > gs_font_name_max)
877
0
            sz = gs_font_name_max;
878
2.10M
        fnm->size = knm->size = sz;
879
880
2.10M
        memcpy(fnm->chars, font_name, sz);
881
2.10M
        fnm->chars[sz] = 0;
882
883
2.10M
        memcpy(knm->chars, font_name, sz);
884
2.10M
        knm->chars[sz] = 0;
885
2.10M
    }
886
2.10M
    return 0;
887
2.10M
}
888
889
/* Fill in bitmap font boilerplate. */
890
void
891
pl_fill_in_bitmap_font(gs_font_base * pfont, long unique_id)
892
19.5k
{
893
19.5k
    pfont->FontType = ft_PCL_user_defined;
894
19.5k
    pfont->BitmapWidths = true;
895
19.5k
    pfont->ExactSize = fbit_use_bitmaps;
896
19.5k
    pfont->InBetweenSize = fbit_use_bitmaps;
897
19.5k
    pfont->TransformedChar = fbit_transform_bitmaps;
898
19.5k
    pl_bitmap_init_procs(pfont);
899
    /* We have no idea what the FontBBox should be. */
900
19.5k
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
901
19.5k
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
902
19.5k
    uid_set_UniqueID(&pfont->UID, unique_id);
903
19.5k
    pfont->encoding_index = 1;          /****** WRONG ******/
904
19.5k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
905
19.5k
}
906
907
/* Fill in TrueType font boilerplate. */
908
int
909
pl_fill_in_tt_font(gs_font_type42 * pfont, void *data, long unique_id)
910
2.00M
{
911
2.00M
    pfont->FontType = ft_TrueType;
912
2.00M
    pfont->BitmapWidths = true;
913
2.00M
    pfont->ExactSize = fbit_use_outlines;
914
2.00M
    pfont->InBetweenSize = fbit_use_outlines;
915
2.00M
    pfont->TransformedChar = fbit_use_outlines;
916
    /* Initialize base font data. */
917
    /*
918
     * We can't set the FontBBox correctly until we've initialized the
919
     * Type 42 specific data, but we need to set it to an empty box now
920
     * for the sake of gs_type42_font_init.
921
     */
922
2.00M
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
923
2.00M
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
924
2.00M
    uid_set_UniqueID(&pfont->UID, unique_id);
925
2.00M
    pfont->encoding_index = 1;          /****** WRONG ******/
926
2.00M
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
927
    /* Initialize Type 42 specific data. */
928
2.00M
    pfont->data.proc_data = data;
929
2.00M
    pl_tt_init_procs(pfont);
930
2.00M
    {
931
2.00M
        int code = gs_type42_font_init(pfont, 0);
932
933
2.00M
        if (code < 0)
934
15
            return code;
935
2.00M
    }
936
    /* disable unused FAPI */
937
2.00M
    pfont->FAPI = 0;
938
2.00M
    pfont->FAPI_font_data = 0;
939
2.00M
    pl_tt_finish_init(pfont, !data);
940
2.00M
    return 0;
941
2.00M
}
942
943
/* Fill in Intellifont boilerplate. */
944
void
945
pl_fill_in_intelli_font(gs_font_base * pfont, long unique_id)
946
0
{                               /* Intellifonts have an 8782-unit design space. */
947
0
    {
948
0
        gs_matrix mat;
949
950
0
        gs_make_scaling(1.0 / 8782, 1.0 / 8782, &mat);
951
0
        gs_matrix_translate(&mat, -2980.0, -5380.0, &pfont->orig_FontMatrix);
952
0
    }
953
0
    pfont->FontType = ft_MicroType;
954
0
    pfont->BitmapWidths = true;
955
0
    pfont->ExactSize = fbit_use_outlines;
956
0
    pfont->InBetweenSize = fbit_use_outlines;
957
0
    pfont->TransformedChar = fbit_use_outlines;
958
    /* We have no idea what the FontBBox should be. */
959
0
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
960
0
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
961
0
    uid_set_UniqueID(&pfont->UID, unique_id);
962
0
    pfont->encoding_index = 1;          /****** WRONG ******/
963
0
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
964
0
    pl_intelli_init_procs(pfont);
965
0
}
966
967
/*
968
 * Set large_sizes, scaling_technology, character_complement, offsets
969
 * (for TrueType fonts), and resolution (for bitmap fonts) by scanning
970
 * the segments of a segmented downloaded font.
971
 * This is used for PCL5 Format 15 and 16 fonts and for PCL XL fonts.
972
 * fst_offset is the offset of the Font Scaling Technology and Variety bytes;
973
 * the segment data runs from start_offset up to end_offset.
974
 * large_sizes = false indicates 2-byte segment sizes, true indicates 4-byte.
975
 */
976
int
977
pl_font_scan_segments(const gs_memory_t * mem,
978
                      pl_font_t * plfont, int fst_offset, int start_offset,
979
                      long end_offset, bool large_sizes,
980
                      const pl_font_offset_errors_t * pfoe)
981
19.5k
{
982
19.5k
    const byte *header = plfont->header;
983
19.5k
    pl_font_scaling_technology_t fst = header[fst_offset];
984
19.5k
    int wsize = (large_sizes ? 4 : 2);
985
19.5k
    const byte *segment = header + start_offset;
986
19.5k
    const byte *end = header + end_offset;
987
19.5k
    const byte *null_segment = end - (2 + wsize);
988
19.5k
    bool found = false;
989
19.5k
    ulong seg_size;
990
19.5k
    int illegal_font_data = pfoe->illegal_font_data;
991
992
19.5k
#define return_scan_error(err)\
993
19.5k
  return_error((err) ? (err) : illegal_font_data);
994
995
19.5k
    if (memcmp(null_segment, "\377\377", 2) /* NULL segment header */ )
996
19.5k
        return_scan_error(pfoe->missing_required_segment);
997
19.5k
    if (memcmp(null_segment + 2, "\0\0\0\0", wsize) /* NULL segment size */ )
998
19.5k
        return_scan_error(pfoe->illegal_null_segment_size);
999
19.5k
    switch (fst) {
1000
19.4k
        case plfst_bitmap:
1001
19.5k
        case plfst_TrueType:
1002
19.5k
            break;
1003
0
        default:
1004
0
            return_scan_error(pfoe->illegal_font_header_fields);
1005
19.5k
    }
1006
19.5k
    if (header[fst_offset + 1]) /* variety, must be 0 */
1007
19.5k
        return_scan_error(pfoe->illegal_font_header_fields);
1008
    /* Scan the segments. */
1009
58.6k
    for (; end - segment >= 2 + wsize; segment += 2 + wsize + seg_size) {
1010
39.1k
        uint seg_id = u16(segment);
1011
39.1k
        const byte *sdata = segment + 2 + wsize;
1012
1013
39.1k
#define id2(c1,c2) (((uint)(c1) << 8) + (c2))
1014
1015
39.1k
        seg_size = (large_sizes ? u32(segment + 2) : u16(segment + 2));
1016
39.1k
        if (seg_size + 2 + wsize > end - segment)
1017
6
            return_error(illegal_font_data);
1018
        /* Handle segments common to all fonts. */
1019
39.1k
        switch (seg_id) {
1020
19.5k
            case 0xffff:       /* NULL segment ID */
1021
19.5k
                if (segment != null_segment)
1022
0
                    return_error(illegal_font_data);
1023
19.5k
                continue;
1024
19.5k
            case id2('V', 'I'):
1025
0
                continue;
1026
0
            case id2('C', 'C'):
1027
0
                if (seg_size != 8)
1028
0
                    return_error(illegal_font_data);
1029
0
                memcpy(plfont->character_complement, sdata, 8);
1030
0
                continue;
1031
19.5k
            default:
1032
19.5k
                ;
1033
39.1k
        }
1034
        /* Handle segments specific to the scaling technology. */
1035
19.5k
        if (fst == plfst_bitmap)
1036
19.4k
            switch (seg_id) {
1037
19.4k
                case id2('B', 'R'):
1038
19.4k
                    if (seg_size != 4)
1039
19.4k
                        return_scan_error(pfoe->illegal_BR_segment);
1040
19.4k
                    {
1041
19.4k
                        uint xres = pl_get_uint16(sdata);
1042
19.4k
                        uint yres = pl_get_uint16(sdata + 2);
1043
1044
19.4k
                        if (xres == 0 || yres == 0)
1045
19.4k
                            return_scan_error(pfoe->illegal_BR_segment);
1046
19.4k
                        plfont->resolution.x = xres;
1047
19.4k
                        plfont->resolution.y = yres;
1048
19.4k
                    }
1049
19.4k
                    found = true;
1050
19.4k
                    break;
1051
0
                default:
1052
0
                    if (pfoe->illegal_font_segment < 0)
1053
0
                        return_error(pfoe->illegal_font_segment);
1054
19.4k
        } else                  /* fst == plfst_TrueType */
1055
139
            switch (seg_id) {
1056
139
                case id2('G', 'T'):
1057
                    /*
1058
                     * We don't do much checking here, but we do check that
1059
                     * the segment starts with a table directory that
1060
                     * includes at least 3 elements (gdir, head,
1061
                     * maxp -- but we don't check the actual names).
1062
                     */
1063
139
                    if (seg_size < 12 + 5 * 16 ||
1064
                        /* memcmp(sdata, "\000\001\000\000", 4) || */
1065
139
                        u16(sdata + 4) < 3)
1066
139
                        return_scan_error(pfoe->illegal_GT_segment);
1067
139
                    plfont->offsets.GT = segment - header;
1068
139
                    found = true;
1069
139
                    break;
1070
0
                case id2('G', 'C'):
1071
0
                    if (seg_size < 6 || u16(sdata) != 0 ||
1072
0
                        seg_size != u16(sdata + 4) * 6 + 6)
1073
0
                        return_scan_error(pfoe->illegal_GC_segment);
1074
0
                    plfont->offsets.GC = segment - header;
1075
0
                    break;
1076
0
                case id2('V', 'T'):
1077
                    /* Check for end of table mark */
1078
0
                    if ((seg_size & 3) != 0 || seg_size < 4 ||
1079
0
                        u16(sdata + seg_size - 4) != 0xffff)
1080
0
                        return_scan_error(pfoe->illegal_VT_segment);
1081
                    /* Check for table sorted by horizontal glyph ID */
1082
0
                    {
1083
0
                        uint i;
1084
1085
0
                        for (i = 0; i < seg_size - 4; i += 4)
1086
0
                            if (u16(sdata + i) > u16(sdata + i + 4))
1087
0
                                return_scan_error(pfoe->illegal_VT_segment);
1088
0
                    }
1089
0
                    plfont->offsets.VT = segment - header;
1090
0
                    break;
1091
0
                case id2('V', 'E'):    /* nb unimplemented */
1092
0
                    break;
1093
0
                case id2('V', 'R'):    /* nb unimplemented */
1094
0
                    break;
1095
0
                case id2('C', 'E'):    /* nb unimplemented */
1096
0
                    break;
1097
0
                default:
1098
0
                    if (pfoe->illegal_font_segment < 0)
1099
0
                        return_error(pfoe->illegal_font_segment);
1100
139
            }
1101
19.5k
#undef id2
1102
19.5k
    }
1103
19.5k
    if (!found)
1104
19.5k
        return_scan_error(pfoe->missing_required_segment);
1105
19.5k
    if (segment != end)
1106
0
        return_error(illegal_font_data);
1107
19.5k
    plfont->large_sizes = large_sizes;
1108
19.5k
    plfont->scaling_technology = fst;
1109
19.5k
    return 0;
1110
19.5k
#undef return_scan_error
1111
19.5k
}
1112
1113
int
1114
pl_free_tt_fontfile_buffer(gs_memory_t * mem, byte * ptt_font_data)
1115
0
{
1116
0
    gs_free_object(mem, ptt_font_data, "pl_tt_load_font data");
1117
0
    return 0;
1118
0
}
1119
1120
int
1121
pl_alloc_tt_fontfile_buffer(stream * in, gs_memory_t * mem,
1122
                            byte ** pptt_font_data, ulong * size)
1123
2.00M
{
1124
2.00M
    ulong len = (sfseek(in, 0L, SEEK_END), sftell(in));
1125
1126
2.00M
    *size = 6 + len;            /* leave room for segment header */
1127
2.00M
    if (*size != (uint) (*size)) {
1128
        /*
1129
         * The font is too big to load in a single piece -- punt.
1130
         * The error message is bogus, but there isn't any more
1131
         * appropriate one.
1132
         */
1133
0
        sfclose(in);
1134
0
        return_error(gs_error_VMerror);
1135
0
    }
1136
2.00M
    srewind(in);
1137
2.00M
    *pptt_font_data = gs_alloc_bytes(mem, *size, "pl_tt_load_font data");
1138
2.00M
    if (*pptt_font_data == 0) {
1139
0
        sfclose(in);
1140
0
        return_error(gs_error_VMerror);
1141
0
    }
1142
2.00M
    sfread(*pptt_font_data + 6, 1, len, in);
1143
2.00M
    sfclose(in);
1144
2.00M
    return 0;
1145
2.00M
}
1146
1147
/* Load a built-in (TrueType) font from external storage. */
1148
int
1149
pl_load_tt_font(stream * in, gs_font_dir * pdir, gs_memory_t * mem,
1150
                long unique_id, pl_font_t ** pplfont, char *font_name)
1151
2.00M
{
1152
2.00M
    byte *tt_font_datap = NULL;
1153
2.00M
    ulong size;
1154
2.00M
    int code;
1155
2.00M
    gs_font_type42 *pfont = NULL;
1156
2.00M
    pl_font_t *plfont = NULL;
1157
2.00M
    byte *file_name = NULL;
1158
2.00M
    gs_const_string pfname;
1159
1160
2.00M
    if (sfilename(in, &pfname) == 0) {
1161
2.00M
        file_name =
1162
2.00M
            gs_alloc_bytes(mem, pfname.size + 1, "pl_load_tt_font file_name");
1163
2.00M
        if (!file_name) {
1164
0
            sfclose(in);
1165
0
            return_error(gs_error_VMerror);
1166
0
        }
1167
        /* the stream code guarantees the string is null terminated */
1168
2.00M
        memcpy(file_name, pfname.data, pfname.size + 1);
1169
2.00M
    }
1170
1171
    /* get the data from the file */
1172
2.00M
    code = pl_alloc_tt_fontfile_buffer(in, mem, &tt_font_datap, &size);
1173
2.00M
    if (code < 0)
1174
0
        goto error;
1175
    /* Make a Type 42 font out of the TrueType data. */
1176
2.00M
    pfont = gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42,
1177
2.00M
                            "pl_tt_load_font(gs_font_type42)");
1178
2.00M
    if (pfont == NULL) {
1179
0
        code = gs_error_VMerror;
1180
0
        goto error;
1181
0
    }
1182
2.00M
    memset(pfont, 0, sizeof(*pfont));
1183
2.00M
    plfont = pl_alloc_font(mem, "pl_tt_load_font(pl_font_t)");
1184
2.00M
    if (plfont == NULL) {
1185
0
        code = gs_error_VMerror;
1186
0
        goto error;
1187
0
    }
1188
1189
    /* Initialize general font boilerplate. */
1190
2.00M
    code = pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, font_name);
1191
2.00M
    if (code < 0)
1192
0
        goto error;
1193
1194
    /* Initialize TrueType font boilerplate. */
1195
2.00M
    plfont->header = tt_font_datap;
1196
2.00M
    plfont->header_size = size;
1197
2.00M
    plfont->scaling_technology = plfst_TrueType;
1198
2.00M
    plfont->font_type = plft_Unicode;
1199
2.00M
    plfont->large_sizes = true;
1200
2.00M
    plfont->offsets.GT = 0;
1201
2.00M
    plfont->is_xl_format = false;
1202
2.00M
    code = pl_fill_in_tt_font(pfont, tt_font_datap, unique_id);
1203
2.00M
    if (code < 0)
1204
0
        goto error;
1205
2.00M
    code = gs_definefont(pdir, (gs_font *) pfont);
1206
2.00M
    if (code < 0)
1207
0
        goto error;
1208
1209
2.00M
    code = pl_fapi_passfont(plfont, 0, NULL, (char *)file_name, NULL, 0);
1210
2.00M
    if (code < 0)
1211
0
        goto error;
1212
2.00M
    if (file_name)
1213
2.00M
        gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1214
1215
2.00M
    *pplfont = plfont;
1216
2.00M
    return 0;
1217
1218
0
error:
1219
0
    gs_free_object(mem, plfont, "pl_tt_load_font(pl_font_t)");
1220
0
    gs_free_object(mem, pfont, "pl_tt_load_font(gs_font_type42)");
1221
0
    pl_free_tt_fontfile_buffer(mem, tt_font_datap);
1222
0
    gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1223
0
    return_error(code);
1224
2.00M
}
1225
1226
/* load resident font data to ram */
1227
int
1228
pl_load_resident_font_data_from_file(gs_memory_t * mem, pl_font_t * plfont)
1229
1.92M
{
1230
1231
1.92M
    ulong len, size;
1232
1.92M
    byte *data;
1233
1234
1.92M
    if (plfont->font_file && !plfont->font_file_loaded) {
1235
48.2k
        stream *in = sfopen(plfont->font_file, "r", mem);
1236
1237
48.2k
        if (in == NULL)
1238
0
            return -1;
1239
        /* note this is exactly the same as the code in pl_load_tt_font */
1240
48.2k
        len = (sfseek(in, 0L, SEEK_END), sftell(in));
1241
48.2k
        size = 6 + len;         /* leave room for segment header */
1242
1243
48.2k
        if (size != (uint) size) {
1244
            /*
1245
             * The font is too big to load in a single piece -- punt.
1246
             * The error message is bogus, but there isn't any more
1247
             * appropriate one.
1248
             */
1249
0
            sfclose(in);
1250
0
            return_error(gs_error_VMerror);
1251
0
        }
1252
48.2k
        srewind(in);
1253
48.2k
        data = gs_alloc_bytes(mem, size, "pl_tt_load_font data");
1254
48.2k
        if (data == 0) {
1255
0
            sfclose(in);
1256
0
            return_error(gs_error_VMerror);
1257
0
        }
1258
48.2k
        sfread(data + 6, 1, len, in);
1259
48.2k
        sfclose(in);
1260
48.2k
        plfont->header = data;
1261
48.2k
        plfont->header_size = size;
1262
48.2k
        plfont->font_file_loaded = true;
1263
48.2k
    }
1264
1.92M
    return 0;
1265
1.92M
}
1266
1267
/* Keep resident font data in (header) and deallocate the memory */
1268
int
1269
pl_store_resident_font_data_in_file(char *font_file, gs_memory_t * mem,
1270
                                    pl_font_t * plfont)
1271
1.63M
{
1272
    /* Free the header data */
1273
1.63M
    if (plfont->header) {
1274
1.63M
        gs_free_object(mem, plfont->header,
1275
1.63M
                       "pl_store_resident_font_data_in_file");
1276
1.63M
        plfont->header = 0;
1277
1.63M
        plfont->header_size = 0;
1278
1.63M
    } else {
1279
        /* nothing to do */
1280
0
        return 0;
1281
0
    }
1282
    /* we don't yet have a filename for this font object. create one
1283
       and store it in the font. */
1284
1.63M
    if (!plfont->font_file) {
1285
1.63M
        plfont->font_file =
1286
1.63M
            (char *)gs_alloc_bytes(mem, strlen(font_file) + 1,
1287
1.63M
                                   "pl_store_resident_font_data_in_file");
1288
1.63M
        if (plfont->font_file == 0)
1289
0
            return -1;
1290
1.63M
        strcpy(plfont->font_file, font_file);
1291
1.63M
    }
1292
    /* designate that the font data is not in RAM */
1293
1.63M
    plfont->font_file_loaded = false;
1294
1.63M
    return 0;
1295
1.63M
}
1296
1297
pl_font_t *
1298
pl_lookup_font_by_pjl_number(pl_dict_t * pfontdict, int pjl_font_number)
1299
430k
{
1300
430k
    pl_dict_enum_t dictp;
1301
430k
    gs_const_string key;
1302
430k
    void *value;
1303
1304
430k
    pl_dict_enum_begin(pfontdict, &dictp);
1305
22.1M
    while (pl_dict_enum_next(&dictp, &key, &value)) {
1306
22.1M
        pl_font_t *plfont = value;
1307
1308
22.1M
        if (plfont->params.pjl_font_number == pjl_font_number)
1309
430k
            return value;
1310
22.1M
    }
1311
0
    return (pl_font_t *) NULL;
1312
430k
}