|
1 # HG changeset patch |
|
2 # User Andrea Canciani <ranma42@gmail.com>, Adrian Johnson <ajohnson@redneon.com> |
|
3 # Date 1354838294 -46800 |
|
4 # Node ID 390df735b9d5c5ba07a4d3fe9ca2ebc9e7626a78 |
|
5 # Parent e30a5b6a5a003b85fc1ca8b76719a56ef59d976e |
|
6 Bug 717178. Part 2: Import changesets eb29a25d, 6e3e3291 and 101fab7c from upstream. |
|
7 ====== |
|
8 |
|
9 From 101fab7cd8a90f7cf3d8113c792b3f8c2a9afb7d Mon Sep 17 00:00:00 2001 |
|
10 From: Andrea Canciani <ranma42@gmail.com> |
|
11 Date: Wed, 15 Jun 2011 09:37:36 +0000 |
|
12 Subject: win32-font: Improve static data reset function |
|
13 |
|
14 The hashtable is guaranteed to only contain font faces which are |
|
15 currently referenced, hence there is no need to remove any font face |
|
16 when it is reset (just like for toy-font). |
|
17 |
|
18 This makes the function simpler and fixes the assertion |
|
19 |
|
20 Assertion failed: predicate != NULL, file cairo-hash.c, line 373 |
|
21 |
|
22 hit by multiple tests (the first one being "clear"). |
|
23 |
|
24 See https://bugs.freedesktop.org/show_bug.cgi?id=38049 |
|
25 |
|
26 ====== |
|
27 |
|
28 From eb29a25dd6dddc511388bf883c9b95843ecdb823 Mon Sep 17 00:00:00 2001 |
|
29 From: Adrian Johnson <ajohnson@redneon.com> |
|
30 Date: Tue, 16 Nov 2010 13:18:39 +0000 |
|
31 Subject: win32: Use a font_face hash table to provide unique font faces |
|
32 |
|
33 Similar to the freetype and toy font backends, use a hash table |
|
34 to map logfont,hfont to font faces. |
|
35 |
|
36 This fixes the multiple embedding of the same font in PDF. |
|
37 |
|
38 https://bugs.freedesktop.org/show_bug.cgi?id=24849 |
|
39 |
|
40 ====== |
|
41 |
|
42 From 6e3e329170ab4b96bc0d587c8071e869e228e758 Mon Sep 17 00:00:00 2001 |
|
43 From: Adrian Johnson <ajohnson@redneon.com> |
|
44 Date: Thu, 18 Nov 2010 12:37:45 +0000 |
|
45 Subject: win32: fix font_face hashing |
|
46 |
|
47 some bugs were discovered while testing with firefox |
|
48 |
|
49 ====== |
|
50 |
|
51 diff --git a/gfx/cairo/cairo/src/cairo-debug.c b/gfx/cairo/cairo/src/cairo-debug.c |
|
52 --- a/gfx/cairo/cairo/src/cairo-debug.c |
|
53 +++ b/gfx/cairo/cairo/src/cairo-debug.c |
|
54 @@ -64,16 +64,20 @@ cairo_debug_reset_static_data (void) |
|
55 _cairo_scaled_font_map_destroy (); |
|
56 |
|
57 _cairo_toy_font_face_reset_static_data (); |
|
58 |
|
59 #if CAIRO_HAS_FT_FONT |
|
60 _cairo_ft_font_reset_static_data (); |
|
61 #endif |
|
62 |
|
63 +#if CAIRO_HAS_WIN32_FONT |
|
64 + _cairo_win32_font_reset_static_data (); |
|
65 +#endif |
|
66 + |
|
67 _cairo_intern_string_reset_static_data (); |
|
68 |
|
69 _cairo_scaled_font_reset_static_data (); |
|
70 |
|
71 _cairo_pattern_reset_static_data (); |
|
72 |
|
73 _cairo_clip_reset_static_data (); |
|
74 |
|
75 diff --git a/gfx/cairo/cairo/src/cairo-mutex-list-private.h b/gfx/cairo/cairo/src/cairo-mutex-list-private.h |
|
76 --- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h |
|
77 +++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h |
|
78 @@ -46,16 +46,20 @@ CAIRO_MUTEX_DECLARE (_cairo_intern_strin |
|
79 CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex) |
|
80 CAIRO_MUTEX_DECLARE (_cairo_scaled_glyph_page_cache_mutex) |
|
81 CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex) |
|
82 |
|
83 #if CAIRO_HAS_FT_FONT |
|
84 CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex) |
|
85 #endif |
|
86 |
|
87 +#if CAIRO_HAS_WIN32_FONT |
|
88 +CAIRO_MUTEX_DECLARE (_cairo_win32_font_face_mutex) |
|
89 +#endif |
|
90 + |
|
91 #if CAIRO_HAS_XLIB_SURFACE |
|
92 CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex) |
|
93 #endif |
|
94 |
|
95 #if CAIRO_HAS_XCB_SURFACE |
|
96 CAIRO_MUTEX_DECLARE (_cairo_xcb_connections_mutex) |
|
97 #endif |
|
98 |
|
99 diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c |
|
100 --- a/gfx/cairo/cairo/src/cairo-win32-font.c |
|
101 +++ b/gfx/cairo/cairo/src/cairo-win32-font.c |
|
102 @@ -42,16 +42,18 @@ |
|
103 # define _WIN32_WINNT 0x0500 |
|
104 #endif |
|
105 |
|
106 #include "cairoint.h" |
|
107 |
|
108 #include "cairo-win32-private.h" |
|
109 #include "cairo-error-private.h" |
|
110 |
|
111 +#include <wchar.h> |
|
112 + |
|
113 #ifndef SPI_GETFONTSMOOTHINGTYPE |
|
114 #define SPI_GETFONTSMOOTHINGTYPE 0x200a |
|
115 #endif |
|
116 #ifndef FE_FONTSMOOTHINGCLEARTYPE |
|
117 #define FE_FONTSMOOTHINGCLEARTYPE 2 |
|
118 #endif |
|
119 #ifndef CLEARTYPE_QUALITY |
|
120 #define CLEARTYPE_QUALITY 5 |
|
121 @@ -1887,19 +1889,17 @@ struct _cairo_win32_font_face { |
|
122 cairo_font_face_t base; |
|
123 LOGFONTW logfont; |
|
124 HFONT hfont; |
|
125 }; |
|
126 |
|
127 /* implement the platform-specific interface */ |
|
128 |
|
129 static void |
|
130 -_cairo_win32_font_face_destroy (void *abstract_face) |
|
131 -{ |
|
132 -} |
|
133 +_cairo_win32_font_face_destroy (void *abstract_face); |
|
134 |
|
135 static cairo_bool_t |
|
136 _is_scale (const cairo_matrix_t *matrix, double scale) |
|
137 { |
|
138 return matrix->xx == scale && matrix->yy == scale && |
|
139 matrix->xy == 0. && matrix->yx == 0. && |
|
140 matrix->x0 == 0. && matrix->y0 == 0.; |
|
141 } |
|
142 @@ -1932,16 +1932,128 @@ static cairo_status_t |
|
143 |
|
144 const cairo_font_face_backend_t _cairo_win32_font_face_backend = { |
|
145 CAIRO_FONT_TYPE_WIN32, |
|
146 _cairo_win32_font_face_create_for_toy, |
|
147 _cairo_win32_font_face_destroy, |
|
148 _cairo_win32_font_face_scaled_font_create |
|
149 }; |
|
150 |
|
151 +/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t. |
|
152 + * The primary purpose of this mapping is to provide unique |
|
153 + * #cairo_font_face_t values so that our cache and mapping from |
|
154 + * #cairo_font_face_t => #cairo_scaled_font_t works. Once the |
|
155 + * corresponding #cairo_font_face_t objects fall out of downstream |
|
156 + * caches, we don't need them in this hash table anymore. |
|
157 + * |
|
158 + * Modifications to this hash table are protected by |
|
159 + * _cairo_win32_font_face_mutex. |
|
160 + */ |
|
161 + |
|
162 +static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL; |
|
163 + |
|
164 +static int |
|
165 +_cairo_win32_font_face_keys_equal (const void *key_a, |
|
166 + const void *key_b); |
|
167 + |
|
168 +static void |
|
169 +_cairo_win32_font_face_hash_table_destroy (void) |
|
170 +{ |
|
171 + cairo_hash_table_t *hash_table; |
|
172 + |
|
173 + /* We manually acquire the lock rather than calling |
|
174 + * _cairo_win32_font_face_hash_table_lock simply to avoid creating |
|
175 + * the table only to destroy it again. */ |
|
176 + CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex); |
|
177 + hash_table = cairo_win32_font_face_hash_table; |
|
178 + cairo_win32_font_face_hash_table = NULL; |
|
179 + CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); |
|
180 + |
|
181 + if (hash_table != NULL) |
|
182 + _cairo_hash_table_destroy (hash_table); |
|
183 +} |
|
184 + |
|
185 +static cairo_hash_table_t * |
|
186 +_cairo_win32_font_face_hash_table_lock (void) |
|
187 +{ |
|
188 + CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex); |
|
189 + |
|
190 + if (unlikely (cairo_win32_font_face_hash_table == NULL)) |
|
191 + { |
|
192 + cairo_win32_font_face_hash_table = |
|
193 + _cairo_hash_table_create (_cairo_win32_font_face_keys_equal); |
|
194 + |
|
195 + if (unlikely (cairo_win32_font_face_hash_table == NULL)) { |
|
196 + CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); |
|
197 + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
|
198 + return NULL; |
|
199 + } |
|
200 + } |
|
201 + |
|
202 + return cairo_win32_font_face_hash_table; |
|
203 +} |
|
204 + |
|
205 +static void |
|
206 +_cairo_win32_font_face_hash_table_unlock (void) |
|
207 +{ |
|
208 + CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); |
|
209 +} |
|
210 + |
|
211 +static void |
|
212 +_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key, |
|
213 + LOGFONTW *logfont, |
|
214 + HFONT font) |
|
215 +{ |
|
216 + unsigned long hash = _CAIRO_HASH_INIT_VALUE; |
|
217 + |
|
218 + key->logfont = *logfont; |
|
219 + key->hfont = font; |
|
220 + |
|
221 + hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName)); |
|
222 + hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight)); |
|
223 + hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic)); |
|
224 + |
|
225 + key->base.hash_entry.hash = hash; |
|
226 +} |
|
227 + |
|
228 +static int |
|
229 +_cairo_win32_font_face_keys_equal (const void *key_a, |
|
230 + const void *key_b) |
|
231 +{ |
|
232 + const cairo_win32_font_face_t *face_a = key_a; |
|
233 + const cairo_win32_font_face_t *face_b = key_b; |
|
234 + |
|
235 + if (face_a->logfont.lfWeight == face_b->logfont.lfWeight && |
|
236 + face_a->logfont.lfItalic == face_b->logfont.lfItalic && |
|
237 + face_a->logfont.lfUnderline == face_b->logfont.lfUnderline && |
|
238 + face_a->logfont.lfStrikeOut == face_b->logfont.lfStrikeOut && |
|
239 + face_a->logfont.lfCharSet == face_b->logfont.lfCharSet && |
|
240 + face_a->logfont.lfOutPrecision == face_b->logfont.lfOutPrecision && |
|
241 + face_a->logfont.lfClipPrecision == face_b->logfont.lfClipPrecision && |
|
242 + face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily && |
|
243 + (wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0)) |
|
244 + return TRUE; |
|
245 + else |
|
246 + return FALSE; |
|
247 +} |
|
248 + |
|
249 +static void |
|
250 +_cairo_win32_font_face_destroy (void *abstract_face) |
|
251 +{ |
|
252 + cairo_hash_table_t *hash_table; |
|
253 + cairo_win32_font_face_t *font_face = abstract_face; |
|
254 + |
|
255 + hash_table = _cairo_win32_font_face_hash_table_lock (); |
|
256 + if (unlikely (hash_table == NULL)) { |
|
257 + return; |
|
258 + } |
|
259 + _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry); |
|
260 + _cairo_win32_font_face_hash_table_unlock (); |
|
261 +} |
|
262 + |
|
263 /** |
|
264 * cairo_win32_font_face_create_for_logfontw_hfont: |
|
265 * @logfont: A #LOGFONTW structure specifying the font to use. |
|
266 * If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement |
|
267 * fields of this structure are ignored. Otherwise lfWidth, lfOrientation and |
|
268 * lfEscapement must be zero. |
|
269 * @font: An #HFONT that can be used when the font matrix is a scale by |
|
270 * -lfHeight and the CTM is identity. |
|
271 @@ -1954,30 +2066,61 @@ const cairo_font_face_backend_t _cairo_w |
|
272 * and can be used with functions such as cairo_win32_scaled_font_select_font(). |
|
273 * |
|
274 * Return value: a newly created #cairo_font_face_t. Free with |
|
275 * cairo_font_face_destroy() when you are done using it. |
|
276 **/ |
|
277 cairo_font_face_t * |
|
278 cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font) |
|
279 { |
|
280 - cairo_win32_font_face_t *font_face; |
|
281 + cairo_win32_font_face_t *font_face, key; |
|
282 + cairo_hash_table_t *hash_table; |
|
283 + cairo_status_t status; |
|
284 |
|
285 + hash_table = _cairo_win32_font_face_hash_table_lock (); |
|
286 + if (unlikely (hash_table == NULL)) { |
|
287 + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
|
288 + return (cairo_font_face_t *)&_cairo_font_face_nil; |
|
289 + } |
|
290 + |
|
291 + _cairo_win32_font_face_init_key (&key, logfont, font); |
|
292 + |
|
293 + /* Return existing unscaled font if it exists in the hash table. */ |
|
294 + font_face = _cairo_hash_table_lookup (hash_table, |
|
295 + &key.base.hash_entry); |
|
296 + if (font_face != NULL) { |
|
297 + cairo_font_face_reference (&font_face->base); |
|
298 + goto DONE; |
|
299 + } |
|
300 + |
|
301 + /* Otherwise create it and insert into hash table. */ |
|
302 font_face = malloc (sizeof (cairo_win32_font_face_t)); |
|
303 if (!font_face) { |
|
304 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
|
305 - return (cairo_font_face_t *)&_cairo_font_face_nil; |
|
306 + goto FAIL; |
|
307 } |
|
308 |
|
309 - font_face->logfont = *logfont; |
|
310 - font_face->hfont = font; |
|
311 - |
|
312 + _cairo_win32_font_face_init_key (font_face, logfont, font); |
|
313 _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend); |
|
314 |
|
315 + assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash); |
|
316 + status = _cairo_hash_table_insert (hash_table, |
|
317 + &font_face->base.hash_entry); |
|
318 + if (unlikely (status)) |
|
319 + goto FAIL; |
|
320 + |
|
321 +DONE: |
|
322 + _cairo_win32_font_face_hash_table_unlock (); |
|
323 + |
|
324 return &font_face->base; |
|
325 + |
|
326 +FAIL: |
|
327 + _cairo_win32_font_face_hash_table_unlock (); |
|
328 + |
|
329 + return (cairo_font_face_t *)&_cairo_font_face_nil; |
|
330 } |
|
331 |
|
332 /** |
|
333 * cairo_win32_font_face_create_for_logfontw: |
|
334 * @logfont: A #LOGFONTW structure specifying the font to use. |
|
335 * The lfHeight, lfWidth, lfOrientation and lfEscapement |
|
336 * fields of this structure are ignored. |
|
337 * |
|
338 @@ -2176,8 +2319,14 @@ cairo_win32_scaled_font_get_device_to_lo |
|
339 cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; |
|
340 if (! _cairo_scaled_font_is_win32 (scaled_font)) { |
|
341 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); |
|
342 cairo_matrix_init_identity (device_to_logical); |
|
343 return; |
|
344 } |
|
345 *device_to_logical = win_font->device_to_logical; |
|
346 } |
|
347 + |
|
348 +void |
|
349 +_cairo_win32_font_reset_static_data (void) |
|
350 +{ |
|
351 + _cairo_win32_font_face_hash_table_destroy (); |
|
352 +} |
|
353 diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h |
|
354 --- a/gfx/cairo/cairo/src/cairoint.h |
|
355 +++ b/gfx/cairo/cairo/src/cairoint.h |
|
356 @@ -403,16 +403,19 @@ cairo_private void |
|
357 _cairo_reset_static_data (void); |
|
358 |
|
359 cairo_private void |
|
360 _cairo_toy_font_face_reset_static_data (void); |
|
361 |
|
362 cairo_private void |
|
363 _cairo_ft_font_reset_static_data (void); |
|
364 |
|
365 +cairo_private void |
|
366 +_cairo_win32_font_reset_static_data (void); |
|
367 + |
|
368 /* the font backend interface */ |
|
369 |
|
370 struct _cairo_unscaled_font_backend { |
|
371 void (*destroy) (void *unscaled_font); |
|
372 }; |
|
373 |
|
374 /* #cairo_toy_font_face_t - simple family/slant/weight font faces used for |
|
375 * the built-in font API |