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

« back to all changes in this revision

Viewing changes to base/gxpath2.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: gxpath2.c 10378 2009-11-24 16:51:12Z robin $ */
 
14
/*$Id$ */
15
15
/* Path tracing procedures for Ghostscript library */
16
16
#include "math_.h"
17
17
#include "gx.h"
30
30
gx_path_current_point(const gx_path * ppath, gs_fixed_point * ppt)
31
31
{
32
32
    if (!path_position_valid(ppath))
33
 
        return_error(gs_error_nocurrentpoint);
 
33
        return_error(gs_error_nocurrentpoint);
34
34
    /* Copying the coordinates individually */
35
35
    /* is much faster on a PC, and almost as fast on other machines.... */
36
36
    ppt->x = ppath->position.x, ppt->y = ppath->position.y;
44
44
    const subpath *psub = ppath->current_subpath;
45
45
 
46
46
    if (!psub)
47
 
        return_error(gs_error_nocurrentpoint);
 
47
        return_error(gs_error_nocurrentpoint);
48
48
    *ppt = psub->pt;
49
49
    return 0;
50
50
}
57
57
gx_path_bbox(gx_path * ppath, gs_fixed_rect * pbox)
58
58
{
59
59
    if (ppath->bbox_accurate) {
60
 
        /* The bounding box was set by setbbox. */
61
 
        *pbox = ppath->bbox;
62
 
        return 0;
 
60
        /* The bounding box was set by setbbox. */
 
61
        *pbox = ppath->bbox;
 
62
        return 0;
63
63
    }
64
64
    if (ppath->first_subpath == 0) {
65
 
        /* The path is empty, use the current point if any. */
66
 
        int code = gx_path_current_point(ppath, &pbox->p);
 
65
        /* The path is empty, use the current point if any. */
 
66
        int code = gx_path_current_point(ppath, &pbox->p);
67
67
 
68
 
        if (code < 0) {
69
 
            /*
70
 
             * Don't return garbage, in case the caller doesn't
71
 
             * check the return code.
72
 
             */
73
 
            pbox->p.x = pbox->p.y = 0;
74
 
        }
75
 
        pbox->q = pbox->p;
76
 
        return code;
 
68
        if (code < 0) {
 
69
            /*
 
70
             * Don't return garbage, in case the caller doesn't
 
71
             * check the return code.
 
72
             */
 
73
            pbox->p.x = pbox->p.y = 0;
 
74
        }
 
75
        pbox->q = pbox->p;
 
76
        return code;
77
77
    }
78
78
    /* The stored bounding box may not be up to date. */
79
79
    /* Correct it now if necessary. */
80
80
    if (ppath->box_last == ppath->current_subpath->last) {
81
 
        /* Box is up to date */
82
 
        *pbox = ppath->bbox;
 
81
        /* Box is up to date */
 
82
        *pbox = ppath->bbox;
83
83
    } else {
84
 
        fixed px, py, qx, qy;
85
 
        const segment *pseg = ppath->box_last;
 
84
        fixed px, py, qx, qy;
 
85
        const segment *pseg = ppath->box_last;
86
86
 
87
 
        if (pseg == 0) {        /* box is uninitialized */
88
 
            pseg = (const segment *)ppath->first_subpath;
89
 
            px = qx = pseg->pt.x;
90
 
            py = qy = pseg->pt.y;
91
 
        } else {
92
 
            px = ppath->bbox.p.x, py = ppath->bbox.p.y;
93
 
            qx = ppath->bbox.q.x, qy = ppath->bbox.q.y;
94
 
        }
 
87
        if (pseg == 0) {        /* box is uninitialized */
 
88
            pseg = (const segment *)ppath->first_subpath;
 
89
            px = qx = pseg->pt.x;
 
90
            py = qy = pseg->pt.y;
 
91
        } else {
 
92
            px = ppath->bbox.p.x, py = ppath->bbox.p.y;
 
93
            qx = ppath->bbox.q.x, qy = ppath->bbox.q.y;
 
94
        }
95
95
 
96
96
/* Macro for adjusting the bounding box when adding a point */
97
97
#define ADJUST_BBOX(pt)\
100
100
  if ((pt).y < py) py = (pt).y;\
101
101
  else if ((pt).y > qy) qy = (pt).y
102
102
 
103
 
        while ((pseg = pseg->next) != 0) {
104
 
            switch (pseg->type) {
105
 
                case s_curve:
106
 
                    ADJUST_BBOX(((const curve_segment *)pseg)->p1);
107
 
                    ADJUST_BBOX(((const curve_segment *)pseg)->p2);
108
 
                    /* falls through */
109
 
                default:
110
 
                    ADJUST_BBOX(pseg->pt);
111
 
            }
112
 
        }
 
103
        while ((pseg = pseg->next) != 0) {
 
104
            switch (pseg->type) {
 
105
                case s_curve:
 
106
                    ADJUST_BBOX(((const curve_segment *)pseg)->p1);
 
107
                    ADJUST_BBOX(((const curve_segment *)pseg)->p2);
 
108
                    /* falls through */
 
109
                default:
 
110
                    ADJUST_BBOX(pseg->pt);
 
111
            }
 
112
        }
113
113
#undef ADJUST_BBOX
114
114
 
115
115
#define STORE_BBOX(b)\
116
116
  (b).p.x = px, (b).p.y = py, (b).q.x = qx, (b).q.y = qy;
117
 
        STORE_BBOX(*pbox);
118
 
        STORE_BBOX(ppath->bbox);
 
117
        STORE_BBOX(*pbox);
 
118
        STORE_BBOX(ppath->bbox);
119
119
#undef STORE_BBOX
120
120
 
121
 
        ppath->box_last = ppath->current_subpath->last;
 
121
        ppath->box_last = ppath->current_subpath->last;
122
122
    }
123
123
    return 0;
124
124
}
128
128
gx_path_bbox_set(gx_path * ppath, gs_fixed_rect * pbox)
129
129
{
130
130
    if (ppath->bbox_set) {
131
 
        /* The bounding box was set by setbbox. */
132
 
        *pbox = ppath->bbox;
133
 
        return 0;
 
131
        /* The bounding box was set by setbbox. */
 
132
        *pbox = ppath->bbox;
 
133
        return 0;
134
134
    } else
135
 
        return gx_path_bbox(ppath, pbox);
 
135
        return gx_path_bbox(ppath, pbox);
136
136
}
137
137
 
