Coverage Report

Created: 2026-04-01 07:17

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.35M
{
63
7.35M
    int skip = pcis->pfont->data.lenIV;
64
7.35M
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
65
7.35M
    const byte *cip = ipsp->cs_data.bits.data;
66
7.35M
    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.35M
    ipsp->ip = cip;
71
7.35M
    ipsp->dstate = state;
72
7.35M
}
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.6M
{
94
69.6M
    pcis->os_count = 0;
95
69.6M
}
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.1M
           (v0 < top[-1].v0 || (v0 == top[-1].v0 && v1 < top[-1].v1))
127
18.0M
           ) {
128
9.62M
        *top = top[-1];
129
9.62M
        top--;
130
9.62M
    }
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.07k
{
150
7.07k
    type1_stem1(pcis, psht, pv3, lsb, active_hints);
151
7.07k
    type1_stem1(pcis, psht, pv3 + 2, lsb, active_hints);
152
7.07k
    type1_stem1(pcis, psht, pv3 + 4, lsb, active_hints);
153
7.07k
}
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.7M
 load:
171
86.7M
    cip = ipsp->ip;
172
86.7M
    cipe = ipsp->cs_data.bits.data + ipsp->cs_data.bits.size;
173
86.7M
    state = ipsp->dstate;
174
286M
    for (;;) {
175
286M
        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
286M
        c0 = *cip++;
183
286M
        charstring_next(c0, state, c, encrypted);
184
286M
        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
28.0k
                long lw;
192
193
28.0k
                decode_num4(lw, cip, state, encrypted);
194
28.0k
                CS_CHECK_PUSH(csp, pcis->ostack);
195
28.0k
                *++csp = int2fixed(lw);
196
28.0k
                if (lw != fixed2long(*csp)) {
197
                    /*
198
                     * The integer was too large to handle in fixed point.
199
                     * Handle this case specially.
200
                     */
201
6
                    code = gs_type1_check_float(&state, encrypted, &cip, csp, lw);
202
6
                    if (code < 0)
203
6
                       return code;
204
6
                }
205
28.0k
            } 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.8M
        default:
227
77.8M
            break;
228
77.8M
        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.7k
            default:
260
10.7k
                c += CE_OFFSET;
261
10.7k
                break;
262
19.0k
            case ce1_div:
263
19.0k
                if (csp + 1 - &pcis->ostack[0] < 1)
264
0
                    return_error(gs_error_invalidfont);
265
19.0k
                csp[-1] = float2fixed((double)csp[-1] / (double)*csp);
266
19.0k
                --csp;
267
19.0k
                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.32k
                case 0:
276
3.32k
                    pcis->ignore_pops = 2;
277
3.32k
                    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
26.5k
                default:
302
26.5k
                    break; /* pass to caller */
303
1.77M
                }
304
1.77M
                break;
305
1.77M
            case ce1_pop:
306
1.74M
                if (pcis->ignore_pops != 0) {
307
1.74M
                    pcis->ignore_pops--;
308
1.74M
                    continue;
309
1.74M
                }
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.7M
}
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.4M
{
328
21.4M
    sputc(s, (byte)(i >> 8));
329
21.4M
    sputc(s, (byte)i);
330
21.4M
}
331
static void
332
sputc4(stream *s, int i)
333
9.46k
{
334
9.46k
    sputc2(s, i >> 16);
335
9.46k
    sputc2(s, i);
336
9.46k
}
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.66k
        spputc(s, cx_escape);
344
1.66k
        spputc(s, (byte)(op - CE_OFFSET));
345
1.66k
    } 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.5M
{
353
87.5M
    if (i >= -107 && i <= 107)
354
66.1M
        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.72M
    else if (i >= -1131 && i < 0)
358
6.71M
        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.5M
}
375
376
/* Put a fixed value on a stream. */
377
static void
378
type2_put_fixed(stream *s, fixed v)
379
87.5M
{
380
87.5M
    if (fixed_is_int(v))
381
87.5M
        type2_put_int(s, fixed2int_var(v));
382
9.46k
    else if (v >= int2fixed(-32768) && v < int2fixed(32768)) {
383
        /* We can represent this as a 16:16 number. */
384
9.46k
        spputc(s, cx_num4);
385
9.46k
        sputc4(s, v << (16 - _fixed_shift));
386
9.46k
    } 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.5M
}
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.2M
#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.87M
  BEGIN\
