~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to psi/zupath.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: zupath.c 11094 2010-04-21 15:08:47Z robin $ */
 
14
/* $Id$ */
15
15
/* Operators related to user paths */
16
16
#include "ghost.h"
17
17
#include "oper.h"
117
117
    gx_device hdev;
118
118
 
119
119
    if (code < 0)
120
 
        return code;
 
120
        return code;
121
121
    if ((spop = upath_stroke(i_ctx_p, &mat, false)) < 0) {
122
 
        gs_grestore(igs);
123
 
        return spop;
 
122
        gs_grestore(igs);
 
123
        return spop;
124
124
    }
125
125
    if ((npop = in_path(op - spop, i_ctx_p, &hdev)) < 0) {
126
 
        gs_grestore(igs);
127
 
        return npop;
 
126
        gs_grestore(igs);
 
127
        return npop;
128
128
    }
129
129
    if (npop > 1)               /* matrix was supplied */
130
 
        code = gs_concat(igs, &mat);
 
130
        code = gs_concat(igs, &mat);
131
131
    if (code >= 0)
132
 
        code = gs_stroke(igs);
 
132
        code = gs_stroke(igs);
133
133
    return in_upath_result(i_ctx_p, npop + spop, code);
134
134
}
135
135
 
145
145
    int code;
146
146
 
147
147
    if (npop < 0)
148
 
        return npop;
 
148
        return npop;
149
149
    code = (*paintproc)(igs);
150
150
    return in_path_result(i_ctx_p, npop, code);
151
151
}
159
159
    double uxy[2];
160
160
 
161
161
    if (code < 0)
162
 
        return code;
 
162
        return code;
163
163
    code = num_params(oppath, 2, uxy);
164
164
    if (code >= 0) {            /* Aperture is a single pixel. */
165
 
        gs_point dxy;
166
 
        gs_fixed_rect fr;
 
165
        gs_point dxy;
 
166
        gs_fixed_rect fr;
167
167
 
168
 
        gs_transform(igs, uxy[0], uxy[1], &dxy);
169
 
        fr.p.x = fixed_floor(float2fixed(dxy.x));
170
 
        fr.p.y = fixed_floor(float2fixed(dxy.y));
171
 
        fr.q.x = fr.p.x + fixed_1;
172
 
        fr.q.y = fr.p.y + fixed_1;
173
 
        code = gx_clip_to_rectangle(igs, &fr);
174
 
        npop = 2;
 
168
        gs_transform(igs, uxy[0], uxy[1], &dxy);
 
169
        fr.p.x = fixed_floor(float2fixed(dxy.x));
 
170
        fr.p.y = fixed_floor(float2fixed(dxy.y));
 
171
        fr.q.x = fr.p.x + fixed_1;
 
172
        fr.q.y = fr.p.y + fixed_1;
 
173
        code = gx_clip_to_rectangle(igs, &fr);
 
174
        npop = 2;
175
175
    } else if (code == e_stackunderflow) {
176
 
        /* If 0 elements, definitely a stackunderflow; otherwise, */
177
 
        /* only 1 number, also a stackunderflow. */
178
 
        npop = code;
 
176
        /* If 0 elements, definitely a stackunderflow; otherwise, */
 
177
        /* only 1 number, also a stackunderflow. */
 
178
        npop = code;
179
179
    } else {                    /* Aperture is a user path. */
180
 
        /* We have to set the clipping path without disturbing */
181
 
        /* the current path. */
182
 
        gx_path *ipath = igs->path;
183
 
        gx_path save;
 
180
        /* We have to set the clipping path without disturbing */
 
181
        /* the current path. */
 
182
        gx_path *ipath = igs->path;
 
183
        gx_path save;
184
184
 
185
 
        gx_path_init_local(&save, imemory);
186
 
        gx_path_assign_preserve(&save, ipath);
187
 
        gs_newpath(igs);
188
 
        code = upath_append(oppath, i_ctx_p, false);
189
 
        if (code >= 0)
190
 
            code = gx_clip_to_path(igs);
191
 
        gx_path_assign_free(igs->path, &save);
192
 
        npop = 1;
 
185
        gx_path_init_local(&save, imemory);
 
186
        gx_path_assign_preserve(&save, ipath);
 
187
        gs_newpath(igs);
 
188
        code = upath_append(oppath, i_ctx_p, false);
 
189
        if (code >= 0)
 
190
            code = gx_clip_to_path(igs);
 
191
        gx_path_assign_free(igs->path, &save);
 
192
        npop = 1;
193
193
    }
