Coverage Report

Created: 2025-08-28 07:06

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