[cairo-commit] 2 commits - perf/cairo-perf.c perf/cairo-perf.h perf/Makefile.am perf/twin.c src/cairo-font-face.c src/cairo-ft-font.c src/cairoint.h src/cairo-quartz-font.c src/cairo-scaled-font.c src/cairo-user-font.c src/cairo-win32-font.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Oct 22 08:39:16 PDT 2008


 perf/Makefile.am        |    3 +-
 perf/cairo-perf.c       |    1 
 perf/cairo-perf.h       |    1 
 perf/twin.c             |   50 +++++++++++++++++++++++++++++++++++++++++++
 src/cairo-font-face.c   |   34 +++++++++++++++++++++++++++++
 src/cairo-ft-font.c     |    2 +
 src/cairo-quartz-font.c |   55 ++++++++++++++++++++++++++++++++++++++----------
 src/cairo-scaled-font.c |   11 ++++++++-
 src/cairo-user-font.c   |   37 ++++++++++++++++++++++++--------
 src/cairo-win32-font.c  |    2 +
 src/cairoint.h          |    8 ++++++
 11 files changed, 182 insertions(+), 22 deletions(-)

New commits:
commit 09651a1c1a4856607423e9b06c1f7c397ba4f304
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 8 22:39:48 2008 +0100

    Twin perf case

diff --git a/perf/Makefile.am b/perf/Makefile.am
index 512e6d1..daec8e4 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -34,8 +34,9 @@ cairo_perf_SOURCES =		\
 	stroke.c		\
 	subimage_copy.c		\
 	tessellate.c		\
-	unaligned-clip.c	\
 	text.c			\
+	twin.c			\
+	unaligned-clip.c	\
 	world-map.c		\
 	world-map.h		\
 	zrusin.c		\
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 613d15c..a6d59a5 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -458,5 +458,6 @@ const cairo_perf_case_t perf_cases[] = {
     { rounded_rectangles, 512, 512},
     { long_dashed_lines, 512, 512},
     { composite_checker, 16, 512},
+    { twin, 800, 800},
     { NULL }
 };
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 57fe85f..0cedb69 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -172,5 +172,6 @@ CAIRO_PERF_DECL (rectangles);
 CAIRO_PERF_DECL (rounded_rectangles);
 CAIRO_PERF_DECL (long_dashed_lines);
 CAIRO_PERF_DECL (composite_checker);
+CAIRO_PERF_DECL (twin);
 
 #endif
diff --git a/perf/twin.c b/perf/twin.c
new file mode 100644
index 0000000..d81c2af
--- /dev/null
+++ b/perf/twin.c
@@ -0,0 +1,50 @@
+#define WIDTH 1350
+#define HEIGHT 900
+
+#include "cairo-perf.h"
+
+static cairo_perf_ticks_t
+do_twin (cairo_t *cr,
+	 int width,
+	 int height)
+{
+    int i, j, h;
+    unsigned char s[2] = {0, 0};
+
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+    cairo_set_source_rgb (cr, 0, 0, 0);
+
+    cairo_perf_timer_start ();
+
+    cairo_select_font_face (cr,
+			    "cairo",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    h = 2;
+    for (i = 8; i < 48; i >= 24 ? i+=3 : i++) {
+	cairo_set_font_size (cr, i);
+	for (j = 33; j < 128; j++) {
+	    if (j == 33 || (j == 80 && i > 24)) {
+		h += i + 2;
+		cairo_move_to (cr, 10, h);
+	    }
+	    s[0] = j;
+	    cairo_text_path (cr, (const char *) s);
+	}
+    }
+    cairo_fill (cr);
+
+    cairo_perf_timer_stop ();
+    return cairo_perf_timer_elapsed ();
+}
+
+void
+twin (cairo_perf_t *perf,
+      cairo_t      *cr,
+      int           width,
+      int           height)
+{
+    cairo_perf_run (perf, "twin", do_twin);
+}
commit 954ebacb71071c53c4e4092b469417f01478bc2d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 22 15:43:56 2008 +0100

    Map toy font face to implementation.
    
    Quartz fonts and user fonts use an indirect font face when creating a
    scaled font for the toy font face. This means that they insert a scaled
    font into the font map that has a different font face to the one that is
    initially searched upon. The result is that when we try to create an
    identical scaled font, we fail to find the existing scaled font and
    attempt to insert a duplicate into the hash table - which triggers an
    assert.
    
    In order to avoid creating duplicate fonts, we add a new method to the
    font backends that allows cairo_scaled_font_create() to peek at the
    font_face that will be used to actually implement the scaled font
    constructor - thus we are able to use the correct font_face as part of the
    hash key.

diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index a260378..6cea395 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -569,6 +569,39 @@ _cairo_toy_font_face_destroy (void *abstract_face)
 }
 
 static cairo_status_t
