/* * Get the additional parameters for a Type 2 font (or FontType 2 FDArray * entry in a CIDFontType 0 font), beyond those common to Type 1 and Type 2 * fonts. */ int type2_font_params(const_os_ptr op, charstring_font_refs_t *pfr, gs_type1_data *pdata1) { int code; float dwx, nwx; ref *temp; pdata1->interpret = gs_type2_interpret; pdata1->lenIV = DEFAULT_LENIV_2; pdata1->subroutineNumberBias = subr_bias(pfr->Subrs); /* Get information specific to Type 2 fonts. */ if (dict_find_string(pfr->Private, "GlobalSubrs", &temp) > 0) { if (!r_is_array(temp)) return_error(e_typecheck); pfr->GlobalSubrs = temp; } pdata1->gsubrNumberBias = subr_bias(pfr->GlobalSubrs); if ((code = dict_uint_param(pfr->Private, "gsubrNumberBias", 0, max_uint, pdata1->gsubrNumberBias, &pdata1->gsubrNumberBias)) < 0 || (code = dict_float_param(pfr->Private, "defaultWidthX", 0.0, &dwx)) < 0 || (code = dict_float_param(pfr->Private, "nominalWidthX", 0.0, &nwx)) < 0 ) return code; pdata1->defaultWidthX = float2fixed(dwx); pdata1->nominalWidthX = float2fixed(nwx); { ref *pirs; if (dict_find_string(pfr->Private, "initialRandomSeed", &pirs) <= 0) pdata1->initialRandomSeed = 0; else if (!r_has_type(pirs, t_integer)) return_error(e_typecheck); else pdata1->initialRandomSeed = pirs->value.intval; } return 0; }
/* <string|name> <font_dict> .buildfont9 <string|name> <font> */ static int zbuildfont9(i_ctx_t *i_ctx_p) { os_ptr op = osp; build_proc_refs build; int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph"); gs_font_cid_data common; ref GlyphDirectory, GlyphData, DataSource; ref *prfda, cfnstr; ref *pCIDFontName, CIDFontName; gs_font_type1 **FDArray; uint FDArray_size; int FDBytes; uint CIDMapOffset; gs_font_base *pfont; gs_font_cid0 *pfcid; uint i; /* * If the CIDFont's data have been loaded into VM, GlyphData will be * a string or an array of strings; if they are loaded incrementally * from a file, GlyphData will be an integer, and DataSource will be * a (reusable) stream. */ if (code < 0 || (code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 || (code = dict_find_string(op, "FDArray", &prfda)) < 0 || (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 || (code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0 ) return code; /* * Since build_gs_simple_font may resize the dictionary and cause * pointers to become invalid, save CIDFontName */ CIDFontName = *pCIDFontName; if (r_has_type(&GlyphDirectory, t_null)) { /* Standard CIDFont, require GlyphData and CIDMapOffset. */ ref *pGlyphData; if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 || (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1, max_uint, &CIDMapOffset)) < 0) return code; GlyphData = *pGlyphData; if (r_has_type(&GlyphData, t_integer)) { ref *pds; stream *ignore_s; if ((code = dict_find_string(op, "DataSource", &pds)) < 0) return code; check_read_file(i_ctx_p, ignore_s, pds); DataSource = *pds; } else { if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData)) return_error(e_typecheck); make_null(&DataSource); } } else { make_null(&GlyphData); make_null(&DataSource); CIDMapOffset = 0; } if (!r_is_array(prfda)) return_error(e_invalidfont); FDArray_size = r_size(prfda); if (FDArray_size == 0) return_error(e_invalidfont); FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *, &st_gs_font_type1_ptr_element, "buildfont9(FDarray)"); if (FDArray == 0) return_error(e_VMerror); memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size); for (i = 0; i < FDArray_size; ++i) { ref rfd; array_get(imemory, prfda, (long)i, &rfd); code = fd_array_element(i_ctx_p, &FDArray[i], &rfd); if (code < 0) goto fail; } code = build_gs_outline_font(i_ctx_p, op, &pfont, ft_CID_encrypted, &st_gs_font_cid0, &build, bf_Encoding_optional | bf_UniqueID_ignored, build_gs_simple_font); if (code < 0) goto fail; if (code == 1) { /* The font already has a FID, don't need to build it again. Release FDArray and return normally. fixme: FDArray fonts are thrown for garbager. We're not safe to build them after build_gs_simple_font(..., &pfont, ...), because a failure in building them would throw an underbuilt font with unclear consequences. */ ifree_object(FDArray, "buildfont9(FDarray)"); return 0; } pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph; pfont->procs.glyph_outline = z9_glyph_outline; pfont->procs.glyph_info = z9_glyph_info; pfcid = (gs_font_cid0 *)pfont; pfcid->cidata.common = common; pfcid->cidata.CIDMapOffset = CIDMapOffset; pfcid->cidata.FDArray = FDArray; pfcid->cidata.FDArray_size = FDArray_size; pfcid->cidata.FDBytes = FDBytes; pfcid->cidata.glyph_data = z9_glyph_data; pfcid->cidata.proc_data = 0; /* for GC */ if (pfcid->font_name.size == 0) { get_font_name(imemory, &cfnstr, &CIDFontName); copy_font_name(&pfcid->font_name, &cfnstr); } ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory); ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData); ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource); code = define_gs_font(i_ctx_p, (gs_font *)pfont); if (code >= 0) code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont); if (code >= 0) { for (i = 0; i < FDArray_size; ++i) { FDArray[i]->dir = pfont->dir; FDArray[i]->data.parent = pfont; } return code; } fail: ifree_object(FDArray, "buildfont9(FDarray)"); return code; }
/* Common setup for encoding and decoding filters */ static int bhc_setup(os_ptr op, stream_BHC_state * pbhcs) { int code; int num_counts; int data[max_hc_length + 1 + 256 + max_zero_run + 1]; uint dsize; int i; uint num_values, accum; ushort *counts; ushort *values; check_type(*op, t_dictionary); check_dict_read(*op); if ((code = dict_bool_param(op, "FirstBitLowOrder", false, &pbhcs->FirstBitLowOrder)) < 0 || (code = dict_int_param(op, "MaxCodeLength", 1, max_hc_length, max_hc_length, &num_counts)) < 0 || (code = dict_bool_param(op, "EndOfData", true, &pbhcs->EndOfData)) < 0 || (code = dict_uint_param(op, "EncodeZeroRuns", 2, 256, 256, &pbhcs->EncodeZeroRuns)) < 0 || /* Note: the code returned from the following call */ /* is actually the number of elements in the array. */ (code = dict_int_array_param(imemory, op, "Tables", countof(data), data)) <= 0 ) return (code < 0 ? code : gs_note_error(e_rangecheck)); dsize = code; if (dsize <= num_counts + 2) return_error(e_rangecheck); for (i = 0, num_values = 0, accum = 0; i <= num_counts; i++, accum <<= 1 ) { int count = data[i]; if (count < 0) return_error(e_rangecheck); num_values += count; accum += count; } if (dsize != num_counts + 1 + num_values || accum != 1 << (num_counts + 1) || pbhcs->EncodeZeroRuns > (pbhcs->EndOfData ? num_values - 1 : num_values) ) return_error(e_rangecheck); for (; i < num_counts + 1 + num_values; i++) { int value = data[i]; if (value < 0 || value >= num_values) return_error(e_rangecheck); } pbhcs->definition.counts = counts = (ushort *) ialloc_byte_array(num_counts + 1, sizeof(ushort), "bhc_setup(counts)"); pbhcs->definition.values = values = (ushort *) ialloc_byte_array(num_values, sizeof(ushort), "bhc_setup(values)"); if (counts == 0 || values == 0) { ifree_object(values, "bhc_setup(values)"); ifree_object(counts, "bhc_setup(counts)"); return_error(e_VMerror); } for (i = 0; i <= num_counts; i++) counts[i] = data[i]; pbhcs->definition.counts = counts; pbhcs->definition.num_counts = num_counts; for (i = 0; i < num_values; i++) values[i] = data[i + num_counts + 1]; pbhcs->definition.values = values; pbhcs->definition.num_values = num_values; return 0; }
/* <source> <dict> eexecDecode/filter <file> */ static int zexD(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_exD_state state; int code; (*s_exD_template.set_defaults)((stream_state *)&state); if (r_has_type(op, t_dictionary)) { uint cstate; bool is_eexec; check_dict_read(*op); if ((code = dict_uint_param(op, "seed", 0, 0xffff, 0x10000, &cstate)) < 0 || (code = dict_int_param(op, "lenIV", 0, max_int, 4, &state.lenIV)) < 0 || (code = dict_bool_param(op, "eexec", false, &is_eexec)) < 0 || (code = dict_bool_param(op, "keep_spaces", false, &state.keep_spaces)) < 0 ) return code; state.cstate = cstate; state.binary = (is_eexec ? -1 : 1); code = 1; } else { state.binary = 1; code = eexec_param(op, &state.cstate); } if (code < 0) return code; /* * If we're reading a .PFB file, let the filter know about it, * so it can read recklessly to the end of the binary section. */ if (r_has_type(op - 1, t_file)) { stream *s = (op - 1)->value.pfile; if (s->state != 0 && s->state->templat == &s_PFBD_template) { stream_PFBD_state *pss = (stream_PFBD_state *)s->state; state.pfb_state = pss; /* * If we're reading the binary section of a PFB stream, * avoid the conversion from binary to hex and back again. */ if (pss->record_type == 2) { /* * The PFB decoder may have converted some data to hex * already. Convert it back if necessary. */ if (pss->binary_to_hex && sbufavailable(s) > 0) { state.binary = 0; /* start as hex */ state.hex_left = sbufavailable(s); } else { state.binary = 1; } pss->binary_to_hex = 0; } } } return filter_read(i_ctx_p, code, &s_exD_template, (stream_state *)&state, 0); }