Coverage Report

Created: 2026-07-24 07:44

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
32.5k
#define u16(bptr) pl_get_uint16(bptr)
49
#define s16(bptr) pl_get_int16(bptr)
50
/**** ASSUME uint >= 32 BITS ****/
51
32.4k
#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.97M
{
58
1.97M
    pl_font_t *plfont = plf;
59
60
    /* Free the characters. */
61
1.97M
    if (!plfont->data_are_permanent) {
62
1.95M
        if (plfont->glyphs.table) {
63
358
            uint i;
64
65
105k
            for (i = plfont->glyphs.size; i > 0;) {
66
105k
                void *data = (void *)plfont->glyphs.table[--i].data;
67
68
105k
                if (data)
69
1.71k
                    gs_free_object(mem, data, cname);
70
105k
            }
71
358
        }
72
1.95M
        gs_free_object(mem, (void *)plfont->header, cname);
73
1.95M
        plfont->header = 0;     /* see hack note above */
74
1.95M
    }
75
76
    /* free any nodes in the widths cache */
77
1.97M
    pl_font_glyph_width_cache_remove_nodes(plfont);
78
79
    /* Free the font data itself. */
80
1.97M
    gs_free_object(mem, (void *)plfont->char_glyphs.table, cname);
81
1.97M
    gs_free_object(mem, (void *)plfont->glyphs.table, cname);
82
1.97M
    if (plfont->pfont) {        /* might be only partially constructed */
83
1.97M
        gs_purge_font_from_char_caches_completely(plfont->pfont);
84
1.97M
        (void)gs_purge_font(plfont->pfont);
85
1.97M
        gs_free_object(mem, plfont->pfont, cname);
86
1.97M
    }
87
1.97M
    if (plfont->font_file) {
88
1.64M
        gs_free_object(mem, plfont->font_file, cname);
89
1.64M
        plfont->font_file = 0;
90
1.64M
    }
91
1.97M
    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.97M
    gs_free_object(mem, plf, cname);
100
1.97M
}
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.51M
{
539
1.51M
    pl_glyph_width_node_t *node;
540
541
    /* We can't safely cache widths for bitmap fonts */
542
1.51M
    if (plfont->scaling_technology == plfst_bitmap) {
543
0
        return(0);
544
0
    }
545
546
1.51M
    if (plfont->widths_cache_nitems > PL_MAX_WIDTHS_CACHE_NITEMS) {
547
573
        pl_font_glyph_width_cache_remove_nodes(plfont);
548
573
    }
549
550
1.51M
    node = (pl_glyph_width_node_t *) gs_alloc_bytes(plfont->pfont->memory,
551
1.51M
                                                 sizeof
552
1.51M
                                                 (pl_glyph_width_node_t),
553
1.51M
                                                 "pl_glyph_width_cache_node_add");
554
555
1.51M
    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.51M
    node->next = plfont->widths_cache;
564
1.51M
    plfont->widths_cache = node;
565
1.51M
    plfont->widths_cache_nitems++;
566
567
1.51M
    node->char_code = char_code;
568
1.51M
    node->font_id = plfont->pfont->id;
569
1.51M
    node->width = *pwidth;
570
571
1.51M
    return 0;
572
1.51M
}
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
28.4M
{
579
28.4M
    pl_glyph_width_node_t *current = plfont->widths_cache;
580
581
1.87G
    while (current) {
582
1.87G
        if (char_code == current->char_code) {
583
26.4M
            *pwidth = current->width;
584
26.4M
            return 0;
585
26.4M
        }
586
1.84G
        current = current->next;
587
1.84G
    }
588
1.98M
    return -1;
589
28.4M
}
590
591
592
/* ---------------- Public procedures ---------------- */
593
/* character width */
594
595
void
596
pl_font_glyph_width_cache_remove_nodes(pl_font_t *plfont)
597
2.22M
{
598
2.22M
    pl_glyph_width_node_t *current = plfont->widths_cache;
599
600
3.74M
    while (current) {
601
1.51M
        pl_glyph_width_node_t *next = current->next;
602
603
1.51M
        gs_free_object(plfont->pfont->memory, current, "pl_glyph_width_list_remove");
604
1.51M
        current = next;
605
1.51M
    }
606
2.22M
    plfont->widths_cache = NULL;
607
2.22M
    plfont->widths_cache_nitems = 0;
608
2.22M
    return;
609
2.22M
}
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
28.4M
{
615
28.4M
    int code = 0;
616
617
28.4M
    if (pl_font_glyph_width_cache_node_search(plfont, char_code, pwidth) >= 0) {
618
26.4M
        return(code);
619
26.4M
    }
620
621
1.98M
    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.51M
        (void)pl_font_glyph_width_cache_node_add((pl_font_t *)plfont, char_code, pwidth);
627
1.51M
    }
