Coverage Report

Created: 2025-06-24 07:01

/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
45.5k
{
54
45.5k
    int code = 0;
55
45.5k
    stream *s;
56
45.5k
    char fname[gp_file_name_sizeof];
57
45.5k
    const char *path_pfx = "Init/";
58
45.5k
    const char *poststring = "\nendstream";
59
45.5k
    const int poststringlen = strlen(poststring);
60
45.5k
    fname[0] = '\0';
61
62
45.5k
    if (strlen(path_pfx) + strlen(mapfilename) + 1 > gp_file_name_sizeof)
63
0
        return_error(gs_error_invalidfileaccess);
64
65
45.5k
    code = pdfi_open_resource_file(ctx, mapfilename, strlen(mapfilename), &s);
66
45.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
45.5k
    if (code >= 0) {
73
45.5k
        int i;
74
45.5k
        int64_t file_size;
75
76
45.5k
        sfseek(s, 0, SEEK_END);
77
45.5k
        file_size = sftell(s);
78
45.5k
        sfseek(s, 0, SEEK_SET);
79
45.5k
        if (file_size < 0 || file_size > max_int - poststringlen) {
80
0
            code = gs_note_error(gs_error_ioerror);
81
45.5k
        } else {
82
45.5k
            byte *dbuf;
83
45.5k
            *buflen = (int)file_size;
84
85
45.5k
            (*buf) = gs_alloc_bytes(ctx->memory, *buflen + poststringlen, "pdf_cmap_open_file(buf)");
86
45.5k
            if (*buf != NULL) {
87
45.5k
                sfread((*buf), 1, *buflen, s);
88
45.5k
                memcpy((*buf) + *buflen, poststring, poststringlen);
89
45.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
145M
                for (i = 0, dbuf = *buf; i < *buflen - 1; i++, dbuf++) {
96
145M
                    if (*dbuf == ';') {
97
3.91M
                        *dbuf = ' ';
98
3.91M
                    }
99
145M
                    if (memcmp(dbuf, "cvn ", 4) == 0) {
100
0
                        dbuf[0] = dbuf[1] = dbuf[2] = 0x20;
101
0
                    }
102
145M
                }
103
45.5k
            }
104
0
            else {
105
0
                code = gs_note_error(gs_error_VMerror);
106
0
            }
107
45.5k
        }
108
45.5k
        sfclose(s);
109
45.5k
    }
110
45.5k
    return code;
111
45.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
45.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
45.5k
    return 0;
236
45.5k
}
237
238
static int
239
pdf_make_fontmap(pdf_context *ctx, const char *default_fmapname, int cidfmap)
240
45.5k
{
241
45.5k
    byte *fmapbuf = NULL;
242
45.5k
    int code, fmapbuflen;
243
45.5k
    pdf_c_stream *fmapstr = NULL;
244
45.5k
    pdf_stream fakedict = {0};
245
45.5k
    pdfi_custom_fmap_entry *pcfe = pdfi_custom_fmap_entries;
246
45.5k
    int i, j = 0;
247
45.5k
    char fmapname[gp_file_name_sizeof];
248
45.5k
    pdf_c_stream fakemainstream = {0};
249
45.5k
    int stacksize = pdfi_count_stack(ctx);
250
251
45.5k
    strncpy(fmapname, default_fmapname, strlen(default_fmapname) + 1);
252
253
45.5k
    code = pdfi_mark_stack(ctx, PDF_DICT_MARK);
254
45.5k
    if (code < 0)
255
0
        goto done;
256
257
45.5k
    do {
258
45.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
45.5k
        code = pdfi_fontmap_open_file(ctx, (const char *)fmapname, &fmapbuf, &fmapbuflen);
264
45.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
45.5k
        else {
277
45.5k
            code = pdfi_open_memory_stream_from_memory(ctx, fmapbuflen, fmapbuf, &fmapstr, true);
278
45.5k
            if (code >= 0) {
279
280
45.5k
                if (ctx->main_stream == NULL) {
281
0
                    ctx->main_stream = &fakemainstream;
282
0
                }
283
284
45.5k
                if (fmapbuflen > 0)
285
45.5k
                    code = pdfi_interpret_content_stream(ctx, fmapstr, &fakedict, NULL);
286
0
                else
287
0
                    code = 0;
288
289
45.5k
                if (ctx->main_stream == &fakemainstream) {
290
0
                    ctx->main_stream = NULL;
291
0
                }
292
45.5k
                gs_free_object(ctx->memory, fmapbuf, "pdf_make_fontmap(fmapbuf)");
293
45.5k
            }
294
45.5k
        }
295
45.5k
        j++;
296
45.5k
    } while(j < ctx->num_fontmapfiles && cidfmap == false && code >= 0);
297
298
45.5k
    if (code >= 0) {
299
45.5k
        if (pdfi_count_stack(ctx) > stacksize) {
300
45.5k
            code = pdfi_dict_from_stack(ctx, 0, 0, true);
301
45.5k
            if (code < 0)
302
0
                goto done;
303
304
45.5k
            if (cidfmap == true) {
305
5.99k
                ctx->pdfcidfmap = (pdf_dict *)ctx->stack_top[-1];
306
5.99k
                pdfi_countup(ctx->pdfcidfmap);
307
5.99k
            }
308
39.5k
            else {
309
39.5k
                ctx->pdffontmap = (pdf_dict *)ctx->stack_top[-1];
310
39.5k
                pdfi_countup(ctx->pdffontmap);
311
39.5k
            }
312
45.5k
            pdfi_pop(ctx, 1);
313
45.5k
            code = 0;
314
315
            /* Add our internal aliases to the fontmap. */
316
45.5k
            if (cidfmap == false) {
317
79.0k
                for (i = 0; pcfe[i].keyname != NULL; i++) {
318
39.5k
                    pdf_obj *value;
319
39.5k
                    bool k;
320
321
                    /* We don't want to *replace* entries */
322
39.5k
                    if (pdfi_dict_known(ctx, ctx->pdffontmap, pcfe[i].keyname, &k) >= 0
323
39.5k
                        && k != true) {
324
39.5k
                        code = pdfi_name_alloc(ctx, (byte *)pcfe[i].mappedname, strlen(pcfe[i].mappedname), &value);
325
39.5k
                        if (code < 0)
326
0
                            continue;
327
39.5k
                        pdfi_countup(value);
328
                        /* If dict_put throws an error, we just carry on - hence the (void) */
329
39.5k
                        (void)pdfi_dict_put(ctx,  ctx->pdffontmap, pcfe[i].keyname, value);
330
39.5k
                        pdfi_countdown(value);
331
39.5k
                    }
332
39.5k
                }
333
39.5k
            }
334
45.5k
        }
335
0
        else {
336
0
            code = gs_note_error(gs_error_syntaxerror);
337
0
        }
338
45.5k
    }
339
45.5k
done:
340
    /* We always want to leave here with a valid map dictionary
341
       even if it's empty
342
     */
343
45.5k
    if (cidfmap == true) {
344
5.99k
        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.99k
    }
350
39.5k
    else {
351
39.5k
        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
39.5k
    }
357
45.5k
    if (code >= 0) {
358
45.5k
        code = pdfi_populate_ufst_fontmap(ctx);
359
45.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
45.5k
    pdfi_clearstack(ctx);
429
45.5k
    return code;
430
45.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
39.5k
        const char *fmap_default = "Fontmap.GS";
1110
39.5k
        char *fmapname = (char *)fmap_default;
1111
39.5k
        code = pdf_make_fontmap(ctx, fmapname, false);
1112
39.5k
        if (code < 0) {
1113
0
            return code;
1114
0
        }
1115
39.5k
    }
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
852k
        while(1) {
1129
852k
            pdf_obj *mname2;
1130
852k
            code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, (pdf_name *)mname, &mname2);
1131
852k
            if (code < 0) {
1132
852k
                code = 0;
1133
852k
                break;
1134
852k
            }
1135
358
            pdfi_countdown(mname);
1136
358
            mname = mname2;
1137
358
        }
