Coverage Report

Created: 2026-04-09 07:06

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-2025 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
29.0k
#define u16(bptr) pl_get_uint16(bptr)
49
#define s16(bptr) pl_get_int16(bptr)
50
/**** ASSUME uint >= 32 BITS ****/
51
28.9k
#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
1.22M
{
58
1.22M
    pl_font_t *plfont = plf;
59
60
    /* Free the characters. */
61
1.22M
    if (!plfont->data_are_permanent) {
62
1.20M
        if (plfont->glyphs.table) {
63
391
            uint i;
64
65
116k
            for (i = plfont->glyphs.size; i > 0;) {
66
116k
                void *data = (void *)plfont->glyphs.table[--i].data;
67
68
116k
                if (data)
69
2.20k
                    gs_free_object(mem, data, cname);
70
116k
            }
71
391
        }
72
1.20M
        gs_free_object(mem, (void *)plfont->header, cname);
73
1.20M
        plfont->header = 0;     /* see hack note above */
74
1.20M
    }
75
76
    /* free any nodes in the widths cache */
77
1.22M
    pl_font_glyph_width_cache_remove_nodes(plfont);
78
79
    /* Free the font data itself. */
80
1.22M
    gs_free_object(mem, (void *)plfont->char_glyphs.table, cname);
81
1.22M
    gs_free_object(mem, (void *)plfont->glyphs.table, cname);
82
1.22M
    if (plfont->pfont) {        /* might be only partially constructed */
83
1.22M
        gs_purge_font_from_char_caches_completely(plfont->pfont);
84
1.22M
        (void)gs_purge_font(plfont->pfont);
85
1.22M
        gs_free_object(mem, plfont->pfont, cname);
86
1.22M
    }
87
1.22M
    if (plfont->font_file) {
88
915k
        gs_free_object(mem, plfont->font_file, cname);
89
915k
        plfont->font_file = 0;
90
915k
    }
91
1.22M
    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
1.22M
    gs_free_object(mem, plf, cname);
100
1.22M
}
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
0
    if (table_length == 0)
396
0
        return -1;
397
398
0
    {
399
0
        ulong format;
400
0
        int numGlyphs;
401
0
        uint glyph_name_index;
402
0
        const byte *postp;      /* post table pointer */
403
404
0
        ((gs_font_type42 *) pfont)->data.string_proc((gs_font_type42 *) pfont,
405
0
                                                     table_offset,
406
0
                                                     table_length, &postp);
407
0
        format = u32(postp);
408
0
        if (format != 0x20000) {
409
            /* format 1.0 (mac encoding) is a simple table see the TT
410
               spec.  We don't implement this because we don't see it
411
               in practice */
412
0
            dmprintf1(pfont->memory, "unknown post table format %lX\n",
413
0
                      format);
414
0
            return -1;
415
0
        }
416
        /* skip over the post header */
417
0
        numGlyphs = (int)u16(postp + 32);
418
0
        if ((int)glyph > numGlyphs - 1) {
419
0
            if_debug1m('=', pfont->memory,
420
0
                       "[=]glyph index %lx out of range\n", glyph);
421
0
            return -1;
422
0
        }
423
        /* glyph name index starts at post + 34 each entry is 2 bytes */
424
0
        glyph_name_index = u16(postp + 34 + (glyph * 2));
425
        /* this shouldn't happen */
426
0
        if (glyph_name_index > 0x7fff)
427
0
            return -1;
428
        /* mac easy */
429
0
        if (glyph_name_index < 258) {
430
431
0
            pstr->data = (const byte *)pl_mac_names[glyph_name_index];
432
0
            pstr->size = strlen((const char *)pstr->data);
433
0
            return 0;
434
            /* not mac */
435
0
        } else {
436
0
            byte *mydata;
437
            /* and here's the tricky part */
438
0
            const byte *pascal_stringp = postp + 34 + (numGlyphs * 2);
439
            /* 0 - 257 lives in the mac table above */
440
0
            glyph_name_index -= 258;
441
            /* The string we want is the index'th pascal string,
442
               so we "hop" to each length byte "index" times. */
443
0
            while (glyph_name_index > 0) {
444
0
                pascal_stringp += ((int)(*pascal_stringp) + 1);
445
0
                glyph_name_index--;
446
0
            }
447
            /* length byte */
448
0
            pstr->size = (int)(*pascal_stringp);
449
            /* + 1 is for the length byte */
450
0
            pstr->data = pascal_stringp + 1;
451
            /* sanity check */
452
0
            if (pstr->data + pstr->size > postp + table_length ||
453
0
                pstr->data - 1 < postp) {
454
0
                dmprintf(pfont->memory, "data out of range\n");
455
0
                return -1;
456
0
            }
457
            /* sigh - we have to allocate a copy of the data - by the
458
               time a high level device makes use of it the font data
459
               may be freed.  Track the allocated memory in our
460
               font 'wrapper' so we can free it when we free tha font wrapper.
461
             */
462
0
            mydata =
463
0
                gs_alloc_bytes(pfont->memory, pstr->size + 1,
464
0
                               "glyph to name");
465
0
            if (mydata == 0)
466
0
                return -1;
467
0
            memcpy(mydata, pascal_stringp + 1, pstr->size);
468
0
            pstr->data = mydata;
469
0
            if (plfont->names == NULL) {
470
0
                plfont->names = (char **)gs_alloc_bytes(pfont->memory, 256 * sizeof (char *), "names storage");
471
0
                if (plfont->names == NULL) {
472
0
                    gs_free_object(pfont->memory, (byte *)pstr->data, "free string on error");
473
0
                    pstr->data = NULL;
474
0
                    pstr->size = 0;
475
0
                    return -1;
476
0
                }
477
0
                plfont->max_name_index = 255;
478
0
                plfont->next_name_index = 0;
479
0
                memset(plfont->names, 0x00, 256 * sizeof (char *));
480
0
            }
481
0
            if (plfont->next_name_index > plfont->max_name_index) {
482
0
                char **temp = NULL;
483
0
                temp = (char **)gs_alloc_bytes(pfont->memory, (size_t)(plfont->max_name_index + 256) * sizeof (char *), "names storage");
484
0
                if (temp == NULL) {
485
0
                    gs_free_object(pfont->memory, (byte *)pstr->data, "free string on error");
486
0
                    pstr->data = NULL;
487
0
                    pstr->size = 0;
488
0
                    return -1;
489
0
                }
490
0
                memset(temp, 0x00, (plfont->max_name_index + 256) * sizeof (char *));
491
0
                memcpy(temp, plfont->names, plfont->max_name_index * sizeof(char *));
492
0
                gs_free_object(pfont->memory, (void *)plfont->names, "realloc names storage");
493
0
                plfont->names = temp;
494
0
                plfont->max_name_index += 256;
495
0
            }
496
0
            plfont->names[plfont->next_name_index++] = (char *)pstr->data;
497
0
            return 0;
498
0
        }
499
0
    }
