int build_gs_FDArray_font(i_ctx_t *i_ctx_p, ref *op, gs_font_base **ppfont, font_type ftype, gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild) { gs_font_base *pfont; font_data *pdata; int code = build_gs_outline_font(i_ctx_p, op, &pfont, ftype, pstype, pbuild, bf_options_none, build_FDArray_sub_font); static const double bbox[4] = { 0, 0, 0, 0 }; gs_uid uid; if (code < 0) return code; pdata = pfont_data(pfont); /* Fill in members normally set by build_gs_primitive_font. */ make_null(&pdata->CharStrings); /* Fill in members normally set by build_gs_simple_font. */ uid_set_invalid(&uid); init_gs_simple_font(pfont, bbox, &uid); pfont->encoding_index = ENCODING_INDEX_UNKNOWN; pfont->nearest_encoding_index = ENCODING_INDEX_UNKNOWN; /* Fill in members normally set by build_gs_font. */ pfont->key_name = pfont->font_name; *ppfont = pfont; return 0; }
/* The caller guarantees that *op is a dictionary. */ int build_gs_primitive_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont, font_type ftype, gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild, build_font_options_t options) { ref *pcharstrings = 0; ref CharStrings; gs_font_base *pfont; font_data *pdata; int code; if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) { if (!(options & bf_CharStrings_optional)) return_error(e_invalidfont); } else { ref *ignore; if (!r_has_type(pcharstrings, t_dictionary)) return_error(e_invalidfont); if ((options & bf_notdef_required) != 0 && dict_find_string(pcharstrings, ".notdef", &ignore) <= 0 ) return_error(e_invalidfont); /* * Since build_gs_simple_font may resize the dictionary and cause * pointers to become invalid, save CharStrings. */ CharStrings = *pcharstrings; } code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild, options, build_gs_simple_font); if (code != 0) return code; pfont = *ppfont; pdata = pfont_data(pfont); if (pcharstrings) ref_assign(&pdata->CharStrings, &CharStrings); else make_null(&pdata->CharStrings); /* Check that the UniqueIDs match. This is part of the */ /* Adobe protection scheme, but we may as well emulate it. */ if (uid_is_valid(&pfont->UID) && !dict_check_uid_param(op, &pfont->UID) ) uid_set_invalid(&pfont->UID); if (uid_is_valid(&pfont->UID)) { const gs_font *pfont0 = (const gs_font *)pfont; code = gs_font_find_similar(ifont_dir, &pfont0, font_with_same_UID_and_another_metrics); if (code < 0) return code; /* Must not happen. */ if (code) uid_set_invalid(&pfont->UID); } 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; }