/* Copyright (C) 1992, 1995, 1997, 1999 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: gxfcache.h,v 1.2.6.1.2.1 2003/01/17 00:49:03 giles Exp $ */ /* Font and character cache definitions and procedures */ /* Requires gsfont.h */ #ifndef gxfcache_INCLUDED # define gxfcache_INCLUDED #include "gsuid.h" #include "gsxfont.h" #include "gxbcache.h" #include "gxftype.h" /* ------ Font/matrix pair cache entry ------ */ #ifndef cached_fm_pair_DEFINED # define cached_fm_pair_DEFINED typedef struct cached_fm_pair_s cached_fm_pair; #endif /* * Define the entry for a cached (font,matrix) pair. If the UID * is valid, the font pointer may be 0, since we keep entries even for * fonts unloaded by a restore if they have valid UIDs; in this case, * we also need the FontType as part of the key. * Note that because of the dependency on StrokeWidth, we can't cache * fonts with non-zero PaintType. * We can't use the address of the pair for the hash value, * since the GC may move pairs in storage, so we create a hash * when we allocate the pair initially. */ struct cached_fm_pair_s { gs_font *font; /* base font */ gs_uid UID; /* font UniqueID or XUID */ font_type FontType; /* (part of key if UID is valid) */ uint hash; /* hash for this pair */ float mxx, mxy, myx, myy; /* transformation */ int num_chars; /* # of cached chars with this */ /* f/m pair */ bool xfont_tried; /* true if we looked up an xfont */ gx_xfont *xfont; /* the xfont (if any) */ gs_memory_t *memory; /* the allocator for the xfont */ uint index; /* index of this pair in mdata */ }; #define private_st_cached_fm_pair() /* in gxccman.c */\ gs_private_st_ptrs3(st_cached_fm_pair, cached_fm_pair,\ "cached_fm_pair", fm_pair_enum_ptrs, fm_pair_reloc_ptrs,\ font, UID.xvalues, xfont) #define private_st_cached_fm_pair_elt() /* in gxccman.c */\ gs_private_st_element(st_cached_fm_pair_element, cached_fm_pair,\ "cached_fm_pair[]", fm_pair_element_enum_ptrs, fm_pair_element_reloc_ptrs,\ st_cached_fm_pair) /* If font == 0 and UID is invalid, this is a free entry. */ #define fm_pair_is_free(pair)\ ((pair)->font == 0 && !uid_is_valid(&(pair)->UID)) #define fm_pair_set_free(pair)\ ((pair)->font = 0, uid_set_invalid(&(pair)->UID)) #define fm_pair_init(pair)\ (fm_pair_set_free(pair), (pair)->xfont_tried = false, (pair)->xfont = 0) /* The font/matrix pair cache itself. */ typedef struct fm_pair_cache_s { uint msize, mmax; /* # of cached font/matrix pairs */ cached_fm_pair *mdata; uint mnext; /* rover for allocating font/matrix pairs */ } fm_pair_cache; /* ------ Character cache entry ------- */ /* Define the allocation chunk type. */ typedef gx_bits_cache_chunk char_cache_chunk; /* * This is a subclass of the entry in a general bitmap cache. * The character cache contains both used and free blocks. * All blocks have a common header; free blocks have ONLY the header. */ typedef gx_cached_bits_head cached_char_head; #define cc_head_is_free(cch) cb_head_is_free(cch) #define cc_head_set_free(cch) cb_head_set_free(cch) /* * Define the cache entry for an individual character. * The bits, if any, immediately follow the structure; * characters with only xfont definitions may not have bits. * An entry is 'real' if it is not free and if pair != 0. * We maintain the invariant that at least one of the following must be true * for all real entries: * - cc_has_bits(cc); * - cc->xglyph != gx_no_xglyph && cc_pair(cc)->xfont != 0. */ #ifndef cached_char_DEFINED # define cached_char_DEFINED typedef struct cached_char_s cached_char; #endif struct cached_char_s { /* The code, font/matrix pair, wmode, and depth */ /* are the 'key' in the cache. */ /* gx_cached_bits_common includes depth. */ gx_cached_bits_common; /* (must be first) */ #define cc_depth(cc) ((cc)->cb_depth) #define cc_set_depth(cc, d) ((cc)->cb_depth = (d)) cached_fm_pair *pair; #define cc_pair(cc) ((cc)->pair) #define cc_set_pair_only(cc, p) ((cc)->pair = (p)) gs_glyph code; /* glyph code */ byte wmode; /* writing mode (0 or 1) */ /* The following are neither 'key' nor 'value'. */ char_cache_chunk *chunk; /* chunk where this char */ /* is allocated */ uint loc; /* relative location in chunk */ uint pair_index; /* index of pair in mdata */ /* The rest of the structure is the 'value'. */ /* gx_cached_bits_common has width, height, raster, */ /* shift (not used here), id. */ #define cc_raster(cc) ((cc)->raster) #define cc_set_raster(cc, r) ((cc)->raster = (r)) gx_xglyph xglyph; /* the xglyph for the xfont, if any */ gs_fixed_point wxy; /* width in device coords */ gs_fixed_point offset; /* (-llx, -lly) in device coords */ }; #define cc_is_free(cc) cc_head_is_free(&(cc)->head) #define cc_set_free(cc) cc_head_set_free(&(cc)->head) #define cc_set_pair(cc, p)\ ((cc)->pair_index = ((cc)->pair = (p))->index) #define cc_has_bits(cc) ((cc)->id != gx_no_bitmap_id) /* * Memory management for cached_chars is a little unusual. * cached_chars are never instantiated on their own; a pointer to * a cached_char points into the middle of a cache chunk. * Consequently, such pointers can't be traced or relocated * in the usual way. What we do instead is allocate the cache * outside garbage-collectable space; we do all the tracing and relocating * of pointers *from* the cache (currently only the head.pair pointer) * when we trace or relocate the font "directory" that owns the cache. * * Since cached_chars are (currently) never instantiated on their own, * they only have a descriptor so that cached_char_ptr can trace them. */ #define private_st_cached_char() /* in gxccman.c */\ gs_private_st_composite(st_cached_char, cached_char, "cached_char",\ cached_char_enum_ptrs, cached_char_reloc_ptrs) #define private_st_cached_char_ptr() /* in gxccman.c */\ gs_private_st_composite(st_cached_char_ptr, cached_char *,\ "cached_char *", cc_ptr_enum_ptrs, cc_ptr_reloc_ptrs) #define private_st_cached_char_ptr_elt() /* in gxccman.c */\ gs_private_st_element(st_cached_char_ptr_element, cached_char *,\ "cached_char *[]", cc_ptr_element_enum_ptrs, cc_ptr_element_reloc_ptrs,\ st_cached_char_ptr) /* * Define the alignment and size of the cache structures. */ #define align_cached_char_mod align_cached_bits_mod #define sizeof_cached_char\ ROUND_UP(sizeof(cached_char), align_cached_char_mod) #define cc_bits(cc) ((byte *)(cc) + sizeof_cached_char) #define cc_const_bits(cc) ((const byte *)(cc) + sizeof_cached_char) /* Define the hash index for a (glyph, fm_pair) key. */ #define chars_head_index(glyph, pair)\ ((uint)(glyph) * 59 + (pair)->hash * 73) /* scramble it a bit */ /* ------ Character cache ------ */ /* * So that we can find all the entries in the cache without * following chains of pointers, we use open hashing rather than * chained hashing for the lookup table. */ typedef struct char_cache_s { /* gx_bits_cache_common provides chunks, cnext, */ /* bsize, csize. */ gx_bits_cache_common; gs_memory_t *struct_memory; gs_memory_t *bits_memory; cached_char **table; /* hash table */ uint table_mask; /* (a power of 2 -1) */ uint bmax; /* max bsize */ uint cmax; /* max csize */ uint bspace; /* space allocated for chunks */ uint lower; /* min size at which cached chars */ /* should be stored compressed */ uint upper; /* max size of a single cached char */ gs_glyph_mark_proc_t mark_glyph; void *mark_glyph_data; /* closure data */ } char_cache; /* ------ Font/character cache ------ */ /* A font "directory" (font/character cache manager). */ #ifndef gs_font_dir_DEFINED # define gs_font_dir_DEFINED typedef struct gs_font_dir_s gs_font_dir; #endif struct gs_font_dir_s { /* Original (unscaled) fonts */ gs_font *orig_fonts; /* Scaled font cache */ gs_font *scaled_fonts; /* list of recently scaled fonts */ uint ssize, smax; /* Font/matrix pair cache */ fm_pair_cache fmcache; /* Character cache */ char_cache ccache; /* Scanning cache for GC */ uint enum_index; /* index (N) */ uint enum_offset; /* ccache.table[offset] is N'th non-zero entry */ }; #define private_st_font_dir() /* in gsfont.c */\ gs_private_st_composite(st_font_dir, gs_font_dir, "gs_font_dir",\ font_dir_enum_ptrs, font_dir_reloc_ptrs) /* Enumerate the pointers in a font directory, except for orig_fonts. */ #define font_dir_do_ptrs(m)\ /*m(-,orig_fonts)*/ m(0,scaled_fonts) m(1,fmcache.mdata)\ m(2,ccache.table) m(3,ccache.mark_glyph_data) #define st_font_dir_max_ptrs 4 /* Character cache procedures (in gxccache.c and gxccman.c) */ int gx_char_cache_alloc(P7(gs_memory_t * struct_mem, gs_memory_t * bits_mem, gs_font_dir * pdir, uint bmax, uint mmax, uint cmax, uint upper)); void gx_char_cache_init(P1(gs_font_dir *)); void gx_purge_selected_cached_chars(P3(gs_font_dir *, bool(*)(P2(cached_char *, void *)), void *)); cached_fm_pair * gx_lookup_fm_pair(P2(gs_font *, const gs_state *)); cached_fm_pair * gx_add_fm_pair(P4(gs_font_dir *, gs_font *, const gs_uid *, const gs_state *)); void gx_lookup_xfont(P3(const gs_state *, cached_fm_pair *, int)); void gs_purge_fm_pair(P3(gs_font_dir *, cached_fm_pair *, int)); #endif /* gxfcache_INCLUDED */