gfx/cairo/win32-gdi-font-cache.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/win32-gdi-font-cache.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,375 @@
     1.4 +# HG changeset patch
     1.5 +# User Andrea Canciani <ranma42@gmail.com>, Adrian Johnson <ajohnson@redneon.com>
     1.6 +# Date 1354838294 -46800
     1.7 +# Node ID 390df735b9d5c5ba07a4d3fe9ca2ebc9e7626a78
     1.8 +# Parent e30a5b6a5a003b85fc1ca8b76719a56ef59d976e
     1.9 +Bug 717178. Part 2: Import changesets eb29a25d, 6e3e3291 and 101fab7c from upstream.
    1.10 +======
    1.11 +
    1.12 +From 101fab7cd8a90f7cf3d8113c792b3f8c2a9afb7d Mon Sep 17 00:00:00 2001
    1.13 +From: Andrea Canciani <ranma42@gmail.com>
    1.14 +Date: Wed, 15 Jun 2011 09:37:36 +0000
    1.15 +Subject: win32-font: Improve static data reset function
    1.16 +
    1.17 +The hashtable is guaranteed to only contain font faces which are
    1.18 +currently referenced, hence there is no need to remove any font face
    1.19 +when it is reset (just like for toy-font).
    1.20 +
    1.21 +This makes the function simpler and fixes the assertion
    1.22 +
    1.23 +Assertion failed: predicate != NULL, file cairo-hash.c, line 373
    1.24 +
    1.25 +hit by multiple tests (the first one being "clear").
    1.26 +
    1.27 +See https://bugs.freedesktop.org/show_bug.cgi?id=38049
    1.28 +
    1.29 +======
    1.30 +
    1.31 +From eb29a25dd6dddc511388bf883c9b95843ecdb823 Mon Sep 17 00:00:00 2001
    1.32 +From: Adrian Johnson <ajohnson@redneon.com>
    1.33 +Date: Tue, 16 Nov 2010 13:18:39 +0000
    1.34 +Subject: win32: Use a font_face hash table to provide unique font faces
    1.35 +
    1.36 +Similar to the freetype and toy font backends, use a hash table
    1.37 +to map logfont,hfont to font faces.
    1.38 +
    1.39 +This fixes the multiple embedding of the same font in PDF.
    1.40 +
    1.41 +https://bugs.freedesktop.org/show_bug.cgi?id=24849
    1.42 +
    1.43 +======
    1.44 +
    1.45 +From 6e3e329170ab4b96bc0d587c8071e869e228e758 Mon Sep 17 00:00:00 2001
    1.46 +From: Adrian Johnson <ajohnson@redneon.com>
    1.47 +Date: Thu, 18 Nov 2010 12:37:45 +0000
    1.48 +Subject: win32: fix font_face hashing
    1.49 +
    1.50 +some bugs were discovered while testing with firefox
    1.51 +
    1.52 +======
    1.53 +
    1.54 +diff --git a/gfx/cairo/cairo/src/cairo-debug.c b/gfx/cairo/cairo/src/cairo-debug.c
    1.55 +--- a/gfx/cairo/cairo/src/cairo-debug.c
    1.56 ++++ b/gfx/cairo/cairo/src/cairo-debug.c
    1.57 +@@ -64,16 +64,20 @@ cairo_debug_reset_static_data (void)
    1.58 +     _cairo_scaled_font_map_destroy ();
    1.59 + 
    1.60 +     _cairo_toy_font_face_reset_static_data ();
    1.61 + 
    1.62 + #if CAIRO_HAS_FT_FONT
    1.63 +     _cairo_ft_font_reset_static_data ();
    1.64 + #endif
    1.65 + 
    1.66 ++#if CAIRO_HAS_WIN32_FONT
    1.67 ++    _cairo_win32_font_reset_static_data ();
    1.68 ++#endif
    1.69 ++
    1.70 +     _cairo_intern_string_reset_static_data ();
    1.71 + 
    1.72 +     _cairo_scaled_font_reset_static_data ();
    1.73 + 
    1.74 +     _cairo_pattern_reset_static_data ();
    1.75 + 
    1.76 +     _cairo_clip_reset_static_data ();
    1.77 + 
    1.78 +diff --git a/gfx/cairo/cairo/src/cairo-mutex-list-private.h b/gfx/cairo/cairo/src/cairo-mutex-list-private.h
    1.79 +--- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h
    1.80 ++++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h
    1.81 +@@ -46,16 +46,20 @@ CAIRO_MUTEX_DECLARE (_cairo_intern_strin
    1.82 + CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
    1.83 + CAIRO_MUTEX_DECLARE (_cairo_scaled_glyph_page_cache_mutex)
    1.84 + CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
    1.85 + 
    1.86 + #if CAIRO_HAS_FT_FONT
    1.87 + CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
    1.88 + #endif
    1.89 + 
    1.90 ++#if CAIRO_HAS_WIN32_FONT
    1.91 ++CAIRO_MUTEX_DECLARE (_cairo_win32_font_face_mutex)
    1.92 ++#endif
    1.93 ++
    1.94 + #if CAIRO_HAS_XLIB_SURFACE
    1.95 + CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
    1.96 + #endif
    1.97 + 
    1.98 + #if CAIRO_HAS_XCB_SURFACE
    1.99 + CAIRO_MUTEX_DECLARE (_cairo_xcb_connections_mutex)
   1.100 + #endif
   1.101 + 
   1.102 +diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c
   1.103 +--- a/gfx/cairo/cairo/src/cairo-win32-font.c
   1.104 ++++ b/gfx/cairo/cairo/src/cairo-win32-font.c
   1.105 +@@ -42,16 +42,18 @@
   1.106 + # define _WIN32_WINNT 0x0500
   1.107 + #endif
   1.108 + 
   1.109 + #include "cairoint.h"
   1.110 + 
   1.111 + #include "cairo-win32-private.h"
   1.112 + #include "cairo-error-private.h"
   1.113 + 
   1.114 ++#include <wchar.h>
   1.115 ++
   1.116 + #ifndef SPI_GETFONTSMOOTHINGTYPE
   1.117 + #define SPI_GETFONTSMOOTHINGTYPE 0x200a
   1.118 + #endif
   1.119 + #ifndef FE_FONTSMOOTHINGCLEARTYPE
   1.120 + #define FE_FONTSMOOTHINGCLEARTYPE 2
   1.121 + #endif
   1.122 + #ifndef CLEARTYPE_QUALITY
   1.123 + #define CLEARTYPE_QUALITY 5
   1.124 +@@ -1887,19 +1889,17 @@ struct _cairo_win32_font_face {
   1.125 +     cairo_font_face_t base;
   1.126 +     LOGFONTW logfont;
   1.127 +     HFONT hfont;
   1.128 + };
   1.129 + 
   1.130 + /* implement the platform-specific interface */
   1.131 + 
   1.132 + static void
   1.133 +-_cairo_win32_font_face_destroy (void *abstract_face)
   1.134 +-{
   1.135 +-}
   1.136 ++_cairo_win32_font_face_destroy (void *abstract_face);
   1.137 + 
   1.138 + static cairo_bool_t
   1.139 + _is_scale (const cairo_matrix_t *matrix, double scale)
   1.140 + {
   1.141 +     return matrix->xx == scale && matrix->yy == scale &&
   1.142 +            matrix->xy == 0. && matrix->yx == 0. &&
   1.143 +            matrix->x0 == 0. && matrix->y0 == 0.;
   1.144 + }
   1.145 +@@ -1932,16 +1932,128 @@ static cairo_status_t
   1.146 + 
   1.147 + const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
   1.148 +     CAIRO_FONT_TYPE_WIN32,
   1.149 +     _cairo_win32_font_face_create_for_toy,
   1.150 +     _cairo_win32_font_face_destroy,
   1.151 +     _cairo_win32_font_face_scaled_font_create
   1.152 + };
   1.153 + 
   1.154 ++/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
   1.155 ++ * The primary purpose of this mapping is to provide unique
   1.156 ++ * #cairo_font_face_t values so that our cache and mapping from
   1.157 ++ * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
   1.158 ++ * corresponding #cairo_font_face_t objects fall out of downstream
   1.159 ++ * caches, we don't need them in this hash table anymore.
   1.160 ++ *
   1.161 ++ * Modifications to this hash table are protected by
   1.162 ++ * _cairo_win32_font_face_mutex.
   1.163 ++ */
   1.164 ++
   1.165 ++static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
   1.166 ++
   1.167 ++static int
   1.168 ++_cairo_win32_font_face_keys_equal (const void *key_a,
   1.169 ++				   const void *key_b);
   1.170 ++
   1.171 ++static void
   1.172 ++_cairo_win32_font_face_hash_table_destroy (void)
   1.173 ++{
   1.174 ++    cairo_hash_table_t *hash_table;
   1.175 ++
   1.176 ++    /* We manually acquire the lock rather than calling
   1.177 ++     * _cairo_win32_font_face_hash_table_lock simply to avoid creating
   1.178 ++     * the table only to destroy it again. */
   1.179 ++    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
   1.180 ++    hash_table = cairo_win32_font_face_hash_table;
   1.181 ++    cairo_win32_font_face_hash_table = NULL;
   1.182 ++    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
   1.183 ++
   1.184 ++    if (hash_table != NULL)
   1.185 ++	_cairo_hash_table_destroy (hash_table);
   1.186 ++}
   1.187 ++
   1.188 ++static cairo_hash_table_t *
   1.189 ++_cairo_win32_font_face_hash_table_lock (void)
   1.190 ++{
   1.191 ++    CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
   1.192 ++
   1.193 ++    if (unlikely (cairo_win32_font_face_hash_table == NULL))
   1.194 ++    {
   1.195 ++	cairo_win32_font_face_hash_table =
   1.196 ++	_cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
   1.197 ++
   1.198 ++	if (unlikely (cairo_win32_font_face_hash_table == NULL)) {
   1.199 ++	    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
   1.200 ++	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
   1.201 ++	    return NULL;
   1.202 ++	}
   1.203 ++    }
   1.204 ++
   1.205 ++    return cairo_win32_font_face_hash_table;
   1.206 ++}
   1.207 ++
   1.208 ++static void
   1.209 ++_cairo_win32_font_face_hash_table_unlock (void)
   1.210 ++{
   1.211 ++    CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
   1.212 ++}
   1.213 ++
   1.214 ++static void
   1.215 ++_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
   1.216 ++				 LOGFONTW                *logfont,
   1.217 ++				 HFONT                    font)
   1.218 ++{
   1.219 ++    unsigned long hash = _CAIRO_HASH_INIT_VALUE;
   1.220 ++
   1.221 ++    key->logfont = *logfont;
   1.222 ++    key->hfont = font;
   1.223 ++
   1.224 ++    hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName));
   1.225 ++    hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight));
   1.226 ++    hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic));
   1.227 ++
   1.228 ++    key->base.hash_entry.hash = hash;
   1.229 ++}
   1.230 ++
   1.231 ++static int
   1.232 ++_cairo_win32_font_face_keys_equal (const void *key_a,
   1.233 ++				   const void *key_b)
   1.234 ++{
   1.235 ++    const cairo_win32_font_face_t *face_a = key_a;
   1.236 ++    const cairo_win32_font_face_t *face_b = key_b;
   1.237 ++
   1.238 ++    if (face_a->logfont.lfWeight         == face_b->logfont.lfWeight &&
   1.239 ++	face_a->logfont.lfItalic         == face_b->logfont.lfItalic &&
   1.240 ++	face_a->logfont.lfUnderline      == face_b->logfont.lfUnderline &&
   1.241 ++	face_a->logfont.lfStrikeOut      == face_b->logfont.lfStrikeOut &&
   1.242 ++	face_a->logfont.lfCharSet        == face_b->logfont.lfCharSet &&
   1.243 ++	face_a->logfont.lfOutPrecision   == face_b->logfont.lfOutPrecision &&
   1.244 ++	face_a->logfont.lfClipPrecision  == face_b->logfont.lfClipPrecision &&
   1.245 ++	face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily &&
   1.246 ++	(wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0))
   1.247 ++	return TRUE;
   1.248 ++    else
   1.249 ++	return FALSE;
   1.250 ++}
   1.251 ++
   1.252 ++static void
   1.253 ++_cairo_win32_font_face_destroy (void *abstract_face)
   1.254 ++{
   1.255 ++    cairo_hash_table_t *hash_table;
   1.256 ++    cairo_win32_font_face_t *font_face = abstract_face;
   1.257 ++
   1.258 ++    hash_table = _cairo_win32_font_face_hash_table_lock ();
   1.259 ++    if (unlikely (hash_table == NULL)) {
   1.260 ++        return;
   1.261 ++    }
   1.262 ++    _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
   1.263 ++    _cairo_win32_font_face_hash_table_unlock ();
   1.264 ++}
   1.265 ++
   1.266 + /**
   1.267 +  * cairo_win32_font_face_create_for_logfontw_hfont:
   1.268 +  * @logfont: A #LOGFONTW structure specifying the font to use.
   1.269 +  *   If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement
   1.270 +  *   fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
   1.271 +  *   lfEscapement must be zero.
   1.272 +  * @font: An #HFONT that can be used when the font matrix is a scale by
   1.273 +  *   -lfHeight and the CTM is identity.
   1.274 +@@ -1954,30 +2066,61 @@ const cairo_font_face_backend_t _cairo_w
   1.275 +  * and can be used with functions such as cairo_win32_scaled_font_select_font().
   1.276 +  *
   1.277 +  * Return value: a newly created #cairo_font_face_t. Free with
   1.278 +  *  cairo_font_face_destroy() when you are done using it.
   1.279 +  **/
   1.280 + cairo_font_face_t *
   1.281 + cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
   1.282 + {
   1.283 +-    cairo_win32_font_face_t *font_face;
   1.284 ++    cairo_win32_font_face_t *font_face, key;
   1.285 ++    cairo_hash_table_t *hash_table;
   1.286 ++    cairo_status_t status;
   1.287 + 
   1.288 ++    hash_table = _cairo_win32_font_face_hash_table_lock ();
   1.289 ++    if (unlikely (hash_table == NULL)) {
   1.290 ++        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
   1.291 ++	return (cairo_font_face_t *)&_cairo_font_face_nil;
   1.292 ++    }
   1.293 ++
   1.294 ++    _cairo_win32_font_face_init_key (&key, logfont, font);
   1.295 ++
   1.296 ++    /* Return existing unscaled font if it exists in the hash table. */
   1.297 ++    font_face = _cairo_hash_table_lookup (hash_table,
   1.298 ++					 &key.base.hash_entry);
   1.299 ++    if (font_face != NULL) {
   1.300 ++	cairo_font_face_reference (&font_face->base);
   1.301 ++	goto DONE;
   1.302 ++    }
   1.303 ++
   1.304 ++    /* Otherwise create it and insert into hash table. */
   1.305 +     font_face = malloc (sizeof (cairo_win32_font_face_t));
   1.306 +     if (!font_face) {
   1.307 +         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
   1.308 +-        return (cairo_font_face_t *)&_cairo_font_face_nil;
   1.309 ++	goto FAIL;
   1.310 +     }
   1.311 + 
   1.312 +-    font_face->logfont = *logfont;
   1.313 +-    font_face->hfont = font;
   1.314 +-
   1.315 ++    _cairo_win32_font_face_init_key (font_face, logfont, font);
   1.316 +     _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
   1.317 + 
   1.318 ++    assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
   1.319 ++    status = _cairo_hash_table_insert (hash_table,
   1.320 ++				       &font_face->base.hash_entry);
   1.321 ++    if (unlikely (status))
   1.322 ++	goto FAIL;
   1.323 ++
   1.324 ++DONE:
   1.325 ++    _cairo_win32_font_face_hash_table_unlock ();
   1.326 ++
   1.327 +     return &font_face->base;
   1.328 ++
   1.329 ++FAIL:
   1.330 ++    _cairo_win32_font_face_hash_table_unlock ();
   1.331 ++
   1.332 ++    return (cairo_font_face_t *)&_cairo_font_face_nil;
   1.333 + }
   1.334 + 
   1.335 + /**
   1.336 +  * cairo_win32_font_face_create_for_logfontw:
   1.337 +  * @logfont: A #LOGFONTW structure specifying the font to use.
   1.338 +  *   The lfHeight, lfWidth, lfOrientation and lfEscapement
   1.339 +  *   fields of this structure are ignored.
   1.340 +  *
   1.341 +@@ -2176,8 +2319,14 @@ cairo_win32_scaled_font_get_device_to_lo
   1.342 +     cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
   1.343 +     if (! _cairo_scaled_font_is_win32 (scaled_font)) {
   1.344 + 	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
   1.345 + 	cairo_matrix_init_identity (device_to_logical);
   1.346 + 	return;
   1.347 +     }
   1.348 +     *device_to_logical = win_font->device_to_logical;
   1.349 + }
   1.350 ++
   1.351 ++void
   1.352 ++_cairo_win32_font_reset_static_data (void)
   1.353 ++{
   1.354 ++    _cairo_win32_font_face_hash_table_destroy ();
   1.355 ++}
   1.356 +diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h
   1.357 +--- a/gfx/cairo/cairo/src/cairoint.h
   1.358 ++++ b/gfx/cairo/cairo/src/cairoint.h
   1.359 +@@ -403,16 +403,19 @@ cairo_private void
   1.360 + _cairo_reset_static_data (void);
   1.361 + 
   1.362 + cairo_private void
   1.363 + _cairo_toy_font_face_reset_static_data (void);
   1.364 + 
   1.365 + cairo_private void
   1.366 + _cairo_ft_font_reset_static_data (void);
   1.367 + 
   1.368 ++cairo_private void
   1.369 ++_cairo_win32_font_reset_static_data (void);
   1.370 ++
   1.371 + /* the font backend interface */
   1.372 + 
   1.373 + struct _cairo_unscaled_font_backend {
   1.374 +     void (*destroy)     	    (void		             *unscaled_font);
   1.375 + };
   1.376 + 
   1.377 + /* #cairo_toy_font_face_t - simple family/slant/weight font faces used for
   1.378 +  * the built-in font API

mercurial