Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zfont1.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Type 1 and Type 4 font creation operators */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "gxfixed.h"
22
#include "gsmatrix.h"
23
#include "gxdevice.h"
24
#include "gxfont.h"
25
#include "gxfont1.h"
26
#include "bfont.h"
27
#include "ialloc.h"
28
#include "icharout.h"
29
#include "ichar1.h"
30
#include "idict.h"
31
#include "idparam.h"
32
#include "ifont1.h"
33
#include "iname.h"    /* for name_index in enumerate_glyph */
34
#include "store.h"
35
36
/* Type 1 font procedures (defined in zchar1.c) */
37
extern const gs_type1_data_procs_t z1_data_procs;
38
font_proc_glyph_info(z1_glyph_info);
39
/* Font procedures defined here */
40
static font_proc_same_font(z1_same_font);
41
42
/* ------ Private utilities ------ */
43
44
static void
45
find_zone_height(float *pmax_height, int count, const float *values)
46
493k
{
47
493k
    int i;
48
493k
    float zone_height;
49
50
974k
    for (i = 0; i < count; i += 2)
51
480k
        if ((zone_height = values[i + 1] - values[i]) > *pmax_height)
52
123k
            *pmax_height = zone_height;
53
493k
}
54
55
/* ------ Font procedures ------ */
56
57
static int
58
z1_enumerate_glyph(gs_font * pfont, int *pindex, gs_glyph_space_t ignored,
59
                   gs_glyph * pglyph)
