[cairo-commit] 2 commits - configure.ac src/cairo-image-compositor.c src/skia

Chris Wilson ickle at kemper.freedesktop.org
Sun Aug 12 11:11:40 PDT 2012


 configure.ac                    |    7 
 src/cairo-image-compositor.c    |  285 ++++++++++++++++++++++++++++++++++++++++
 src/skia/cairo-skia-surface.cpp |   16 --
 3 files changed, 296 insertions(+), 12 deletions(-)

New commits:
commit 95b7f4fe3a5deea6766538d843c75626e4bb68cf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Aug 12 19:10:04 2012 +0100

    image: Temporarily resurrect the old non-pixman glyph compositor
    
    As the easiest approach to making another snapshot that only depends
    upon a stable pixman, make the new dependency a compile time option.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index a721cdf..0067bfc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -619,7 +619,7 @@ CAIRO_ENABLE(test_surfaces, test surfaces, no)
 dnl ===========================================================================
 
 CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
-  pixman_REQUIRES="pixman-1 >= 0.27.1"
+  pixman_REQUIRES="pixman-1 >= 0.26.0"
   PKG_CHECK_MODULES(pixman, $pixman_REQUIRES, , [AC_MSG_RESULT(no)
   use_image="no (requires $pixman_REQUIRES http://cairographics.org/releases/)"])
   image_REQUIRES=$pixman_REQUIRES
@@ -627,6 +627,11 @@ CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
   image_LIBS=$pixman_LIBS
 ])
 
+if pkg-config --exists 'pixman-1 >= 0.27.1'; then
+    AC_DEFINE([HAS_PIXMAN_GLYPHS], 1, [Enable pixman glyph cache])
+fi
+
+
 dnl ===========================================================================
 
 CAIRO_ENABLE_SURFACE_BACKEND(mime, mime, always)
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 14e982d..1ec9838 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -785,6 +785,7 @@ check_composite_glyphs (const cairo_composite_rectangles_t *extents,
     return CAIRO_STATUS_SUCCESS;
 }
 
+#if HAS_PIXMAN_GLYPHS
 static cairo_int_status_t
 composite_glyphs (void				*_dst,
 		  cairo_operator_t		 op,
@@ -894,6 +895,290 @@ out_unlock:
     CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
     return status;
 }