628
1.98M
    return code;
629
28.4M
}
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.97M
{
643
1.97M
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
644
645
1.97M
    if (plfont) {               /* Initialize pointers. */
646
1.97M
        plfont->pfont = 0;
647
1.97M
        plfont->header = 0;
648
1.97M
        plfont->glyphs.table = 0;
649
1.97M
        plfont->char_glyphs.table = 0;
650
        /* Initialize other defaults. */
651
1.97M
        plfont->orient = 0;
652
1.97M
        plfont->allow_vertical_substitutes = false;
653
1.97M
        plfont->bold_fraction = 0;
654
1.97M
        plfont->font_file = 0;
655
1.97M
        plfont->resolution.x = plfont->resolution.y = 0;
656
1.97M
        plfont->params.proportional_spacing = true;
657
1.97M
        memset(plfont->character_complement, 0xff, 8);
658
1.97M
        plfont->offsets.GC = plfont->offsets.GT = plfont->offsets.VT = -1;
659
1.97M
        plfont->pts_per_inch = 72.0;    /* normal value */
660
1.97M
        plfont->widths_cache = NULL;
661
1.97M
        plfont->widths_cache_nitems = 0;
662
1.97M
        plfont->names = NULL;
663
1.97M
        plfont->max_name_index = 0;
664
1.97M
        plfont->next_name_index = 0;
665
1.97M
    }
666
1.97M
    return plfont;
667
1.97M
}
668
669
/* Structure descriptors for cloning fonts */
670
gs_private_st_ptrs1(st_pl_font_glyph_f, pl_font_glyph_t, "pl_font_glyph_t",
671
                    pl_font_glyph_enum_ptrs_f, pl_font_glyph_reloc_ptrs_f,
672
                    data);
673
gs_private_st_element(st_pl_font_glyph_element_f, pl_font_glyph_t,
674
                      "pl_font_glyph_t[]", pl_font_glyph_elt_enum_ptrs_f,
675
                      pl_font_glyph_elt_reloc_ptrs_f, st_pl_font_glyph_f);
676
677
pl_font_t *
678
pl_clone_font(const pl_font_t * src, gs_memory_t * mem, client_name_t cname)
679
0
{
680
0
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
681
682
0
    if (plfont == 0)
683
0
        return 0;
684
    /* copy technology common parts */
685
0
    plfont->storage = src->storage;
686
0
    plfont->header_size = src->header_size;
687
0
    plfont->scaling_technology = src->scaling_technology;
688
0
    plfont->is_xl_format = src->is_xl_format;
689
0
    plfont->allow_vertical_substitutes = src->allow_vertical_substitutes;
690
0
    plfont->font_type = src->font_type;
691
0
    plfont->char_width = src->char_width;
692
0
    plfont->char_metrics = src->char_metrics;
693
0
    plfont->large_sizes = src->large_sizes;
694
0
    plfont->resolution = src->resolution;
695
0
    plfont->params = src->params;
696
0
    plfont->pts_per_inch = src->pts_per_inch;
697
0
    plfont->font_file_loaded = src->font_file_loaded;
698
0
    plfont->orient = src->orient;
699
0
    plfont->bold_fraction = src->bold_fraction;
700
0
    plfont->widths_cache = NULL;
701
0
    plfont->widths_cache_nitems = 0;
702
0
    {
703
0
        int i;
704
705
0
        for (i = 0; i < sizeof(src->character_complement); i++)
706
0
            plfont->character_complement[i] = src->character_complement[i];
707
0
    }
708
0
    plfont->offsets = src->offsets;
709
0
    plfont->header = gs_alloc_bytes(mem, src->header_size, cname);
710
0
    if (plfont->header == 0)
711
0
        return 0;
712
0
    memcpy(plfont->header, src->header, src->header_size);
713
714
0
    plfont->names = NULL;
715
0
    plfont->max_name_index = 0;
716
0
    plfont->next_name_index = 0;
717
718
0
    if (src->font_file) {
719
0
        plfont->font_file =
720
0
            (char *)gs_alloc_bytes(mem, strlen(src->font_file) + 1,
721
0
                                   "pl_clone_font");
722
0
        if (plfont->font_file == 0)
723
0
            return 0;           /* #NB errors!!! */
724
0
        strcpy(plfont->font_file, src->font_file);
725
0
    } else
726
0
        plfont->font_file = 0;
727
    /* technology specific setup */
728
0
    switch (plfont->scaling_technology) {
729
0
        case plfst_bitmap:
730
0
            {
731
0
                gs_font_base *pfont =
732
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
733
0
                                    cname);
734
0
                if (pfont == 0)
735
0
                    return 0;
736
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
737
0
                                mem, "nameless_font");
738
0
                pl_fill_in_bitmap_font(pfont, gs_next_ids(mem, 1));
739
0
                break;
740
0
            }
