/* Check whether we need to call out to restore the page device. */ static bool restore_page_device(const gs_state * pgs_old, const gs_state * pgs_new) { gx_device *dev_old = gs_currentdevice(pgs_old); gx_device *dev_new; gx_device *dev_t1; gx_device *dev_t2; bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice, &gs_int_gstate(pgs_new)->pagedevice); if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0) return false; /* If we are going to putdeviceparams in a callout, we need to */ /* unlock temporarily. The device will be re-locked as needed */ /* by putdeviceparams from the pgs_old->pagedevice dict state. */ if (!samepagedevice) dev_old->LockSafetyParams = false; dev_new = gs_currentdevice(pgs_new); if (dev_old != dev_new) { if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0) return false; if (dev_t1 != dev_t2) return true; } /* * The current implementation of setpagedevice just sets new * parameters in the same device object, so we have to check * whether the page device dictionaries are the same. */ return !samepagedevice; }
/* <gstate> currentgstate <gstate> */ int zcurrentgstate(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_state *pgs; int_gstate *pistate; int code; gs_memory_t *mem; check_stype(*op, st_igstate_obj); check_write(*op); code = gstate_unshare(i_ctx_p); if (code < 0) return code; pgs = igstate_ptr(op); pistate = gs_int_gstate(pgs); code = gstate_check_space(i_ctx_p, istate, r_space(op)); if (code < 0) return code; #define gsref_save(p) ref_save(op, p, "currentgstate") int_gstate_map_refs(pistate, gsref_save); #undef gsref_save mem = gs_state_swap_memory(pgs, imemory); code = gs_currentgstate(pgs, igs); gs_state_swap_memory(pgs, mem); if (code < 0) return code; int_gstate_map_refs(pistate, ref_mark_new); return 0; }
/* Check whether we need to call out to create the page device dictionary. */ static bool save_page_device(gs_state *pgs) { return (r_has_type(&gs_int_gstate(pgs)->pagedevice, t_null) && (*dev_proc(gs_currentdevice(pgs), get_page_device))(gs_currentdevice(pgs)) != 0); }
/* copy for gstates */ int zcopy_gstate(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; gs_state *pgs; gs_state *pgs1; int_gstate *pistate; gs_memory_t *mem; int code; check_stype(*op, st_igstate_obj); check_stype(*op1, st_igstate_obj); check_write(*op); code = gstate_unshare(i_ctx_p); if (code < 0) return code; pgs = igstate_ptr(op); pgs1 = igstate_ptr(op1); pistate = gs_int_gstate(pgs); code = gstate_check_space(i_ctx_p, gs_int_gstate(pgs1), r_space(op)); if (code < 0) return code; #define gsref_save(p) ref_save(op, p, "copygstate") int_gstate_map_refs(pistate, gsref_save); #undef gsref_save mem = gs_state_swap_memory(pgs, imemory); code = gs_copygstate(pgs, pgs1); gs_state_swap_memory(pgs, mem); if (code < 0) return code; int_gstate_map_refs(pistate, ref_mark_new); *op1 = *op; pop(1); return 0; }
/* *op is of type t_astruct(igstate_obj). */ static int gstate_unshare(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref *pgsref = &r_ptr(op, igstate_obj)->gstate; gs_state *pgs = r_ptr(pgsref, gs_state); gs_state *pnew; int_gstate *isp; if (!ref_must_save(pgsref)) return 0; /* Copy the gstate. */ pnew = gs_gstate(pgs); if (pnew == 0) return_error(e_VMerror); isp = gs_int_gstate(pnew); int_gstate_map_refs(isp, ref_mark_new); ref_do_save(op, pgsref, "gstate_unshare"); make_istruct_new(pgsref, 0, pnew); return 0; }
/* - gstate <gstate> */ int zgstate(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code = gstate_check_space(i_ctx_p, istate, icurrent_space); igstate_obj *pigo; gs_state *pnew; int_gstate *isp; if (code < 0) return code; pigo = ialloc_struct(igstate_obj, &st_igstate_obj, "gstate"); if (pigo == 0) return_error(e_VMerror); pnew = gs_state_copy(igs, imemory); if (pnew == 0) { ifree_object(pigo, "gstate"); return_error(e_VMerror); } isp = gs_int_gstate(pnew); int_gstate_map_refs(isp, ref_mark_new); push(1); /* * Since igstate_obj isn't a ref, but only contains a ref, save won't * clear its l_new bit automatically, and restore won't set it * automatically; we have to make sure this ref is on the changes chain. */ make_iastruct(op, a_all, pigo); #if 0 /* Bug 689849 "gstate leaks memory" */ make_null(&pigo->gstate); ref_save(op, &pigo->gstate, "gstate"); make_istruct_new(&pigo->gstate, 0, pnew); #else make_istruct(&pigo->gstate, 0, pnew); #endif return 0; }