194
194
    if (code < 0) {
195
 
        gs_grestore(igs);
196
 
        return code;
 
195
        gs_grestore(igs);
 
196
        return code;
197
197
    }
198
198
    /* Install the hit detection device. */
199
199
    gx_set_device_color_1(igs);
200
200
    gx_device_init((gx_device *) phdev, (const gx_device *)&gs_hit_device,
201
 
                   NULL, true);
 
201
                   NULL, true);
202
202
    phdev->width = phdev->height = max_int;
203
203
    gx_device_fill_in_procs(phdev);
204
204
    gx_set_device_only(igs, phdev);
214
214
 
215
215
    gs_grestore(igs);           /* matches gsave in in_path */
216
216
    if (code == gs_hit_detected)
217
 
        result = true;
 
217
        result = true;
218
218
    else if (code == 0)         /* completed painting without a hit */
219
 
        result = false;
 
219
        result = false;
220
220
    else                        /* error */
221
 
        return code;
 
221
        return code;
222
222
    npop--;
223
223
    pop(npop);
224
224
    op -= npop;
236
236
    int code;
237
237
 
238
238
    if (npop < 0)
239
 
        return npop;
 
239
        return npop;
240
240
    code = (*paintproc)(igs);
241
241
    return in_upath_result(i_ctx_p, npop, code);
242
242
}
251
251
    int npop;
252
252
 
253
253
    if (code < 0)
254
 
        return code;
 
254
        return code;
255
255
    if ((code = upath_append(op, i_ctx_p, false)) < 0 ||
256
 
        (code = npop = in_path(op - 1, i_ctx_p, phdev)) < 0
257
 
        ) {
258
 
        gs_grestore(igs);
259
 
        return code;
 
256
        (code = npop = in_path(op - 1, i_ctx_p, phdev)) < 0
 
257
        ) {
 
258
        gs_grestore(igs);
 
259
        return code;
260
260
    }
261
261
    return npop + 1;
262
262
}
346
346
    int code = gs_gsave(igs);
347
347
 
348
348
    if (code < 0)
349
 
        return code;
 
349
        return code;
350
350
    if ((code = upath_append(op, i_ctx_p, false)) >= 0)
351
 
        code = gs_upmergepath(igs);
 
351
        code = gs_upmergepath(igs);
352
352
    gs_grestore(igs);
353
353
    if (code < 0)
354
 
        return code;
 
354
        return code;
355
355
    pop(1);
356
356
    return 0;
357
357
}
364
364
    int code = gs_gsave(igs);
365
365
 
366
366
    if (code < 0)
367
 
        return code;
 
367
        return code;
368
368
    if ((code = upath_append(op, i_ctx_p, gs_currentcpsimode(imemory))) >= 0)
369
 
        code = gs_eofill(igs);
 
369
        code = gs_eofill(igs);
370
370
    gs_grestore(igs);
371
371
    if (code < 0)
372
 
        return code;
 
372
        return code;
373
373
    pop(1);
374
374
    return 0;
375
375
}
382
382
    int code = gs_gsave(igs);
383
383
 
384
384
    if (code < 0)
385
 
        return code;
 
385
        return code;
386
386
    if ((code = upath_append(op, i_ctx_p, gs_currentcpsimode(imemory))) >= 0)
387
 
        code = gs_fill(igs);
 
387
        code = gs_fill(igs);
388
388
    gs_grestore(igs);
389
389
    if (code < 0)
390
 
        return code;
 
390
        return code;
391
391
    pop(1);
392
392
    return 0;
393
393
}
401
401
    int npop;
402
402
 
403
403
    if (code < 0)
404
 
        return code;
 
404
        return code;
405
405
    if ((code = npop = upath_stroke(i_ctx_p, NULL, gs_currentcpsimode(imemory))) >= 0)
406
 
        code = gs_stroke(igs);
 
406
        code = gs_stroke(igs);
407
407
    gs_grestore(igs);
408
408
    if (code < 0)
409
 
        return code;
 
409
        return code;
410
410
    pop(npop);
411
411
    return 0;