741
0
        case plfst_Intellifont:
742
0
            {
743
0
                gs_font_base *pfont =
744
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
745
0
                                    cname);
746
0
                if (pfont == 0)
747
0
                    return 0;
748
0
                pl_fill_in_font((gs_font *) pfont, plfont, src->pfont->dir,
749
0
                                mem, "nameless_font");
750
0
                pl_fill_in_intelli_font(pfont, gs_next_ids(mem, 1));
751
0
                break;
752
0
            }
753
0
        case plfst_TrueType:
754
0
            {
755
0
                {
756
0
                    gs_font_type42 *pfont =
757
0
                        gs_alloc_struct(mem, gs_font_type42,
758
0
                                        &st_gs_font_type42, cname);
759
                    /* detect if a truetype font is downloaded or
760
                       internal.  There must be a better way... */
761
0
                    gs_font_type42 *pfont_src = (gs_font_type42 *) src->pfont;
762
0
                    bool downloaded =
763
0
                        (pfont_src->data.get_outline == pl_tt_get_outline);
764
0
                    if (pfont == 0)
765
0
                        return 0;
766
0
                    pl_fill_in_font((gs_font *) pfont, plfont,
767
0
                                    src->pfont->dir, mem, "nameless_font");
768
0
                    pl_fill_in_tt_font(pfont, downloaded ? NULL : src->header,
769
0
                                       gs_next_ids(mem, 1));
770
0
                }
771
0
                break;
772
0
            }
773
0
        default:
774
0
            return 0;
775
0
    }
776
0
    if (src->char_glyphs.table != 0) {
777
        /* HAS may gs_alloc_struct_array() here but this is
778
           consistant with pl_tt_alloc_char_glyphs() */
779
0
        pl_tt_char_glyph_t *char_glyphs =
780
0
            (pl_tt_char_glyph_t *) gs_alloc_byte_array(mem,
781
0
                                                       src->char_glyphs.size,
782
0
                                                       sizeof
783
0
                                                       (pl_tt_char_glyph_t),
784
0
                                                       cname);
785
0
        int i;
786
787
0
        if (char_glyphs == 0)
788
0
            return 0;
789
0
        for (i = 0; i < src->char_glyphs.size; i++)
790
0
            char_glyphs[i] = src->char_glyphs.table[i];
791
        /* once again a copy struct shortcut and then are restore
792
           of the char_glyphs.table pointer */
793
0
        plfont->char_glyphs = src->char_glyphs;
794
0
        plfont->char_glyphs.table = char_glyphs;
795
0
    } else                      /* no character glyph table data */
796
0
        plfont->char_glyphs = src->char_glyphs;
797
798
0
    if (src->glyphs.table != 0) {
799
0
        int i;
800
801
0
        plfont->glyphs.table =
802
0
            gs_alloc_struct_array(mem, src->glyphs.size, pl_font_glyph_t,
803
0
                                  &st_pl_font_glyph_element_f, cname);
804
0
        if (plfont->glyphs.table == NULL)
805
0
            return 0;
806
0
        plfont->glyphs.used = src->glyphs.used;
807
0
        plfont->glyphs.limit = src->glyphs.limit;
808
0
        plfont->glyphs.size = src->glyphs.size;
809
0
        plfont->glyphs.skip = src->glyphs.skip;
810
0
        for (i = 0; i < src->glyphs.size; i++) {
811
0
            const byte *data = src->glyphs.table[i].data;
812
0
            byte *char_data;
813
814
0
            plfont->glyphs.table[i].glyph = src->glyphs.table[i].glyph;
815
0
            plfont->glyphs.table[i].data = 0;
816
0
            if (data) {
817
0
                uint size = src->glyphs.table[i].data_len;
818
0
                char_data = gs_alloc_bytes(mem, size, cname);
819
0
                if (char_data == 0)
820
0
                    return 0;
821
0
                memcpy(char_data, data, size);
822
0
                plfont->glyphs.table[i].data = char_data;
823
0
                plfont->glyphs.table[i].data_len = size;
824
0
            }
825
826
0
        }
827
0
    } else                      /* no glyph table */