138
 
 
139
138
/* Test if a path has any curves. */
140
139
#undef gx_path_has_curves
141
140
bool
175
174
 */
176
175
gx_path_rectangular_type
177
176
gx_subpath_is_rectangular(const subpath * pseg0, gs_fixed_rect * pbox,
178
 
                          const subpath ** ppnext)
 
177
                          const subpath ** ppnext)
179
178
{
180
179
    const segment *pseg1, *pseg2, *pseg3, *pseg4;
181
180
    gx_path_rectangular_type type;
182
181
 
183
182
    if (pseg0->curve_count == 0 &&
184
 
        (pseg1 = pseg0->next) != 0 &&
185
 
        (pseg2 = pseg1->next) != 0 &&
186
 
        (pseg3 = pseg2->next) != 0
187
 
        ) {
188
 
        if ((pseg4 = pseg3->next) == 0 || pseg4->type == s_start)
189
 
            type = prt_open;    /* M, L, L, L */
190
 
        else if (pseg4->type != s_line)         /* must be s_line_close */
191
 
            type = prt_closed;  /* M, L, L, L, C */
192
 
        else if (pseg4->pt.x != pseg0->pt.x ||
193
 
                 pseg4->pt.y != pseg0->pt.y
194
 
            )
195
 
            return prt_none;
196
 
        else if (pseg4->next == 0 || pseg4->next->type == s_start)
197
 
            type = prt_fake_closed;     /* Mo, L, L, L, Lo */
198
 
        else if (pseg4->next->type != s_line)   /* must be s_line_close */
199
 
            type = prt_closed;  /* Mo, L, L, L, Lo, C */
200
 
        else
201
 
            return prt_none;
202
 
        {
203
 
            fixed x0 = pseg0->pt.x, y0 = pseg0->pt.y;
204
 
            fixed x2 = pseg2->pt.x, y2 = pseg2->pt.y;
 
183
        (pseg1 = pseg0->next) != 0 &&
 
184
        (pseg2 = pseg1->next) != 0 &&
 
185
        (pseg3 = pseg2->next) != 0
 
186
        ) {
 
187
        if ((pseg4 = pseg3->next) == 0 || pseg4->type == s_start)
 
188
            type = prt_open;    /* M, L, L, L */
 
189
        else if (pseg4->type != s_line)         /* must be s_line_close */
 
190
            type = prt_closed;  /* M, L, L, L, C */
 
191
        else if (pseg4->pt.x != pseg0->pt.x ||
 
192
                 pseg4->pt.y != pseg0->pt.y
 
193
            )
 
194
            return prt_none;
 
195
        else if (pseg4->next == 0 || pseg4->next->type == s_start)
 
196
            type = prt_fake_closed;     /* Mo, L, L, L, Lo */
 
197
        else if (pseg4->next->type != s_line)   /* must be s_line_close */
 
198
            type = prt_closed;  /* Mo, L, L, L, Lo, C */
 
199
        else
 
200
            return prt_none;
 
201
        {
 
202
            fixed x0 = pseg0->pt.x, y0 = pseg0->pt.y;
 
203
            fixed x2 = pseg2->pt.x, y2 = pseg2->pt.y;
205
204
 
206
 
            if ((x0 == pseg1->pt.x && pseg1->pt.y == y2 &&
207
 
                 x2 == pseg3->pt.x && pseg3->pt.y == y0) ||
208
 
                (x0 == pseg3->pt.x && pseg3->pt.y == y2 &&
209
 
                 x2 == pseg1->pt.x && pseg1->pt.y == y0)
210
 
                ) {             /* Path is a rectangle.  Return the bounding box. */
211
 
                if (x0 < x2)
212
 
                    pbox->p.x = x0, pbox->q.x = x2;
213
 
                else
214
 
                    pbox->p.x = x2, pbox->q.x = x0;
215
 
                if (y0 < y2)
216
 
                    pbox->p.y = y0, pbox->q.y = y2;
217
 
                else
218
 
                    pbox->p.y = y2, pbox->q.y = y0;
219
 
                while (pseg4 != 0 && pseg4->type != s_start)
220
 
                    pseg4 = pseg4->next;
221
 
                *ppnext = (const subpath *)pseg4;
222
 
                return type;
223
 
            }
224
 
        }
 
205
            if ((x0 == pseg1->pt.x && pseg1->pt.y == y2 &&
 
206
                 x2 == pseg3->pt.x && pseg3->pt.y == y0) ||
 
207
                (x0 == pseg3->pt.x && pseg3->pt.y == y2 &&
 
208
                 x2 == pseg1->pt.x && pseg1->pt.y == y0)
 
209
                ) {             /* Path is a rectangle.  Return the bounding box. */
 
210
                if (x0 < x2)
 
211
                    pbox->p.x = x0, pbox->q.x = x2;
 
212
                else
 
213
                    pbox->p.x = x2, pbox->q.x = x0;
 
214
                if (y0 < y2)
 
215
                    pbox->p.y = y0, pbox->q.y = y2;
 
216
                else
 
217
                    pbox->p.y = y2, pbox->q.y = y0;
 
218
                while (pseg4 != 0 && pseg4->type != s_start)
 
219
                    pseg4 = pseg4->next;
 
220
                *ppnext = (const subpath *)pseg4;
 
221
                return type;
 
222
            }
 
223
        }
225
224
    }
226
225
    return prt_none;
227
226
}
232
231
    const subpath *pnext;
