[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