Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/pdf/pdf_fmap.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2020-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
/* Font re-mapping */
16
17
#include "strmio.h"
18
#include "stream.h"
19
#include "scanchar.h"
20
#include "gsstrl.h"
21
22
#include "pdf_int.h"
23
#include "pdf_types.h"
24
#include "pdf_font_types.h"
25
#include "pdf_array.h"
26
#include "pdf_dict.h"
27
#include "pdf_stack.h"
28
#include "pdf_file.h"
29
#include "pdf_misc.h"
30
#include "pdf_font.h"
31
#include "pdf_fontmt.h"
32
#include "pdf_fmap.h"
33
34
typedef struct
35
{
36
    const char *keyname;
37
    const char *mappedname;
38
} pdfi_custom_fmap_entry;
39
40
pdfi_custom_fmap_entry pdfi_custom_fmap_entries[] =
41
{
42
  {"Helv", "Helvetica"},
43
  {NULL, NULL}
44
};
45
46
static inline bool pdfi_fmap_file_exists(pdf_context *ctx, pdf_string *fname)
47
0
{
48
0
    return pdfi_font_file_exists(ctx, (const char *)fname->data, fname->length);
49
0
}
50
51
static int
52
pdfi_fontmap_open_file(pdf_context *ctx, const char *mapfilename, byte **buf, int *buflen)
53
44.5k
{
54
44.5k
    int code = 0;
55
44.5k
    stream *s;
56
44.5k
    char fname[gp_file_name_sizeof];
57
44.5k
    const char *path_pfx = "Init/";
58
44.5k
    const char *poststring = "\nendstream";
59
44.5k
    const int poststringlen = strlen(poststring);
60
44.5k
    fname[0] = '\0';
61
62
44.5k
    if (strlen(path_pfx) + strlen(mapfilename) + 1 > gp_file_name_sizeof)
63
0
        return_error(gs_error_invalidfileaccess);
64
65
44.5k
    code = pdfi_open_resource_file(ctx, mapfilename, strlen(mapfilename), &s);
66
44.5k
    if (code < 0) {
67
0
        strncat(fname, path_pfx, strlen(path_pfx));
68
0
        strncat(fname, (char *)mapfilename, strlen(mapfilename));
69
0
        code = pdfi_open_resource_file(ctx, fname, strlen(fname), &s);
70
0
    }
71
72
44.5k
    if (code >= 0) {
73
44.5k
        int i;
74
44.5k
        int64_t file_size;
75
76
44.5k
        sfseek(s, 0, SEEK_END);
77
44.5k
        file_size = sftell(s);
78
44.5k
        sfseek(s, 0, SEEK_SET);
79
44.5k
        if (file_size < 0 || file_size > max_int - poststringlen) {
80
0
            code = gs_note_error(gs_error_ioerror);
81
44.5k
        } else {
82
44.5k
            byte *dbuf;
83
44.5k
            *buflen = (int)file_size;
84
85
44.5k
            (*buf) = gs_alloc_bytes(ctx->memory, *buflen + poststringlen, "pdf_cmap_open_file(buf)");
86
44.5k
            if (*buf != NULL) {
87
44.5k
                sfread((*buf), 1, *buflen, s);
88
44.5k
                memcpy((*buf) + *buflen, poststring, poststringlen);
89
44.5k
                *buflen += poststringlen;
90
                /* This is naff, but works for now
91
                   When parsing Fontmap in PS, ";" is defined as "def"
92
                   Also some people use "cvn" to convert a string to a name.
93
                   We don't need either, because the dictionary is built from the stack.
94
                 */
95
142M
                for (i = 0, dbuf = *buf; i < *buflen - 1; i++, dbuf++) {
96
142M
                    if (*dbuf == ';') {
97
3.82M
                        *dbuf = ' ';
98
3.82M
                    }
99
142M
                    if (memcmp(dbuf, "cvn ", 4) == 0) {
100
0
                        dbuf[0] = dbuf[1] = dbuf[2] = 0x20;
101
0
                    }
102
142M
                }
103
44.5k
            }
104
0
            else {
105
0
                code = gs_note_error(gs_error_VMerror);
106
0
            }
107
44.5k
        }
108
44.5k
        sfclose(s);
109
44.5k
    }
110
44.5k
    return code;
111
44.5k
}
112
113
#ifdef UFST_BRIDGE
114
/* we know fco_path is null terminated */
115
static pdf_string *pdfi_make_fco_path_string(pdf_context *ctx, char *fco_path)
116
{
117
    pdf_string *fp;
118
    int code = pdfi_object_alloc(ctx, PDF_STRING, strlen(fco_path), (pdf_obj **)&fp);
119
    if (code < 0)
120
        return NULL;
121
    pdfi_countup(fp);
122
    memcpy(fp->data, fco_path, strlen(fco_path));
123
124
    return fp;
125
}
126
#endif /* UFST_BRIDGE */
127
128
static inline int pdfi_populate_ufst_fontmap(pdf_context *ctx)
129
44.5k
{
130
#ifdef UFST_BRIDGE
131
    int status = 0;
132
    int bSize, i;
133
    char pthnm[gp_file_name_sizeof];
134
    char *ufst_root_dir;
135
    char *fco;
136
    char *fco_start, *fco_lim;
137
    size_t ufst_root_dir_len;
138
139
    if (pdfi_fapi_ufst_available(ctx->memory) == false) {
140
        return (0);
141
    }
142
143
    ufst_root_dir = (char *)pdfi_fapi_ufst_get_font_dir(ctx->memory);
144
    ufst_root_dir_len = strlen(ufst_root_dir);
145
    if (ufst_root_dir_len >= gp_file_name_sizeof) {
146
        return gs_error_Fatal;
147
    }
148
    fco_start = fco = (char *)pdfi_fapi_ufst_get_fco_list(ctx->memory);
149
    fco_lim = fco_start + strlen(fco_start) + 1;
150
    while (fco < fco_lim && status == 0) {
151
        pdf_string *fco_str;
152
        status = 0;
153
        /* build and open (get handle) for the k'th fco file name */
154
        gs_strlcpy((char *)pthnm, ufst_root_dir, sizeof pthnm);
155
156
        for (i = 2; fco[i] != gp_file_name_list_separator && (&fco[i]) < fco_lim - 1; i++)
157
            ;
158
159
        if (i + ufst_root_dir_len >= gp_file_name_sizeof) {
160
            return gs_error_Fatal;
161
        }
162
        strncat(pthnm, fco, i);
163
        fco += (i + 1);
164
        fco_str = pdfi_make_fco_path_string(ctx, pthnm);
165
        if (fco_str == NULL) {
166
            return gs_error_Fatal;
167
        }
168
169
        /* enumerate the files in this fco */
170
        for (i = 0; status == 0; i++) {
171
            char *pname = NULL;
172
            pdf_font_microtype *pdffont = NULL;
173
            int font_number = 0;
174
175
            status = pdfi_alloc_mt_font(ctx, fco_str, i, &pdffont);
176
            if (status < 0)
177
                break;
178
            status = pdfi_fapi_passfont((pdf_font *)pdffont, i, (char *)"UFST", pthnm, NULL, 0);
179
            if (status < 0){
180
#ifdef DEBUG
181
                outprintf(ctx->memory, "CGIFfco_Access error %d\n", status);
182
#endif
183
                pdfi_countdown(pdffont);
184
                break;
185
            }
186
187
            /* For Microtype fonts, once we get here, these
188
             * pl_fapi_get*() calls cannot fail, so we can
189
             * safely ignore the return value
190
             */
191
            (void)pdfi_fapi_get_mtype_font_name((gs_font *)pdffont->pfont, NULL, &bSize);
192
193
            pname = (char *)gs_alloc_bytes(ctx->memory, bSize, "pdfi: mt font name buffer");
194
            if (!pname) {
195
                pdfi_countdown(pdffont);
196
                (void)pdfi_set_warning_stop(ctx, gs_note_error(gs_error_VMerror), NULL, W_PDF_VMERROR_BUILTIN_FONT, "pdfi_populate_ufst_fontmap", "");
197
                outprintf(ctx->memory, "VM Error for built-in font %d", i);
198
                continue;
199
            }
200
201
            (void)pdfi_fapi_get_mtype_font_name((gs_font *)pdffont->pfont, (byte *) pname, &bSize);
202
            (void)pdfi_fapi_get_mtype_font_number((gs_font *)pdffont->pfont, &font_number);
203
204
            if (bSize < gs_font_name_max) {
205
                memcpy(pdffont->pfont->key_name.chars, pname, bSize);
206
                pdffont->pfont->key_name.chars[bSize] = 0;
207
                pdffont->pfont->key_name.size = bSize;
208
                memcpy(pdffont->pfont->font_name.chars, pname, bSize);
209
                pdffont->pfont->font_name.chars[bSize] = 0;
210
                pdffont->pfont->font_name.size = bSize;
211
            }
212
            status = gs_definefont(ctx->font_dir, (gs_font *) pdffont->pfont);
213
            if (status < 0) {
214
                pdfi_countdown(pdffont);
215
                status = 0;
216
                continue;
217
            }
218
            gs_notify_release(&pdffont->pfont->notify_list);
219
            status = pdfi_fapi_passfont((pdf_font *)pdffont, i, (char *)"UFST", pthnm, NULL, 0);
220
            if (status < 0) {
221
                pdfi_countdown(pdffont);
222
                status = 0;
223
                continue;
224
            }
225
            status = pdfi_dict_put(ctx, ctx->pdffontmap, pname, (pdf_obj *)pdffont);
226
            pdfi_countdown(pdffont);
227
            if (status < 0) {
228
                status = 0;
229
                continue;
230
            }
231
        }
232
        pdfi_countdown(fco_str);
233
    }
234
#endif /* UFST_BRIDGE */
235
44.5k
    return 0;
236
44.5k
}
237
238
static int
239
pdf_make_fontmap(pdf_context *ctx, const char *default_fmapname, int cidfmap)
240
44.5k
{
241
44.5k
    byte *fmapbuf = NULL;
242
44.5k
    int code, fmapbuflen;
243
44.5k
    pdf_c_stream *fmapstr = NULL;
244
44.5k
    pdf_stream fakedict = {0};
245
44.5k
    pdfi_custom_fmap_entry *pcfe = pdfi_custom_fmap_entries;
246
44.5k
    int i, j = 0;
247
44.5k
    char fmapname[gp_file_name_sizeof];
248
44.5k
    pdf_c_stream fakemainstream = {0};
249
44.5k
    int stacksize = pdfi_count_stack(ctx);
250
251
44.5k
    strncpy(fmapname, default_fmapname, strlen(default_fmapname) + 1);
252
253
44.5k
    code = pdfi_mark_stack(ctx, PDF_DICT_MARK);
254
44.5k
    if (code < 0)
255
0
        goto done;
256
257
44.5k
    do {
258
44.5k
        if (j < ctx->num_fontmapfiles && cidfmap == false) {
259
0
            memcpy(fmapname, ctx->fontmapfiles[j].data, ctx->fontmapfiles[j].size);
260
0
            fmapname[ctx->fontmapfiles[j].size] = '\0';
261
0
        }
262
263
44.5k
        code = pdfi_fontmap_open_file(ctx, (const char *)fmapname, &fmapbuf, &fmapbuflen);
264
44.5k
        if (code < 0) {
265
0
            if (ctx->args.QUIET != true) {
266
0
                (void)outwrite(ctx->memory, "Warning: ", 9);
267
0
                if (cidfmap)
268
0
                    (void)outwrite(ctx->memory, "cidfmap file ", 13);
269
0
                else
270
0
                    (void)outwrite(ctx->memory, "Fontmap file \"", 14);
271
0
                (void)outwrite(ctx->memory, fmapname, strlen(fmapname));
272
0
                (void)outwrite(ctx->memory, "\" not found.\n", 13);
273
0
                code = 0;
274
0
            }
275
0
        }
276
44.5k
        else {
277
44.5k
            code = pdfi_open_memory_stream_from_memory(ctx, fmapbuflen, fmapbuf, &fmapstr, true);
278
44.5k
            if (code >= 0) {
279
280
44.5k
                if (ctx->main_stream == NULL) {
281
0
                    ctx->main_stream = &fakemainstream;
282
0
                }
283
284
44.5k
                if (fmapbuflen > 0)
285
44.5k
                    code = pdfi_interpret_content_stream(ctx, fmapstr, &fakedict, NULL);
286
0
                else
287
0
                    code = 0;
288
289
44.5k
                if (ctx->main_stream == &fakemainstream) {
290
0
                    ctx->main_stream = NULL;
291
0
                }
292
44.5k
                gs_free_object(ctx->memory, fmapbuf, "pdf_make_fontmap(fmapbuf)");
293
44.5k
            }
294
44.5k
        }
295
44.5k
        j++;
296
44.5k
    } while(j < ctx->num_fontmapfiles && cidfmap == false && code >= 0);
297
298
44.5k
    if (code >= 0) {
299
44.5k
        if (pdfi_count_stack(ctx) > stacksize) {
300
44.5k
            code = pdfi_dict_from_stack(ctx, 0, 0, true);
301
44.5k
            if (code < 0)
302
0
                goto done;
303
304
44.5k
            if (cidfmap == true) {
305
5.93k
                ctx->pdfcidfmap = (pdf_dict *)ctx->stack_top[-1];
306
5.93k
                pdfi_countup(ctx->pdfcidfmap);
307
5.93k
            }
308
38.6k
            else {
309
38.6k
                ctx->pdffontmap = (pdf_dict *)ctx->stack_top[-1];
310
38.6k
                pdfi_countup(ctx->pdffontmap);
311
38.6k
            }
312
44.5k
            pdfi_pop(ctx, 1);
313
44.5k
            code = 0;
314
315
            /* Add our internal aliases to the fontmap. */
316
44.5k
            if (cidfmap == false) {
317
77.2k
                for (i = 0; pcfe[i].keyname != NULL; i++) {
318
38.6k
                    pdf_obj *value;
319
38.6k
                    bool k;
320
321
                    /* We don't want to *replace* entries */
322
38.6k
                    if (pdfi_dict_known(ctx, ctx->pdffontmap, pcfe[i].keyname, &k) >= 0
323
38.6k
                        && k != true) {
324
38.6k
                        code = pdfi_name_alloc(ctx, (byte *)pcfe[i].mappedname, strlen(pcfe[i].mappedname), &value);
325
38.6k
                        if (code < 0)
326
0
                            continue;
327
38.6k
                        pdfi_countup(value);
328
                        /* If dict_put throws an error, we just carry on - hence the (void) */
329
38.6k
                        (void)pdfi_dict_put(ctx,  ctx->pdffontmap, pcfe[i].keyname, value);
330
38.6k
                        pdfi_countdown(value);
331
38.6k
                    }
332
38.6k
                }
333
38.6k
            }
334
44.5k
        }
335
0
        else {
336
0
            code = gs_note_error(gs_error_syntaxerror);
337
0
        }
338
44.5k
    }
339
44.5k
done:
340
    /* We always want to leave here with a valid map dictionary
341
       even if it's empty
342
     */
343
44.5k
    if (cidfmap == true) {
344
5.93k
        if (ctx->pdfcidfmap == NULL) {
345
0
            code = pdfi_dict_alloc(ctx, 0, &ctx->pdfcidfmap);
346
0
            if (code >= 0)
347
0
                pdfi_countup(ctx->pdfcidfmap);
348
0
        }
349
5.93k
    }
350
38.6k
    else {
351
38.6k
        if (ctx->pdffontmap == NULL) {
352
0
            code = pdfi_dict_alloc(ctx, 0, &ctx->pdffontmap);
353
0
            if (code >= 0)
354
0
                pdfi_countup(ctx->pdffontmap);
355
0
        }
356
38.6k
    }
357
44.5k
    if (code >= 0) {
358
44.5k
        code = pdfi_populate_ufst_fontmap(ctx);
359
44.5k
    }
360
#ifdef DUMP_FONTMAP
361
    if (ctx->pdffontmap != NULL) {
362
        uint64_t ind;
363
        int find = -1;
364
        pdf_name *key = NULL;
365
        pdf_obj *v = NULL;
366
        pdf_string *val = NULL;
367
        (void)pdfi_dict_key_first(ctx, ctx->pdffontmap, (pdf_obj **) &key, &ind);
368
        (void)pdfi_dict_get_by_key(ctx, ctx->pdffontmap, key, (pdf_obj **)&v);
369
        for (j = 0; j < key->length; j++)
370
            dprintf1("%c", key->data[j]);
371
        if (pdfi_type_of(v) == PDF_DICT) {
372
            pdf_num *n;
373
            pdf_string *val2;
374
            code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
375
            if (code >= 0 && pdfi_type_of(n) == PDF_INT)
376
                find = n->value.i;
377
            else
378
                code = 0;
379
            (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
380
            val = val2;
381
        }
382
        else {
383
            val = (pdf_string *)v;
384
        }
385
        dprintf(" ");
386
        for (j = 0; j < val->length; j++)
387
            dprintf1("%c", val->data[j]);
388
        if (find != -1) {
389
            dprintf1("  Index = %d", find);
390
            find = -1;
391
        }
392
393
        dprintf("\n");
394
        pdfi_countdown(key);
395
        pdfi_countdown(val);
396
397
        while (pdfi_dict_key_next(ctx, ctx->pdffontmap, (pdf_obj **) &key, &ind) >= 0 && ind > 0) {
398
            (void)pdfi_dict_get_by_key(ctx, ctx->pdffontmap, key, (pdf_obj **)&v);
399
            for (j = 0; j < key->length; j++)
400
                dprintf1("%c", key->data[j]);
401
            if (pdfi_type_of(v) == PDF_DICT) {
402
                pdf_num *n;
403
                pdf_string *val2;
404
                code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
405
                if (code >= 0 && pdfi_type_of(n) == PDF_INT)
406
                    find = n->value.i;
407
                else
408
                    code = 0;
409
                (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
410
                val = val2;
411
            }
412
            else {
413
                val = (pdf_string *)v;
414
            }
415
            dprintf("       ");
416
            for (j = 0; j < val->length; j++)
417
                dprintf1("%c", val->data[j]);
418
            if (find != -1) {
419
                dprintf1("  Index = %d", find);
420
                find = -1;
421
            }
422
            pdfi_countdown(key);
423
            pdfi_countdown(val);
424
            dprintf("\n");
425
        }
426
    }
427
#endif
428
44.5k
    pdfi_clearstack(ctx);
429
44.5k
    return code;
430
44.5k
}
431
432
enum {
433
  no_type_font = -1,
434
  type0_font = 0,
435
  type1_font = 1,
436
  cff_font = 2,
437
  type3_font = 3,
438
  tt_font = 42
439
};
440
441
/* For font file scanning we want to treat OTTO as TTF (rather than, for "normal"
442
   font loading, treat OTTO as CFF, hence we need a different type picker.
443
 */
444
static int pdfi_font_scan_type_picker(byte *buf, int64_t buflen)
445
0
{
446
0
#define MAKEMAGIC(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
447
448
0
    if (buflen >= 4) {
449
0
        if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC(0, 1, 0, 0)
450
0
            || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 'r', 'u', 'e')
451
0
            || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 't', 'c', 'f')) {
452
0
            return tt_font;
453
0
        }
454
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('O', 'T', 'T', 'O')) {
455
0
            return tt_font;
456
0
        }