233
232
 
234
233
    return
235
 
        (gx_path_subpath_count(ppath) == 1 ?
236
 
         gx_subpath_is_rectangular(ppath->first_subpath, pbox, &pnext) :
237
 
         prt_none);
 
234
        (gx_path_subpath_count(ppath) == 1 ?
 
235
         gx_subpath_is_rectangular(ppath->first_subpath, pbox, &pnext) :
 
236
         prt_none);
238
237
}
239
238
 
240
239
/* Translate an already-constructed path (in device space). */
247
246
#define update_xy(pt)\
248
247
  pt.x += dx, pt.y += dy
249
248
    if (ppath->box_last != 0) {
250
 
        update_xy(ppath->bbox.p);
251
 
        update_xy(ppath->bbox.q);
 
249
        update_xy(ppath->bbox.p);
 
250
        update_xy(ppath->bbox.q);
252
251
    }
253
252
    if (path_position_valid(ppath))
254
 
        update_xy(ppath->position);
 
253
        update_xy(ppath->position);
255
254
    for (pseg = (segment *) (ppath->first_subpath); pseg != 0;
256
 
         pseg = pseg->next
257
 
        )
258
 
        switch (pseg->type) {
259
 
            case s_curve:
 
255
         pseg = pseg->next
 
256
        )
 
