Coverage Report

Created: 2026-08-08 08:00

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
33.6k
#define u16(bptr) pl_get_uint16(bptr)
49
#define s16(bptr) pl_get_int16(bptr)
50
/**** ASSUME uint >= 32 BITS ****/
51
33.5k
#define u32(bptr) (uint)pl_get_uint32(bptr)
52
53
/* ---------------- Utilities ---------------- */
54
/* Free a font.  This is the freeing procedure in the font dictionary. */
55
void
56
pl_free_font(gs_memory_t * mem, void *plf, client_name_t cname)
57
1.98M
{
58
1.98M
    pl_font_t *plfont = plf;
59
60
    /* Free the characters. */
61
1.98M
    if (!plfont->data_are_permanent) {
62
1.96M
        if (plfont->glyphs.table) {
63
361
            uint i;
64
65
106k
            for (i = plfont->glyphs.size; i > 0;) {
66
105k
                void *data = (void *)plfont->glyphs.table[--i].data;
67
68
105k
                if (data)
69
1.78k
                    gs_free_object(mem, data, cname);
70
105k
            }
71
361
        }
72
1.96M
        gs_free_object(mem, (void *)plfont->header, cname);
73
1.96M
        plfont->header = 0;     /* see hack note above */
74
1.96M
    }
75
76
    /* free any nodes in the widths cache */
77
1.98M
    pl_font_glyph_width_cache_remove_nodes(plfont);
78
79
    /* Free the font data itself. */
80
1.98M
    gs_free_object(mem, (void *)plfont->char_glyphs.table, cname);
81
1.98M
    gs_free_object(mem, (void *)plfont->glyphs.table, cname);
82
1.98M
    if (plfont->pfont) {        /* might be only partially constructed */
83
1.98M
        gs_purge_font_from_char_caches_completely(plfont->pfont);
84
1.98M
        (void)gs_purge_font(plfont->pfont);
85
1.98M
        gs_free_object(mem, plfont->pfont, cname);
86
1.98M
    }
87
1.98M
    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.98M
    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.98M
    gs_free_object(mem, plf, cname);
100
1.98M
}
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.49M
{
539
1.49M
    pl_glyph_width_node_t *node;
540
541
    /* We can't safely cache widths for bitmap fonts */
542
1.49M
    if (plfont->scaling_technology == plfst_bitmap) {
543
0
        return(0);
544
0
    }
545
546
1.49M
    if (plfont->widths_cache_nitems > PL_MAX_WIDTHS_CACHE_NITEMS) {
547
508
        pl_font_glyph_width_cache_remove_nodes(plfont);
548
508
    }
549
550
1.49M
    node = (pl_glyph_width_node_t *) gs_alloc_bytes(plfont->pfont->memory,
551
1.49M
                                                 sizeof
552
1.49M
                                                 (pl_glyph_width_node_t),
553
1.49M
                                                 "pl_glyph_width_cache_node_add");
554
555
1.49M
    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.49M
    node->next = plfont->widths_cache;
564
1.49M
    plfont->widths_cache = node;
565
1.49M
    plfont->widths_cache_nitems++;
566
567
1.49M
    node->char_code = char_code;
568
1.49M
    node->font_id = plfont->pfont->id;
569
1.49M
    node->width = *pwidth;
570
571
1.49M
    return 0;
572
1.49M
}
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.8M
{
579
27.8M
    pl_glyph_width_node_t *current = plfont->widths_cache;
580
581
1.80G
    while (current) {
582
1.80G
        if (char_code == current->char_code) {
583
25.8M
            *pwidth = current->width;
584
25.8M
            return 0;
585
25.8M
        }
586
1.77G
        current = current->next;
587
1.77G
    }
588
1.95M
    return -1;
589
27.8M
}
590
591
592
/* ---------------- Public procedures ---------------- */
593
/* character width */
594
595
void
596
pl_font_glyph_width_cache_remove_nodes(pl_font_t *plfont)
597
2.23M
{
598
2.23M
    pl_glyph_width_node_t *current = plfont->widths_cache;
599
600
3.72M
    while (current) {
601
1.49M
        pl_glyph_width_node_t *next = current->next;
602
603
1.49M
        gs_free_object(plfont->pfont->memory, current, "pl_glyph_width_list_remove");
604
1.49M
        current = next;
605
1.49M
    }
606
2.23M
    plfont->widths_cache = NULL;
607
2.23M
    plfont->widths_cache_nitems = 0;
608
2.23M
    return;
609
2.23M
}
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.8M
{
615
27.8M
    int code = 0;
616
617
27.8M
    if (pl_font_glyph_width_cache_node_search(plfont, char_code, pwidth) >= 0) {
618
25.8M
        return(code);
619
25.8M
    }
620
621
1.95M
    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.49M
        (void)pl_font_glyph_width_cache_node_add((pl_font_t *)plfont, char_code, pwidth);
627
1.49M
    }
