Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pl/pllfont.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 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
/* pclfont.c */
18
/* PCL5 font preloading */
19
#include "ctype_.h"
20
#include "stdio_.h"
21
#include "string_.h"
22
#include "gx.h"
23
#include "gxiodev.h"
24
#include "gp.h"
25
#include "gsccode.h"
26
#include "gserrors.h"
27
#include "gsmatrix.h"
28
#include "gsutil.h"
29
#include "gxfont.h"
30
#include "gxfont42.h"
31
#include "stream.h"
32
#include "strmio.h"
33
#include "plfont.h"
34
#include "pldict.h"
35
#include "pllfont.h"
36
#include "plftable.h"
37
#include "plvalue.h"
38
#include "plvocab.h"
39
#include "gxfapi.h"
40
#include "plfapi.h"
41
#include "plufstlp.h"
42
43
44
extern const char gp_file_name_list_separator;
45
46
/* Load some built-in fonts.  This must be done at initialization time, but
47
 * after the state and memory are set up.  Return an indication of whether
48
 * at least one font was successfully loaded.  XXX The existing code is more
49
 * than a bit of a hack.  Approach: expect to find some fonts in one or more
50
 * of a given list of directories with names *.ttf.  Load whichever ones are
51
 * found in the table below.  Probably very little of this code can be
52
 * salvaged for later.
53
 */
54
55
/* get the windows truetype font file name */
56
#define WINDOWSNAME 4
57
862k
#define PSNAME 6
58
59
static int
60
get_name_from_tt_file(stream * tt_file, gs_memory_t * mem,
61
                      char *pfontfilename, int nameoffset)
62
862k
{
63
    /* check if an open file a ttfile saving and restoring the file position */
64
862k
    long pos;                   /* saved file position */
65
862k
    unsigned long len;
66
862k
    char *ptr = pfontfilename;
67
862k
    byte *ptt_font_data;
68
69
862k
    if ((pos = sftell(tt_file)) < 0)
70
0
        return -1;
71
    /* seek to end and get the file length and allocate a buffer
72
       for the entire file */
73
862k
    if (sfseek(tt_file, 0L, SEEK_END))
74
0
        return -1;
75
862k
    len = sftell(tt_file);
76
77
    /* allocate a buffer for the entire file */
78
862k
    ptt_font_data = gs_alloc_bytes(mem, len, "get_name_from_tt_file");
79
862k
    if (ptt_font_data == NULL)
80
0
        return_error(gs_error_VMerror);
81
82
    /* seek back to the beginning of the file and read the data
83
       into the buffer */
84
862k
    if ((sfseek(tt_file, 0L, SEEK_SET) == 0) && (sfread(ptt_font_data, 1, len, tt_file) == len));       /* ok */
85
0
    else {
86
0
        gs_free_object(mem, ptt_font_data, "get_name_from_tt_file");
87
0
        return -1;
88
0
    }
89
90
862k
    {
91
        /* find the "name" table */
92
862k
        byte *pnum_tables_data = ptt_font_data + 4;
93
862k
        byte *ptable_directory_data = ptt_font_data + 12;
94
862k
        int table;
95
96
10.8M
        for (table = 0; table < pl_get_uint16(pnum_tables_data); table++)
97
10.8M
            if (!memcmp(ptable_directory_data + (table * 16), "name", 4)) {
98
862k
                unsigned int offset =
99
862k
                    pl_get_uint32(ptable_directory_data + (table * 16) + 8);
100
862k
                byte *name_table = ptt_font_data + offset;
101
                /* the offset to the string pool */
102
862k
                unsigned short storageOffset = pl_get_uint16(name_table + 4);
103
862k
                byte *name_recs = name_table + 6;
104
105
862k
                {
106
                    /* 4th entry in the name table - the complete name */
107
862k
                    unsigned short length =
108
862k
                        pl_get_uint16(name_recs + (12 * nameoffset) + 8);
109
862k
                    unsigned short offset =
110
862k
                        pl_get_uint16(name_recs + (12 * nameoffset) + 10);
111
862k
                    int k;
112
113
16.8M
                    for (k = 0; k < length; k++) {
114
                        /* hack around unicode if necessary */
115
15.9M
                        int c = name_table[storageOffset + offset + k];
116
117
15.9M
                        if (isprint(c))
118
15.8M
                            *ptr++ = (char)c;
119
15.9M
                    }
120
862k
                }
121
862k
                break;
122
862k
            }
123
862k
    }
124
    /* free up the data and restore the file position */
125
862k
    gs_free_object(mem, ptt_font_data, "get_name_from_tt_file");
126
862k
    if (sfseek(tt_file, pos, SEEK_SET) < 0)
127
0
        return -1;
128
    /* null terminate the fontname string and return success.  Note
129
       the string can be 0 length if no fontname was found. */
130
862k
    *ptr = '\0';
131
132
    /* trim trailing white space */
133
862k
    {
134
862k
        int i = strlen(pfontfilename);
135
136
862k
        while (--i >= 0) {
137
862k
            if (!isspace(pfontfilename[i]))
138
862k
                break;
139
862k
        }
140
862k
        pfontfilename[++i] = '\0';
141
862k
    }
142
143
862k
    return 0;
144
862k
}
145
146
#ifdef DEBUG
147
static void
148
check_resident_ufst_fonts(pl_dict_t * pfontdict,
149
                          bool use_unicode_names_for_keys, gs_memory_t * mem)