257
        switch (pseg->type) {
 
258
            case s_curve:
260
259
#define pcseg ((curve_segment *)pseg)
261
 
                update_xy(pcseg->p1);
262
 
                update_xy(pcseg->p2);
 
260
                update_xy(pcseg->p1);
 
261
                update_xy(pcseg->p2);
263
262
#undef pcseg
264
 
            default:
265
 
                update_xy(pseg->pt);
266
 
        }
 
263
            default:
 
264
                update_xy(pseg->pt);
 
265
        }
267
266
#undef update_xy
268
267
    return 0;
269
268
}
286
285
            pt->x = -v;
287
286
        pt->x <<= sx;
288
287
    } else
289
 
        pt->x >>= -sx;
 
288
        pt->x >>= -sx;
290
289
 
291
290
    if (sy > 0) {
292
291
        v = (max_int - int2fixed(1000)) >> sy;
296
295
            pt->y = -v;
297
296
        pt->y <<= sy;
298
297
    } else
299
 
        pt->y >>= -sy;
 
298
        pt->y >>= -sy;
300
299
}
301
300
void
302
301
gx_rect_scale_exp2(gs_fixed_rect * pr, int sx, int sy)
306
305
}
307
306
int
308
307
gx_path_scale_exp2_shared(gx_path * ppath, int log2_scale_x, int log2_scale_y,
309
 
                          bool segments_shared)
 
308
                          bool segments_shared)