412
412
}
421
421
    int npop, code = gs_currentmatrix(igs, &saved_matrix);
422
422
 
423
423
    if (code < 0)
424
 
        return code;
 
424
        return code;
425
425
    /* Save and reset the path. */
426
426
    gx_path_init_local(&save, imemory);
427
427
    gx_path_assign_preserve(&save, igs->path);
428
428
    if ((code = npop = upath_stroke(i_ctx_p, NULL, false)) < 0 ||
429
 
        (code = gs_strokepath(igs)) < 0
430
 
        ) {
431
 
        gx_path_assign_free(igs->path, &save);
432
 
        return code;
 
429
        (code = gs_strokepath(igs)) < 0
 
430
        ) {
 
431
        gx_path_assign_free(igs->path, &save);
 
432
        return code;
433
433
    }
434
434
    /*
435
435
     * If a matrix was specified then restore the previous matrix.
436
436
     */
437
437
    if (npop > 1) {
438
438
        if ((code = gs_setmatrix(igs, &saved_matrix)) < 0) {
439
 
            gx_path_assign_free(igs->path, &save);
440
 
            return code;
 
439
            gx_path_assign_free(igs->path, &save);
 
440
            return code;
441
441
        }
442
442
    }
443
443
    gx_path_free(&save, "ustrokepath");
449
449
/* We do all the work in a procedure that is also used to construct */
450
450
/* the UnpaintedPath user path for ImageType 2 images. */
451
451
int make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
452
 
               bool with_ucache);
 
452
               bool with_ucache);
453
453
static int
454
454
zupath(i_ctx_t *i_ctx_p)
455
455
{
460
460
}
461
461
 
462
462
/* Compute the path length for user path purposes. */
463
 
static int 
 
463
static int
464
464
path_length_for_upath(const gx_path *ppath)
465
465
{
466
466
    gs_path_enum penum;
469
469
 
470
470
    gx_path_enum_init(&penum, ppath);
471
471
    while ((op = gx_path_enum_next(&penum, pts)) != 0) {
472
 
        switch (op) {
473
 
            case gs_pe_moveto:
474
 
            case gs_pe_lineto:
475
 
                size += 3;
476
 
                continue;
477
 
            case gs_pe_curveto:
478
 
                size += 7;
479
 
                continue;
480
 
            case gs_pe_closepath:
481
 
                size += 1;
482
 
                continue;
483
 
            default:
484
 
                return_error(e_unregistered);
485
 
        }
 
472
        switch (op) {
 
473
            case gs_pe_moveto:
 
474
            case gs_pe_lineto:
 
475
                size += 3;
 
476
                continue;
 
477
            case gs_pe_curveto:
 
478
                size += 7;
 
479
                continue;
 
480
            case gs_pe_closepath:
 
481
                size += 1;
 
482
                continue;
 
483
            default:
 
484
                return_error(e_unregistered);
 
485
        }
486
486
    }
487
487
    return size;
488
488
}
489
489
 
490
490
int
491
491
make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
492
 
           bool with_ucache)
 
492
           bool with_ucache)
493
493
{
494
494
    int size = (with_ucache ? 6 : 5);
495
495
    gs_path_enum penum;
498
498
    ref *next;
499
499
    int code;
500
500
 
501
 
 
502
501
    /* Compute the bounding box. */
503
502
    if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
504
 
        /*
505
 
         * Note: Adobe throws 'nocurrentpoint' error, but the PLRM does
506
 
         * not list this as a possible error from 'upath', so if we are
507
 
         * not in CPSI compatibility mode, we set a reasonable default
508
 
         * bbox instead.
509
 
         */
510
 
        if (code != e_nocurrentpoint || gs_currentcpsimode(imemory))
511
 
            return code;
512
 
        bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
 
503
        /*
 
504
         * Note: Adobe throws 'nocurrentpoint' error, but the PLRM does
 
505
         * not list this as a possible error from 'upath', so if we are
 
506
         * not in CPSI compatibility mode, we set a reasonable default
 
507
         * bbox instead.
 
508
         */
 
509
        if (code != e_nocurrentpoint || gs_currentcpsimode(imemory))
 
510
            return code;
 
511
        bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
513
512
    }
514
513
 
515
514
    code = path_length_for_upath(ppath);
520
519
        return_error(e_limitcheck);
521
520
 
