int cie_cache_joint(i_ctx_t *i_ctx_p, const ref_cie_render_procs * pcrprocs, const gs_cie_common *pcie, gs_state * pgs) { const gs_cie_render *pcrd = gs_currentcolorrendering(pgs); gx_cie_joint_caches *pjc = gx_unshare_cie_caches(pgs); gs_ref_memory_t *imem = (gs_ref_memory_t *) gs_state_memory(pgs); ref pqr_procs; uint space; int code; int i; if (pcrd == 0) /* cache is not set up yet */ return 0; if (pjc == 0) /* must already be allocated */ return_error(e_VMerror); if (r_has_type(&pcrprocs->TransformPQR, t_null)) { /* * This CRD came from a driver, not from a PostScript dictionary. * Resample TransformPQR in C code. */ return gs_cie_cs_complete(pgs, true); } gs_cie_compute_points_sd(pjc, pcie, pcrd); code = ialloc_ref_array(&pqr_procs, a_readonly, 3 * (1 + 4 + 4 * 6), "cie_cache_common"); if (code < 0) return code; /* When we're done, deallocate the procs and complete the caches. */ check_estack(3); cie_cache_push_finish(i_ctx_p, cie_tpqr_finish, imem, pgs); *++esp = pqr_procs; space = r_space(&pqr_procs); for (i = 0; i < 3; i++) { ref *p = pqr_procs.value.refs + 3 + (4 + 4 * 6) * i; const float *ppt = (float *)&pjc->points_sd; int j; make_array(pqr_procs.value.refs + i, a_readonly | a_executable | space, 4, p); make_array(p, a_readonly | space, 4 * 6, p + 4); p[1] = pcrprocs->TransformPQR.value.refs[i]; make_oper(p + 2, 0, cie_exec_tpqr); make_oper(p + 3, 0, cie_post_exec_tpqr); for (j = 0, p += 4; j < 4 * 6; j++, p++, ppt++) make_real(p, *ppt); } return cie_prepare_cache3(i_ctx_p, &pcrd->RangePQR, pqr_procs.value.const_refs, pjc->TransformPQR.caches, pjc, imem, "Transform.PQR"); }
/* * Execute a quit in the case of an exit or stop with no appropriate * enclosing control scope (loop or stopped). The caller has already * ensured two free slots on the top of the o-stack. */ static int unmatched_exit(os_ptr op, op_proc_t opproc) { make_oper(op - 1, 0, opproc); make_int(op, e_invalidexit); return_error(e_Quit); }
/* * Convert an operator index to an operator or oparray ref. * This is only used for debugging and for 'get' from packed arrays, * so it doesn't have to be very fast. */ void op_index_ref(uint index, ref * pref) { const op_array_table *opt; if (op_index_is_operator(index)) { make_oper(pref, index, op_index_proc(index)); return; } opt = op_index_op_array_table(index); make_tasv(pref, t_oparray, opt->attrs, index, const_refs, (opt->table.value.const_refs + index - opt->base_index)); }
/* Get the calling operator for error reporting in %Type32BuildGlyph */ static int zgetshowoperator(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_text_enum_t *osenum = op_show_find(i_ctx_p); push(1); if (osenum == NULL) make_null(op); else { op_proc_t proc; *(void **)&proc = osenum->enum_client_data; make_oper(op, 0, proc); } 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; }
/* * Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return * o_push_estack if we had to call a CDevProc, or if we are skipping the * rendering process (only getting the metrics). * Returns exec_cont - a function, which must be called by caller after this function. */ int zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont, const ref * pcnref, const double psb[2], const double pwidth[2], const gs_rect * pbbox, op_proc_t cont, op_proc_t *exec_cont, const double Metrics2_sbw_default[4]) { os_ptr op = osp; ref *pcdevproc, *valueref; int have_cdevproc; ref rpop; ref cid, *cidptr; bool metrics2; bool metrics2_use_default = false; double w2[10]; gs_text_enum_t *penum = op_show_find(i_ctx_p); w2[0] = pwidth[0], w2[1] = pwidth[1]; /* Adjust the bounding box for stroking if needed. */ w2[2] = pbbox->p.x, w2[3] = pbbox->p.y; w2[4] = pbbox->q.x, w2[5] = pbbox->q.y; if (pbfont->PaintType != 0) { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; } /* Check for Metrics2. */ { int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6); if (code < 0) return code; metrics2 = code > 0; } /* * For FontType 9 and 11, if Metrics2 is missing, the caller provides * default Metrics2 values derived from the FontBBox. */ if (!metrics2 && Metrics2_sbw_default != NULL) { w2[6] = Metrics2_sbw_default[2]; w2[7] = Metrics2_sbw_default[3]; w2[8] = Metrics2_sbw_default[0]; w2[9] = Metrics2_sbw_default[1]; metrics2 = true; metrics2_use_default = true; } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = zchar_get_CDevProc(pbfont, &pcdevproc); /* Obscure test. The CDevProc is supposed to be called with the original CID but what we get passed * here is the TT GID. So the CDevProc won't do the right thing. We need to extract the CID from the * enumerator, and use that instead. */ cidptr = (ref *)pcnref; if (pbfont->FontType == ft_CID_TrueType && dict_find_string(&pfont_data(gs_font_parent(pbfont))->dict, "File", &valueref) > 0) { if (pbfont->key_name.size != pbfont->font_name.size || strncmp((const char *)pbfont->key_name.chars, (const char *)pbfont->font_name.chars, pbfont->key_name.size)) { if (penum->returned.current_glyph >= GS_MIN_CID_GLYPH) { make_int(&cid, penum->returned.current_glyph - GS_MIN_CID_GLYPH); } else { make_int(&cid, penum->returned.current_glyph); } cidptr = &cid; } } if (have_cdevproc || zchar_show_width_only(penum)) { int i; op_proc_t zsetc; int nparams; if (have_cdevproc) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; /* If we have cdevproc and the font type is CID type 0, we'll throw away Metrics2_sbw_default that is calculated from FontBBox. */ if (!metrics2 || (penum->current_font->FontType == ft_CID_encrypted && metrics2_use_default)) { w2[6] = w2[0], w2[7] = w2[1]; w2[8] = w2[9] = 0; } nparams = 10; } else { make_oper(&rpop, 0, zpop); pcdevproc = &rpop; if (metrics2) zsetc = zsetcachedevice2, nparams = 10; else zsetc = zsetcachedevice, nparams = 6; } check_estack(3); /* Push the l.s.b. for .type1addpath if necessary. */ if (psb != 0) { push(nparams + 3); make_real(op - (nparams + 2), psb[0]); make_real(op - (nparams + 1), psb[1]); } else { push(nparams + 1); } for (i = 0; i < nparams; ++i) make_real(op - nparams + i, w2[i]); ref_assign(op, cidptr); push_op_estack(cont); push_op_estack(zsetc); ++esp; ref_assign(esp, pcdevproc); return o_push_estack; } { int code = (metrics2 ? gs_text_setcachedevice2(penum, w2) : gs_text_setcachedevice(penum, w2)); if (code < 0) return code; } /* No metrics modification, do the stroke or fill now. */ /* Push the l.s.b. for .type1addpath if necessary. */ if (psb != 0) { push(2); make_real(op - 1, psb[0]); make_real(op, psb[1]); } *exec_cont = cont; return 0; }
/* * Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return * o_push_estack if we had to call a CDevProc, or if we are skipping the * rendering process (only getting the metrics). */ int zchar_set_cache(os_ptr op, const gs_font_base *pbfont, const ref *pcnref, const float psb[2], const float pwidth[2], const gs_rect *pbbox, int (*cont_fill)(P1(os_ptr)), int (*cont_stroke)(P1(os_ptr))) { const ref *pfdict = &pfont_data(pbfont)->dict; ref *pmdict; ref *pcdevproc; int have_cdevproc; ref rpop; bool metrics2 = false; int (*cont)(P1(os_ptr)); float w2[10]; gs_show_enum *penum = op_show_find(); w2[0] = pwidth[0], w2[1] = pwidth[1]; /* Adjust the bounding box for stroking if needed. */ w2[2] = pbbox->p.x, w2[3] = pbbox->p.y; w2[4] = pbbox->q.x, w2[5] = pbbox->q.y; if ( pbfont->PaintType == 0 ) cont = cont_fill; else { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; cont = cont_stroke; } /* Check for Metrics2. */ if ( dict_find_string(pfdict, "Metrics2", &pmdict) > 0 ) { ref *pmvalue; check_type_only(*pmdict, t_dictionary); check_dict_read(*pmdict); if ( dict_find(pmdict, pcnref, &pmvalue) > 0 ) { check_read_type_only(*pmvalue, t_array); if ( r_size(pmvalue) == 4 ) { int code = num_params(pmvalue->value.refs + 3, 4, w2 + 6); if ( code < 0 ) return code; metrics2 = true; } } } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = dict_find_string(pfdict, "CDevProc", &pcdevproc) > 0; if ( have_cdevproc || gs_show_width_only(penum) ) { int i; int (*zsetc)(P1(os_ptr)); int nparams; if ( have_cdevproc ) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; if ( !metrics2 ) { w2[6] = w2[0], w2[7] = w2[1]; w2[8] = w2[9] = 0; } nparams = 10; } else { make_oper(&rpop, 0, zpop); pcdevproc = &rpop; if ( metrics2 ) zsetc = zsetcachedevice2, nparams = 10; else zsetc = zsetcachedevice, nparams = 6; } check_estack(3); /* Push the l.s.b. for .type1addpath if necessary. */ if ( psb != 0 ) { push(nparams + 3); make_real(op - (nparams + 2), psb[0]); make_real(op - (nparams + 1), psb[1]); } else { push(nparams + 1); } for ( i = 0; i < nparams; ++i ) make_real(op - nparams + i, w2[i]); ref_assign(op, pcnref); push_op_estack(cont); push_op_estack(zsetc); ++esp; ref_assign(esp, pcdevproc); return o_push_estack; } { int code = (metrics2 ? gs_setcachedevice2(penum, igs, w2) : gs_setcachedevice(penum, igs, w2)); if ( code < 0 ) return code; } /* No metrics modification, do the stroke or fill now. */ /* Push the l.s.b. for .type1addpath if necessary. */ if ( psb != 0 ) { push(2); make_real(op - 1, psb[0]); make_real(op, psb[1]); } return cont(op); }
/* * Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return * o_push_estack if we had to call a CDevProc, or if we are skipping the * rendering process (only getting the metrics). * Returns exec_cont - a function, which must be called by caller after this function. */ int zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont, const ref * pcnref, const double psb[2], const double pwidth[2], const gs_rect * pbbox, op_proc_t cont, op_proc_t *exec_cont, const double Metrics2_sbw_default[4]) { os_ptr op = osp; ref *pcdevproc; int have_cdevproc; ref rpop; bool metrics2; bool metrics2_use_default = false; double w2[10]; gs_text_enum_t *penum = op_show_find(i_ctx_p); w2[0] = pwidth[0], w2[1] = pwidth[1]; /* Adjust the bounding box for stroking if needed. */ w2[2] = pbbox->p.x, w2[3] = pbbox->p.y; w2[4] = pbbox->q.x, w2[5] = pbbox->q.y; if (pbfont->PaintType != 0) { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; } /* Check for Metrics2. */ { int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6); if (code < 0) return code; metrics2 = code > 0; } /* * For FontType 9 and 11, if Metrics2 is missing, the caller provides * default Metrics2 values derived from the FontBBox. */ if (!metrics2 && Metrics2_sbw_default != NULL) { w2[6] = Metrics2_sbw_default[2]; w2[7] = Metrics2_sbw_default[3]; w2[8] = Metrics2_sbw_default[0]; w2[9] = Metrics2_sbw_default[1]; metrics2 = true; metrics2_use_default = true; } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = zchar_get_CDevProc(pbfont, &pcdevproc); if (have_cdevproc || zchar_show_width_only(penum)) { int i; op_proc_t zsetc; int nparams; if (have_cdevproc) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; /* If we have cdevproc and the font type is CID type 0, we'll throw away Metrics2_sbw_default that is calculated from FontBBox. */ if (!metrics2 || (penum->current_font->FontType == ft_CID_encrypted && metrics2_use_default)) { w2[6] = w2[0], w2[7] = w2[1]; w2[8] = w2[9] = 0; } nparams = 10; } else { make_oper(&rpop, 0, zpop); pcdevproc = &rpop; if (metrics2) zsetc = zsetcachedevice2, nparams = 10; else zsetc = zsetcachedevice, nparams = 6; } check_estack(3); /* Push the l.s.b. for .type1addpath if necessary. */ if (psb != 0) { push(nparams + 3); make_real(op - (nparams + 2), psb[0]); make_real(op - (nparams + 1), psb[1]); } else { push(nparams + 1); } for (i = 0; i < nparams; ++i) make_real(op - nparams + i, w2[i]); ref_assign(op, pcnref); push_op_estack(cont); push_op_estack(zsetc); ++esp; ref_assign(esp, pcdevproc); return o_push_estack; } { int code = (metrics2 ? gs_text_setcachedevice2(penum, w2) : gs_text_setcachedevice(penum, w2)); if (code < 0) return code; } /* No metrics modification, do the stroke or fill now. */ /* Push the l.s.b. for .type1addpath if necessary. */ if (psb != 0) { push(2); make_real(op - 1, psb[0]); make_real(op, psb[1]); } *exec_cont = cont; return 0; }