310
309
{
311
310
    segment *pseg;
312
311
 
314
313
#define SCALE_XY(pt) gx_point_scale_exp2(&pt, log2_scale_x, log2_scale_y)
315
314
    SCALE_XY(ppath->position);
316
315
    if (!segments_shared) {
317
 
        for (pseg = (segment *) (ppath->first_subpath); pseg != 0;
318
 
             pseg = pseg->next
319
 
             )
320
 
            switch (pseg->type) {
321
 
            case s_curve:
322
 
                SCALE_XY(((curve_segment *)pseg)->p1);
323
 
                SCALE_XY(((curve_segment *)pseg)->p2);
324
 
            default:
325
 
                SCALE_XY(pseg->pt);
326
 
            }
 
316
        for (pseg = (segment *) (ppath->first_subpath); pseg != 0;
 
317
             pseg = pseg->next
 
318
             )
 
319
            switch (pseg->type) {
 
320
            case s_curve:
 
321
                SCALE_XY(((curve_segment *)pseg)->p1);
 
322
                SCALE_XY(((curve_segment *)pseg)->p2);
 
323
            default:
 
324
                SCALE_XY(pseg->pt);
 
325
            }
327
326
    }
328
327
#undef SCALE_XY
329
328
    return 0;
347
346
 
348
347
#ifdef DEBUG
349
348
    if (gs_debug_c('P'))
350
 
        gx_dump_path(ppath_old, "before reversepath");
 
349
        gx_dump_path(ppath_old, "before reversepath");
351
350
#endif
352
351
 nsp:
353
352
    if (psub) {
354
 
        const segment *prev = psub->last;
355
 
        const segment *pseg;
356
 
        segment_notes notes =
357
 
            (prev == (const segment *)psub ? sn_none :
358
 
             psub->next->notes);
359
 
        segment_notes prev_notes;
360
 
        int code;
361
 
 
362
 
        if (!psub->is_closed) {
363
 
            code = gx_path_add_point(ppath, prev->pt.x, prev->pt.y);
364
 
            if (code < 0)
365
 
                return code;
366
 
        }
367
 
        /*
368
 
         * The do ... while structure of this loop is artificial,
369
 
         * designed solely to keep compilers from complaining about
370
 
         * 'statement not reached' or 'end-of-loop code not reached'.
371
 
         * The normal exit from this loop is the goto statement in
372
 
         * the s_start arm of the switch.
373
 
         */
374
 
        do {
375
 
            pseg = prev;
376
 
            prev_notes = notes;
377
 
            prev = pseg->prev;
378
 
            notes = pseg->notes;
379
 
            prev_notes = (prev_notes & sn_not_first) |
380
 
                (notes & ~sn_not_first);
381
 
            switch (pseg->type) {
382
 
                case s_start:
383
 
                    /* Finished subpath */
384
 
                    if (psub->is_closed) {
385
 
                        code =
386
 
                            gx_path_close_subpath_notes(ppath, prev_notes);
387
 
                        if (code < 0)
388
 
                            return code;
389
 
                    }
390
 
                    do {
391
 
                        psub = (const subpath *)psub->prev;
392
 
                    } while (psub && psub->type != s_start);
393
 
                    goto nsp;
394
 
                case s_curve:
395
 
                    {
396
 
                        const curve_segment *pc =
397
 
                        (const curve_segment *)pseg;
398
 
 
399
 
                        code = gx_path_add_curve_notes(ppath,
400
 
                                                       pc->p2.x, pc->p2.y,
401
 
                                                       pc->p1.x, pc->p1.y,
402
 
                                        prev->pt.x, prev->pt.y, prev_notes);
403
 
                        break;
404
 
                    }
405
 
                case s_line:
406
 
                    code = gx_path_add_line_notes(ppath,
407
 
                                        prev->pt.x, prev->pt.y, prev_notes);
408
 
                    break;
409
 
                case s_line_close:
410
 
                    /* Skip the closing line. */
411
 
                    code = gx_path_add_point(ppath, prev->pt.x,
412
 
                                             prev->pt.y);
413
 
                    break;
414
 
                default:        /* not possible */
415
 
                    return_error(gs_error_Fatal);
416
 
            }
417
 
        } while (code >= 0);
418
 
        return code;            /* only reached if code < 0 */
 
353
        const segment *prev = psub->last;
 
354
        const segment *pseg;
 
355
        segment_notes notes =
 
356
            (prev == (const segment *)psub ? sn_none :
 
357
             psub->next->notes);
 
358
        segment_notes prev_notes;
 
359
        int code;
 
360
 
 
361
        if (!psub->is_closed) {
 
362
            code = gx_path_add_point(ppath, prev->pt.x, prev->pt.y);
 
363
            if (code < 0)
 
364
                return code;
 
365
        }
 
366
        /*
 
367
         * The do ... while structure of this loop is artificial,
 
368
         * designed solely to keep compilers from complaining about
 
369
         * 'statement not reached' or 'end-of-loop code not reached'.
 
370
         * The normal exit from this loop is the goto statement in
 
371
         * the s_start arm of the switch.
 
372
         */
 
373
        do {
 
374
            pseg = prev;
 
375
            prev_notes = notes;
 
376
            prev = pseg->prev;
 
377
            notes = pseg->notes;
 
378
            prev_notes = (prev_notes & sn_not_first) |
 
379
                (notes & ~sn_not_first);
 
380
            switch (pseg->type) {
 
381
                case s_start:
 
382
                    /* Finished subpath */
 
383
                    if (psub->is_closed) {
 
384
                        code =
 
385
                            gx_path_close_subpath_notes(ppath, prev_notes);
 
386
                        if (code < 0)
 
387
                            return code;
 
388
                    }
 
389
                    do {
 
390
                        psub = (const subpath *)psub->prev;
 
391
                    } while (psub && psub->type != s_start);
 
392
                    goto nsp;
 
393
                case s_curve:
 
394
                    {
 
395
                        const curve_segment *pc =
 
396
                        (const curve_segment *)pseg;
 
397
 
 
398
                        code = gx_path_add_curve_notes(ppath,
 
399
                                                       pc->p2.x, pc->p2.y,
 
400
                                                       pc->p1.x, pc->p1.y,
 
401
                                        prev->pt.x, prev->pt.y, prev_notes);
 
402
                        break;
 
403
                    }
 
404
                case s_line:
 
405
                    code = gx_path_add_line_notes(ppath,
 
406
                                        prev->pt.x, prev->pt.y, prev_notes);
 
407
                    break;
 
408
                case s_line_close:
 
409
                    /* Skip the closing line. */
 
410
                    code = gx_path_add_point(ppath, prev->pt.x,
 
411
                                             prev->pt.y);
 
412
                    break;
 
413
                default:        /* not possible */
 
414
                    return_error(gs_error_Fatal);
 
415
            }
 
416
        } while (code >= 0);
 
417
        return code;            /* only reached if code < 0 */
419
418
    }
420
419
#undef sn_not_end
421
420
    /*
424
423
     * this behavior here, even though we consider it a bug.
425
424
     */
426
425
    if (ppath_old->first_subpath == 0 &&
427
 
        path_last_is_moveto(ppath_old)
428
 
        ) {
429
 
        int code = gx_path_add_point(ppath, ppath_old->position.x,
430
 
                                     ppath_old->position.y);
 
426
        path_last_is_moveto(ppath_old)
 
427
        ) {
 
428
        int code = gx_path_add_point(ppath, ppath_old->position.x,
 
429
                                     ppath_old->position.y);
431
430
 
432
 
        if (code < 0)
433
 
            return code;
 
431
        if (code < 0)
 
432
            return code;
434
433
    }
435
434
#ifdef DEBUG
436
435
    if (gs_debug_c('P'))
437
 
        gx_dump_path(ppath, "after reversepath");
 
436
        gx_dump_path(ppath, "after reversepath");
438
437
#endif
439
438
    return 0;
440
439
}
446
445
 