500
0
    return 0;
501
0
}
502
503
/* Get the unicode valude for a glyph */
504
static int
505
pl_decode_glyph(gs_font * font, gs_glyph glyph, int ch, ushort *unicode_return, unsigned int length)
506
0
{
507
0
    unsigned char *ucode = (unsigned char *)unicode_return;
508
509
0
    if (ch < 0 || ch > 255)
510
0
        return (int) GS_NO_CHAR;
511
512
0
    if (length == 0)
513
0
        return 2;
514
515
#if ARCH_IS_BIG_ENDIAN
516
    *unicode_return = (ushort)ch;
517
#else
518
0
    ucode[0] = 0x00;
519
0
    ucode[1] = ch & 0xff;
520
0
#endif
521
0
    return 2;
522
0
}
523
524
/* ---------------- Width cache ---------------- */
525
static int
526
pl_font_glyph_width_cache_node_add(pl_font_t *plfont,
527
                              uint char_code, gs_point * pwidth)
528
1.46M
{
529
1.46M
    pl_glyph_width_node_t *node;
530
531
    /* We can't safely cache widths for bitmap fonts */
532
1.46M
    if (plfont->scaling_technology == plfst_bitmap) {
533
0
        return(0);
534
0
    }
535
536
1.46M
    if (plfont->widths_cache_nitems > PL_MAX_WIDTHS_CACHE_NITEMS) {
537
456
        pl_font_glyph_width_cache_remove_nodes(plfont);
538
456
    }
539
540
1.46M
    node = (pl_glyph_width_node_t *) gs_alloc_bytes(plfont->pfont->memory,
541
1.46M
                                                 sizeof
542
1.46M
                                                 (pl_glyph_width_node_t),
543
1.46M
                                                 "pl_glyph_width_cache_node_add");
544
545
1.46M
    if (node == NULL) {
546
        /* if we couldn't allocate a node, it probably doesn't hurt
547
         * to get rid of all the nodes we have.
548
         */
549
0
        pl_font_glyph_width_cache_remove_nodes(plfont);
550
0
        return -1;
551
0
    }
552
553
1.46M
    node->next = plfont->widths_cache;
554
1.46M
    plfont->widths_cache = node;
555
1.46M
    plfont->widths_cache_nitems++;
556
557
1.46M
    node->char_code = char_code;
558
1.46M
    node->font_id = plfont->pfont->id;
559
1.46M
    node->width = *pwidth;
560
561
1.46M
    return 0;
562
1.46M
}
563
564
565
static int
566
pl_font_glyph_width_cache_node_search(const pl_font_t *plfont, uint char_code,
567
                                 gs_point * pwidth)
568
16.7M
{
569
16.7M
    pl_glyph_width_node_t *current = plfont->widths_cache;
570
571
1.47G
    while (current) {
572
1.46G
        if (char_code == current->char_code) {
573
15.1M
            *pwidth = current->width;
574
15.1M
            return 0;
575
15.1M
        }
576
1.45G
        current = current->next;
577
1.45G
    }
578
1.60M
    return -1;
579
16.7M
}
580
581
582
/* ---------------- Public procedures ---------------- */
583
/* character width */
584
585
void
586
pl_font_glyph_width_cache_remove_nodes(pl_font_t *plfont)
587
1.46M
{
588
1.46M
    pl_glyph_width_node_t *current = plfont->widths_cache;
589
590
2.93M
    while (current) {
591
1.46M
        pl_glyph_width_node_t *next = current->next;
592
593
1.46M
        gs_free_object(plfont->pfont->memory, current, "pl_glyph_width_list_remove");
594
1.46M
        current = next;
595
1.46M
    }
596
1.46M
    plfont->widths_cache = NULL;
597
1.46M
    plfont->widths_cache_nitems = 0;
598
1.46M
    return;
599
1.46M
}
600
601
int
602
pl_font_char_width(const pl_font_t * plfont, const void *pgs,
603
                   gs_char char_code, gs_point * pwidth)