+_cairo_toy_font_face_scaled_font_get_implementation (void                *abstract_font_face,
+						     cairo_font_face_t **font_face_out)
+{
+    cairo_toy_font_face_t *font_face = abstract_font_face;
+    cairo_status_t status;
+
+    if (font_face->base.status)
+	return font_face->base.status;
+
+    if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend &&
+	0 != strcmp (font_face->family, CAIRO_USER_FONT_FAMILY_DEFAULT))
+    {
+	const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
+
+	if (backend->get_implementation == NULL) {
+	    *font_face_out = &font_face->base;
+	    return CAIRO_STATUS_SUCCESS;
+	}
+
+	status = backend->get_implementation (font_face,
+					      font_face_out);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return _cairo_font_face_set_error (&font_face->base, status);
+    }
+
+    status = _cairo_user_scaled_font_backend.get_implementation (font_face,
+								 font_face_out);
+
+    return _cairo_font_face_set_error (&font_face->base, status);
+}
+
+static cairo_status_t
 _cairo_toy_font_face_scaled_font_create (void                *abstract_font_face,
 					 const cairo_matrix_t       *font_matrix,
 					 const cairo_matrix_t       *ctm,
@@ -689,6 +722,7 @@ slim_hidden_def (cairo_toy_font_face_get_weight);
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
     CAIRO_FONT_TYPE_TOY,
     _cairo_toy_font_face_destroy,
+    _cairo_toy_font_face_scaled_font_get_implementation,
     _cairo_toy_font_face_scaled_font_create
 };
 
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 7075b5d..cd11253 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2211,6 +2211,7 @@ _cairo_ft_index_to_ucs4(void	        *abstract_font,
 
 const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
+    NULL,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
@@ -2317,6 +2318,7 @@ _cairo_ft_font_face_scaled_font_create (void                     *abstract_face,
 static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_font_face_destroy,
+    NULL, /* direct implementation */
     _cairo_ft_font_face_scaled_font_create
 };
 
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index c689800..2bca372 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -225,6 +225,7 @@ FINISH:
 static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
     CAIRO_FONT_TYPE_QUARTZ,
     _cairo_quartz_font_face_destroy,
+    NULL, /* direct implementation */
     _cairo_quartz_font_face_scaled_font_create
 };
 
@@ -277,24 +278,27 @@ _cairo_quartz_scaled_to_face (void *abstract_font)
 }
 
 static cairo_status_t
