int charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask) { gs_text_enum_t *penum = op_show_find(i_ctx_p); gs_font *pfont; os_ptr op = osp; int code = font_param(op - 3, &pfont); if (code < 0) return code; if (penum == 0 || pfont->FontType >= sizeof(font_type_mask) * 8 || !(font_type_mask & (1 << (int)pfont->FontType))) return_error(e_undefined); code = charstring_execchar_aux(i_ctx_p, penum, pfont); if (code < 0 && igs->in_cachedevice == CACHE_DEVICE_CACHING) { /* Perform the cache cleanup, when the cached character data has been allocated (gx_alloc_char_bits) but the character has not been added to the cache (gx_add_cached_char) due to a falure in the character renderer. */ gs_show_enum *const penum_s = (gs_show_enum *)penum; if (penum_s->cc != NULL) { gx_free_cached_char(pfont->dir, penum_s->cc); penum_s->cc = NULL; } } return code; }
/* Make a transformed font (common code for makefont/scalefont). */ static int make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat) { os_ptr op = osp; os_ptr fp = op - 1; gs_font *oldfont, *newfont; int code; ref *pencoding = 0; code = font_param(fp, &oldfont); if (code < 0) return code; { uint space = ialloc_space(idmemory); ialloc_set_space(idmemory, r_space(fp)); if (dict_find_string(fp, "Encoding", &pencoding) > 0 && !r_is_array(pencoding) ) code = gs_note_error(e_invalidfont); else { /* * Temporarily substitute the new dictionary * for the old one, in case the Encoding changed. */ ref olddict; olddict = *pfont_dict(oldfont); *pfont_dict(oldfont) = *fp; code = gs_makefont(ifont_dir, oldfont, pmat, &newfont); *pfont_dict(oldfont) = olddict; } ialloc_set_space(idmemory, space); } if (code < 0) return code; /* * We have to allow for the possibility that the font's Encoding * is different from that of the base font. Note that the * font_data of the new font was simply copied from the old one. */ if (pencoding != 0 && !obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding) ) { if (newfont->FontType == ft_composite) return_error(e_rangecheck); /* We should really do validity checking here.... */ ref_assign(&pfont_data(newfont)->Encoding, pencoding); lookup_gs_simple_font_encoding((gs_font_base *) newfont); } *fp = *pfont_dict(newfont); pop(1); return 0; }
/* <font> setfont - */ int zsetfont(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_font *pfont; int code = font_param(op, &pfont); if (code < 0 || (code = gs_setfont(igs, pfont)) < 0) return code; pop(1); return code; }
/* <font> .registerfont - */ static int zregisterfont(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_font *pfont; int code = font_param(op, &pfont); if (code < 0) return code; pfont->is_resource = true; pop(1); return 0; }
/* <cid9font> <cid> .type9mapcid <charstring> <font_index> */ int ztype9mapcid(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_font *pfont; gs_font_cid0 *pfcid; int code = font_param(op - 1, &pfont); gs_glyph_data_t gdata; int fidx; if (code < 0) return code; if (pfont->FontType != ft_CID_encrypted) return_error(e_invalidfont); check_type(*op, t_integer); pfcid = (gs_font_cid0 *)pfont; gdata.memory = pfont->memory; code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, (gs_glyph)(gs_min_cid_glyph + op->value.intval), &gdata, &fidx); /* return code; original error-sensitive & fragile code */ if (code < 0) { /* failed to load glyph data, put CID 0 */ int default_fallback_CID = 0 ; if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval); op->value.intval = default_fallback_CID; /* reload glyph for default_fallback_CID */ code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, (gs_glyph)(gs_min_cid_glyph + default_fallback_CID), &gdata, &fidx); if (code < 0) { if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval); return_error(e_invalidfont); } } /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/ make_const_string(op - 1, a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory), gdata.bits.size, gdata.bits.data); make_int(op, fidx); return code; }
/* <file> <cid9font> .writefont9 - */ static int zwritefont9(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_font *pfont; gs_font_cid0 *pfcid; int code = font_param(op, &pfont); stream *s; if (code < 0) return code; if (pfont->FontType != ft_CID_encrypted) return_error(e_invalidfont); check_write_file(s, op - 1); pfcid = (gs_font_cid0 *)pfont; code = psf_write_cid0_font(s, pfcid, WRITE_TYPE2_NO_LENIV | WRITE_TYPE2_CHARSTRINGS, NULL, 0, NULL); if (code >= 0) pop(2); return code; }
/* <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */ static int zmakeglyph32(i_ctx_t *i_ctx_p) { os_ptr op = osp; bool long_form; uint msize; double metrics[10]; int wx, llx, lly, urx, ury; int width, height, raster; gs_font *pfont; int code; byte *str; check_array(op[-4]); msize = r_size(op - 4); switch (msize) { case 10: long_form = true; break; case 6: long_form = false; break; default: return_error(gs_error_rangecheck); } code = num_params(op[-4].value.refs + msize - 1, msize, metrics); if (code < 0) return code; if (~code & 0x3c) /* check llx .. ury for integers */ return_error(gs_error_typecheck); check_read_type(op[-3], t_string); llx = (int)metrics[2]; lly = (int)metrics[3]; urx = (int)metrics[4]; ury = (int)metrics[5]; width = urx - llx; height = ury - lly; raster = (width + 7) >> 3; if (width < 0 || height < 0 || r_size(op - 3) != raster * height) return_error(gs_error_rangecheck); check_int_leu(op[-2], 65535); code = font_param(op - 1, &pfont); if (code < 0) return code; if (pfont->FontType != ft_CID_bitmap) return_error(gs_error_invalidfont); check_write_type(*op, t_string); if (r_size(op) < 22) return_error(gs_error_rangecheck); str = op->value.bytes; if (long_form || metrics[0] != (wx = (int)metrics[0]) || metrics[1] != 0 || height == 0 || ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0 ) { /* Use the long form. */ int i, n = (long_form ? 10 : 6); str[0] = 0; str[1] = long_form; for (i = 0; i < n; ++i) { int v = (int)metrics[i]; /* no floating point widths yet */ str[2 + 2 * i] = (byte)(v >> 8); str[2 + 2 * i + 1] = (byte)v; } r_set_size(op, 2 + n * 2); } else {
/* * Check the path against FontBBox before drawing. The original operands * of type1execchar are still on the o-stack. * Returns exec_cont - a function, which must be called by caller after this function. */ static int bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *), op_proc_t *exec_cont) { os_ptr op = osp; gs_rect bbox; gs_font *pfont; gs_text_enum_t *penum; gs_font_base * pbfont; gs_font_type1 * pfont1; gs_type1exec_state cxs; int code; if (igs->in_cachedevice < 2) /* not caching */ return nobbox_draw(i_ctx_p, draw); if ((code = font_param(op - 3, &pfont)) < 0) return code; penum = op_show_find(i_ctx_p); if (penum == 0 || !font_uses_charstrings(pfont)) return_error(e_undefined); if ((code = gs_pathbbox(igs, &bbox)) < 0) { /* * If the matrix is singular, all user coordinates map onto a * straight line. Don't bother rendering the character at all. */ if (code == e_undefinedresult) { pop(4); gs_newpath(igs); return 0; } return code; } if (draw == gs_stroke) { /* Expand the bounding box by the line width. */ float width = gs_currentlinewidth(igs) * 1.41422; bbox.p.x -= width, bbox.p.y -= width; bbox.q.x += width, bbox.q.y += width; } pbfont = (gs_font_base *)pfont; if (rect_within(bbox, pbfont->FontBBox)) /* within bounds */ return nobbox_draw(i_ctx_p, draw); /* Enlarge the FontBBox to save work in the future. */ rect_merge(pbfont->FontBBox, bbox); /* Dismantle everything we've done, and start over. */ gs_text_retry(penum); pfont1 = (gs_font_type1 *) pfont; if ((penum->FontBBox_as_Metrics2.x == 0 && penum->FontBBox_as_Metrics2.y == 0) || gs_rootfont(igs)->WMode == 0 ) { code = zchar_get_metrics(pbfont, op - 1, cxs.sbw); if (code < 0) return code; cxs.present = code; cxs.use_FontBBox_as_Metrics2 = false; } else { cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2; cxs.sbw[1] = penum->FontBBox_as_Metrics2.y; cxs.sbw[2] = 0; cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */ cxs.use_FontBBox_as_Metrics2 = true; cxs.present = metricsSideBearingAndWidth; } code = type1_exec_init(&cxs.cis, penum, igs, pfont1); if (code < 0) return code; cxs.char_bbox = pfont1->FontBBox; code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, exec_cont); return code; }
static int bbox_finish(i_ctx_t *i_ctx_p, op_proc_t cont, op_proc_t *exec_cont) { /* Returns exec_cont - a function, which must be called by caller after this function. */ os_ptr op = osp; gs_font *pfont; int code; gs_text_enum_t *penum = op_show_find(i_ctx_p); gs_type1exec_state cxs; /* stack allocate to avoid sandbars */ gs_type1_state *const pcis = &cxs.cis; double sbxy[2]; gs_point sbpt; gs_point *psbpt = 0; os_ptr opc = op; const ref *opstr; ref other_subr; if (!r_has_type(opc, t_string)) { check_op(3); code = num_params(op, 2, sbxy); if (code < 0) return code; sbpt.x = sbxy[0]; sbpt.y = sbxy[1]; psbpt = &sbpt; opc -= 2; check_type(*opc, t_string); } code = font_param(opc - 3, &pfont); if (code < 0) return code; if (penum == 0 || !font_uses_charstrings(pfont)) return_error(e_undefined); { gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont; int lenIV = pfont1->data.lenIV; if (lenIV > 0 && r_size(opc) <= lenIV) return_error(e_invalidfont); check_estack(5); /* in case we need to do a callout */ code = type1_exec_init(pcis, penum, igs, pfont1); if (code < 0) return code; if (psbpt) gs_type1_set_lsb(pcis, psbpt); } opstr = opc; icont: code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, (psbpt ? 6 : 4)); op = osp; /* OtherSubrs might have altered it */ switch (code) { case 0: /* all done */ /* Call the continuation now. */ if (psbpt) pop(2); *exec_cont = cont; return 0; case type1_result_callothersubr: /* unknown OtherSubr */ push_op_estack(cont); /* call later */ return type1_call_OtherSubr(i_ctx_p, &cxs, bbox_continue, &other_subr); case type1_result_sbw: /* [h]sbw, just continue */ opstr = 0; goto icont; default: /* code < 0, error */ return code; } }