/* <proc> <string> kshow - */ static int zkshow(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_text_enum_t *penum; int code; check_read_type(*op, t_string); check_proc(op[-1]); /* * Per PLRM Section xx.x, kshow is illegal if the current font is a * composite font. The graphics library does not have this limitation, * so we check for it here. */ if (gs_currentfont(igs)->FontType == ft_composite) return_error(e_invalidfont); if ((code = op_show_setup(i_ctx_p, op)) != 0 || (code = gs_kshow_begin(igs, op->value.bytes, r_size(op), imemory, &penum)) < 0) return code; *(op_proc_t *)&penum->enum_client_data = zkshow; if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) { ifree_object(penum, "op_show_enum_setup"); return code; } sslot = op[-1]; /* save kerning proc */ return op_show_continue_pop(i_ctx_p, 2); }
/* <cx> <cy> <char> <string> widthshow - */ static int zwidthshow(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_text_enum_t *penum; double cxy[2]; int code; if ((code = op_show_setup(i_ctx_p, op)) != 0 ) return code; check_type(op[-1], t_integer); if (gs_currentfont(igs)->FontType == ft_composite) { if ((gs_char) (op[-1].value.intval) != op[-1].value.intval) return_error(e_rangecheck); } else { if (op[-1].value.intval < 0 || op[-1].value.intval > 255) return_error(e_rangecheck); /* per PLRM and CET 13-26 */ } if ((code = num_params(op - 2, 2, cxy)) < 0 ) return code; if ((code = gs_widthshow_begin(igs, cxy[0], cxy[1], (gs_char) op[-1].value.intval, op->value.bytes, r_size(op), imemory, &penum)) < 0) return code; *(op_proc_t *)&penum->enum_client_data = zwidthshow; if ((code = op_show_finish_setup(i_ctx_p, penum, 4, finish_show)) < 0) { ifree_object(penum, "op_show_enum_setup"); return code; } return op_show_continue_pop(i_ctx_p, 4); }
/* - currentfont <font> */ static int zcurrentfont(i_ctx_t *i_ctx_p) { os_ptr op = osp; push(1); *op = *pfont_dict(gs_currentfont(igs)); return 0; }
/* pcref points to a t_string ref. */ static int type1_continue_dispatch(i_ctx_t *i_ctx_p, gs_type1exec_state *pcxs, const ref * pcref, ref *pos, int num_args) { int value; int code; gs_glyph_data_t cs_data; gs_glyph_data_t *pcsd; cs_data.memory = imemory; if (pcref == 0) { pcsd = 0; } else { gs_glyph_data_from_string(&cs_data, pcref->value.const_bytes, r_size(pcref), NULL); pcsd = &cs_data; } /* * Since OtherSubrs may push or pop values on the PostScript operand * stack, remove the arguments of .type1execchar before calling the * Type 1 interpreter, and put them back afterwards unless we're * about to execute an OtherSubr procedure. Also, we must set up * the callback data for pushing OtherSubrs arguments. */ pcxs->i_ctx_p = i_ctx_p; pcxs->num_args = num_args; memcpy(pcxs->save_args, osp - (num_args - 1), num_args * sizeof(ref)); osp -= num_args; gs_type1_set_callback_data(&pcxs->cis, pcxs); code = pcxs->cis.pfont->data.interpret(&pcxs->cis, pcsd, &value); switch (code) { case type1_result_callothersubr: { /* * The Type 1 interpreter handles all known OtherSubrs, * so this must be an unknown one. */ const font_data *pfdata = pfont_data(gs_currentfont(igs)); code = array_get(imemory, &pfdata->u.type1.OtherSubrs, (long)value, pos); if (code >= 0) return type1_result_callothersubr; } } /* Put back the arguments removed above. */ memcpy(osp + 1, pcxs->save_args, num_args * sizeof(ref)); osp += num_args; return code; }
/* - .wrapfont - */ static int zwrapfont(i_ctx_t *i_ctx_p) { gs_font *font = gs_currentfont(igs); gs_font_type0 *font0; int wmode = 0; int code; switch (font->FontType) { case ft_TrueType: code = gs_font_type0_from_type42(&font0, (gs_font_type42 *)font, wmode, true, font->memory); if (code < 0) return code; /* * Patch up BuildChar and CIDMap. This isn't necessary for * TrueType fonts in general, only for Type 42 fonts whose * BuildChar is implemented in PostScript code. */ { font_data *pdata = pfont_data(font); const char *bgstr = "%Type11BuildGlyph"; ref temp; make_int(&temp, 0); ref_assign(&pdata->u.type42.CIDMap, &temp); code = name_ref((const byte *)bgstr, strlen(bgstr), &temp, 1); if (code < 0) return code; r_set_attrs(&temp, a_executable); ref_assign(&pdata->BuildGlyph, &temp); } break; case ft_CID_encrypted: case ft_CID_user_defined: case ft_CID_TrueType: code = gs_font_type0_from_cidfont(&font0, font, wmode, NULL, font->memory); break; default: return_error(e_rangecheck); } if (code < 0) return code; gs_setfont(igs, (gs_font *)font0); return 0; }
/* Common setup for glyphshow and .glyphwidth. */ static int glyph_show_setup(i_ctx_t *i_ctx_p, gs_glyph *pglyph) { os_ptr op = osp; switch (gs_currentfont(igs)->FontType) { case ft_CID_encrypted: case ft_CID_user_defined: case ft_CID_TrueType: case ft_CID_bitmap: check_int_leu(*op, gs_max_glyph - gs_min_cid_glyph); *pglyph = (gs_glyph) op->value.intval + gs_min_cid_glyph; break; default: check_type(*op, t_name); *pglyph = name_index(imemory, op); } return op_show_enum_setup(i_ctx_p); }
/* * 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); } }