150
{
151
    int j;
152
153
    for (j = 0;
154
         *pl_built_in_resident_font_table[j].full_font_name[AGFANAME] != 0
155
         && j < pl_built_in_resident_font_table_count; j++) {
156
        void *value;
157
158
        /* lookup unicode key in the resident table */
159
        if (use_unicode_names_for_keys) {
160
            if (!pl_dict_lookup(pfontdict,
161
                                (const byte *)pl_built_in_resident_font_table[j].
162
                                unicode_fontname,
163
                                sizeof(pl_built_in_resident_font_table[j].unicode_fontname),
164
                                &value, true,
165
                                NULL) /* return data ignored */ ) {
166
                int i;
167
168
                dmprintf(mem, "Font with unicode key: ");
169
                for (i = 0;
170
                     i <
171
                     sizeof(pl_built_in_resident_font_table[j].unicode_fontname) /
172
                     sizeof(pl_built_in_resident_font_table[j].unicode_fontname[0]); i++) {
173
                    dmprintf1(mem, "%c",
174
                              (char)pl_built_in_resident_font_table[j].unicode_fontname[i]);
175
                }
176
                dmprintf1(mem,
177
                          " not available in font dictionary, resident table position: %d\n",
178
                          j);
179
            }
180
        } else {
181
            byte key[3];
182
183
            key[2] = (byte) j;
184
            key[0] = key[1] = 0;
185
            if (!pl_dict_lookup(pfontdict,
186
                                key,
187
                                sizeof(key),
188
                                &value, true,
189
                                NULL) /* return data ignored */ )
190
                dmprintf2(mem,
191
                          "%s not available in font dictionary, resident table position: %d\n",
192
                          (char *)pl_built_in_resident_font_table[j].full_font_name, j);
193
        }
194
    }
195
    return;
196
}
197
198
static void
199
check_resident_fonts(pl_dict_t * pfontdict, gs_memory_t * mem)
200
{
201
    int i;
202
203
    for (i = 0;
204
         *pl_built_in_resident_font_table[i].full_font_name[URWNAME] != 0
205
         && i < pl_built_in_resident_font_table_count; i++)
206
        if (!pl_lookup_font_by_pjl_number(pfontdict, i)) {
207
            int j;
208
209
            dmprintf2(mem, "%s (entry %d) not found\n",
210
                      pl_built_in_resident_font_table[i].full_font_name[URWNAME], i);
211
            dmprintf(mem, "pxl unicode name:");
212
            for (j = 0; j < countof(pl_built_in_resident_font_table[i].unicode_fontname); j++)
213
                dmprintf1(mem, "'%c'", pl_built_in_resident_font_table[i].unicode_fontname[j]);
214
            dmprintf(mem, "\n");
215
        }
216
}
217
#endif
218
219
/* Load a built-in AGFA MicroType font */
220
static int
221
pl_fill_in_mt_font(gs_font_base * pfont, pl_font_t * plfont, ushort handle,
222
                   char *fco_path, gs_font_dir * pdir, gs_memory_t * mem,
223
                   long unique_id)
