Coverage Report

Created: 2026-09-14 07:34

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