628
1.95M
    return code;
629
27.8M
}
630
631
/* character width */
632
int
633
pl_font_char_metrics(const pl_font_t * plfont, const void *pgs,
634
                     gs_char char_code, float metrics[4])
635
643k
{
636
643k
    return (*(plfont)->char_metrics) (plfont, pgs, char_code, metrics);
637
643k
}
638
639
/* Allocate a font. */
640
pl_font_t *
641
pl_alloc_font(gs_memory_t * mem, client_name_t cname)
642
1.98M
{
643
1.98M
    pl_font_t *plfont = gs_alloc_struct(mem, pl_font_t, &st_pl_font, cname);
644
645
1.98M
    if (plfont) {               /* Initialize pointers. */
646
1.98M
        plfont->pfont = 0;
647
1.98M
        plfont->header = 0;
648
1.98M
        plfont->glyphs.table = 0;
649
1.98M
        plfont->char_glyphs.table = 0;
650
        /* Initialize other defaults. */
651
1.98M
        plfont->orient = 0;
652
1.98M
        plfont->allow_vertical_substitutes = false;
653
1.98M
        plfont->bold_fraction = 0;
654
1.98M
        plfont->font_file = 0;
655
1.98M
        plfont->resolution.x = plfont->resolution.y = 0;
656
1.98M
        plfont->params.proportional_spacing = true;
657
1.98M
        memset(plfont->character_complement, 0xff, 8);
658
1.98M
        plfont->offsets.GC = plfont->offsets.GT = plfont->offsets.VT = -1;
659
1.98M
        plfont->pts_per_inch = 72.0;    /* normal value */
660
1.98M
        plfont->widths_cache = NULL;
661
1.98M
        plfont->widths_cache_nitems = 0;
662
1.98M
        plfont->names = NULL;
663
1.98M
        plfont->max_name_index = 0;
664
1.98M
        plfont->next_name_index = 0;
665
1.98M
    }
666
1.98M
    return plfont;
667
1.98M
}
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.04M
{
840
2.04M
    gs_font_base *pbfont = (gs_font_base *) pfont;
841
842
2.04M
    plfont->pfont = pfont;
843
    /* Initialize generic font data. */
844
2.04M
    gs_make_identity(&pbfont->orig_FontMatrix);
845
2.04M
    gs_make_identity(&pbfont->FontMatrix);
846
2.04M
    pbfont->next = pbfont->prev = 0;
847
2.04M
    pbfont->memory = mem;
848
2.04M
    pbfont->dir = pdir;
849
2.04M
    pbfont->is_resource = false;
850
2.04M
    gs_notify_init(&pbfont->notify_list, gs_memory_stable(mem));
851
2.04M
    pbfont->base = (gs_font *) pbfont;
852
2.04M
    pbfont->client_data = plfont;
853
2.04M
    pbfont->WMode = 0;
854
2.04M
    pbfont->PaintType = 0;
855
2.04M
    pbfont->StrokeWidth = 0;
856
2.04M
    pbfont->is_cached = 0;
857
2.04M
    pbfont->procs.init_fstack = gs_default_init_fstack;
858
2.04M
    pbfont->procs.next_char_glyph = gs_default_next_char_glyph;
859
2.04M
    pbfont->FAPI = NULL;
860
2.04M
    pbfont->FAPI_font_data = NULL;
861
862
2.04M
    pbfont->procs.glyph_name = pl_glyph_name;
863
2.04M
    pbfont->procs.decode_glyph = pl_decode_glyph;
864
    /* NB pbfont->procs.callbacks.known_encode = pl_known_encode; */
865
2.04M
    pbfont->procs.define_font = gs_no_define_font;
866
2.04M
    pbfont->procs.make_font = gs_no_make_font;
867
2.04M
    pbfont->procs.font_info = gs_default_font_info;
868
2.04M
    pbfont->procs.glyph_info = gs_default_glyph_info;
869
2.04M
    pbfont->procs.glyph_outline = gs_no_glyph_outline;
870
2.04M
    pbfont->id = gs_next_ids(mem, 1);
871
2.04M
    {
872
2.04M
        size_t sz = strlen(font_name);
873
2.04M
        gs_font_name *fnm = &pbfont->font_name;
874
2.04M
        gs_font_name *knm = &pbfont->key_name;
875
876
2.04M
        if (sz > gs_font_name_max)
877
0
            sz = gs_font_name_max;
878
2.04M
        fnm->size = knm->size = sz;
879
880
2.04M
        memcpy(fnm->chars, font_name, sz);
881
2.04M
        fnm->chars[sz] = 0;
882
883
2.04M
        memcpy(knm->chars, font_name, sz);
884
2.04M
        knm->chars[sz] = 0;
885
2.04M
    }
886
2.04M
    return 0;
887
2.04M
}
888
889
/* Fill in bitmap font boilerplate. */
890
void
891
pl_fill_in_bitmap_font(gs_font_base * pfont, long unique_id)
892
16.7k
{
893
16.7k
    pfont->FontType = ft_PCL_user_defined;
894
16.7k
    pfont->BitmapWidths = true;
895
16.7k
    pfont->ExactSize = fbit_use_bitmaps;
896
16.7k
    pfont->InBetweenSize = fbit_use_bitmaps;
897
16.7k
    pfont->TransformedChar = fbit_transform_bitmaps;
898
16.7k
    pl_bitmap_init_procs(pfont);
899
    /* We have no idea what the FontBBox should be. */
900
16.7k
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
901
16.7k
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
902
16.7k
    uid_set_UniqueID(&pfont->UID, unique_id);
903
16.7k
    pfont->encoding_index = 1;          /****** WRONG ******/
904
16.7k
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
905
16.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.96M
{
911
1.96M
    pfont->FontType = ft_TrueType;
912
1.96M
    pfont->BitmapWidths = true;
913
1.96M
    pfont->ExactSize = fbit_use_outlines;
914
1.96M
    pfont->InBetweenSize = fbit_use_outlines;
915
1.96M
    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.96M
    pfont->FontBBox.p.x = pfont->FontBBox.p.y =
923
1.96M
        pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
924
1.96M
    uid_set_UniqueID(&pfont->UID, unique_id);
925
1.96M
    pfont->encoding_index = 1;          /****** WRONG ******/
926
1.96M
    pfont->nearest_encoding_index = 1;          /****** WRONG ******/
927
    /* Initialize Type 42 specific data. */
928
1.96M
    pfont->data.proc_data = data;
929
1.96M
    pl_tt_init_procs(pfont);
930
1.96M
    {
931
1.96M
        int code = gs_type42_font_init(pfont, 0);
932
933
1.96M
        if (code < 0)
934
15
            return code;
935
1.96M
    }
936
    /* disable unused FAPI */
937
1.96M
    pfont->FAPI = 0;
938
1.96M
    pfont->FAPI_font_data = 0;
939
1.96M
    pl_tt_finish_init(pfont, !data);
940
1.96M
    return 0;
941
1.96M
}
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.7k
{
982
16.7k
    const byte *header = plfont->header;
983
16.7k
    pl_font_scaling_technology_t fst = header[fst_offset];
984
16.7k
    int wsize = (large_sizes ? 4 : 2);
985
16.7k
    const byte *segment = header + start_offset;
986
16.7k
    const byte *end = header + end_offset;
987
16.7k
    const byte *null_segment = end - (2 + wsize);
988
16.7k
    bool found = false;
989
16.7k
    ulong seg_size;
990
16.7k
    int illegal_font_data = pfoe->illegal_font_data;
991
992
16.7k
#define return_scan_error(err)\
993
16.7k
  return_error((err) ? (err) : illegal_font_data);
994
995
16.7k
    if (memcmp(null_segment, "\377\377", 2) /* NULL segment header */ )
996
16.7k
        return_scan_error(pfoe->missing_required_segment);
997
16.7k
    if (memcmp(null_segment + 2, "\0\0\0\0", wsize) /* NULL segment size */ )
998
16.7k
        return_scan_error(pfoe->illegal_null_segment_size);
999
16.7k
    switch (fst) {
1000
16.6k
        case plfst_bitmap:
1001
16.7k
        case plfst_TrueType:
1002
16.7k
            break;
1003
0
        default:
1004
0
            return_scan_error(pfoe->illegal_font_header_fields);
1005
16.7k
    }
1006
16.7k
    if (header[fst_offset + 1]) /* variety, must be 0 */
1007
16.7k
        return_scan_error(pfoe->illegal_font_header_fields);
1008
    /* Scan the segments. */
1009
50.3k
    for (; end - segment >= 2 + wsize; segment += 2 + wsize + seg_size) {
1010
33.5k
        uint seg_id = u16(segment);
1011
33.5k
        const byte *sdata = segment + 2 + wsize;
1012
1013
33.5k
#define id2(c1,c2) (((uint)(c1) << 8) + (c2))
1014
1015
33.5k
        seg_size = (large_sizes ? u32(segment + 2) : u16(segment + 2));
1016
33.5k
        if (seg_size + 2 + wsize > end - segment)
1017
2
            return_error(illegal_font_data);
1018
        /* Handle segments common to all fonts. */
1019
33.5k
        switch (seg_id) {
1020
16.7k
            case 0xffff:       /* NULL segment ID */
1021
16.7k
                if (segment != null_segment)
1022
0
                    return_error(illegal_font_data);
1023
16.7k
                continue;
1024
16.7k
            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.7k
            default:
1032
16.7k
                ;
1033
33.5k
        }
1034
        /* Handle segments specific to the scaling technology. */
1035
16.7k
        if (fst == plfst_bitmap)
1036
16.6k
            switch (seg_id) {
1037
16.6k
                case id2('B', 'R'):
1038
16.6k
                    if (seg_size != 4)
1039
16.6k
                        return_scan_error(pfoe->illegal_BR_segment);
1040
16.6k
                    {
1041
16.6k
                        uint xres = pl_get_uint16(sdata);
1042
16.6k
                        uint yres = pl_get_uint16(sdata + 2);
1043
1044
16.6k
                        if (xres == 0 || yres == 0)
1045
16.6k
                            return_scan_error(pfoe->illegal_BR_segment);
1046
16.6k
                        plfont->resolution.x = xres;
1047
16.6k
                        plfont->resolution.y = yres;
1048
16.6k
                    }
1049
16.6k
                    found = true;
1050
16.6k
                    break;
1051
0
                default:
1052
0
                    if (pfoe->illegal_font_segment < 0)
1053
0
                        return_error(pfoe->illegal_font_segment);
1054
16.6k
        } else                  /* fst == plfst_TrueType */
1055
98
            switch (seg_id) {
1056
98
                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
98
                    if (seg_size < 12 + 5 * 16 ||
1064
                        /* memcmp(sdata, "\000\001\000\000", 4) || */
1065
98
                        u16(sdata + 4) < 3)
1066
98
                        return_scan_error(pfoe->illegal_GT_segment);
1067
98
                    plfont->offsets.GT = segment - header;
1068
98
                    found = true;
1069
98
                    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
98
            }
1101
16.7k
#undef id2
1102
16.7k
    }
1103
16.7k
    if (!found)
1104
16.7k
        return_scan_error(pfoe->missing_required_segment);
1105
16.7k
    if (segment != end)
1106
0
        return_error(illegal_font_data);
1107
16.7k
    plfont->large_sizes = large_sizes;
1108
16.7k
    plfont->scaling_technology = fst;
1109
16.7k
    return 0;
1110
16.7k
#undef return_scan_error
1111
16.7k
}
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.96M
{
1124
1.96M
    ulong len = (sfseek(in, 0L, SEEK_END), sftell(in));
1125
1126
1.96M
    *size = 6 + len;            /* leave room for segment header */
1127
1.96M
    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.96M
    srewind(in);
1137
1.96M
    *pptt_font_data = gs_alloc_bytes(mem, *size, "pl_tt_load_font data");
1138
1.96M
    if (*pptt_font_data == 0) {
1139
0
        sfclose(in);
1140
0
        return_error(gs_error_VMerror);
1141
0
    }
1142
1.96M
    sfread(*pptt_font_data + 6, 1, len, in);
1143
1.96M
    sfclose(in);
1144
1.96M
    return 0;
1145
1.96M
}
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.96M
{
1152
1.96M
    byte *tt_font_datap = NULL;
1153
1.96M
    ulong size;
1154
1.96M
    int code;
1155
1.96M
    gs_font_type42 *pfont = NULL;
1156
1.96M
    pl_font_t *plfont = NULL;
1157
1.96M
    byte *file_name = NULL;
1158
1.96M
    gs_const_string pfname;
1159
1160
1.96M
    if (sfilename(in, &pfname) == 0) {
1161
1.96M
        file_name =
1162
1.96M
            gs_alloc_bytes(mem, pfname.size + 1, "pl_load_tt_font file_name");
1163
1.96M
        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.96M
        memcpy(file_name, pfname.data, pfname.size + 1);
1169
1.96M
    }
1170
1171
    /* get the data from the file */
1172
1.96M
    code = pl_alloc_tt_fontfile_buffer(in, mem, &tt_font_datap, &size);
1173
1.96M
    if (code < 0)
1174
0
        goto error;
1175
    /* Make a Type 42 font out of the TrueType data. */
1176
1.96M
    pfont = gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42,
1177
1.96M
                            "pl_tt_load_font(gs_font_type42)");
1178
1.96M
    if (pfont == NULL) {
1179
0
        code = gs_error_VMerror;
1180
0
        goto error;
1181
0
    }
1182
1.96M
    memset(pfont, 0, sizeof(*pfont));
1183
1.96M
    plfont = pl_alloc_font(mem, "pl_tt_load_font(pl_font_t)");
1184
1.96M
    if (plfont == NULL) {
1185
0
        code = gs_error_VMerror;
1186
0
        goto error;
1187
0
    }
1188
1189
    /* Initialize general font boilerplate. */
1190
1.96M
    code = pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, font_name);
