Skip to content

Commit

Permalink
Revert "Use pixman glyphs"
Browse files Browse the repository at this point in the history
This was pushed accidentally - apologies.

This reverts commit 752c3b6.
  • Loading branch information
Søren Sandmann Pedersen committed Apr 30, 2012
1 parent 752c3b6 commit af3c8ab
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 108 deletions.
313 changes: 212 additions & 101 deletions src/cairo-image-compositor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
1 change: 0 additions & 1 deletion src/cairo-mutex-list-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions src/cairo-scaled-font.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 0 additions & 4 deletions src/cairoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -1483,10 +1483,6 @@ cairo_private cairo_bool_t
_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);

Expand Down

0 comments on commit af3c8ab

Please sign in to comment.