17dd7cddfSDavid du Colombier /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gsfont.c,v 1.37 2005/07/27 11:24:38 igor Exp $ */
187dd7cddfSDavid du Colombier /* Font operators for Ghostscript library */
197dd7cddfSDavid du Colombier #include "gx.h"
207dd7cddfSDavid du Colombier #include "memory_.h"
217dd7cddfSDavid du Colombier #include "gserrors.h"
227dd7cddfSDavid du Colombier #include "gsstruct.h"
237dd7cddfSDavid du Colombier #include "gsutil.h"
247dd7cddfSDavid du Colombier #include "gxfixed.h"
257dd7cddfSDavid du Colombier #include "gxmatrix.h"
267dd7cddfSDavid du Colombier #include "gzstate.h" /* must precede gxdevice */
277dd7cddfSDavid du Colombier #include "gxdevice.h" /* must precede gxfont */
287dd7cddfSDavid du Colombier #include "gxfont.h"
297dd7cddfSDavid du Colombier #include "gxfcache.h"
30*593dc095SDavid du Colombier #include "gzpath.h" /* for default implementation */
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /* Define the sizes of the various aspects of the font/character cache. */
337dd7cddfSDavid du Colombier /*** Big memory machines ***/
347dd7cddfSDavid du Colombier #define smax_LARGE 50 /* smax - # of scaled fonts */
357dd7cddfSDavid du Colombier #define bmax_LARGE 500000 /* bmax - space for cached chars */
367dd7cddfSDavid du Colombier #define mmax_LARGE 200 /* mmax - # of cached font/matrix pairs */
377dd7cddfSDavid du Colombier #define cmax_LARGE 5000 /* cmax - # of cached chars */
387dd7cddfSDavid du Colombier #define blimit_LARGE 2500 /* blimit/upper - max size of a single cached char */
397dd7cddfSDavid du Colombier /*** Small memory machines ***/
407dd7cddfSDavid du Colombier #define smax_SMALL 20 /* smax - # of scaled fonts */
417dd7cddfSDavid du Colombier #define bmax_SMALL 25000 /* bmax - space for cached chars */
427dd7cddfSDavid du Colombier #define mmax_SMALL 40 /* mmax - # of cached font/matrix pairs */
437dd7cddfSDavid du Colombier #define cmax_SMALL 500 /* cmax - # of cached chars */
447dd7cddfSDavid du Colombier #define blimit_SMALL 100 /* blimit/upper - max size of a single cached char */
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier /* Define a default procedure vector for fonts. */
477dd7cddfSDavid du Colombier const gs_font_procs gs_font_procs_default = {
487dd7cddfSDavid du Colombier gs_no_define_font, /* (actually a default) */
497dd7cddfSDavid du Colombier gs_no_make_font, /* (actually a default) */
507dd7cddfSDavid du Colombier gs_default_font_info,
517dd7cddfSDavid du Colombier gs_default_same_font,
527dd7cddfSDavid du Colombier gs_no_encode_char,
53*593dc095SDavid du Colombier gs_no_decode_glyph,
547dd7cddfSDavid du Colombier gs_no_enumerate_glyph,
557dd7cddfSDavid du Colombier gs_default_glyph_info,
567dd7cddfSDavid du Colombier gs_no_glyph_outline,
57*593dc095SDavid du Colombier gs_no_glyph_name,
587dd7cddfSDavid du Colombier gs_default_init_fstack,
597dd7cddfSDavid du Colombier gs_default_next_char_glyph,
60*593dc095SDavid du Colombier gs_no_build_char
617dd7cddfSDavid du Colombier };
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier private_st_font_dir();
647dd7cddfSDavid du Colombier private struct_proc_enum_ptrs(font_enum_ptrs);
657dd7cddfSDavid du Colombier private struct_proc_reloc_ptrs(font_reloc_ptrs);
667dd7cddfSDavid du Colombier
67*593dc095SDavid du Colombier public_st_gs_font_info();
687dd7cddfSDavid du Colombier public_st_gs_font();
697dd7cddfSDavid du Colombier public_st_gs_font_base();
707dd7cddfSDavid du Colombier private_st_gs_font_ptr();
717dd7cddfSDavid du Colombier public_st_gs_font_ptr_element();
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier /*
747dd7cddfSDavid du Colombier * Garbage collection of fonts poses some special problems. On the one
757dd7cddfSDavid du Colombier * hand, we need to keep track of all existing base (not scaled) fonts,
767dd7cddfSDavid du Colombier * using the next/prev list whose head is the orig_fonts member of the font
777dd7cddfSDavid du Colombier * directory; on the other hand, we want these to be "weak" pointers that
787dd7cddfSDavid du Colombier * don't keep fonts in existence if the fonts aren't referenced from
797dd7cddfSDavid du Colombier * anywhere else. We accomplish this as follows:
807dd7cddfSDavid du Colombier *
817dd7cddfSDavid du Colombier * We don't trace through gs_font_dir.orig_fonts or gs_font.{next,prev}
827dd7cddfSDavid du Colombier * during the mark phase of the GC.
837dd7cddfSDavid du Colombier *
847dd7cddfSDavid du Colombier * When we finalize a base gs_font, we unlink it from the list. (A
857dd7cddfSDavid du Colombier * gs_font is a base font iff its base member points to itself.)
867dd7cddfSDavid du Colombier *
877dd7cddfSDavid du Colombier * We *do* relocate the orig_fonts and next/prev pointers during the
887dd7cddfSDavid du Colombier * relocation phase of the GC. */
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier /* Font directory GC procedures */
917dd7cddfSDavid du Colombier private
ENUM_PTRS_WITH(font_dir_enum_ptrs,gs_font_dir * dir)927dd7cddfSDavid du Colombier ENUM_PTRS_WITH(font_dir_enum_ptrs, gs_font_dir *dir)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier /* Enumerate pointers from cached characters to f/m pairs, */
957dd7cddfSDavid du Colombier /* and mark the cached character glyphs. */
967dd7cddfSDavid du Colombier /* See gxfcache.h for why we do this here. */
977dd7cddfSDavid du Colombier uint cci = index - st_font_dir_max_ptrs;
987dd7cddfSDavid du Colombier uint offset, count;
997dd7cddfSDavid du Colombier uint tmask = dir->ccache.table_mask;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier if (cci == 0)
1027dd7cddfSDavid du Colombier offset = 0, count = 1;
1037dd7cddfSDavid du Colombier else if (cci == dir->enum_index + 1)
1047dd7cddfSDavid du Colombier offset = dir->enum_offset + 1, count = 1;
1057dd7cddfSDavid du Colombier else
1067dd7cddfSDavid du Colombier offset = 0, count = cci;
1077dd7cddfSDavid du Colombier for (; offset <= tmask; ++offset) {
1087dd7cddfSDavid du Colombier cached_char *cc = dir->ccache.table[offset];
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier if (cc != 0 && !--count) {
1117dd7cddfSDavid du Colombier (*dir->ccache.mark_glyph)
112*593dc095SDavid du Colombier (mem, cc->code, dir->ccache.mark_glyph_data);
1137dd7cddfSDavid du Colombier /****** HACK: break const. We'll fix this someday. ******/
1147dd7cddfSDavid du Colombier ((gs_font_dir *)dir)->enum_index = cci;
1157dd7cddfSDavid du Colombier ((gs_font_dir *)dir)->enum_offset = offset;
1167dd7cddfSDavid du Colombier ENUM_RETURN(cc_pair(cc) - cc->pair_index);
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier }
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier return 0;
1217dd7cddfSDavid du Colombier #define e1(i,elt) ENUM_PTR(i,gs_font_dir,elt);
1227dd7cddfSDavid du Colombier font_dir_do_ptrs(e1)
1237dd7cddfSDavid du Colombier #undef e1
1247dd7cddfSDavid du Colombier ENUM_PTRS_END
1257dd7cddfSDavid du Colombier private RELOC_PTRS_WITH(font_dir_reloc_ptrs, gs_font_dir *dir);
1267dd7cddfSDavid du Colombier /* Relocate the pointers from cached characters to f/m pairs. */
1277dd7cddfSDavid du Colombier /* See gxfcache.h for why we do this here. */
1287dd7cddfSDavid du Colombier {
1297dd7cddfSDavid du Colombier int chi;
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier for (chi = dir->ccache.table_mask; chi >= 0; --chi) {
1327dd7cddfSDavid du Colombier cached_char *cc = dir->ccache.table[chi];
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier if (cc != 0)
1357dd7cddfSDavid du Colombier cc_set_pair_only(cc,
1367dd7cddfSDavid du Colombier (cached_fm_pair *)
1377dd7cddfSDavid du Colombier RELOC_OBJ(cc_pair(cc) - cc->pair_index) +
1387dd7cddfSDavid du Colombier cc->pair_index);
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier /* We have to relocate the cached characters before we */
1427dd7cddfSDavid du Colombier /* relocate dir->ccache.table! */
1437dd7cddfSDavid du Colombier RELOC_PTR(gs_font_dir, orig_fonts);
1447dd7cddfSDavid du Colombier #define r1(i,elt) RELOC_PTR(gs_font_dir, elt);
font_dir_do_ptrs(r1)1457dd7cddfSDavid du Colombier font_dir_do_ptrs(r1)
1467dd7cddfSDavid du Colombier #undef r1
1477dd7cddfSDavid du Colombier RELOC_PTRS_END
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier /* GC procedures for fonts */
1507dd7cddfSDavid du Colombier /*
1517dd7cddfSDavid du Colombier * When we finalize a base font, we unlink it from the orig_fonts list;
1527dd7cddfSDavid du Colombier * when we finalize a scaled font, we unlink it from scaled_fonts.
1537dd7cddfSDavid du Colombier * See above for more information.
1547dd7cddfSDavid du Colombier */
1557dd7cddfSDavid du Colombier void
1567dd7cddfSDavid du Colombier gs_font_finalize(void *vptr)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier gs_font *const pfont = vptr;
1597dd7cddfSDavid du Colombier gs_font **ppfirst;
1607dd7cddfSDavid du Colombier gs_font *next = pfont->next;
1617dd7cddfSDavid du Colombier gs_font *prev = pfont->prev;
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier if_debug4('u', "[u]unlinking font 0x%lx, base=0x%lx, prev=0x%lx, next=0x%lx\n",
1647dd7cddfSDavid du Colombier (ulong) pfont, (ulong) pfont->base, (ulong) prev, (ulong) next);
1657dd7cddfSDavid du Colombier /* Notify clients that the font is being freed. */
1667dd7cddfSDavid du Colombier gs_notify_all(&pfont->notify_list, NULL);
1677dd7cddfSDavid du Colombier if (pfont->dir == 0)
1687dd7cddfSDavid du Colombier ppfirst = 0;
1697dd7cddfSDavid du Colombier else if (pfont->base == pfont)
1707dd7cddfSDavid du Colombier ppfirst = &pfont->dir->orig_fonts;
1717dd7cddfSDavid du Colombier else {
1727dd7cddfSDavid du Colombier /*
1737dd7cddfSDavid du Colombier * Track the number of cached scaled fonts. Only decrement the
1747dd7cddfSDavid du Colombier * count if we didn't do this already in gs_makefont.
1757dd7cddfSDavid du Colombier */
1767dd7cddfSDavid du Colombier if (next || prev || pfont->dir->scaled_fonts == pfont)
1777dd7cddfSDavid du Colombier pfont->dir->ssize--;
1787dd7cddfSDavid du Colombier ppfirst = &pfont->dir->scaled_fonts;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier /*
1817dd7cddfSDavid du Colombier * gs_purge_font may have unlinked this font already:
1827dd7cddfSDavid du Colombier * don't unlink it twice.
1837dd7cddfSDavid du Colombier */
1847dd7cddfSDavid du Colombier if (next != 0 && next->prev == pfont)
1857dd7cddfSDavid du Colombier next->prev = prev;
1867dd7cddfSDavid du Colombier if (prev != 0) {
1877dd7cddfSDavid du Colombier if (prev->next == pfont)
1887dd7cddfSDavid du Colombier prev->next = next;
1897dd7cddfSDavid du Colombier } else if (ppfirst != 0 && *ppfirst == pfont)
1907dd7cddfSDavid du Colombier *ppfirst = next;
1917dd7cddfSDavid du Colombier gs_notify_release(&pfont->notify_list);
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier private
1947dd7cddfSDavid du Colombier ENUM_PTRS_WITH(font_enum_ptrs, gs_font *pfont) return ENUM_USING(st_gs_notify_list, &pfont->notify_list, sizeof(gs_notify_list_t), index - 5);
1957dd7cddfSDavid du Colombier /* We don't enumerate next or prev of base fonts. */
1967dd7cddfSDavid du Colombier /* See above for details. */
1977dd7cddfSDavid du Colombier case 0: ENUM_RETURN((pfont->base == pfont ? 0 : pfont->next));
1987dd7cddfSDavid du Colombier case 1: ENUM_RETURN((pfont->base == pfont ? 0 : pfont->prev));
1997dd7cddfSDavid du Colombier ENUM_PTR3(2, gs_font, dir, base, client_data);
2007dd7cddfSDavid du Colombier ENUM_PTRS_END
2017dd7cddfSDavid du Colombier private RELOC_PTRS_WITH(font_reloc_ptrs, gs_font *pfont);
2027dd7cddfSDavid du Colombier RELOC_USING(st_gs_notify_list, &pfont->notify_list, sizeof(gs_notify_list_t));
2037dd7cddfSDavid du Colombier /* We *do* always relocate next and prev. */
2047dd7cddfSDavid du Colombier /* Again, see above for details. */
2057dd7cddfSDavid du Colombier RELOC_PTR(gs_font, next);
2067dd7cddfSDavid du Colombier RELOC_PTR(gs_font, prev);
2077dd7cddfSDavid du Colombier RELOC_PTR3(gs_font, dir, base, client_data);
2087dd7cddfSDavid du Colombier RELOC_PTRS_END
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier /* Allocate a font directory */
2117dd7cddfSDavid du Colombier private bool
cc_no_mark_glyph(const gs_memory_t * mem,gs_glyph glyph,void * ignore_data)212*593dc095SDavid du Colombier cc_no_mark_glyph(const gs_memory_t *mem, gs_glyph glyph, void *ignore_data)
2137dd7cddfSDavid du Colombier {
2147dd7cddfSDavid du Colombier return false;
2157dd7cddfSDavid du Colombier }
2167dd7cddfSDavid du Colombier gs_font_dir *
gs_font_dir_alloc2(gs_memory_t * struct_mem,gs_memory_t * bits_mem)2177dd7cddfSDavid du Colombier gs_font_dir_alloc2(gs_memory_t * struct_mem, gs_memory_t * bits_mem)
2187dd7cddfSDavid du Colombier {
2197dd7cddfSDavid du Colombier gs_font_dir *pdir = 0;
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier #if !arch_small_memory
2227dd7cddfSDavid du Colombier # ifdef DEBUG
2237dd7cddfSDavid du Colombier if (!gs_debug_c('.'))
2247dd7cddfSDavid du Colombier # endif
2257dd7cddfSDavid du Colombier { /* Try allocating a very large cache. */
2267dd7cddfSDavid du Colombier /* If this fails, allocate a small one. */
2277dd7cddfSDavid du Colombier pdir = gs_font_dir_alloc2_limits(struct_mem, bits_mem,
2287dd7cddfSDavid du Colombier smax_LARGE, bmax_LARGE, mmax_LARGE,
2297dd7cddfSDavid du Colombier cmax_LARGE, blimit_LARGE);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier if (pdir == 0)
2327dd7cddfSDavid du Colombier #endif
2337dd7cddfSDavid du Colombier pdir = gs_font_dir_alloc2_limits(struct_mem, bits_mem,
2347dd7cddfSDavid du Colombier smax_SMALL, bmax_SMALL, mmax_SMALL,
2357dd7cddfSDavid du Colombier cmax_SMALL, blimit_SMALL);
2367dd7cddfSDavid du Colombier if (pdir == 0)
2377dd7cddfSDavid du Colombier return 0;
2387dd7cddfSDavid du Colombier pdir->ccache.mark_glyph = cc_no_mark_glyph;
2397dd7cddfSDavid du Colombier pdir->ccache.mark_glyph_data = 0;
2407dd7cddfSDavid du Colombier return pdir;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier gs_font_dir *
gs_font_dir_alloc2_limits(gs_memory_t * struct_mem,gs_memory_t * bits_mem,uint smax,uint bmax,uint mmax,uint cmax,uint upper)2437dd7cddfSDavid du Colombier gs_font_dir_alloc2_limits(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
2447dd7cddfSDavid du Colombier uint smax, uint bmax, uint mmax, uint cmax, uint upper)
2457dd7cddfSDavid du Colombier {
2467dd7cddfSDavid du Colombier gs_font_dir *pdir =
2477dd7cddfSDavid du Colombier gs_alloc_struct(struct_mem, gs_font_dir, &st_font_dir,
2487dd7cddfSDavid du Colombier "font_dir_alloc(dir)");
2497dd7cddfSDavid du Colombier int code;
2507dd7cddfSDavid du Colombier
2517dd7cddfSDavid du Colombier if (pdir == 0)
2527dd7cddfSDavid du Colombier return 0;
2537dd7cddfSDavid du Colombier code = gx_char_cache_alloc(struct_mem, bits_mem, pdir,
2547dd7cddfSDavid du Colombier bmax, mmax, cmax, upper);
2557dd7cddfSDavid du Colombier if (code < 0) {
2567dd7cddfSDavid du Colombier gs_free_object(struct_mem, pdir, "font_dir_alloc(dir)");
2577dd7cddfSDavid du Colombier return 0;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier pdir->orig_fonts = 0;
2607dd7cddfSDavid du Colombier pdir->scaled_fonts = 0;
2617dd7cddfSDavid du Colombier pdir->ssize = 0;
2627dd7cddfSDavid du Colombier pdir->smax = smax;
263*593dc095SDavid du Colombier pdir->align_to_pixels = false;
264*593dc095SDavid du Colombier pdir->glyph_to_unicode_table = NULL;
265*593dc095SDavid du Colombier pdir->grid_fit_tt = 2;
266*593dc095SDavid du Colombier pdir->memory = struct_mem;
267*593dc095SDavid du Colombier pdir->tti = 0;
268*593dc095SDavid du Colombier pdir->san = 0;
269*593dc095SDavid du Colombier pdir->global_glyph_code = NULL;
2707dd7cddfSDavid du Colombier return pdir;
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier
2737dd7cddfSDavid du Colombier /* Allocate and minimally initialize a font. */
2747dd7cddfSDavid du Colombier gs_font *
gs_font_alloc(gs_memory_t * mem,gs_memory_type_ptr_t pstype,const gs_font_procs * procs,gs_font_dir * dir,client_name_t cname)2757dd7cddfSDavid du Colombier gs_font_alloc(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
2767dd7cddfSDavid du Colombier const gs_font_procs *procs, gs_font_dir *dir,
2777dd7cddfSDavid du Colombier client_name_t cname)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier gs_font *pfont = gs_alloc_struct(mem, gs_font, pstype, cname);
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier if (pfont == 0)
2827dd7cddfSDavid du Colombier return 0;
283*593dc095SDavid du Colombier #if 1 /* Clear entire structure to avoid unitialized pointers
284*593dc095SDavid du Colombier when the initialization exits prematurely by error. */
285*593dc095SDavid du Colombier memset(pfont, 0, pstype->ssize);
286*593dc095SDavid du Colombier pfont->memory = mem;
287*593dc095SDavid du Colombier pfont->dir = dir;
288*593dc095SDavid du Colombier gs_font_notify_init(pfont);
289*593dc095SDavid du Colombier pfont->id = gs_next_ids(mem, 1);
290*593dc095SDavid du Colombier pfont->base = pfont;
291*593dc095SDavid du Colombier pfont->ExactSize = pfont->InBetweenSize = pfont->TransformedChar =
292*593dc095SDavid du Colombier fbit_use_outlines;
293*593dc095SDavid du Colombier pfont->procs = *procs;
294*593dc095SDavid du Colombier #else
295*593dc095SDavid du Colombier /* For clarity we leave old initializations here
296*593dc095SDavid du Colombier to know which fields needs to be initialized. */
2977dd7cddfSDavid du Colombier pfont->next = pfont->prev = 0;
2987dd7cddfSDavid du Colombier pfont->memory = mem;
2997dd7cddfSDavid du Colombier pfont->dir = dir;
3007dd7cddfSDavid du Colombier pfont->is_resource = false;
301*593dc095SDavid du Colombier gs_font_notify_init(pfont);
302*593dc095SDavid du Colombier pfont->id = gs_next_ids(mem, 1);
3037dd7cddfSDavid du Colombier pfont->base = pfont;
3047dd7cddfSDavid du Colombier pfont->client_data = 0;
3057dd7cddfSDavid du Colombier /* not FontMatrix, FontType */
3067dd7cddfSDavid du Colombier pfont->BitmapWidths = false;
3077dd7cddfSDavid du Colombier pfont->ExactSize = pfont->InBetweenSize = pfont->TransformedChar =
3087dd7cddfSDavid du Colombier fbit_use_outlines;
3097dd7cddfSDavid du Colombier pfont->WMode = 0;
3107dd7cddfSDavid du Colombier pfont->PaintType = 0;
3117dd7cddfSDavid du Colombier pfont->StrokeWidth = 0;
3127dd7cddfSDavid du Colombier pfont->procs = *procs;
313*593dc095SDavid du Colombier memset(&pfont->orig_FontMatrix, 0, sizeof(pfont->orig_FontMatrix));
314*593dc095SDavid du Colombier #endif
3157dd7cddfSDavid du Colombier /* not key_name, font_name */
3167dd7cddfSDavid du Colombier return pfont;
3177dd7cddfSDavid du Colombier }
3187dd7cddfSDavid du Colombier /* Allocate and minimally initialize a base font. */
3197dd7cddfSDavid du Colombier gs_font_base *
gs_font_base_alloc(gs_memory_t * mem,gs_memory_type_ptr_t pstype,const gs_font_procs * procs,gs_font_dir * dir,client_name_t cname)3207dd7cddfSDavid du Colombier gs_font_base_alloc(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
3217dd7cddfSDavid du Colombier const gs_font_procs *procs, gs_font_dir *dir,
3227dd7cddfSDavid du Colombier client_name_t cname)
3237dd7cddfSDavid du Colombier {
3247dd7cddfSDavid du Colombier gs_font_base *pfont =
3257dd7cddfSDavid du Colombier (gs_font_base *)gs_font_alloc(mem, pstype, procs, dir, cname);
3267dd7cddfSDavid du Colombier
3277dd7cddfSDavid du Colombier if (pfont == 0)
3287dd7cddfSDavid du Colombier return 0;
3297dd7cddfSDavid du Colombier pfont->FontBBox.p.x = pfont->FontBBox.p.y =
3307dd7cddfSDavid du Colombier pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
3317dd7cddfSDavid du Colombier uid_set_invalid(&pfont->UID);
3327dd7cddfSDavid du Colombier pfont->encoding_index = pfont->nearest_encoding_index = -1;
3337dd7cddfSDavid du Colombier return pfont;
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier
336*593dc095SDavid du Colombier /* Initialize the notification list for a font. */
337*593dc095SDavid du Colombier void
gs_font_notify_init(gs_font * font)338*593dc095SDavid du Colombier gs_font_notify_init(gs_font *font)
339*593dc095SDavid du Colombier {
340*593dc095SDavid du Colombier /*
341*593dc095SDavid du Colombier * The notification list for a font must be allocated in the font's
342*593dc095SDavid du Colombier * stable memory, because of the following possible sequence of events:
343*593dc095SDavid du Colombier *
344*593dc095SDavid du Colombier * - Allocate font X in local VM.
345*593dc095SDavid du Colombier * - Client A registers for notification when X is freed.
346*593dc095SDavid du Colombier * - 'save'
347*593dc095SDavid du Colombier * - Client B registers for notification when X is freed.
348*593dc095SDavid du Colombier * - 'restore'
349*593dc095SDavid du Colombier *
350*593dc095SDavid du Colombier * If the notification list element for client B is allocated in
351*593dc095SDavid du Colombier * restorable local VM (i.e., the same VM as the font), then when the
352*593dc095SDavid du Colombier * 'restore' occurs, either the list element will be deleted (not what
353*593dc095SDavid du Colombier * client B wants, because font X hasn't been freed yet), or there will
354*593dc095SDavid du Colombier * be a dangling pointer.
355*593dc095SDavid du Colombier */
356*593dc095SDavid du Colombier gs_notify_init(&font->notify_list, gs_memory_stable(font->memory));
357*593dc095SDavid du Colombier }
358*593dc095SDavid du Colombier
359*593dc095SDavid du Colombier
3607dd7cddfSDavid du Colombier /*
3617dd7cddfSDavid du Colombier * Register/unregister a client for notification by a font. Currently
3627dd7cddfSDavid du Colombier * the clients are only notified when a font is freed. Note that any
3637dd7cddfSDavid du Colombier * such client must unregister itself when *it* is freed.
3647dd7cddfSDavid du Colombier */
3657dd7cddfSDavid du Colombier int
gs_font_notify_register(gs_font * font,gs_notify_proc_t proc,void * proc_data)3667dd7cddfSDavid du Colombier gs_font_notify_register(gs_font *font, gs_notify_proc_t proc, void *proc_data)
3677dd7cddfSDavid du Colombier {
3687dd7cddfSDavid du Colombier return gs_notify_register(&font->notify_list, proc, proc_data);
3697dd7cddfSDavid du Colombier }
3707dd7cddfSDavid du Colombier int
gs_font_notify_unregister(gs_font * font,gs_notify_proc_t proc,void * proc_data)3717dd7cddfSDavid du Colombier gs_font_notify_unregister(gs_font *font, gs_notify_proc_t proc, void *proc_data)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier return gs_notify_unregister(&font->notify_list, proc, proc_data);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier /* Link an element at the head of a chain. */
3777dd7cddfSDavid du Colombier private void
font_link_first(gs_font ** pfirst,gs_font * elt)3787dd7cddfSDavid du Colombier font_link_first(gs_font **pfirst, gs_font *elt)
3797dd7cddfSDavid du Colombier {
3807dd7cddfSDavid du Colombier gs_font *first = elt->next = *pfirst;
3817dd7cddfSDavid du Colombier
3827dd7cddfSDavid du Colombier if (first)
3837dd7cddfSDavid du Colombier first->prev = elt;
3847dd7cddfSDavid du Colombier elt->prev = 0;
3857dd7cddfSDavid du Colombier *pfirst = elt;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier /* definefont */
3897dd7cddfSDavid du Colombier /* Use this only for original (unscaled) fonts! */
3907dd7cddfSDavid du Colombier /* Note that it expects pfont->procs.define_font to be set already. */
3917dd7cddfSDavid du Colombier int
gs_definefont(gs_font_dir * pdir,gs_font * pfont)3927dd7cddfSDavid du Colombier gs_definefont(gs_font_dir * pdir, gs_font * pfont)
3937dd7cddfSDavid du Colombier {
3947dd7cddfSDavid du Colombier int code;
3957dd7cddfSDavid du Colombier
3967dd7cddfSDavid du Colombier pfont->dir = pdir;
3977dd7cddfSDavid du Colombier pfont->base = pfont;
3987dd7cddfSDavid du Colombier code = (*pfont->procs.define_font) (pdir, pfont);
3997dd7cddfSDavid du Colombier if (code < 0) { /* Make sure we don't try to finalize this font. */
4007dd7cddfSDavid du Colombier pfont->base = 0;
4017dd7cddfSDavid du Colombier return code;
4027dd7cddfSDavid du Colombier }
4037dd7cddfSDavid du Colombier font_link_first(&pdir->orig_fonts, pfont);
4047dd7cddfSDavid du Colombier if_debug2('m', "[m]defining font 0x%lx, next=0x%lx\n",
4057dd7cddfSDavid du Colombier (ulong) pfont, (ulong) pfont->next);
4067dd7cddfSDavid du Colombier return 0;
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier
409*593dc095SDavid du Colombier /* Find a sililar registered font of same type. */
410*593dc095SDavid du Colombier int
gs_font_find_similar(const gs_font_dir * pdir,const gs_font ** ppfont,int (* similar)(const gs_font *,const gs_font *))411*593dc095SDavid du Colombier gs_font_find_similar(const gs_font_dir * pdir, const gs_font **ppfont,
412*593dc095SDavid du Colombier int (*similar)(const gs_font *, const gs_font *))
413*593dc095SDavid du Colombier {
414*593dc095SDavid du Colombier const gs_font *pfont0 = *ppfont;
415*593dc095SDavid du Colombier const gs_font *pfont1 = pdir->orig_fonts;
416*593dc095SDavid du Colombier
417*593dc095SDavid du Colombier for (; pfont1 != NULL; pfont1 = pfont1->next) {
418*593dc095SDavid du Colombier if (pfont1 != pfont0 && pfont1->FontType == pfont0->FontType) {
419*593dc095SDavid du Colombier int code = similar(pfont0, pfont1);
420*593dc095SDavid du Colombier if (code != 0) {
421*593dc095SDavid du Colombier *ppfont = pfont1;
422*593dc095SDavid du Colombier return code;
423*593dc095SDavid du Colombier }
424*593dc095SDavid du Colombier }
425*593dc095SDavid du Colombier }
426*593dc095SDavid du Colombier return 0;
427*593dc095SDavid du Colombier }
428*593dc095SDavid du Colombier
4297dd7cddfSDavid du Colombier /* scalefont */
4307dd7cddfSDavid du Colombier int
gs_scalefont(gs_font_dir * pdir,const gs_font * pfont,floatp scale,gs_font ** ppfont)4317dd7cddfSDavid du Colombier gs_scalefont(gs_font_dir * pdir, const gs_font * pfont, floatp scale,
4327dd7cddfSDavid du Colombier gs_font ** ppfont)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier gs_matrix mat;
4357dd7cddfSDavid du Colombier
4367dd7cddfSDavid du Colombier gs_make_scaling(scale, scale, &mat);
4377dd7cddfSDavid du Colombier return gs_makefont(pdir, pfont, &mat, ppfont);
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier
4407dd7cddfSDavid du Colombier /* makefont */
4417dd7cddfSDavid du Colombier int
gs_makefont(gs_font_dir * pdir,const gs_font * pfont,const gs_matrix * pmat,gs_font ** ppfont)4427dd7cddfSDavid du Colombier gs_makefont(gs_font_dir * pdir, const gs_font * pfont,
4437dd7cddfSDavid du Colombier const gs_matrix * pmat, gs_font ** ppfont)
4447dd7cddfSDavid du Colombier {
4457dd7cddfSDavid du Colombier int code;
4467dd7cddfSDavid du Colombier gs_font *prev = 0;
4477dd7cddfSDavid du Colombier gs_font *pf_out = pdir->scaled_fonts;
4487dd7cddfSDavid du Colombier gs_memory_t *mem = pfont->memory;
4497dd7cddfSDavid du Colombier gs_matrix newmat;
4507dd7cddfSDavid du Colombier bool can_cache;
4517dd7cddfSDavid du Colombier
4527dd7cddfSDavid du Colombier if ((code = gs_matrix_multiply(&pfont->FontMatrix, pmat, &newmat)) < 0)
4537dd7cddfSDavid du Colombier return code;
4547dd7cddfSDavid du Colombier /*
4557dd7cddfSDavid du Colombier * Check for the font already being in the scaled font cache.
4567dd7cddfSDavid du Colombier * Until version 5.97, we only cached scaled fonts if the base
4577dd7cddfSDavid du Colombier * (unscaled) font had a valid UniqueID or XUID; now, we will cache
4587dd7cddfSDavid du Colombier * scaled versions of any non-composite font.
4597dd7cddfSDavid du Colombier */
4607dd7cddfSDavid du Colombier #ifdef DEBUG
4617dd7cddfSDavid du Colombier if (gs_debug_c('m')) {
4627dd7cddfSDavid du Colombier const gs_font_base *const pbfont = (const gs_font_base *)pfont;
4637dd7cddfSDavid du Colombier
4647dd7cddfSDavid du Colombier if (pfont->FontType == ft_composite)
4657dd7cddfSDavid du Colombier dlprintf("[m]composite");
4667dd7cddfSDavid du Colombier else if (uid_is_UniqueID(&pbfont->UID))
4677dd7cddfSDavid du Colombier dlprintf1("[m]UniqueID=%ld", pbfont->UID.id);
4687dd7cddfSDavid du Colombier else if (uid_is_XUID(&pbfont->UID))
4697dd7cddfSDavid du Colombier dlprintf1("[m]XUID(%u)", (uint) (-pbfont->UID.id));
4707dd7cddfSDavid du Colombier else
4717dd7cddfSDavid du Colombier dlprintf("[m]no UID");
4727dd7cddfSDavid du Colombier dprintf7(", FontType=%d,\n[m] new FontMatrix=[%g %g %g %g %g %g]\n",
4737dd7cddfSDavid du Colombier pfont->FontType,
4747dd7cddfSDavid du Colombier pmat->xx, pmat->xy, pmat->yx, pmat->yy,
4757dd7cddfSDavid du Colombier pmat->tx, pmat->ty);
4767dd7cddfSDavid du Colombier }
4777dd7cddfSDavid du Colombier #endif
4787dd7cddfSDavid du Colombier /*
4797dd7cddfSDavid du Colombier * Don't try to cache scaled composite fonts, because of the side
4807dd7cddfSDavid du Colombier * effects on FDepVector and descendant fonts that occur in makefont.
4817dd7cddfSDavid du Colombier */
4827dd7cddfSDavid du Colombier if (pfont->FontType != ft_composite) {
4837dd7cddfSDavid du Colombier for (; pf_out != 0; prev = pf_out, pf_out = pf_out->next)
4847dd7cddfSDavid du Colombier if (pf_out->FontType == pfont->FontType &&
4857dd7cddfSDavid du Colombier pf_out->base == pfont->base &&
4867dd7cddfSDavid du Colombier pf_out->FontMatrix.xx == newmat.xx &&
4877dd7cddfSDavid du Colombier pf_out->FontMatrix.xy == newmat.xy &&
4887dd7cddfSDavid du Colombier pf_out->FontMatrix.yx == newmat.yx &&
4897dd7cddfSDavid du Colombier pf_out->FontMatrix.yy == newmat.yy &&
4907dd7cddfSDavid du Colombier pf_out->FontMatrix.tx == newmat.tx &&
4917dd7cddfSDavid du Colombier pf_out->FontMatrix.ty == newmat.ty
4927dd7cddfSDavid du Colombier ) {
4937dd7cddfSDavid du Colombier *ppfont = pf_out;
4947dd7cddfSDavid du Colombier if_debug1('m', "[m]found font=0x%lx\n", (ulong) pf_out);
4957dd7cddfSDavid du Colombier return 0;
4967dd7cddfSDavid du Colombier }
4977dd7cddfSDavid du Colombier can_cache = true;
4987dd7cddfSDavid du Colombier } else
4997dd7cddfSDavid du Colombier can_cache = false;
5007dd7cddfSDavid du Colombier pf_out = gs_alloc_struct(mem, gs_font, gs_object_type(mem, pfont),
5017dd7cddfSDavid du Colombier "gs_makefont");
5027dd7cddfSDavid du Colombier if (!pf_out)
5037dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
5047dd7cddfSDavid du Colombier memcpy(pf_out, pfont, gs_object_size(mem, pfont));
505*593dc095SDavid du Colombier gs_font_notify_init(pf_out);
5067dd7cddfSDavid du Colombier pf_out->FontMatrix = newmat;
5077dd7cddfSDavid du Colombier pf_out->client_data = 0;
5087dd7cddfSDavid du Colombier pf_out->dir = pdir;
5097dd7cddfSDavid du Colombier pf_out->base = pfont->base;
5107dd7cddfSDavid du Colombier *ppfont = pf_out;
5117dd7cddfSDavid du Colombier code = (*pf_out->procs.make_font) (pdir, pfont, pmat, ppfont);
5127dd7cddfSDavid du Colombier if (code < 0)
5137dd7cddfSDavid du Colombier return code;
5147dd7cddfSDavid du Colombier if (can_cache) {
5157dd7cddfSDavid du Colombier if (pdir->ssize >= pdir->smax && prev != 0) {
5167dd7cddfSDavid du Colombier /*
5177dd7cddfSDavid du Colombier * We must discard a cached scaled font.
5187dd7cddfSDavid du Colombier * prev points to the last (oldest) font.
5197dd7cddfSDavid du Colombier * (We can't free it, because there might be
5207dd7cddfSDavid du Colombier * other references to it.)
5217dd7cddfSDavid du Colombier */
5227dd7cddfSDavid du Colombier if_debug1('m', "[m]discarding font 0x%lx\n",
5237dd7cddfSDavid du Colombier (ulong) prev);
5247dd7cddfSDavid du Colombier if (prev->prev != 0)
5257dd7cddfSDavid du Colombier prev->prev->next = 0;
5267dd7cddfSDavid du Colombier else
5277dd7cddfSDavid du Colombier pdir->scaled_fonts = 0;
5287dd7cddfSDavid du Colombier pdir->ssize--;
5297dd7cddfSDavid du Colombier prev->prev = 0;
5307dd7cddfSDavid du Colombier if (prev->FontType != ft_composite) {
5317dd7cddfSDavid du Colombier if_debug1('m', "[m]discarding UID 0x%lx\n",
5327dd7cddfSDavid du Colombier (ulong) ((gs_font_base *) prev)->
5337dd7cddfSDavid du Colombier UID.xvalues);
5347dd7cddfSDavid du Colombier uid_free(&((gs_font_base *) prev)->UID,
5357dd7cddfSDavid du Colombier prev->memory,
5367dd7cddfSDavid du Colombier "gs_makefont(discarding)");
5377dd7cddfSDavid du Colombier uid_set_invalid(&((gs_font_base *) prev)->UID);
5387dd7cddfSDavid du Colombier }
5397dd7cddfSDavid du Colombier }
5407dd7cddfSDavid du Colombier pdir->ssize++;
5417dd7cddfSDavid du Colombier font_link_first(&pdir->scaled_fonts, pf_out);
5427dd7cddfSDavid du Colombier } else { /* Prevent garbage pointers. */
5437dd7cddfSDavid du Colombier pf_out->next = pf_out->prev = 0;
5447dd7cddfSDavid du Colombier }
5457dd7cddfSDavid du Colombier if_debug2('m', "[m]new font=0x%lx can_cache=%s\n",
5467dd7cddfSDavid du Colombier (ulong) * ppfont, (can_cache ? "true" : "false"));
5477dd7cddfSDavid du Colombier return 1;
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier
5507dd7cddfSDavid du Colombier /* Set the current font. This is provided only for the benefit of cshow, */
5517dd7cddfSDavid du Colombier /* which must reset the current font without disturbing the root font. */
5527dd7cddfSDavid du Colombier void
gs_set_currentfont(gs_state * pgs,gs_font * pfont)5537dd7cddfSDavid du Colombier gs_set_currentfont(gs_state * pgs, gs_font * pfont)
5547dd7cddfSDavid du Colombier {
5557dd7cddfSDavid du Colombier pgs->font = pfont;
5567dd7cddfSDavid du Colombier pgs->char_tm_valid = false;
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier /* setfont */
5607dd7cddfSDavid du Colombier int
gs_setfont(gs_state * pgs,gs_font * pfont)5617dd7cddfSDavid du Colombier gs_setfont(gs_state * pgs, gs_font * pfont)
5627dd7cddfSDavid du Colombier {
5637dd7cddfSDavid du Colombier pgs->font = pgs->root_font = pfont;
5647dd7cddfSDavid du Colombier pgs->char_tm_valid = false;
5657dd7cddfSDavid du Colombier return 0;
5667dd7cddfSDavid du Colombier }
5677dd7cddfSDavid du Colombier
5687dd7cddfSDavid du Colombier /* currentfont */
5697dd7cddfSDavid du Colombier gs_font *
gs_currentfont(const gs_state * pgs)5707dd7cddfSDavid du Colombier gs_currentfont(const gs_state * pgs)
5717dd7cddfSDavid du Colombier {
5727dd7cddfSDavid du Colombier return pgs->font;
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier
5757dd7cddfSDavid du Colombier /* rootfont */
5767dd7cddfSDavid du Colombier gs_font *
gs_rootfont(const gs_state * pgs)5777dd7cddfSDavid du Colombier gs_rootfont(const gs_state * pgs)
5787dd7cddfSDavid du Colombier {
5797dd7cddfSDavid du Colombier return pgs->root_font;
5807dd7cddfSDavid du Colombier }
5817dd7cddfSDavid du Colombier
5827dd7cddfSDavid du Colombier /* cachestatus */
5837dd7cddfSDavid du Colombier void
gs_cachestatus(register const gs_font_dir * pdir,register uint pstat[7])5847dd7cddfSDavid du Colombier gs_cachestatus(register const gs_font_dir * pdir, register uint pstat[7])
5857dd7cddfSDavid du Colombier {
5867dd7cddfSDavid du Colombier pstat[0] = pdir->ccache.bsize;
5877dd7cddfSDavid du Colombier pstat[1] = pdir->ccache.bmax;
5887dd7cddfSDavid du Colombier pstat[2] = pdir->fmcache.msize;
5897dd7cddfSDavid du Colombier pstat[3] = pdir->fmcache.mmax;
5907dd7cddfSDavid du Colombier pstat[4] = pdir->ccache.csize;
5917dd7cddfSDavid du Colombier pstat[5] = pdir->ccache.cmax;
5927dd7cddfSDavid du Colombier pstat[6] = pdir->ccache.upper;
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier /* setcacheparams */
5967dd7cddfSDavid du Colombier int
gs_setcachesize(gs_font_dir * pdir,uint size)5977dd7cddfSDavid du Colombier gs_setcachesize(gs_font_dir * pdir, uint size)
5987dd7cddfSDavid du Colombier { /* This doesn't delete anything from the cache yet. */
5997dd7cddfSDavid du Colombier pdir->ccache.bmax = size;
6007dd7cddfSDavid du Colombier return 0;
6017dd7cddfSDavid du Colombier }
6027dd7cddfSDavid du Colombier int
gs_setcachelower(gs_font_dir * pdir,uint size)6037dd7cddfSDavid du Colombier gs_setcachelower(gs_font_dir * pdir, uint size)
6047dd7cddfSDavid du Colombier {
6057dd7cddfSDavid du Colombier pdir->ccache.lower = size;
6067dd7cddfSDavid du Colombier return 0;
6077dd7cddfSDavid du Colombier }
6087dd7cddfSDavid du Colombier int
gs_setcacheupper(gs_font_dir * pdir,uint size)6097dd7cddfSDavid du Colombier gs_setcacheupper(gs_font_dir * pdir, uint size)
6107dd7cddfSDavid du Colombier {
6117dd7cddfSDavid du Colombier pdir->ccache.upper = size;
6127dd7cddfSDavid du Colombier return 0;
6137dd7cddfSDavid du Colombier }
614*593dc095SDavid du Colombier int
gs_setaligntopixels(gs_font_dir * pdir,uint v)615*593dc095SDavid du Colombier gs_setaligntopixels(gs_font_dir * pdir, uint v)
616*593dc095SDavid du Colombier {
617*593dc095SDavid du Colombier pdir->align_to_pixels = v;
618*593dc095SDavid du Colombier return 0;
619*593dc095SDavid du Colombier }
620*593dc095SDavid du Colombier int
gs_setgridfittt(gs_font_dir * pdir,uint v)621*593dc095SDavid du Colombier gs_setgridfittt(gs_font_dir * pdir, uint v)
622*593dc095SDavid du Colombier {
623*593dc095SDavid du Colombier pdir->grid_fit_tt = v;
624*593dc095SDavid du Colombier return 0;
625*593dc095SDavid du Colombier }
6267dd7cddfSDavid du Colombier
6277dd7cddfSDavid du Colombier /* currentcacheparams */
6287dd7cddfSDavid du Colombier uint
gs_currentcachesize(const gs_font_dir * pdir)6297dd7cddfSDavid du Colombier gs_currentcachesize(const gs_font_dir * pdir)
6307dd7cddfSDavid du Colombier {
6317dd7cddfSDavid du Colombier return pdir->ccache.bmax;
6327dd7cddfSDavid du Colombier }
6337dd7cddfSDavid du Colombier uint
gs_currentcachelower(const gs_font_dir * pdir)6347dd7cddfSDavid du Colombier gs_currentcachelower(const gs_font_dir * pdir)
6357dd7cddfSDavid du Colombier {
6367dd7cddfSDavid du Colombier return pdir->ccache.lower;
6377dd7cddfSDavid du Colombier }
6387dd7cddfSDavid du Colombier uint
gs_currentcacheupper(const gs_font_dir * pdir)6397dd7cddfSDavid du Colombier gs_currentcacheupper(const gs_font_dir * pdir)
6407dd7cddfSDavid du Colombier {
6417dd7cddfSDavid du Colombier return pdir->ccache.upper;
6427dd7cddfSDavid du Colombier }
643*593dc095SDavid du Colombier uint
gs_currentaligntopixels(const gs_font_dir * pdir)644*593dc095SDavid du Colombier gs_currentaligntopixels(const gs_font_dir * pdir)
645*593dc095SDavid du Colombier {
646*593dc095SDavid du Colombier return pdir->align_to_pixels;
647*593dc095SDavid du Colombier }
648*593dc095SDavid du Colombier uint
gs_currentgridfittt(const gs_font_dir * pdir)649*593dc095SDavid du Colombier gs_currentgridfittt(const gs_font_dir * pdir)
650*593dc095SDavid du Colombier {
651*593dc095SDavid du Colombier return pdir->grid_fit_tt;
652*593dc095SDavid du Colombier }
6537dd7cddfSDavid du Colombier
6547dd7cddfSDavid du Colombier /* Purge a font from all font- and character-related tables. */
6557dd7cddfSDavid du Colombier /* This is only used by restore (and, someday, the GC). */
6567dd7cddfSDavid du Colombier void
gs_purge_font(gs_font * pfont)6577dd7cddfSDavid du Colombier gs_purge_font(gs_font * pfont)
6587dd7cddfSDavid du Colombier {
6597dd7cddfSDavid du Colombier gs_font_dir *pdir = pfont->dir;
6607dd7cddfSDavid du Colombier gs_font *pf;
6617dd7cddfSDavid du Colombier
6627dd7cddfSDavid du Colombier /* Remove the font from its list (orig_fonts or scaled_fonts). */
6637dd7cddfSDavid du Colombier gs_font *prev = pfont->prev;
6647dd7cddfSDavid du Colombier gs_font *next = pfont->next;
6657dd7cddfSDavid du Colombier
6667dd7cddfSDavid du Colombier if (next != 0)
6677dd7cddfSDavid du Colombier next->prev = prev, pfont->next = 0;
6687dd7cddfSDavid du Colombier if (prev != 0)
6697dd7cddfSDavid du Colombier prev->next = next, pfont->prev = 0;
6707dd7cddfSDavid du Colombier else if (pdir->orig_fonts == pfont)
6717dd7cddfSDavid du Colombier pdir->orig_fonts = next;
6727dd7cddfSDavid du Colombier else if (pdir->scaled_fonts == pfont)
6737dd7cddfSDavid du Colombier pdir->scaled_fonts = next;
6747dd7cddfSDavid du Colombier else { /* Shouldn't happen! */
6757dd7cddfSDavid du Colombier lprintf1("purged font 0x%lx not found\n", (ulong) pfont);
6767dd7cddfSDavid du Colombier }
6777dd7cddfSDavid du Colombier
6787dd7cddfSDavid du Colombier /* Purge the font from the scaled font cache. */
6797dd7cddfSDavid du Colombier for (pf = pdir->scaled_fonts; pf != 0;) {
6807dd7cddfSDavid du Colombier if (pf->base == pfont) {
6817dd7cddfSDavid du Colombier gs_purge_font(pf);
6827dd7cddfSDavid du Colombier pf = pdir->scaled_fonts; /* start over */
6837dd7cddfSDavid du Colombier } else
6847dd7cddfSDavid du Colombier pf = pf->next;
6857dd7cddfSDavid du Colombier }
6867dd7cddfSDavid du Colombier
6877dd7cddfSDavid du Colombier /* Purge the font from the font/matrix pair cache, */
6887dd7cddfSDavid du Colombier /* including all cached characters rendered with that font. */
6897dd7cddfSDavid du Colombier gs_purge_font_from_char_caches(pdir, pfont);
6907dd7cddfSDavid du Colombier
6917dd7cddfSDavid du Colombier }
6927dd7cddfSDavid du Colombier
693*593dc095SDavid du Colombier /* Locate a gs_font by gs_id. */
694*593dc095SDavid du Colombier gs_font *
gs_find_font_by_id(gs_font_dir * pdir,gs_id id,gs_matrix * FontMatrix)695*593dc095SDavid du Colombier gs_find_font_by_id(gs_font_dir *pdir, gs_id id, gs_matrix *FontMatrix)
696*593dc095SDavid du Colombier {
697*593dc095SDavid du Colombier gs_font *pfont = pdir->orig_fonts;
698*593dc095SDavid du Colombier
699*593dc095SDavid du Colombier for(; pfont != NULL; pfont = pfont->next)
700*593dc095SDavid du Colombier if(pfont->id == id &&
701*593dc095SDavid du Colombier !memcmp(&pfont->FontMatrix, FontMatrix, sizeof(pfont->FontMatrix)))
702*593dc095SDavid du Colombier return pfont;
703*593dc095SDavid du Colombier return NULL;
704*593dc095SDavid du Colombier }
705*593dc095SDavid du Colombier
7067dd7cddfSDavid du Colombier /* ---------------- Default font procedures ---------------- */
7077dd7cddfSDavid du Colombier
7087dd7cddfSDavid du Colombier /* ------ Font-level procedures ------ */
7097dd7cddfSDavid du Colombier
7107dd7cddfSDavid du Colombier /* Default (vacuous) definefont handler. */
7117dd7cddfSDavid du Colombier int
gs_no_define_font(gs_font_dir * pdir,gs_font * pfont)7127dd7cddfSDavid du Colombier gs_no_define_font(gs_font_dir * pdir, gs_font * pfont)
7137dd7cddfSDavid du Colombier {
7147dd7cddfSDavid du Colombier return 0;
7157dd7cddfSDavid du Colombier }
7167dd7cddfSDavid du Colombier
7177dd7cddfSDavid du Colombier /* Default (vacuous) makefont handler. */
7187dd7cddfSDavid du Colombier int
gs_no_make_font(gs_font_dir * pdir,const gs_font * pfont,const gs_matrix * pmat,gs_font ** ppfont)7197dd7cddfSDavid du Colombier gs_no_make_font(gs_font_dir * pdir, const gs_font * pfont,
7207dd7cddfSDavid du Colombier const gs_matrix * pmat, gs_font ** ppfont)
7217dd7cddfSDavid du Colombier {
7227dd7cddfSDavid du Colombier return 0;
7237dd7cddfSDavid du Colombier }
7247dd7cddfSDavid du Colombier /* Makefont handler for base fonts, which must copy the XUID. */
7257dd7cddfSDavid du Colombier int
gs_base_make_font(gs_font_dir * pdir,const gs_font * pfont,const gs_matrix * pmat,gs_font ** ppfont)7267dd7cddfSDavid du Colombier gs_base_make_font(gs_font_dir * pdir, const gs_font * pfont,
7277dd7cddfSDavid du Colombier const gs_matrix * pmat, gs_font ** ppfont)
7287dd7cddfSDavid du Colombier {
729*593dc095SDavid du Colombier return uid_copy(&((gs_font_base *)*ppfont)->UID, (*ppfont)->memory,
7307dd7cddfSDavid du Colombier "gs_base_make_font(XUID)");
7317dd7cddfSDavid du Colombier }
7327dd7cddfSDavid du Colombier
7337dd7cddfSDavid du Colombier /* Default font info procedure */
7347dd7cddfSDavid du Colombier int
gs_default_font_info(gs_font * font,const gs_point * pscale,int members,gs_font_info_t * info)7357dd7cddfSDavid du Colombier gs_default_font_info(gs_font *font, const gs_point *pscale, int members,
7367dd7cddfSDavid du Colombier gs_font_info_t *info)
7377dd7cddfSDavid du Colombier {
7387dd7cddfSDavid du Colombier int wmode = font->WMode;
7397dd7cddfSDavid du Colombier gs_font_base *bfont = (gs_font_base *)font;
7407dd7cddfSDavid du Colombier gs_point scale;
7417dd7cddfSDavid du Colombier gs_matrix smat;
7427dd7cddfSDavid du Colombier const gs_matrix *pmat;
7437dd7cddfSDavid du Colombier
7447dd7cddfSDavid du Colombier if (pscale == 0) {
7457dd7cddfSDavid du Colombier scale.x = scale.y = 0;
7467dd7cddfSDavid du Colombier pmat = 0;
7477dd7cddfSDavid du Colombier } else {
7487dd7cddfSDavid du Colombier scale = *pscale;
7497dd7cddfSDavid du Colombier gs_make_scaling(scale.x, scale.y, &smat);
7507dd7cddfSDavid du Colombier pmat = &smat;
7517dd7cddfSDavid du Colombier }
7527dd7cddfSDavid du Colombier info->members = 0;
7537dd7cddfSDavid du Colombier if (members & FONT_INFO_FLAGS)
7547dd7cddfSDavid du Colombier info->Flags_returned = 0;
7557dd7cddfSDavid du Colombier if (font->FontType == ft_composite)
7567dd7cddfSDavid du Colombier return 0; /* nothing available */
757*593dc095SDavid du Colombier if (members & FONT_INFO_BBOX) {
758*593dc095SDavid du Colombier info->BBox.p.x = (int)bfont->FontBBox.p.x;
759*593dc095SDavid du Colombier info->BBox.p.y = (int)bfont->FontBBox.p.y;
760*593dc095SDavid du Colombier info->BBox.q.x = (int)bfont->FontBBox.q.x;
761*593dc095SDavid du Colombier info->BBox.q.y = (int)bfont->FontBBox.q.y;
762*593dc095SDavid du Colombier info->Flags_returned |= FONT_INFO_BBOX;
763*593dc095SDavid du Colombier }
7647dd7cddfSDavid du Colombier if ((members & FONT_INFO_FLAGS) &&
7657dd7cddfSDavid du Colombier (info->Flags_requested & FONT_IS_FIXED_WIDTH)
7667dd7cddfSDavid du Colombier ) {
7677dd7cddfSDavid du Colombier /*
7687dd7cddfSDavid du Colombier * Scan the glyph space to compute the fixed width if any.
7697dd7cddfSDavid du Colombier */
7707dd7cddfSDavid du Colombier gs_glyph notdef = gs_no_glyph;
7717dd7cddfSDavid du Colombier gs_glyph glyph;
7727dd7cddfSDavid du Colombier int fixed_width = 0;
773*593dc095SDavid du Colombier int index;
774*593dc095SDavid du Colombier int code = 0; /* Quiet compiler. */
7757dd7cddfSDavid du Colombier
7767dd7cddfSDavid du Colombier for (index = 0;
7773ff48bf5SDavid du Colombier fixed_width >= 0 &&
7787dd7cddfSDavid du Colombier (code = font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_NAME, &glyph)) >= 0 &&
7797dd7cddfSDavid du Colombier index != 0;
7807dd7cddfSDavid du Colombier ) {
7817dd7cddfSDavid du Colombier gs_glyph_info_t glyph_info;
7827dd7cddfSDavid du Colombier
7837dd7cddfSDavid du Colombier code = font->procs.glyph_info(font, glyph, pmat,
7847dd7cddfSDavid du Colombier (GLYPH_INFO_WIDTH0 << wmode),
7857dd7cddfSDavid du Colombier &glyph_info);
7867dd7cddfSDavid du Colombier if (code < 0)
7877dd7cddfSDavid du Colombier return code;
7883ff48bf5SDavid du Colombier if (notdef == gs_no_glyph && gs_font_glyph_is_notdef(bfont, glyph)) {
7897dd7cddfSDavid du Colombier notdef = glyph;
790*593dc095SDavid du Colombier info->MissingWidth = (int)glyph_info.width[wmode].x;
7917dd7cddfSDavid du Colombier info->members |= FONT_INFO_MISSING_WIDTH;
7927dd7cddfSDavid du Colombier }
7937dd7cddfSDavid du Colombier if (glyph_info.width[wmode].y != 0)
7947dd7cddfSDavid du Colombier fixed_width = min_int;
7957dd7cddfSDavid du Colombier else if (fixed_width == 0)
796*593dc095SDavid du Colombier fixed_width = (int)glyph_info.width[wmode].x;
7977dd7cddfSDavid du Colombier else if (glyph_info.width[wmode].x != fixed_width)
7987dd7cddfSDavid du Colombier fixed_width = min_int;
7997dd7cddfSDavid du Colombier }
8007dd7cddfSDavid du Colombier if (code < 0)
8017dd7cddfSDavid du Colombier return code;
8027dd7cddfSDavid du Colombier if (fixed_width > 0) {
8037dd7cddfSDavid du Colombier info->Flags |= FONT_IS_FIXED_WIDTH;
8047dd7cddfSDavid du Colombier info->members |= FONT_INFO_AVG_WIDTH | FONT_INFO_MAX_WIDTH |
8057dd7cddfSDavid du Colombier FONT_INFO_MISSING_WIDTH;
8067dd7cddfSDavid du Colombier info->AvgWidth = info->MaxWidth = info->MissingWidth = fixed_width;
8077dd7cddfSDavid du Colombier }
8087dd7cddfSDavid du Colombier info->Flags_returned |= FONT_IS_FIXED_WIDTH;
8097dd7cddfSDavid du Colombier } else if (members & FONT_INFO_MISSING_WIDTH) {
8107dd7cddfSDavid du Colombier gs_glyph glyph;
8117dd7cddfSDavid du Colombier int index;
8127dd7cddfSDavid du Colombier
8137dd7cddfSDavid du Colombier for (index = 0;
8147dd7cddfSDavid du Colombier font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_NAME, &glyph) >= 0 &&
8157dd7cddfSDavid du Colombier index != 0;
8167dd7cddfSDavid du Colombier ) {
8173ff48bf5SDavid du Colombier /*
8183ff48bf5SDavid du Colombier * If this is a CIDFont or TrueType font that uses integers as
8193ff48bf5SDavid du Colombier * glyph names, check for glyph 0; otherwise, check for .notdef.
8203ff48bf5SDavid du Colombier */
8213ff48bf5SDavid du Colombier if (!gs_font_glyph_is_notdef(bfont, glyph))
8223ff48bf5SDavid du Colombier continue;
8233ff48bf5SDavid du Colombier {
8247dd7cddfSDavid du Colombier gs_glyph_info_t glyph_info;
8257dd7cddfSDavid du Colombier int code = font->procs.glyph_info(font, glyph, pmat,
8267dd7cddfSDavid du Colombier (GLYPH_INFO_WIDTH0 << wmode),
8277dd7cddfSDavid du Colombier &glyph_info);
8287dd7cddfSDavid du Colombier
8297dd7cddfSDavid du Colombier if (code < 0)
8307dd7cddfSDavid du Colombier return code;
831*593dc095SDavid du Colombier info->MissingWidth = (int)glyph_info.width[wmode].x;
8327dd7cddfSDavid du Colombier info->members |= FONT_INFO_MISSING_WIDTH;
8337dd7cddfSDavid du Colombier break;
8347dd7cddfSDavid du Colombier }
8357dd7cddfSDavid du Colombier }
8367dd7cddfSDavid du Colombier }
8377dd7cddfSDavid du Colombier return 0;
8387dd7cddfSDavid du Colombier }
8397dd7cddfSDavid du Colombier
8407dd7cddfSDavid du Colombier /* Default font similarity testing procedure */
8417dd7cddfSDavid du Colombier int
gs_default_same_font(const gs_font * font,const gs_font * ofont,int mask)8427dd7cddfSDavid du Colombier gs_default_same_font(const gs_font *font, const gs_font *ofont, int mask)
8437dd7cddfSDavid du Colombier {
8447dd7cddfSDavid du Colombier while (font->base != font)
8457dd7cddfSDavid du Colombier font = font->base;
8467dd7cddfSDavid du Colombier while (ofont->base != ofont)
8477dd7cddfSDavid du Colombier ofont = ofont->base;
8487dd7cddfSDavid du Colombier if (ofont == font)
8497dd7cddfSDavid du Colombier return mask;
8507dd7cddfSDavid du Colombier /* In general, we can't determine similarity. */
8517dd7cddfSDavid du Colombier return 0;
8527dd7cddfSDavid du Colombier }
8537dd7cddfSDavid du Colombier int
gs_base_same_font(const gs_font * font,const gs_font * ofont,int mask)8547dd7cddfSDavid du Colombier gs_base_same_font(const gs_font *font, const gs_font *ofont, int mask)
8557dd7cddfSDavid du Colombier {
8567dd7cddfSDavid du Colombier int same = gs_default_same_font(font, ofont, mask);
8577dd7cddfSDavid du Colombier
8587dd7cddfSDavid du Colombier if (!same) {
8597dd7cddfSDavid du Colombier const gs_font_base *const bfont = (const gs_font_base *)font;
8607dd7cddfSDavid du Colombier const gs_font_base *const obfont = (const gs_font_base *)ofont;
8617dd7cddfSDavid du Colombier
8627dd7cddfSDavid du Colombier if (mask & FONT_SAME_ENCODING) {
8637dd7cddfSDavid du Colombier if (bfont->encoding_index != ENCODING_INDEX_UNKNOWN ||
8647dd7cddfSDavid du Colombier obfont->encoding_index != ENCODING_INDEX_UNKNOWN
8657dd7cddfSDavid du Colombier ) {
8667dd7cddfSDavid du Colombier if (bfont->encoding_index == obfont->encoding_index)
8677dd7cddfSDavid du Colombier same |= FONT_SAME_ENCODING;
8687dd7cddfSDavid du Colombier }
8697dd7cddfSDavid du Colombier }
8707dd7cddfSDavid du Colombier }
8717dd7cddfSDavid du Colombier return same;
8727dd7cddfSDavid du Colombier }
8737dd7cddfSDavid du Colombier
8747dd7cddfSDavid du Colombier /* ------ Glyph-level procedures ------ */
8757dd7cddfSDavid du Colombier
8763ff48bf5SDavid du Colombier /*
8773ff48bf5SDavid du Colombier * Test whether a glyph is the notdef glyph for a base font.
8783ff48bf5SDavid du Colombier * The test is somewhat adhoc: perhaps this should be a virtual procedure.
8793ff48bf5SDavid du Colombier */
8803ff48bf5SDavid du Colombier bool
gs_font_glyph_is_notdef(gs_font_base * bfont,gs_glyph glyph)8813ff48bf5SDavid du Colombier gs_font_glyph_is_notdef(gs_font_base *bfont, gs_glyph glyph)
8823ff48bf5SDavid du Colombier {
8833ff48bf5SDavid du Colombier gs_const_string gnstr;
8843ff48bf5SDavid du Colombier
8853ff48bf5SDavid du Colombier if (glyph == gs_no_glyph)
8863ff48bf5SDavid du Colombier return false;
8873ff48bf5SDavid du Colombier if (glyph >= gs_min_cid_glyph)
8883ff48bf5SDavid du Colombier return (glyph == gs_min_cid_glyph);
889*593dc095SDavid du Colombier return (bfont->procs.glyph_name((gs_font *)bfont, glyph, &gnstr) >= 0 &&
890*593dc095SDavid du Colombier gnstr.size == 7 && !memcmp(gnstr.data, ".notdef", 7));
8913ff48bf5SDavid du Colombier }
8923ff48bf5SDavid du Colombier
8937dd7cddfSDavid du Colombier /* Dummy character encoding procedure */
8947dd7cddfSDavid du Colombier gs_glyph
gs_no_encode_char(gs_font * pfont,gs_char chr,gs_glyph_space_t glyph_space)8957dd7cddfSDavid du Colombier gs_no_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t glyph_space)
8967dd7cddfSDavid du Colombier {
8977dd7cddfSDavid du Colombier return gs_no_glyph;
8987dd7cddfSDavid du Colombier }
8997dd7cddfSDavid du Colombier
900*593dc095SDavid du Colombier /* Dummy glyph decoding procedure */
901*593dc095SDavid du Colombier gs_char
gs_no_decode_glyph(gs_font * pfont,gs_glyph glyph)902*593dc095SDavid du Colombier gs_no_decode_glyph(gs_font *pfont, gs_glyph glyph)
903*593dc095SDavid du Colombier {
904*593dc095SDavid du Colombier return GS_NO_CHAR;
905*593dc095SDavid du Colombier }
906*593dc095SDavid du Colombier
9077dd7cddfSDavid du Colombier /* Dummy glyph enumeration procedure */
9087dd7cddfSDavid du Colombier int
gs_no_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)9097dd7cddfSDavid du Colombier gs_no_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,
9107dd7cddfSDavid du Colombier gs_glyph *pglyph)
9117dd7cddfSDavid du Colombier {
9127dd7cddfSDavid du Colombier return_error(gs_error_undefined);
9137dd7cddfSDavid du Colombier }
9147dd7cddfSDavid du Colombier
9157dd7cddfSDavid du Colombier /* Default glyph info procedure */
9167dd7cddfSDavid du Colombier int
gs_default_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)9177dd7cddfSDavid du Colombier gs_default_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
9187dd7cddfSDavid du Colombier int members, gs_glyph_info_t *info)
919*593dc095SDavid du Colombier { /* WMode may be inherited from an upper font. */
920*593dc095SDavid du Colombier gx_path path;
9217dd7cddfSDavid du Colombier int returned = 0;
9227dd7cddfSDavid du Colombier int code;
923*593dc095SDavid du Colombier int wmode = ((members & GLYPH_INFO_WIDTH1) != 0);
924*593dc095SDavid du Colombier double sbw[4] = {0, 0, 0, 0};
925*593dc095SDavid du Colombier /* Currently glyph_outline retrieves sbw only with type 1,2,9 fonts. */
926*593dc095SDavid du Colombier bool charstrings_font = (font->FontType == ft_encrypted ||
927*593dc095SDavid du Colombier font->FontType == ft_encrypted2 ||
928*593dc095SDavid du Colombier font->FontType == ft_CID_encrypted);
9297dd7cddfSDavid du Colombier
930*593dc095SDavid du Colombier gx_path_init_bbox_accumulator(&path);
931*593dc095SDavid du Colombier code = gx_path_add_point(&path, fixed_0, fixed_0);
9327dd7cddfSDavid du Colombier if (code < 0)
9337dd7cddfSDavid du Colombier goto out;
934*593dc095SDavid du Colombier code = font->procs.glyph_outline(font, wmode, glyph, pmat, &path, sbw);
9357dd7cddfSDavid du Colombier if (code < 0)
9367dd7cddfSDavid du Colombier goto out;
9377dd7cddfSDavid du Colombier if (members & GLYPH_INFO_WIDTHS) {
9387dd7cddfSDavid du Colombier int wmode = font->WMode;
9397dd7cddfSDavid du Colombier int wmask = GLYPH_INFO_WIDTH0 << wmode;
9407dd7cddfSDavid du Colombier
9417dd7cddfSDavid du Colombier if (members & wmask) {
9427dd7cddfSDavid du Colombier gs_fixed_point pt;
9437dd7cddfSDavid du Colombier
944*593dc095SDavid du Colombier code = gx_path_current_point(&path, &pt);
9457dd7cddfSDavid du Colombier if (code < 0)
9467dd7cddfSDavid du Colombier goto out;
9477dd7cddfSDavid du Colombier info->width[wmode].x = fixed2float(pt.x);
9487dd7cddfSDavid du Colombier info->width[wmode].y = fixed2float(pt.y);
9497dd7cddfSDavid du Colombier returned |= wmask;
9507dd7cddfSDavid du Colombier }
9517dd7cddfSDavid du Colombier }
9527dd7cddfSDavid du Colombier if (members & GLYPH_INFO_BBOX) {
9537dd7cddfSDavid du Colombier gs_fixed_rect bbox;
9547dd7cddfSDavid du Colombier
955*593dc095SDavid du Colombier code = gx_path_bbox(&path, &bbox);
9567dd7cddfSDavid du Colombier if (code < 0)
9577dd7cddfSDavid du Colombier goto out;
9587dd7cddfSDavid du Colombier info->bbox.p.x = fixed2float(bbox.p.x);
9597dd7cddfSDavid du Colombier info->bbox.p.y = fixed2float(bbox.p.y);
9607dd7cddfSDavid du Colombier info->bbox.q.x = fixed2float(bbox.q.x);
9617dd7cddfSDavid du Colombier info->bbox.q.y = fixed2float(bbox.q.y);
9627dd7cddfSDavid du Colombier returned |= GLYPH_INFO_BBOX;
9637dd7cddfSDavid du Colombier }
964*593dc095SDavid du Colombier if (members & (GLYPH_INFO_WIDTH0 << wmode) && charstrings_font) {
965*593dc095SDavid du Colombier if (pmat == 0) {
966*593dc095SDavid du Colombier info->width[wmode].x = sbw[2];
967*593dc095SDavid du Colombier info->width[wmode].y = sbw[3];
968*593dc095SDavid du Colombier } else {
969*593dc095SDavid du Colombier code = gs_distance_transform(sbw[2], sbw[3], pmat, &info->width[wmode]);
970*593dc095SDavid du Colombier if (code < 0)
971*593dc095SDavid du Colombier return code;
972*593dc095SDavid du Colombier }
973*593dc095SDavid du Colombier returned |= GLYPH_INFO_WIDTH0 << wmode;
974*593dc095SDavid du Colombier }
975*593dc095SDavid du Colombier if (members & (GLYPH_INFO_VVECTOR0 << wmode) && charstrings_font) {
976*593dc095SDavid du Colombier if (pmat == 0) {
977*593dc095SDavid du Colombier info->v.x = sbw[0];
978*593dc095SDavid du Colombier info->v.y = sbw[1];
979*593dc095SDavid du Colombier } else {
980*593dc095SDavid du Colombier gs_distance_transform(sbw[0], sbw[1], pmat, &info->v);
981*593dc095SDavid du Colombier if (code < 0)
982*593dc095SDavid du Colombier return code;
983*593dc095SDavid du Colombier }
984*593dc095SDavid du Colombier returned |= GLYPH_INFO_VVECTOR0 << wmode;
985*593dc095SDavid du Colombier }
9867dd7cddfSDavid du Colombier if (members & GLYPH_INFO_NUM_PIECES) {
9877dd7cddfSDavid du Colombier info->num_pieces = 0;
9887dd7cddfSDavid du Colombier returned |= GLYPH_INFO_NUM_PIECES;
9897dd7cddfSDavid du Colombier }
9907dd7cddfSDavid du Colombier returned |= members & GLYPH_INFO_PIECES; /* no pieces stored */
9917dd7cddfSDavid du Colombier out:
9927dd7cddfSDavid du Colombier info->members = returned;
9937dd7cddfSDavid du Colombier return code;
9947dd7cddfSDavid du Colombier }
9957dd7cddfSDavid du Colombier
9967dd7cddfSDavid du Colombier /* Dummy glyph outline procedure */
9977dd7cddfSDavid du Colombier int
gs_no_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])998*593dc095SDavid du Colombier gs_no_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
999*593dc095SDavid du Colombier gx_path *ppath, double sbw[4])
10007dd7cddfSDavid du Colombier {
10017dd7cddfSDavid du Colombier return_error(gs_error_undefined);
10027dd7cddfSDavid du Colombier }
1003*593dc095SDavid du Colombier
1004*593dc095SDavid du Colombier /* Dummy glyph name procedure */
1005*593dc095SDavid du Colombier int
gs_no_glyph_name(gs_font * font,gs_glyph glyph,gs_const_string * pstr)1006*593dc095SDavid du Colombier gs_no_glyph_name(gs_font *font, gs_glyph glyph, gs_const_string *pstr)
1007*593dc095SDavid du Colombier {
1008*593dc095SDavid du Colombier return_error(gs_error_undefined);
1009*593dc095SDavid du Colombier }
1010*593dc095SDavid du Colombier
1011