+#else
+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_image_surface_t *glyph_surface;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_status_t status;
+    int x, y;
+
+    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);
+
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+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];
+    pixman_image_t *white = _pixman_image_for_color (CAIRO_COLOR_WHITE);
+    cairo_scaled_glyph_t *scaled_glyph;
+    uint8_t buf[2048];
+    pixman_image_t *mask;
+    pixman_format_code_t format;
+    cairo_status_t status;
+    int i;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    if (unlikely (white == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    /* 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.
+     */
+
+    status = _cairo_scaled_glyph_lookup (info->font,
+					 info->glyphs[0].index,
+					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
+					 &scaled_glyph);
+    if (unlikely (status)) {
+	pixman_image_unref (white);
+	return status;
+    }
+
+    memset (glyph_cache, 0, sizeof (glyph_cache));
+    glyph_cache[info->glyphs[0].index % ARRAY_LENGTH (glyph_cache)] = scaled_glyph;
+
+    format = PIXMAN_a8;
+    i = (info->extents.width + 3) & ~3;
+    if (scaled_glyph->surface->base.content & CAIRO_CONTENT_COLOR) {
+	format = PIXMAN_a8r8g8b8;
+	i = info->extents.width * 4;
+    }
+
+    if (i * info->extents.height > (int) sizeof (buf)) {
+	mask = pixman_image_create_bits (format,
+					info->extents.width,
+					info->extents.height,
+					NULL, 0);
+    } else {
+	memset (buf, 0, i * info->extents.height);
+	mask = pixman_image_create_bits (format,
+					info->extents.width,
+					info->extents.height,
+					(uint32_t *)buf, i);
+    }
+    if (unlikely (mask == NULL)) {
+	pixman_image_unref (white);
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+
+    status = CAIRO_STATUS_SUCCESS;
+    for (i = 0; i < info->num_glyphs; i++) {
+	unsigned long glyph_index = info->glyphs[i].index;
+	int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
+	cairo_image_surface_t *glyph_surface;
+	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);
+		pixman_image_unref (white);
+		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 &&
+		format == PIXMAN_a8) {
+		pixman_image_t *ca_mask;
+
+		format = PIXMAN_a8r8g8b8;
+		ca_mask = pixman_image_create_bits (format,
+						    info->extents.width,
+						    info->extents.height,
+						    NULL, 0);
+		if (unlikely (ca_mask == NULL)) {
+		    pixman_image_unref (mask);
+		    pixman_image_unref (white);
+		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+		}
+
+		pixman_image_composite32 (PIXMAN_OP_SRC,
+					  white, mask, ca_mask,
+					  0, 0,
+					  0, 0,
+					  0, 0,
+					  info->extents.width,
+					  info->extents.height);
+		pixman_image_unref (mask);
+		mask = ca_mask;
+	    }
+
+	    /* 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);
+
+	    if (glyph_surface->pixman_format == format) {
+		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);
+	    } else {
+		pixman_image_composite32 (PIXMAN_OP_ADD,
+					  white, glyph_surface->pixman_image, mask,
+					  0, 0,
+					  0, 0,
+					  x - info->extents.x, y - info->extents.y,
+					  glyph_surface->width,
+					  glyph_surface->height);
+	    }
+	}
+    }
+
+    if (format == PIXMAN_a8r8g8b8)
+	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);
+    pixman_image_unref (white);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+composite_glyphs (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];
+    pixman_image_t *dst, *src;
+    cairo_status_t status;
+    int i;
+
+    TRACE ((stderr, "%s\n", __FUNCTION__));
+
+    if (info->num_glyphs == 1)
+	return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
+
+    if (info->use_mask)
+	return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
+
+    op = _pixman_operator (op);
+    dst = to_pixman_image (_dst);
+    src = ((cairo_image_source_t *)_src)->pixman_image;
+
+    memset (glyph_cache, 0, sizeof (glyph_cache));
+    status = CAIRO_STATUS_SUCCESS;
+
+    for (i = 0; i < info->num_glyphs; i++) {
+	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))
+		break;
+
+	    glyph_cache[cache_index] = scaled_glyph;
+	}
+
+	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);
+	}
+    }
+
+    return status;
+}
+#endif
 
 static cairo_int_status_t
 check_composite (const cairo_composite_rectangles_t *extents)
commit 16426dab486767cb16dfaf5158c5d4b3317546b0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Aug 12 16:12:47 2012 +0100

    skia: Compile fix for changes to map-to-image
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/skia/cairo-skia-surface.cpp b/src/skia/cairo-skia-surface.cpp
index cc76cfb..bb785e1 100644
--- a/src/skia/cairo-skia-surface.cpp
+++ b/src/skia/cairo-skia-surface.cpp
@@ -97,16 +97,7 @@ _cairo_skia_surface_map_to_image (void *asurface,
     cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
 
     surface->bitmap->lockPixels ();
-
-    /* XXX: Broken! */
-    if (extents->width < surface->image.width ||
-	extents->height < surface->image.height)
-    {
-	return _cairo_surface_create_for_rectangle_int (&surface->image.base,
-							extents);
-    }
-
-    return cairo_surface_reference (&surface->image.base);
+    return _cairo_image_surface_map_to_image (&surface->image, extents);
 }
 
 static cairo_int_status_t
@@ -114,9 +105,12 @@ _cairo_skia_surface_unmap_image (void *asurface,
 				 cairo_image_surface_t *image)
 {
     cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+    cairo_int_status_t status;
 
+    status = _cairo_image_surface_unmap_image (&surface->image, image);
     surface->bitmap->unlockPixels ();
-    return CAIRO_INT_STATUS_SUCCESS;
+
+    return status;
 }
 
 static cairo_status_t


More information about the cairo-commit mailing list