60
6.79M
{
61
6.79M
    const gs_font_type1 *const pfont1 = (gs_font_type1 *)pfont;
62
6.79M
    const ref *pcsdict = &pfont_data(pfont1)->CharStrings;
63
64
6.79M
    return zchar_enumerate_glyph(pfont->memory, pcsdict, pindex, pglyph);
65
6.79M
}
66
67
/* ------ Public procedures ------ */
68
69
/* Extract pointers to internal structures. */
70
int
71
charstring_font_get_refs(const_os_ptr op, charstring_font_refs_t *pfr)
72
123k
{
73
123k
    check_type(*op, t_dictionary);
74
123k
    if (dict_find_string(op, "Private", &pfr->Private) <= 0 ||
75
123k
        !r_has_type(pfr->Private, t_dictionary)
76
123k
        )
77
10
        return_error(gs_error_invalidfont);
78
123k
    make_empty_array(&pfr->no_subrs, 0);
79
123k
    if (dict_find_string(pfr->Private, "OtherSubrs", &pfr->OtherSubrs) > 0) {
80
123k
        if (!r_is_array(pfr->OtherSubrs))
81
0
            return_error(gs_error_typecheck);
82
123k
    } else
83
0
        pfr->OtherSubrs = &pfr->no_subrs;
84
123k
    if (dict_find_string(pfr->Private, "Subrs", &pfr->Subrs) > 0) {
85
123k
        if (!r_is_array(pfr->Subrs))
86
0
            return_error(gs_error_typecheck);
87
123k
    } else
88
0
        pfr->Subrs = &pfr->no_subrs;
89
123k
    pfr->GlobalSubrs = &pfr->no_subrs;
90
123k
    return 0;
91
123k
}
92
93
static int
94
charstring_check_mm_params(ref *fdict, unsigned int ndesigns)
95
1
{
96
1
    ref *p1;
97
1
    ref p2, p3;
98
1
    ref *Blend, *FInfo, *BFInfo, *BPriv;
99
1
    int code;
100
1
    int i, j;
101
1
    gs_memory_t *mem = dict_mem(fdict->value.pdict);
102
103
1
    code = dict_find_string(fdict, "$Blend", &p1);
104
1
    if (code < 0 || !r_is_proc(p1))
105
0
        goto bad;
106
107
1
    code = dict_find_string(fdict, "FontInfo", &FInfo);
108
1
    if (code < 0 || !r_has_type(FInfo, t_dictionary))
109
0
        goto bad;
110
111
1
    code = dict_find_string(FInfo, "BlendAxisTypes", &p1);
112
1
    if (code < 0 || !r_is_array(p1))
113
0
        goto bad;
114
2
    for (i = 0; i < r_size(p1); i ++) {
115
1
        code = array_get(mem, p1, i, &p2);
116
1
        if (code < 0 || !r_has_type(&p2, t_name))
117
0
            goto bad;
118
1
    }
119
1
    code = dict_find_string(FInfo, "BlendDesignPositions", &p1);
120
1
    if (code < 0 || !r_is_array(p1))
121
0
        goto bad;
122
3
    for (i = 0; i < r_size(p1); i++) {
123
2
        code = array_get(mem, p1, i, &p2);
124
2
        if (code < 0 || !r_is_array(&p2)) {
125
0
            goto bad;
126
0
        }
127
2
        else {
128
4
            for (j = 0; j < r_size(&p2); j++) {
129
2
                code = array_get(mem, &p2, j, &p3);
130
2
                if (code < 0 || !r_has_type(&p3, t_integer))
131
0
                    goto bad;
132
2
            }
133
2
        }
134
2
    }
135
1
    code = dict_find_string(FInfo, "BlendDesignMap", &p1);
136
1
    if (code < 0 || !r_is_array(p1))
137
0
        goto bad;
138
2
    for (i = 0; i < r_size(p1); i++) {
139
1
        code = array_get(mem, p1, i , &p2);
140
1
        if (code < 0 || !r_is_array(&p2)) {
141
0
            goto bad;
142
0
        }
143
1
        else {
144
3
            for (j = 0; j < r_size(&p2); j++) {
145
2
                code = array_get(mem, &p2, j, &p3);
146
2
                if (code < 0 || !r_is_array(&p3))
147
0
                    goto bad;
148
2
                else {
149
2
                    ref p5;
150
2
                    int k;
151
6
                    for (k = 0; k < r_size(&p3); k++) {
152
4
                        code = array_get(mem, &p3, k, &p5);
153
4
                        if (code < 0 || !r_is_number(&p5))
154
0
                            goto bad;
155
4
                    }
156
2
                }
157
2
            }
158
1
        }
159
1
    }
160
1
    code = dict_find_string(fdict, "Blend", &Blend);
161
1
    if (code < 0 || !r_has_type(Blend, t_dictionary))
162
0
        goto bad;
163
1
    code = dict_find_string(Blend, "FontBBox", &p1);
164
1
    if (code < 0 || !r_is_array(p1))
165
0
        goto bad;
166
5
    for (i = 0; i < r_size(p1); i++) {
167
4
         code = array_get(mem, p1, i, &p2);
168
4
         if (code < 0 || !r_is_array(&p2)) {
169
0
             goto bad;
170
0
         }
171
4
         else {
172
12
             for (j = 0; j < r_size(&p2); j++) {
173
8
                 code = array_get(mem, &p2, j, &p3);
174
8
                 if (code < 0 || !r_is_number(&p3))
175
0
                     goto bad;
176
8
             }
177
4
         }
178
4
    }
179
1
    code = dict_find_string(Blend, "Private", &BPriv);
180
1
    if (code < 0 || !r_has_type(BPriv, t_dictionary))
181
0
        goto bad;
182
1
    code = dict_find_string(BPriv, "BlueValues", &p1);
183
1
    if (code > 0) {
184
0
        if (!r_is_array(p1) || r_size(p1) < 2) {
185
0
            goto bad;
186
0
        }
187
0
        else {
188
0
            for (i = 0; i < r_size(p1); i++) {
189
0
                code = array_get(mem, p1, i, &p2);
190
0
                if (code < 0 || !r_is_array(&p2)) {
191
0
                    goto bad;
192
0
                }
193
0
                else {
194
0
                    for (j = 0; j < r_size(&p2); j++) {
195
0
                        code = array_get(mem, &p2, j, &p3);
196
0
                        if (code < 0 || !r_has_type(&p3, t_integer))
197
0
                            goto bad;
198
0
                    }
199
0
                }
200
0
            }
201
0
        }
202
0
    }
203
1
    code = dict_find_string(BPriv, "OtherBlues", &p1);
204
1
    if (code > 0) {
205
0
        if (!r_is_array(p1) || r_size(p1) < 2) {
206
0
            goto bad;
207
0
        }
208
0
        else {
209
0
            for (i = 0; i < r_size(p1); i++) {
210
0
                code = array_get(mem, p1, i, &p2);
211
0
                if (code < 0 || !r_is_array(&p2))
212
0
                    goto bad;
213
0
                else {
214
0
                    for (j = 0; j < r_size(&p2); j++) {
215
0
                        code = array_get(mem, &p2, j, &p3);
216
0
                        if (code < 0 || !r_has_type(&p3, t_integer))
217
0
                            goto bad;
218
0
                    }
219
0
                }
220
0
            }
221
0
        }
222
0
    }
223
1
    code = dict_find_string(BPriv, "StdHW", &p1);
224
1
    if (code > 0) {
225
0
        if (!r_is_array(p1)) {
226
0
            goto bad;
227
0
        }
228
0
        else {
229
0
            for (i = 0; i < r_size(p1); i++){
230
0
                code = array_get(mem, p1, i, &p2);
231
0
                if (code < 0 || !r_is_array(&p2))
232
0
                    goto bad;
233
0
                else {
234
0
                    for (j = 0; j < r_size(&p2); j++) {
235
0
                        code = array_get(mem, &p2, j, &p3);
236
0
                        if (code < 0 || !r_is_number(&p3))
237
0
                            goto bad;
238
0
                    }
239
0
                }
240
0
            }
241
0
        }
242
0
    }
243
1
    code = dict_find_string(BPriv, "StdVW", &p1);
244
1
    if (code > 0) {
245
0
        if (!r_is_array(p1)) {
246
0
            goto bad;
247
0
        }
248
0
        else {
249
0
            for (i = 0; i < r_size(p1); i++){
250
0
                code = array_get(mem, p1, i, &p2);
251
0
                if (code < 0 || !r_is_array(&p2))
252
0
                    goto bad;
253
0
                else {
254
0
                    for (j = 0; j < r_size(&p2); j++) {
255
0
                        code = array_get(mem, &p2, j, &p3);
256
0
                        if (code < 0 || !r_is_number(&p3))
257
0
                            goto bad;
258
0
                    }
259
0
                }
260
0
            }
261
0
        }
262
0
    }
263
1
    code = dict_find_string(BPriv, "StemSnapH,", &p1);
264
1
    if (code > 0) {
265
0
        if (!r_is_array(p1)) {
266
0
            goto bad;
267
0
        }
268
0
        else {
269
0
            for (i = 0; i < r_size(p1); i++){
270
0
                code = array_get(mem, p1, i, &p2);
271
0
                if (code < 0 || !r_is_array(&p2))
272
0
                    goto bad;
273
0
                else {
274
0
                    for (j = 0; j < r_size(&p2); j++) {
275
0
                        code = array_get(mem, &p2, j, &p3);
276
0
                        if (code < 0 || !r_is_number(&p3))
277
0
                            goto bad;
278
0
                    }
279
0
                }
280
0
            }
281
0
        }
282
0
    }
283
1
    code = dict_find_string(BPriv, "StemSnapV", &p1);
284
1
    if (code > 0) {
285
0
        if (!r_is_array(p1)) {
286
0
            goto bad;
287
0
        }
288
0
        else {
289
0
            for (i = 0; i < r_size(p1); i++){
290
0
                code = array_get(mem, p1, i, &p2);
291
0
                if (code < 0 || !r_is_array(&p2))
292
0
                    goto bad;
293
0
                else {
294
0
                    for (j = 0; j < r_size(&p2); j++) {
295
0
                        code = array_get(mem, &p2, j, &p3);
296
0
                        if (code < 0 || !r_is_number(&p3))
297
0
                            goto bad;
298
0
                    }
299
0
                }
300
0
            }
301
0
        }
302
0
    }
303
1
    code = dict_find_string(BPriv, "BlueScale", &p1);
304
1
    if (code > 0) {
305
0
        if (!r_is_array(p1)) {
306
0
            goto bad;
307
0
        }
308
0
        else {
309
0
            for (i = 0; i < r_size(p1); i++) {
310
0
                code = array_get(mem, p1, i, &p3);
311
0
                if (code < 0 || !r_is_number(&p3))
312
0
                    goto bad;
313
0
            }
314
0
        }
315
0
    }
316
1
    code = dict_find_string(BPriv, "BlueShift", &p1);
317
1
    if (code > 0) {
318
0
        if (!r_is_array(p1)) {
319
0
            goto bad;
320
0
        }
321
0
        else {
322
0
            for (i = 0; i < r_size(p1); i++) {
323
0
                code = array_get(mem, p1, i, &p3);
324
0
                if (code < 0 || !r_has_type(&p3, t_integer))
325
0
                    goto bad;
326
0
            }
327
0
        }
328
0
    }
329
1
    code = dict_find_string(BPriv, "FamilyBlues", &p1);
330
1
    if (code > 0) {
331
0
        if (!r_is_array(p1) || r_size(p1) < 2) {
332
0
            goto bad;
333
0
        }
334
0
        else {
335
0
            for (i = 0; i < r_size(p1); i++){
336
0
                code = array_get(mem, p1, i, &p2);
337
0
                if (code < 0 || !r_is_array(&p2))
338
0
                    goto bad;
339
0
                else {
340
0
                    for (j = 0; j < r_size(&p2); j++) {
341
0
                        code = array_get(mem, &p2, j, &p3);
342
0
                        if (code < 0 || !r_has_type(&p3, t_integer))
343
0
                            goto bad;
344
0
                    }
345
0
                }
346
0
            }
347
0
        }
348
0
    }
349
1
    code = dict_find_string(BPriv, "FamilyOtherBlues", &p1);
350
1
    if (code > 0) {
351
0
        if (!r_is_array(p1) || r_size(p1) < 2) {
352
0
            goto bad;
353
0
        }
354
0
        else {
355
0
            for (i = 0; i < r_size(p1); i++){
356
0
                code = array_get(mem, p1, i, &p2);
357
0
                if (code < 0 || !r_is_array(&p2))
358
0
                    goto bad;
359
0
                else {
360
0
                    for (j = 0; j < r_size(&p2); j++) {
361
0
                        code = array_get(mem, &p2, j, &p3);
362
0
                        if (code < 0 || !r_has_type(&p3, t_integer))
363
0
                            goto bad;
364
0
                    }
365
0
                }
366
0
            }
367
0
        }
368
0
    }
369
1
    code = dict_find_string(BPriv, "ForceBold", &p1);
370
1
    if (code > 0) {
371
0
        if (!r_is_array(p1)) {
372
0
            goto bad;
373
0
        }
374
0
        else {
375
0
            for (i = 0; i < r_size(p1); i++) {
376
0
                code = array_get(mem, p1, i, &p3);
377
0
                if (code < 0 || !r_has_type(&p3, t_boolean))
378
0
                    goto bad;
379
0
            }
380
0
        }
381
0
    }
382
1
    code = dict_find_string(Blend, "FontInfo", &BFInfo);
383
1
    if (code > 0 && r_has_type(BFInfo, t_dictionary)) {
384
0
        code = dict_find_string(BFInfo, "UnderlinePosition", &p1);
385
0
        if (code > 0) {
386
0
            if (!r_is_array(p1)) {
387
0
                goto bad;
388
0
            }
389
0
            else {
390
0
                for (i = 0; i < r_size(p1); i++) {
391
0
                    code = array_get(mem, p1, i, &p3);
392
0
                    if (code < 0 || !r_is_number(&p3))
393
0
                        goto bad;
394
0
                }
395
0
            }
396
0
        }
397
0
        code = dict_find_string(BFInfo, "UnderlineThickness", &p1);
398
0
        if (code > 0) {
399
0
            if (!r_is_array(p1)) {
400
0
                goto bad;
401
0
            }
402
0
            else {
403
0
                for (i = 0; i < r_size(p1); i++) {
404
0
                    code = array_get(mem, p1, i, &p3);
405
0
                    if (code < 0 || !r_is_number(&p3))
406
0
                        goto bad;
407
0
                }
408
0
            }
409
0
        }
410
0
        code = dict_find_string(BFInfo, "ItalicAngle", &p1);
411
0
        if (code > 0) {
412
0
            if (!r_is_array(p1)) {
413
0
                goto bad;
414
0
            }
415
0
            else {
416
0
                for (i = 0; i < r_size(p1); i++) {
417
0
                    code = array_get(mem, p1, i, &p3);
418
0
                    if (code < 0 || !r_is_number(&p3))
419
0
                        goto bad;
420
0
                }
421
0
            }
422
0
        }
423
0
    }
424
1
    return 0;
425
0
bad:
426
0
    return_error(gs_error_invalidfont);
427
1
}
428
429
/* Get the parameters of a CharString-based font or a FDArray entry. */
430
int
431
charstring_font_params(const gs_memory_t *mem,
432
                       const_os_ptr op, charstring_font_refs_t *pfr,
433
                       gs_type1_data *pdata1)
