Coverage Report

Created: 2026-04-01 07:17

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
24.5k
#define u16(bptr) pl_get_uint16(bptr)
49
#define s16(bptr) pl_get_int16(bptr)
50
/**** ASSUME uint >= 32 BITS ****/
51
24.5k
#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.09M
{
58
1.09M
    pl_font_t *plfont = plf;
59
60
    /* Free the characters. */
61
1.09M
    if (!plfont->data_are_permanent) {
62
1.08M
        if (plfont->glyphs.table) {
63
373
            uint i;
64
65
114k
            for (i = plfont->glyphs.size; i > 0;) {
66
113k
                void *data = (void *)plfont->glyphs.table[--i].data;
67
68
113k
                if (data)
69
2.02k
                    gs_free_object(mem, data, cname);
70
113k
            }
71
373
        }
72
1.08M
        gs_free_object(mem, (void *)plfont->header, cname);
73
1.08M
        plfont->header = 0;     /* see hack note above */
74
1.08M
    }
75
76
    /* free any nodes in the widths cache */
77
1.09M
    pl_font_glyph_width_cache_remove_nodes(plfont);
78
79
    /* Free the font data itself. */
80
1.09M
    gs_free_object(mem, (void *)plfont->char_glyphs.table, cname);
81
1.09M
    gs_free_object(mem, (void *)plfont->glyphs.table, cname);
82
1.09M
    if (plfont->pfont) {        /* might be only partially constructed */
83
1.09M
        gs_purge_font_from_char_caches_completely(plfont->pfont);
84
1.09M
        (void)gs_purge_font(plfont->pfont);
85
1.09M
        gs_free_object(mem, plfont->pfont, cname);
86
1.09M
    }
87
1.09M
    if (plfont->font_file) {
88
825k
        gs_free_object(mem, plfont->font_file, cname);
89
825k
        plfont->font_file = 0;
90
825k
    }
91
1.09M
    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.09M
    gs_free_object(mem, plf, cname);
100
1.09M
}
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.26M
{
529
1.26M
    pl_glyph_width_node_t *node;
530
531
    /* We can't safely cache widths for bitmap fonts */
532
1.26M
    if (plfont->scaling_technology == plfst_bitmap) {
533
0
        return(0);
534
0
    }
535
536
1.26M
    if (plfont->widths_cache_nitems > PL_MAX_WIDTHS_CACHE_NITEMS) {
537
31
        pl_font_glyph_width_cache_remove_nodes(plfont);
538
31
    }
539
540
1.26M
    node = (pl_glyph_width_node_t *) gs_alloc_bytes(plfont->pfont->memory,
541
1.26M
                                                 sizeof
542
1.26M
                                                 (pl_glyph_width_node_t),
543
1.26M
                                                 "pl_glyph_width_cache_node_add");
544
545
1.26M
    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.26M
    node->next = plfont->widths_cache;
554
1.26M
    plfont->widths_cache = node;
555
1.26M
    plfont->widths_cache_nitems++;
556
557
1.26M
    node->char_code = char_code;
558
1.26M
    node->font_id = plfont->pfont->id;
559
1.26M
    node->width = *pwidth;
560
561
1.26M
    return 0;
562
1.26M
}
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
14.7M
{
569
14.7M
    pl_glyph_width_node_t *current = plfont->widths_cache;
570
571
1.30G
    while (current) {
572
1.29G
        if (char_code == current->char_code) {
573
13.4M
            *pwidth = current->width;
574
13.4M
            return 0;
575
13.4M
        }
576
1.28G
        current = current->next;
577
1.28G
    }
578
1.35M
    return -1;
579
14.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.33M
{
588
1.33M
    pl_glyph_width_node_t *current = plfont->widths_cache;
589
590
2.60M
    while (current) {
591
1.26M
        pl_glyph_width_node_t *next = current->next;
592
593
1.26M
        gs_free_object(plfont->pfont->memory, current, "pl_glyph_width_list_remove");
594
1.26M
        current = next;
595
1.26M
    }
596
1.33M
    plfont->widths_cache = NULL;
597
1.33M
    plfont->widths_cache_nitems = 0;
598
1.33M
    return;
599
1.33M
}
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
14.7M
{
605
14.7M
    int code = 0;
606
607
14.7M
    if (pl_font_glyph_width_cache_node_search(plfont, char_code, pwidth) >= 0) {
608
13.4M
        return(code);
609
13.4M
    }
610
611
1.35M
    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.26M
        (void)pl_font_glyph_width_cache_node_add((pl_font_t *)plfont, char_code, pwidth);
617
1.26M
    }
618
1.35M
    return code;
619
14.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
442k
{
626
442k
    return (*(plfont)->char_metrics) (plfont, pgs, char_code, metrics);
627
442k
}
628
629
/* Allocate a font. */
630
pl_font_t *
631
pl_alloc_font(gs_memory_t * mem, client_name_t cname)
632
1.09M
{
633
1.09M
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
634
635
1.09M
    if (plfont) {               /* Initialize pointers. */
636
1.09M
        plfont->pfont = 0;
637
1.09M
        plfont->header = 0;
638
1.09M
        plfont->glyphs.table = 0;
639
1.09M
        plfont->char_glyphs.table = 0;
640
        /* Initialize other defaults. */
641
1.09M
        plfont->orient = 0;
642
1.09M
        plfont->allow_vertical_substitutes = false;
643
1.09M
        plfont->bold_fraction = 0;
644
1.09M
        plfont->font_file = 0;
645
1.09M
        plfont->resolution.x = plfont->resolution.y = 0;
646
1.09M
        plfont->params.proportional_spacing = true;
647
1.09M
        memset(plfont->character_complement, 0xff, 8);
648
1.09M
        plfont->offsets.GC = plfont->offsets.GT = plfont->offsets.VT = -1;
649
1.09M
        plfont->pts_per_inch = 72.0;    /* normal value */
650
1.09M
        plfont->widths_cache = NULL;
651
1.09M
        plfont->widths_cache_nitems = 0;
652
1.09M
        plfont->names = NULL;
653
1.09M
        plfont->max_name_index = 0;
654
1.09M
        plfont->next_name_index = 0;
655
1.09M
    }
656
1.09M
    return plfont;
657
1.09M
}
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.14M
{
830
1.14M
    gs_font_base *pbfont = (gs_font_base *) pfont;
831
832
1.14M
    plfont->pfont = pfont;
833
    /* Initialize generic font data. */
834
1.14M
    gs_make_identity(&pbfont->orig_FontMatrix);
835
1.14M
    gs_make_identity(&pbfont->FontMatrix);
836
1.14M
    pbfont->next = pbfont->prev = 0;
837
1.14M
    pbfont->memory = mem;
838
1.14M
    pbfont->dir = pdir;
839
1.14M
    pbfont->is_resource = false;
840
1.14M
    gs_notify_init(&pbfont->notify_list, gs_memory_stable(mem));
841
1.14M
    pbfont->base = (gs_font *) pbfont;
842
1.14M
    pbfont->client_data = plfont;
843
1.14M
    pbfont->WMode = 0;
844
1.14M
    pbfont->PaintType = 0;
845
1.14M
    pbfont->StrokeWidth = 0;
846
1.14M
    pbfont->is_cached = 0;
847
1.14M
    pbfont->procs.init_fstack = gs_default_init_fstack;
848
1.14M
    pbfont->procs.next_char_glyph = gs_default_next_char_glyph;
849
1.14M
    pbfont->FAPI = NULL;
850
1.14M
    pbfont->FAPI_font_data = NULL;
851
852
1.14M
    pbfont->procs.glyph_name = pl_glyph_name;
853
1.14M
    pbfont->procs.decode_glyph = pl_decode_glyph;
854
    /* NB pbfont->procs.callbacks.known_encode = pl_known_encode; */
855
1.14M
    pbfont->procs.define_font = gs_no_define_font;
856
1.14M
    pbfont->procs.make_font = gs_no_make_font;
857
1.14M
    pbfont->procs.font_info = gs_default_font_info;
858
1.14M
    pbfont->procs.glyph_info = gs_default_glyph_info;
859
1.14M
    pbfont->procs.glyph_outline = gs_no_glyph_outline;
860
1.14M
    pbfont->id = gs_next_ids(mem, 1);
861
1.14M
    {
862
1.14M
        size_t sz = strlen(font_name);
863
1.14M
        gs_font_name *fnm = &pbfont->font_name;
864
1.14M
        gs_font_name *knm = &pbfont->key_name;
865
866
1.14M
        if (sz > gs_font_name_max)
867
0
            sz = gs_font_name_max;
868
1.14M
        fnm->size = knm->size = sz;
869
870
1.14M
        memcpy(fnm->chars, font_name, sz);
871
1.14M
        fnm->chars[sz] = 0;
872
873
1.14M
        memcpy(knm->chars, font_name, sz);
874
1.14M
        knm->chars[sz] = 0;
875
1.14M
    }
876
1.14M
    return 0;
877
1.14M
}
878
879
/* Fill in bitmap font boilerplate. */
880
void
881
pl_fill_in_bitmap_font(gs_font_base * pfont, long unique_id)
882
12.3k
{
883
12.3k
    pfont->FontType = ft_PCL_user_defined;
884
12.3k
    pfont->BitmapWidths = true;
885
12.3k
    pfont->ExactSize = fbit_use_bitmaps;
886
12.3k
    pfont->InBetweenSize = fbit_use_bitmaps;
887
12.3k
    pfont->TransformedChar = fbit_transform_bitmaps;
888
12.3k
    pl_bitmap_init_procs(pfont);
889
    /* We have no idea what the FontBBox should be. */
890
12.3k
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
891
12.3k
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
892
12.3k
    uid_set_UniqueID(&pfont->UID, unique_id);
893
12.3k
    pfont->encoding_index = 1;          /****** WRONG ******/
894
12.3k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
895
12.3k
}
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.08M
{
901
1.08M
    pfont->FontType = ft_TrueType;
902
1.08M
    pfont->BitmapWidths = true;
903
1.08M
    pfont->ExactSize = fbit_use_outlines;
904
1.08M
    pfont->InBetweenSize = fbit_use_outlines;
905
1.08M
    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.08M
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
913
1.08M
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
914
1.08M
    uid_set_UniqueID(&pfont->UID, unique_id);
915
1.08M
    pfont->encoding_index = 1;          /****** WRONG ******/
916
1.08M
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
917
    /* Initialize Type 42 specific data. */
918
1.08M
    pfont->data.proc_data = data;
919
1.08M
    pl_tt_init_procs(pfont);
920
1.08M
    {
921
1.08M
        int code = gs_type42_font_init(pfont, 0);
922
923
1.08M
        if (code < 0)
924
3
            return code;
925
1.08M
    }
926
    /* disable unused FAPI */
927
1.08M
    pfont->FAPI = 0;
928
1.08M
    pfont->FAPI_font_data = 0;
929
1.08M
    pl_tt_finish_init(pfont, !data);
930
1.08M
    return 0;
931
1.08M
}
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
12.2k
{
972
12.2k
    const byte *header = plfont->header;
973
12.2k
    pl_font_scaling_technology_t fst = header[fst_offset];
974
12.2k
    int wsize = (large_sizes ? 4 : 2);
975
12.2k
    const byte *segment = header + start_offset;
976
12.2k
    const byte *end = header + end_offset;
977
12.2k
    const byte *null_segment = end - (2 + wsize);
978
12.2k
    bool found = false;
979
12.2k
    ulong seg_size;
980
12.2k
    int illegal_font_data = pfoe->illegal_font_data;
981
982
12.2k
#define return_scan_error(err)\
983
12.2k
  return_error((err) ? (err) : illegal_font_data);
984
985
12.2k
    if (memcmp(null_segment, "\377\377", 2) /* NULL segment header */ )
986
12.2k
        return_scan_error(pfoe->missing_required_segment);
987
12.2k
    if (memcmp(null_segment + 2, "\0\0\0\0", wsize) /* NULL segment size */ )
988
12.2k
        return_scan_error(pfoe->illegal_null_segment_size);
989
12.2k
    switch (fst) {
990
12.2k
        case plfst_bitmap:
991
12.2k
        case plfst_TrueType:
992
12.2k
            break;
993
0
        default:
994
0
            return_scan_error(pfoe->illegal_font_header_fields);
995
12.2k
    }
996
12.2k
    if (header[fst_offset + 1]) /* variety, must be 0 */
997
12.2k
        return_scan_error(pfoe->illegal_font_header_fields);
998
    /* Scan the segments. */
999
36.7k
    for (; end - segment >= 2 + wsize; segment += 2 + wsize + seg_size) {
1000
24.5k
        uint seg_id = u16(segment);
1001
24.5k
        const byte *sdata = segment + 2 + wsize;
1002
1003
24.5k
#define id2(c1,c2) (((uint)(c1) << 8) + (c2))
1004
1005
24.5k
        seg_size = (large_sizes ? u32(segment + 2) : u16(segment + 2));
1006
24.5k
        if (seg_size + 2 + wsize > end - segment)
1007
1
            return_error(illegal_font_data);
1008
        /* Handle segments common to all fonts. */
1009
24.5k
        switch (seg_id) {
1010
12.2k
            case 0xffff:       /* NULL segment ID */
1011
12.2k
                if (segment != null_segment)
1012
0
                    return_error(illegal_font_data);
1013
12.2k
                continue;
1014
12.2k
            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
12.2k
            default:
1022
12.2k
                ;
1023
24.5k
        }
1024
        /* Handle segments specific to the scaling technology. */
1025
12.2k
        if (fst == plfst_bitmap)
1026
12.2k
            switch (seg_id) {
1027
12.2k
                case id2('B', 'R'):
1028
12.2k
                    if (seg_size != 4)
1029
12.2k
                        return_scan_error(pfoe->illegal_BR_segment);
1030
12.2k
                    {
1031
12.2k
                        uint xres = pl_get_uint16(sdata);
1032
12.2k
                        uint yres = pl_get_uint16(sdata + 2);
1033
1034
12.2k
                        if (xres == 0 || yres == 0)
1035
12.2k
                            return_scan_error(pfoe->illegal_BR_segment);
1036
12.2k
                        plfont->resolution.x = xres;
1037
12.2k
                        plfont->resolution.y = yres;
1038
12.2k
                    }
1039
12.2k
                    found = true;
1040
12.2k
                    break;
1041
1
                default:
1042
1
                    if (pfoe->illegal_font_segment < 0)
1043
1
                        return_error(pfoe->illegal_font_segment);
1044
12.2k
        } else                  /* fst == plfst_TrueType */
1045
62
            switch (seg_id) {
1046
62
                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
62
                    if (seg_size < 12 + 5 * 16 ||
1054
                        /* memcmp(sdata, "\000\001\000\000", 4) || */
1055
62
                        u16(sdata + 4) < 3)
1056
62
                        return_scan_error(pfoe->illegal_GT_segment);
1057
62
                    plfont->offsets.GT = segment - header;
1058
62
                    found = true;
1059
62
                    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
62
            }
1091
12.2k
#undef id2
1092
12.2k
    }
1093
12.2k
    if (!found)
1094
12.2k
        return_scan_error(pfoe->missing_required_segment);
1095
12.2k
    if (segment != end)
1096
0
        return_error(illegal_font_data);
1097
12.2k
    plfont->large_sizes = large_sizes;
1098
12.2k
    plfont->scaling_technology = fst;
1099
12.2k
    return 0;
1100
12.2k
#undef return_scan_error
1101
12.2k
}
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.08M
{
1114
1.08M
    ulong len = (sfseek(in, 0L, SEEK_END), sftell(in));
1115
1116
1.08M
    *size = 6 + len;            /* leave room for segment header */
1117
1.08M
    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.08M
    srewind(in);
1127
1.08M
    *pptt_font_data = gs_alloc_bytes(mem, *size, "pl_tt_load_font data");
1128
1.08M
    if (*pptt_font_data == 0) {
1129
0
        sfclose(in);
1130
0
        return_error(gs_error_VMerror);
1131
0
    }
1132
1.08M
    sfread(*pptt_font_data + 6, 1, len, in);
1133
1.08M
    sfclose(in);
1134
1.08M
    return 0;
1135
1.08M
}
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.08M
{
1142
1.08M
    byte *tt_font_datap = NULL;
1143
1.08M
    ulong size;
1144
1.08M
    int code;
1145
1.08M
    gs_font_type42 *pfont = NULL;
1146
1.08M
    pl_font_t *plfont = NULL;
1147
1.08M
    byte *file_name = NULL;
1148
1.08M
    gs_const_string pfname;
1149
1150
1.08M
    if (sfilename(in, &pfname) == 0) {
1151
1.08M
        file_name =
1152
1.08M
            gs_alloc_bytes(mem, pfname.size + 1, "pl_load_tt_font file_name");
1153
1.08M
        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.08M
        memcpy(file_name, pfname.data, pfname.size + 1);
1159
1.08M
    }
1160
1161
    /* get the data from the file */
1162
1.08M
    code = pl_alloc_tt_fontfile_buffer(in, mem, &tt_font_datap, &size);
1163
1.08M
    if (code < 0)
1164
0
        goto error;
1165
    /* Make a Type 42 font out of the TrueType data. */
1166
1.08M
    pfont = gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42,
1167
1.08M
                            "pl_tt_load_font(gs_font_type42)");
1168
1.08M
    if (pfont == NULL) {
1169
0
        code = gs_error_VMerror;
1170
0
        goto error;
1171
0
    }
1172
1.08M
    memset(pfont, 0, sizeof(*pfont));
1173
1.08M
    plfont = pl_alloc_font(mem, "pl_tt_load_font(pl_font_t)");
1174
1.08M
    if (plfont == NULL) {
1175
0
        code = gs_error_VMerror;
1176
0
        goto error;
1177
0
    }
1178
1179
    /* Initialize general font boilerplate. */
1180
1.08M
    code = pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, font_name);
