/* <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; }
/* 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; }
/* Initialize the graphics stack. */ gs_state * int_gstate_alloc(const gs_dual_memory_t * dmem) { int_gstate *iigs; ref proc0; int_remap_color_info_t *prci; gs_ref_memory_t *lmem = dmem->space_local; gs_ref_memory_t *gmem = dmem->space_global; gs_state *pgs = gs_state_alloc((gs_memory_t *)lmem); iigs = gs_alloc_struct((gs_memory_t *)lmem, int_gstate, &st_int_gstate, "int_gstate_alloc(int_gstate)"); int_gstate_map_refs(iigs, make_null); make_empty_array(&iigs->dash_pattern_array, a_all); gs_alloc_ref_array(lmem, &proc0, a_readonly + a_executable, 2, "int_gstate_alloc(proc0)"); make_oper(proc0.value.refs, 0, zpop); make_real(proc0.value.refs + 1, 0.0); iigs->black_generation = proc0; iigs->undercolor_removal = proc0; make_false(&iigs->use_cie_color); /* * Even though the gstate itself is allocated in local VM, the * container for the color remapping procedure must be allocated in * global VM so that the gstate can be copied into global VM. */ prci = gs_alloc_struct((gs_memory_t *)gmem, int_remap_color_info_t, &st_int_remap_color_info, "int_gstate_alloc(remap color info)"); make_struct(&iigs->remap_color_info, imemory_space(gmem), prci); clear_pagedevice(iigs); gs_state_set_client(pgs, iigs, &istate_procs, true); /* PostScript code wants limit clamping enabled. */ gs_setlimitclamp(pgs, true); /* * gsave and grestore only work properly * if there are always at least 2 entries on the stack. * We count on the PostScript initialization code to do a gsave. */ return pgs; }
/* ****** DOESN'T CHECK THE NON-REFS. ****** */ static int gstate_check_space(i_ctx_t *i_ctx_p, int_gstate *isp, uint space) { /* * ****** WORKAROUND ALERT ****** * This code doesn't check the space of the non-refs, or copy their * contents, so it can create dangling references from global VM to * local VM. Because of this, we simply disallow writing into gstates * in global VM (including creating them in the first place) if the * save level is greater than 0. * ****** WORKAROUND ALERT ****** */ #if 1 /* ****** WORKAROUND ****** */ if (space != avm_local && imemory_save_level(iimemory) > 0) return_error(e_invalidaccess); #endif /* ****** END ****** */ #define gsref_check(p) store_check_space(space, p) int_gstate_map_refs(isp, gsref_check); #undef gsref_check 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; }