434
123k
{
435
123k
    const ref *pprivate = pfr->Private;
436
123k
    int code;
437
438
    /* Get the rest of the information from the Private dictionary. */
439
123k
    if ((code = dict_int_param(pprivate, "lenIV", -1, 255, pdata1->lenIV, &pdata1->lenIV)) < 0)
440
0
        return code;
441
123k
    if ((code = dict_uint_param(pprivate, "subroutineNumberBias",
442
123k
         0, max_uint, pdata1->subroutineNumberBias, &pdata1->subroutineNumberBias)) < 0)
443
0
        return code;
444
123k
    if ((code = dict_int_param(pprivate, "BlueFuzz", 0, 1999, 1, &pdata1->BlueFuzz)) < 0)
445
0
        return code;
446
123k
    if ((code = dict_float_param(pprivate, "BlueScale", 0.039625, &pdata1->BlueScale)) < 0)
447
0
        return code;
448
123k
    if ((code = dict_float_param(pprivate, "BlueShift", 7.0, &pdata1->BlueShift)) < 0)
449
0
        return code;
450
123k
    if ((code = pdata1->BlueValues.count = dict_float_array_param(mem, pprivate, "BlueValues",
451
123k
                max_BlueValues * 2, &pdata1->BlueValues.values[0], NULL)) < 0)
452
0
        return code;
453
123k
    if (pdata1->BlueValues.count % 2 != 0)
454
0
        return_error(gs_error_rangecheck);
455
456
123k
    if ((code = dict_float_param(pprivate, "ExpansionFactor", 0.06, &pdata1->ExpansionFactor)) < 0)
457
0
        return code;
458
123k
    if ((code = pdata1->FamilyBlues.count = dict_float_array_param(mem, pprivate, "FamilyBlues",
459
123k
                max_FamilyBlues * 2, &pdata1->FamilyBlues.values[0], NULL)) < 0)
460
0
        return code;
461
123k
    if (pdata1->FamilyBlues.count % 2 != 0)
462
0
        return_error(gs_error_rangecheck);
463
464
123k
    if ((code = pdata1->FamilyOtherBlues.count = dict_float_array_param(mem, pprivate, "FamilyOtherBlues",
465
123k
                max_FamilyOtherBlues * 2, &pdata1->FamilyOtherBlues.values[0], NULL)) < 0)
466
0
        return code;
467
123k
    if (pdata1->FamilyOtherBlues.count % 2 != 0)
468
0
        return_error(gs_error_rangecheck);
469
470
123k
    if ((code = dict_bool_param(pprivate, "ForceBold", false, &pdata1->ForceBold)) < 0)
471
0
        return code;
472
    /*
473
     * We've seen a few fonts with out-of-range LanguageGroup values;
474
     * if it weren't for this, the only legal values should be 0 or 1.
475
     */
476
123k
    if ((code = dict_int_param(pprivate, "LanguageGroup", min_int, max_int, 0, &pdata1->LanguageGroup)) < 0)
477
0
        return code;
478
123k
    if ((code = pdata1->OtherBlues.count = dict_float_array_param(mem, pprivate, "OtherBlues",
479
123k
                max_OtherBlues * 2, &pdata1->OtherBlues.values[0], NULL)) < 0)
480
0
        return code;
481
123k
    if (pdata1->OtherBlues.count % 2 != 0)
482
0
        return_error(gs_error_rangecheck);
483
484
123k
    if ((code = dict_bool_param(pprivate, "RndStemUp", true, &pdata1->RndStemUp)) < 0)
485
0
        return code;
486
123k
    if ((code = pdata1->StdHW.count = dict_float_array_check_param(mem, pprivate, "StdHW",
487
123k
                1, &pdata1->StdHW.values[0], NULL, 0, gs_error_rangecheck)) < 0)
488
0
        return code;
489
123k
    if ((code = pdata1->StdVW.count = dict_float_array_check_param(mem, pprivate, "StdVW",
490
123k
                1, &pdata1->StdVW.values[0], NULL, 0, gs_error_rangecheck)) < 0)
491
0
        return code;
492
123k
    if ((code = pdata1->StemSnapH.count = dict_float_array_param(mem, pprivate, "StemSnapH",
493
123k
                max_StemSnap, &pdata1->StemSnapH.values[0], NULL)) < 0)
494
0
        return code;
495
123k
    if ((code = pdata1->StemSnapV.count = dict_float_array_param(mem, pprivate, "StemSnapV",
496
123k
                max_StemSnap, &pdata1->StemSnapV.values[0], NULL)) < 0)
497
0
        return code;
498
    /* The WeightVector is in the font dictionary, not Private. */
499
123k
    if ((code = pdata1->WeightVector.count = dict_float_array_param(mem, op, "WeightVector",
500
123k
                max_WeightVector, pdata1->WeightVector.values, NULL)) < 0)
501
0
        return code;
502
503
123k
    if (pdata1->WeightVector.count > 0) {
504
1
        code = charstring_check_mm_params((ref *)op, pdata1->WeightVector.count);
505
1
        if (code < 0)
506
0
            return code;
507
1
    }
508
    /*
509
     * According to section 5.6 of the "Adobe Type 1 Font Format",
510
     * there is a requirement that BlueScale times the maximum
511
     * alignment zone height must be less than 1.  Some fonts
512
     * produced by Fontographer have ridiculously large BlueScale
513
     * values, so we force BlueScale back into range here.
514
     */
515
123k
    {
516
123k
        float max_zone_height = 1.0;
517
518
123k
        find_zone_height(&max_zone_height, pdata1->BlueValues.count, pdata1->BlueValues.values);
519
123k
        find_zone_height(&max_zone_height, pdata1->OtherBlues.count, pdata1->OtherBlues.values);
520
123k
        find_zone_height(&max_zone_height, pdata1->FamilyBlues.count, pdata1->FamilyBlues.values);
521
123k
        find_zone_height(&max_zone_height, pdata1->FamilyOtherBlues.count, pdata1->FamilyOtherBlues.values);
522
123k
        if (pdata1->BlueScale * max_zone_height > 1.0)
523
0
            pdata1->BlueScale = 1.0 / max_zone_height;
524
123k
    }
525
    /*
526
     * According to the same Adobe book, section 5.11, only values
527
     * 0 and 1 are allowed for LanguageGroup and we have encountered
528
     * fonts with other values. If the value is anything else, map it to 0
529
     * so that the remainder of the graphics library won't see an
530
     * unexpected value.
531
     */
532
123k
    if (pdata1->LanguageGroup > 1 || pdata1->LanguageGroup < 0)
533
0
        pdata1->LanguageGroup = 0;
534
535
    /* This is used only when determining if its possible to copy glyphs
536
     * between fonts. Currenly only by pdfwrite and friends. Rather than
537
     * check all the subrs (which we used to do) we hash tehm, store it
538
     * and check the hashes. Zero except when in use by pdfwrite..
539
     */
540
123k
    memset(&pdata1->hash_subrs, 0x00, 16);
541
123k
    return 0;
542
123k
}
543
544
/* Fill in a newly built CharString-based font or FDArray entry. */
545
int
546
charstring_font_init(gs_font_type1 *pfont, const charstring_font_refs_t *pfr,
547
                     const gs_type1_data *pdata1)