-_cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
-			      const cairo_matrix_t *font_matrix,
-			      const cairo_matrix_t *ctm,
-			      const cairo_font_options_t *options,
-			      cairo_scaled_font_t **font_out)
+_cairo_quartz_font_get_implementation (cairo_toy_font_face_t *toy_face,
+				       cairo_scaled_font_t **font_face_out)
 {
+    static cairo_user_data_key_t impl_font_face_key;
+    cairo_font_face_t *face;
+    cairo_status_t status;
     const char *family = toy_face->family;
     char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
     CFStringRef cgFontName = NULL;
     CGFontRef cgFont = NULL;
     int loop;
 
-    cairo_status_t status;
-    cairo_font_face_t *face;
-    cairo_scaled_font_t *scaled_font;
+    face = cairo_font_face_get_user_data (&toy_face->base,
+					  &impl_font_face_key);
+    if (face) {
+	*font_face_out = face;
+	return CAIRO_STATUS_SUCCESS;
+    }
 
     quartz_font_ensure_symbols();
-    if (!_cairo_quartz_font_symbols_present)
+    if (! _cairo_quartz_font_symbols_present)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     /* handle CSS-ish faces */
@@ -345,7 +349,7 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
 
     if (!cgFont) {
 	/* Give up */
-	return CAIRO_STATUS_NO_MEMORY;
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
     face = cairo_quartz_font_face_create_for_cgfont (cgFont);
@@ -354,6 +358,35 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
     if (face->status)
 	return face->status;
 
+    status = cairo_font_face_set_user_data (&toy_face->base,
+					    &impl_font_face_key,
+					    face,
+					    (cairo_destroy_func_t) cairo_font_face_destroy);
+
+    if (status) {
+	cairo_font_face_destroy (face);
+	return status;
+    }
+
+    *font_face_out = face;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_quartz_font_create_toy (cairo_toy_font_face_t *toy_face,
+			       const cairo_matrix_t *font_matrix,
+			       const cairo_matrix_t *ctm,
+			       const cairo_font_options_t *options,
+			       cairo_scaled_font_t **font_out)
+{
+    cairo_font_face_t *face;
+    cairo_scaled_font_t *scaled_font;
+    cairo_status_t status;
+
+    status = _cairo_quartz_font_get_implementation (toy_face, &face);
+    if (status)
+	return status;
+
     status = _cairo_quartz_font_face_scaled_font_create (face,
 							 font_matrix, ctm,
 							 options,
@@ -363,7 +396,6 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
 	return status;
 
     *font_out = scaled_font;
-
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -743,6 +775,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
 
 const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
     CAIRO_FONT_TYPE_QUARTZ,
+    _cairo_quartz_font_get_implementation,
     _cairo_quartz_font_create_toy,
     _cairo_quartz_font_fini,
     _cairo_quartz_font_scaled_glyph_init,
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index d312a4c..3ec07d5 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -772,6 +772,7 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 			  const cairo_font_options_t *options)
 {
     cairo_status_t status;
+    cairo_font_face_t *impl_face;
     cairo_scaled_font_map_t *font_map;
     cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
 
@@ -785,11 +786,19 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
     /* Note that degenerate ctm or font_matrix *are* allowed.
      * We want to support a font size of 0. */
 
+    if (font_face->backend->get_implementation != NULL) {
+	/* indirect implementation, lookup the face that is used for the key */
+	status = font_face->backend->get_implementation (font_face, &impl_face);
+	if (status)
+	    return _cairo_scaled_font_create_in_error (status);
+    } else
+	impl_face = font_face;
+
     font_map = _cairo_scaled_font_map_lock ();
     if (font_map == NULL)
 	return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    _cairo_scaled_font_init_key (&key, font_face,
+    _cairo_scaled_font_init_key (&key, impl_face,
 				 font_matrix, ctm, options);
     scaled_font = font_map->mru_scaled_font;
     if (scaled_font != NULL &&
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 385b841..ddcbc77 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -337,17 +337,14 @@ _cairo_user_font_face_scaled_font_create (void                        *abstract_
 					  cairo_scaled_font_t        **scaled_font);
 
 static cairo_status_t
-_cairo_user_scaled_font_create_toy (cairo_toy_font_face_t     *toy_face,
-				    const cairo_matrix_t      *font_matrix,
-				    const cairo_matrix_t      *ctm,
-				    const cairo_font_options_t *font_options,
-				    cairo_scaled_font_t	     **font)
+_cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face,
+					    cairo_font_face_t **font_face_out)
 {
-    cairo_status_t status;
-    cairo_font_face_t *face;
-
     static cairo_user_data_key_t twin_font_face_key;
 
+    cairo_font_face_t *face;
+    cairo_status_t status;
+
     face = cairo_font_face_get_user_data (&toy_face->base,
 					  &twin_font_face_key);
     if (!face) {
@@ -365,17 +362,38 @@ _cairo_user_scaled_font_create_toy (cairo_toy_font_face_t     *toy_face,
 	}
     }
 
+    *font_face_out = face;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_user_scaled_font_create_toy (cairo_toy_font_face_t     *toy_face,
+				    const cairo_matrix_t      *font_matrix,
+				    const cairo_matrix_t      *ctm,
+				    const cairo_font_options_t *font_options,
+				    cairo_scaled_font_t	     **font)
+{
+    cairo_font_face_t *face;
+    cairo_status_t status;
+
+    status = _cairo_user_scaled_font_get_implementation (toy_face, &face);
+    if (status)
+	return status;
+
     status = _cairo_user_font_face_scaled_font_create (face,
 						       font_matrix,
 						       ctm,
 						       font_options,
 						       font);
+    if (status)
+	return status;
 
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
     CAIRO_FONT_TYPE_USER,
+    _cairo_user_scaled_font_get_implementation,
     _cairo_user_scaled_font_create_toy,	/* create_toy */
     NULL,	/* scaled_font_fini */
     _cairo_user_scaled_glyph_init,
@@ -501,6 +519,7 @@ _cairo_user_font_face_scaled_font_create (void                        *abstract_
 static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
     CAIRO_FONT_TYPE_USER,
     NULL,	/* destroy */
+    NULL,       /* direct implementation */
     _cairo_user_font_face_scaled_font_create
 };
 
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index dc93758..7f6d435 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1835,6 +1835,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
 
 const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     CAIRO_FONT_TYPE_WIN32,
+    NULL,
     _cairo_win32_scaled_font_create_toy,
     _cairo_win32_scaled_font_fini,
     _cairo_win32_scaled_font_glyph_init,
@@ -1904,6 +1905,7 @@ _cairo_win32_font_face_scaled_font_create (void			*abstract_face,
 static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
     CAIRO_FONT_TYPE_WIN32,
     _cairo_win32_font_face_destroy,
+    NULL, /* direct implementation */
     _cairo_win32_font_face_scaled_font_create
 };
 
diff --git a/src/cairoint.h b/src/cairoint.h
index a60de51..a1d3f3d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -412,6 +412,10 @@ struct _cairo_scaled_font_backend {
     cairo_font_type_t type;
 
     cairo_warn cairo_status_t
+    (*get_implementation)  (cairo_toy_font_face_t	*toy_face,
+			    cairo_font_face_t	       **font_face);
+
+    cairo_warn cairo_status_t
     (*create_toy)  (cairo_toy_font_face_t	*toy_face,
 		    const cairo_matrix_t	*font_matrix,
 		    const cairo_matrix_t	*ctm,
@@ -484,6 +488,10 @@ struct _cairo_font_face_backend {
     (*destroy)     (void			*font_face);
 
     cairo_warn cairo_status_t
+    (*get_implementation)  (void			*font_face,
+			    cairo_font_face_t	       **font_face_out);
+
+    cairo_warn cairo_status_t
     (*scaled_font_create) (void				*font_face,
 			   const cairo_matrix_t		*font_matrix,
 			   const cairo_matrix_t		*ctm,


More information about the cairo-commit mailing list