457
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC('%', '!', 'P', 0)) {
458
0
            return type1_font; /* pfa */
459
0
        }
460
0
        else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC(1, 0, 4, 0)) {
461
0
            return cff_font; /* 1C/CFF */
462
0
        }
463
0
        else if (MAKEMAGIC(buf[0], buf[1], 0, 0) == MAKEMAGIC(128, 1, 0, 0)) {
464
0
            return type1_font; /* pfb */
465
0
        }
466
0
    }
467
0
    return no_type_font;
468
0
#undef MAKEMAGIC
469
0
}
470
471
static int pdfi_add__to_native_fontmap(pdf_context *ctx, const char *fontname, const char *filepath, const int index)
472
0
{
473
0
    int code;
474
0
    pdf_string *fpstr;
475
476
0
    if (ctx->pdfnativefontmap == NULL) {
477
        /* 32 is just an arbitrary starting point */
478
0
        code = pdfi_dict_alloc(ctx, 32, &ctx->pdfnativefontmap);
479
0
        if (code < 0)
480
0
            return code;
481
0
        pdfi_countup(ctx->pdfnativefontmap);
482
0
    }
483
    /* index == -1 is a file with a single font in it */
484
0
    if (index == -1) {
485
0
        code = pdfi_object_alloc(ctx, PDF_STRING, strlen(filepath), (pdf_obj **)&fpstr);
486
0
        if (code < 0)
487
0
            return code;
488
0
        pdfi_countup(fpstr);
489
0
        memcpy(fpstr->data, filepath, fpstr->length);
490
0
        code = pdfi_dict_put(ctx, ctx->pdfnativefontmap, fontname, (pdf_obj *)fpstr);
491
0
        pdfi_countdown(fpstr);
492
0
    }
493
0
    else {
494
0
        pdf_dict *recdict;
495
0
        pdf_num *ind;
496
497
0
        code = pdfi_object_alloc(ctx, PDF_DICT, 2, (pdf_obj **)&recdict);
498
0
        if (code < 0)
499
0
            return code;
500
0
        pdfi_countup(recdict);
501
502
0
        code = pdfi_object_alloc(ctx, PDF_STRING, strlen(filepath), (pdf_obj **)&fpstr);
503
0
        if (code < 0) {
504
0
            pdfi_countdown(recdict);
505
0
            return code;
506
0
        }
507
0
        pdfi_countup(fpstr);
508
0
        memcpy(fpstr->data, filepath, fpstr->length);
509
0
        code = pdfi_dict_put(ctx, recdict, "Path", (pdf_obj *)fpstr);
510
0
        pdfi_countdown(fpstr);
511
0
        if (code < 0) {
512
0
            pdfi_countdown(recdict);
513
0
            return code;
514
0
        }
515
516
0
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)&ind);
517
0
        if (code < 0) {
518
0
            pdfi_countdown(recdict);
519
0
            return code;
520
0
        }