224
0
{
225
0
    int code = 0;
226
227
0
    if (pfont == 0 || plfont == 0)
228
0
        code = gs_note_error(gs_error_VMerror);
229
0
    else {                      /* Initialize general font boilerplate. */
230
0
        code =
231
0
            pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem,
232
0
                            "illegal_font");
233
0
        if (code >= 0) {        /* Initialize MicroType font boilerplate. */
234
0
            plfont->header = 0;
235
0
            plfont->header_size = 0;
236
0
            plfont->scaling_technology = plfst_MicroType;
237
0
            plfont->font_type = plft_Unicode;
238
0
            plfont->large_sizes = true;
239
0
            plfont->is_xl_format = false;
240
0
            plfont->allow_vertical_substitutes = false;
241
242
0
            gs_make_identity(&pfont->FontMatrix);
243
0
            pfont->FontMatrix.xx = pfont->FontMatrix.yy = 0.001f;
244
0
            pfont->FontType = ft_MicroType;
245
0
            pfont->BitmapWidths = true;
246
0
            pfont->ExactSize = fbit_use_outlines;
247
0
            pfont->InBetweenSize = fbit_use_outlines;
248
0
            pfont->TransformedChar = fbit_use_outlines;
249
250
0
            pfont->FontBBox.p.x = pfont->FontBBox.p.y =
251
0
                pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
252
253
0
            uid_set_UniqueID(&pfont->UID, unique_id | ( ((long) handle) << 16));
254
0
            pfont->encoding_index = 1;      /****** WRONG ******/
255
0
            pfont->nearest_encoding_index = 1;      /****** WRONG ******/
256
0
        }
257
0
    }
258
0
    return (code);
259
0
}
260
261
int
262
pl_load_ufst_lineprinter(gs_memory_t * mem, pl_dict_t * pfontdict,
263
                         gs_font_dir * pdir, int storage,
264
                         bool use_unicode_names_for_keys)