604
16.7M
{
605
16.7M
    int code = 0;
606
607
16.7M
    if (pl_font_glyph_width_cache_node_search(plfont, char_code, pwidth) >= 0) {
608
15.1M
        return(code);
609
15.1M
    }
610
611
1.60M
    if ((code = (*(plfont)->char_width) (plfont, pgs, char_code, pwidth)) == 0) {
612
613
        /* at least here, ignore the return value - if we fail to add a node
614
         * to the cache, we can reasonably attempt to carry on without it
615
         */
616
1.46M
        (void)pl_font_glyph_width_cache_node_add((pl_font_t *)plfont, char_code, pwidth);
617
1.46M
    }
618
1.60M
    return code;
619
16.7M
}
620
621
/* character width */
622
int
623
pl_font_char_metrics(const pl_font_t * plfont, const void *pgs,
624
                     gs_char char_code, float metrics[4])
625
447k
{
626
447k
    return (*(plfont)->char_metrics) (plfont, pgs, char_code, metrics);
627
447k
}
628
629
/* Allocate a font. */
630
pl_font_t *
631
pl_alloc_font(gs_memory_t * mem, client_name_t cname)
632
1.22M
{
633
1.22M
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
634
635
1.22M
    if (plfont) {               /* Initialize pointers. */
636
1.22M
        plfont->pfont = 0;
637
1.22M
        plfont->header = 0;
638
1.22M
        plfont->glyphs.table = 0;
639
1.22M
        plfont->char_glyphs.table = 0;
640
        /* Initialize other defaults. */
641
1.22M
        plfont->orient = 0;
642
1.22M
        plfont->allow_vertical_substitutes = false;
643
1.22M
        plfont->bold_fraction = 0;
644
1.22M
        plfont->font_file = 0;
645
1.22M
        plfont->resolution.x = plfont->resolution.y = 0;
646
1.22M
        plfont->params.proportional_spacing = true;
647
1.22M
        memset(plfont->character_complement, 0xff, 8);
648
1.22M
        plfont->offsets.GC = plfont->offsets.GT = plfont->offsets.VT = -1;
649
1.22M
        plfont->pts_per_inch = 72.0;    /* normal value */
650
1.22M
        plfont->widths_cache = NULL;
651
1.22M
        plfont->widths_cache_nitems = 0;
652
1.22M
        plfont->names = NULL;
653
1.22M
        plfont->max_name_index = 0;
654
1.22M
        plfont->next_name_index = 0;
655
1.22M
    }
656
1.22M
    return plfont;
657
1.22M
}
658
659
/* Structure descriptors for cloning fonts */
660
gs_private_st_ptrs1(st_pl_font_glyph_f, pl_font_glyph_t, "pl_font_glyph_t",
661
                    pl_font_glyph_enum_ptrs_f, pl_font_glyph_reloc_ptrs_f,
662
                    data);
663
gs_private_st_element(st_pl_font_glyph_element_f, pl_font_glyph_t,
664
                      "pl_font_glyph_t[]", pl_font_glyph_elt_enum_ptrs_f,
665
                      pl_font_glyph_elt_reloc_ptrs_f, st_pl_font_glyph_f);
666
667
pl_font_t *
668
pl_clone_font(const pl_font_t * src, gs_memory_t * mem, client_name_t cname)
669
0
{
670
0
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
671
672
0
    if (plfont == 0)
673
0
        return 0;
674
    /* copy technology common parts */
675
0
    plfont->storage = src->storage;
676
0
    plfont->header_size = src->header_size;
677
0
    plfont->scaling_technology = src->scaling_technology;
678
0
    plfont->is_xl_format = src->is_xl_format;
679
0
    plfont->allow_vertical_substitutes = src->allow_vertical_substitutes;
680
0
    plfont->font_type = src->font_type;
681
0
    plfont->char_width = src->char_width;
682
0
    plfont->char_metrics = src->char_metrics;
683
0
    plfont->large_sizes = src->large_sizes;
684
0
    plfont->resolution = src->resolution;
685
0
    plfont->params = src->params;
686
0
    plfont->pts_per_inch = src->pts_per_inch;
687
0
    plfont->font_file_loaded = src->font_file_loaded;
688
0
    plfont->orient = src->orient;
689
0
    plfont->bold_fraction = src->bold_fraction;
690
0
    plfont->widths_cache = NULL;
691
0
    plfont->widths_cache_nitems = 0;
692
0
    {
693
0
        int i;
694
695
0
        for (i = 0; i < sizeof(src->character_complement); i++)
696
0
            plfont->character_complement[i] = src->character_complement[i];
697
0
    }
698
0
    plfont->offsets = src->offsets;
699
0
    plfont->header = gs_alloc_bytes(mem, src->header_size, cname);
700
0
    if (plfont->header == 0)
701
0
        return 0;
702
0
    memcpy(plfont->header, src->header, src->header_size);
703
704
0
    plfont->names = NULL;
705
0
    plfont->max_name_index = 0;
706
0
    plfont->next_name_index = 0;
707
708
0
    if (src->font_file) {
709
0
        plfont->font_file =
710
0
            (char *)gs_alloc_bytes(mem, strlen(src->font_file) + 1,
711
0
                                   "pl_clone_font");
712
0
        if (plfont->font_file == 0)
713
0
            return 0;           /* #NB errors!!! */
714
0
        strcpy(plfont->font_file, src->font_file);
715
0
    } else
716
0
        plfont->font_file = 0;
717
    /* technology specific setup */
718
0
    switch (plfont->scaling_technology) {
719
0
        case plfst_bitmap:
720
0
            {
721
0
                gs_font_base *pfont =
722
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
723
0
                                    cname);
724
0
                if (pfont == 0)
725
0
                    return 0;
726
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
727
0
                                mem, "nameless_font");
728
0
                pl_fill_in_bitmap_font(pfont, gs_next_ids(mem, 1));
729
0
                break;
730
0
            }
