[cairo-commit] src/cairo-image-compositor.c src/cairoint.h src/cairo-mutex-list-private.h src/cairo-scaled-font.c

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Mon Apr 30 09:03:55 PDT 2012


 src/cairo-image-compositor.c   |  313 +++++++++++++++++++++++++++--------------
 src/cairo-mutex-list-private.h |    1 
 src/cairo-scaled-font.c        |    2 
 src/cairoint.h                 |    4 
 4 files changed, 212 insertions(+), 108 deletions(-)

New commits:
commit af3c8abbce529b0928742cc219e5e8e21191eee7
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Apr 30 12:02:38 2012 -0400

    Revert "Use pixman glyphs"
    
    This was pushed accidentally - apologies.
    
    This reverts commit 752c3b69e008b7d219da8cc5c657cf995732d3b8.

diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 047fbb1..5a1ea4a 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -750,37 +750,187 @@ composite_tristrip (void			*_dst,
     return  CAIRO_STATUS_SUCCESS;
 }
 
-static pixman_glyph_cache_t *global_glyph_cache;
-
-static inline pixman_glyph_cache_t *
-get_glyph_cache (void)
+static cairo_int_status_t
+check_composite_glyphs (const cairo_composite_rectangles_t *extents,
+			cairo_scaled_font_t *scaled_font,
+			cairo_glyph_t *glyphs,
+			int *num_glyphs)
 {
-    if (!global_glyph_cache)
-	global_glyph_cache = pixman_glyph_cache_create ();
-
-    return global_glyph_cache;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-void
-_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
-				cairo_scaled_glyph_t *scaled_glyph)
+static cairo_int_status_t
+composite_one_glyph (void				*_dst,
+		     cairo_operator_t			 op,
+		     cairo_surface_t			*_src,
+		     int				 src_x,
+		     int				 src_y,
+		     int				 dst_x,
+		     int				 dst_y,
+		     cairo_composite_glyphs_info_t	 *info)
 {
-    CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
+    cairo_image_surface_t *glyph_surface;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_status_t status;
+    int x, y;
 
-    if (global_glyph_cache) {
-	pixman_glyph_cache_remove (
-	    global_glyph_cache, scaled_font, (void *)_cairo_scaled_glyph_index (scaled_glyph));
-    }
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    status = _cairo_scaled_glyph_lookup (info->font,
+					 info->glyphs[0].index,
+					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
+					 &scaled_glyph);
+
+    if (unlikely (status))
+	return status;
+
+    glyph_surface = scaled_glyph->surface;
+    if (glyph_surface->width == 0 || glyph_surface->height == 0)
+	return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+    /* round glyph locations to the nearest pixel */
+    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
+    x = _cairo_lround (info->glyphs[0].x -
+		       glyph_surface->base.device_transform.x0);
+    y = _cairo_lround (info->glyphs[0].y -
+		       glyph_surface->base.device_transform.y0);
+
+    pixman_image_composite32 (_pixman_operator (op),
+			      ((cairo_image_source_t *)_src)->pixman_image,
+			      glyph_surface->pixman_image,
+			      to_pixman_image (_dst),
+			      x + src_x,  y + src_y,
+			      0, 0,
+			      x - dst_x, y - dst_y,
+			      glyph_surface->width,
+			      glyph_surface->height);
 
-    CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
-check_composite_glyphs (const cairo_composite_rectangles_t *extents,
-			cairo_scaled_font_t *scaled_font,
-			cairo_glyph_t *glyphs,
-			int *num_glyphs)
+composite_glyphs_via_mask (void				*_dst,
+			   cairo_operator_t		 op,
+			   cairo_surface_t		*_src,
+			   int				 src_x,
+			   int				 src_y,
+			   int				 dst_x,
+			   int				 dst_y,
+			   cairo_composite_glyphs_info_t *info)
 {
+    cairo_scaled_glyph_t *glyph_cache[64];
+    cairo_bool_t component_alpha = FALSE;
+    uint8_t buf[2048];
+    pixman_image_t *mask;
+    cairo_status_t status;
+    int i;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    /* XXX convert the glyphs to common formats a8/a8r8g8b8 to hit
+     * optimised paths through pixman. Should we increase the bit
+     * depth of the target surface, we should reconsider the appropriate
+     * mask formats.
+     */
+    i = (info->extents.width + 3) & ~3;
+    if (i * info->extents.height > (int) sizeof (buf)) {
+	mask = pixman_image_create_bits (PIXMAN_a8,
+					info->extents.width,
+					info->extents.height,
+					NULL, 0);
+    } else {
+	memset (buf, 0, i * info->extents.height);
+	mask = pixman_image_create_bits (PIXMAN_a8,
+					info->extents.width,
+					info->extents.height,
+					(uint32_t *)buf, i);
+    }
+    if (unlikely (mask == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    memset (glyph_cache, 0, sizeof (glyph_cache));
+    status = CAIRO_STATUS_SUCCESS;
+
+    for (i = 0; i < info->num_glyphs; i++) {
+	cairo_image_surface_t *glyph_surface;
+	cairo_scaled_glyph_t *scaled_glyph;
+	unsigned long glyph_index = info->glyphs[i].index;
+	int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
+	int x, y;
+
+	scaled_glyph = glyph_cache[cache_index];
+	if (scaled_glyph == NULL ||
+	    _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
+	{
+	    status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
+						 CAIRO_SCALED_GLYPH_INFO_SURFACE,
+						 &scaled_glyph);
+
+	    if (unlikely (status)) {
+		pixman_image_unref (mask);
+		return status;
+	    }
+
+	    glyph_cache[cache_index] = scaled_glyph;
+	}
+
+	glyph_surface = scaled_glyph->surface;
+	if (glyph_surface->width && glyph_surface->height) {
+	    if (glyph_surface->base.content & CAIRO_CONTENT_COLOR &&
+		! component_alpha) {
+		pixman_image_t *ca_mask;
+
+		ca_mask = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+						    info->extents.width,
+						    info->extents.height,
+						    NULL, 0);
+		if (unlikely (ca_mask == NULL)) {
+		    pixman_image_unref (mask);
+		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		}
+
+		pixman_image_composite32 (PIXMAN_OP_SRC,
+					  mask, 0, ca_mask,
+					  0, 0,
+					  0, 0,
+					  0, 0,
+					  info->extents.width,
+					  info->extents.height);
+		pixman_image_unref (mask);
+		mask = ca_mask;
+		component_alpha = TRUE;
+	    }
+
+	    /* round glyph locations to the nearest pixel */
+	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
+	    x = _cairo_lround (info->glyphs[i].x -
+			       glyph_surface->base.device_transform.x0);
+	    y = _cairo_lround (info->glyphs[i].y -
+			       glyph_surface->base.device_transform.y0);
+
+	    pixman_image_composite32 (PIXMAN_OP_ADD,
+				      glyph_surface->pixman_image, NULL, mask,
+                                      0, 0,
+				      0, 0,
+                                      x - info->extents.x, y - info->extents.y,
+				      glyph_surface->width,
+				      glyph_surface->height);
+	}
+    }
+
+    if (component_alpha)
+	pixman_image_set_component_alpha (mask, TRUE);
+
+    pixman_image_composite32 (_pixman_operator (op),
+			      ((cairo_image_source_t *)_src)->pixman_image,
+			      mask,
+			      to_pixman_image (_dst),
+			      info->extents.x + src_x, info->extents.y + src_y,
+			      0, 0,
+			      info->extents.x - dst_x, info->extents.y - dst_y,
+			      info->extents.width, info->extents.height);
+    pixman_image_unref (mask);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -794,104 +944,65 @@ composite_glyphs (void				*_dst,
 		  int				 dst_y,
 		  cairo_composite_glyphs_info_t *info)
 {
+    cairo_scaled_glyph_t *glyph_cache[64];
+    pixman_image_t *dst, *src;
     cairo_status_t status;
-    pixman_glyph_cache_t *glyph_cache;
-    pixman_glyph_t pglyphs_stack[CAIRO_STACK_ARRAY_LENGTH (pixman_glyph_t)];
-    pixman_glyph_t *pglyphs = pglyphs_stack;
-    pixman_format_code_t mask_format = 0;
-    pixman_glyph_t *pg;
     int i;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
 
-    CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
+    if (info->num_glyphs == 1)
+	return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
 
-    glyph_cache = get_glyph_cache();
+    if (info->use_mask)
+	return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
 
-    if (unlikely (!glyph_cache)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto out_no_glyph_cache;
-    }
+    op = _pixman_operator (op);
+    dst = to_pixman_image (_dst);
+    src = ((cairo_image_source_t *)_src)->pixman_image;
 
-    pixman_glyph_cache_freeze (glyph_cache);
-    
-    if (info->num_glyphs > ARRAY_LENGTH (pglyphs_stack)) {
-	pglyphs = _cairo_malloc_ab (info->num_glyphs, sizeof (pixman_glyph_t));
+    memset (glyph_cache, 0, sizeof (glyph_cache));
+    status = CAIRO_STATUS_SUCCESS;
 
-	if (unlikely (!pglyphs)) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto out;
-	}
-    }
-	
-    if (unlikely (!glyph_cache))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    pg = pglyphs;
     for (i = 0; i < info->num_glyphs; i++) {
-	unsigned long index = info->glyphs[i].index;
-	const void *glyph;
-
-	glyph = pixman_glyph_cache_contains (glyph_cache, info->font, (void *)index);
-	if (!glyph || !mask_format) {
-	    cairo_scaled_glyph_t *scaled_glyph;
-	    cairo_image_surface_t *glyph_surface;
-
-	    status = _cairo_scaled_glyph_lookup (info->font, index,
+	int x, y;
+	cairo_image_surface_t *glyph_surface;
+	cairo_scaled_glyph_t *scaled_glyph;
+	unsigned long glyph_index = info->glyphs[i].index;
+	int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
+
+	scaled_glyph = glyph_cache[cache_index];
+	if (scaled_glyph == NULL ||
+	    _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
+	{
+	    status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
 						 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 						 &scaled_glyph);
+
 	    if (unlikely (status))
-		goto out;
-
-	    glyph_surface = scaled_glyph->surface;
-
-	    if (!glyph) {
-		glyph = pixman_glyph_cache_insert (glyph_cache, info->font, (void *)index,
-						   glyph_surface->base.device_transform.x0,
-						   glyph_surface->base.device_transform.y0,
-						   glyph_surface->pixman_image);
-		if (unlikely (!glyph)) {
-		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-		    
-		    goto out;
-		}
-	    }
+		break;
 
-	    if (!mask_format)
-		mask_format = pixman_image_get_format (glyph_surface->pixman_image);
+	    glyph_cache[cache_index] = scaled_glyph;
 	}
-		
-	pg->x = info->glyphs[i].x;
-	pg->y = info->glyphs[i].y;
-	pg->glyph = glyph;
-	pg++;
-    }
 
-    if (info->use_mask)
-    {
-	pixman_composite_glyphs (_pixman_operator (op),
-				 ((cairo_image_source_t *)_src)->pixman_image,
-				 to_pixman_image (_dst),
-				 mask_format,
-				 src_x, src_y,
-				 dst_x, dst_y,
-				 glyph_cache, pg - pglyphs, pglyphs);
-    }
-    else
-    {
-	pixman_composite_glyphs_no_mask (_pixman_operator (op),
-					 ((cairo_image_source_t *)_src)->pixman_image,
-					 to_pixman_image (_dst),
-					 src_x, src_y,
-					 dst_x, dst_y,
-					 glyph_cache, pg - pglyphs, pglyphs);
+	glyph_surface = scaled_glyph->surface;
+	if (glyph_surface->width && glyph_surface->height) {
+	    /* round glyph locations to the nearest pixel */
+	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
+	    x = _cairo_lround (info->glyphs[i].x -
+			       glyph_surface->base.device_transform.x0);
+	    y = _cairo_lround (info->glyphs[i].y -
+			       glyph_surface->base.device_transform.y0);
+
+	    pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
+                                      x + src_x,  y + src_y,
+                                      0, 0,
+                                      x - dst_x, y - dst_y,
+				      glyph_surface->width,
+				      glyph_surface->height);
+	}
     }
 
-out:
-    pixman_glyph_cache_freeze (glyph_cache);
-out_no_glyph_cache:
-    CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-    
     return status;
 }
 
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index f46afad..4016f8e 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -45,7 +45,6 @@ CAIRO_MUTEX_DECLARE (_cairo_intern_string_mutex)
 CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
 CAIRO_MUTEX_DECLARE (_cairo_scaled_glyph_page_cache_mutex)
 CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
-CAIRO_MUTEX_DECLARE (_cairo_glyph_cache_mutex)
 
 #if CAIRO_HAS_FT_FONT
 CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 2a48978..59440b2 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -212,8 +212,6 @@ _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
 	private->destroy (private, scaled_glyph, scaled_font);
     }
 
-    _cairo_image_scaled_glyph_fini (scaled_font, scaled_glyph);
-    
     if (scaled_glyph->surface != NULL)
 	cairo_surface_destroy (&scaled_glyph->surface->base);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 22fd248..9f20d51 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1484,10 +1484,6 @@ _pixman_format_to_masks (pixman_format_code_t	 pixman_format,
 			 cairo_format_masks_t	*masks);
 
 cairo_private void
-_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
-				cairo_scaled_glyph_t *scaled_glyph);
-
-cairo_private void
 _cairo_image_reset_static_data (void);
 
 cairo_private cairo_surface_t *


More information about the cairo-commit mailing list