Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpsfx.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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
/* Convert Type 1 Charstrings to Type 2 */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gxfixed.h"
23
#include "gxmatrix.h"   /* for gsfont.h */
24
#include "gxfont.h"
25
#include "gxfont1.h"
26
#include "gxtype1.h"
27
#include "stream.h"
28
#include "gdevpsf.h"
29
#include "gxgstate.h"
30
31
/* ------ Type 1 Charstring parsing ------ */
32
33
/*
34
 * The parsing code handles numbers on its own; it reports callsubr and
35
 * return operators to the caller, but also executes them.
36
 *
37
 * Only the following elements of the Type 1 state are used:
38
 *  ostack, os_count, ipstack, ips_count
39
 */
40
41
19.7M
#define CE_OFFSET 32    /* offset for extended opcodes */
42
43
typedef struct {
44
    fixed v0, v1;   /* coordinates */
45
    ushort index;   /* sequential index of hint */
46
} cv_stem_hint;
47
typedef struct {
48
    int count;
49
    int current;    /* cache cursor for search */
50
    /*
51
     * For dotsection and Type 1 Charstring hint replacement,
52
     * we store active hints at the bottom of the table, and
53
     * replaced hints at the top.
54
     */
55
    int replaced_count;   /* # of replaced hints at top */
56
    cv_stem_hint data[max_total_stem_hints];
57
} cv_stem_hint_table;
58
59
/* Skip over the initial bytes in a Charstring, if any. */
60
static void
61
skip_iv(gs_type1_state *pcis)
62
7.36M
{
63
7.36M
    int skip = pcis->pfont->data.lenIV;
64
7.36M
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
65
7.36M
    const byte *cip = ipsp->cs_data.bits.data;
66
7.36M
    crypt_state state = crypt_charstring_seed;
67
68
36.7M
    for (; skip > 0; ++cip, --skip)
69
29.4M
        decrypt_skip_next(*cip, state);
70
7.36M
    ipsp->ip = cip;
71
7.36M
    ipsp->dstate = state;
72
7.36M
}
73
74
/*
75
 * Set up for parsing a Type 1 Charstring.
76
 *
77
 * Only uses the following elements of *pfont:
78
 *  data.lenIV
79
 */
80
static void
81
type1_next_init(gs_type1_state *pcis, const gs_glyph_data_t *pgd,
82
                gs_font_type1 *pfont)
83
3.79M
{
84
3.79M
    gs_type1_interp_init(pcis, NULL, NULL, NULL, NULL, false, 0, pfont);
85
3.79M
    pcis->flex_count = flex_max;
86
3.79M
    pcis->ipstack[0].cs_data = *pgd;
87
3.79M
    skip_iv(pcis);
88
3.79M
}
89
90
/* Clear the Type 1 operand stack. */
91
static inline void
92
type1_clear(gs_type1_state *pcis)
93
69.5M
{
94
69.5M
    pcis->os_count = 0;
95
69.5M
}
96
97
/* Execute a callsubr. */
98
static int
99
type1_callsubr(gs_type1_state *pcis, int index)
100
3.56M
{
101
3.56M
    gs_font_type1 *pfont = pcis->pfont;
102
3.56M
    ip_state_t *ipsp1 = &pcis->ipstack[pcis->ips_count];
103
3.56M
    int code = pfont->data.procs.subr_data(pfont, index, false,
104
3.56M
                                           &ipsp1->cs_data);
105
106
3.56M
    if (code < 0)
107
1
        return_error(code);
108
3.56M
    pcis->ips_count++;
109
3.56M
    skip_iv(pcis);
110
3.56M
    return code;
111
3.56M
}
112
113
/* Add 1 or 3 stem hints. */
114
static int
115
type1_stem1(gs_type1_state *pcis, cv_stem_hint_table *psht, const fixed *pv,
116
            fixed lsb, byte *active_hints)
117
18.0M
{
118
18.0M
    fixed v0 = pv[0] + lsb, v1 = v0 + pv[1];
119
18.0M
    cv_stem_hint *bot = &psht->data[0];
120
18.0M
    cv_stem_hint *orig_top = bot + psht->count;
121
18.0M
    cv_stem_hint *top = orig_top;
122
123
18.0M
    if (psht->count >= max_total_stem_hints)
124
0
        return_error(gs_error_limitcheck);
125
27.6M
    while (top > bot &&
126
24.0M
           (v0 < top[-1].v0 || (v0 == top[-1].v0 && v1 < top[-1].v1))
127
18.0M
           ) {
128
9.61M
        *top = top[-1];
129
9.61M
        top--;
130
9.61M
    }
131
18.0M
    if (top > bot && v0 == top[-1].v0 && v1 == top[-1].v1) {
132
        /* Duplicate hint, don't add it. */
133
11.2M
        memmove(top, top + 1, (char *)orig_top - (char *)top);
134
11.2M
        if (active_hints) {
135
9.00M
            uint index = top[-1].index;
136
137
9.00M
            active_hints[index >> 3] |= 0x80 >> (index & 7);
138
9.00M
        }
139
11.2M
        return 0;
140
11.2M
    }
141
6.72M
    top->v0 = v0;
142
6.72M
    top->v1 = v1;
143
6.72M
    psht->count++;
144
6.72M
    return 0;
145
18.0M
}
146
static void
147
type1_stem3(gs_type1_state *pcis, cv_stem_hint_table *psht, const fixed *pv3,
148
            fixed lsb, byte *active_hints)
149
7.13k
{
150
7.13k
    type1_stem1(pcis, psht, pv3, lsb, active_hints);
151
7.13k
    type1_stem1(pcis, psht, pv3 + 2, lsb, active_hints);
152
7.13k
    type1_stem1(pcis, psht, pv3 + 4, lsb, active_hints);
153
7.13k
}
154
155
/*
156
 * Get the next operator from a Type 1 Charstring.  This procedure handles
157
 * numbers, div, blend, pop, and callsubr/return.
158
 */