521
0
        ind->value.i = index;
522
0
        pdfi_countup(ind);
523
0
        code = pdfi_dict_put(ctx, recdict, "Index", (pdf_obj *)ind);
524
0
        pdfi_countdown(ind);
525
0
        if (code < 0) {
526
0
            pdfi_countdown(recdict);
527
0
            return code;
528
0
        }
529
0
        code = pdfi_dict_put(ctx, ctx->pdfnativefontmap, fontname, (pdf_obj *)recdict);
530
0
        pdfi_countdown(recdict);
531
0
    }
532
533
0
    return code;
534
0
}
535
536
static inline int
537
pdfi_end_ps_token(int c)
538
0
{
539
0
    return (c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA) || (c == '/')  || (c == '\0');
540
0
}
541
542
/* Naive way to find a Type 1 /FontName key */
543
static int pdfi_type1_add_to_native_map(pdf_context *ctx, stream *f, char *fname, char *pname, int pname_size)
544
0
{
545
0
    gs_string buf;
546
0
    uint count = 0;
547
0
    int code = gs_error_undefined;
548
0
    char *namestr = NULL, *enamestr;
549
0
    char *typestr;
550
0
    bool pin_eol = false; /* initialised just to placate coverity */
551
0
    int type = -1;
552
0
    int lines = 0;
553
0
    buf.data = (byte *)pname;
554
0
    buf.size = pname_size;
555
556
    /* It's not an absolute requirement, but it is a de facto standard that
557
       /FontType and /FontName keys start in column 0 of their lines
558
     */
559
0
    while ((code = sreadline(f, NULL, NULL, NULL, &buf, NULL, &count, &pin_eol, NULL)) >= 0) {
560
0
        lines++;
561
0
        if (lines > 100 || (buf.size >= 17 && memcmp(buf.data, "currentfile eexec", 17) == 0))
562
0
            break;
563
0
        else if (buf.size > 9 && memcmp(buf.data, "/FontName", 9) == 0) {
564
0
            namestr = (char *)buf.data + 9;
565
0
            while (pdfi_end_ps_token(*namestr))
566
0
                namestr++;
567
0
            if (*namestr != '\0') {
568
0
                while(*namestr == 0x20 || *namestr == 0x9)
569
0
                    namestr++;
570
0
                if (*namestr == '/')
571
0
                    namestr++;
572
0
                enamestr = namestr;
573
0
                while(!pdfi_end_ps_token((int)*enamestr))
574
0
                    enamestr++;
575
0
                count = enamestr - namestr > pname_size - 1 ? pname_size - 1 : enamestr - namestr;
576
0
                memmove(pname, namestr, count);
577
0
                pname[count] = '\0';
578
0
                buf.data += count + 1;
579
0
                buf.size -= count + 1;
580
0
                if (type == 1)
581
0
                    break;
582
0
            }
583
0
        }
584
0
        else if (buf.size > 9 && memcmp(buf.data, "/FontType", 9) == 0) {
585
0
            typestr = (char *)buf.data + 9;
586
0
            while (pdfi_end_ps_token(*typestr))
587
0
                typestr++;
588
0
            if (*typestr != '\0') {
589
0
                while(*typestr == 0x20 || *typestr == 0x9)
590
0
                    namestr++;
591
0
                if (*typestr == '/')
592
0
                    typestr++;
593
0
                enamestr = typestr;
594
0
                while(!pdfi_end_ps_token((int)*enamestr))
595
0
                    enamestr++;
596
0
                count = enamestr - typestr > pname_size - 1 ? pname_size - 1 : enamestr - typestr;
597
0
                if (count == 1 && *typestr == '1') {
598
0
                    type = 1;
599
0
                    if (namestr != NULL)
600
0
                        break;
601
0
                }
602
0
            }
603
0
        }
604
0
        count = 0;
605
0
    }
606
0
    if (type == 1 && namestr != NULL) {
607
0
        code = pdfi_add__to_native_fontmap(ctx, (const char *)pname, (const char *)fname, -1);
608
0
    }
609
0
    return code < 0 ? code : gs_error_handled;
610
0
}
611
612
static inline int
613
u16(const byte *p)
614
0
{
615
0
    return (p[0] << 8) | p[1];
616
0
}
617
618
static inline int
619
sru16(stream *s)
620
0
{
621
0
    byte p[2];
622
0
    int code = sfread(p, 1, 2, s);
623
624
0
    if (code < 0)
625
0
        return 0;
626
627
0
    return u16(p);
628
0
}
629
630
static inline int
631
u32(const byte *p)
632
0
{
633
0
    return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
634
0
}
635
636
static inline int
637
sru32(stream *s)
638
0
{
639
0
    byte p[4];
640
0
    int code = sfread(p, 1, 4, s);
641
0
    if (code < 0)
642
0
        return 0;
643
644
0
    return u32(p);
645
0
}
646
647
static int pdfi_ttf_add_to_native_map(pdf_context *ctx, stream *f, byte magic[4], char *fname, char *pname, int pname_size)
648
0
{
649
0
    int ntables, i, j, k, code2, code = gs_error_undefined;
650
0
    char table[4];
651
0
    int nte, storageOffset;
652
0
    bool include_index = false;
653
0
    uint32_t nfonts = 1, tableoffs;
654
0
    int findex;
655
0
    gs_offset_t l;
656
657
0
    code2 = sfseek(f, 0, SEEK_END);
658
0
    if (code2 < 0)
659
0
        return code;
660
0
    l = stell(f);
661
    /* 4 to skip the magic number */
662
0
    code2 = sfseek(f, 4, SEEK_SET);
663
0
    if (code2 < 0)
664
0
        return code;
665
666
0
    if (memcmp(magic, "ttcf", 4) == 0) {
667
0
        uint32_t ver;
668
0
        include_index = true;
669
0
        ver = sru32(f);
670
0
        if (ver != 0x00010000 && ver !=0x00020000) {
671
0
            code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_invalidaccess), NULL, E_PDF_BAD_TTC_VERSION, "pdfi_ttf_add_to_native_map", NULL);
672
0
            outprintf(ctx->memory, "Unknown TTC header version %08X.\n", ver);
673
0
            return code;
674
0
        }