731
0
        case plfst_Intellifont:
732
0
            {
733
0
                gs_font_base *pfont =
734
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
735
0
                                    cname);
736
0
                if (pfont == 0)
737
0
                    return 0;
738
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
739
0
                                mem, "nameless_font");
740
0
                pl_fill_in_intelli_font(pfont, gs_next_ids(mem, 1));
741
0
                break;
742
0
            }
743
0
        case plfst_TrueType:
744
0
            {
745
0
                {
746
0
                    gs_font_type42 *pfont =
747
0
                        gs_alloc_struct(mem, gs_font_type42,
748
0
                                        &st_gs_font_type42, cname);
749
                    /* detect if a truetype font is downloaded or
750
                       internal.  There must be a better way... */
751
0
                    gs_font_type42 *pfont_src = (gs_font_type42 *) src->pfont;
752
0
                    bool downloaded =
753
0
                        (pfont_src->data.get_outline == pl_tt_get_outline);
754
0
                    if (pfont == 0)
755
0
                        return 0;
756
0
                    pl_fill_in_font((gs_font *) pfont, plfont,
757
0
                                    src->pfont->dir, mem, "nameless_font");
758
0
                    pl_fill_in_tt_font(pfont, downloaded ? NULL : src->header,
759
0
                                       gs_next_ids(mem, 1));
760
0
                }
761
0
                break;
762
0
            }
763
0
        default:
764
0
            return 0;
765
0
    }
766
0
    if (src->char_glyphs.table != 0) {
767
        /* HAS may gs_alloc_struct_array() here but this is
768
           consistant with pl_tt_alloc_char_glyphs() */
769
0
        pl_tt_char_glyph_t *char_glyphs =
770
0
            (pl_tt_char_glyph_t *) gs_alloc_byte_array(mem,
771
0
                                                       src->char_glyphs.size,
772
0
                                                       sizeof
773
0
                                                       (pl_tt_char_glyph_t),
774
0
                                                       cname);
775
0
        int i;
776
777
0
        if (char_glyphs == 0)
778
0
            return 0;
779
0
        for (i = 0; i < src->char_glyphs.size; i++)
780
0
            char_glyphs[i] = src->char_glyphs.table[i];
781
        /* once again a copy struct shortcut and then are restore
782
           of the char_glyphs.table pointer */
783
0
        plfont->char_glyphs = src->char_glyphs;
784
0
        plfont->char_glyphs.table = char_glyphs;
785
0
    } else                      /* no character glyph table data */
786
0
        plfont->char_glyphs = src->char_glyphs;
787
788
0
    if (src->glyphs.table != 0) {
789
0
        int i;
790
791
0
        plfont->glyphs.table =
792
0
            gs_alloc_struct_array(mem, src->glyphs.size, pl_font_glyph_t,
793
0
                                  &st_pl_font_glyph_element_f, cname);
794
0
        if (plfont->glyphs.table == NULL)
795
0
            return 0;
796
0
        plfont->glyphs.used = src->glyphs.used;
797
0
        plfont->glyphs.limit = src->glyphs.limit;
798
0
        plfont->glyphs.size = src->glyphs.size;
799
0
        plfont->glyphs.skip = src->glyphs.skip;
800
0
        for (i = 0; i < src->glyphs.size; i++) {
801
0
            const byte *data = src->glyphs.table[i].data;
802
0
            byte *char_data;
803
804
0
            plfont->glyphs.table[i].glyph = src->glyphs.table[i].glyph;
805
0
            plfont->glyphs.table[i].data = 0;
806
0
            if (data) {
807
0
                uint size = src->glyphs.table[i].data_len;
808
0
                char_data = gs_alloc_bytes(mem, size, cname);
809
0
                if (char_data == 0)
810
0
                    return 0;
811
0
                memcpy(char_data, data, size);
812
0
                plfont->glyphs.table[i].data = char_data;
813
0
                plfont->glyphs.table[i].data_len = size;
814
0
            }
815
816
0
        }
817
0
    } else                      /* no glyph table */
818
0
        plfont->glyphs = src->glyphs;
819
0
    return plfont;
820
0
}
821
822
/* Fill in generic font boilerplate. NB TODO examine duplication with
823
   gs_font_alloc().  The font name must not contain spaces.  It is
824
   used for PDF output and Acrobat (some versions) do not process the
825
   file correctly with spaces in the name. */
826
int
827
pl_fill_in_font(gs_font * pfont, pl_font_t * plfont, gs_font_dir * pdir,
828
                gs_memory_t * mem, const char *font_name)