459
9.87M
    hints_changed = replace_hints;\
460
9.87M
    if (hints_changed)\
461
9.87M
        CHECK_OP();   /* see below */\
462
9.87M
  END
463
1.89M
#define CHECK_HINTS_CHANGED()\
464
15.8M
  BEGIN\
465
15.8M
    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.8M
  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.3M
  BEGIN\
481
28.3M
    if (prev_op >= 0) {\
482
13.3M
        type2_put_op(s, prev_op);\
483
13.3M
        CLEAR_OP();\
484
13.3M
    }\
485
28.3M
  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.1M
        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.1M
           if (c == gs_error_unknownerror)
512
0
                break;
513
26.1M
            if (c < 0)
514
7
                return c;
515
26.1M
            type1_clear(&cis);
516
26.1M
            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.67M
        case cx_vstem:
528
3.67M
            if (cis.os_count < 2)
529
0
                return_error(gs_error_invalidfont);
530
3.67M
            type1_stem1(&cis, &vstem_hints, csp - 1, cis.lsb.x, NULL);
531
3.67M
            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.52k
        case CE_OFFSET + ce1_vstem3:
539
3.52k
            if (cis.os_count < 6)
540
0
                return_error(gs_error_invalidfont);
541
3.52k
            type1_stem3(&cis, &vstem_hints, csp - 5, cis.lsb.x, NULL);
542
3.52k
            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 (fixed2int(csp[-1]) < 0)
556
0
                return_error(gs_error_invalidfont);
557
886k
            if (cis.os_count < 2 + fixed2int(csp[-1]))
558
0
                return_error(gs_error_invalidfont);
559
886k
            if (*csp == int2fixed(12) || *csp == int2fixed(13))
560
0
                cis.os_count -= fixed2int(csp[-1]);
561
886k
            cis.os_count -= 2;
562
886k
            continue;
563
162
        case CE_OFFSET + ce1_dotsection:
564
162
            replace_hints = true;
565
162
            continue;
566
0
        case CE_OFFSET + ce1_seac:
567
0
            if (cis.os_count < 5)
568
0
                return_error(gs_error_invalidfont);
569
1.89M
        case cx_endchar:
570
1.89M
            break;
571
39.7M
        }
572
1.89M
        break;
573
39.7M
    }
574
    /*
575
     * Number the hints for hintmask.  We must do this even if we never
576
     * replace hints, because type1_stem# uses the index to set bits in
577
     * active_hints.
578
     */
579
1.89M
    {
580
1.89M
        int i;
581
582
6.06M
        for (i = 0; i < hstem_hints.count; ++i)
583
4.16M
            hstem_hints.data[i].index = i;
584
4.45M
        for (i = 0; i < vstem_hints.count; ++i)
585
2.55M
            vstem_hints.data[i].index = i + hstem_hints.count;
586
1.89M
    }
587
1.89M
    if (replace_hints) {
588
437k
        hintmask_size =
589
437k
            (hstem_hints.count + vstem_hints.count + 7) / 8;
590
437k
        memset(active_hints, 0, hintmask_size);
591
437k
    } else
592
1.45M
        hintmask_size = 0;
593
594
    /* Do a second pass to write the result. */
595
1.89M
    type1_next_init(&cis, pgd, pfont);
596
1.89M
    CLEAR_OP();