522
521
    code = ialloc_ref_array(rupath, a_all | a_executable, size,
523
 
                            "make_upath");
 
522
                            "make_upath");
524
523
    if (code < 0)
525
 
        return code;
 
524
        return code;
526
525
    /* Construct the path. */
527
526
    next = rupath->value.refs;
528
527
    if (with_ucache) {
529
528
        if ((code = name_enter_string(pgs->memory, "ucache", next)) < 0)
530
 
            return code;
531
 
        r_set_attrs(next, a_executable | l_new);
532
 
        ++next;
 
529
            return code;
 
530
        r_set_attrs(next, a_executable | l_new);
 
531
        ++next;
533
532
    }
534
533
    make_real_new(next, bbox.p.x);
535
534
    make_real_new(next + 1, bbox.p.y);
537
536
    make_real_new(next + 3, bbox.q.y);
538
537
    next += 4;
539
538
    if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
540
 
        return code;
 
539
        return code;
541
540
    r_set_attrs(next, a_executable | l_new);
542
541
    ++next;
543
542
    {
544
 
        gs_point pts[3];
545
 
 
546
 
        /* Patch the path in the gstate to set up the enumerator. */
547
 
        gx_path *save_path = pgs->path;
548
 
 
549
 
        pgs->path = ppath;
550
 
        gs_path_enum_copy_init(&penum, pgs, false);
551
 
        pgs->path = save_path;
552
 
        while ((op = gs_path_enum_next(&penum, pts)) != 0) {
553
 
            const char *opstr;
554
 
 
555
 
            switch (op) {
556
 
                case gs_pe_moveto:
557
 
                    opstr = "moveto";
558
 
                    goto ml;
559
 
                case gs_pe_lineto:
560
 
                    opstr = "lineto";
561
 
                  ml:make_real_new(next, pts[0].x);
562
 
                    make_real_new(next + 1, pts[0].y);
563
 
                    next += 2;
564
 
                    break;
565
 
                case gs_pe_curveto:
566
 
                    opstr = "curveto";
567
 
                    make_real_new(next, pts[0].x);
568
 
                    make_real_new(next + 1, pts[0].y);
569
 
                    make_real_new(next + 2, pts[1].x);
570
 
                    make_real_new(next + 3, pts[1].y);
571
 
                    make_real_new(next + 4, pts[2].x);
572
 
                    make_real_new(next + 5, pts[2].y);
573
 
                    next += 6;
574
 
                    break;
575
 
                case gs_pe_closepath:
576
 
                    opstr = "closepath";
577
 
                    break;
578
 
                default:
579
 
                    return_error(e_unregistered);
580
 
            }
581
 
            if ((code = name_enter_string(pgs->memory, opstr, next)) < 0)
582
 
                return code;
583
 
            r_set_attrs(next, a_executable);
584
 
            ++next;
585
 
        }
 
543
        gs_point pts[3];
 
544
 
 
545
        /* Patch the path in the gstate to set up the enumerator. */
 
546
        gx_path *save_path = pgs->path;
 
547
 
 
548
        pgs->path = ppath;
 
549
        gs_path_enum_copy_init(&penum, pgs, false);
 
550
        pgs->path = save_path;
 
551
        while ((op = gs_path_enum_next(&penum, pts)) != 0) {
 
552
            const char *opstr;
 
553
 
 
554
            switch (op) {
 
555
                case gs_pe_moveto:
 
556
                    opstr = "moveto";
 
557
                    goto ml;
 
558
                case gs_pe_lineto:
 
559
                    opstr = "lineto";
 
560
                  ml:make_real_new(next, pts[0].x);
 
561
                    make_real_new(next + 1, pts[0].y);
 
562
                    next += 2;
 
563
                    break;
 
564
                case gs_pe_curveto:
 
565
                    opstr = "curveto";
 
566
                    make_real_new(next, pts[0].x);
 
567
                    make_real_new(next + 1, pts[0].y);
 
568
                    make_real_new(next + 2, pts[1].x);
 
569
                    make_real_new(next + 3, pts[1].y);
 
570
                    make_real_new(next + 4, pts[2].x);
 
571
                    make_real_new(next + 5, pts[2].y);
 
572
                    next += 6;
 
573
                    break;
 
574
                case gs_pe_closepath:
 
575
                    opstr = "closepath";
 
576
                    break;
 
577
                default:
 
578
                    return_error(e_unregistered);
 
579
            }
 
580
            if ((code = name_enter_string(pgs->memory, opstr, next)) < 0)
 
581
                return code;
 
582
            r_set_attrs(next, a_executable);
 
583
            ++next;
 
584
        }
586
585
    }