675
0
        nfonts = sru32(f);
676
        /* There isn't a specific limit on the number of fonts,
677
           freetype limits to 255, so we'll do the same here
678
         */
679
0
        if (nfonts > 255)
680
0
            return_error(gs_error_invalidfont);
681
0
    }
682
683
0
    for (findex = 0; findex < nfonts; findex++) {
684
0
        if (include_index == true ) {
685
0
            if (findex * 4 > l)
686
0
                break;
687
0
            code2 = sfseek(f, findex * 4, SEEK_CUR);
688
0
            if (code2 < 0)
689
0
                return code2;
690
691
0
            tableoffs = sru32(f);
692
0
            if (tableoffs + 4 > l)
693
0
                break;
694
0
            code2 = sfseek(f, tableoffs + 4, SEEK_SET);
695
0
            if (code2 < 0)
696
0
                return code2;
697
0
        }
698
699
0
        ntables = sru16(f);
700
        /* Similar to above - no spec limit, but we do the same
701
           as freetype
702
         */
703
0
        if (ntables > 255)
704
0
            continue;
705
706
        /* Skip the remainder of the invariant header bytes */
707
0
        (void)sru16(f);
708
0
        (void)sru32(f);
709
710
0
        for (i = 0, code2 = 0; i < ntables && code2 >= 0; i++) {
711
0
            if (stell(f) + 4 > l) {
712
0
                code2 = gs_error_ioerror;
713
0
                continue;
714
0
            }
715
0
            code2 = sfread(table, 1, 4, f);
716
0
            if (code2 < 0)
717
0
                return code2;
718
0
            if (!memcmp(table, "name", 4)) {
719
0
                uint table_pos, table_len;
720
0
                byte *namet;
721
0
                (void)sru32(f); /* skip checksum */
722
723
0
                table_pos = sru32(f);
724
0
                table_len = sru32(f);
725
0
                if (table_pos + table_len > l) {
726
0
                    code2 = gs_error_ioerror;
727
0
                    continue;
728
0
                }
729
730
0
                code2 = sfseek(f, table_pos, SEEK_SET);
731
0
                if (code2 < 0)
732
0
                    continue;
733
734
0
                namet = (byte *)gs_alloc_bytes(ctx->memory, table_len, "pdfi_ttf_add_to_native_map");
735
0
                if (namet == NULL)
736
0
                    return_error(gs_error_VMerror);
737
0
                code2 = sfread(namet, 1, table_len, f);
738
0
                if (code2 < 0) {
739
0
                    gs_free_object(ctx->memory, namet,"pdfi_ttf_add_to_native_map");
740
0
                    continue;
741
0
                }
742
0
                nte = u16(namet + 2);
743
                /* Again, arbitrary limit... */
744
0
                if (nte > 255) {
745
0
                    gs_free_object(ctx->memory, namet,"pdfi_ttf_add_to_native_map");
746
0
                    continue;
747
0
                }
748
0
                storageOffset = u16(namet + 4);
749
750
0
                for (j = 0; j < nte; j++) {
751
0
                    byte *rec = namet + 6 + j * 12;
752
0
                    if (u16(rec + 6) == 6) {
753
0
                        int pid = u16(rec);
754
0
                        int eid = u16(rec + 2);
755
0
                        int nl = u16(rec + 8);
756
0
                        int noffs = u16(rec + 10);
757
758
0
                        if (nl + noffs + storageOffset > table_len || nl >= pname_size) {
759
0
                            break;
760
0
                        }
761
0
                        memcpy(pname, namet + storageOffset + noffs, nl);
762
0
                        pname[nl] = '\0';
763
0
                        if ((pid == 0 || (pid == 2 && eid == 1) || (pid == 3 && eid == 1)) && (nl % 2) == 0) {
764
0
                            for (k = 0; k < nl; k += 2) {
765
0
                                if (pname[k] != '\0')
766
0
                                    break;
767
0
                            }
768
0
                            if (k == nl) {
769
0
                                int k1, k2;
770
0
                                for (k1 = 0, k2 = 1; k2 < nl; k1++, k2 += 2) {
771
0
                                    pname[k1] = pname[k2];
772
0
                                }
773
0
                                nl = nl >> 1;
774
0
                                pname[nl] = '\0';
775
0
                            }
776
0
                        }
777
778
0
                        for (k = 0; k < nl; k++)
779
0
                            if (pname[k] < 32 || pname[k] > 126) /* is it a valid PS name? */
780
0
                                break;
781
0
                        if (k == nl) {
782
0
                            code = 0;
783
0
                            break;
784
0
                       }
785
0
                    }
786
0
                }
787
0
                if (code == gs_error_undefined) {
788
0
                    for (j = 0; j < nte; j++) {
789
0
                        byte *rec = namet + 6 + j * 12;
790
0
                        if (u16(rec + 6) == 4) {
791
0
                            int pid = u16(rec);
792
0
                            int eid = u16(rec + 2);
793
0
                            int nl = u16(rec + 8);
794
0
                            int noffs = u16(rec + 10);
795
796
0
                            if (nl + noffs + storageOffset > table_len || nl >= pname_size) {
797
0
                                break;
798
0
                            }
799
0
                            memcpy(pname, namet + storageOffset + noffs, nl);
800
0
                            pname[nl] = '\0';
801
0
                            if ((pid == 0 || (pid == 2 && eid == 1) || (pid == 3 && eid == 1)) && (nl % 2) == 0) {
802
0
                                for (k = 0; k < nl; k += 2) {
803
0
                                    if (pname[k] != '\0')
804
0
                                        break;
805
0
                                }
806
0
                                if (k == nl) {
807
0
                                    int k1, k2;
808
0
                                    for (k1 = 0, k2 = 1; k2 < nl; k1++, k2 += 2) {
809
0
                                        pname[k1] = pname[k2];
810
0
                                    }
811
0
                                    nl = nl >> 1;
812
0
                                    pname[nl] = '\0';
813
0
                                }
814
0
                            }
815
0
                            for (k = 0; k < nl; k++)
816
0
                                if (pname[k] < 32 || pname[k] > 126) /* is it a valid PS name? */
817
0
                                    break;
818
0
                            if (k == nl)
819
0
                                code = 0;
820
0
                            break;
821
0
                        }
822
0
                    }
823
0
                }
824
0
                gs_free_object(ctx->memory, namet, "pdfi_ttf_add_to_native_map");
825
0
                break;
826
0
            }
827
0
            else {
828
0
                sfseek(f, 12, SEEK_CUR);
829
0
            }
830
0
        }
831
0
        if (code >= 0)
832
0
            code = pdfi_add__to_native_fontmap(ctx, (const char *)pname, (const char *)fname, (include_index == true ? findex : -1));
833
0
    }