1191
1.96M
    if (code < 0)
1192
0
        goto error;
1193
1194
    /* Initialize TrueType font boilerplate. */
1195
1.96M
    plfont->header = tt_font_datap;
1196
1.96M
    plfont->header_size = size;
1197
1.96M
    plfont->scaling_technology = plfst_TrueType;
1198
1.96M
    plfont->font_type = plft_Unicode;
1199
1.96M
    plfont->large_sizes = true;
1200
1.96M
    plfont->offsets.GT = 0;
1201
1.96M
    plfont->is_xl_format = false;
1202
1.96M
    code = pl_fill_in_tt_font(pfont, tt_font_datap, unique_id);
1203
1.96M
    if (code < 0)
1204
0
        goto error;
1205
1.96M
    code = gs_definefont(pdir, (gs_font *) pfont);
1206
1.96M
    if (code < 0)
1207
0
        goto error;
1208
1209
1.96M
    code = pl_fapi_passfont(plfont, 0, NULL, (char *)file_name, NULL, 0);
1210
1.96M
    if (code < 0)
1211
0
        goto error;
1212
1.96M
    if (file_name)
1213
1.96M
        gs_free_object(mem, file_name, "pl_load_tt_font file_name");
1214
1215
1.96M
    *pplfont = plfont;