587
586
    return 0;
588
587
}
589
588
 
590
 
 
591
589
static int
592
590
zgetpath(i_ctx_t *i_ctx_p)
593
591
{
607
605
        return 0;
608
606
 
609
607
    if (dict_find_string(systemdict, "moveto", &operators[1]) <= 0 ||
610
 
        dict_find_string(systemdict, "lineto", &operators[2]) <= 0 ||
611
 
        dict_find_string(systemdict, "curveto", &operators[3]) <= 0 ||
612
 
        dict_find_string(systemdict, "closepath", &operators[4]) <= 0)
 
608
        dict_find_string(systemdict, "lineto", &operators[2]) <= 0 ||
 
609
        dict_find_string(systemdict, "curveto", &operators[3]) <= 0 ||
 
610
        dict_find_string(systemdict, "closepath", &operators[4]) <= 0)
613
611
          return_error(e_undefined);
614
612
 
615
613
    main_ref = op->value.refs;
624
622
        int pe, j, k;
625
623
        gs_path_enum penum;
626
624
        static const int oper_count[5] = { 0, 2, 2, 6, 0 };
627
 
        gs_point pts[3];
628
 
        const double  *fts[6]; 
 
625
        gs_point pts[3];
 
626
        const double  *fts[6];
629
627
 
630
628
        fts[0] = &pts[0].x;
631
629
        fts[1] = &pts[0].y;
635
633
        fts[5] = &pts[2].y;
636
634
 
637
635
        main_ref = op->value.refs;
638
 
        gs_path_enum_copy_init(&penum, igs, false);
 
636
        gs_path_enum_copy_init(&penum, igs, false);
639
637
        pe = gs_path_enum_next(&penum, pts);
640
638
        if (pe < 0)
641
639
            return pe;
