/* shfill */ int gs_shfill(gs_state * pgs, const gs_shading_t * psh) { /* * shfill is equivalent to filling the current clipping path (or, if * clipping, its bounding box) with the shading, disregarding the * Background if any. In order to produce reasonable high-level output, * we must actually implement this by calling gs_fill rather than * gs_shading_fill_path. However, filling with a shading pattern does * paint the Background, so if necessary, we construct a copy of the * shading with Background removed. */ gs_pattern2_template_t pat; gx_path cpath; gs_matrix imat; gs_client_color cc; gs_color_space cs; gx_device_color devc; int code; gs_pattern2_init(&pat); pat.Shading = psh; gs_make_identity(&imat); code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs, pgs->memory); if (code < 0) return code; code = gs_pattern2_set_shfill(&cc); if (code < 0) return code; gs_cspace_init(&cs, &gs_color_space_type_Pattern, pgs->memory, false); cs.params.pattern.has_base_space = false; code = cs.type->remap_color(&cc, &cs, &devc, (gs_imager_state *)pgs, pgs->device, gs_color_select_texture); if (code >= 0) { gx_path_init_local(&cpath, pgs->memory); code = gx_cpath_to_path(pgs->clip_path, &cpath); if (code >= 0) code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number, fixed_0, fixed_0); gx_path_free(&cpath, "gs_shfill"); } gs_pattern_reference(&cc, -1); return code; }
int gs_clippath(gs_state * pgs) { gx_path cpath; int code; gx_path_init_local(&cpath, pgs->path->memory); code = gx_cpath_to_path(pgs->clip_path, &cpath); if (code >= 0) { code = gx_path_assign_free(pgs->path, &cpath); pgs->current_point.x = fixed2float(pgs->path->position.x); pgs->current_point.y = fixed2float(pgs->path->position.y); pgs->current_point_valid = true; } if (code < 0) gx_path_free(&cpath, "gs_clippath"); return code; }
int gs_viewclippath(gs_state * pgs) { gx_path cpath; gx_clip_path *pcpath = pgs->view_clip; int code; gx_path_init_local(&cpath, pgs->memory); if (pcpath == 0 || pcpath->rule == 0) { /* No view clip path is active: fabricate one. */ gs_fixed_rect box; code = gx_default_clip_box(pgs, &box); if (code < 0) return code; code = gx_path_add_rectangle(&cpath, box.p.x, box.p.y, box.q.x, box.q.y); } else { code = gx_cpath_to_path(pcpath, &cpath); } if (code < 0) return code; return gx_path_assign_free(pgs->path, &cpath); }
/* * 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; }
/* shfill */ int gs_shfill(gs_gstate * pgs, const gs_shading_t * psh) { /* * shfill is equivalent to filling the current clipping path (or, if * clipping, its bounding box) with the shading, disregarding the * Background if any. In order to produce reasonable high-level output, * we must implement this by calling gs_fill_path. */ gs_pattern2_template_t pat; gs_matrix imat; gs_client_color cc; gs_color_space *pcs; gx_device_color devc; int code; /* Must install the shading color space to allow check_DeviceN_component_names initialize the color component map. */ /* Don't bother with saving the old color space, color, and cie_joint_caches, because .shfill is always called within gsave-grestore - see gs/lib . */ code = gs_setcolorspace(pgs, psh->params.ColorSpace); if (code < 0) return 0; if (psh->params.cie_joint_caches != NULL) { pgs->cie_joint_caches = psh->params.cie_joint_caches; rc_increment(pgs->cie_joint_caches); } gs_pattern2_init(&pat); pat.Shading = psh; gs_make_identity(&imat); code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs, pgs->memory); if (code < 0) return code; code = gs_pattern2_set_shfill(&cc); if (code < 0) return code; pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern); if (pcs == NULL) return_error(gs_error_VMerror); pcs->params.pattern.has_base_space = false; code = pcs->type->remap_color(&cc, pcs, &devc, pgs, pgs->device, gs_color_select_texture); if (code >= 0) { gx_device *dev = pgs->device; bool need_path = !dev_proc(dev, dev_spec_op)(dev, gxdso_pattern_shfill_doesnt_need_path, NULL, 0); if (need_path) { gx_path cpath; gx_path_init_local(&cpath, pgs->memory); code = gx_cpath_to_path(pgs->clip_path, &cpath); if (code >= 0) code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number, pgs->fill_adjust.x, pgs->fill_adjust.y); gx_path_free(&cpath, "gs_shfill"); } else code = gx_fill_path(NULL, &devc, pgs, gx_rule_winding_number, pgs->fill_adjust.x, pgs->fill_adjust.y); } rc_decrement_cs(pcs, "gs_shfill"); gs_pattern_reference(&cc, -1); return code; }