/* Someday we'll find a way to merge them. */ static int common_viewclip(gs_state * pgs, int rule) { gs_fixed_rect bbox; gx_clip_path rpath; int code; gx_clip_path *pcpath = pgs->view_clip; if (pcpath == 0) { pcpath = gx_cpath_alloc(pgs->memory, "gs_[eo]viewclip"); if (pcpath == 0) return_error(gs_error_VMerror); pgs->view_clip = pcpath; } if ((code = gx_path_bbox(pgs->path, &bbox)) < 0) return code; gx_cpath_init_local(&rpath, pgs->memory); code = gx_cpath_from_rectangle(&rpath, &bbox); if (code >= 0) code = gx_cpath_clip(pgs, &rpath, pgs->path, rule); if (code < 0) { gx_cpath_free(&rpath, "gs_[eo]viewclip"); return code; } rpath.rule = rule; gx_cpath_assign_free(pcpath, &rpath); gs_newpath(pgs); return 0; }
/* * Return the effective clipping path of a graphics state. Sometimes this * is the intersection of the clip path and the view clip path; sometimes it * is just the clip path. We aren't sure what the correct algorithm is for * this: for now, we use view clipping unless the current device is a memory * device. This takes care of the most important case, where the current * device is a cache device. */ int gx_effective_clip_path(gs_state * pgs, gx_clip_path ** ppcpath) { gs_id view_clip_id = (pgs->view_clip == 0 || pgs->view_clip->rule == 0 ? gs_no_id : pgs->view_clip->id); if (gs_device_is_memory(pgs->device)) { *ppcpath = pgs->clip_path; return 0; } if (pgs->effective_clip_id == pgs->clip_path->id && pgs->effective_view_clip_id == view_clip_id ) { *ppcpath = pgs->effective_clip_path; return 0; } /* Update the cache. */ if (view_clip_id == gs_no_id) { if (!pgs->effective_clip_shared) gx_cpath_free(pgs->effective_clip_path, "gx_effective_clip_path"); pgs->effective_clip_path = pgs->clip_path; pgs->effective_clip_shared = true; } else { gs_fixed_rect cbox, vcbox; gx_cpath_inner_box(pgs->clip_path, &cbox); gx_cpath_outer_box(pgs->view_clip, &vcbox); if (rect_within(vcbox, cbox)) { if (!pgs->effective_clip_shared) gx_cpath_free(pgs->effective_clip_path, "gx_effective_clip_path"); pgs->effective_clip_path = pgs->view_clip; pgs->effective_clip_shared = true; } else { /* Construct the intersection of the two clip paths. */ int code; gx_clip_path ipath; gx_path vpath; gx_clip_path *npath = pgs->effective_clip_path; if (pgs->effective_clip_shared) { npath = gx_cpath_alloc(pgs->memory, "gx_effective_clip_path"); if (npath == 0) return_error(gs_error_VMerror); } gx_cpath_init_local(&ipath, pgs->memory); code = gx_cpath_assign_preserve(&ipath, pgs->clip_path); if (code < 0) return code; gx_path_init_local(&vpath, pgs->memory); code = gx_cpath_to_path(pgs->view_clip, &vpath); if (code < 0 || (code = gx_cpath_clip(pgs, &ipath, &vpath, gx_rule_winding_number)) < 0 || (code = gx_cpath_assign_free(npath, &ipath)) < 0 ) DO_NOTHING; gx_path_free(&vpath, "gx_effective_clip_path"); gx_cpath_free(&ipath, "gx_effective_clip_path"); if (code < 0) return code; pgs->effective_clip_path = npath; pgs->effective_clip_shared = false; } } pgs->effective_clip_id = pgs->effective_clip_path->id; pgs->effective_view_clip_id = view_clip_id; *ppcpath = pgs->effective_clip_path; return 0; }