/* We know ppath != ppath_old. */ int gx_path_copy_reversed(const gx_path *ppath_old, gx_path *ppath, int init) { const subpath *psub = ppath_old->first_subpath; #ifdef DEBUG if ( gs_debug['p'] ) gx_dump_path(ppath_old, "before reversepath"); #endif if ( init ) gx_path_init(ppath, &ppath_old->memory_procs); nsp: while ( psub ) { const segment *pseg = psub->last; const segment *prev; int code = gx_path_add_point(ppath, pseg->pt.x, pseg->pt.y); if ( code < 0 ) { gx_path_release(ppath); return code; } for ( ; ; pseg = prev ) { prev = pseg->prev; switch ( pseg->type ) { case s_start: /* Finished subpath */ if ( psub->closed ) code = gx_path_close_subpath(ppath); psub = (const subpath *)psub->last->next; goto nsp; case s_curve: { const curve_segment *pc = (const curve_segment *)pseg; code = gx_path_add_curve(ppath, pc->p2.x, pc->p2.y, pc->p1.x, pc->p1.y, prev->pt.x, prev->pt.y); break; } case s_line: case s_line_close: code = gx_path_add_line(ppath, prev->pt.x, prev->pt.y); break; } if ( code ) { gx_path_release(ppath); return code; } } /* not reached */ } ppath->position = ppath_old->position; /* restore current point */ #ifdef DEBUG if ( gs_debug['p'] ) gx_dump_path(ppath, "after reversepath"); #endif return 0; }
/* * Reverse a path. We know ppath != ppath_old. * NOTE: in releases 5.01 and earlier, the implicit line added by closepath * became the first segment of the reversed path. Starting in release * 5.02, the code follows the Adobe implementation (and LanguageLevel 3 * specification), in which this line becomes the *last* segment of the * reversed path. This can produce some quite unintuitive results. * * The order of the subpaths is unspecified in the PLRM, but the CPSI * reverses the subpaths, and the CET (11-05 p6, test 3) tests for it. */ int gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath) { const subpath *psub = ppath_old->current_subpath; #ifdef DEBUG if (gs_debug_c('P')) gx_dump_path(ppath_old, "before reversepath"); #endif nsp: if (psub) { const segment *prev = psub->last; const segment *pseg; segment_notes notes = (prev == (const segment *)psub ? sn_none : psub->next->notes); segment_notes prev_notes; int code; if (!psub->is_closed) { code = gx_path_add_point(ppath, prev->pt.x, prev->pt.y); if (code < 0) return code; } /* * The do ... while structure of this loop is artificial, * designed solely to keep compilers from complaining about * 'statement not reached' or 'end-of-loop code not reached'. * The normal exit from this loop is the goto statement in * the s_start arm of the switch. */ do { pseg = prev; prev_notes = notes; prev = pseg->prev; notes = pseg->notes; prev_notes = (prev_notes & sn_not_first) | (notes & ~sn_not_first); switch (pseg->type) { case s_start: /* Finished subpath */ if (psub->is_closed) { code = gx_path_close_subpath_notes(ppath, prev_notes); if (code < 0) return code; } do { psub = (const subpath *)psub->prev; } while (psub && psub->type != s_start); goto nsp; case s_curve: { const curve_segment *pc = (const curve_segment *)pseg; code = gx_path_add_curve_notes(ppath, pc->p2.x, pc->p2.y, pc->p1.x, pc->p1.y, prev->pt.x, prev->pt.y, prev_notes); break; } case s_line: code = gx_path_add_line_notes(ppath, prev->pt.x, prev->pt.y, prev_notes); break; case s_line_close: /* Skip the closing line. */ code = gx_path_add_point(ppath, prev->pt.x, prev->pt.y); break; default: /* not possible */ return_error(gs_error_Fatal); } } while (code >= 0); return code; /* only reached if code < 0 */ } #undef sn_not_end /* * In the Adobe implementations, reversepath discards a trailing * moveto unless the path consists only of a moveto. We reproduce * this behavior here, even though we consider it a bug. */ if (ppath_old->first_subpath == 0 && path_last_is_moveto(ppath_old) ) { int code = gx_path_add_point(ppath, ppath_old->position.x, ppath_old->position.y); if (code < 0) return code; } #ifdef DEBUG if (gs_debug_c('P')) gx_dump_path(ppath, "after reversepath"); #endif return 0; }