Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | #include "fitz.h" |
2 | |||
3 | #define MAX_FONT_SIZE 1000 |
||
4 | #define MAX_GLYPH_SIZE 256 |
||
5 | #define MAX_CACHE_SIZE (1024*1024) |
||
6 | |||
7 | typedef struct fz_glyph_key_s fz_glyph_key; |
||
8 | |||
9 | struct fz_glyph_cache_s |
||
10 | { |
||
11 | fz_hash_table *hash; |
||
12 | int total; |
||
13 | }; |
||
14 | |||
15 | struct fz_glyph_key_s |
||
16 | { |
||
17 | fz_font *font; |
||
18 | int a, b; |
||
19 | int c, d; |
||
20 | unsigned short gid; |
||
21 | unsigned char e, f; |
||
22 | }; |
||
23 | |||
24 | fz_glyph_cache * |
||
25 | fz_new_glyph_cache(void) |
||
26 | { |
||
27 | fz_glyph_cache *cache; |
||
28 | |||
29 | cache = fz_malloc(sizeof(fz_glyph_cache)); |
||
30 | cache->hash = fz_new_hash_table(509, sizeof(fz_glyph_key)); |
||
31 | cache->total = 0; |
||
32 | |||
33 | return cache; |
||
34 | } |
||
35 | |||
36 | static void |
||
37 | fz_evict_glyph_cache(fz_glyph_cache *cache) |
||
38 | { |
||
39 | fz_glyph_key *key; |
||
40 | fz_pixmap *pixmap; |
||
41 | int i; |
||
42 | |||
43 | for (i = 0; i < fz_hash_len(cache->hash); i++) |
||
44 | { |
||
45 | key = fz_hash_get_key(cache->hash, i); |
||
46 | if (key->font) |
||
47 | fz_drop_font(key->font); |
||
48 | pixmap = fz_hash_get_val(cache->hash, i); |
||
49 | if (pixmap) |
||
50 | fz_drop_pixmap(pixmap); |
||
51 | } |
||
52 | |||
53 | cache->total = 0; |
||
54 | |||
55 | fz_empty_hash(cache->hash); |
||
56 | } |
||
57 | |||
58 | void |
||
59 | fz_free_glyph_cache(fz_glyph_cache *cache) |
||
60 | { |
||
61 | fz_evict_glyph_cache(cache); |
||
62 | fz_free_hash(cache->hash); |
||
63 | fz_free(cache); |
||
64 | } |
||
65 | |||
66 | fz_pixmap * |
||
67 | fz_render_stroked_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke) |
||
68 | { |
||
69 | if (font->ft_face) |
||
70 | return fz_render_ft_stroked_glyph(font, gid, trm, ctm, stroke); |
||
71 | return fz_render_glyph(cache, font, gid, trm, NULL); |
||
72 | } |
||
73 | |||
74 | fz_pixmap * |
||
75 | fz_render_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model) |
||
76 | { |
||
77 | fz_glyph_key key; |
||
78 | fz_pixmap *val; |
||
79 | float size = fz_matrix_expansion(ctm); |
||
80 | |||
81 | if (size > MAX_FONT_SIZE) |
||
82 | { |
||
83 | /* TODO: this case should be handled by rendering glyph as a path fill */ |
||
84 | fz_warn("font size too large (%g), not rendering glyph", size); |
||
85 | return NULL; |
||
86 | } |
||
87 | |||
88 | memset(&key, 0, sizeof key); |
||
89 | key.font = font; |
||
90 | key.gid = gid; |
||
91 | key.a = ctm.a * 65536; |
||
92 | key.b = ctm.b * 65536; |
||
93 | key.c = ctm.c * 65536; |
||
94 | key.d = ctm.d * 65536; |
||
95 | key.e = (ctm.e - floorf(ctm.e)) * 256; |
||
96 | key.f = (ctm.f - floorf(ctm.f)) * 256; |
||
97 | |||
98 | val = fz_hash_find(cache->hash, &key); |
||
99 | if (val) |
||
100 | return fz_keep_pixmap(val); |
||
101 | |||
102 | ctm.e = floorf(ctm.e) + key.e / 256.0f; |
||
103 | ctm.f = floorf(ctm.f) + key.f / 256.0f; |
||
104 | |||
105 | if (font->ft_face) |
||
106 | { |
||
107 | val = fz_render_ft_glyph(font, gid, ctm); |
||
108 | } |
||
109 | else if (font->t3procs) |
||
110 | { |
||
111 | val = fz_render_t3_glyph(font, gid, ctm, model); |
||
112 | } |
||
113 | else |
||
114 | { |
||
115 | fz_warn("assert: uninitialized font structure"); |
||
116 | return NULL; |
||
117 | } |
||
118 | |||
119 | if (val) |
||
120 | { |
||
121 | if (val->w < MAX_GLYPH_SIZE && val->h < MAX_GLYPH_SIZE) |
||
122 | { |
||
123 | if (cache->total + val->w * val->h > MAX_CACHE_SIZE) |
||
124 | fz_evict_glyph_cache(cache); |
||
125 | fz_keep_font(key.font); |
||
126 | fz_hash_insert(cache->hash, &key, val); |
||
127 | cache->total += val->w * val->h; |
||
128 | return fz_keep_pixmap(val); |
||
129 | } |
||
130 | return val; |
||
131 | } |
||
132 | |||
133 | return NULL; |
||
134 | }>>> |