828
0
        plfont->glyphs = src->glyphs;
829
0
    return plfont;
830
0
}
831
832
/* Fill in generic font boilerplate. NB TODO examine duplication with
833
   gs_font_alloc().  The font name must not contain spaces.  It is
834
   used for PDF output and Acrobat (some versions) do not process the
835
   file correctly with spaces in the name. */
836
int
837
pl_fill_in_font(gs_font * pfont, pl_font_t * plfont, gs_font_dir * pdir,
838
                gs_memory_t * mem, const char *font_name)
839
2.03M
{
840
2.03M
    gs_font_base *pbfont = (gs_font_base *) pfont;
841
842
2.03M
    plfont->pfont = pfont;
843
    /* Initialize generic font data. */
844
2.03M
    gs_make_identity(&pbfont->orig_FontMatrix);
845
2.03M
    gs_make_identity(&pbfont->FontMatrix);
846
2.03M
    pbfont->next = pbfont->prev = 0;
847
2.03M
    pbfont->memory = mem;
848
2.03M
    pbfont->dir = pdir;
849
2.03M
    pbfont->is_resource = false;
850
2.03M
    gs_notify_init(&pbfont->notify_list, gs_memory_stable(mem));
851
2.03M
    pbfont->base = (gs_font *) pbfont;
852
2.03M
    pbfont->client_data = plfont;
853
2.03M
    pbfont->WMode = 0;
854
2.03M
    pbfont->PaintType = 0;
855
2.03M
    pbfont->StrokeWidth = 0;
856
2.03M
    pbfont->is_cached = 0;
857
2.03M
    pbfont->procs.init_fstack = gs_default_init_fstack;
858
2.03M
    pbfont->procs.next_char_glyph = gs_default_next_char_glyph;
859
2.03M
    pbfont->FAPI = NULL;
860
2.03M
    pbfont->FAPI_font_data = NULL;
861
862
2.03M
    pbfont->procs.glyph_name = pl_glyph_name;
863
2.03M
    pbfont->procs.decode_glyph = pl_decode_glyph;
864
    /* NB pbfont->procs.callbacks.known_encode = pl_known_encode; */
865
2.03M
    pbfont->procs.define_font = gs_no_define_font;
866
2.03M
    pbfont->procs.make_font = gs_no_make_font;
867
2.03M
    pbfont->procs.font_info = gs_default_font_info;
868
2.03M
    pbfont->procs.glyph_info = gs_default_glyph_info;
869
2.03M
    pbfont->procs.glyph_outline = gs_no_glyph_outline;
870
2.03M
    pbfont->id = gs_next_ids(mem, 1);
871
2.03M
    {
872
2.03M
        size_t sz = strlen(font_name);
873
2.03M
        gs_font_name *fnm = &pbfont->font_name;
874
2.03M
        gs_font_name *knm = &pbfont->key_name;
875
876
2.03M
        if (sz > gs_font_name_max)
877
0
            sz = gs_font_name_max;
878
2.03M
        fnm->size = knm->size = sz;
879
880
2.03M
        memcpy(fnm->chars, font_name, sz);
881
2.03M
        fnm->chars[sz] = 0;
882
883
2.03M
        memcpy(knm->chars, font_name, sz);
884
2.03M
        knm->chars[sz] = 0;
885
2.03M
    }
886
2.03M
    return 0;
887
2.03M
}
888
889
/* Fill in bitmap font boilerplate. */
890
void
891
pl_fill_in_bitmap_font(gs_font_base * pfont, long unique_id)
892
16.2k
{
893
16.2k
    pfont->FontType = ft_PCL_user_defined;
894
16.2k
    pfont->BitmapWidths = true;
895
16.2k
    pfont->ExactSize = fbit_use_bitmaps;
896
16.2k
    pfont->InBetweenSize = fbit_use_bitmaps;
897
16.2k
    pfont->TransformedChar = fbit_transform_bitmaps;
898
16.2k
    pl_bitmap_init_procs(pfont);
899
    /* We have no idea what the FontBBox should be. */
900
16.2k
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
901
16.2k
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
902
16.2k
    uid_set_UniqueID(&pfont->UID, unique_id);
903
16.2k
    pfont->encoding_index = 1;          /****** WRONG ******/
904
16.2k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
905
16.2k
}
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.95M
{
911
1.95M
    pfont->FontType = ft_TrueType;
912
1.95M
    pfont->BitmapWidths = true;
913
1.95M
    pfont->ExactSize = fbit_use_outlines;
914
1.95M
    pfont->InBetweenSize = fbit_use_outlines;
915
1.95M
    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.95M
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
923
1.95M
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
924
1.95M
    uid_set_UniqueID(&pfont->UID, unique_id);
925
1.95M
    pfont->encoding_index = 1;          /****** WRONG ******/
926
1.95M
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
927
    /* Initialize Type 42 specific data. */
928
1.95M
    pfont->data.proc_data = data;
929
1.95M
    pl_tt_init_procs(pfont);
930
1.95M
    {
931
1.95M
        int code = gs_type42_font_init(pfont, 0);
932
933
1.95M
        if (code < 0)
934
15
            return code;
935
1.95M
    }
936
    /* disable unused FAPI */
937
1.95M
    pfont->FAPI = 0;
938
1.95M
    pfont->FAPI_font_data = 0;
939
1.95M
    pl_tt_finish_init(pfont, !data);
940
1.95M
    return 0;
941
1.95M
}
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
16.2k
{
982
16.2k
    const byte *header = plfont->header;
983
16.2k
    pl_font_scaling_technology_t fst = header[fst_offset];
984
16.2k
    int wsize = (large_sizes ? 4 : 2);
985
16.2k
    const byte *segment = header + start_offset;
986
16.2k
    const byte *end = header + end_offset;
987
16.2k
    const byte *null_segment = end - (2 + wsize);
988
16.2k
    bool found = false;
989
16.2k
    ulong seg_size;
990
16.2k
    int illegal_font_data = pfoe->illegal_font_data;
991
992
16.2k
#define return_scan_error(err)\
993
16.2k
  return_error((err) ? (err) : illegal_font_data);
994
995
16.2k
    if (memcmp(null_segment, "\377\377", 2) /* NULL segment header */ )
996
16.2k
        return_scan_error(pfoe->missing_required_segment);
997
16.2k
    if (memcmp(null_segment + 2, "\0\0\0\0", wsize) /* NULL segment size */ )
998
16.2k
        return_scan_error(pfoe->illegal_null_segment_size);
999
16.2k
    switch (fst) {
1000
16.1k
        case plfst_bitmap:
1001
16.2k
        case plfst_TrueType:
1002
16.2k
            break;
1003
0
        default:
1004
0
            return_scan_error(pfoe->illegal_font_header_fields);
1005
16.2k
    }
1006
16.2k
    if (header[fst_offset + 1]) /* variety, must be 0 */
1007
16.2k
        return_scan_error(pfoe->illegal_font_header_fields);
1008
    /* Scan the segments. */
1009
48.6k
    for (; end - segment >= 2 + wsize; segment += 2 + wsize + seg_size) {
1010
32.4k
        uint seg_id = u16(segment);
1011
32.4k
        const byte *sdata = segment + 2 + wsize;
1012
1013
32.4k
#define id2(c1,c2) (((uint)(c1) << 8) + (c2))
1014
1015
32.4k
        seg_size = (large_sizes ? u32(segment + 2) : u16(segment + 2));
1016
32.4k
        if (seg_size + 2 + wsize > end - segment)
1017
2
            return_error(illegal_font_data);
1018
        /* Handle segments common to all fonts. */
1019
32.4k
        switch (seg_id) {
1020
16.2k
            case 0xffff:       /* NULL segment ID */
1021
16.2k
                if (segment != null_segment)
1022
0
                    return_error(illegal_font_data);
1023
16.2k
                continue;
1024
16.2k
            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
16.2k
            default:
1032
16.2k
                ;
1033
32.4k
        }
1034
        /* Handle segments specific to the scaling technology. */
1035
16.2k
        if (fst == plfst_bitmap)
1036
16.1k
            switch (seg_id) {
1037
16.1k
                case id2('B', 'R'):
1038
16.1k
                    if (seg_size != 4)
1039
16.1k
                        return_scan_error(pfoe->illegal_BR_segment);
1040
16.1k
                    {
1041
16.1k
                        uint xres = pl_get_uint16(sdata);
1042
16.1k
                        uint yres = pl_get_uint16(sdata + 2);
1043
1044
16.1k
                        if (xres == 0 || yres == 0)
1045
16.1k
                            return_scan_error(pfoe->illegal_BR_segment);
1046
16.1k
                        plfont->resolution.x = xres;
1047
16.1k
                        plfont->resolution.y = yres;
1048
16.1k
                    }
1049
16.1k
                    found = true;
1050
16.1k
                    break;
1051
0
                default:
1052
0
                    if (pfoe->illegal_font_segment < 0)
1053
0
                        return_error(pfoe->illegal_font_segment);
1054
16.1k
        } else                  /* fst == plfst_TrueType */
1055
93
            switch (seg_id) {
1056
93
                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
93
                    if (seg_size < 12 + 5 * 16 ||
1064
                        /* memcmp(sdata, "\000\001\000\000", 4) || */
1065
93
                        u16(sdata + 4) < 3)
1066
93
                        return_scan_error(pfoe->illegal_GT_segment);
1067
93
                    plfont->offsets.GT = segment - header;
1068
93
                    found = true;
1069
93
                    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
93
            }
1101
16.2k
#undef id2
1102
16.2k
    }
1103
16.2k
    if (!found)
1104
16.2k
        return_scan_error(pfoe->missing_required_segment);
1105
16.2k
    if (segment != end)
1106
0
        return_error(illegal_font_data);
1107
16.2k
    plfont->large_sizes = large_sizes;
1108
16.2k
    plfont->scaling_technology = fst;
1109
16.2k
    return 0;
1110
16.2k
#undef return_scan_error
1111
16.2k
}
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.95M
{
1124
1.95M
    ulong len = (sfseek(in, 0L, SEEK_END), sftell(in));
1125
1126
1.95M
    *size = 6 + len;            /* leave room for segment header */
1127
1.95M
    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.95M
    srewind(in);
1137
1.95M
    *pptt_font_data = gs_alloc_bytes(mem, *size, "pl_tt_load_font data");
1138
1.95M
    if (*pptt_font_data == 0) {
1139
0
        sfclose(in);
1140
0
        return_error(gs_error_VMerror);
1141
0
    }
1142
1.95M
    sfread(*pptt_font_data + 6, 1, len, in);
1143
1.95M
    sfclose(in);
1144
1.95M
    return 0;
1145
1.95M
}
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.95M
{
1152
1.95M
    byte *tt_font_datap = NULL;
1153
1.95M
    ulong size;
1154
1.95M
    int code;
1155
1.95M
    gs_font_type42 *pfont = NULL;
1156
1.95M
    pl_font_t *plfont = NULL;
1157
1.95M
    byte *file_name = NULL;
1158
1.95M
    gs_const_string pfname;
1159
1160
1.95M
    if (sfilename(in, &pfname) == 0) {
1161
1.95M
        file_name =
1162
1.95M
            gs_alloc_bytes(mem, pfname.size + 1, "pl_load_tt_font file_name");
1163
1.95M
        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.95M
        memcpy(file_name, pfname.data, pfname.size + 1);
1169
1.95M
    }
1170
1171
    /* get the data from the file */
1172
1.95M
    code = pl_alloc_tt_fontfile_buffer(in, mem, &tt_font_datap, &size);
1173
1.95M
    if (code < 0)
1174
0
        goto error;
1175
    /* Make a Type 42 font out of the TrueType data. */
1176
1.95M
    pfont = gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42,
1177
1.95M
                            "pl_tt_load_font(gs_font_type42)");