644
642
        for (i = 0; i < leaf_count; i++) {
645
643
            int leaf_size = ( i == leaf_count - 1) ? path_size - i * max_array_size : max_array_size;
646
644
            ref *leaf_ref = main_ref[i].value.refs;
647
 
            
 
645
 
648
646
            for (j = 0; j < leaf_size; j++) {
649
647
                if (k < oper_count[pe])
650
648
                   make_real_new(&leaf_ref[j], (float)*fts[k++]);
673
671
    ref opcodes;
674
672
 
675
673
    if (r_has_type(oppath, t__invalid))
676
 
        return_error(e_stackunderflow);
 
674
        return_error(e_stackunderflow);
677
675
    if (!r_is_array(oppath))
678
 
        return_error(e_typecheck);
 
676
        return_error(e_typecheck);
679
677
    check_read(*oppath);
680
678
    gs_newpath(igs);
681
679
    /****** ROUND tx AND ty ******/
682
 
    
 
680
 
683
681
    if ( r_size(oppath) == 2 &&
684
 
         array_get(imemory, oppath, 1, &opcodes) >= 0 &&
 
682
         array_get(imemory, oppath, 1, &opcodes) >= 0 &&
685
683
         r_has_type(&opcodes, t_string)
686
 
        ) {                     /* 1st element is operands, 2nd is operators */
687
 
        ref operands;
688
 
        int code, format;
689
 
        int repcount = 1;
690
 
        const byte *opp;
691
 
        uint ocount, i = 0;
 
684
        ) {                     /* 1st element is operands, 2nd is operators */
 
685
        ref operands;
 
686
        int code, format;
 
687
        int repcount = 1;
 
688
        const byte *opp;
 
689
        uint ocount, i = 0;
692
690
 
693
691
        array_get(imemory, oppath, 0, &operands);
694
692
        code = num_array_format(&operands);
695
 
        if (code < 0)
696
 
            return code;
697
 
        format = code;
698
 
        check_read(opcodes);
699
 
        opp = opcodes.value.bytes;
700
 
        ocount = r_size(&opcodes);
701
 
        while (ocount--) {
702
 
            byte opx = *opp++;
703
 
 
704
 
            if (opx > UPATH_REPEAT)
705
 
                repcount = opx - UPATH_REPEAT;
706
 
            else if (opx > UPATH_MAX_OP)
707
 
                return_error(e_rangecheck);
708
 
            else {              /* operator */
709
 
                const up_data_t data = up_data[opx];
710
 
 
711
 
                *pnargs = 0;    /* in case of error */
712
 
                if (upath_compat && opx == upath_op_ucache) {
713
 
                    /* CPSI does not complain about incorrect ucache
714
 
                       placement, even though PLRM3 says it's illegal. */
715
 
                    ups = ups > UPS_UCACHE ? ups : data.state_after;
716
 
                } else {
717
 
                    if (!(ups & data.states_before))
718
 
                        return_error(e_typecheck);
719
 
                    ups = data.state_after;
720
 
                }
721
 
                do {
722
 
                    os_ptr op = osp;
723
 
                    byte opargs = data.num_args;
724
 
 
725
 
                    while (opargs--) {
726
 
                        push(1);
727
 
                        (*pnargs)++; /* in case of error */
728
 
                        code = num_array_get(imemory, &operands, format, i++, op);
729
 
                        switch (code) {
730
 
                            case t_integer:
731
 
                                r_set_type_attrs(op, t_integer, 0);
732
 
                                break;
733
 
                            case t_real:
734
 
                                r_set_type_attrs(op, t_real, 0);
735
 
                                break;
736
 
                            default:
737
 
                                return_error(e_typecheck);
738
 
                        }
739
 
                    }
740
 
                    code = (*up_ops[opx])(i_ctx_p);
741
 
                    if (code < 0)
742
 
                        return code;
743
 
                }
744
 
                while (--repcount);
745
 
                repcount = 1;
746
 
            }
747
 
        }
 
693
        if (code < 0)
 
694
            return code;
 
695
        format = code;
 
696
        check_read(opcodes);
 
697
        opp = opcodes.value.bytes;
 
698
        ocount = r_size(&opcodes);
 
699
        while (ocount--) {
 
700
            byte opx = *opp++;
 
701
 
 
702
            if (opx > UPATH_REPEAT)
 
703
                repcount = opx - UPATH_REPEAT;
 
704
            else if (opx > UPATH_MAX_OP)
 
705
                return_error(e_rangecheck);
 
706
            else {              /* operator */
 
707
                const up_data_t data = up_data[opx];
 
708
 
 
709
                *pnargs = 0;    /* in case of error */
 
710
                if (upath_compat && opx == upath_op_ucache) {
 
711
                    /* CPSI does not complain about incorrect ucache
 
712
                       placement, even though PLRM3 says it's illegal. */
 
713
                    ups = ups > UPS_UCACHE ? ups : data.state_after;
 
714
                } else {
 
715
                    if (!(ups & data.states_before))
 
716
                        return_error(e_typecheck);
 
717
                    ups = data.state_after;
 
718
                }
 
719
                do {
 
720
                    os_ptr op = osp;
 
721
                    byte opargs = data.num_args;
 
722
 
 
723
                    while (opargs--) {
 
724
                        push(1);
 
725
                        (*pnargs)++; /* in case of error */
 
726
                        code = num_array_get(imemory, &operands, format, i++, op);
 
727
                        switch (code) {
 
728
                            case t_integer:
 
729
                                r_set_type_attrs(op, t_integer, 0);
 
730
                                break;
 
731
                            case t_real:
 
732
                                r_set_type_attrs(op, t_real, 0);
 
733
                                break;
 
734
                            default:
 
735
                                return_error(e_typecheck);
 
736
                        }
 
737
                    }
 
738
                    code = (*up_ops[opx])(i_ctx_p);
 
739
                    if (code < 0)
 
740
                        return code;
 
741
                }
 
742
                while (--repcount);
 
743
                repcount = 1;
 
744
            }
 
745
        }
748
746
    } else {    /* Ordinary executable array. */
749
 
        const ref *arp = oppath;
750
 
        uint ocount = r_size(oppath);
751
 
        long index = 0;
752
 
        int argcount = 0;
753
 
        op_proc_t oproc;
754
 
        int opx, code;
755
 
 
756
 
        for (; index < ocount; index++) {
757
 
            ref rup;
758
 
            ref *defp;
759
 
            os_ptr op = osp;
760
 
            up_data_t data;
761
 
 
762
 
            *pnargs = argcount;
763
 
            array_get(imemory, arp, index, &rup);
764
 
            switch (r_type(&rup)) {
765
 
                case t_integer:
766
 
                case t_real:
767
 
                    argcount++;
768
 
                    push(1);
769
 
                    *op = rup;
770
 
                    break;
771
 
                case t_name:
772
 
                    if (!r_has_attr(&rup, a_executable) ||
773
 
                        dict_find(systemdict, &rup, &defp) <= 0 ||
774
 
                        r_btype(defp) != t_operator)
775
 
                        return_error(e_typecheck); /* all errors = typecheck */
776
 
                    goto xop;
777
 
                case t_operator:
778
 
                    defp = &rup;
779
 
                  xop:if (!r_has_attr(defp, a_executable))
780
 
                        return_error(e_typecheck);
781
 
                    oproc = real_opproc(defp);
782
 
                    for (opx = 0; opx <= UPATH_MAX_OP; opx++)
783
 
                        if (oproc == up_ops[opx])
784
 
                            break;
785
 
                    if (opx > UPATH_MAX_OP)
786
 
                        return_error(e_typecheck);
787
 
                    data = up_data[opx];
788
 
                    if (argcount != data.num_args)
789
 
                        return_error(e_typecheck);
790
 
                    if (upath_compat && opx == upath_op_ucache) {
791
 
                        /* CPSI does not complain about incorrect ucache
792
 
                           placement, even though PLRM3 says it's illegal. */
793
 
                        ups = ups > UPS_UCACHE ? ups : data.state_after;
794
 
                    } else {
795
 
                        if (!(ups & data.states_before))
796
 
                            return_error(e_typecheck);
797
 
                        ups = data.state_after;
798
 
                    }
799
 
                    code = (*up_ops[opx])(i_ctx_p);
800
 
                    if (code < 0) {
801
 
                        if (code == e_nocurrentpoint)
 
747
        const ref *arp = oppath;
 
748
        uint ocount = r_size(oppath);
 
749
        long index = 0;
 
750
        int argcount = 0;
 
751
        op_proc_t oproc;
 
752
        int opx, code;
 
753
 
 
754
        for (; index < ocount; index++) {
 
755
            ref rup;
 
756
            ref *defp;
 
757
            os_ptr op = osp;
 
758
            up_data_t data;
 
759
 
 
760
            *pnargs = argcount;
 
761
            array_get(imemory, arp, index, &rup);
 
762
            switch (r_type(&rup)) {
 
763
                case t_integer:
 
764
                case t_real:
 
765
                    argcount++;
 
766
                    push(1);
 
767
                    *op = rup;
 
768
                    break;
 
769
                case t_name:
 
770
                    if (!r_has_attr(&rup, a_executable) ||
 
771
                        dict_find(systemdict, &rup, &defp) <= 0 ||
 
772
                        r_btype(defp) != t_operator)
 
773
                        return_error(e_typecheck); /* all errors = typecheck */
 
774
                    goto xop;
 
775
                case t_operator:
 
776
                    defp = &rup;
 
777
                  xop:if (!r_has_attr(defp, a_executable))
 
778
                        return_error(e_typecheck);
 
779
                    oproc = real_opproc(defp);
 
780
                    for (opx = 0; opx <= UPATH_MAX_OP; opx++)
 
781
                        if (oproc == up_ops[opx])
 
782
                            break;
 
783
                    if (opx > UPATH_MAX_OP)
 
784
                        return_error(e_typecheck);
 
785
                    data = up_data[opx];
 
786
                    if (argcount != data.num_args)
 
787
                        return_error(e_typecheck);
 
788
                    if (upath_compat && opx == upath_op_ucache) {
 
789
                        /* CPSI does not complain about incorrect ucache
 
790
                           placement, even though PLRM3 says it's illegal. */
 
791
                        ups = ups > UPS_UCACHE ? ups : data.state_after;
 
792
                    } else {
 
793
                        if (!(ups & data.states_before))
 
794
                            return_error(e_typecheck);
 
795
                        ups = data.state_after;
 
796
                    }
 
797
                    code = (*up_ops[opx])(i_ctx_p);
 
798
                    if (code < 0) {
 
799
                        if (code == e_nocurrentpoint)
802
800
                            return_error(e_rangecheck); /* CET 11-22 */
803
801
                        return code;
804
 
                    }
 
802
                    }
805
803
                    argcount = 0;
806
 
                    break;
807
 
                default:
808
 
                    return_error(e_typecheck);
809
 
            }
810
 
        }
811
 
        if (argcount) {
812
 
            *pnargs = argcount;
813
 
            return_error(e_typecheck);  /* leftover args */
814
 
        }
 
804
                    break;
 
805
                default:
 
806
                    return_error(e_typecheck);
 
807
            }
 
808
        }
 
809
        if (argcount) {
 
810
            *pnargs = argcount;
 
811
            return_error(e_typecheck);  /* leftover args */
 
812
        }
815
813
    }
816
814
    if (ups < UPS_SETBBOX)
817
 
        return_error(e_typecheck);      /* no setbbox */
 
815
        return_error(e_typecheck);      /* no setbbox */
818
816
    if (ups == UPS_SETBBOX && upath_compat) {
819
 
        /*
820
 
         * In CPSI compatibility mode, an empty path with a setbbox also
821
 
         * does a moveto (but only if the path is empty).  Since setbbox
822
 
         * was the last operator, its operands are still on the o-stack.
823
 
         */
824
 
        osp += 2;
825
 
        return zmoveto(i_ctx_p);
 
817
        /*
 
818
         * In CPSI compatibility mode, an empty path with a setbbox also
 
819
         * does a moveto (but only if the path is empty).  Since setbbox
 
820
         * was the last operator, its operands are still on the o-stack.
 
821
         */
 
822
        osp += 2;
 
823
        return zmoveto(i_ctx_p);
826
824
    }
827
825
    return 0;
828
826
}
833
831
    int code = upath_append_aux(oppath, i_ctx_p, &nargs, upath_compat);
834
832
 
835
833
    if (code < 0) {
836
 
        /* Pop args on error, to match Adobe interpreters. */
837
 
        pop(nargs);
838
 
        return code;
 
834
        /* Pop args on error, to match Adobe interpreters. */
 
835
        pop(nargs);
 
836
        return code;
839
837
    }
840
838
    return 0;
841
839
}
850
848
    gs_matrix mat;