159
static int
160
type1_next(gs_type1_state *pcis)
161
79.5M
{
162
79.5M
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
163
79.5M
    const byte *cip, *cipe;
164
79.5M
    crypt_state state;
165
79.5M
#define CLEAR (csp = pcis->ostack - 1)
166
79.5M
    fixed *csp = (&pcis->ostack[pcis->os_count]) - 1;
167
79.5M
    const bool encrypted = pcis->pfont->data.lenIV >= 0;
168
79.5M
    int c, code, num_results, c0;
169
170
86.6M
 load:
171
86.6M
    cip = ipsp->ip;
172
86.6M
    cipe = ipsp->cs_data.bits.data + ipsp->cs_data.bits.size;
173
86.6M
    state = ipsp->dstate;
174
285M
    for (;;) {
175
285M
        if (cip >= cipe)
176
            /* We used to treat buffer overrun as a simple invalid font, now we assume that
177
             * there is an implicit endchar, so we return a particular error for later
178
             * interception. Returning an error allows any other code to continue as before.
179
             * Part of bug #693170 where the fonts are invalid (no endchar on some glyphs).
180
             */
181
0
            return_error(gs_error_unknownerror);
182
285M
        c0 = *cip++;
183
285M
        charstring_next(c0, state, c, encrypted);
184
285M
        if (c >= c_num1) {
185
            /* This is a number, decode it and push it on the stack. */
186
197M
            if (c < c_pos2_0) { /* 1-byte number */
187
151M
                decode_push_num1(csp, pcis->ostack, c);
188
151M
            } else if (c < cx_num4) { /* 2-byte number */
189
46.0M
                decode_push_num2(csp, pcis->ostack, c, cip, state, encrypted);
190
46.0M
            } else if (c == cx_num4) { /* 4-byte number */
191
27.1k
                long lw;
192
193
27.1k
                decode_num4(lw, cip, state, encrypted);
194
27.1k
                CS_CHECK_PUSH(csp, pcis->ostack);
195
27.1k
                *++csp = int2fixed(lw);
196
27.1k
                if (lw != fixed2long(*csp)) {
197
                    /*
198
                     * The integer was too large to handle in fixed point.
199
                     * Handle this case specially.
200
                     */
201
4
                    code = gs_type1_check_float(&state, encrypted, &cip, csp, lw);
202
4
                    if (code < 0)
203
4
                       return code;
204
4
                }
205
27.1k
            } else   /* not possible */
206
0
                return_error(gs_error_invalidfont);
207
197M
            continue;
208
197M
        }
209
#ifdef DEBUG
210
        if (gs_debug_c('1')) {
211
            const fixed *p;
212
213
            for (p = pcis->ostack; p <= csp; ++p)
214
                dmprintf1(pcis->pgs->memory, " %g", fixed2float(*p));
215
            if (c == cx_escape) {
216
                crypt_state cstate = state;
217
                int cn;
218
219
                charstring_next(*cip, cstate, cn, encrypted);
220
                dmprintf1(pcis->pgs->memory, " [*%d]\n", cn);
221
            } else
222
                dmprintf1(pcis->pgs->memory, " [%d]\n", c);
223
        }
224
#endif
225
88.4M
        switch ((char_command) c) {
226
77.7M
        default:
227
77.7M
            break;
228
77.7M
        case c_undef0:
229
0
        case c_undef2:
230
0
        case c_undef17:
231
0
            return_error(gs_error_invalidfont);
232
3.56M
        case c_callsubr:
233
3.56M
            if (csp + 1 - &pcis->ostack[0] < 1)
234
0
                return_error(gs_error_invalidfont);
235
3.56M
            code = type1_callsubr(pcis, fixed2int_var(*csp) +
236
3.56M
                                  pcis->pfont->data.subroutineNumberBias);
237
3.56M
            if (code < 0)
238
1
                return_error(code);
239
3.56M
            ipsp->ip = cip, ipsp->dstate = state;
240
3.56M
            --csp;
241
3.56M
            ++ipsp;
242
3.56M
            goto load;
243
3.56M
        case c_return:
244
3.56M
            if (pcis->ips_count > 1) {
245
3.56M
                gs_glyph_data_free(&ipsp->cs_data, "type1_next");
246
3.56M
                pcis->ips_count--;
247
3.56M
                --ipsp;
248
3.56M
            } else
249
0
                return_error(gs_error_invalidfont);
250
3.56M
            goto load;
251
3.56M
        case c_undoc15:
252
            /* See gstype1.h for information on this opcode. */
253
19
            CLEAR;
254
19
            continue;
255
3.55M
        case cx_escape:
256
3.55M
            charstring_next(*cip, state, c, encrypted);
257
3.55M
            ++cip;
258
3.55M
            switch ((char1_extended_command) c) {
259
10.6k
            default:
260
10.6k
                c += CE_OFFSET;
261
10.6k
                break;
262
18.2k
            case ce1_div:
263
18.2k
                if (csp + 1 - &pcis->ostack[0] < 1)
264
0
                    return_error(gs_error_invalidfont);
265
18.2k
                csp[-1] = float2fixed((double)csp[-1] / (double)*csp);
266
18.2k
                --csp;
267
18.2k
                continue;
268
0
            case ce1_undoc15: /* see gstype1.h */
269
0
                CLEAR;
270
0
                continue;
271
1.77M
            case ce1_callothersubr:
272
1.77M
                if (csp + 1 - &pcis->ostack[0] < 2)
273
0
                    return_error(gs_error_invalidfont);
274
1.77M
                switch (fixed2int_var(*csp)) {
275
3.21k
                case 0:
276
3.21k
                    pcis->ignore_pops = 2;
277
3.21k
                    break; /* pass to caller */
278
1.74M
                case 3:
279
1.74M
                    pcis->ignore_pops = 1;
280
1.74M
                    break; /* pass to caller */
281
0
                case 14:
282
0
                    num_results = 1; goto blend;
283
0
                case 15:
284
0
                    num_results = 2; goto blend;
285
0
                case 16:
286
0
                    num_results = 3; goto blend;
287
0
                case 17:
288
0
                    num_results = 4; goto blend;
289
0
                case 18:
290
0
                    num_results = 6;
291
0
                blend:
292
0
                    CS_CHECK_POP(csp, pcis->ostack);
293
0
                    if (!CS_CHECK_CSTACK_BOUNDS(&csp[-fixed2int_var(csp[-1])], pcis->ostack))
294
0
                        return_error(gs_error_invalidfont);
295
296
0
                    code = gs_type1_blend(pcis, csp, num_results);
297
0
                    if (code < 0)
298
0
                        return code;
299
0
                    csp -= code;
300
0
                    continue;
301
25.6k
                default:
302
25.6k
                    break; /* pass to caller */
303
1.77M
                }
304
1.77M
                break;
305
1.77M
            case ce1_pop:
306
1.75M
                if (pcis->ignore_pops != 0) {
307
1.75M
                    pcis->ignore_pops--;
308
1.75M
                    continue;
309
1.75M
                }
310
3.55M
                return_error(gs_error_rangecheck);
311
3.55M
            }
312
1.78M
            break;
313
88.4M
        }
314
79.5M
        break;
315
88.4M
    }
316
79.5M
    ipsp->ip = cip, ipsp->dstate = state;
317
79.5M
    pcis->ips_count = ipsp + 1 - &pcis->ipstack[0];
318
79.5M
    pcis->os_count = csp + 1 - &pcis->ostack[0];
319
79.5M
    return c;
320
86.6M
}
321
322
/* ------ Output ------ */
323
324
/* Put 2 or 4 bytes on a stream (big-endian). */
325
static void
326
sputc2(stream *s, int i)
327
21.3M
{
328
21.3M
    sputc(s, (byte)(i >> 8));
329
21.3M
    sputc(s, (byte)i);
330
21.3M
}
331
static void
332
sputc4(stream *s, int i)
333
9.04k
{
334
9.04k
    sputc2(s, i >> 16);
335
9.04k
    sputc2(s, i);
336
9.04k
}
337
338
/* Put a Type 2 operator on a stream. */
339
static void
340
type2_put_op(stream *s, int op)
341
19.7M
{
342
19.7M
    if (op >= CE_OFFSET) {
343
1.60k
        spputc(s, cx_escape);
344
1.60k
        spputc(s, (byte)(op - CE_OFFSET));
345
1.60k
    } else
346
19.7M
        sputc(s, (byte)op);
347
19.7M
}
348
349
/* Put a Type 2 number on a stream. */
350
static void
351
type2_put_int(stream *s, int i)
352
87.4M
{
353
87.4M
    if (i >= -107 && i <= 107)
354
66.0M
        sputc(s, (byte)(i + 139));
355
21.3M
    else if (i <= 1131 && i >= 0)
356
14.6M
        sputc2(s, (c_pos2_0 << 8) + i - 108);
357
6.70M
    else if (i >= -1131 && i < 0)
358
6.70M
        sputc2(s, (c_neg2_0 << 8) - i - 108);
359
4.82k
    else if (i >= -32768 && i <= 32767) {
360
4.82k
        spputc(s, c2_shortint);
361
4.82k
        sputc2(s, i);
362
4.82k
    } else {
363
        /*
364
         * We can't represent this number directly: compute it.
365
         * (This can be done much more efficiently in particular cases;
366
         * we'll do this if it ever seems worthwhile.)
367
         */
368
0
        type2_put_int(s, i >> 10);
369
0
        type2_put_int(s, 1024);
370
0
        type2_put_op(s, CE_OFFSET + ce2_mul);
371
0
        type2_put_int(s, i & 1023);
372
0
        type2_put_op(s, CE_OFFSET + ce2_add);
373
0
    }
374
87.4M
}
375
376
/* Put a fixed value on a stream. */
377
static void
378
type2_put_fixed(stream *s, fixed v)
379
87.4M
{
380
87.4M
    if (fixed_is_int(v))
381
87.4M
        type2_put_int(s, fixed2int_var(v));
382
9.04k
    else if (v >= int2fixed(-32768) && v < int2fixed(32768)) {
383
        /* We can represent this as a 16:16 number. */
384
9.04k
        spputc(s, cx_num4);
385
9.04k
        sputc4(s, v << (16 - _fixed_shift));
386
9.04k
    } else {
387
0
        type2_put_int(s, fixed2int_var(v));
388
0
        type2_put_fixed(s, fixed_fraction(v));
389
0
        type2_put_op(s, CE_OFFSET + ce2_add);
390
0
    }
391
87.4M
}
392
393
/* Put a stem hint table on a stream. */
394
static void
395
type2_put_stems(stream *s, int os_count, const cv_stem_hint_table *psht, int op)
396
3.17M
{
397
3.17M
    fixed prev = 0;
398
3.17M
    int pushed = os_count;
399
3.17M
    int i;
400
401
9.89M
    for (i = 0; i < psht->count; ++i, pushed += 2) {
402
6.72M
        fixed v0 = psht->data[i].v0;
403
6.72M
        fixed v1 = psht->data[i].v1;
404
405
6.72M
        if (pushed > ostack_size - 2) {
406
0
            type2_put_op(s, op);
407
0
            pushed = 0;
408
0
        }
409
6.72M
        type2_put_fixed(s, v0 - prev);
410
6.72M
        type2_put_fixed(s, v1 - v0);
411
6.72M
        prev = v1;
412
6.72M
    }
413
3.17M
    type2_put_op(s, op);
414
3.17M
}
415
416
/* Put out a hintmask command. */
417
static void
418
type2_put_hintmask(stream *s, const byte *mask, uint size)
419
1.30M
{
420
1.30M
    uint ignore;
421
422
1.30M
    type2_put_op(s, c2_hintmask);
423
1.30M
    sputs(s, mask, size, &ignore);
424
1.30M
}
425
426
/* ------ Main program ------ */
427
428
/*
429
 * Convert a Type 1 Charstring to (unencrypted) Type 2.
430
 * For simplicity, we expand all Subrs in-line.
431
 * We still need to optimize the output using these patterns:
432
 *  (vhcurveto hvcurveto)* (vhcurveto hrcurveto | vrcurveto) =>
433
 *    vhcurveto
434
 *  (hvcurveto vhcurveto)* (hvcurveto vrcurveto | hrcurveto) =>
435
 *    hvcurveto
436
 */
