/* Check that a UID in a dictionary is equal to an existing, valid UID. */ bool dict_check_uid_param(const ref * pdict, const gs_uid * puid) { ref *puniqueid; if (uid_is_XUID(puid)) { uint size = uid_XUID_size(puid); uint i; if (dict_find_string(pdict, "XUID", &puniqueid) <= 0) return false; if (!r_has_type(puniqueid, t_array) || r_size(puniqueid) != size ) return false; for (i = 0; i < size; i++) { const ref *pvalue = puniqueid->value.const_refs + i; if (!r_has_type(pvalue, t_integer)) return false; if (pvalue->value.intval != uid_XUID_values(puid)[i]) return false; } return true; } else { if (dict_find_string(pdict, "UniqueID", &puniqueid) <= 0) return false; return (r_has_type(puniqueid, t_integer) && puniqueid->value.intval == puid->id); } }
/* (This is a single-use procedure, for clearer code.) */ static bool fid_eq(const gs_memory_t *mem, const gs_font *pfont1, const gs_font *pfont2) { while (pfont1->base != pfont1) pfont1 = pfont1->base; while (pfont2->base != pfont2) pfont2 = pfont2->base; if (pfont1 == pfont2) return true; switch (pfont1->FontType) { case 1: case 3: if (pfont1->FontType == pfont2->FontType) break; default: return false; } /* The following, while peculiar, appears to match CPSI. */ { const gs_uid *puid1 = &((const gs_font_base *)pfont1)->UID; const gs_uid *puid2 = &((const gs_font_base *)pfont2)->UID; if (uid_is_UniqueID(puid1) || uid_is_UniqueID(puid2) || ((uid_is_XUID(puid1) || uid_is_XUID(puid2)) && !uid_equal(puid1, puid2))) return false; } { const font_data *pfd1 = (const font_data *)pfont1->client_data; const font_data *pfd2 = (const font_data *)pfont2->client_data; if (!(obj_eq(mem, &pfd1->BuildChar, &pfd2->BuildChar) && obj_eq(mem, &pfd1->BuildGlyph, &pfd2->BuildGlyph) && obj_eq(mem, &pfd1->Encoding, &pfd2->Encoding) && obj_eq(mem, &pfd1->CharStrings, &pfd2->CharStrings))) return false; if (pfont1->FontType == 1) { ref *ppd1, *ppd2; if (dict_find_string(&pfd1->dict, "Private", &ppd1) > 0 && dict_find_string(&pfd2->dict, "Private", &ppd2) > 0 && !obj_eq(mem, ppd1, ppd2)) return false; } } return true; }
/* Write a UniqueID and/or XUID. */ static void write_uid(stream *s, const gs_uid *puid) { if (uid_is_UniqueID(puid)) pprintld1(s, "/UniqueID %ld def\n", puid->id); else if (uid_is_XUID(puid)) { uint i, n = uid_XUID_size(puid); stream_puts(s, "/XUID ["); for (i = 0; i < n; ++i) pprintld1(s, "%ld ", uid_XUID_values(puid)[i]); stream_puts(s, "] readonly def\n"); } }
/* Write a CMap in its standard (source) format. */ int psf_write_cmap(const gs_memory_t *mem, stream *s, const gs_cmap_t *pcmap, psf_put_name_chars_proc_t put_name_chars, const gs_const_string *alt_cmap_name, int font_index_only) { const gs_const_string *const cmap_name = (alt_cmap_name ? alt_cmap_name : &pcmap->CMapName); const gs_cid_system_info_t *const pcidsi = pcmap->CIDSystemInfo; switch (pcmap->CMapType) { case 0: case 1: case 2: break; default: return_error(gs_error_rangecheck); } /* Write the header. */ if (!pcmap->ToUnicode) { stream_puts(s, "%!PS-Adobe-3.0 Resource-CMap\n"); stream_puts(s, "%%DocumentNeededResources: ProcSet (CIDInit)\n"); stream_puts(s, "%%IncludeResource: ProcSet (CIDInit)\n"); pput_string_entry(s, "%%BeginResource: CMap (", cmap_name); pput_string_entry(s, ")\n%%Title: (", cmap_name); pput_string_entry(s, " ", &pcidsi->Registry); pput_string_entry(s, " ", &pcidsi->Ordering); pprintd1(s, " %d)\n", pcidsi->Supplement); pprintg1(s, "%%%%Version: %g\n", pcmap->CMapVersion); } stream_puts(s, "/CIDInit /ProcSet findresource begin\n"); stream_puts(s, "12 dict begin\nbegincmap\n"); /* Write the fixed entries. */ pprintd1(s, "/CMapType %d def\n", pcmap->CMapType); stream_puts(s, "/CMapName/"); put_name_chars(s, cmap_name->data, cmap_name->size); stream_puts(s, " def\n"); if (!pcmap->ToUnicode) { pprintg1(s, "/CMapVersion %g def\n", pcmap->CMapVersion); stream_puts(s, "/CIDSystemInfo"); if (font_index_only >= 0 && font_index_only < pcmap->num_fonts) { cmap_put_system_info(s, pcidsi + font_index_only); } else if (pcmap->num_fonts == 1) { cmap_put_system_info(s, pcidsi); } else { int i; pprintd1(s, " %d array\n", pcmap->num_fonts); for (i = 0; i < pcmap->num_fonts; ++i) { pprintd1(s, "dup %d", i); cmap_put_system_info(s, pcidsi + i); stream_puts(s, "put\n"); } } stream_puts(s, " def\n"); if (uid_is_XUID(&pcmap->uid)) { uint i, n = uid_XUID_size(&pcmap->uid); const long *values = uid_XUID_values(&pcmap->uid); stream_puts(s, "/XUID ["); for (i = 0; i < n; ++i) pprintld1(s, " %ld", values[i]); stream_puts(s, "] def\n"); } pprintld1(s, "/UIDOffset %ld def\n", pcmap->UIDOffset); pprintd1(s, "/WMode %d def\n", pcmap->WMode); } /* Write the code space ranges. */ { gs_cmap_ranges_enum_t renum; #define MAX_RANGES 100 gx_code_space_range_t ranges[MAX_RANGES]; int code, count = 0; for (gs_cmap_ranges_enum_init(pcmap, &renum); (code = gs_cmap_enum_next_range(&renum)) == 0; ) { if (count == MAX_RANGES) { cmap_put_ranges(s, ranges, count); count = 0; } ranges[count++] = renum.range; } if (code < 0) return code; if (count) cmap_put_ranges(s, ranges, count); #undef MAX_RANGES } /* Write the code and notdef data. */ { int code; code = cmap_put_code_map(mem, s, 1, pcmap, &cmap_notdef_operators, put_name_chars, font_index_only); if (code < 0) return code; code = cmap_put_code_map(mem, s, 0, pcmap, &cmap_cid_operators, put_name_chars, font_index_only); if (code < 0) return code; } /* Write the trailer. */ stream_puts(s, "endcmap\n"); stream_puts(s, "CMapName currentdict /CMap defineresource pop\nend end\n"); if (!pcmap->ToUnicode) { stream_puts(s, "%%EndResource\n"); stream_puts(s, "%%EOF\n"); } return 0; }
/* Remove entries from font and character caches. */ int font_restore(const alloc_save_t * save) { gs_memory_t *smem = gs_save_any_memory(save); gs_font_dir *pdir = smem->gs_lib_ctx->font_dir; const gs_memory_t *mem = 0; int code; if (pdir == 0) /* not initialized yet */ return 0; /* Purge original (unscaled) fonts. */ { gs_font *pfont; otop: for (pfont = pdir->orig_fonts; pfont != 0; pfont = pfont->next ) { mem = pfont->memory; if (alloc_is_since_save((char *)pfont, save)) { code = gs_purge_font(pfont); if (code < 0) return code; goto otop; } } } /* Purge cached scaled fonts. */ { gs_font *pfont; top: for (pfont = pdir->scaled_fonts; pfont != 0; pfont = pfont->next ) { if (alloc_is_since_save((char *)pfont, save)) { code = gs_purge_font(pfont); if (code < 0) return code; goto top; } } } /* Purge xfonts and uncached scaled fonts. */ { cached_fm_pair *pair; uint n; for (pair = pdir->fmcache.mdata, n = pdir->fmcache.mmax; n > 0; pair++, n-- ) if (!fm_pair_is_free(pair)) { #if 0 /* We disabled this code portion because gx_add_fm_pair now copied xvalues into a stable memory. */ if ((uid_is_XUID(&pair->UID) && alloc_is_since_save((char *)pair->UID.xvalues, save)) ) { code = gs_purge_fm_pair(pdir, pair, 0); if (code < 0) return code; continue; } #endif if (pair->font != 0 && alloc_is_since_save((char *)pair->font, save) ) { if (!uid_is_valid(&pair->UID)) gs_clean_fm_pair(pdir, pair); /* Don't discard pairs with a surviving UID. */ pair->font = 0; } if (pair->xfont != 0 && alloc_is_since_save((char *)pair->xfont, save) ) { code = gs_purge_fm_pair(pdir, pair, 1); if (code < 0) return code; } } } /* Purge characters with names about to be removed. */ /* We only need to do this if any new names have been created */ /* since the save. */ if (alloc_any_names_since_save(save)) gx_purge_selected_cached_chars(pdir, purge_if_name_removed, (void *)save); return 0; }