597
39.7M
    for (;;) {
598
39.7M
        int c = type1_next(&cis);
599
39.7M
        fixed *csp = (&cis.ostack[cis.os_count]) - 1;
600
39.7M
#define POP(n)\
601
39.7M
  (csp -= (n), cis.os_count -= (n))
602
39.7M
        int i;
603
39.7M
        fixed mx, my;
604
605
39.7M
        if (need_moveto && ((c >= cx_rlineto && c <= cx_rrcurveto) ||
606
12.9M
            c == cx_vhcurveto || c == cx_hvcurveto))
607
0
        {
608
0
            mx = my = 0;
609
0
            need_moveto = false;
610
0
            CHECK_OP();
611
0
            if (first) {
612
0
                if (width_on_stack) {
613
0
                    if (cis.os_count < 1)
614
0
                        return_error(gs_error_invalidfont);
615
0
                    type2_put_fixed(s, *csp); /* width */
616
                    /* We need to move all the stored numeric values up by
617
                     * one in the stack, eliminating the width, so that later
618
                     * processing when we handle the drswing operator emits the correct
619
                     * values. This is different to the 'move' case below.
620
                     */
621
0
                    cis.os_count--;
622
0
                    for (i = 0; i < cis.os_count; ++i)
623
0
                        cis.ostack[i] = cis.ostack[i+1];
624
0
                }
625
0
                mx += cis.lsb.x + mx0, my += cis.lsb.y + my0;
626
0
                first = false;
627
0
            }
628
0
            CHECK_HINTS_CHANGED();
629
0
            if (mx == 0) {
630
0
                type2_put_fixed(s, my);
631
0
                depth = 1, prev_op = cx_vmoveto;
632
0
            } else if (my == 0) {
633
0
                type2_put_fixed(s, mx);
634
0
                depth = 1, prev_op = cx_hmoveto;
635
0
            } else {
636
0
                type2_put_fixed(s, mx);
637
0
                type2_put_fixed(s, my);
638
0
                depth = 2, prev_op = cx_rmoveto;
639
0
            }
640
0
        }
641
642
39.7M
        switch (c) {
643
0
        default:
644
             /* We used to treat buffer overrun as a simple invalid font, now we assume that
645
             * there is an implicit endchar, this is handled by looking for a specific error.
646
             * Part of bug #693170 where the fonts are invalid (no endchar on some glyphs).
647
             */
648
0
            if (c == gs_error_unknownerror) {
649
0
                type2_put_op(s, cx_endchar);
650
0
                return 0;
651
0
            }
652
0
            if (c < 0)
653
0
                return c;
654
0
            if (c >= CE_OFFSET)
655
0
                return_error(gs_error_rangecheck);
656
            /* The Type 1 use of all other operators is the same in Type 2. */
657
10.8M
        copy:
658
10.8M
            CHECK_OP();
659
10.8M
            CHECK_HINTS_CHANGED();
660
21.1M
        put:
661
88.8M
            for (i = 0; i < cis.os_count; ++i)
662
67.6M
                type2_put_fixed(s, cis.ostack[i]);
663
21.1M
            depth += cis.os_count;
664
21.1M
            prev_op = c;
665
21.1M
            type1_clear(&cis);
666
21.1M
            continue;
667
5.32M
        case cx_hstem:
668
5.32M
            if (cis.os_count < 2)
669
0
                return_error(gs_error_invalidfont);
670
5.32M
            type1_stem1(&cis, &hstem_hints, csp - 1, cis.lsb.y, active_hints);
671
8.99M
        hint:
672
8.99M
            HINTS_CHANGED();
673
8.99M
            type1_clear(&cis);
674
8.99M
            continue;
675
3.67M
        case cx_vstem:
676
3.67M
            if (cis.os_count < 2)
677
0
                return_error(gs_error_invalidfont);
678
3.67M
            type1_stem1(&cis, &vstem_hints, csp - 1, cis.lsb.x, active_hints);
679
3.67M
            goto hint;
680
3.52k
        case CE_OFFSET + ce1_vstem3:
681
3.52k
            if (cis.os_count < 6)
682
0
                return_error(gs_error_invalidfont);
683
3.52k
            type1_stem3(&cis, &vstem_hints, csp - 5, cis.lsb.x, active_hints);
684
3.52k
            goto hint;
685
9
        case CE_OFFSET + ce1_hstem3:
686
9
            if (cis.os_count < 6)
687
0
                return_error(gs_error_invalidfont);
688
9
            type1_stem3(&cis, &hstem_hints, csp - 5, cis.lsb.y, active_hints);
689
9
            goto hint;
690
162
        case CE_OFFSET + ce1_dotsection:
691
162
            if (dotsection_flag == dotsection_out) {
692
90
                memcpy(dot_save_hints, active_hints, hintmask_size);
693
90
                memset(active_hints, 0, hintmask_size);
694
90
                dotsection_flag = dotsection_in;
695
90
            } else {
696
72
                memcpy(active_hints, dot_save_hints, hintmask_size);
697
72
                dotsection_flag = dotsection_out;
698
72
            }
699
162
            HINTS_CHANGED();
700
162
            continue;
701
2.45M
        case c1_closepath:
702
2.45M
            need_moveto = true;
703
2.45M
            continue;
704
1.66k
        case CE_OFFSET + ce1_setcurrentpoint:
705
1.66k
            if (first) {
706
0
                if (cis.os_count < 2)
707
0
                    return_error(gs_error_invalidfont);
708
709
                /*  A workaround for fonts which use ce1_setcurrentpoint
710
                    in an illegal way for shifting a path.
711
                    See t1_hinter__setcurrentpoint for more information. */
712
0
                mx0 = csp[-1], my0 = *csp;
713
0
            }
714
1.66k
            continue;
715
435k
        case cx_vmoveto:
716
435k
            if (cis.os_count < 1)
717
0
                return_error(gs_error_invalidfont);
718
435k
            mx = 0, my = *csp;
719
435k
            POP(1); goto move;
720
125k
        case cx_hmoveto:
721
125k
            if (cis.os_count < 1)
722
0
                return_error(gs_error_invalidfont);
723
125k
            mx = *csp, my = 0;
724
125k
            POP(1); goto move;
725
1.91M
        case cx_rmoveto:
726
1.91M
            if (cis.os_count < 2)
727
0
                return_error(gs_error_invalidfont);
728
1.91M
            mx = csp[-1], my = *csp;
729
1.91M
            POP(2);
730
2.47M
        move:
731
2.47M
            need_moveto = false;
732
2.47M
            CHECK_OP();
733
2.47M
            if (first) {
734
1.75M
                if (cis.os_count)
735
11.7k
                    type2_put_fixed(s, *csp); /* width */
736
1.75M
                mx += cis.lsb.x + mx0, my += cis.lsb.y + my0;
737
1.75M
                first = false;
738
1.75M
            }
739
2.47M
            if (cis.flex_count != flex_max) {
740
                /* We're accumulating points for a flex. */
741
11.6k
                if (type1_next(&cis) != ce1_callothersubr)
742
0
                    return_error(gs_error_rangecheck);
743
11.6k
                csp = &cis.ostack[cis.os_count - 1];
744
11.6k
                if (*csp != int2fixed(2) || csp[-1] != fixed_0)
745
0
                    return_error(gs_error_rangecheck);
746
11.6k
                cis.flex_count++;
747
11.6k
                csp[-1] = mx, *csp = my;
748
11.6k
                continue;
749
11.6k
            }
750
2.47M
            CHECK_HINTS_CHANGED();
751
2.45M
            if (mx == 0) {
752
180k
                type2_put_fixed(s, my);
753
180k
                depth = 1, prev_op = cx_vmoveto;
754
2.27M
            } else if (my == 0) {
755
170k
                type2_put_fixed(s, mx);
756
170k
                depth = 1, prev_op = cx_hmoveto;
757
2.10M
            } else {
758
2.10M
                type2_put_fixed(s, mx);
759
2.10M
                type2_put_fixed(s, my);
760
2.10M
                depth = 2, prev_op = cx_rmoveto;
761
2.10M
            }
762
2.45M
            type1_clear(&cis);
763
2.45M
            continue;
764
1.89M
        case c1_hsbw:
765
1.89M
            if (cis.os_count < 2)
766
0
                return_error(gs_error_invalidfont);
767
1.89M
            gs_type1_sbw(&cis, cis.ostack[0], fixed_0, cis.ostack[1], fixed_0);
768
            /*
769
             * Leave the l.s.b. on the operand stack for the initial hint,
770
             * moveto, or endchar command.
771
             */
772
1.89M
            cis.ostack[0] = cis.ostack[1];
773
1.89M
        sbw:
774
            /* cff_write_Private doesn't write defaultWidthX
775
               when called with the Type 1 font,
776
               so the reader will assume
777
               defaultWidthX = defaultWidthX_DEFAULT
778
               Use the latter here.
779
             */
780
1.89M
            if (cis.ostack[0] == default_defaultWidthX)
781
1.73k
                cis.os_count = 0;
782
1.89M
            else {
783
1.89M
                cis.ostack[0] -= default_defaultWidthX;
784
1.89M
                cis.os_count = 1;
785
1.89M
                width_on_stack = true;
786
1.89M
            }
787
1.89M
            if (hstem_hints.count) {
788
1.72M
                if (cis.os_count)
789
1.72M
                    type2_put_fixed(s, cis.ostack[0]);
790
1.72M
                type2_put_stems(s, cis.os_count, &hstem_hints,
791
1.72M
                                (replace_hints ? c2_hstemhm : cx_hstem));
792
1.72M
                cis.os_count = 0;
793
1.72M
                width_on_stack = false;
794
1.72M
            }
795
1.89M
            if (vstem_hints.count) {
796
1.44M
                if (cis.os_count)
797
16.2k
                    type2_put_fixed(s, cis.ostack[0]);
798
1.44M
                type2_put_stems(s, cis.os_count, &vstem_hints,
799
1.44M
                                (replace_hints ? c2_vstemhm : cx_vstem));
800
1.44M
                cis.os_count = 0;
801
1.44M
                width_on_stack = false;
802
1.44M
            }
803
1.89M
            continue;
804
0
        case CE_OFFSET + ce1_seac:
805
0
            if (cis.os_count < 5)
806
0
                return_error(gs_error_invalidfont);
807
            /*
808
             * It is an undocumented feature of the Type 2 CharString
809
             * format that endchar + 4 or 5 operands is equivalent to
810
             * seac with an implicit asb operand + endchar with 0 or 1
811
             * operands.  Remove the asb argument from the stack, but
812
             * adjust the adx argument to compensate for the fact that
813
             * Type 2 CharStrings don't have any concept of l.s.b.
814
             */
815
0
            csp[-3] += cis.lsb.x - csp[-4];
816
0
            memmove(csp - 4, csp - 3, sizeof(*csp) * 4);
817
0
            POP(1);
818
            /* (falls through) */
819
1.89M
        case cx_endchar:
820
1.89M
            CHECK_OP();
821
2.03M
            for (i = 0; i < cis.os_count; ++i)
822
140k
                type2_put_fixed(s, cis.ostack[i]);
823
1.89M
            type2_put_op(s, cx_endchar);
824
1.89M
            return 0;
825
0
        case CE_OFFSET + ce1_sbw:
826
0
            if (cis.os_count < 4)
827
0
                return_error(gs_error_invalidfont);
828
0
            gs_type1_sbw(&cis, cis.ostack[0], cis.ostack[1],
829
0
                         cis.ostack[2], cis.ostack[3]);
830
0
            cis.ostack[0] = cis.ostack[2];
831
0
            goto sbw;
832
874k
        case ce1_callothersubr:
833
874k
            if (cis.os_count < 2)
834
0
                return_error(gs_error_invalidfont);
835
874k
            CHECK_OP();
836
874k
            switch (fixed2int_var(*csp)) {
837
0
            default:
838
0
                return_error(gs_error_rangecheck);
839
1.66k
            case 0:
840
                /*
841
                 * The operand stack contains: delta to reference point,
842
                 * 6 deltas for the two curves, fd, final point, 3, 0.
843
                 */
844
1.66k
                csp[-18] += csp[-16], csp[-17] += csp[-15];
845
1.66k
                memmove(csp - 16, csp - 14, sizeof(*csp) * 11);
846
1.66k
                cis.os_count -= 6, csp -= 6;
847
                /*
848
                 * We could optimize by using [h]flex[1],
849
                 * but it isn't worth the trouble.
850
                 */
851
1.66k
                c = CE_OFFSET + ce2_flex;
852
1.66k
                cis.flex_count = flex_max; /* not inside flex */
853
1.66k
                cis.ignore_pops = 2;
854
1.66k
                goto copy;
855
1.66k
            case 1:
856
1.66k
                cis.flex_count = 0;
857
1.66k
                cis.os_count -= 2;
858
1.66k
                continue;
859
            /*case 2:*/   /* detected in *moveto */
860
871k
            case 3:
861
871k
                memset(active_hints, 0, hintmask_size);
862
871k
                HINTS_CHANGED();
863
871k
                cis.ignore_pops = 1;
864
871k
                cis.os_count -= 2;
865
871k
                continue;
866
0
            case 12:
867
0
            case 13:
868
                /* Counter control is not implemented. */
869
0
                if (fixed2int(csp[-1]) < 0)
870
0
                    return_error(gs_error_invalidfont);
871
0
                if (cis.os_count < 2 + fixed2int(csp[-1]))
872
0
                    return_error(gs_error_invalidfont);
873
0
                cis.os_count -= 2 + fixed2int(csp[-1]);
874
0
                continue;
875
874k
            }
876
            /*
877
             * The remaining cases are strictly for optimization.
878
             */
879
2.14M
        case cx_rlineto:
880
2.14M
            if (cis.os_count < 2)
881
0
                return_error(gs_error_invalidfont);
882
2.14M
            if (depth > MAX_STACK - 2)
883
505
                goto copy;
884
2.14M
            switch (prev_op) {
885
513k
            case cx_rlineto:  /* rlineto+ => rlineto */
886
513k
                goto put;
887
219k
            case cx_rrcurveto:  /* rrcurveto+ rlineto => rcurveline */
888
219k
                c = c2_rcurveline;
889
219k
                goto put;
890
1.41M
            default:
891
1.41M
                goto copy;
892
2.14M
            }
893
4.22M
        case cx_hlineto:  /* hlineto (vlineto hlineto)* [vlineto] => hlineto */
894
4.22M
            if (cis.os_count < 1)
895
0
                return_error(gs_error_invalidfont);
896
4.22M
            if (depth > MAX_STACK - 1 ||
897
4.22M
                prev_op != (depth & 1 ? cx_vlineto : cx_hlineto))
898
2.16M
                goto copy;
899
2.05M
            c = prev_op;
900
2.05M
            goto put;
901
3.88M
        case cx_vlineto:  /* vlineto (hlineto vlineto)* [hlineto] => vlineto */
902
3.88M
            if (cis.os_count < 1)
903
0
                return_error(gs_error_invalidfont);
904
3.88M
            if (depth > MAX_STACK - 1 ||
905
3.88M
                prev_op != (depth & 1 ? cx_hlineto : cx_vlineto))
906
1.86M
                goto copy;
907
2.02M
            c = prev_op;
908
2.02M
            goto put;
909
2.12M
        case cx_hvcurveto: /* hvcurveto (vhcurveto hvcurveto)* => hvcurveto */
910
                                /* (vhcurveto hvcurveto)+ => vhcurveto  */
911
2.12M
            if (cis.os_count < 4)
912
0
                return_error(gs_error_invalidfont);
913
            /*
914
             * We have to check (depth & 1) because the last curve might
915
             * have 5 parameters rather than 4 (see rrcurveto below).
916
             */
917
2.12M
            if ((depth & 1) || depth > MAX_STACK - 4 ||
918
1.88M
                prev_op != (depth & 4 ? cx_vhcurveto : cx_hvcurveto))
919
1.46M
                goto copy;
920
662k
            c = prev_op;
921
662k
            goto put;
922
2.26M
        case cx_vhcurveto: /* vhcurveto (hvcurveto vhcurveto)* => vhcurveto */
923
                                /* (hvcurveto vhcurveto)+ => hvcurveto  */
924
2.26M
            if (cis.os_count < 4)
925
0
                return_error(gs_error_invalidfont);
926
            /* See above re the (depth & 1) check. */
927
2.26M
            if ((depth & 1) || depth > MAX_STACK - 4 ||
928
1.89M
                prev_op != (depth & 4 ? cx_hvcurveto : cx_vhcurveto))
929
1.05M
                goto copy;
930
1.21M
            c = prev_op;
931
1.21M
            goto put;
932
6.53M
        case cx_rrcurveto:
933
6.53M
            if (cis.os_count < 6)
934
0
                return_error(gs_error_invalidfont);
935
6.53M
            if (depth == 0) {
936
360k
                if (csp[-1] == 0) {
937
                    /* A|0 B C D 0 F rrcurveto => [A] B C D F vvcurveto */
938
63.6k
                    c = c2_vvcurveto;
939
63.6k
                    csp[-1] = csp[0];
940
63.6k
                    if (csp[-5] == 0) {
941
9
                        memmove(csp - 5, csp - 4, sizeof(*csp) * 4);
942
9
                        POP(2);
943
9
                    } else
944
63.6k
                        POP(1);
945
296k
                } else if (*csp == 0) {
946
                    /* A B|0 C D E 0 rrcurveto => [B] A C D E hhcurveto */
947
151k
                    c = c2_hhcurveto;
948
151k
                    if (csp[-4] == 0) {
949
110
                        memmove(csp - 4, csp - 3, sizeof(*csp) * 3);
950
110
                        POP(2);
951
151k
                    } else {
952
151k
                        *csp = csp[-5], csp[-5] = csp[-4], csp[-4] = *csp;
953
151k
                        POP(1);
954
151k
                    }
955
151k
                }
956
                /*
957
                 * We could also optimize:
958
                 *   0 B C D E F|0 rrcurveto => B C D E [F] vhcurveto
959
                 *   A 0 C D E|0 F rrcurveto => A C D F [E] hvcurveto
960
                 * but this gets in the way of subsequent optimization
961
                 * of multiple rrcurvetos, so we don't do it.
962
                 */
963
360k
                goto copy;
964
360k
            }
965
6.17M
            if (depth > MAX_STACK - 6)
966
2.60k
                goto copy;
967
6.16M
            switch (prev_op) {
968
67.1k
            case c2_hhcurveto:  /* hrcurveto (x1 0 x2 y2 x3 0 rrcurveto)* => */
969
                                /* hhcurveto */
970
67.1k
                if (csp[-4] == 0 && *csp == 0) {
971
0
                    memmove(csp - 4, csp - 3, sizeof(*csp) * 3);
972
0
                    c = prev_op;
973
0
                    POP(2);
974
0
                    goto put;
975
0
                }
976
67.1k
                goto copy;
977
67.1k
            case c2_vvcurveto:  /* rvcurveto (0 y1 x2 y2 0 y3 rrcurveto)* => */
978
                                /* vvcurveto */
979
26.2k
                if (csp[-5] == 0 && csp[-1] == 0) {
980
0
                    memmove(csp - 5, csp - 4, sizeof(*csp) * 3);
981
0
                    csp[-2] = *csp;
982
0
                    c = prev_op;
983
0
                    POP(2);
984
0
                    goto put;
985
0
                }
986
26.2k
                goto copy;
987
894k
            case cx_hvcurveto:
988
894k
                if (depth & 1)
989
217k
                    goto copy;
990
677k
                if (!(depth & 4))
991
342k
                    goto hrc;
992
407k
            vrc:  /* (vhcurveto hvcurveto)+ vrcurveto => vhcurveto */
993
                /* hvcurveto (vhcurveto hvcurveto)* vrcurveto => hvcurveto */
994
407k
                if (csp[-5] != 0)
995
1.24k
                    goto copy;
996
406k
                memmove(csp - 5, csp - 4, sizeof(*csp) * 5);
997
406k
                c = prev_op;
998
406k
                POP(1);
999
406k
                goto put;
1000
952k
            case cx_vhcurveto:
1001
952k
                if (depth & 1)
1002
301k
                    goto copy;
1003
650k
                if (!(depth & 4))
1004
72.9k
                    goto vrc;
1005
920k
            hrc:  /* (hvcurveto vhcurveto)+ hrcurveto => hvcurveto */
1006
                /* vhcurveto (hvcurveto vhcurveto)* hrcurveto => vhcurveto */
1007
920k
                if (csp[-4] != 0)
1008
4.87k
                    goto copy;
1009
                /* A 0 C D E F => A C D F E */
1010
915k
                memmove(csp - 4, csp - 3, sizeof(*csp) * 2);
1011
915k
                csp[-2] = *csp;
1012
915k
                c = prev_op;
1013
915k
                POP(1);
1014
915k
                goto put;
1015
376k
            case cx_rlineto:  /* rlineto+ rrcurveto => rlinecurve */
1016
376k
                c = c2_rlinecurve;
1017
376k
                goto put;
1018
1.89M
            case cx_rrcurveto:  /* rrcurveto+ => rrcurveto */
1019
1.89M
                goto put;
1020
1.96M
            default:
1021
1.96M
                goto copy;
1022
6.16M
            }
1023
39.7M
        }
1024
39.7M
    }
1025
1.89M
}