1181
1.08M
    if (code < 0)
1182
0
        goto error;
1183
1184
    /* Initialize TrueType font boilerplate. */
1185
1.08M
    plfont->header = tt_font_datap;
1186
1.08M
    plfont->header_size = size;
1187
1.08M
    plfont->scaling_technology = plfst_TrueType;
1188
1.08M
    plfont->font_type = plft_Unicode;
1189
1.08M
    plfont->large_sizes = true;
1190
1.08M
    plfont->offsets.GT = 0;
1191
1.08M
    plfont->is_xl_format = false;
1192
1.08M
    code = pl_fill_in_tt_font(pfont, tt_font_datap, unique_id);
1193
1.08M
    if (code < 0)
1194
0
        goto error;
1195
1.08M
    code = gs_definefont(pdir, (gs_font *) pfont);
1196
1.08M
    if (code < 0)
1197
0
        goto error;
1198
1199
1.08M
    code = pl_fapi_passfont(plfont, 0, NULL, (char *)file_name, NULL, 0);
1200
1.08M
    if (code < 0)
1201
0
        goto error;
1202
1.08M
    if (file_name)
1203
1.08M
        gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1204
1205
1.08M
    *pplfont = plfont;
1206
1.08M
    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.08M
}
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
621k
{
1220
1221
621k
    ulong len, size;
1222
621k
    byte *data;
1223
1224
621k
    if (plfont->font_file && !plfont->font_file_loaded) {
1225
34.7k
        stream *in = sfopen(plfont->font_file, "r", mem);
1226
1227
34.7k
        if (in == NULL)
1228
0
            return -1;
1229
        /* note this is exactly the same as the code in pl_load_tt_font */
1230
34.7k
        len = (sfseek(in, 0L, SEEK_END), sftell(in));
1231
34.7k
        size = 6 + len;         /* leave room for segment header */
1232
1233
34.7k
        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
34.7k
        srewind(in);
1243
34.7k
        data = gs_alloc_bytes(mem, size, "pl_tt_load_font data");
1244
34.7k
        if (data == 0) {
1245
0
            sfclose(in);
1246
0
            return_error(gs_error_VMerror);
1247
0
        }
1248
34.7k
        sfread(data + 6, 1, len, in);
1249
34.7k
        sfclose(in);
1250
34.7k
        plfont->header = data;
1251
34.7k
        plfont->header_size = size;
1252
34.7k
        plfont->font_file_loaded = true;
1253
34.7k
    }
1254
621k
    return 0;
1255
621k
}
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
825k
{
1262
    /* Free the header data */
1263
825k
    if (plfont->header) {
1264
825k
        gs_free_object(mem, plfont->header,
1265
825k
                       "pl_store_resident_font_data_in_file");
1266
825k
        plfont->header = 0;
1267
825k
        plfont->header_size = 0;
1268
825k
    } 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
825k
    if (!plfont->font_file) {
1275
825k
        plfont->font_file =
1276
825k
            (char *)gs_alloc_bytes(mem, strlen(font_file) + 1,
1277
825k
                                   "pl_store_resident_font_data_in_file");
1278
825k
        if (plfont->font_file == 0)
1279
0
            return -1;
1280
825k
        strcpy(plfont->font_file, font_file);
1281
825k
    }
1282
    /* designate that the font data is not in RAM */
1283
825k
    plfont->font_file_loaded = false;
1284
825k
    return 0;
1285
825k
}
1286
1287
pl_font_t *
1288
pl_lookup_font_by_pjl_number(pl_dict_t * pfontdict, int pjl_font_number)
1289
66.0k
{
1290
66.0k
    pl_dict_enum_t dictp;
1291
66.0k
    gs_const_string key;
1292
66.0k
    void *value;
1293
1294
66.0k
    pl_dict_enum_begin(pfontdict, &dictp);
1295
3.40M
    while (pl_dict_enum_next(&dictp, &key, &value)) {
1296
3.40M
        pl_font_t *plfont = value;
1297
1298
3.40M
        if (plfont->params.pjl_font_number == pjl_font_number)
1299
66.0k
            return value;
1300
3.40M
    }
1301
0
    return (pl_font_t *) NULL;
1302
66.0k
}