829
1.26M
{
830
1.26M
    gs_font_base *pbfont = (gs_font_base *) pfont;
831
832
1.26M
    plfont->pfont = pfont;
833
    /* Initialize generic font data. */
834
1.26M
    gs_make_identity(&pbfont->orig_FontMatrix);
835
1.26M
    gs_make_identity(&pbfont->FontMatrix);
836
1.26M
    pbfont->next = pbfont->prev = 0;
837
1.26M
    pbfont->memory = mem;
838
1.26M
    pbfont->dir = pdir;
839
1.26M
    pbfont->is_resource = false;
840
1.26M
    gs_notify_init(&pbfont->notify_list, gs_memory_stable(mem));
841
1.26M
    pbfont->base = (gs_font *) pbfont;
842
1.26M
    pbfont->client_data = plfont;
843
1.26M
    pbfont->WMode = 0;
844
1.26M
    pbfont->PaintType = 0;
845
1.26M
    pbfont->StrokeWidth = 0;
846
1.26M
    pbfont->is_cached = 0;
847
1.26M
    pbfont->procs.init_fstack = gs_default_init_fstack;
848
1.26M
    pbfont->procs.next_char_glyph = gs_default_next_char_glyph;
849
1.26M
    pbfont->FAPI = NULL;
850
1.26M
    pbfont->FAPI_font_data = NULL;
851
852
1.26M
    pbfont->procs.glyph_name = pl_glyph_name;
853
1.26M
    pbfont->procs.decode_glyph = pl_decode_glyph;
854
    /* NB pbfont->procs.callbacks.known_encode = pl_known_encode; */
855
1.26M
    pbfont->procs.define_font = gs_no_define_font;
856
1.26M
    pbfont->procs.make_font = gs_no_make_font;
857
1.26M
    pbfont->procs.font_info = gs_default_font_info;
858
1.26M
    pbfont->procs.glyph_info = gs_default_glyph_info;
859
1.26M
    pbfont->procs.glyph_outline = gs_no_glyph_outline;
860
1.26M
    pbfont->id = gs_next_ids(mem, 1);
861
1.26M
    {
862
1.26M
        size_t sz = strlen(font_name);
863
1.26M
        gs_font_name *fnm = &pbfont->font_name;
864
1.26M
        gs_font_name *knm = &pbfont->key_name;
865
866
1.26M
        if (sz > gs_font_name_max)
867
0
            sz = gs_font_name_max;
868
1.26M
        fnm->size = knm->size = sz;
869
870
1.26M
        memcpy(fnm->chars, font_name, sz);
871
1.26M
        fnm->chars[sz] = 0;
872
873
1.26M
        memcpy(knm->chars, font_name, sz);
874
1.26M
        knm->chars[sz] = 0;
875
1.26M
    }
876
1.26M
    return 0;
877
1.26M
}
878
879
/* Fill in bitmap font boilerplate. */
880
void
881
pl_fill_in_bitmap_font(gs_font_base * pfont, long unique_id)
882
14.4k
{
883
14.4k
    pfont->FontType = ft_PCL_user_defined;
884
14.4k
    pfont->BitmapWidths = true;
885
14.4k
    pfont->ExactSize = fbit_use_bitmaps;
886
14.4k
    pfont->InBetweenSize = fbit_use_bitmaps;
887
14.4k
    pfont->TransformedChar = fbit_transform_bitmaps;
888
14.4k
    pl_bitmap_init_procs(pfont);
889
    /* We have no idea what the FontBBox should be. */
890
14.4k
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
891
14.4k
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
892
14.4k
    uid_set_UniqueID(&pfont->UID, unique_id);
893
14.4k
    pfont->encoding_index = 1;          /****** WRONG ******/
894
14.4k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
895
14.4k
}
896
897
/* Fill in TrueType font boilerplate. */
898
int
899
pl_fill_in_tt_font(gs_font_type42 * pfont, void *data, long unique_id)
900
1.20M
{
901
1.20M
    pfont->FontType = ft_TrueType;
902
1.20M
    pfont->BitmapWidths = true;
903
1.20M
    pfont->ExactSize = fbit_use_outlines;
904
1.20M
    pfont->InBetweenSize = fbit_use_outlines;
905
1.20M
    pfont->TransformedChar = fbit_use_outlines;
906
    /* Initialize base font data. */
907
    /*
908
     * We can't set the FontBBox correctly until we've initialized the
909
     * Type 42 specific data, but we need to set it to an empty box now
910
     * for the sake of gs_type42_font_init.
911
     */
912
1.20M
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
913
1.20M
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
914
1.20M
    uid_set_UniqueID(&pfont->UID, unique_id);
915
1.20M
    pfont->encoding_index = 1;          /****** WRONG ******/
916
1.20M
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
917
    /* Initialize Type 42 specific data. */
918
1.20M
    pfont->data.proc_data = data;
919
1.20M
    pl_tt_init_procs(pfont);
920
1.20M
    {
921
1.20M
        int code = gs_type42_font_init(pfont, 0);
922
923
1.20M
        if (code < 0)
924
5
            return code;
925
1.20M
    }
926
    /* disable unused FAPI */
927
1.20M
    pfont->FAPI = 0;
928
1.20M
    pfont->FAPI_font_data = 0;
929
1.20M
    pl_tt_finish_init(pfont, !data);
930
1.20M
    return 0;
931
1.20M
}
932
933
/* Fill in Intellifont boilerplate. */
934
void
935
pl_fill_in_intelli_font(gs_font_base * pfont, long unique_id)
936
0
{                               /* Intellifonts have an 8782-unit design space. */
937
0
    {
938
0
        gs_matrix mat;
939
940
0
        gs_make_scaling(1.0 / 8782, 1.0 / 8782, &mat);
941
0
        gs_matrix_translate(&mat, -2980.0, -5380.0, &pfont->orig_FontMatrix);
942
0
    }
943
0
    pfont->FontType = ft_MicroType;
944
0
    pfont->BitmapWidths = true;
945
0
    pfont->ExactSize = fbit_use_outlines;
946
0
    pfont->InBetweenSize = fbit_use_outlines;
947
0
    pfont->TransformedChar = fbit_use_outlines;
948
    /* We have no idea what the FontBBox should be. */
949
0
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
950
0
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
951
0
    uid_set_UniqueID(&pfont->UID, unique_id);
952
0
    pfont->encoding_index = 1;          /****** WRONG ******/
953
0
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
954
0
    pl_intelli_init_procs(pfont);
955
0
}
956
957
/*
958
 * Set large_sizes, scaling_technology, character_complement, offsets
959
 * (for TrueType fonts), and resolution (for bitmap fonts) by scanning
960
 * the segments of a segmented downloaded font.
961
 * This is used for PCL5 Format 15 and 16 fonts and for PCL XL fonts.
962
 * fst_offset is the offset of the Font Scaling Technology and Variety bytes;
963
 * the segment data runs from start_offset up to end_offset.
964
 * large_sizes = false indicates 2-byte segment sizes, true indicates 4-byte.
965
 */