447
446
#ifdef DEBUG
448
447
    if (gs_debug_c('P'))
449
 
        gx_dump_path(ppath_old, "before reversepath");
 
448
        gx_dump_path(ppath_old, "before reversepath");
450
449
#endif
451
450
 nsp:
452
451
    if (psub) {
453
 
        const segment *prev = psub->last;
454
 
        const segment *pseg;
455
 
        segment_notes notes =
456
 
            (prev == (const segment *)psub ? sn_none :
457
 
             psub->next->notes);
458
 
        segment_notes prev_notes;
459
 
        int code;
460
 
 
461
 
        if (!psub->is_closed) {
462
 
            code = gx_path_add_line(ppath, prev->pt.x, prev->pt.y);
463
 
            if (code < 0)
464
 
                return code;
465
 
        }
466
 
        /*
467
 
         * The do ... while structure of this loop is artificial,
468
 
         * designed solely to keep compilers from complaining about
469
 
         * 'statement not reached' or 'end-of-loop code not reached'.
470
 
         * The normal exit from this loop is the goto statement in
471
 
         * the s_start arm of the switch.
472
 
         */
473
 
        do {
474
 
            pseg = prev;
475
 
            prev_notes = notes;
476
 
            prev = pseg->prev;
477
 
            notes = pseg->notes;
478
 
            prev_notes = (prev_notes & sn_not_first) |
479
 
                (notes & ~sn_not_first);
480
 
            switch (pseg->type) {
481
 
                case s_start:
482
 
                    /* Finished subpath */
483
 
                    if (psub->is_closed) {
484
 
                        code =
485
 
                            gx_path_close_subpath_notes(ppath, prev_notes);
486
 
                        if (code < 0)
487
 
                            return code;
488
 
                    }
489
 
                    do {
490
 
                        psub = (const subpath *)psub->prev;
491
 
                    } while (psub && psub->type != s_start);
492
 
                    goto nsp;
493
 
                case s_curve:
494
 
                    {
495
 
                        const curve_segment *pc =
496
 
                        (const curve_segment *)pseg;
497
 
 
498
 
                        code = gx_path_add_curve_notes(ppath,
499
 
                                                       pc->p2.x, pc->p2.y,
500
 
                                                       pc->p1.x, pc->p1.y,
501
 
                                        prev->pt.x, prev->pt.y, prev_notes);
502
 
                        break;
503
 
                    }
504
 
                case s_line:
505
 
                    code = gx_path_add_line_notes(ppath,
506
 
                                        prev->pt.x, prev->pt.y, prev_notes);
507
 
                    break;
508
 
                case s_line_close:
509
 
                    /* Skip the closing line. */
510
 
                    code = gx_path_add_point(ppath, prev->pt.x,
511
 
                                             prev->pt.y);
512
 
                    break;
513
 
                default:        /* not possible */
514
 
                    return_error(gs_error_Fatal);
515
 
            }
516
 
        } while (code >= 0);
517
 
        return code;            /* only reached if code < 0 */
 
452
        const segment *prev = psub->last;
 
453
        const segment *pseg;
 
454
        segment_notes notes =
 
455
            (prev == (const segment *)psub ? sn_none :
 
456
             psub->next->notes);
 
457
        segment_notes prev_notes;
 
458
        int code;
 
459
 
 
460
        if (!psub->is_closed) {
 
461
            code = gx_path_add_line(ppath, prev->pt.x, prev->pt.y);
 
462
            if (code < 0)
 
463
                return code;
 
464
        }
 
465
        /*
 
466
         * The do ... while structure of this loop is artificial,
 
467
         * designed solely to keep compilers from complaining about
 
468
         * 'statement not reached' or 'end-of-loop code not reached'.
 
469
         * The normal exit from this loop is the goto statement in
 
470
         * the s_start arm of the switch.
 
471
         */
 
472
        do {
 
473
            pseg = prev;
 
474
            prev_notes = notes;
 
475
            prev = pseg->prev;
 
476
            notes = pseg->notes;
 
477
            prev_notes = (prev_notes & sn_not_first) |
 
478
                (notes & ~sn_not_first);
 
479
            switch (pseg->type) {
 
480
                case s_start:
 
481
                    /* Finished subpath */
 
482
                    if (psub->is_closed) {
 
483
                        code =
 
484
                            gx_path_close_subpath_notes(ppath, prev_notes);
 
485
                        if (code < 0)
 
486
                            return code;
 
487
                    }
 
488
                    do {
 
489
                        psub = (const subpath *)psub->prev;
 
490
                    } while (psub && psub->type != s_start);
 
491
                    goto nsp;
 
492
                case s_curve:
 
493
                    {
 
494
                        const curve_segment *pc =
 
495
                        (const curve_segment *)pseg;
 
496
 
 
497
                        code = gx_path_add_curve_notes(ppath,
 
498
                                                       pc->p2.x, pc->p2.y,
 
499
                                                       pc->p1.x, pc->p1.y,
 
500
                                        prev->pt.x, prev->pt.y, prev_notes);
 
501
                        break;
 
502
                    }
 
503
                case s_line:
 
504
                    code = gx_path_add_line_notes(ppath,
 
505
                                        prev->pt.x, prev->pt.y, prev_notes);
 
506
                    break;
 
507
                case s_line_close:
 
508
                    /* Skip the closing line. */
 
509
                    code = gx_path_add_point(ppath, prev->pt.x,
 
510
                                             prev->pt.y);
 
511
                    break;
 
512
                default:        /* not possible */
 
513
                    return_error(gs_error_Fatal);
 
514
            }
 
515
        } while (code >= 0);
 
516
        return code;            /* only reached if code < 0 */
518
517
    }
