/* <userpath> <matrix> ustrokepath - */ static int zustrokepath(i_ctx_t *i_ctx_p) { gx_path save; gs_matrix saved_matrix; int npop, code = gs_currentmatrix(igs, &saved_matrix); if (code < 0) return code; /* Save and reset the path. */ gx_path_init_local(&save, imemory); gx_path_assign_preserve(&save, igs->path); if ((code = npop = upath_stroke(i_ctx_p, NULL, false)) < 0 || (code = gs_strokepath(igs)) < 0 ) { gx_path_assign_free(igs->path, &save); return code; } /* * If a matrix was specified then restore the previous matrix. */ if (npop > 1) { if ((code = gs_setmatrix(igs, &saved_matrix)) < 0) { gx_path_assign_free(igs->path, &save); return code; } } gx_path_free(&save, "ustrokepath"); pop(npop); return 0; }
/* Set up a clipping path and device for insideness testing. */ static int in_path(os_ptr oppath, i_ctx_t *i_ctx_p, gx_device * phdev) { int code = gs_gsave(igs); int npop; double uxy[2]; if (code < 0) return code; code = num_params(oppath, 2, uxy); if (code >= 0) { /* Aperture is a single pixel. */ gs_point dxy; gs_fixed_rect fr; gs_transform(igs, uxy[0], uxy[1], &dxy); fr.p.x = fixed_floor(float2fixed(dxy.x)); fr.p.y = fixed_floor(float2fixed(dxy.y)); fr.q.x = fr.p.x + fixed_1; fr.q.y = fr.p.y + fixed_1; code = gx_clip_to_rectangle(igs, &fr); npop = 2; } else if (code == e_stackunderflow) { /* If 0 elements, definitely a stackunderflow; otherwise, */ /* only 1 number, also a stackunderflow. */ npop = code; } else { /* Aperture is a user path. */ /* We have to set the clipping path without disturbing */ /* the current path. */ gx_path *ipath = igs->path; gx_path save; gx_path_init_local(&save, imemory); gx_path_assign_preserve(&save, ipath); gs_newpath(igs); code = upath_append(oppath, i_ctx_p, false); if (code >= 0) code = gx_clip_to_path(igs); gx_path_assign_free(igs->path, &save); npop = 1; } if (code < 0) { gs_grestore(igs); return code; } /* Install the hit detection device. */ gx_set_device_color_1(igs); gx_device_init((gx_device *) phdev, (const gx_device *)&gs_hit_device, NULL, true); phdev->width = phdev->height = max_int; gx_device_fill_in_procs(phdev); gx_set_device_only(igs, phdev); return npop; }
/* Clip to a list of rectangles. */ int gs_rectclip(gs_state * pgs, const gs_rect * pr, uint count) { int code; gx_path save; gx_path_init_local(&save, pgs->memory); gx_path_assign_preserve(&save, pgs->path); gs_newpath(pgs); if ((code = gs_rectappend_compat(pgs, pr, count, true)) < 0 || (code = gs_clip(pgs)) < 0 ) { gx_path_assign_free(pgs->path, &save); return code; } gx_path_free(&save, "gs_rectclip"); gs_newpath(pgs); return 0; }
/* * Assign one path to another and free the first path at the same time. * (This may do less work than assign_preserve + free.) */ int gx_path_assign_free(gx_path * ppto, gx_path * ppfrom) { /* * Detect the special case where both paths have non-shared local * segments, since we can avoid allocating new segments in this case. */ if (ppto->segments == &ppto->local_segments && ppfrom->segments == &ppfrom->local_segments && !gx_path_is_shared(ppto) ) { #define fromsegs (&ppfrom->local_segments) #define tosegs (&ppto->local_segments) gs_memory_t *mem = ppto->memory; gx_path_allocation_t allocation = ppto->allocation; rc_free_path_segments_local(tosegs->rc.memory, tosegs, "gx_path_assign_free"); /* We record a bogus reference to fromsegs, which */ /* gx_path_free will undo. */ *ppto = *ppfrom; rc_increment(fromsegs); ppto->segments = tosegs; ppto->memory = mem; ppto->allocation = allocation; #undef fromsegs #undef tosegs } else { /* In all other cases, just do assign + free. */ int code = gx_path_assign_preserve(ppto, ppfrom); if (code < 0) return code; } gx_path_free(ppfrom, "gx_path_assign_free"); return 0; }