966
int
967
pl_font_scan_segments(const gs_memory_t * mem,
968
                      pl_font_t * plfont, int fst_offset, int start_offset,
969
                      long end_offset, bool large_sizes,
970
                      const pl_font_offset_errors_t * pfoe)
971
14.4k
{
972
14.4k
    const byte *header = plfont->header;
973
14.4k
    pl_font_scaling_technology_t fst = header[fst_offset];
974
14.4k
    int wsize = (large_sizes ? 4 : 2);
975
14.4k
    const byte *segment = header + start_offset;
976
14.4k
    const byte *end = header + end_offset;
977
14.4k
    const byte *null_segment = end - (2 + wsize);
978
14.4k
    bool found = false;
979
14.4k
    ulong seg_size;
980
14.4k
    int illegal_font_data = pfoe->illegal_font_data;
981
982
14.4k
#define return_scan_error(err)\
983
14.4k
  return_error((err) ? (err) : illegal_font_data);
984
985
14.4k
    if (memcmp(null_segment, "\377\377", 2) /* NULL segment header */ )
986
14.4k
        return_scan_error(pfoe->missing_required_segment);
987
14.4k
    if (memcmp(null_segment + 2, "\0\0\0\0", wsize) /* NULL segment size */ )
988
14.4k
        return_scan_error(pfoe->illegal_null_segment_size);
989
14.4k
    switch (fst) {
990
14.3k
        case plfst_bitmap:
991
14.4k
        case plfst_TrueType:
992
14.4k
            break;
993
0
        default:
994
0
            return_scan_error(pfoe->illegal_font_header_fields);
995
14.4k
    }
996
14.4k
    if (header[fst_offset + 1]) /* variety, must be 0 */
997
14.4k
        return_scan_error(pfoe->illegal_font_header_fields);
998
    /* Scan the segments. */
999
43.3k
    for (; end - segment >= 2 + wsize; segment += 2 + wsize + seg_size) {
1000
28.9k
        uint seg_id = u16(segment);
1001
28.9k
        const byte *sdata = segment + 2 + wsize;
1002
1003
28.9k
#define id2(c1,c2) (((uint)(c1) << 8) + (c2))
1004
1005
28.9k
        seg_size = (large_sizes ? u32(segment + 2) : u16(segment + 2));
1006
28.9k
        if (seg_size + 2 + wsize > end - segment)
1007
2
            return_error(illegal_font_data);
1008
        /* Handle segments common to all fonts. */
1009
28.9k
        switch (seg_id) {
1010
14.4k
            case 0xffff:       /* NULL segment ID */
1011
14.4k
                if (segment != null_segment)
1012
0
                    return_error(illegal_font_data);
1013
14.4k
                continue;
1014
14.4k
            case id2('V', 'I'):
1015
0
                continue;
1016
0
            case id2('C', 'C'):
1017
0
                if (seg_size != 8)
1018
0
                    return_error(illegal_font_data);
1019
0
                memcpy(plfont->character_complement, sdata, 8);
1020
0
                continue;
1021
14.4k
            default:
1022
14.4k
                ;
1023
28.9k
        }
1024
        /* Handle segments specific to the scaling technology. */
1025
14.4k
        if (fst == plfst_bitmap)
1026
14.3k
            switch (seg_id) {
1027
14.3k
                case id2('B', 'R'):
1028
14.3k
                    if (seg_size != 4)
1029
14.3k
                        return_scan_error(pfoe->illegal_BR_segment);
1030
14.3k
                    {
1031
14.3k
                        uint xres = pl_get_uint16(sdata);
1032
14.3k
                        uint yres = pl_get_uint16(sdata + 2);
1033
1034
14.3k
                        if (xres == 0 || yres == 0)
1035
14.3k
                            return_scan_error(pfoe->illegal_BR_segment);
1036
14.3k
                        plfont->resolution.x = xres;
1037
14.3k
                        plfont->resolution.y = yres;
1038
14.3k
                    }
1039
14.3k
                    found = true;
1040
14.3k
                    break;
1041
1
                default:
1042
1
                    if (pfoe->illegal_font_segment < 0)
1043
1
                        return_error(pfoe->illegal_font_segment);
1044
14.3k
        } else                  /* fst == plfst_TrueType */
1045
89
            switch (seg_id) {
1046
89
                case id2('G', 'T'):
1047
                    /*
1048
                     * We don't do much checking here, but we do check that
1049
                     * the segment starts with a table directory that
1050
                     * includes at least 3 elements (gdir, head,
1051
                     * maxp -- but we don't check the actual names).
1052
                     */
1053
89
                    if (seg_size < 12 + 5 * 16 ||
1054
                        /* memcmp(sdata, "\000\001\000\000", 4) || */
1055
89
                        u16(sdata + 4) < 3)
1056
89
                        return_scan_error(pfoe->illegal_GT_segment);
1057
89
                    plfont->offsets.GT = segment - header;
1058
89
                    found = true;
1059
89
                    break;
1060
0
                case id2('G', 'C'):
1061
0
                    if (seg_size < 6 || u16(sdata) != 0 ||
1062
0
                        seg_size != u16(sdata + 4) * 6 + 6)
1063
0
                        return_scan_error(pfoe->illegal_GC_segment);
1064
0
                    plfont->offsets.GC = segment - header;
1065
0
                    break;
1066
0
                case id2('V', 'T'):
1067
                    /* Check for end of table mark */
1068
0
                    if ((seg_size & 3) != 0 || seg_size < 4 ||
1069
0
                        u16(sdata + seg_size - 4) != 0xffff)
1070
0
                        return_scan_error(pfoe->illegal_VT_segment);
1071
                    /* Check for table sorted by horizontal glyph ID */
1072
0
                    {
1073
0
                        uint i;
1074
1075
0
                        for (i = 0; i < seg_size - 4; i += 4)
1076
0
                            if (u16(sdata + i) > u16(sdata + i + 4))
1077
0
                                return_scan_error(pfoe->illegal_VT_segment);
1078
0
                    }
1079
0
                    plfont->offsets.VT = segment - header;
1080
0
                    break;
1081
0
                case id2('V', 'E'):    /* nb unimplemented */
1082
0
                    break;
1083
0
                case id2('V', 'R'):    /* nb unimplemented */
1084
0
                    break;
1085
0
                case id2('C', 'E'):    /* nb unimplemented */
1086
0
                    break;
1087
0
                default:
1088
0
                    if (pfoe->illegal_font_segment < 0)
1089
0
                        return_error(pfoe->illegal_font_segment);
1090
89
            }
1091
14.4k
#undef id2
1092
14.4k
    }
1093
14.4k
    if (!found)
1094
14.4k
        return_scan_error(pfoe->missing_required_segment);
1095
14.4k
    if (segment != end)
1096
0
        return_error(illegal_font_data);
1097
14.4k
    plfont->large_sizes = large_sizes;
1098
14.4k
    plfont->scaling_technology = fst;
1099
14.4k
    return 0;
1100
14.4k
#undef return_scan_error
1101
14.4k
}
1102
1103
int
1104
pl_free_tt_fontfile_buffer(gs_memory_t * mem, byte * ptt_font_data)
1105
0
{
1106
0
    gs_free_object(mem, ptt_font_data, "pl_tt_load_font data");
1107
0
    return 0;
1108
0
}
1109
1110
int
1111
pl_alloc_tt_fontfile_buffer(stream * in, gs_memory_t * mem,
1112
                            byte ** pptt_font_data, ulong * size)