265
0
{
266
0
    int i;
267
268
0
    for (i = 0;
269
0
         *pl_built_in_resident_font_table[i].full_font_name[AGFANAME] != 0
270
0
         && i < pl_built_in_resident_font_table_count; i++) {
271
0
        if (pl_built_in_resident_font_table[i].params.typeface_family == 0) {
272
0
            const byte *header = NULL;
273
0
            const byte *char_data = NULL;
274
0
            pl_font_t *pplfont =
275
0
                pl_alloc_font(mem, "pl_load_ufst_lineprinter pplfont");
276
0
            gs_font_base *pfont =
277
0
                gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
278
0
                                "pl_load_ufst_lineprinter pfont");
279
0
            int code;
280
281
0
            pl_get_ulp_character_data((byte **) & header,
282
0
                                      (byte **) & char_data);
283
284
0
            if (!header || !char_data) {
285
0
                return -1;
286
0
            }
287
288
            /* these shouldn't happen during system setup */
289
0
            if (pplfont == 0 || pfont == 0)
290
0
                return -1;
291
0
            if (pl_fill_in_font
292
0
                ((gs_font *) pfont, pplfont, pdir, mem,
293
0
                 "lineprinter_font") < 0)
294
0
                return -1;
295
296
0
            pl_fill_in_bitmap_font(pfont, gs_next_ids(mem, 1));
297
0
            pplfont->params = pl_built_in_resident_font_table[i].params;
298
0
            memcpy(pplfont->character_complement,
299
0
                   pl_built_in_resident_font_table[i].character_complement, 8);
300
301
0
            if (use_unicode_names_for_keys)
302
0
                code = pl_dict_put(pfontdict,
303
0
                            (const byte *)pl_built_in_resident_font_table[i].unicode_fontname,
304
0
                            sizeof(pl_built_in_resident_font_table[i].unicode_fontname), pplfont);
305
0
            else {
306
0
                byte key[3];
307
308
0
                key[2] = (byte) i;
309
0
                key[0] = key[1] = 0;
310
0
                code = pl_dict_put(pfontdict, key, sizeof(key), pplfont);
311
0
            }
312
0
            if (code < 0)
313
0
                return code;
314
0
            pplfont->storage = storage; /* should be an internal font */
315
0
            pplfont->data_are_permanent = true;
316
0
            pplfont->header = (byte *) header;
317
0
            pplfont->font_type = plft_8bit_printable;
318
0
            pplfont->scaling_technology = plfst_bitmap;
319
0
            pplfont->is_xl_format = false;
320
0
            pplfont->resolution.x = pplfont->resolution.y = 300;
321
322
0
            code = pl_font_alloc_glyph_table(pplfont, 256, mem,
323
0
                                             "pl_load_ufst_lineprinter pplfont (glyph table)");
324
0
            if (code < 0)
325
0
                return code;
326
327
0
            while (1) {
328
329
0
                uint width = pl_get_uint16(char_data + 12);
330
0
                uint height = pl_get_uint16(char_data + 14);
331
0
                uint ccode_plus_header_plus_data =
332
0
                    2 + 16 + (((width + 7) >> 3) * height);
333
0
                uint ucode =
334
0
                    pl_map_MSL_to_Unicode(pl_get_uint16(char_data), 0);
335
0
                int code = 0;
336
337
                /* NB this shouldn't happen but it does, should be
338
                   looked at */
339
0
                if (ucode != 0xffff)
340
0
                    code = pl_font_add_glyph(pplfont, ucode, char_data + 2, ccode_plus_header_plus_data);
341
342
0
                if (code < 0)
343
                    /* shouldn't happen */
344
0
                    return -1;
345
                /* calculate the offset of the next character code in the table */
346
0
                char_data += ccode_plus_header_plus_data;
347
348
                /* char code 0 is end of table */
349
0
                if (pl_get_uint16(char_data) == 0)
350
0
                    break;
351
0
            }
352
0
            code = gs_definefont(pdir, (gs_font *) pfont);
353
0
            if (code < 0)
354
                /* shouldn't happen */
355
0
                return -1;
356
0
        }
357
0
    }
358
0
    return 0;
359
0
}
360
361
362
static int
363
pl_load_built_in_mtype_fonts(const char *pathname, gs_memory_t * mem,
364
                             pl_dict_t * pfontdict, gs_font_dir * pdir,
365
                             int storage, bool use_unicode_names_for_keys)