548
123k
{
549
123k
    font_data *pdata;
550
551
123k
    pdata = pfont_data(pfont);
552
123k
    pfont->data = *pdata1;
553
123k
    pfont->data.parent = NULL;
554
123k
    ref_assign(&pdata->u.type1.OtherSubrs, pfr->OtherSubrs);
555
123k
    ref_assign(&pdata->u.type1.Subrs, pfr->Subrs);
556
123k
    ref_assign(&pdata->u.type1.GlobalSubrs, pfr->GlobalSubrs);
557
123k
    pfont->data.procs = z1_data_procs;
558
123k
    pfont->data.proc_data = (char *)pdata;
559
123k
    pfont->procs.same_font = z1_same_font;
560
123k
    pfont->procs.glyph_info = z1_glyph_info;
561
123k
    pfont->procs.enumerate_glyph = z1_enumerate_glyph;
562
123k
    pfont->procs.glyph_outline = zchar1_glyph_outline;
563
123k
    return 0;
564
123k
}
565
566
/* Build a Type 1, Type 2, or Type 4 font. */
567
int
568
build_charstring_font(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs *pbuild,
569
                      font_type ftype, charstring_font_refs_t *pfr,
570
                      gs_type1_data *pdata1, build_font_options_t options)
571
123k
{
572
123k
    int code = charstring_font_params(imemory, op, pfr, pdata1);
573
123k
    gs_font_type1 *pfont;
574
575
123k
    if (code < 0)
576
0
        return code;
577
123k
    code = build_gs_primitive_font(i_ctx_p, op, (gs_font_base **)&pfont, ftype,
578
123k
                                   &st_gs_font_type1, pbuild, options);
579
123k
    if (code != 0)
580
44
        return code;
581
    /* This is a new font, fill it in. */
582
123k
    charstring_font_init(pfont, pfr, pdata1);
583
123k
    return define_gs_font(i_ctx_p, (gs_font *)pfont);
584
123k
}
585
586
/* ------ Operators ------ */
587
588
/* Build a Type 1 or Type 4 font. */
589
static int
590
buildfont1or4(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs * pbuild,
591
              font_type ftype, build_font_options_t options)
