int zchar_charstring_data(gs_font *font, const ref *pgref, gs_glyph_data_t *pgd) { ref *pcstr; if (dict_find(&pfont_data(font)->CharStrings, pgref, &pcstr) <= 0) return_error(e_undefined); if (!r_has_type(pcstr, t_string)) { /* * The ADOBEPS4 Windows driver replaces the .notdef entry of * otherwise normal Type 1 fonts with the procedure * {pop 0 0 setcharwidth} * To prevent this from making the font unembeddable in PDF files * (with our present font-writing code), we recognize this as a * special case and return a Type 1 CharString consisting of * 0 0 hsbw endchar */ if (font->FontType == ft_encrypted && charstring_is_notdef_proc(font->memory, pcstr) ) return charstring_make_notdef(pgd, font); else return_error(e_typecheck); } gs_glyph_data_from_string(pgd, pcstr->value.const_bytes, r_size(pcstr), NULL); return 0; }
static int charstring_make_notdef(gs_glyph_data_t *pgd, gs_font *font) { gs_font_type1 *const pfont = (gs_font_type1 *)font; static const byte char_data[4] = { 139, /* 0 */ 139, /* 0 */ c1_hsbw, cx_endchar }; uint len = max(pfont->data.lenIV, 0) + sizeof(char_data); byte *chars = gs_alloc_string(font->memory, len, "charstring_make_notdef"); if (chars == 0) return_error(e_VMerror); gs_glyph_data_from_string(pgd, chars, len, font); if (pfont->data.lenIV < 0) memcpy(chars, char_data, sizeof(char_data)); else { crypt_state state = crypt_charstring_seed; memcpy(chars + pfont->data.lenIV, char_data, sizeof(char_data)); gs_type1_encrypt(chars, chars, len, &state); } 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; }
/* Get bytes from GlyphData or DataSource. */ static int cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf, gs_glyph_data_t *pgd) { const font_data *pfdata = pfont_data(pfont); byte *data = buf; gs_font *gdfont = 0; /* pfont if newly allocated, 0 if not */ int code = 0; /* Check for overflow. */ if (base != (long)base || base > base + count) return_error(e_rangecheck); if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) { /* Get the bytes from GlyphData (a string or array of strings). */ const ref *pgdata = &pfdata->u.cid0.GlyphData; if (r_has_type(pgdata, t_string)) { /* single string */ uint size = r_size(pgdata); if (base >= size || count > size - base) return_error(e_rangecheck); data = pgdata->value.bytes + base; } else { /* array of strings */ /* * The algorithm is similar to the one in * string_array_access_proc in zfont42.c, but it also has to * deal with the case where the requested string crosses array * elements. */ ulong skip = base; uint copied = 0; uint index = 0; ref rstr; uint size; for (;; skip -= size, ++index) { int code = array_get(pfont->memory, pgdata, index, &rstr); if (code < 0) return code; if (!r_has_type(&rstr, t_string)) return_error(e_typecheck); size = r_size(&rstr); if (skip < size) break; } size -= skip; if (count <= size) { data = rstr.value.bytes + skip; } else { /* multiple strings needed */ if (data == 0) { /* no buffer provided */ data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes"); if (data == 0) return_error(e_VMerror); gdfont = (gs_font *)pfont; /* newly allocated */ } memcpy(data, rstr.value.bytes + skip, size); copied = size; while (copied < count) { int code = array_get(pfont->memory, pgdata, ++index, &rstr); if (code < 0) goto err; if (!r_has_type(&rstr, t_string)) { code = gs_note_error(e_typecheck); goto err; } size = r_size(&rstr); if (size > count - copied) size = count - copied; memcpy(data + copied, rstr.value.bytes, size); copied += size; } } } } else { /* Get the bytes from DataSource (a stream). */ stream *s; uint nread; i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p; check_read_known_file(i_ctx_p, s, &pfdata->u.cid0.DataSource, return_error); if (sseek(s, base) < 0) return_error(e_ioerror); if (data == 0) { /* no buffer provided */ data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes"); if (data == 0) return_error(e_VMerror); gdfont = (gs_font *)pfont; /* newly allocated */ } if (sgets(s, data, count, &nread) < 0 || nread != count) { code = gs_note_error(e_ioerror); goto err; } } gs_glyph_data_from_string(pgd, data, count, gdfont); return code; err: if (data != buf) gs_free_string(pfont->memory, data, count, "cid0_read_bytes"); return code; }