1216
1.96M
    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.96M
}
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.44M
{
1230
1231
1.44M
    ulong len, size;
1232
1.44M
    byte *data;
1233
1234
1.44M
    if (plfont->font_file && !plfont->font_file_loaded) {
1235
40.3k
        stream *in = sfopen(plfont->font_file, "r", mem);
1236
1237
40.3k
        if (in == NULL)
1238
0
            return -1;
1239
        /* note this is exactly the same as the code in pl_load_tt_font */
1240
40.3k
        len = (sfseek(in, 0L, SEEK_END), sftell(in));
1241
40.3k
        size = 6 + len;         /* leave room for segment header */
1242
1243
40.3k
        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.3k
        srewind(in);
1253
40.3k
        data = gs_alloc_bytes(mem, size, "pl_tt_load_font data");
1254
40.3k
        if (data == 0) {
1255
0
            sfclose(in);
1256
0
            return_error(gs_error_VMerror);
1257
0
        }
1258
40.3k
        sfread(data + 6, 1, len, in);
1259
40.3k
        sfclose(in);
1260
40.3k
        plfont->header = data;
1261
40.3k
        plfont->header_size = size;
1262
40.3k
        plfont->font_file_loaded = true;
1263
40.3k
    }
1264
1.44M
    return 0;
1265
1.44M
}
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
303k
{
1300
303k
    pl_dict_enum_t dictp;
1301
303k
    gs_const_string key;
1302
303k
    void *value;
1303
1304
303k
    pl_dict_enum_begin(pfontdict, &dictp);
1305
15.6M
    while (pl_dict_enum_next(&dictp, &key, &value)) {
1306
15.6M
        pl_font_t *plfont = value;
1307
1308
15.6M
        if (plfont->params.pjl_font_number == pjl_font_number)
1309
303k
            return value;
1310
15.6M
    }
1311
0
    return (pl_font_t *) NULL;
1312
303k
}