437
20.1M
#define MAX_STACK ostack_size
438
int
439
psf_convert_type1_to_type2(stream *s, const gs_glyph_data_t *pgd,
440
                           gs_font_type1 *pfont)
441
1.89M
{
442
1.89M
    gs_type1_state cis;
443
1.89M
    cv_stem_hint_table hstem_hints; /* horizontal stem hints */
444
1.89M
    cv_stem_hint_table vstem_hints; /* vertical stem hints */
445
1.89M
    bool first = true;
446
1.89M
    bool need_moveto = true;
447
1.89M
    bool replace_hints = false;
448
1.89M
    bool hints_changed = false;
449
1.89M
    bool width_on_stack = false;
450
1.89M
    enum {
451
1.89M
        dotsection_in = 0,
452
1.89M
        dotsection_out = -1
453
1.89M
    } dotsection_flag = dotsection_out;
454
1.89M
    byte active_hints[(max_total_stem_hints + 7) / 8];
455
1.89M
    byte dot_save_hints[(max_total_stem_hints + 7) / 8];
456
1.89M
    uint hintmask_size;
457
1.89M
#define HINTS_CHANGED()\
458
9.86M
  BEGIN\
459
9.86M
    hints_changed = replace_hints;\
460
9.86M
    if (hints_changed)\
461
9.86M
        CHECK_OP();   /* see below */\
462
9.86M
  END
463
1.89M
#define CHECK_HINTS_CHANGED()\
464
15.7M
  BEGIN\
465
15.7M
    if (hints_changed) {\
466
1.30M
        type2_put_hintmask(s, active_hints, hintmask_size);\
467
1.30M
        hints_changed = false;\
468
1.30M
    }\
469
15.7M
  END
470
    /*
471
     * In order to combine Type 1 operators, we usually delay writing
472
     * out operators (but not their operands).  We must keep track of
473
     * the stack depth so we don't exceed it when combining operators.
474
     */
475
1.89M
    int depth;      /* of operands on stack */
476
1.89M
    int prev_op;    /* operator to write, -1 if none */
477
1.89M
#define CLEAR_OP()\
478
15.2M
  (depth = 0, prev_op = -1)
479
1.89M
#define CHECK_OP()\
480
28.2M
  BEGIN\
481
28.2M
    if (prev_op >= 0) {\
482
13.3M
        type2_put_op(s, prev_op);\
483
13.3M
        CLEAR_OP();\
484
13.3M
    }\
485
28.2M
  END
486
1.89M
    fixed mx0 = 0, my0 = 0; /* See ce1_setcurrentpoint. */
487
488
    /* Really this is to silence Coverity, but it makes sense and we do it a lot so no penatly */
489
1.89M
    memset(active_hints, 0, (max_total_stem_hints + 7) / 8);
490
491
    /* In case we do not get an sbw or hsbw op */
492
1.89M
    cis.lsb.x = cis.lsb.y = cis.width.x = cis.width.y = fixed_0;
493
494
    /*
495
     * Do a first pass to collect hints.  Note that we must also process
496
     * [h]sbw, because the hint coordinates are relative to the lsb.
497
     */
498
1.89M
    hstem_hints.count = hstem_hints.replaced_count = hstem_hints.current = 0;
499
1.89M
    vstem_hints.count = vstem_hints.replaced_count = vstem_hints.current = 0;
500
1.89M
    type1_next_init(&cis, pgd, pfont);
501
39.7M
    for (;;) {
502
39.7M
        int c = type1_next(&cis);
503
39.7M
        fixed *csp = (&cis.ostack[cis.os_count]) - 1;
504
505
39.7M
        switch (c) {
506
26.0M
        default:
507
             /* We used to treat buffer overrun as a simple invalid font, now we assume that
508
             * there is an implicit endchar, this is handled by looking for a specific error.
509
             * Part of bug #693170 where the fonts are invalid (no endchar on some glyphs).
510
             */
511
26.0M
           if (c == gs_error_unknownerror)
512
0
                break;
513
26.0M
            if (c < 0)
514
5
                return c;
515
26.0M
            type1_clear(&cis);
516
26.0M
            continue;
517
1.89M
        case c1_hsbw:
518
1.89M
            if (cis.os_count < 2)
519
0
                return_error(gs_error_invalidfont);
520
1.89M
            gs_type1_sbw(&cis, cis.ostack[0], fixed_0, cis.ostack[1], fixed_0);
521
1.89M
            goto clear;
522
5.32M
        case cx_hstem:
523
5.32M
            if (cis.os_count < 2)
524
0
                return_error(gs_error_invalidfont);
525
5.32M
            type1_stem1(&cis, &hstem_hints, csp - 1, cis.lsb.y, NULL);
526
5.32M
            goto clear;
527
3.66M
        case cx_vstem:
528
3.66M
            if (cis.os_count < 2)
529
0
                return_error(gs_error_invalidfont);
530
3.66M
            type1_stem1(&cis, &vstem_hints, csp - 1, cis.lsb.x, NULL);
531
3.66M
            goto clear;
532
0
        case CE_OFFSET + ce1_sbw:
533
0
            if (cis.os_count < 4)
534
0
                return_error(gs_error_invalidfont);
535
0
            gs_type1_sbw(&cis, cis.ostack[0], cis.ostack[1],
536
0
                         cis.ostack[2], cis.ostack[3]);
537
0
            goto clear;
538
3.55k
        case CE_OFFSET + ce1_vstem3:
539
3.55k
            if (cis.os_count < 6)
540
0
                return_error(gs_error_invalidfont);
541
3.55k
            type1_stem3(&cis, &vstem_hints, csp - 5, cis.lsb.x, NULL);
542
3.55k
            goto clear;
543
9
        case CE_OFFSET + ce1_hstem3:
544
9
            if (cis.os_count < 6)
545
0
                return_error(gs_error_invalidfont);
546
9
            type1_stem3(&cis, &hstem_hints, csp - 5, cis.lsb.y, NULL);
547
10.8M
        clear:
548
10.8M
            type1_clear(&cis);
549
10.8M
            continue;
550
886k
        case ce1_callothersubr:
551
886k
            if (cis.os_count < 2)
552
0
                return_error(gs_error_invalidfont);
553
886k
            if (*csp == int2fixed(3))
554
871k
                replace_hints = true;
555
886k
            if (*csp == int2fixed(12) || *csp == int2fixed(13))
556
0
                cis.os_count -= fixed2int(csp[-1]);
557
886k
            cis.os_count -= 2;
558
886k
            continue;
559
162
        case CE_OFFSET + ce1_dotsection:
560
162
            replace_hints = true;
561
162
            continue;
562
0
        case CE_OFFSET + ce1_seac:
563
0
            if (cis.os_count < 5)
564
0
                return_error(gs_error_invalidfont);
565
1.89M
        case cx_endchar:
566
1.89M
            break;
567
39.7M
        }
568
1.89M
        break;
569
39.7M
    }
570
    /*
571
     * Number the hints for hintmask.  We must do this even if we never
572
     * replace hints, because type1_stem# uses the index to set bits in
573
     * active_hints.
574
     */
575
1.89M
    {
576
1.89M
        int i;
577
578
6.06M
        for (i = 0; i < hstem_hints.count; ++i)
579
4.16M
            hstem_hints.data[i].index = i;
580
4.45M
        for (i = 0; i < vstem_hints.count; ++i)
581
2.55M
            vstem_hints.data[i].index = i + hstem_hints.count;
582
1.89M
    }
583
1.89M
    if (replace_hints) {
584
437k
        hintmask_size =
585
437k
            (hstem_hints.count + vstem_hints.count + 7) / 8;
586
437k
        memset(active_hints, 0, hintmask_size);
587
437k
    } else
588
1.46M
        hintmask_size = 0;
589
590
    /* Do a second pass to write the result. */
591
1.89M
    type1_next_init(&cis, pgd, pfont);
592
1.89M
    CLEAR_OP();
593
39.7M
    for (;;) {
594
39.7M
        int c = type1_next(&cis);
595
39.7M
        fixed *csp = (&cis.ostack[cis.os_count]) - 1;
596
39.7M
#define POP(n)\
597
39.7M
  (csp -= (n), cis.os_count -= (n))
598
39.7M
        int i;
599
39.7M
        fixed mx, my;
600
601
39.7M
        if (need_moveto && ((c >= cx_rlineto && c <= cx_rrcurveto) ||
602
12.9M
            c == cx_vhcurveto || c == cx_hvcurveto))
603
0
        {
604
0
            mx = my = 0;
605
0
            need_moveto = false;
606
0
            CHECK_OP();
607
0
            if (first) {
608
0
                if (width_on_stack) {
609
0
                    type2_put_fixed(s, *csp); /* width */
610
                    /* We need to move all the stored numeric values up by
611
                     * one in the stack, eliminating the width, so that later
612
                     * processing when we handle the drswing operator emits the correct
613
                     * values. This is different to the 'move' case below.
614
                     */
615
0
                    cis.os_count--;
616
0
                    for (i = 0; i < cis.os_count; ++i)
617
0
                        cis.ostack[i] = cis.ostack[i+1];
618
0
                }
619
0
                mx += cis.lsb.x + mx0, my += cis.lsb.y + my0;
620
0
                first = false;
621
0
            }
622
0
            CHECK_HINTS_CHANGED();
623
0
            if (mx == 0) {
624
0
                type2_put_fixed(s, my);
625
0
                depth = 1, prev_op = cx_vmoveto;
626
0
            } else if (my == 0) {
627
0
                type2_put_fixed(s, mx);
628
0
                depth = 1, prev_op = cx_hmoveto;
629
0
            } else {
630
0
                type2_put_fixed(s, mx);
631
0
                type2_put_fixed(s, my);
632
0
                depth = 2, prev_op = cx_rmoveto;
633
0
            }
634
0
        }
635
636
39.7M
        switch (c) {
637
0
        default:
638
             /* We used to treat buffer overrun as a simple invalid font, now we assume that
639
             * there is an implicit endchar, this is handled by looking for a specific error.
640
             * Part of bug #693170 where the fonts are invalid (no endchar on some glyphs).
641
             */
642
0
            if (c == gs_error_unknownerror) {
643
0
                type2_put_op(s, cx_endchar);
644
0
                return 0;
645
0
            }
646
0
            if (c < 0)
647
0
                return c;
648
0
            if (c >= CE_OFFSET)
649
0
                return_error(gs_error_rangecheck);
650
            /* The Type 1 use of all other operators is the same in Type 2. */
651
10.8M
        copy:
652
10.8M
            CHECK_OP();
653
10.8M
            CHECK_HINTS_CHANGED();
654
21.1M
        put:
655
88.6M
            for (i = 0; i < cis.os_count; ++i)
656
67.5M
                type2_put_fixed(s, cis.ostack[i]);
657
21.1M
            depth += cis.os_count;
658
21.1M
            prev_op = c;
659
21.1M
            type1_clear(&cis);
660
21.1M
            continue;
661
5.32M
        case cx_hstem:
662
5.32M
            if (cis.os_count < 2)
663
0
                return_error(gs_error_invalidfont);
664
5.32M
            type1_stem1(&cis, &hstem_hints, csp - 1, cis.lsb.y, active_hints);
665
8.99M
        hint:
666
8.99M
            HINTS_CHANGED();
667
8.99M
            type1_clear(&cis);
668
8.99M
            continue;
669
3.66M
        case cx_vstem:
670
3.66M
            if (cis.os_count < 2)
671
0
                return_error(gs_error_invalidfont);
672
3.66M
            type1_stem1(&cis, &vstem_hints, csp - 1, cis.lsb.x, active_hints);
673
3.66M
            goto hint;
674
3.55k
        case CE_OFFSET + ce1_vstem3:
675
3.55k
            if (cis.os_count < 6)
676
0
                return_error(gs_error_invalidfont);
677
3.55k
            type1_stem3(&cis, &vstem_hints, csp - 5, cis.lsb.x, active_hints);
678
3.55k
            goto hint;
679
9
        case CE_OFFSET + ce1_hstem3:
680
9
            if (cis.os_count < 6)
681
0
                return_error(gs_error_invalidfont);
682
9
            type1_stem3(&cis, &hstem_hints, csp - 5, cis.lsb.y, active_hints);
683
9
            goto hint;
684
162
        case CE_OFFSET + ce1_dotsection:
685
162
            if (dotsection_flag == dotsection_out) {
686
90
                memcpy(dot_save_hints, active_hints, hintmask_size);
687
90
                memset(active_hints, 0, hintmask_size);
688
90
                dotsection_flag = dotsection_in;
689
90
            } else {
690
72
                memcpy(active_hints, dot_save_hints, hintmask_size);
691
72
                dotsection_flag = dotsection_out;
692
72
            }
693
162
            HINTS_CHANGED();
694
162
            continue;
695
2.45M
        case c1_closepath:
696
2.45M
            need_moveto = true;
697
2.45M
            continue;
698
1.60k
        case CE_OFFSET + ce1_setcurrentpoint:
699
1.60k
            if (first) {
700
                /*  A workaround for fonts which use ce1_setcurrentpoint
701
                    in an illegal way for shifting a path.
702
                    See t1_hinter__setcurrentpoint for more information. */
703
0
                mx0 = csp[-1], my0 = *csp;
704
0
            }
705
1.60k
            continue;
706
435k
        case cx_vmoveto:
707
435k
            if (cis.os_count < 1)
708
0
                return_error(gs_error_invalidfont);
709
435k
            mx = 0, my = *csp;
710
435k
            POP(1); goto move;
711
125k
        case cx_hmoveto:
712
125k
            if (cis.os_count < 1)
713
0
                return_error(gs_error_invalidfont);
714
125k
            mx = *csp, my = 0;
715
125k
            POP(1); goto move;
716
1.90M
        case cx_rmoveto:
717
1.90M
            if (cis.os_count < 2)
718
0
                return_error(gs_error_invalidfont);
719
1.90M
            mx = csp[-1], my = *csp;
720
1.90M
            POP(2);
721
2.46M
        move:
722
2.46M
            need_moveto = false;
723
2.46M
            CHECK_OP();
724
2.46M
            if (first) {
725
1.75M
                if (cis.os_count)
726
12.1k
                    type2_put_fixed(s, *csp); /* width */
727
1.75M
                mx += cis.lsb.x + mx0, my += cis.lsb.y + my0;
728
1.75M
                first = false;
729
1.75M
            }
730
2.46M
            if (cis.flex_count != flex_max) {
731
                /* We're accumulating points for a flex. */
732
11.2k
                if (type1_next(&cis) != ce1_callothersubr)
733
0
                    return_error(gs_error_rangecheck);
734
11.2k
                csp = &cis.ostack[cis.os_count - 1];
735
11.2k
                if (*csp != int2fixed(2) || csp[-1] != fixed_0)
736
0
                    return_error(gs_error_rangecheck);
737
11.2k
                cis.flex_count++;
738
11.2k
                csp[-1] = mx, *csp = my;
739
11.2k
                continue;
740
11.2k
            }
741
2.46M
            CHECK_HINTS_CHANGED();
742
2.45M
            if (mx == 0) {
743
179k
                type2_put_fixed(s, my);
744
179k
                depth = 1, prev_op = cx_vmoveto;
745
2.27M
            } else if (my == 0) {
746
170k
                type2_put_fixed(s, mx);
747
170k
                depth = 1, prev_op = cx_hmoveto;
748
2.10M
            } else {
749
2.10M
                type2_put_fixed(s, mx);
750
2.10M
                type2_put_fixed(s, my);
751
2.10M
                depth = 2, prev_op = cx_rmoveto;
752
2.10M
            }
753
2.45M
            type1_clear(&cis);
754
2.45M
            continue;
755
1.89M
        case c1_hsbw:
756
1.89M
            if (cis.os_count < 2)
757
0
                return_error(gs_error_invalidfont);
758
1.89M
            gs_type1_sbw(&cis, cis.ostack[0], fixed_0, cis.ostack[1], fixed_0);
759
            /*
760
             * Leave the l.s.b. on the operand stack for the initial hint,
761
             * moveto, or endchar command.
762
             */
763
1.89M
            cis.ostack[0] = cis.ostack[1];
764
1.89M
        sbw:
765
            /* cff_write_Private doesn't write defaultWidthX
766
               when called with the Type 1 font,
767
               so the reader will assume
768
               defaultWidthX = defaultWidthX_DEFAULT
769
               Use the latter here.
770
             */
771
1.89M
            if (cis.ostack[0] == default_defaultWidthX)
772
1.71k
                cis.os_count = 0;
773
1.89M
            else {
774
1.89M
                cis.ostack[0] -= default_defaultWidthX;
775
1.89M
                cis.os_count = 1;
776
1.89M
                width_on_stack = true;
777
1.89M
            }
778
1.89M
            if (hstem_hints.count) {
779
1.72M
                if (cis.os_count)
780
1.72M
                    type2_put_fixed(s, cis.ostack[0]);
781
1.72M
                type2_put_stems(s, cis.os_count, &hstem_hints,
782
1.72M
                                (replace_hints ? c2_hstemhm : cx_hstem));
783
1.72M
                cis.os_count = 0;
784
1.72M
                width_on_stack = false;
785
1.72M
            }
786
1.89M
            if (vstem_hints.count) {
787
1.44M
                if (cis.os_count)
788
16.1k
                    type2_put_fixed(s, cis.ostack[0]);
789
1.44M
                type2_put_stems(s, cis.os_count, &vstem_hints,
790
1.44M
                                (replace_hints ? c2_vstemhm : cx_vstem));
791
1.44M
                cis.os_count = 0;
792
1.44M
                width_on_stack = false;
793
1.44M
            }
794
1.89M
            continue;
795
0
        case CE_OFFSET + ce1_seac:
796
0
            if (cis.os_count < 5)
797
0
                return_error(gs_error_invalidfont);
798
            /*
799
             * It is an undocumented feature of the Type 2 CharString
800
             * format that endchar + 4 or 5 operands is equivalent to
801
             * seac with an implicit asb operand + endchar with 0 or 1
802
             * operands.  Remove the asb argument from the stack, but
803
             * adjust the adx argument to compensate for the fact that
804
             * Type 2 CharStrings don't have any concept of l.s.b.
805
             */
806
0
            csp[-3] += cis.lsb.x - csp[-4];
807
0
            memmove(csp - 4, csp - 3, sizeof(*csp) * 4);
808
0
            POP(1);
809
            /* (falls through) */
810
1.89M
        case cx_endchar:
811
1.89M
            CHECK_OP();
812
2.04M
            for (i = 0; i < cis.os_count; ++i)
813
142k
                type2_put_fixed(s, cis.ostack[i]);
814
1.89M
            type2_put_op(s, cx_endchar);
815
1.89M
            return 0;
816
0
        case CE_OFFSET + ce1_sbw:
817
0
            if (cis.os_count < 4)
818
0
                return_error(gs_error_invalidfont);
819
0
            gs_type1_sbw(&cis, cis.ostack[0], cis.ostack[1],
820
0
                         cis.ostack[2], cis.ostack[3]);
821
0
            cis.ostack[0] = cis.ostack[2];
822
0
            goto sbw;
823
875k
        case ce1_callothersubr:
824
875k
            if (cis.os_count < 2)
825
0
                return_error(gs_error_invalidfont);
826
875k
            CHECK_OP();
827
875k
            switch (fixed2int_var(*csp)) {
828
0
            default:
829
0
                return_error(gs_error_rangecheck);
830
1.60k
            case 0:
831
                /*
832
                 * The operand stack contains: delta to reference point,
833
                 * 6 deltas for the two curves, fd, final point, 3, 0.
834
                 */
835
1.60k
                csp[-18] += csp[-16], csp[-17] += csp[-15];
836
1.60k
                memmove(csp - 16, csp - 14, sizeof(*csp) * 11);
837
1.60k
                cis.os_count -= 6, csp -= 6;
838
                /*
839
                 * We could optimize by using [h]flex[1],
840
                 * but it isn't worth the trouble.
841
                 */
842
1.60k
                c = CE_OFFSET + ce2_flex;
843
1.60k
                cis.flex_count = flex_max; /* not inside flex */
844
1.60k
                cis.ignore_pops = 2;
845
1.60k
                goto copy;
846
1.60k
            case 1:
847
1.60k
                cis.flex_count = 0;
848
1.60k
                cis.os_count -= 2;
849
1.60k
                continue;
850
            /*case 2:*/   /* detected in *moveto */
851
871k
            case 3:
852
871k
                memset(active_hints, 0, hintmask_size);
853
871k
                HINTS_CHANGED();
854
871k
                cis.ignore_pops = 1;
855
871k
                cis.os_count -= 2;
856
871k
                continue;
857
0
            case 12:
858
0
            case 13:
859
                /* Counter control is not implemented. */
860
0
                cis.os_count -= 2 + fixed2int(csp[-1]);
861
0
                continue;
862
875k
            }
863
            /*
864
             * The remaining cases are strictly for optimization.
865
             */
866
2.14M
        case cx_rlineto:
867
2.14M
            if (cis.os_count < 2)
868
0
                return_error(gs_error_invalidfont);
869
2.14M
            if (depth > MAX_STACK - 2)
870
478
                goto copy;
871
2.14M
            switch (prev_op) {
872
516k
            case cx_rlineto:  /* rlineto+ => rlineto */
873
516k
                goto put;
874
220k
            case cx_rrcurveto:  /* rrcurveto+ rlineto => rcurveline */
875
220k
                c = c2_rcurveline;
876
220k
                goto put;
877
1.40M
            default:
878
1.40M
                goto copy;
879
2.14M
            }
880
4.22M
        case cx_hlineto:  /* hlineto (vlineto hlineto)* [vlineto] => hlineto */
881
4.22M
            if (cis.os_count < 1)
882
0
                return_error(gs_error_invalidfont);
883
4.22M
            if (depth > MAX_STACK - 1 ||
884
4.21M
                prev_op != (depth & 1 ? cx_vlineto : cx_hlineto))
885
2.16M
                goto copy;
886
2.06M
            c = prev_op;
887
2.06M
            goto put;
888
3.88M
        case cx_vlineto:  /* vlineto (hlineto vlineto)* [hlineto] => vlineto */
889
3.88M
            if (cis.os_count < 1)
890
0
                return_error(gs_error_invalidfont);
891
3.88M
            if (depth > MAX_STACK - 1 ||
892
3.88M
                prev_op != (depth & 1 ? cx_hlineto : cx_vlineto))
893
1.85M
                goto copy;
894
2.02M
            c = prev_op;
895
2.02M
            goto put;
896
2.12M
        case cx_hvcurveto: /* hvcurveto (vhcurveto hvcurveto)* => hvcurveto */
897
                                /* (vhcurveto hvcurveto)+ => vhcurveto  */
898
2.12M
            if (cis.os_count < 4)
899
0
                return_error(gs_error_invalidfont);
900
            /*
901
             * We have to check (depth & 1) because the last curve might
902
             * have 5 parameters rather than 4 (see rrcurveto below).
903
             */
904
2.12M
            if ((depth & 1) || depth > MAX_STACK - 4 ||
905
1.88M
                prev_op != (depth & 4 ? cx_vhcurveto : cx_hvcurveto))
906
1.46M
                goto copy;
907
660k
            c = prev_op;
908
660k
            goto put;
909
2.26M
        case cx_vhcurveto: /* vhcurveto (hvcurveto vhcurveto)* => vhcurveto */
910
                                /* (hvcurveto vhcurveto)+ => hvcurveto  */
911
2.26M
            if (cis.os_count < 4)
912
0
                return_error(gs_error_invalidfont);
913
            /* See above re the (depth & 1) check. */
914
2.26M
            if ((depth & 1) || depth > MAX_STACK - 4 ||
915
1.88M
                prev_op != (depth & 4 ? cx_hvcurveto : cx_vhcurveto))
916
1.04M
                goto copy;
917
1.21M
            c = prev_op;
918
1.21M
            goto put;
919
6.51M
        case cx_rrcurveto:
920
6.51M
            if (cis.os_count < 6)
921
0
                return_error(gs_error_invalidfont);
922
6.51M
            if (depth == 0) {
923
361k
                if (csp[-1] == 0) {
924
                    /* A|0 B C D 0 F rrcurveto => [A] B C D F vvcurveto */
925
63.7k
                    c = c2_vvcurveto;
926
63.7k
                    csp[-1] = csp[0];
927
63.7k
                    if (csp[-5] == 0) {
928
9
                        memmove(csp - 5, csp - 4, sizeof(*csp) * 4);
929
9
                        POP(2);
930
9
                    } else
931
63.7k
                        POP(1);
932
297k
                } else if (*csp == 0) {
933
                    /* A B|0 C D E 0 rrcurveto => [B] A C D E hhcurveto */
934
151k
                    c = c2_hhcurveto;
935
151k
                    if (csp[-4] == 0) {
936
110
                        memmove(csp - 4, csp - 3, sizeof(*csp) * 3);
937
110
                        POP(2);
938
151k
                    } else {
939
151k
                        *csp = csp[-5], csp[-5] = csp[-4], csp[-4] = *csp;
940
151k
                        POP(1);
941
151k
                    }
942
151k
                }
943
                /*
944
                 * We could also optimize:
945
                 *   0 B C D E F|0 rrcurveto => B C D E [F] vhcurveto
946
                 *   A 0 C D E|0 F rrcurveto => A C D F [E] hvcurveto
947
                 * but this gets in the way of subsequent optimization
948
                 * of multiple rrcurvetos, so we don't do it.
949
                 */
950
361k
                goto copy;
951
361k
            }
952
6.15M
            if (depth > MAX_STACK - 6)
953
2.67k
                goto copy;
954
6.15M
            switch (prev_op) {
955
68.4k
            case c2_hhcurveto:  /* hrcurveto (x1 0 x2 y2 x3 0 rrcurveto)* => */
956
                                /* hhcurveto */
957
68.4k
                if (csp[-4] == 0 && *csp == 0) {
958
0
                    memmove(csp - 4, csp - 3, sizeof(*csp) * 3);
959
0
                    c = prev_op;
960
0
                    POP(2);
961
0
                    goto put;
962
0
                }
963
68.4k
                goto copy;
964
68.4k
            case c2_vvcurveto:  /* rvcurveto (0 y1 x2 y2 0 y3 rrcurveto)* => */
965
                                /* vvcurveto */
966
26.4k
                if (csp[-5] == 0 && csp[-1] == 0) {
967
0
                    memmove(csp - 5, csp - 4, sizeof(*csp) * 3);
968
0
                    csp[-2] = *csp;
969
0
                    c = prev_op;
970
0
                    POP(2);
971
0
                    goto put;
972
0
                }
973
26.4k
                goto copy;
974
890k
            case cx_hvcurveto:
975
890k
                if (depth & 1)
976
214k
                    goto copy;
977
675k
                if (!(depth & 4))
978
343k
                    goto hrc;
979
405k
            vrc:  /* (vhcurveto hvcurveto)+ vrcurveto => vhcurveto */
980
                /* hvcurveto (vhcurveto hvcurveto)* vrcurveto => hvcurveto */
981
405k
                if (csp[-5] != 0)
982
1.13k
                    goto copy;
983
404k
                memmove(csp - 5, csp - 4, sizeof(*csp) * 5);
984
404k
                c = prev_op;
985
404k
                POP(1);
986
404k
                goto put;
987
948k
            case cx_vhcurveto:
988
948k
                if (depth & 1)
989
300k
                    goto copy;
990
648k
                if (!(depth & 4))
991
72.7k
                    goto vrc;
992
918k
            hrc:  /* (hvcurveto vhcurveto)+ hrcurveto => hvcurveto */
993
                /* vhcurveto (hvcurveto vhcurveto)* hrcurveto => vhcurveto */
994
918k
                if (csp[-4] != 0)
995
4.73k
                    goto copy;
996
                /* A 0 C D E F => A C D F E */
997
914k
                memmove(csp - 4, csp - 3, sizeof(*csp) * 2);
998
914k
                csp[-2] = *csp;
999
914k
                c = prev_op;
1000
914k
                POP(1);
1001
914k
                goto put;
1002
377k
            case cx_rlineto:  /* rlineto+ rrcurveto => rlinecurve */
1003
377k
                c = c2_rlinecurve;
1004
377k
                goto put;
1005
1.88M
            case cx_rrcurveto:  /* rrcurveto+ => rrcurveto */
1006
1.88M
                goto put;
1007
1.95M
            default:
1008
1.95M
                goto copy;
1009
6.15M
            }
1010
39.7M
        }
1011
39.7M
    }
1012
1.89M
}