519
518
#undef sn_not_end
520
519
    /*
523
522
     * this behavior here, even though we consider it a bug.
524
523
     */
525
524
    if (ppath_old->first_subpath == 0 &&
526
 
        path_last_is_moveto(ppath_old)
527
 
        ) {
528
 
        int code = gx_path_add_point(ppath, ppath_old->position.x,
529
 
                                     ppath_old->position.y);
 
525
        path_last_is_moveto(ppath_old)
 
526
        ) {
 
527
        int code = gx_path_add_point(ppath, ppath_old->position.x,
 
528
                                     ppath_old->position.y);
530
529
 
531
 
        if (code < 0)
532
 
            return code;
 
530
        if (code < 0)
 
531
            return code;
533
532
    }
534
533
#ifdef DEBUG
535
534
    if (gs_debug_c('P'))
536
 
        gx_dump_path(ppath, "after reversepath");
 
535
        gx_dump_path(ppath, "after reversepath");
537
536
#endif
538
537
    return 0;
539
538
}
569
568
    const segment *pseg = penum->pseg;
570
569
 
571
570
    if (pseg == 0) {            /* We've enumerated all the segments, but there might be */
572
 
        /* a trailing moveto. */
573
 
        const gx_path *ppath = penum->path;
 
571
        /* a trailing moveto. */
 
572
        const gx_path *ppath = penum->path;
574
573
 
575
 
        if (path_last_is_moveto(ppath) && !penum->moveto_done) {        /* Handle a trailing moveto */
576
 
            penum->moveto_done = true;
577
 
            penum->notes = sn_none;
578
 
            ppts[0] = ppath->position;
579
 
            return gs_pe_moveto;
580
 
        }
581
 
        return 0;
 
574
        if (path_last_is_moveto(ppath) && !penum->moveto_done) {        /* Handle a trailing moveto */
 
575
            penum->moveto_done = true;
 
576
            penum->notes = sn_none;
 
577
            ppts[0] = ppath->position;
 
578
            return gs_pe_moveto;
 
579
        }
 
580
        return 0;
582
581
    }
