/* * Ensure that a path owns its segments, by copying the segments if * they currently have multiple references. */ int gx_path_unshare(gx_path * ppath) { int code = 0; if (gx_path_is_shared(ppath)) code = path_alloc_copy(ppath); return code; }
/* Release an alpha buffer. */ static int alpha_buffer_release(gs_state * pgs, bool newpath) { gx_device_memory *mdev = (gx_device_memory *) gs_currentdevice_inline(pgs); int code = (*dev_proc(mdev, close_device)) ((gx_device *) mdev); if (code >= 0) scale_paths(pgs, -mdev->log2_scale.x, -mdev->log2_scale.y, !(newpath && !gx_path_is_shared(pgs->path))); /* Reference counting will free mdev. */ gx_set_device_only(pgs, mdev->target); return code; }
/* Make a new path (newpath). */ int gx_path_new(gx_path * ppath) { gx_path_segments *psegs = ppath->segments; if (gx_path_is_shared(ppath)) { int code = path_alloc_segments(&ppath->segments, ppath->memory, "gx_path_new"); if (code < 0) return code; rc_decrement(psegs, "gx_path_new"); } else { rc_free_path_segments_local(psegs->rc.memory, psegs, "gx_path_new"); } gx_path_init_contents(ppath); 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; }
/* * Assign one path to another, adjusting reference counts appropriately. * Note that this requires that segments of the two paths (but not the path * objects themselves) were allocated with the same allocator. Note also * that since it does the equivalent of a gx_path_new(ppto), it may allocate * a new segments object for ppto. */ int gx_path_assign_preserve(gx_path * ppto, gx_path * ppfrom) { gx_path_segments *fromsegs = ppfrom->segments; gx_path_segments *tosegs = ppto->segments; gs_memory_t *mem = ppto->memory; gx_path_allocation_t allocation = ppto->allocation; if (fromsegs == &ppfrom->local_segments) { /* We can't use ppfrom's segments object. */ if (tosegs == &ppto->local_segments || gx_path_is_shared(ppto)) { /* We can't use ppto's segments either. Allocate a new one. */ int code = path_alloc_segments(&tosegs, ppto->memory, "gx_path_assign"); if (code < 0) return code; rc_decrement(ppto->segments, "gx_path_assign"); } else { /* Use ppto's segments object. */ rc_free_path_segments_local(tosegs->rc.memory, tosegs, "gx_path_assign"); } tosegs->contents = fromsegs->contents; ppfrom->segments = tosegs; rc_increment(tosegs); /* for reference from ppfrom */ } else { /* We can use ppfrom's segments object. */ rc_increment(fromsegs); rc_decrement(tosegs, "gx_path_assign"); } *ppto = *ppfrom; ppto->memory = mem; ppto->allocation = allocation; return 0; }