1138
852k
    }
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
852k
        *mapname = mname;
1175
852k
        code = 0;
1176
852k
    }
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
56.9k
{
1187
56.9k
    int code = 0;
1188
56.9k
    pdf_obj *cidname = NULL;
1189
56.9k
    pdf_obj *mname;
1190
1191
56.9k
    *findex = 0;
1192
1193
56.9k
    if (ctx->pdfcidfmap == NULL) {
1194
5.99k
        const char *cidfmap_default = "cidfmap";
1195
5.99k
        char *cidfmapname = (char *)cidfmap_default;
1196
5.99k
        code = pdf_make_fontmap(ctx, cidfmapname, true);
1197
5.99k
        if (code < 0) {
1198
0
            return code;
1199
0
        }
1200
5.99k
    }
1201
56.9k
    if (name == NULL || pdfi_type_of(name) != PDF_NAME) {
1202
29.9k
        code = pdfi_dict_get(ctx, font_dict, "BaseFont", &cidname);
1203
29.9k
        if (code < 0 || pdfi_type_of(cidname) != PDF_NAME) {
1204
538
            pdfi_countdown(cidname);
1205
538
            return_error(gs_error_undefined);
1206
538
        }
1207
1208
29.9k
    }
1209
26.9k
    else {
1210
26.9k
        cidname = (pdf_obj *)name;
1211
26.9k
        pdfi_countup(cidname);
1212
26.9k
    }
1213
1214
56.3k
    code = pdfi_dict_get_by_key(ctx, ctx->pdfcidfmap, (pdf_name *)cidname, &mname);
1215
56.3k
    pdfi_countdown(cidname);
1216
56.3k
    if (code < 0)
1217
56.3k
        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
}