592
123k
{
593
123k
    charstring_font_refs_t refs;
594
123k
    int code;
595
123k
    gs_type1_data data1;
596
597
123k
    check_op(2);
598
123k
    code = charstring_font_get_refs(op, &refs);
599
123k
    if (code < 0)
600
6
        return code;
601
123k
    data1.interpret = gs_type1_interpret;
602
123k
    data1.subroutineNumberBias = 0;
603
123k
    data1.gsubrNumberBias = 0;
604
605
123k
    data1.lenIV = DEFAULT_LENIV_1;
606
123k
    return build_charstring_font(i_ctx_p, op, pbuild, ftype, &refs, &data1,
607
123k
                                 options);
608
123k
}
609
610
/* <string|name> <font_dict> .buildfont1 <string|name> <font> */
611
/* Build a type 1 (Adobe encrypted) font. */
612
static int
613
zbuildfont1(i_ctx_t *i_ctx_p)
614
123k
{
615
123k
    os_ptr op = osp;
616
123k
    build_proc_refs build;
617
123k
    int code = build_proc_name_refs(imemory, &build,
618
123k
                                    "%Type1BuildChar", "%Type1BuildGlyph");
619
620
123k
    if (code < 0)
621
0
        return code;
622
123k
    return buildfont1or4(i_ctx_p, op, &build, ft_encrypted,
623
123k
                         bf_notdef_required);
624
123k
}
625
626
/* <string|name> <font_dict> .buildfont4 <string|name> <font> */
627
/* Build a type 4 (disk-based Adobe encrypted) font. */
628
static int
629
zbuildfont4(i_ctx_t *i_ctx_p)
630
4
{
631
4
    os_ptr op = osp;
632
4
    build_proc_refs build;
633
4
    int code = build_gs_font_procs(op, &build);
634
635
4
    if (code < 0)
636
4
        return code;
637
0
    return buildfont1or4(i_ctx_p, op, &build, ft_disk_based, bf_options_none);
638
4
}
639
640
/* ------ Initialization procedure ------ */
641
642
const op_def zfont1_op_defs[] =
643
{
644
    {"2.buildfont1", zbuildfont1},
645
    {"2.buildfont4", zbuildfont4},
646
    op_def_end(0)
647
};
648
649
/* ------ Font procedures for Type 1 fonts ------ */
650
651
/* same_font procedure */
652
static bool
653
same_font_dict(const font_data *pdata, const font_data *podata,
654
               const char *key)