366
105k
{
367
105k
    int i, k;
368
105k
    short status = 0;
369
105k
    int bSize;
370
105k
    byte key[3] = {0};
371
105k
    char pthnm[1024];
372
105k
    char *ufst_root_dir;
373
105k
    char *fco;
374
105k
    char *fco_start, *fco_lim;
375
105k
    pl_font_t *plfont = NULL;
376
105k
    gs_font *pfont = NULL;
377
105k
    gs_font_base *pbfont;
378
379
    /* don't load fonts more than once */
380
105k
    if (pl_dict_length(pfontdict, true) > 0)
381
94.8k
        return 1;
382
383
10.6k
    if (!pl_fapi_ufst_available(mem)) {
384
10.6k
        return (0);
385
10.6k
    }
386
387
388
    /*
389
     * Open and install the various font collection objects.
390
     *
391
     * For each font collection object, step through the object until it is
392
     * exhausted, placing any fonts found in the built_in_fonts dictionary.
393
     *
394
     */
395
0
    ufst_root_dir = (char *)pl_fapi_ufst_get_font_dir(mem);
396
0
    fco_start = fco = (char *)pl_fapi_ufst_get_fco_list(mem);
397
0
    fco_lim = fco_start + strlen(fco_start) + 1;
398
399
0
    for (k = 0; fco < fco_lim && strlen(fco) > 0; k++) {
400
0
        status = 0;
401
        /* build and open (get handle) for the k'th fco file name */
402
0
        gs_strlcpy((char *)pthnm, ufst_root_dir, sizeof pthnm);
403
404
0
        for (i = 2; fco[i] != gp_file_name_list_separator && (&fco[i]) < fco_lim - 1; i++)
405
0
            ;
406
407
0
        strncat(pthnm, fco, i);
408
0
        fco += (i + 1);
409
410
        /* enumerat the files in this fco */
411
0
        for (i = 0; status == 0; i++, key[2] += 1) {
412
0
            char *pname = NULL;
413
414
            /* If we hit a font we're not going to use, we'll reuse the allocated
415
             * memory.
416
             */
417
0
            if (!plfont) {
418
419
0
                pbfont =
420
0
                    gs_alloc_struct(mem, gs_font_base, &st_gs_font_base,
421
0
                                    "pl_mt_load_font(gs_font_base)");
422
0
                plfont = pl_alloc_font(mem, "pl_mt_load_font(pl_font_t)");
423
0
                if (!pbfont || !plfont) {
424
0
                    gs_free_object(mem, plfont, "pl_mt_load_font(pl_font_t)");
425
0
                    gs_free_object(mem, pfont,
426
0
                                   "pl_mt_load_font(gs_font_base)");
427
0
                    dmprintf1(mem, "VM error for built-in font %d", i);
428
0
                    continue;
429
0
                }
430
0
            }
431
0
            pfont = (gs_font *) pbfont;
432
433
0
            status =
434
0
                pl_fill_in_mt_font(pbfont, plfont, i, pthnm, pdir, mem, i);
435
0
            if (status < 0) {
436
0
                dmprintf2(mem, "Error %d for built-in font %d", status, i);
437
0
                continue;
438
0
            }
439
440
0
            status =
441
0
                pl_fapi_passfont(plfont, i, (char *)"UFST", pthnm, NULL, 0);
442
443
0
            if (status != 0) {
444
#ifdef DEBUG
445
                dmprintf1(mem, "CGIFfco_Access error %d\n", status);
446
#endif
447
0
            } else {
448
0
                int font_number = 0;
449
                /* unfortunately agfa has 2 fonts named symbol.  We
450
                   believe the font with internal number, NB, NB, NB  */
451
0
                char *symname = (char *)"SymbPS";
452
0
                int j;
453
0
                uint spaceBand;
454
0
                uint scaleFactor;
455
0
                bool used = false;
456
0
                int code = 0;
457
458
                /* For Microtype fonts, once we get here, these
459
                 * pl_fapi_get*() calls cannot fail, so we can
460
                 * safely ignore the return value
461
                 */
462
0
                (void)pl_fapi_get_mtype_font_name(pfont, NULL, &bSize);
463
464
0
                pname =
465
0
                    (char *)gs_alloc_bytes(mem, bSize,
466
0
                                           "pl_mt_load_font: font name buffer");
467
0
                if (!pname) {
468
0
                    dmprintf1(mem, "VM Error for built-in font %d", i);
469
0
                    continue;
470
0
                }
471
472
0
                (void)pl_fapi_get_mtype_font_name(pfont, (byte *) pname,
473
0
                                                  &bSize);
474
475
0
                (void)pl_fapi_get_mtype_font_number(pfont, &font_number);
476
0
                (void)pl_fapi_get_mtype_font_spaceBand(pfont, &spaceBand);
477
0
                (void)pl_fapi_get_mtype_font_scaleFactor(pfont, &scaleFactor);
478
479
0
                if (font_number == 24463) {
480
0
                    gs_free_object(mem, pname,
481
0
                                   "pl_mt_load_font: font name buffer");
482
0
                    pname = symname;
483
0
                }
484
485
0
                for (j = 0; *pl_built_in_resident_font_table[j].full_font_name[AGFANAME]; j++) {
486
0
                    if (strcmp
487
0
                        ((char *)pl_built_in_resident_font_table[j].full_font_name[AGFANAME],
488
0
                         (char *)pname) != 0)
489
0
                        continue;
490
491
#ifdef DEBUG
492
                    if (gs_debug_c('='))
493
                        dmprintf2(mem, "Loading %s from fco %s\n", pname,
494
                                  pthnm);
495
#endif
496
                    /* Record the differing points per inch value
497
                       for Intellifont derived fonts. */
498
499
0
                    if (scaleFactor == 8782) {
500
0
                        plfont->pts_per_inch = 72.307f;
501
0
                    }
502
503
0
                    plfont->font_type = pl_built_in_resident_font_table[j].font_type;
504
0
                    plfont->storage = storage;
505
0
                    plfont->data_are_permanent = false;
506
0
                    plfont->params = pl_built_in_resident_font_table[j].params;
507
508
                    /*
509
                     * NB: though the TTFONTINFOTYPE structure has a
510
                     * pcltChComp field, it is not filled in by the UFST
511
                     * code (which just initializes it to 0). Hence, the
512
                     * hard-coded information in the resident font
513
                     * initialization structure is used.
514
                     */
515
0
                    memcpy(plfont->character_complement,
516
0
                           pl_built_in_resident_font_table[j].character_complement, 8);
517
518
0
                    status = gs_definefont(pdir, (gs_font *) pfont);
519
0
                    if (status < 0) {
520
0
                        status = 0;
521
0
                        continue;
522
0
                    }
523
0
                    status =
524
0
                        pl_fapi_passfont(plfont, i, (char *)"UFST", pthnm,
525
0
                                         NULL, 0);
526
0
                    if (status < 0) {
527
0
                        status = 0;
528
0
                        continue;
529
0
                    }
530
0
                    if (use_unicode_names_for_keys)
531
0
                        code = pl_dict_put(pfontdict,
532
0
                                    (const byte *)pl_built_in_resident_font_table[j].unicode_fontname,
533
0
                                    sizeof(pl_built_in_resident_font_table[j].unicode_fontname),
534
0
                                    plfont);
535
0
                    else {
536
0
                        key[2] = (byte) j;
537
0
                        key[0] = key[1] = 0;
538
0
                        code = pl_dict_put(pfontdict, key, sizeof(key), plfont);
539
0
                    }
540
0
                    if (code < 0)
541
0
                        return code;
542
0
                    used = true;
543
0
                }
544
                /* If we've stored the font, null the local reference */
545
0
                if (used) {
546
0
                    plfont = NULL;
547
0
                    pfont = NULL;
548
0
                }
549
0
                if (pname != symname)
550
0
                    gs_free_object(mem, pname,
551
0
                                   "pl_mt_load_font: font name buffer");
552
0
                pname = NULL;
553
0
            }
554
0
        }
555
0
    }                           /* end enumerate fco loop */
556
557
0
    gs_free_object(mem, plfont, "pl_mt_load_font(pl_font_t)");
558
0
    gs_free_object(mem, pfont, "pl_mt_load_font(gs_font_base)");
559
560
    /* finally add lineprinter NB return code ignored */
561
0
    (void)pl_load_ufst_lineprinter(mem, pfontdict, pdir, storage,
562
0
                                   use_unicode_names_for_keys);
563
564
#ifdef DEBUG
565
    if (gs_debug_c('='))
566
        check_resident_ufst_fonts(pfontdict, use_unicode_names_for_keys, mem);
567
#endif
568
569
0
    if (status == 0 || status == -10)
570
0
        return (1);
571
572
0
    return (0);
573
0
}
574
575
576
/* NOTES ABOUT NB NB - if the font dir necessary */
577
int
578
pl_load_built_in_fonts(const char *pathname, gs_memory_t * mem,
579
                       pl_dict_t * pfontdict, gs_font_dir * pdir,
580
                       int storage, bool use_unicode_names_for_keys)
