[cairo-commit] Branch '1.8' - 4 commits - AUTHORS src/cairo-ft-font.c test/cairo-test.c test/get-path-extents.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Jun 2 23:24:17 PDT 2009


 AUTHORS                 |    2 +-
 src/cairo-ft-font.c     |   42 ++++++++++++++++++++++++++++++++----------
 test/cairo-test.c       |   42 +++++++++++++++++++++---------------------
 test/get-path-extents.c |    8 ++++----
 4 files changed, 58 insertions(+), 36 deletions(-)

New commits:
commit c8f4b2fe80583de939613cc4d118a0b5920cb7ae
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Thu May 14 11:46:29 2009 +0100

    [ft] Resolve mutual referencing problems with zombie faces
    
    Bug 21706 -- zombie ft_font_face / ft_unscaled_font mutual
                 referencing problems
    [http://bugs.freedesktop.org/show_bug.cgi?id=21706]
    
    There can be more than one zombie font_face belonging to an unscaled_font,
    but only the first is destroyed.  This leaks the client's FT_Face
    (and associated font data) as release of the FT_Face depends on release
    of the font_face.
    
    (The reason why Firefox ends up with two different font_faces for one
    unscaled_font is that load_flags for faces with artificial oblique have
    FT_LOAD_NO_BITMAP set.
    https://bugzilla.mozilla.org/show_bug.cgi?id=486974)
    
    Also it's possible for _cairo_ft_font_face_create to pull out a zombie
    font_face from the unscaled_font, which would crash
    _cairo_ft_font_face_scaled_font_create, as that expects non-null
    font_face->unscaled (if !font-face->pattern).

diff --git a/AUTHORS b/AUTHORS
index 289fecb..8c06174 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -86,7 +86,7 @@ Travis Spencer <tspencer at cs.pdx.edu> XCB backend fix
 Bill Spitzak <spitzak at d2.com> Build fix to find Xrender.h without xrender.pc
 Zhe Su <james.su at gmail.com> Add support for fontconfig's embeddedbitmap option
 Owen Taylor <otaylor at redhat.com> Font rewrite, documentation, win32 backend
-Karl Tomlinson <karlt+ at karlt.net>
+Karl Tomlinson <karlt+ at karlt.net> Optimisation and obscure bug fixes (mozilla)
 Alp Toker <alp at atoker.com> Fix several code/comment typos
 Malcolm Tredinnick <malcolm at commsecure.com.au> Documentation fixes
 David Turner <david at freetype.org> Optimize gradient calculations
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 22206bb..19bfe46 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -511,8 +511,10 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
 	/* See comments in _ft_font_face_destroy about the "zombie" state
 	 * for a _ft_font_face.
 	 */
-	if (unscaled->faces && !unscaled->faces->unscaled)
+	if (unscaled->faces && unscaled->faces->unscaled == NULL) {
+	    assert (unscaled->faces->next == NULL);
 	    cairo_font_face_destroy (&unscaled->faces->base);
+	}
     } else {
 	_font_map_release_face_lock_held (font_map, unscaled);
     }
@@ -2235,9 +2237,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
     if (font_face == NULL)
 	return;
 
-    /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
+    /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
      * we have a special "zombie" state for the face when the unscaled font
-     * is still alive but there are no public references to the font face.
+     * is still alive but there are no other references to a font face with
+     * the same FT_Face.
      *
      * We go from:
      *
@@ -2251,6 +2254,8 @@ _cairo_ft_font_face_destroy (void *abstract_face)
 
     if (font_face->unscaled &&
 	font_face->unscaled->from_face &&
+	font_face->next == NULL &&
+	font_face->unscaled->faces == font_face &&
 	CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
     {
 	cairo_font_face_reference (&font_face->base);
@@ -2337,12 +2342,21 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 	    font_face->ft_options.extra_flags == ft_options->extra_flags &&
 	    cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
 	{
-	    if (font_face->base.status == CAIRO_STATUS_SUCCESS)
-		return cairo_font_face_reference (&font_face->base);
+	    if (font_face->base.status) {
+		/* The font_face has been left in an error state, abandon it. */
+		*prev_font_face = font_face->next;
+		break;
+	    }
 
-	    /* The font_face has been left in an error state, abandon it. */
-	    *prev_font_face = font_face->next;
-	    break;
+	    if (font_face->unscaled == NULL) {
+		/* Resurrect this "zombie" font_face (from
+		 * _cairo_ft_font_face_destroy), switching its unscaled_font
+		 * from owner to ownee. */
+		font_face->unscaled = unscaled;
+		_cairo_unscaled_font_reference (&unscaled->base);
+		return &font_face->base;
+	    } else
+		return cairo_font_face_reference (&font_face->base);
 	}
     }
 
@@ -2358,6 +2372,14 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 
     font_face->ft_options = *ft_options;
 
+    if (unscaled->faces && unscaled->faces->unscaled == NULL) {
+	/* This "zombie" font_face (from _cairo_ft_font_face_destroy)
+	 * is no longer needed. */
+	assert (unscaled->from_face && unscaled->faces->next == NULL);
+	cairo_font_face_destroy (&unscaled->faces->base);
+	unscaled->faces = NULL;
+    }
+
     font_face->next = unscaled->faces;
     unscaled->faces = font_face;
 
commit 634298af1326a39452c9432a2d9a8fd98c9c2d19
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat May 30 23:03:55 2009 -0400

    [ft] Fix vertical advance metrics of bitmap fonts (#21985)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 3675db6..22206bb 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1993,7 +1993,7 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
 	    FT_Pos x1, x2;
 	    FT_Pos y1, y2;
 	    FT_Pos advance;
-	    
+
 	    if (!vertical_layout) {
 		x1 = (metrics->horiBearingX) & -64;
 		x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
@@ -2048,7 +2048,7 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
 		if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
 		    fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
 		else
-		    fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
+		    fs_metrics.y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor;
 	    }
 	 }
 
commit 5c63efe5fd182212c3f382bbdc0179c9e99e636d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 8 17:36:01 2009 +0100

    [test] Relax APPROX_EQUALS condition
    
    The bounding box of the text is rounded to the nearest pixel boundaries,
    so therefore the test must accept a similar level of imprecision.

diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 5bfdcd7..7a959c8 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -79,10 +79,10 @@ check_extents (const cairo_test_context_t *ctx,
         break;
     case APPROX_EQUALS:
         relation_string = "approx. equal";
-        if (floor (ext_x1 + 0.5) == floor (x + 0.5) &&
-	    floor (ext_y1 + 0.5) == floor (y + 0.5) &&
-	    floor (ext_x2 + 0.5) == floor (x + width + 0.5) &&
-	    floor (ext_y2 + 0.5) == floor (y + height + 0.5))
+        if (fabs (ext_x1 - x) < 1. &&
+	    fabs (ext_y1 - y) < 1. &&
+	    fabs (ext_x2 - (x + width))  < 1. &&
+	    fabs (ext_y2 - (y + height)) < 1.)
 	{
             return 1;
 	}
commit 130ac1f9453b5e746576fc4887d7e1372c1605b1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 3 07:06:42 2009 +0100

    [test] Sync with memfault headers.
    
    Update the macros to reflect the current version of memfault.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 12fc3ad..61ea63d 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -128,7 +128,7 @@ _cairo_test_init (cairo_test_context_t *ctx,
 {
     char *log_name;
 
-    MF (VALGRIND_DISABLE_FAULTS ());
+    MF (MEMFAULT_DISABLE_FAULTS ());
 
 #if HAVE_FEENABLEEXCEPT
     feenableexcept (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
@@ -191,7 +191,7 @@ cairo_test_init_thread (cairo_test_context_t *ctx,
 			cairo_test_context_t *master,
 			int thread)
 {
-    MF (VALGRIND_DISABLE_FAULTS ());
+    MF (MEMFAULT_DISABLE_FAULTS ());
 
     *ctx = *master;
     ctx->thread = thread;
@@ -631,11 +631,11 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 
 REPEAT:
 #if HAVE_MEMFAULT
-    VALGRIND_CLEAR_FAULTS ();
-    VALGRIND_RESET_LEAKS ();
+    MEMFAULT_CLEAR_FAULTS ();
+    MEMFAULT_RESET_LEAKS ();
     ctx->last_fault_count = 0;
-    last_fault_count = VALGRIND_COUNT_FAULTS ();
-    VALGRIND_ENABLE_FAULTS ();
+    last_fault_count = MEMFAULT_COUNT_FAULTS ();
+    MEMFAULT_ENABLE_FAULTS ();
 #endif
     have_output = FALSE;
     have_result = FALSE;
@@ -660,7 +660,7 @@ REPEAT:
 	goto REPEAT;
 
     if (cairo_surface_status (surface)) {
-	MF (VALGRIND_PRINT_FAULTS ());
+	MF (MEMFAULT_PRINT_FAULTS ());
 	cairo_test_log (ctx, "Error: Created an error surface\n");
 	ret = CAIRO_TEST_FAILURE;
 	goto UNWIND_STRINGS;
@@ -668,7 +668,7 @@ REPEAT:
 
     /* Check that we created a surface of the expected type. */
     if (cairo_surface_get_type (surface) != target->expected_type) {
-	MF (VALGRIND_PRINT_FAULTS ());
+	MF (MEMFAULT_PRINT_FAULTS ());
 	cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n",
 			cairo_surface_get_type (surface), target->expected_type);
 	ret = CAIRO_TEST_FAILURE;
@@ -681,7 +681,7 @@ REPEAT:
     expected_content = cairo_boilerplate_content (target->content);
 
     if (cairo_surface_get_content (surface) != expected_content) {
-	MF (VALGRIND_PRINT_FAULTS ());
+	MF (MEMFAULT_PRINT_FAULTS ());
 	cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n",
 			cairo_surface_get_content (surface), expected_content);
 	ret = CAIRO_TEST_FAILURE;
@@ -736,11 +736,11 @@ REPEAT:
     }
 
 #if HAVE_MEMFAULT
-    VALGRIND_DISABLE_FAULTS ();
+    MEMFAULT_DISABLE_FAULTS ();
 
     /* repeat test after malloc failure injection */
     if (ctx->malloc_failure &&
-	VALGRIND_COUNT_FAULTS () - last_fault_count > 0 &&
+	MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
 	(status == CAIRO_TEST_NO_MEMORY ||
 	 cairo_status (cr) == CAIRO_STATUS_NO_MEMORY ||
 	 cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY))
@@ -754,9 +754,9 @@ REPEAT:
 #if HAVE_FCFINI
 	    FcFini ();
 #endif
-	    if (VALGRIND_COUNT_LEAKS () > 0) {
-		VALGRIND_PRINT_FAULTS ();
-		VALGRIND_PRINT_LEAKS ();
+	    if (MEMFAULT_COUNT_LEAKS () > 0) {
+		MEMFAULT_PRINT_FAULTS ();
+		MEMFAULT_PRINT_LEAKS ();
 	    }
 	}
 
@@ -779,9 +779,9 @@ REPEAT:
     }
 
 #if HAVE_MEMFAULT
-    if (VALGRIND_COUNT_FAULTS () - last_fault_count > 0) {
+    if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0) {
 	VALGRIND_PRINTF ("Unreported memfaults...");
-	VALGRIND_PRINT_FAULTS ();
+	MEMFAULT_PRINT_FAULTS ();
     }
 #endif
 
@@ -983,7 +983,7 @@ UNWIND_CAIRO:
 
 #if HAVE_MEMFAULT
     if (ret == CAIRO_TEST_FAILURE && ctx->expectation != CAIRO_TEST_FAILURE)
-	VALGRIND_PRINT_FAULTS ();
+	MEMFAULT_PRINT_FAULTS ();
 #endif
     cairo_destroy (cr);
 UNWIND_SURFACE:
@@ -1000,13 +1000,13 @@ UNWIND_SURFACE:
 	FcFini ();
 #endif
 
-	if (VALGRIND_COUNT_LEAKS () > 0) {
+	if (MEMFAULT_COUNT_LEAKS () > 0) {
 	    if (ret != CAIRO_TEST_FAILURE ||
 		ctx->expectation == CAIRO_TEST_FAILURE)
 	    {
-		VALGRIND_PRINT_FAULTS ();
+		MEMFAULT_PRINT_FAULTS ();
 	    }
-	    VALGRIND_PRINT_LEAKS ();
+	    MEMFAULT_PRINT_LEAKS ();
 	}
     }
 
@@ -1481,7 +1481,7 @@ cairo_test_malloc_failure (const cairo_test_context_t *ctx,
 
 #if HAVE_MEMFAULT
     /* prevent infinite loops... */
-    n_faults = VALGRIND_COUNT_FAULTS ();
+    n_faults = MEMFAULT_COUNT_FAULTS ();
     if (n_faults == ctx->last_fault_count)
 	return FALSE;
 


More information about the cairo-commit mailing list