834
0
    return code;
835
0
}
836
837
static const char *font_scan_skip_list[] = {
838
  ".afm",
839
  ".bat",
840
  ".c",
841
  ".cmd",
842
  ".com",
843
  ".dir",
844
  ".dll",
845
  ".doc",
846
  ".drv",
847
  ".exe",
848
  ".fon",
849
  ".fot",
850
  ".h",
851
  ".o",
852
  ".obj",
853
  ".pfm",
854
  ".pss",
855
  ".txt",
856
  ".gz",
857
  ".pcf"
858
};
859
860
static bool font_scan_skip_file(const char *fname)
861
0
{
862
0
    size_t l2, l = strlen(fname);
863
0
    bool skip = false;
864
0
    int i;
865
866
0
    for (i = 0; i < (sizeof(font_scan_skip_list)/sizeof(*font_scan_skip_list)); i++) {
867
0
        l2 = strlen(font_scan_skip_list[i]);
868
0
        if (memcmp(font_scan_skip_list[i], fname + l - l2, l2) == 0) {
869
0
            skip = true;
870
0
            break;
871
0
        }
872
0
    }
873
0
    return skip;
874
0
}
875
876
static int pdfi_add_font_to_native_map(pdf_context *ctx, const char *fp, char *working)
877
0
{
878
0
    stream *sf;
879
0
    int code = 0;
880
0
    uint nread;
881
0
    byte magic[4]; /* We only (currently) use up to 4 bytes for type guessing */
882
0
    int type;
883
884
0
    if (font_scan_skip_file(fp))
885
0
        return 0;
886
887
0
    sf = sfopen(fp, "r", ctx->memory);
888
0
    if (sf == NULL)
889
0
        return 0;
890
0
    code = sgets(sf, magic, 4, &nread);
891
0
    if (code < 0 || nread < 4) {
892
0
        code = 0;
893
0
        sfclose(sf);
894
0
        return 0;
895
0
    }
896
897
0
    code = sfseek(sf, 0, SEEK_SET);
898
0
    if (code < 0) {
899
0
        code = 0;
900
0
        sfclose(sf);
901
0
        return 0;
902
0
    }
903
    /* Slightly naff: in this one case, we want to treat OTTO fonts
904
       as Truetype, so we lookup the TTF 'name' table - it's more efficient
905
       than decoding the CFF, and probably will give more expected results
906
     */
907
0
    if (memcmp(magic, "OTTO", 4) == 0 || memcmp(magic, "ttcf", 4) == 0) {
908
0
        type = tt_font;
909
0
    }
910
0
    else {
911
0
        type = pdfi_font_scan_type_picker((byte *)magic, 4);
912
0
    }
913
0
    switch(type) {
914
0
        case tt_font:
915
0
          code = pdfi_ttf_add_to_native_map(ctx, sf, magic, (char *)fp, working, gp_file_name_sizeof);
916
0
          break;
917
0
        case cff_font:
918
0
              code = gs_error_undefined;
919
0
          break;
920
0
        case type1_font:
921
0
          code = pdfi_type1_add_to_native_map(ctx, sf, (char *)fp, working, gp_file_name_sizeof);
922
0
          break;
923
0
        default:
924
0
          break;
925
0
    }
926
0
    sfclose(sf);
927
    /* We ignore most errors, on the basis it probably means it wasn't a valid font file */
928
0
    if (code != gs_error_VMerror)
929
0
        code = 0;
930
931
0
    return code;
932
0
}
933
934
/* still writes into pdfnativefontmap dictionary */
935
static int pdfi_generate_platform_fontmap(pdf_context *ctx)
936
4.06M
{
937
4.06M
    void *enum_state = NULL;
938
4.06M
    int code = 0;
939
4.06M
    char *fontname, *path;
940
4.06M
    char *working = NULL;
941
942
4.06M
    working = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_platform_fontmap");
943
4.06M
    if (working == NULL) {
944
0
        code = gs_note_error(gs_error_VMerror);
945
0
        goto done;
946
0
    }
947
948
4.06M
    enum_state = gp_enumerate_fonts_init(ctx->memory);
949
4.06M
    if (enum_state == NULL) {
950
4.06M
        code = gs_note_error(gs_error_VMerror);
951
4.06M
        goto done;
952
4.06M
    }
953
954
0
    while((code = gp_enumerate_fonts_next(enum_state, &fontname, &path )) > 0) {
955
0
        if (fontname == NULL || path == NULL) {
956
0
            continue;
957
0
        }
958
0
        code = pdfi_add_font_to_native_map(ctx, path, working);
959
960
        /* We ignore most errors, on the basis it probably means it wasn't a valid font file */
961
0
        if (code == gs_error_VMerror)
962
0
            break;
963
0
        code = 0;
964
0
    }
965
4.06M
done:
966
4.06M
    gp_enumerate_fonts_free(enum_state);
967
4.06M
    gs_free_object(ctx->memory, working, "pdfi_generate_platform_fontmap");
968
4.06M
    return code;
969
0
}
970
971
static int pdfi_generate_native_fontmap(pdf_context *ctx)
972
4.06M
{
973
4.06M
    file_enum *fe;
974
4.06M
    int i;
975
4.06M
    char *patrn= NULL;
976
4.06M
    char *result = NULL;
977
4.06M
    char *working = NULL;
978
4.06M
    int code = 0, l;
979
980
4.06M
    if (ctx->pdfnativefontmap != NULL) /* Only run this once */
981
0
        return 0;
982
4.06M
    if (ctx->args.nonativefontmap == true) {
983
        /* Basically create an empty dictionary */
984
0
        code = pdfi_dict_alloc(ctx, 1, &ctx->pdfnativefontmap);
985
0
        if (code < 0)
986
0
            return code;
987
0
        pdfi_countup(ctx->pdfnativefontmap);
988
0
        return 0;
989
0
    }
990
991
4.06M
    (void)pdfi_generate_platform_fontmap(ctx);
992
993
4.06M
    patrn = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
994
4.06M
    result = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
995
4.06M
    working = (char *)gs_alloc_bytes(ctx->memory, gp_file_name_sizeof, "pdfi_generate_native_fontmap");
996
4.06M
    if (patrn == NULL || result == NULL || working == NULL) {
997
0
        gs_free_object(ctx->memory, patrn, "pdfi_generate_native_fontmap");
998
0
        gs_free_object(ctx->memory, result, "pdfi_generate_native_fontmap");
999
0
        gs_free_object(ctx->memory, working, "pdfi_generate_native_fontmap");
1000
0
        return_error(gs_error_VMerror);
1001
0
    }
1002
1003
4.06M
    for (i = 0; i < ctx->search_paths.num_font_paths; i++) {
1004
1005
0
        memcpy(patrn, ctx->search_paths.font_paths[i].data, ctx->search_paths.font_paths[i].size);
1006
0
        memcpy(patrn + ctx->search_paths.font_paths[i].size, "/*", 2);
1007
0
        patrn[ctx->search_paths.font_paths[i].size + 2] = '\0';
1008
1009
0
        fe = gp_enumerate_files_init(ctx->memory, (const char *)patrn, strlen(patrn));
1010
0
        while ((l = gp_enumerate_files_next(ctx->memory, fe, result, gp_file_name_sizeof - 1)) != ~(uint) 0) {
1011
0
            result[l] = '\0';
1012
1013
0
            code = pdfi_add_font_to_native_map(ctx, result, working);
1014
1015
            /* We ignore most errors, on the basis it probably means it wasn't a valid font file */
1016
0
            if (code == gs_error_VMerror)
1017
0
                break;
1018
0
            code = 0;
1019
0
        }
1020
        /* We only need to explicitly destroy the enumerator if we exit before enumeration is complete */
1021
0
        if (code < 0)
1022
0
            gp_enumerate_files_close(ctx->memory, fe);
1023
0
    }
1024
1025
#ifdef DUMP_NATIVE_FONTMAP
1026
    if (ctx->pdfnativefontmap != NULL) {
1027
        uint64_t ind;
1028
        int find = -1;
1029
        pdf_name *key = NULL;
1030
        pdf_obj *v = NULL;
1031
        pdf_string *val = NULL;
1032
        (void)pdfi_dict_key_first(ctx, ctx->pdfnativefontmap, (pdf_obj **) &key, &ind);
1033
        (void)pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, key, (pdf_obj **)&v);
1034
        for (j = 0; j < key->length; j++)
1035
            dprintf1("%c", key->data[j]);
1036
        if (pdfi_type_of(v) == PDF_DICT) {
1037
            pdf_num *n;
1038
            pdf_string *val2;
1039
            code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
1040
            if (code >= 0 && pdfi_type_of(n) == PDF_INT)
1041
                find = n->value.i;
1042
            else
1043
                code = 0;
1044
            (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
1045
            val = val2;
1046
        }
1047
        else {
1048
            val = (pdf_string *)v;
1049
        }
1050
        dprintf(" ");
1051
        for (j = 0; j < val->length; j++)
1052
            dprintf1("%c", val->data[j]);
1053
        if (find != -1) {
1054
            dprintf1("  Index = %d", find);
1055
            find = -1;
1056
        }
1057
1058
        dprintf("\n");
1059
        pdfi_countdown(key);
1060
        pdfi_countdown(val);
1061
1062
        while (pdfi_dict_key_next(ctx, ctx->pdfnativefontmap, (pdf_obj **) &key, &ind) >= 0 && ind > 0) {
1063
            (void)pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, key, (pdf_obj **)&v);
1064
            for (j = 0; j < key->length; j++)
1065
                dprintf1("%c", key->data[j]);
1066
            if (pdfi_type_of(v) == PDF_DICT) {
1067
                pdf_num *n;
1068
                pdf_string *val2;
1069
                code = pdfi_dict_get(ctx, (pdf_dict *)v, "Index", (pdf_obj **)&n);
1070
                if (code >= 0 && pdfi_type_of(n) == PDF_INT)
1071
                    find = n->value.i;
1072
                else
1073
                    code = 0;
1074
                (void)pdfi_dict_get(ctx, (pdf_dict *)v, "Path", (pdf_obj **)&val2);
1075
                val = val2;
1076
            }
1077
            else {
1078
                val = (pdf_string *)v;
1079
            }
1080
            dprintf("       ");
1081
            for (j = 0; j < val->length; j++)
1082
                dprintf1("%c", val->data[j]);
1083
            if (find != -1) {
1084
                dprintf1("  Index = %d", find);
1085
                find = -1;
1086
            }
1087
            pdfi_countdown(key);
1088
            pdfi_countdown(val);
1089
            dprintf("\n");
1090
        }
1091
    }