1113
1.20M
{
1114
1.20M
    ulong len = (sfseek(in, 0L, SEEK_END), sftell(in));
1115
1116
1.20M
    *size = 6 + len;            /* leave room for segment header */
1117
1.20M
    if (*size != (uint) (*size)) {
1118
        /*
1119
         * The font is too big to load in a single piece -- punt.
1120
         * The error message is bogus, but there isn't any more
1121
         * appropriate one.
1122
         */
1123
0
        sfclose(in);
1124
0
        return_error(gs_error_VMerror);
1125
0
    }
1126
1.20M
    srewind(in);
1127
1.20M
    *pptt_font_data = gs_alloc_bytes(mem, *size, "pl_tt_load_font data");
1128
1.20M
    if (*pptt_font_data == 0) {
1129
0
        sfclose(in);
1130
0
        return_error(gs_error_VMerror);
1131
0
    }
1132
1.20M
    sfread(*pptt_font_data + 6, 1, len, in);
1133
1.20M
    sfclose(in);
1134
1.20M
    return 0;
1135
1.20M
}
1136
1137
/* Load a built-in (TrueType) font from external storage. */
1138
int
1139
pl_load_tt_font(stream * in, gs_font_dir * pdir, gs_memory_t * mem,
1140
                long unique_id, pl_font_t ** pplfont, char *font_name)
1141
1.20M
{
1142
1.20M
    byte *tt_font_datap = NULL;
1143
1.20M
    ulong size;
1144
1.20M
    int code;
1145
1.20M
    gs_font_type42 *pfont = NULL;
1146
1.20M
    pl_font_t *plfont = NULL;
1147
1.20M
    byte *file_name = NULL;
1148
1.20M
    gs_const_string pfname;
1149
1150
1.20M
    if (sfilename(in, &pfname) == 0) {
1151
1.20M
        file_name =
1152
1.20M
            gs_alloc_bytes(mem, pfname.size + 1, "pl_load_tt_font file_name");
1153
1.20M
        if (!file_name) {
1154
0
            sfclose(in);
1155
0
            return_error(gs_error_VMerror);
1156
0
        }
1157
        /* the stream code guarantees the string is null terminated */
1158
1.20M
        memcpy(file_name, pfname.data, pfname.size + 1);
1159
1.20M
    }
1160
1161
    /* get the data from the file */
1162
1.20M
    code = pl_alloc_tt_fontfile_buffer(in, mem, &tt_font_datap, &size);
1163
1.20M
    if (code < 0)
1164
0
        goto error;
1165
    /* Make a Type 42 font out of the TrueType data. */
1166
1.20M
    pfont = gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42,
1167
1.20M
                            "pl_tt_load_font(gs_font_type42)");
1168
1.20M
    if (pfont == NULL) {
1169
0
        code = gs_error_VMerror;
1170
0
        goto error;
1171
0
    }
1172
1.20M
    memset(pfont, 0, sizeof(*pfont));
1173
1.20M
    plfont = pl_alloc_font(mem, "pl_tt_load_font(pl_font_t)");
1174
1.20M
    if (plfont == NULL) {
1175
0
        code = gs_error_VMerror;
1176
0
        goto error;
1177
0
    }
