/* Set up the next sample */ static int screen_sample(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_screen_enum *penum = senum; gs_point pt; int code = gs_screen_currentpoint(penum, &pt); ref proc; switch (code) { default: return code; case 1: /* All done */ if (real_opproc(esp - 2) != 0) code = (*real_opproc(esp - 2)) (i_ctx_p); esp -= snumpush; screen_cleanup(i_ctx_p); return (code < 0 ? code : o_pop_estack); case 0: ; } push(2); make_real(op - 1, pt.x); make_real(op, pt.y); proc = sproc; push_op_estack(set_screen_continue); *++esp = proc; return o_push_estack; }
static int zforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr obj = op - 1; es_ptr ep = esp; es_ptr cproc = ep + 4; check_estack(6); check_proc(*op); switch (r_type(obj)) { default: return_op_typecheck(obj); case t_array: check_read(*obj); make_op_estack(cproc, array_continue); break; case t_dictionary: check_dict_read(*obj); make_int(cproc, dict_first(obj)); ++cproc; make_op_estack(cproc, dict_continue); break; case t_string: check_read(*obj); make_op_estack(cproc, string_continue); break; case t_mixedarray: case t_shortarray: check_read(*obj); make_op_estack(cproc, packedarray_continue); break; } /* * Push: * - a mark; * - the composite object; * - the procedure; * - the iteration index (only for dictionaries, done above); * and invoke the continuation operator. */ make_mark_estack(ep + 1, es_for, forall_cleanup); ep[2] = *obj; ep[3] = *op; esp = cproc - 1; pop(2); return (*real_opproc(cproc))(i_ctx_p); }
/* Find the index of an operator that doesn't have one stored in it. */ ushort op_find_index(const ref * pref /* t_operator */ ) { op_proc_t proc = real_opproc(pref); const op_def *const *opp = op_defs_all; const op_def *const *opend = opp + (op_def_count / OP_DEFS_MAX_SIZE); for (; opp < opend; ++opp) { const op_def *def = *opp; for (; def->oname != 0; ++def) if (def->proc == proc) return (opp - op_defs_all) * OP_DEFS_MAX_SIZE + (def - *opp); } /* Lookup failed! This isn't possible.... */ return 0; }
/* * Pop the e-stack, executing cleanup procedures as needed. * We could make this more efficient using ref_stack_enum_*, * but it isn't used enough to make this worthwhile. */ void pop_estack(i_ctx_t *i_ctx_p, uint count) { uint idx = 0; uint popped = 0; esfile_clear_cache(); for (; idx < count; idx++) { ref *ep = ref_stack_index(&e_stack, idx - popped); if (r_is_estack_mark(ep)) { ref_stack_pop(&e_stack, idx + 1 - popped); popped = idx + 1; (*real_opproc(ep)) (i_ctx_p); } } ref_stack_pop(&e_stack, count - popped); }
/* * Note that op_show_continue_dispatch sets osp = op explicitly iff the * dispatch succeeds. This is so that the show operators don't pop anything * from the o-stack if they don't succeed. Note also that if it returns an * error, it has freed the enumerator. */ int op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code) { os_ptr op = osp - npop; gs_text_enum_t *penum = senum; switch (code) { case 0: { /* all done */ os_ptr save_osp = osp; osp = op; code = (*real_opproc(&seproc)) (i_ctx_p); op_show_free(i_ctx_p, code); if (code < 0) { osp = save_osp; return code; } return o_pop_estack; } case TEXT_PROCESS_INTERVENE: { ref *pslot = &sslot; /* only used for kshow */ push(2); make_int(op - 1, gs_text_current_char(penum)); /* previous char */ make_int(op, gs_text_next_char(penum)); push_op_estack(op_show_continue); /* continue after kerning */ *++esp = *pslot; /* kerning procedure */ return o_push_estack; } case TEXT_PROCESS_RENDER: { gs_font *pfont = gs_currentfont(igs); font_data *pfdata = pfont_data(pfont); gs_char chr = gs_text_current_char(penum); gs_glyph glyph = gs_text_current_glyph(penum); push(2); op[-1] = pfdata->dict; /* push the font */ /* * For Type 1 and Type 4 fonts, prefer BuildChar to BuildGlyph * if there is no glyph, or if there is both a character and a * glyph and the glyph is the one that corresponds to the * character in the Encoding, so that PostScript procedures * appearing in the CharStrings dictionary will receive the * character code rather than the character name; for Type 3 * fonts, prefer BuildGlyph to BuildChar. For other font types * (such as CID fonts), only BuildGlyph will be present. */ if (pfont->FontType == ft_user_defined) { /* Type 3 font, prefer BuildGlyph. */ if (level2_enabled && !r_has_type(&pfdata->BuildGlyph, t_null) && glyph != gs_no_glyph ) { glyph_ref(imemory, glyph, op); esp[2] = pfdata->BuildGlyph; } else if (r_has_type(&pfdata->BuildChar, t_null)) goto err; else if (chr == gs_no_char) { /* glyphshow, reverse map the character */ /* through the Encoding */ ref gref; const ref *pencoding = &pfdata->Encoding; glyph_ref(imemory, glyph, &gref); if (!map_glyph_to_char(imemory, &gref, pencoding, (ref *) op) ) { /* Not found, try .notdef */ name_enter_string(imemory, ".notdef", &gref); if (!map_glyph_to_char(imemory, &gref, pencoding, (ref *) op) ) goto err; } esp[2] = pfdata->BuildChar; } else { make_int(op, chr & 0xff); esp[2] = pfdata->BuildChar; } } else { /* * For a Type 1 or Type 4 font, prefer BuildChar or * BuildGlyph as described above: we know that both * BuildChar and BuildGlyph are present. For other font * types, only BuildGlyph is available. */ ref eref, gref; if (chr != gs_no_char && !r_has_type(&pfdata->BuildChar, t_null) && (glyph == gs_no_glyph || (!r_has_type(&pfdata->Encoding, t_null) && array_get(imemory, &pfdata->Encoding, (long)(chr & 0xff), &eref) >= 0 && (glyph_ref(imemory, glyph, &gref), obj_eq(imemory, &gref, &eref)))) ) { make_int(op, chr & 0xff); esp[2] = pfdata->BuildChar; } else { /* We might not have a glyph: substitute 0. **HACK** */ if (glyph == gs_no_glyph) make_int(op, 0); else glyph_ref(imemory, glyph, op); esp[2] = pfdata->BuildGlyph; } } /* Save the stack depths in case we bail out. */ sodepth.value.intval = ref_stack_count(&o_stack) - 2; sddepth.value.intval = ref_stack_count(&d_stack); push_op_estack(op_show_continue); ++esp; /* skip BuildChar or BuildGlyph proc */ return o_push_estack; } case TEXT_PROCESS_CDEVPROC: { gs_font *pfont = penum->current_font; ref cnref; op_proc_t cont = op_show_continue, exec_cont = 0; gs_glyph glyph = penum->returned.current_glyph; int code; pop(npop); op = osp; glyph_ref(imemory, glyph, &cnref); if (pfont->FontType == ft_CID_TrueType) { gs_font_type42 *pfont42 = (gs_font_type42 *)pfont; uint glyph_index = pfont42->data.get_glyph_index(pfont42, glyph); code = zchar42_set_cache(i_ctx_p, (gs_font_base *)pfont42, &cnref, glyph_index, cont, &exec_cont); } else if (pfont->FontType == ft_CID_encrypted) code = z1_set_cache(i_ctx_p, (gs_font_base *)pfont, &cnref, glyph, cont, &exec_cont); else return_error(e_unregistered); /* Unimplemented. */ if (exec_cont != 0) return_error(e_unregistered); /* Must not happen. */ return code; } default: /* error */ err: if (code >= 0) code = gs_note_error(e_invalidfont); return op_show_free(i_ctx_p, code); } }
/* Append a user path to the current path. */ static inline int upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p, int *pnargs, bool upath_compat) { upath_state ups = UPS_INITIAL; ref opcodes; if (r_has_type(oppath, t__invalid)) return_error(e_stackunderflow); if (!r_is_array(oppath)) return_error(e_typecheck); check_read(*oppath); gs_newpath(igs); /****** ROUND tx AND ty ******/ if ( r_size(oppath) == 2 && array_get(imemory, oppath, 1, &opcodes) >= 0 && r_has_type(&opcodes, t_string) ) { /* 1st element is operands, 2nd is operators */ ref operands; int code, format; int repcount = 1; const byte *opp; uint ocount, i = 0; array_get(imemory, oppath, 0, &operands); code = num_array_format(&operands); if (code < 0) return code; format = code; check_read(opcodes); opp = opcodes.value.bytes; ocount = r_size(&opcodes); while (ocount--) { byte opx = *opp++; if (opx > UPATH_REPEAT) repcount = opx - UPATH_REPEAT; else if (opx > UPATH_MAX_OP) return_error(e_rangecheck); else { /* operator */ const up_data_t data = up_data[opx]; *pnargs = 0; /* in case of error */ if (upath_compat && opx == upath_op_ucache) { /* CPSI does not complain about incorrect ucache placement, even though PLRM3 says it's illegal. */ ups = ups > UPS_UCACHE ? ups : data.state_after; } else { if (!(ups & data.states_before)) return_error(e_typecheck); ups = data.state_after; } do { os_ptr op = osp; byte opargs = data.num_args; while (opargs--) { push(1); (*pnargs)++; /* in case of error */ code = num_array_get(imemory, &operands, format, i++, op); switch (code) { case t_integer: r_set_type_attrs(op, t_integer, 0); break; case t_real: r_set_type_attrs(op, t_real, 0); break; default: return_error(e_typecheck); } } code = (*up_ops[opx])(i_ctx_p); if (code < 0) return code; } while (--repcount); repcount = 1; } } } else { /* Ordinary executable array. */ const ref *arp = oppath; uint ocount = r_size(oppath); long index = 0; int argcount = 0; op_proc_t oproc; int opx, code; for (; index < ocount; index++) { ref rup; ref *defp; os_ptr op = osp; up_data_t data; *pnargs = argcount; array_get(imemory, arp, index, &rup); switch (r_type(&rup)) { case t_integer: case t_real: argcount++; push(1); *op = rup; break; case t_name: if (!r_has_attr(&rup, a_executable) || dict_find(systemdict, &rup, &defp) <= 0 || r_btype(defp) != t_operator) return_error(e_typecheck); /* all errors = typecheck */ goto xop; case t_operator: defp = &rup; xop:if (!r_has_attr(defp, a_executable)) return_error(e_typecheck); oproc = real_opproc(defp); for (opx = 0; opx <= UPATH_MAX_OP; opx++) if (oproc == up_ops[opx]) break; if (opx > UPATH_MAX_OP) return_error(e_typecheck); data = up_data[opx]; if (argcount != data.num_args) return_error(e_typecheck); if (upath_compat && opx == upath_op_ucache) { /* CPSI does not complain about incorrect ucache placement, even though PLRM3 says it's illegal. */ ups = ups > UPS_UCACHE ? ups : data.state_after; } else { if (!(ups & data.states_before)) return_error(e_typecheck); ups = data.state_after; } code = (*up_ops[opx])(i_ctx_p); if (code < 0) { if (code == e_nocurrentpoint) return_error(e_rangecheck); /* CET 11-22 */ return code; } argcount = 0; break; default: return_error(e_typecheck); } } if (argcount) { *pnargs = argcount; return_error(e_typecheck); /* leftover args */ } } if (ups < UPS_SETBBOX) return_error(e_typecheck); /* no setbbox */ if (ups == UPS_SETBBOX && upath_compat) { /* * In CPSI compatibility mode, an empty path with a setbbox also * does a moveto (but only if the path is empty). Since setbbox * was the last operator, its operands are still on the o-stack. */ osp += 2; return zmoveto(i_ctx_p); } return 0; }