1092
#endif
1093
1094
4.06M
    gs_free_object(ctx->memory, patrn, "pdfi_generate_native_fontmap");
1095
4.06M
    gs_free_object(ctx->memory, result, "pdfi_generate_native_fontmap");
1096
4.06M
    gs_free_object(ctx->memory, working, "pdfi_generate_native_fontmap");
1097
4.06M
    return 0;
1098
4.06M
}
1099
1100
int
1101
pdfi_fontmap_lookup_font(pdf_context *ctx, pdf_dict *font_dict, pdf_name *fname, pdf_obj **mapname, int *findex)
1102
4.06M
{
1103
4.06M
    int code;
1104
4.06M
    pdf_obj *mname;
1105
1106
4.06M
    *findex = 0;
1107
1108
4.06M
    if (ctx->pdffontmap == NULL) {
1109
38.6k
        const char *fmap_default = "Fontmap.GS";
1110
38.6k
        char *fmapname = (char *)fmap_default;
1111
38.6k
        code = pdf_make_fontmap(ctx, fmapname, false);
1112
38.6k
        if (code < 0) {
1113
0
            return code;
1114
0
        }
1115
38.6k
    }
1116
4.06M
    if (ctx->pdfnativefontmap == NULL) {
1117
4.06M
        code = pdfi_generate_native_fontmap(ctx);
1118
4.06M
        if (code < 0)
1119
0
            return code;
1120
4.06M
    }
1121
4.06M
    code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, fname, &mname);
