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