1# HG changeset patch
2# User Robert O'Callahan <robert@ocallahan.org>
3# Date 1357107533 -46800
4# Node ID ed54dfdd2facb11a4d4158138b460a31de45e9f7
5# Parent ab6457cc16ec14ea07386dcfc57cad6b8a9ac55d
6Bug 717178. Part 3 alternative: don't put Win32 cairo_font_face_ts into the font-face cache if they were created with an explicit HFONT. r=jrmuizel
7
8diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c
9--- a/gfx/cairo/cairo/src/cairo-win32-font.c
10+++ b/gfx/cairo/cairo/src/cairo-win32-font.c
11@@ -1941,16 +1942,21 @@ const cairo_font_face_backend_t _cairo_w
12  * The primary purpose of this mapping is to provide unique
13  * #cairo_font_face_t values so that our cache and mapping from
14  * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
15  * corresponding #cairo_font_face_t objects fall out of downstream
16  * caches, we don't need them in this hash table anymore.
17  *
18  * Modifications to this hash table are protected by
19  * _cairo_win32_font_face_mutex.
20+ *
21+ * Only #cairo_font_face_t values with null 'hfont' (no
22+ * HFONT preallocated by caller) are stored in this table. We rely
23+ * on callers to manage the lifetime of the HFONT, and they can't
24+ * do that if we share #cairo_font_face_t values with other callers.
25  */
26
27 static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
28
29 static int
30 _cairo_win32_font_face_keys_equal (const void *key_a,
31 				   const void *key_b);
32
33@@ -2036,22 +2042,24 @@ static int
34 }
35
36 static void
37 _cairo_win32_font_face_destroy (void *abstract_face)
38 {
39     cairo_hash_table_t *hash_table;
40     cairo_win32_font_face_t *font_face = abstract_face;
41
42-    hash_table = _cairo_win32_font_face_hash_table_lock ();
43-    if (unlikely (hash_table == NULL)) {
44-        return;
45+    if (!font_face->hfont) {
46+        hash_table = _cairo_win32_font_face_hash_table_lock ();
47+        if (unlikely (hash_table == NULL)) {
48+            return;
49+        }
50+        _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
51+        _cairo_win32_font_face_hash_table_unlock ();
52     }
53-    _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
54-    _cairo_win32_font_face_hash_table_unlock ();
55 }
56
57 /**
58  * cairo_win32_font_face_create_for_logfontw_hfont:
59  * @logfont: A #LOGFONTW structure specifying the font to use.
60  *   If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement
61  *   fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
62  *   lfEscapement must be zero.
63@@ -2070,55 +2078,63 @@ static void
64  **/
65 cairo_font_face_t *
66 cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
67 {
68     cairo_win32_font_face_t *font_face, key;
69     cairo_hash_table_t *hash_table;
70     cairo_status_t status;
71
72-    hash_table = _cairo_win32_font_face_hash_table_lock ();
73-    if (unlikely (hash_table == NULL)) {
74-        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
75-	return (cairo_font_face_t *)&_cairo_font_face_nil;
76-    }
77+    if (!font) {
78+        hash_table = _cairo_win32_font_face_hash_table_lock ();
79+        if (unlikely (hash_table == NULL)) {
80+            _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
81+	    return (cairo_font_face_t *)&_cairo_font_face_nil;
82+        }
83
84-    _cairo_win32_font_face_init_key (&key, logfont, font);
85+        _cairo_win32_font_face_init_key (&key, logfont, font);
86
87-    /* Return existing unscaled font if it exists in the hash table. */
88-    font_face = _cairo_hash_table_lookup (hash_table,
89-					 &key.base.hash_entry);
90-    if (font_face != NULL) {
91-	cairo_font_face_reference (&font_face->base);
92-	goto DONE;
93+        /* Return existing unscaled font if it exists in the hash table. */
94+        font_face = _cairo_hash_table_lookup (hash_table,
95+                                              &key.base.hash_entry);
96+        if (font_face != NULL) {
97+	    cairo_font_face_reference (&font_face->base);
98+	    goto DONE;
99+        }
100     }
101
102     /* Otherwise create it and insert into hash table. */
103     font_face = malloc (sizeof (cairo_win32_font_face_t));
104     if (!font_face) {
105         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
106 	goto FAIL;
107     }
108
109     _cairo_win32_font_face_init_key (font_face, logfont, font);
110     _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
111+    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
112
113-    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
114-    status = _cairo_hash_table_insert (hash_table,
115-				       &font_face->base.hash_entry);
116-    if (unlikely (status))
117-	goto FAIL;
118+    if (!font) {
119+        status = _cairo_hash_table_insert (hash_table,
120+                                           &font_face->base.hash_entry);
121+        if (unlikely (status))
122+	    goto FAIL;
123+    }
124
125 DONE:
126-    _cairo_win32_font_face_hash_table_unlock ();
127+    if (!font) {
128+        _cairo_win32_font_face_hash_table_unlock ();
129+    }
130
131     return &font_face->base;
132
133 FAIL:
134-    _cairo_win32_font_face_hash_table_unlock ();
135+    if (!font) {
136+        _cairo_win32_font_face_hash_table_unlock ();
137+    }
138
139     return (cairo_font_face_t *)&_cairo_font_face_nil;
140 }
141
142 /**
143  * cairo_win32_font_face_create_for_logfontw:
144  * @logfont: A #LOGFONTW structure specifying the font to use.
145  *   The lfHeight, lfWidth, lfOrientation and lfEscapement
146