1122
4.06M
    if (code >= 0) {
1123
        /* Fontmap can map in multiple "jump" i.e.
1124
           name -> substitute name
1125
           subsitute name -> file name
1126
           So we want to loop until we no more hits.
1127
         */
1128
851k
        while(1) {
1129
851k
            pdf_obj *mname2;
1130
851k
            code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, (pdf_name *)mname, &mname2);
1131
851k
            if (code < 0) {
1132
851k
                code = 0;
1133
851k
                break;
1134
851k
            }
1135
319
            pdfi_countdown(mname);
1136
319
            mname = mname2;
1137
319
        }
1138
851k
    }
1139
1140
4.06M
    if (code < 0 && ctx->pdfnativefontmap != NULL) {
1141
0
        pdf_obj *record;
1142
0
        code = pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, fname, &record);
1143
0
        if (code >= 0) {
1144
0
            if (pdfi_type_of(record) == PDF_STRING) {
1145
0
                mname = record;
1146
0
            }
1147
0
            else if (pdfi_type_of(record) == PDF_DICT) {
1148
0
                int64_t i64;
1149
0
                code = pdfi_dict_get(ctx, (pdf_dict *)record, "Path", &mname);
1150
0
                if (code >= 0)
1151
0
                    code = pdfi_dict_get_int(ctx, (pdf_dict *)record, "Index", &i64);
1152
0
                if (code < 0) {
1153
0
                    pdfi_countdown(record);
1154
0
                    return code;
1155
0
                }
1156
0
                *findex = (int)i64; /* Rangecheck? */
1157
0
            }
1158
0
            else {
1159
0
                pdfi_countdown(record);
1160
0
                code = gs_error_undefined;
1161
0
            }
1162
0
        }