1178
1.95M
    if (pfont == NULL) {
1179
0
        code = gs_error_VMerror;
1180
0
        goto error;
1181
0
    }
1182
1.95M
    memset(pfont, 0, sizeof(*pfont));
1183
1.95M
    plfont = pl_alloc_font(mem, "pl_tt_load_font(pl_font_t)");
1184
1.95M
    if (plfont == NULL) {
1185
0
        code = gs_error_VMerror;
1186
0
        goto error;
1187
0
    }
1188
1189
    /* Initialize general font boilerplate. */
1190
1.95M
    code = pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, font_name);
1191
1.95M
    if (code < 0)
1192
0
        goto error;
1193
1194
    /* Initialize TrueType font boilerplate. */
1195
1.95M
    plfont->header = tt_font_datap;
1196
1.95M
    plfont->header_size = size;
1197
1.95M
    plfont->scaling_technology = plfst_TrueType;
1198
1.95M
    plfont->font_type = plft_Unicode;
1199
1.95M
    plfont->large_sizes = true;
1200
1.95M
    plfont->offsets.GT = 0;
1201
1.95M
    plfont->is_xl_format = false;
1202
1.95M
    code = pl_fill_in_tt_font(pfont, tt_font_datap, unique_id);
1203
1.95M
    if (code < 0)