583
582
    penum->pseg = pseg->next;
584
583
    penum->notes = pseg->notes;
585
584
    switch (pseg->type) {
586
 
        case s_start:
587
 
            ppts[0] = pseg->pt;
588
 
            return gs_pe_moveto;
589
 
        case s_line:
590
 
            ppts[0] = pseg->pt;
591
 
            return gs_pe_lineto;
592
 
        case s_line_close:
593
 
            ppts[0] = pseg->pt;
594
 
            return gs_pe_closepath;
595
 
        case s_curve:
 
585
        case s_start:
 
586
            ppts[0] = pseg->pt;
 
587
            return gs_pe_moveto;
 
588
        case s_line:
 
589
            ppts[0] = pseg->pt;
 
590
            return gs_pe_lineto;
 
591
        case s_line_close:
 
592
            ppts[0] = pseg->pt;
 
593
            return gs_pe_closepath;
 
594
        case s_curve:
596
595
#define pcseg ((const curve_segment *)pseg)
597
 
            ppts[0] = pcseg->p1;
598
 
            ppts[1] = pcseg->p2;
599
 
            ppts[2] = pseg->pt;
600
 
            return gs_pe_curveto;
 
596
            ppts[0] = pcseg->p1;
 
597
            ppts[1] = pcseg->p2;
 
598
            ppts[2] = pseg->pt;
 
599
            return gs_pe_curveto;
601
600
#undef pcseg
602
 
        default:
603
 
            lprintf1("bad type %x in gx_path_enum_next!\n", pseg->type);
604
 
            return_error(gs_error_Fatal);
 
601
        default:
 
602
            lprintf1("bad type %x in gx_path_enum_next!\n", pseg->type);
 
603
            return_error(gs_error_Fatal);
605
604
    }
606
605
}
607
606
 
622
621
    const segment *pseg = penum->pseg;
623
622
 
624
623
    if (pseg != 0) {
625
 
        if ((pseg = pseg->prev) == 0)
626
 
            return false;
627
 
        penum->pseg = pseg;
628
 
        return true;
 
624
        if ((pseg = pseg->prev) == 0)
 
625
            return false;
 
626
        penum->pseg = pseg;
 
627
        return true;
629
628
    }
630
629
    /* We're at the end of the path.  Check to see whether */
631
630
    /* we need to back up over a trailing moveto. */
632
631
    {
633
 
        const gx_path *ppath = penum->path;
634
 
 
635
 
        if (path_last_is_moveto(ppath) && penum->moveto_done) {         /* Back up over the trailing moveto. */
636
 
            penum->moveto_done = false;
637
 
            return true;
638
 
        } {
639
 
            const subpath *psub = ppath->current_subpath;
640
 
 
641
 
            if (psub == 0)      /* empty path */
642
 
                return false;
643
 
            /* Back up to the last segment of the last subpath. */
644
 
            penum->pseg = psub->last;
645
 
            return true;
646
 
        }
 
632
        const gx_path *ppath = penum->path;
 
633
 
 
634
        if (path_last_is_moveto(ppath) && penum->moveto_done) {         /* Back up over the trailing moveto. */
 
635
            penum->moveto_done = false;
 
636
            return true;
 
637
        } {
 
638
            const subpath *psub = ppath->current_subpath;
 
639
 
 
640
            if (psub == 0)      /* empty path */
 
641
                return false;
 
642
            /* Back up to the last segment of the last subpath. */
 
643
            penum->pseg = psub->last;
 
644
            return true;
 
645
        }
647
646
    }
648
647
}