1163
0
    }
1164
4.06M
    else {
1165
4.06M
        code = gs_error_undefined;
1166
4.06M
    }
1167
1168
4.06M
    if (mname != NULL && pdfi_type_of(mname) == PDF_STRING && pdfi_fmap_file_exists(ctx, (pdf_string *)mname)) {
1169
0
        *mapname = mname;
1170
0
        (void)pdfi_dict_put(ctx, font_dict, ".Path", mname);
1171
0
        code = 0;
1172
0
    }
1173
4.06M
    else if (mname != NULL && (pdfi_type_of(mname) == PDF_NAME || pdfi_type_of(mname) == PDF_FONT)) { /* If we map to a name, we assume (for now) we have the font as a "built-in" */
1174
851k
        *mapname = mname;
1175
851k
        code = 0;
1176
851k
    }
1177
3.21M
    else {
1178
3.21M
        pdfi_countdown(mname);
1179
3.21M
        code = gs_note_error(gs_error_undefined);
1180
3.21M
    }
1181
4.06M
    return code;
1182
4.06M
}
1183
1184
int
1185
pdfi_fontmap_lookup_cidfont(pdf_context *ctx, pdf_dict *font_dict, pdf_name *name, pdf_obj **mapname, int *findex)
1186
55.7k
{
1187
55.7k
    int code = 0;
1188
55.7k
    pdf_obj *cidname = NULL;
1189
55.7k
    pdf_obj *mname;
1190
1191
55.7k
    *findex = 0;
1192
1193
55.7k
    if (ctx->pdfcidfmap == NULL) {
1194
5.93k
        const char *cidfmap_default = "cidfmap";
1195
5.93k
        char *cidfmapname = (char *)cidfmap_default;
1196
5.93k
        code = pdf_make_fontmap(ctx, cidfmapname, true);
1197
5.93k
        if (code < 0) {
1198
0
            return code;
1199
0
        }
1200
5.93k
    }
1201
55.7k
    if (name == NULL || pdfi_type_of(name) != PDF_NAME) {
1202
29.3k
        code = pdfi_dict_get(ctx, font_dict, "BaseFont", &cidname);
1203
29.3k
        if (code < 0 || pdfi_type_of(cidname) != PDF_NAME) {
1204
494
            pdfi_countdown(cidname);
1205
494
            return_error(gs_error_undefined);
1206
494
        }
1207
1208
29.3k
    }
1209
26.3k
    else {
1210
26.3k
        cidname = (pdf_obj *)name;
1211
26.3k
        pdfi_countup(cidname);
1212
26.3k
    }
1213
1214
55.2k
    code = pdfi_dict_get_by_key(ctx, ctx->pdfcidfmap, (pdf_name *)cidname, &mname);
1215
55.2k
    pdfi_countdown(cidname);
1216
55.2k
    if (code < 0)
1217
55.2k
        return code;
1218
    /* As above cidfmap can map in multiple "jump" i.e.
1219
       name -> substitute name
1220
       subsitute name -> "record"
1221
       So we want to loop until we no more hits.
1222
     */
1223
0
    while(1) {
1224
0
        pdf_obj *mname2;
1225
0
        code = pdfi_dict_get_by_key(ctx, ctx->pdfcidfmap, (pdf_name *)mname, &mname2);
1226
0
        if (code < 0) break;
1227
0
        pdfi_countdown(mname);
1228
0
        mname = mname2;
1229
0
    }
1230
0
    if (pdfi_type_of(mname) == PDF_DICT) {
1231
0
        pdf_dict *rec = (pdf_dict *)mname;
1232
0
        pdf_name *filetype;
1233
0
        pdf_name *path = NULL;
1234
0
        int64_t i64;
1235
1236
0
        code = pdfi_dict_get(ctx, rec, "FileType", (pdf_obj **)&filetype);
1237
        /* We only handle TTF files, just now */
1238
0
        if (code < 0 || pdfi_type_of(filetype) != PDF_NAME || filetype->length != 8 || memcmp(filetype->data, "TrueType", 8) != 0) {
1239
0
            pdfi_countdown(filetype);
1240
0
            pdfi_countdown(rec);
1241
0
            return_error(gs_error_undefined);
1242
0
        }
1243
0
        pdfi_countdown(filetype);
1244
1245
0
        code = pdfi_dict_get(ctx, rec, "Path", (pdf_obj **)&path);
1246
0
        if (code < 0 || pdfi_type_of(path) != PDF_STRING || !pdfi_fmap_file_exists(ctx, (pdf_string *)path)) {
1247
0
            pdfi_countdown(rec);
1248
0
            return_error(gs_error_undefined);
1249
0
        }
1250
1251
0
        *mapname = (pdf_obj *)path;
1252
0
        (void)pdfi_dict_put(ctx, font_dict, ".Path", (pdf_obj *)path);
1253
0
        code = pdfi_dict_get_int(ctx, rec, "SubfontID", &i64);
1254
0
        *findex = (code < 0) ? 0 : (int)i64; /* rangecheck? */
1255
0
        code = 0;
1256
1257
0
    }
1258
0
    else {
1259
0
        *mapname = (pdf_obj *)mname;
1260
0
        code = 0;
1261
0
    }
1262
1263
0
    return code;
1264
0
}