851
849
 
852
850
    if ((code = read_matrix(imemory, op, &mat)) >= 0) {
853
 
        if ((code = upath_append(op - 1, i_ctx_p, upath_compat)) >= 0) {
854
 
            if (pmat)
855
 
                *pmat = mat;
856
 
            else
857
 
                code = gs_concat(igs, &mat);
858
 
        }
859
 
        npop = 2;
 
851
        if ((code = upath_append(op - 1, i_ctx_p, upath_compat)) >= 0) {
 
852
            if (pmat)
 
853
                *pmat = mat;
 
854
            else
 
855
                code = gs_concat(igs, &mat);
 
856
        }
 
857
        npop = 2;
860
858
    } else {
861
 
        if ((code = upath_append(op, i_ctx_p, upath_compat)) >= 0)
862
 
            if (pmat)
863
 
                gs_make_identity(pmat);
864
 
        npop = 1;
 
859
        if ((code = upath_append(op, i_ctx_p, upath_compat)) >= 0)
 
860
            if (pmat)
 
861
                gs_make_identity(pmat);
 
862
        npop = 1;
865
863
    }
866
864
    return (code < 0 ? code : npop);
867
865
}
871
869
const op_def zupath_l2_op_defs[] =
872
870
{
873
871
    op_def_begin_level2(),
874
 
                /* Insideness testing */
 
872
                /* Insideness testing */
875
873
    {"1ineofill", zineofill},
876
874
    {"1infill", zinfill},
877
875
    {"1instroke", zinstroke},
878
876
    {"2inueofill", zinueofill},
879
877
    {"2inufill", zinufill},
880
878
    {"2inustroke", zinustroke},
881
 
                /* User paths */
 
879
                /* User paths */
882
880
    {"1uappend", zuappend},
883
881
    {"0ucache", zucache},
884
882
    {"1ueofill", zueofill},
886
884
    {"1upath", zupath},
887
885
    {"1ustroke", zustroke},
888
886
    {"1ustrokepath", zustrokepath},
889
 
                /* Path access for PDF */
 
887
                /* Path access for PDF */
890
888
    {"0.getpath", zgetpath},
891
889
    op_def_end(0)
892
890
};