581
105k
{
582
105k
    const font_resident_t *residentp;
583
    /* get rid of this should be keyed by pjl font number */
584
105k
    byte key[3];
585
105k
    char path[1024];
586
105k
    bool found;
587
105k
    bool found_any = false;
588
105k
    file_enum *fe;
589
105k
    int code = 0;
590
591
105k
    if ((code =
592
105k
         pl_load_built_in_mtype_fonts(pathname, mem, pfontdict, pdir, storage,
593
105k
                                      use_unicode_names_for_keys))) {
594
94.8k
        return (code);
595
94.8k
    }
596
597
    /* don't load fonts more than once */
598
10.6k
    if (pl_dict_length(pfontdict, true) > 0)
599
0
        return 1;
600
601
10.6k
    if (pathname == NULL)
602
0
        return 0;
603
604
10.6k
    if (gs_strlcpy(path, pathname, sizeof(path)) >= sizeof(path))
605
0
        return 0;
606
607
10.6k
    if (gs_strlcat(path, "*", sizeof(path)) >= sizeof(path))
608
0
        return 0;
609
610
10.6k
    fe = gs_enumerate_files_init(mem, path, strlen(path));
611
10.6k
    if (fe == NULL)
612
0
        return 0;
613
614
    /* loop through the files */
615
873k
    while ((code = gs_enumerate_files_next(mem, fe, path, sizeof(path) - 1)) >= 0) {
616
862k
        char buffer[1024];
617
862k
        pl_font_t *plfont;
618
862k
        stream *in;
619
620
862k
        if (code > sizeof(path) - 1) {
621
0
            dmprintf(mem,
622
0
                     "filename length exceeds file name storage buffer length\n");
623
0
            continue;
624
0
        }
625
        /* null terminate the string */
626
862k
        path[code] = '\0';
627
628
862k
        in = sfopen(path, "r", mem);
629
862k
        if (in == NULL) {   /* shouldn't happen */
630
0
            dmprintf1(mem, "cannot open file %s\n", path);
631
0
            continue;
632
0
        }
633
634
862k
        code = get_name_from_tt_file(in, mem, buffer, PSNAME);
635
862k
        if (code < 0) {
636
0
            dmprintf1(mem, "input output failure on TrueType File %s\n",
637
0
                      path);
638
0
            sfclose(in);
639
0
            continue;
640
0
        }
641
642
862k
        if (strlen(buffer) == 0) {
643
0
            dmprintf1(mem,
644
0
                      "could not extract font file name from file %s\n",
645
0
                      path);
646
0
            sfclose(in);
647
0
            continue;
648
0
        }
649
650
        /* lookup the font file name in the resident table */
651
862k
        found = false;
652
862k
        for (residentp = pl_built_in_resident_font_table;
653
88.8M
             *residentp->full_font_name[URWNAME]; ++residentp) {
654
87.9M
            if (strcmp(buffer, residentp->full_font_name[URWNAME]) != 0)
655
86.8M
                continue;
656
            /* load the font file into memory.  NOTE: this closes the file - argh... */
657
1.08M
            if (pl_load_tt_font(in, pdir, mem,
658
1.08M
                                gs_next_ids(mem, 1), &plfont,
659
1.08M
                                buffer) < 0) {
660
                /* vm error */
661
0
                gs_enumerate_files_close(mem, fe);
662
0
                return gs_throw1(0,
663
0
                                 "An unrecoverable failure occurred while reading the resident font %s\n",
664
0
                                 path);
665
0
            }
666
            /* reopen the file */
667
1.08M
            in = sfopen(path, "r", mem);
668
1.08M
            if (in == NULL) {
669
0
                gs_free_object(mem, plfont->pfont, "pl_tt_load_font(gs_font_type42)");
670
0
                pl_free_tt_fontfile_buffer(mem, plfont->header);
671
0
                gs_free_object(mem, plfont, "pl_tt_load_font(pl_font_t)");
672
0
                gs_enumerate_files_close(mem, fe);
673
0
                return gs_throw1(0,
674
0
                                 "An unrecoverable failure occurred while reading the resident font %s\n",
675
0
                                 path);
676
0
            }
677
678
1.08M
            plfont->storage = storage;
679
1.08M
            plfont->data_are_permanent = false;
680
681
            /* use the offset in the table as the pjl font number */
682
            /* for unicode keying of the dictionary use the unicode
683
               font name, otherwise use the keys. */
684
1.08M
            plfont->font_type = residentp->font_type;
685
1.08M
            plfont->params = residentp->params;
686
1.08M
            memcpy(plfont->character_complement,
687
1.08M
                   residentp->character_complement, 8);
688
1.08M
            if (use_unicode_names_for_keys)
689
260k
                code = pl_dict_put(pfontdict,
690
260k
                                   (const byte *)residentp->unicode_fontname,
691
260k
                                   sizeof(residentp->unicode_fontname),
692
260k
                                   plfont);
693
825k
            else {
694
825k
                key[2] = (byte) (residentp - pl_built_in_resident_font_table);
695
825k
                key[0] = key[1] = 0;
696
825k
                code = pl_dict_put(pfontdict, key, sizeof(key), plfont);
697
                /* leave data stored in the file.  NB this should be a fatal error also. */
698
825k
                if ((code >= 0) && pl_store_resident_font_data_in_file
699
825k
                    (path, mem, plfont) < 0) {
700
0
                    dmprintf1(mem, "%s could not store data",
701
0
                              path);
702
0
                    continue;
703
0
                }
704
825k
            }
705
1.08M
            if (code < 0) {
706
                /* on error, pl_dict_put consumes plfont */
707
0
                continue;
708
0
            }
709
1.08M
            found = true;
710
1.08M
            found_any = true;
711
1.08M
        }
712
862k
        sfclose(in);
713
714
        /* nothing found */
715
862k
        if (!found) {
716
#ifdef DEBUG
717
            if (gs_debug_c('=')) {
718
                dmprintf2(mem,
719
                          "TrueType font %s in file %s not found in table\n",
720
                          buffer, path);
721
                in = sfopen(path, "r", mem);
722
                code =
723
                    get_name_from_tt_file(in, mem, buffer, WINDOWSNAME);
724
                sfclose(in);
725
                dmprintf1(mem, "Windows name %s\n", buffer);
726
                if (code < 0)
727
                    return code;
728
            }
729
#endif
730
0
        }
731
862k
    }                       /* next file */
732
#ifdef DEBUG
733
    if (gs_debug_c('='))
734
        check_resident_fonts(pfontdict, mem);
735
#endif
736
10.6k
    return found_any;
737
10.6k
}
738
739
/* These are not implemented */
740
741
/* load simm fonts given a path */
742
int
743
pl_load_simm_fonts(const char *pathname, gs_memory_t * mem,
744
                   pl_dict_t * pfontdict, gs_font_dir * pdir, int storage)
745
0
{
746
    /* not implemented */
747
0
    return 0;
748
0
}
749
750
/* load simm fonts given a path */
751
int
752
pl_load_cartridge_fonts(const char *pathname, gs_memory_t * mem,
753
                        pl_dict_t * pfontdict, gs_font_dir * pdir,
754
                        int storage)
755
0
{
756
    /* not implemented */
757
0
    return 0;
758
0
}