1204
0
        goto error;
1205
1.95M
    code = gs_definefont(pdir, (gs_font *) pfont);
1206
1.95M
    if (code < 0)
1207
0
        goto error;
1208
1209
1.95M
    code = pl_fapi_passfont(plfont, 0, NULL, (char *)file_name, NULL, 0);
1210
1.95M
    if (code < 0)
1211
0
        goto error;
1212
1.95M
    if (file_name)
1213
1.95M
        gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1214
1215
1.95M
    *pplfont = plfont;
1216
1.95M
    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.95M
}
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.47M
{
1230
1231
1.47M
    ulong len, size;
1232
1.47M
    byte *data;
1233
1234
1.47M
    if (plfont->font_file && !plfont->font_file_loaded) {
1235
40.5k
        stream *in = sfopen(plfont->font_file, "r", mem);
1236
1237
40.5k
        if (in == NULL)
1238
0
            return -1;
1239
        /* note this is exactly the same as the code in pl_load_tt_font */
1240
40.5k
        len = (sfseek(in, 0L, SEEK_END), sftell(in));
1241
40.5k
        size = 6 + len;         /* leave room for segment header */
1242
1243
40.5k
        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
40.5k
        srewind(in);
1253
40.5k
        data = gs_alloc_bytes(mem, size, "pl_tt_load_font data");
1254
40.5k
        if (data == 0) {
1255
0
            sfclose(in);
1256
0
            return_error(gs_error_VMerror);
1257
0
        }
1258
40.5k
        sfread(data + 6, 1, len, in);
1259
40.5k
        sfclose(in);
1260
40.5k
        plfont->header = data;
1261
40.5k
        plfont->header_size = size;
1262
40.5k
        plfont->font_file_loaded = true;
1263
40.5k
    }
1264
1.47M
    return 0;
1265
1.47M
}
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.64M
{
1272
    /* Free the header data */
1273
1.64M
    if (plfont->header) {
1274
1.64M
        gs_free_object(mem, plfont->header,
1275
1.64M
                       "pl_store_resident_font_data_in_file");
1276
1.64M
        plfont->header = 0;
1277
1.64M
        plfont->header_size = 0;
1278
1.64M
    } 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.64M
    if (!plfont->font_file) {
1285
1.64M
        plfont->font_file =
1286
1.64M
            (char *)gs_alloc_bytes(mem, strlen(font_file) + 1,
1287
1.64M
                                   "pl_store_resident_font_data_in_file");
1288
1.64M
        if (plfont->font_file == 0)
1289
0
            return -1;
1290
1.64M
        strcpy(plfont->font_file, font_file);
1291
1.64M
    }
1292
    /* designate that the font data is not in RAM */
1293
1.64M
    plfont->font_file_loaded = false;
1294
1.64M
    return 0;
1295
1.64M
}
1296
1297
pl_font_t *
1298
pl_lookup_font_by_pjl_number(pl_dict_t * pfontdict, int pjl_font_number)
1299
310k
{
1300
310k
    pl_dict_enum_t dictp;
1301
310k
    gs_const_string key;
1302
310k
    void *value;
1303
1304
310k
    pl_dict_enum_begin(pfontdict, &dictp);
1305
15.9M
    while (pl_dict_enum_next(&dictp, &key, &value)) {
1306
15.9M
        pl_font_t *plfont = value;
1307
1308
15.9M
        if (plfont->params.pjl_font_number == pjl_font_number)
1309
310k
            return value;
1310
15.9M
    }
1311
0
    return (pl_font_t *) NULL;
1312
310k
}