655
0
{
656
0
    ref *pvalue;
657
0
    bool present = dict_find_string(&pdata->dict, key, &pvalue) > 0;
658
0
    ref *povalue;
659
0
    bool opresent = dict_find_string(&podata->dict, key, &povalue) > 0;
660
0
    dict *pdict = (&(podata->dict))->value.pdict;
661
662
0
    return (present == opresent &&
663
0
            (present <= 0 || obj_eq(dict_mem(pdict), pvalue, povalue)));
664
0
}
665
static bool z1_check_data_procs_equal(const gs_type1_data_procs_t *p1, const gs_type1_data_procs_t *p2)
666
0
{
667
0
    if (p1->glyph_data != p2->glyph_data)
668
0
        return false;
669
0
    if (p1->subr_data != p2->subr_data)
670
0
        return false;
671
0
    if (p1->seac_data != p2->seac_data)
672
0
        return false;
673
0
    if (p1->push_values != p2->push_values)
674
0
        return false;
675
0
    if (p1->pop_value != p2->pop_value)
676
0
        return false;
677
0
    return true;
678
0
}
679
680
static int
681
z1_same_font(const gs_font *font, const gs_font *ofont, int mask)
682
2.65k
{
683
2.65k
    if (ofont->FontType != font->FontType)
684
0
        return 0;
685
3.97k
    while (font->base != font)
686
1.32k
        font = font->base;
687
3.97k
    while (ofont->base != ofont)
688
1.32k
        ofont = ofont->base;
689
2.65k
    if (ofont == font)
690
2.65k
        return mask;
691
0
    {
692
0
        int same = gs_base_same_font(font, ofont, mask);
693
0
        int check = mask & ~same;
694
0
        const gs_font_type1 *const pfont1 = (const gs_font_type1 *)font;
695
0
        const font_data *const pdata = pfont_data(pfont1);
696
0
        const gs_font_type1 *pofont1 = (const gs_font_type1 *)ofont;
697
0
        const font_data *const podata = pfont_data(pofont1);
698
0
        bool same_data_procs = z1_check_data_procs_equal(&pofont1->data.procs, &z1_data_procs);
699
700
701
0
        if ((check & (FONT_SAME_OUTLINES | FONT_SAME_METRICS)) && same_data_procs &&
702
0
            obj_eq(font->memory, &pdata->CharStrings, &podata->CharStrings) &&
703
            /*
704
             * We use same_font_dict for convenience: we know that
705
             * both fonts do have Private dictionaries.
706
             */
707
0
            same_font_dict(pdata, podata, "Private")
708
0
            )
709
0
            same |= FONT_SAME_OUTLINES;
710
711
0
        if ((check & FONT_SAME_METRICS) && (same & FONT_SAME_OUTLINES) && same_data_procs  &&
712
            /* Metrics may be affected by CDevProc, Metrics, Metrics2. */
713
0
            same_font_dict(pdata, podata, "Metrics") &&
714
0
            same_font_dict(pdata, podata, "Metrics2") &&
715
0
            same_font_dict(pdata, podata, "CDevProc")
716
0
            )
717
0
            same |= FONT_SAME_METRICS;
718
719
0
        if ((check & FONT_SAME_ENCODING) &&
720
0
            pofont1->procs.same_font == z1_same_font &&
721
0
            obj_eq(font->memory, &pdata->Encoding, &podata->Encoding)
722
0
            )
723
0
            same |= FONT_SAME_ENCODING;
724
725
0
        return same & mask;
726
2.65k
    }
727
2.65k
}