xref: /plan9/sys/src/cmd/gs/src/gxfcache.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1992, 1995, 1997, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gxfcache.h,v 1.27 2004/08/19 19:33:09 stefan Exp $ */
18 /* Font and character cache definitions and procedures */
19 /* Requires gsfont.h */
20 
21 #ifndef gxfcache_INCLUDED
22 #  define gxfcache_INCLUDED
23 
24 #include "gsccode.h"
25 #include "gsuid.h"
26 #include "gsxfont.h"
27 #include "gxbcache.h"
28 #include "gxfixed.h"
29 #include "gxftype.h"
30 
31 /* ------ Font/matrix pair cache entry ------ */
32 
33 #ifndef gs_font_DEFINED
34 #  define gs_font_DEFINED
35 typedef struct gs_font_s gs_font;
36 #endif
37 #ifndef cached_fm_pair_DEFINED
38 #  define cached_fm_pair_DEFINED
39 typedef struct cached_fm_pair_s cached_fm_pair;
40 #endif
41 #ifndef gs_matrix_DEFINED
42 #  define gs_matrix_DEFINED
43 typedef struct gs_matrix_s gs_matrix;
44 #endif
45 
46 #ifndef ttfFont_DEFINED
47 #  define ttfFont_DEFINED
48 typedef struct ttfFont_s ttfFont;
49 #endif
50 #ifndef gx_ttfReader_DEFINED
51 #  define gx_ttfReader_DEFINED
52 typedef struct gx_ttfReader_s gx_ttfReader;
53 #endif
54 #ifndef ttfInterpreter_DEFINED
55 #  define ttfInterpreter_DEFINED
56 typedef struct ttfInterpreter_s ttfInterpreter;
57 #endif
58 #ifndef gx_device_spot_analyzer_DEFINED
59 #   define gx_device_spot_analyzer_DEFINED
60 typedef struct gx_device_spot_analyzer_s gx_device_spot_analyzer;
61 #endif
62 #ifndef gs_state_DEFINED
63 #  define gs_state_DEFINED
64 typedef struct gs_state_s gs_state;
65 #endif
66 
67 
68 /*
69  * Define the entry for a cached (font,matrix) pair.  If the UID
70  * is valid, the font pointer may be 0, since we keep entries even for
71  * fonts unloaded by a restore if they have valid UIDs; in this case,
72  * we also need the FontType as part of the key.
73  * Note that because of the dependency on StrokeWidth, we can't cache
74  * fonts with non-zero PaintType.
75  * We can't use the address of the pair for the hash value,
76  * since the GC may move pairs in storage, so we create a hash
77  * when we allocate the pair initially.
78  */
79 struct cached_fm_pair_s {
80     gs_font *font;		/* base font */
81     gs_uid UID;			/* font UniqueID or XUID */
82     font_type FontType;		/* (part of key if UID is valid) */
83     uint hash;			/* hash for this pair */
84     float mxx, mxy, myx, myy;	/* transformation */
85     int num_chars;		/* # of cached chars with this */
86     /* f/m pair */
87     bool xfont_tried;		/* true if we looked up an xfont */
88     gx_xfont *xfont;		/* the xfont (if any) */
89     gs_memory_t *memory;	/* the allocator for the xfont */
90     uint index;			/* index of this pair in mdata */
91     ttfFont *ttf;		/* True Type interpreter data. */
92     gx_ttfReader *ttr;		/* True Type interpreter data. */
93     bool design_grid;           /* A charpath font face.  */
94 };
95 
96 #define private_st_cached_fm_pair() /* in gxccman.c */\
97   gs_private_st_ptrs5(st_cached_fm_pair, cached_fm_pair,\
98     "cached_fm_pair", fm_pair_enum_ptrs, fm_pair_reloc_ptrs,\
99     font, UID.xvalues, xfont, ttf, ttr)
100 #define private_st_cached_fm_pair_elt()	/* in gxccman.c */\
101   gs_private_st_element(st_cached_fm_pair_element, cached_fm_pair,\
102     "cached_fm_pair[]", fm_pair_element_enum_ptrs, fm_pair_element_reloc_ptrs,\
103     st_cached_fm_pair)
104 /* If font == 0 and UID is invalid, this is a free entry. */
105 #define fm_pair_is_free(pair)\
106   ((pair)->font == 0 && !uid_is_valid(&(pair)->UID))
107 #define fm_pair_set_free(pair)\
108   ((pair)->font = 0, uid_set_invalid(&(pair)->UID))
109 #define fm_pair_init(pair)\
110   (fm_pair_set_free(pair), (pair)->xfont_tried = false, (pair)->xfont = 0)
111 
112 /* The font/matrix pair cache itself. */
113 typedef struct fm_pair_cache_s {
114     uint msize, mmax;		/* # of cached font/matrix pairs */
115     cached_fm_pair *mdata;
116     uint mnext;			/* rover for allocating font/matrix pairs */
117 } fm_pair_cache;
118 
119 /* ------ Character cache entry ------- */
120 
121 /* Define the allocation chunk type. */
122 typedef gx_bits_cache_chunk char_cache_chunk;
123 
124 /*
125  * This is a subclass of the entry in a general bitmap cache.
126  * The character cache contains both used and free blocks.
127  * All blocks have a common header; free blocks have ONLY the header.
128  */
129 typedef gx_cached_bits_head cached_char_head;
130 
131 #define cc_head_is_free(cch) cb_head_is_free(cch)
132 #define cc_head_set_free(cch) cb_head_set_free(cch)
133 /*
134  * Define the cache entry for an individual character.
135  * The bits, if any, immediately follow the structure;
136  * characters with only xfont definitions may not have bits.
137  * An entry is 'real' if it is not free and if pair != 0.
138  * We maintain the invariant that at least one of the following must be true
139  * for all real entries:
140  *      - cc_has_bits(cc);
141  *      - cc->xglyph != gx_no_xglyph && cc_pair(cc)->xfont != 0.
142  */
143 #ifndef cached_char_DEFINED
144 #  define cached_char_DEFINED
145 typedef struct cached_char_s cached_char;
146 
147 #endif
148 struct cached_char_s {
149 
150     /* The code, font/matrix pair, wmode, and depth */
151     /* are the 'key' in the cache. */
152     /* gx_cached_bits_common includes depth. */
153 
154     gx_cached_bits_common;	/* (must be first) */
155 #define cc_depth(cc) ((cc)->cb_depth)
156 #define cc_set_depth(cc, d) ((cc)->cb_depth = (d))
157     cached_fm_pair *pair;
158     bool linked;
159 #define cc_pair(cc) ((cc)->pair)
160 #define cc_set_pair_only(cc, p) ((cc)->pair = (p))
161     gs_glyph code;		/* glyph code */
162     byte wmode;			/* writing mode (0 or 1) */
163 
164     /* The following are neither 'key' nor 'value'. */
165 
166     char_cache_chunk *chunk;	/* chunk where this char */
167     /* is allocated */
168     uint loc;			/* relative location in chunk */
169     uint pair_index;		/* index of pair in mdata */
170     gs_fixed_point subpix_origin; /* glyph origin offset modulo pixel */
171 
172     /* The rest of the structure is the 'value'. */
173     /* gx_cached_bits_common has width, height, raster, */
174     /* shift (not used here), id. */
175 
176 #define cc_raster(cc) ((cc)->raster)
177 #define cc_set_raster(cc, r) ((cc)->raster = (r))
178     gx_xglyph xglyph;		/* the xglyph for the xfont, if any */
179     gs_fixed_point wxy;		/* width in device coords */
180     gs_fixed_point offset;	/* (-llx, -lly) in device coords */
181 };
182 
183 #define cc_is_free(cc) cc_head_is_free(&(cc)->head)
184 #define cc_set_free(cc) cc_head_set_free(&(cc)->head)
185 #define cc_set_pair(cc, p)\
186   ((cc)->pair_index = ((cc)->pair = (p))->index)
187 #define cc_has_bits(cc) ((cc)->id != gx_no_bitmap_id)
188 /*
189  * Memory management for cached_chars is a little unusual.
190  * cached_chars are never instantiated on their own; a pointer to
191  * a cached_char points into the middle of a cache chunk.
192  * Consequently, such pointers can't be traced or relocated
193  * in the usual way.  What we do instead is allocate the cache
194  * outside garbage-collectable space; we do all the tracing and relocating
195  * of pointers *from* the cache (currently only the head.pair pointer)
196  * when we trace or relocate the font "directory" that owns the cache.
197  *
198  * Since cached_chars are (currently) never instantiated on their own,
199  * they only have a descriptor so that cached_char_ptr can trace them.
200  */
201 #define private_st_cached_char() /* in gxccman.c */\
202   gs_private_st_composite(st_cached_char, cached_char, "cached_char",\
203     cached_char_enum_ptrs, cached_char_reloc_ptrs)
204 #define private_st_cached_char_ptr() /* in gxccman.c */\
205   gs_private_st_composite(st_cached_char_ptr, cached_char *,\
206     "cached_char *", cc_ptr_enum_ptrs, cc_ptr_reloc_ptrs)
207 #define private_st_cached_char_ptr_elt() /* in gxccman.c */\
208   gs_private_st_element(st_cached_char_ptr_element, cached_char *,\
209     "cached_char *[]", cc_ptr_element_enum_ptrs, cc_ptr_element_reloc_ptrs,\
210     st_cached_char_ptr)
211 
212 /*
213  * Define the alignment and size of the cache structures.
214  */
215 #define align_cached_char_mod align_cached_bits_mod
216 #define sizeof_cached_char\
217   ROUND_UP(sizeof(cached_char), align_cached_char_mod)
218 #define cc_bits(cc) ((byte *)(cc) + sizeof_cached_char)
219 #define cc_const_bits(cc) ((const byte *)(cc) + sizeof_cached_char)
220 
221 /* Define the hash index for a (glyph, fm_pair) key. */
222 #define chars_head_index(glyph, pair)\
223   ((uint)(glyph) * 59 + (pair)->hash * 73)	/* scramble it a bit */
224 
225 /* ------ Character cache ------ */
226 
227 /*
228  * So that we can find all the entries in the cache without
229  * following chains of pointers, we use open hashing rather than
230  * chained hashing for the lookup table.
231  */
232 typedef struct char_cache_s {
233     /* gx_bits_cache_common provides chunks, cnext, */
234     /* bsize, csize. */
235     gx_bits_cache_common;
236     gs_memory_t *struct_memory;
237     gs_memory_t *bits_memory;
238     cached_char **table;	/* hash table */
239     uint table_mask;		/* (a power of 2 -1) */
240     uint bmax;			/* max bsize */
241     uint cmax;			/* max csize */
242     uint bspace;		/* space allocated for chunks */
243     uint lower;			/* min size at which cached chars */
244     /* should be stored compressed */
245     uint upper;			/* max size of a single cached char */
246     gs_glyph_mark_proc_t mark_glyph;
247     void *mark_glyph_data;	/* closure data */
248 } char_cache;
249 
250 /* ------ Font/character cache ------ */
251 
252 /* A font "directory" (font/character cache manager). */
253 #ifndef gs_font_dir_DEFINED
254 #  define gs_font_dir_DEFINED
255 typedef struct gs_font_dir_s gs_font_dir;
256 #endif
257 struct gs_font_dir_s {
258 
259     /* Original (unscaled) fonts */
260 
261     gs_font *orig_fonts;
262 
263     /* Scaled font cache */
264 
265     gs_font *scaled_fonts;	/* list of recently scaled fonts */
266     uint ssize, smax;
267 
268     /* Font/matrix pair cache */
269 
270     fm_pair_cache fmcache;
271 
272     /* Character cache */
273 
274     char_cache ccache;
275     /* Scanning cache for GC */
276     uint enum_index;		/* index (N) */
277     uint enum_offset;		/* ccache.table[offset] is N'th non-zero entry */
278 
279     /* User parameter AlignToPixels. */
280     bool align_to_pixels;
281 
282     /* A table for converting glyphs to Unicode */
283     void *glyph_to_unicode_table; /* closure data */
284 
285     /* An allocator for extension structures */
286     gs_memory_t *memory;
287     ttfInterpreter *tti;
288     /* User parameter GridFitTT. */
289     uint grid_fit_tt;
290     gx_device_spot_analyzer *san;
291     int (*global_glyph_code)(const gs_memory_t *mem, gs_const_string *gstr, gs_glyph *pglyph);
292 };
293 
294 #define private_st_font_dir()	/* in gsfont.c */\
295   gs_private_st_composite(st_font_dir, gs_font_dir, "gs_font_dir",\
296     font_dir_enum_ptrs, font_dir_reloc_ptrs)
297 
298 /* Enumerate the pointers in a font directory, except for orig_fonts. */
299 #define font_dir_do_ptrs(m)\
300   /*m(-,orig_fonts)*/ m(0,scaled_fonts) m(1,fmcache.mdata)\
301   m(2,ccache.table) m(3,ccache.mark_glyph_data)\
302   m(4,glyph_to_unicode_table) m(5,tti) m(6,san)
303 #define st_font_dir_max_ptrs 7
304 
305 /* Character cache procedures (in gxccache.c and gxccman.c) */
306 int gx_char_cache_alloc(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
307 			gs_font_dir * pdir, uint bmax, uint mmax,
308 			uint cmax, uint upper);
309 void gx_char_cache_init(gs_font_dir *);
310 void gx_purge_selected_cached_chars(gs_font_dir *,
311 				    bool(*)(const gs_memory_t *, cached_char *, void *), void *);
312 void gx_compute_char_matrix(const gs_matrix *char_tm, const gs_log2_scale_point *log2_scale,
313     float *mxx, float *mxy, float *myx, float *myy);
314 void gx_compute_ccache_key(gs_font * pfont, const gs_matrix *char_tm,
315     const gs_log2_scale_point *log2_scale, bool design_grid,
316     float *mxx, float *mxy, float *myx, float *myy);
317 int gx_lookup_fm_pair(gs_font * pfont, const gs_matrix *char_tm,
318     const gs_log2_scale_point *log2_scale, bool design_grid, cached_fm_pair **ppair);
319 int gx_add_fm_pair(register gs_font_dir * dir, gs_font * font, const gs_uid * puid,
320 	       const gs_matrix * char_tm, const gs_log2_scale_point *log2_scale,
321 	       bool design_grid, cached_fm_pair **ppair);
322 void gx_lookup_xfont(const gs_state *, cached_fm_pair *, int);
323 void gs_purge_fm_pair(gs_font_dir *, cached_fm_pair *, int);
324 void gs_purge_font_from_char_caches(gs_font_dir *, const gs_font *);
325 
326 #endif /* gxfcache_INCLUDED */
327