Coverage Report

Created: 2025-08-28 07:06

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