1178
1179
    /* Initialize general font boilerplate. */
1180
1.20M
    code = pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, font_name);
1181
1.20M
    if (code < 0)
1182
0
        goto error;
1183
1184
    /* Initialize TrueType font boilerplate. */
1185
1.20M
    plfont->header = tt_font_datap;
1186
1.20M
    plfont->header_size = size;
1187
1.20M
    plfont->scaling_technology = plfst_TrueType;
1188
1.20M
    plfont->font_type = plft_Unicode;
1189
1.20M
    plfont->large_sizes = true;
1190
1.20M
    plfont->offsets.GT = 0;
1191
1.20M
    plfont->is_xl_format = false;
1192
1.20M
    code = pl_fill_in_tt_font(pfont, tt_font_datap, unique_id);
1193
1.20M
    if (code < 0)
1194
0
        goto error;
1195
1.20M
    code = gs_definefont(pdir, (gs_font *) pfont);
1196
1.20M
    if (code < 0)
1197
0
        goto error;
1198
1199
1.20M
    code = pl_fapi_passfont(plfont, 0, NULL, (char *)file_name, NULL, 0);
1200
1.20M
    if (code < 0)
1201
0
        goto error;
1202
1.20M
    if (file_name)
1203
1.20M
        gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1204
1205
1.20M
    *pplfont = plfont;
1206
1.20M
    return 0;
1207
1208
0
error:
1209
0
    gs_free_object(mem, plfont, "pl_tt_load_font(pl_font_t)");
1210
0
    gs_free_object(mem, pfont, "pl_tt_load_font(gs_font_type42)");
1211
0
    pl_free_tt_fontfile_buffer(mem, tt_font_datap);
1212
0
    gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1213
0
    return_error(code);
1214
1.20M
}
1215
1216
/* load resident font data to ram */
1217
int
1218
pl_load_resident_font_data_from_file(gs_memory_t * mem, pl_font_t * plfont)
1219
719k
{
1220
1221
719k
    ulong len, size;
1222
719k
    byte *data;
1223
1224
719k
    if (plfont->font_file && !plfont->font_file_loaded) {
1225
38.1k
        stream *in = sfopen(plfont->font_file, "r", mem);
1226
1227
38.1k
        if (in == NULL)
1228
0
            return -1;
1229
        /* note this is exactly the same as the code in pl_load_tt_font */
1230
38.1k
        len = (sfseek(in, 0L, SEEK_END), sftell(in));
1231
38.1k
        size = 6 + len;         /* leave room for segment header */
1232
1233
38.1k
        if (size != (uint) size) {
1234
            /*
1235
             * The font is too big to load in a single piece -- punt.
1236
             * The error message is bogus, but there isn't any more
1237
             * appropriate one.
1238
             */
1239
0
            sfclose(in);
1240
0
            return_error(gs_error_VMerror);
1241
0
        }
1242
38.1k
        srewind(in);
1243
38.1k
        data = gs_alloc_bytes(mem, size, "pl_tt_load_font data");
1244
38.1k
        if (data == 0) {
1245
0
            sfclose(in);
1246
0
            return_error(gs_error_VMerror);
1247
0
        }
1248
38.1k
        sfread(data + 6, 1, len, in);
1249
38.1k
        sfclose(in);
1250
38.1k
        plfont->header = data;
1251
38.1k
        plfont->header_size = size;
1252
38.1k
        plfont->font_file_loaded = true;
1253
38.1k
    }
1254
719k
    return 0;
1255
719k
}
1256
1257
/* Keep resident font data in (header) and deallocate the memory */
1258
int
1259
pl_store_resident_font_data_in_file(char *font_file, gs_memory_t * mem,
1260
                                    pl_font_t * plfont)
1261
915k
{
1262
    /* Free the header data */
1263
915k
    if (plfont->header) {
1264
915k
        gs_free_object(mem, plfont->header,
1265
915k
                       "pl_store_resident_font_data_in_file");
1266
915k
        plfont->header = 0;
1267
915k
        plfont->header_size = 0;
1268
915k
    } else {
1269
        /* nothing to do */
1270
0
        return 0;
1271
0
    }
1272
    /* we don't yet have a filename for this font object. create one
1273
       and store it in the font. */
1274
915k
    if (!plfont->font_file) {
1275
915k
        plfont->font_file =
1276
915k
            (char *)gs_alloc_bytes(mem, strlen(font_file) + 1,
1277
915k
                                   "pl_store_resident_font_data_in_file");
1278
915k
        if (plfont->font_file == 0)
1279
0
            return -1;
1280
915k
        strcpy(plfont->font_file, font_file);
1281
915k
    }
1282
    /* designate that the font data is not in RAM */
1283
915k
    plfont->font_file_loaded = false;
1284
915k
    return 0;
1285
915k
}
1286
1287
pl_font_t *
1288
pl_lookup_font_by_pjl_number(pl_dict_t * pfontdict, int pjl_font_number)
1289
86.3k
{
1290
86.3k
    pl_dict_enum_t dictp;
1291
86.3k
    gs_const_string key;
1292
86.3k
    void *value;
1293
1294
86.3k
    pl_dict_enum_begin(pfontdict, &dictp);
1295
4.44M
    while (pl_dict_enum_next(&dictp, &key, &value)) {
1296
4.44M
        pl_font_t *plfont = value;
1297
1298
4.44M
        if (plfont->params.pjl_font_number == pjl_font_number)
1299
86.3k
            return value;
1300
4.44M
    }
1301
0
    return (pl_font_t *) NULL;
1302
86.3k
}