/* The caller guarantees that *op is a dictionary. */ int build_gs_sub_font(i_ctx_t *i_ctx_p, const ref *op, gs_font **ppfont, font_type ftype, gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild, const ref *pencoding, ref *fid_op) { gs_matrix mat, omat; ref fname; /* t_string */ gs_font *pfont; font_data *pdata; /* * Make sure that we allocate the font data * in the same VM as the font dictionary. */ uint space = ialloc_space(idmemory); int code = sub_font_params(imemory, op, &mat, &omat, &fname); if (code < 0) return code; ialloc_set_space(idmemory, r_space(op)); pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL, "buildfont(font)"); pdata = ialloc_struct(font_data, &st_font_data, "buildfont(data)"); if (pfont == 0 || pdata == 0) code = gs_note_error(e_VMerror); else if (fid_op) code = add_FID(i_ctx_p, fid_op, pfont, iimemory); if (code < 0) { ifree_object(pdata, "buildfont(data)"); ifree_object(pfont, "buildfont(font)"); ialloc_set_space(idmemory, space); return code; } refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref)); ref_assign_new(&pdata->dict, op); ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar); ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph); if (pencoding) ref_assign_new(&pdata->Encoding, pencoding); pfont->client_data = pdata; pfont->FontType = ftype; pfont->FontMatrix = mat; pfont->orig_FontMatrix = omat; pfont->BitmapWidths = false; pfont->ExactSize = fbit_use_bitmaps; pfont->InBetweenSize = fbit_use_outlines; pfont->TransformedChar = fbit_use_outlines; pfont->WMode = 0; pfont->procs.encode_char = zfont_encode_char; pfont->procs.glyph_name = zfont_glyph_name; ialloc_set_space(idmemory, space); copy_font_name(&pfont->font_name, &fname); *ppfont = pfont; return 0; }
void refcpy_to_new(ref * to, const ref * from, uint size, gs_dual_memory_t *idmemory) { while (size--) ref_assign_new(to, from), to++, from++; }
/* Create and store [/key any] array in $error.errorinfo. * The key must be a permanently allocated C string. * This routine is here because it is often used with parameter dictionaries. */ int gs_errorinfo_put_pair(i_ctx_t *i_ctx_p, const char *key, int len, const ref *any) { int code; ref pair, *aptr, key_name, *pderror; code = name_ref(imemory_local, (const byte *)key, len, &key_name, 0); if (code < 0) return code; code = gs_alloc_ref_array(iimemory_local, &pair, a_readonly, 2, "gs_errorinfo_put_pair"); if (code < 0) return code; aptr = pair.value.refs; ref_assign_new(aptr, &key_name); ref_assign_new(aptr+1, any); if (dict_find_string(systemdict, "$error", &pderror) <= 0 || !r_has_type(pderror, t_dictionary) || idict_put_string(pderror, "errorinfo", &pair) < 0 ) return_error(e_Fatal); return 0; }
void get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref) { ref *pfontinfo = NULL, *g2u = NULL; font_data *pdata; if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 || !r_has_type(pfontinfo, t_dictionary) || dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 || !r_has_type(pfontinfo, t_dictionary)) return; /* * Since build_gs_font may resize the dictionary and cause * pointers to become invalid, save Glyph2Unicode */ pdata = pfont_data(pfont); ref_assign_new(&pdata->GlyphNames2Unicode, g2u); }
/* ensuring that refs in mixed arrays are properly aligned. */ #undef idmemory /****** NOTA BENE ******/ int make_packed_array(ref * parr, ref_stack_t * pstack, uint size, gs_dual_memory_t *idmemory, client_name_t cname) { uint i; const ref *pref; uint idest = 0, ishort = 0; ref_packed *pbody; ref_packed *pdest; ref_packed *pshort; /* points to start of */ /* last run of short elements */ gs_ref_memory_t *imem = idmemory->current; uint space = imemory_space(imem); int skip = 0, pad; ref rtemp; int code; /* Do a first pass to calculate the size of the array, */ /* and to detect local-into-global stores. */ for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: if (name_index(imem, pref) >= packed_name_max_index) break; /* can't pack */ idest++; continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; idest++; continue; case t_oparray: /* Check for local-into-global store. */ store_check_space(space, pref); /* falls through */ case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; } idest++; continue; default: /* Check for local-into-global store. */ store_check_space(space, pref); } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* If we are at the beginning of the array, however, */ /* we can just move the elements up. */ { int i = (idest - ishort) & (align_packed_per_ref - 1); if (ishort == 0) /* first time */ idest += skip = -i & (align_packed_per_ref - 1); else idest += (packed_per_ref - 1) * i; } ishort = idest += packed_per_ref; } pad = -(int)idest & (packed_per_ref - 1); /* padding at end */ /* Now we can allocate the array. */ code = gs_alloc_ref_array(imem, &rtemp, 0, (idest + pad) / packed_per_ref, cname); if (code < 0) return code; pbody = (ref_packed *) rtemp.value.refs; /* Make sure any initial skipped elements contain legal packed */ /* refs, so that the garbage collector can scan storage. */ pshort = pbody; for (; skip; skip--) *pbody++ = pt_tag(pt_integer); pdest = pbody; for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: { uint nidx = name_index(imem, pref); if (nidx >= packed_name_max_index) break; /* can't pack */ *pdest++ = nidx + (r_has_attr(pref, a_executable) ? pt_tag(pt_executable_name) : pt_tag(pt_literal_name)); } continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; *pdest++ = pt_tag(pt_integer) + ((short)pref->value.intval - packed_min_intval); continue; case t_oparray: case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; *pdest++ = pt_tag(pt_executable_operator) + oidx; } continue; } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* Note that if we are at the beginning of the array, */ /* 'skip' already ensures that we don't need to do this. */ { int i = (pdest - pshort) & (align_packed_per_ref - 1); const ref_packed *psrc = pdest; ref *pmove = (ref *) (pdest += (packed_per_ref - 1) * i); ref_assign_new(pmove, pref); while (--i >= 0) { --psrc; --pmove; packed_get(imem->non_gc_memory, psrc, pmove); } } pshort = pdest += packed_per_ref; } { int atype = (pdest == pbody + size ? t_shortarray : t_mixedarray); /* Pad with legal packed refs so that the garbage collector */ /* can scan storage. */ for (; pad; pad--) *pdest++ = pt_tag(pt_integer); /* Finally, make the array. */ ref_stack_pop(pstack, size); make_tasv_new(parr, atype, a_readonly | space, size, packed, pbody + skip); } return 0; }