Track changes to glitz and update glyph caching in glitz backend

This commit is contained in:
David Reveman 2005-09-14 09:07:00 +00:00
parent c9ad68e6e9
commit 82cb5baeb2
3 changed files with 358 additions and 378 deletions

View file

@ -1,3 +1,8 @@
2005-09-14 David Reveman <davidr@novell.com>
* src/cairo-glitz-surface.c: Track changes to glitz.
Update glyph caching.
2005-09-13 Carl Worth <cworth@cworth.org>
* src/cairo-scaled-font.c (_cairo_scaled_font_text_to_glyphs): Set

View file

@ -231,7 +231,7 @@ AC_ARG_ENABLE(glitz,
[use_glitz=$enableval], [use_glitz=no])
if test "x$use_glitz" = "xyes"; then
PKG_CHECK_MODULES(GLITZ, glitz >= 0.4.4, [
PKG_CHECK_MODULES(GLITZ, glitz >= 0.5.0, [
GLITZ_REQUIRES=glitz
use_glitz=yes], [use_glitz="no (requires glitz http://freedesktop.org/Software/glitz)"])
fi

View file

@ -35,6 +35,9 @@ typedef struct _cairo_glitz_surface {
pixman_region16_t *clip;
} cairo_glitz_surface_t;
static const cairo_surface_backend_t *
_cairo_glitz_surface_get_backend (void);
static cairo_status_t
_cairo_glitz_surface_finish (void *abstract_surface)
{
@ -454,11 +457,54 @@ _glitz_operator (cairo_operator_t op)
static glitz_status_t
_glitz_ensure_target (glitz_surface_t *surface)
{
if (glitz_surface_get_attached_drawable (surface) ||
CAIRO_GLITZ_FEATURE_OK (surface, FRAMEBUFFER_OBJECT))
return CAIRO_STATUS_SUCCESS;
if (!glitz_surface_get_attached_drawable (surface))
{
glitz_drawable_format_t *target_format, templ;
glitz_format_t *format;
glitz_drawable_t *drawable, *target;
unsigned int width, height;
unsigned long mask;
return CAIRO_INT_STATUS_UNSUPPORTED;
drawable = glitz_surface_get_drawable (surface);
format = glitz_surface_get_format (surface);
width = glitz_surface_get_width (surface);
height = glitz_surface_get_height (surface);
if (format->type != GLITZ_FORMAT_TYPE_COLOR)
return CAIRO_INT_STATUS_UNSUPPORTED;
templ.color = format->color;
templ.depth_size = 0;
templ.stencil_size = 0;
templ.doublebuffer = 0;
templ.samples = 1;
mask =
GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK |
GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_ALPHA_SIZE_MASK |
GLITZ_FORMAT_DEPTH_SIZE_MASK |
GLITZ_FORMAT_STENCIL_SIZE_MASK |
GLITZ_FORMAT_DOUBLEBUFFER_MASK |
GLITZ_FORMAT_SAMPLES_MASK;
target_format = glitz_find_drawable_format (drawable, mask, &templ, 0);
if (!target_format)
return CAIRO_INT_STATUS_UNSUPPORTED;
target = glitz_create_drawable (drawable, target_format,
width, height);
if (!target)
return CAIRO_INT_STATUS_UNSUPPORTED;
glitz_surface_attach (surface, target,
GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
glitz_drawable_destroy (target);
}
return CAIRO_STATUS_SUCCESS;
}
typedef struct _cairo_glitz_surface_attributes {
@ -1218,8 +1264,6 @@ _cairo_glitz_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
#define CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
#define CAIRO_GLITZ_AREA_AVAILABLE 0
#define CAIRO_GLITZ_AREA_DIVIDED 1
#define CAIRO_GLITZ_AREA_OCCUPIED 2
@ -1530,6 +1574,56 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root)
_cairo_glitz_area_destroy (root->area);
}
typedef struct _cairo_glitz_surface_font_private {
cairo_glitz_root_area_t root;
glitz_surface_t *surface;
} cairo_glitz_surface_font_private_t;
typedef struct _cairo_glitz_surface_glyph_private {
cairo_glitz_area_t *area;
cairo_bool_t locked;
cairo_point_double_t p1, p2;
} cairo_glitz_surface_glyph_private_t;
static cairo_status_t
_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area,
void *closure)
{
cairo_glitz_surface_glyph_private_t *glyph_private = closure;
glyph_private->area = area;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area,
void *closure)
{
cairo_glitz_surface_glyph_private_t *glyph_private = closure;
glyph_private->area = NULL;
}
static int
_cairo_glitz_glyph_compare (cairo_glitz_area_t *area,
void *closure1,
void *closure2)
{
cairo_glitz_surface_glyph_private_t *glyph_private = closure1;
if (glyph_private->locked)
return 1;
return -1;
}
static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
_cairo_glitz_glyph_move_in,
_cairo_glitz_glyph_move_out,
_cairo_glitz_glyph_compare
};
#define GLYPH_CACHE_TEXTURE_SIZE 512
#define GLYPH_CACHE_MAX_LEVEL 64
#define GLYPH_CACHE_MAX_HEIGHT 72
@ -1549,266 +1643,170 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root)
WRITE_VEC2 (ptr, _vx1, _vy2); \
WRITE_VEC2 (ptr, (p1)->x, (p1)->y)
typedef struct _cairo_glitz_glyph_cache {
cairo_cache_t base;
cairo_glitz_root_area_t root;
glitz_surface_t *surface;
} cairo_glitz_glyph_cache_t;
typedef struct {
cairo_glyph_cache_key_t key;
int ref_count;
cairo_glyph_size_t size;
cairo_glitz_area_t *area;
cairo_bool_t locked;
cairo_point_double_t p1, p2;
} cairo_glitz_glyph_cache_entry_t;
static cairo_status_t
_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area,
void *closure)
_cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_format_t format)
{
cairo_glitz_glyph_cache_entry_t *entry = closure;
entry->area = area;
cairo_glitz_surface_font_private_t *font_private;
glitz_drawable_t *drawable;
glitz_format_t *surface_format = NULL;
cairo_int_status_t status;
drawable = glitz_surface_get_drawable (surface->surface);
switch (format) {
case CAIRO_FORMAT_A8:
surface_format =
glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
break;
case CAIRO_FORMAT_ARGB32:
surface_format =
glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32);
default:
break;
}
if (!surface_format)
return CAIRO_INT_STATUS_UNSUPPORTED;
font_private = malloc (sizeof (cairo_glitz_surface_font_private_t));
if (!font_private)
return CAIRO_STATUS_NO_MEMORY;
font_private->surface = glitz_surface_create (drawable, surface_format,
GLYPH_CACHE_TEXTURE_SIZE,
GLYPH_CACHE_TEXTURE_SIZE,
0, NULL);
if (font_private->surface == NULL)
{
free (font_private);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (format == CAIRO_FORMAT_ARGB32)
glitz_surface_set_component_alpha (font_private->surface, 1);
status = _cairo_glitz_root_area_init (&font_private->root,
GLYPH_CACHE_MAX_LEVEL,
GLYPH_CACHE_TEXTURE_SIZE,
GLYPH_CACHE_TEXTURE_SIZE,
&_cairo_glitz_area_funcs);
if (status != CAIRO_STATUS_SUCCESS)
{
glitz_surface_destroy (font_private->surface);
free (font_private);
return status;
}
scaled_font->surface_private = font_private;
scaled_font->surface_backend = _cairo_glitz_surface_get_backend ();
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area,
void *closure)
_cairo_glitz_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
cairo_glitz_glyph_cache_entry_t *entry = closure;
entry->area = NULL;
}
cairo_glitz_surface_font_private_t *font_private;
static int
_cairo_glitz_glyph_compare (cairo_glitz_area_t *area,
void *closure1,
void *closure2)
{
cairo_glitz_glyph_cache_entry_t *entry = closure1;
if (entry->locked)
return 1;
return -1;
}
static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
_cairo_glitz_glyph_move_in,
_cairo_glitz_glyph_move_out,
_cairo_glitz_glyph_compare
};
static cairo_status_t
_cairo_glitz_glyph_cache_create_entry (void *abstract_cache,
void *abstract_key,
void **return_entry)
{
cairo_glitz_glyph_cache_entry_t *entry;
cairo_glyph_cache_key_t *key = abstract_key;
cairo_status_t status;
cairo_cache_t *im_cache;
cairo_image_glyph_cache_entry_t *im;
unsigned long entry_memory = 0;
entry = malloc (sizeof (cairo_glitz_glyph_cache_entry_t));
if (!entry)
return CAIRO_STATUS_NO_MEMORY;
_cairo_lock_global_image_glyph_cache ();
im_cache = _cairo_get_global_image_glyph_cache ();
if (im_cache == NULL) {
_cairo_unlock_global_image_glyph_cache ();
free (entry);
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL);
if (status != CAIRO_STATUS_SUCCESS || im == NULL) {
_cairo_unlock_global_image_glyph_cache ();
free (entry);
return CAIRO_STATUS_NO_MEMORY;
}
if (im->image)
entry_memory = im->image->width * im->image->stride;
_cairo_unlock_global_image_glyph_cache ();
entry->ref_count = 1;
entry->key = *key;
entry->key.base.memory = entry_memory;
entry->area = NULL;
entry->locked = FALSE;
_cairo_unscaled_font_reference (entry->key.unscaled);
*return_entry = entry;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_glitz_glyph_cache_destroy_entry (void *abstract_cache,
void *abstract_entry)
{
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
entry->ref_count--;
if (entry->ref_count)
return;
if (entry->area)
_cairo_glitz_area_move_out (entry->area);
_cairo_unscaled_font_destroy (entry->key.unscaled);
free (entry);
}
static void
_cairo_glitz_glyph_cache_entry_reference (void *abstract_entry)
{
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
entry->ref_count++;
}
static void
_cairo_glitz_glyph_cache_destroy_cache (void *abstract_cache)
{
cairo_glitz_glyph_cache_t *cache = abstract_cache;
_cairo_glitz_root_area_fini (&cache->root);
glitz_surface_destroy (cache->surface);
}
static const cairo_cache_backend_t _cairo_glitz_glyph_cache_backend = {
_cairo_glyph_cache_hash,
_cairo_glyph_cache_keys_equal,
_cairo_glitz_glyph_cache_create_entry,
_cairo_glitz_glyph_cache_destroy_entry,
_cairo_glitz_glyph_cache_destroy_cache
};
static cairo_glitz_glyph_cache_t *_cairo_glitz_glyph_caches = NULL;
static cairo_glitz_glyph_cache_t *
_cairo_glitz_get_glyph_cache (cairo_glitz_surface_t *surface)
{
cairo_glitz_glyph_cache_t *cache;
glitz_drawable_t *drawable;
glitz_format_t *format;
/*
* FIXME: caches should be thread specific, display specific and screen
* specific.
*/
if (_cairo_glitz_glyph_caches)
return _cairo_glitz_glyph_caches;
drawable = glitz_surface_get_drawable (surface->surface);
format = glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
if (!format)
return NULL;
cache = malloc (sizeof (cairo_glitz_glyph_cache_t));
if (!cache)
return NULL;
cache->surface =
glitz_surface_create (drawable, format,
GLYPH_CACHE_TEXTURE_SIZE,
GLYPH_CACHE_TEXTURE_SIZE,
0, NULL);
if (cache->surface == NULL)
font_private = scaled_font->surface_private;
if (font_private)
{
free (cache);
return NULL;
_cairo_glitz_root_area_fini (&font_private->root);
glitz_surface_destroy (font_private->surface);
free (font_private);
}
}
if (_cairo_glitz_root_area_init (&cache->root,
GLYPH_CACHE_MAX_LEVEL,
GLYPH_CACHE_TEXTURE_SIZE,
GLYPH_CACHE_TEXTURE_SIZE,
&_cairo_glitz_area_funcs))
{
glitz_surface_destroy (cache->surface);
free (cache);
return NULL;
}
static void
_cairo_glitz_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font)
{
cairo_glitz_surface_glyph_private_t *glyph_private;
if (_cairo_cache_init (&cache->base,
&_cairo_glitz_glyph_cache_backend,
CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT))
glyph_private = scaled_glyph->surface_private;
if (glyph_private)
{
_cairo_glitz_root_area_fini (&cache->root);
glitz_surface_destroy (cache->surface);
free (cache);
return NULL;
if (glyph_private->area)
_cairo_glitz_area_move_out (glyph_private->area);
free (glyph_private);
}
_cairo_glitz_glyph_caches = cache;
return cache;
}
#define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536)
static cairo_status_t
_cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache,
cairo_glitz_glyph_cache_entry_t *entry,
cairo_image_glyph_cache_entry_t *image_entry)
_cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
glitz_point_fixed_t p1, p2;
glitz_pixel_format_t pf;
glitz_buffer_t *buffer;
pixman_format_t *format;
int am, rm, gm, bm;
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
cairo_glitz_surface_font_private_t *font_private;
cairo_glitz_surface_glyph_private_t *glyph_private;
glitz_point_fixed_t p1, p2;
glitz_pixel_format_t pf;
glitz_buffer_t *buffer;
pixman_format_t *format;
int am, rm, gm, bm;
cairo_int_status_t status;
entry->size = image_entry->size;
if (entry->size.width > GLYPH_CACHE_MAX_WIDTH ||
entry->size.height > GLYPH_CACHE_MAX_HEIGHT)
glyph_private = scaled_glyph->surface_private;
if (glyph_private == NULL)
{
glyph_private = malloc (sizeof (cairo_glitz_surface_glyph_private_t));
if (!glyph_private)
return CAIRO_STATUS_NO_MEMORY;
glyph_private->area = NULL;
glyph_private->locked = FALSE;
scaled_glyph->surface_private = (void *) glyph_private;
}
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
return CAIRO_STATUS_SUCCESS;
if ((entry->size.width == 0 && entry->size.height == 0) ||
!image_entry->image)
if (scaled_font->surface_private == NULL)
{
entry->area = &_empty_area;
status = _cairo_glitz_surface_font_init (surface, scaled_font,
glyph_surface->format);
if (status)
return status;
}
font_private = scaled_font->surface_private;
if (glyph_surface->width == 0 || glyph_surface->height == 0)
{
glyph_private->area = &_empty_area;
return CAIRO_STATUS_SUCCESS;
}
format = pixman_image_get_format (image_entry->image->pixman_image);
format = pixman_image_get_format (glyph_surface->pixman_image);
if (!format)
return CAIRO_STATUS_NO_MEMORY;
if (_cairo_glitz_area_find (cache->root.area,
entry->size.width,
entry->size.height,
FALSE, entry))
if (_cairo_glitz_area_find (font_private->root.area,
glyph_surface->width,
glyph_surface->height,
FALSE, glyph_private))
{
if (_cairo_glitz_area_find (cache->root.area,
entry->size.width,
entry->size.height,
TRUE, entry))
if (_cairo_glitz_area_find (font_private->root.area,
glyph_surface->width,
glyph_surface->height,
TRUE, glyph_private))
return CAIRO_STATUS_SUCCESS;
}
buffer = glitz_buffer_create_for_data (image_entry->image->data);
buffer = glitz_buffer_create_for_data (glyph_surface->data);
if (!buffer)
{
_cairo_glitz_area_move_out (entry->area);
_cairo_glitz_area_move_out (glyph_private->area);
return CAIRO_STATUS_NO_MEMORY;
}
@ -1818,34 +1816,34 @@ _cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache,
pf.masks.red_mask = rm;
pf.masks.green_mask = gm;
pf.masks.blue_mask = bm;
pf.bytes_per_line = image_entry->image->stride;
pf.bytes_per_line = glyph_surface->stride;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
pf.xoffset = 0;
pf.skip_lines = 0;
glitz_set_pixels (cache->surface,
entry->area->x,
entry->area->y,
entry->size.width,
entry->size.height,
glitz_set_pixels (font_private->surface,
glyph_private->area->x,
glyph_private->area->y,
glyph_surface->width,
glyph_surface->height,
&pf, buffer);
glitz_buffer_destroy (buffer);
p1.x = entry->area->x << 16;
p1.y = entry->area->y << 16;
p2.x = (entry->area->x + entry->size.width) << 16;
p2.y = (entry->area->y + entry->size.height) << 16;
glitz_surface_translate_point (cache->surface, &p1, &p1);
glitz_surface_translate_point (cache->surface, &p2, &p2);
entry->p1.x = FIXED_TO_FLOAT (p1.x);
entry->p1.y = FIXED_TO_FLOAT (p1.y);
entry->p2.x = FIXED_TO_FLOAT (p2.x);
entry->p2.y = FIXED_TO_FLOAT (p2.y);
p1.x = glyph_private->area->x << 16;
p1.y = glyph_private->area->y << 16;
p2.x = (glyph_private->area->x + glyph_surface->width) << 16;
p2.y = (glyph_private->area->y + glyph_surface->height) << 16;
glitz_surface_translate_point (font_private->surface, &p1, &p1);
glitz_surface_translate_point (font_private->surface, &p2, &p2);
glyph_private->p1.x = FIXED_TO_FLOAT (p1.x);
glyph_private->p1.y = FIXED_TO_FLOAT (p1.y);
glyph_private->p2.x = FIXED_TO_FLOAT (p2.x);
glyph_private->p2.y = FIXED_TO_FLOAT (p2.y);
return CAIRO_STATUS_SUCCESS;
}
@ -1865,21 +1863,21 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_glitz_surface_attributes_t attributes;
cairo_glitz_surface_t *dst = abstract_surface;
cairo_glitz_surface_t *src;
cairo_glitz_glyph_cache_t *cache;
cairo_glitz_glyph_cache_entry_t *stack_entries[N_STACK_BUF];
cairo_glitz_glyph_cache_entry_t **entries;
cairo_glyph_cache_key_t key;
glitz_float_t stack_vertices[N_STACK_BUF * 16];
glitz_float_t *vertices;
glitz_buffer_t *buffer;
cairo_int_status_t status;
int i, cached_glyphs = 0;
int remaining_glyps = num_glyphs;
glitz_float_t x1, y1, x2, y2;
static glitz_vertex_format_t format = {
cairo_glitz_surface_attributes_t attributes;
cairo_glitz_surface_glyph_private_t *glyph_private;
cairo_glitz_surface_t *dst = abstract_surface;
cairo_glitz_surface_t *src;
cairo_scaled_glyph_t *stack_scaled_glyphs[N_STACK_BUF];
cairo_scaled_glyph_t **scaled_glyphs;
glitz_float_t stack_vertices[N_STACK_BUF * 16];
glitz_float_t *vertices;
glitz_buffer_t *buffer;
cairo_int_status_t status;
int x_offset, y_offset;
int i, cached_glyphs = 0;
int remaining_glyps = num_glyphs;
glitz_float_t x1, y1, x2, y2;
static glitz_vertex_format_t format = {
GLITZ_PRIMITIVE_QUADS,
GLITZ_DATA_TYPE_FLOAT,
sizeof (glitz_float_t) * 4,
@ -1892,6 +1890,10 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
}
};
if (scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != _cairo_glitz_surface_get_backend ())
return CAIRO_INT_STATUS_UNSUPPORTED;
if (op == CAIRO_OPERATOR_SATURATE)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1910,67 +1912,57 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (num_glyphs > N_STACK_BUF)
{
char *data;
data = malloc (num_glyphs * sizeof (void *) +
num_glyphs * sizeof (glitz_float_t) * 16);
if (!data)
goto FAIL1;
entries = (cairo_glitz_glyph_cache_entry_t **) data;
scaled_glyphs = (cairo_scaled_glyph_t **) data;
vertices = (glitz_float_t *) (data + num_glyphs * sizeof (void *));
}
else
{
entries = stack_entries;
scaled_glyphs = stack_scaled_glyphs;
vertices = stack_vertices;
}
buffer = glitz_buffer_create_for_data (vertices);
if (!buffer)
goto FAIL2;
cache = _cairo_glitz_get_glyph_cache (dst);
if (!cache)
{
num_glyphs = 0;
goto UNLOCK;
}
status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
if (status)
goto UNLOCK;
for (i = 0; i < num_glyphs; i++)
{
key.index = glyphs[i].index;
status = _cairo_cache_lookup (&cache->base,
&key,
(void **) &entries[i],
NULL);
if (status)
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyphs[i]);
if (status != CAIRO_STATUS_SUCCESS)
{
num_glyphs = i;
goto UNLOCK;
}
_cairo_glitz_glyph_cache_entry_reference (entries[i]);
if (entries[i]->area)
glyph_private = scaled_glyphs[i]->surface_private;
if (glyph_private && glyph_private->area)
{
remaining_glyps--;
if (entries[i]->area->width)
if (glyph_private->area->width)
{
x1 = floor (glyphs[i].x + 0.5) + entries[i]->size.x;
y1 = floor (glyphs[i].y + 0.5) + entries[i]->size.y;
x2 = x1 + entries[i]->size.width;
y2 = y1 + entries[i]->size.height;
x_offset = scaled_glyphs[i]->surface->base.device_x_offset;
y_offset = scaled_glyphs[i]->surface->base.device_y_offset;
x1 = floor (glyphs[i].x + 0.5) + x_offset;
y1 = floor (glyphs[i].y + 0.5) + y_offset;
x2 = x1 + glyph_private->area->width;
y2 = y1 + glyph_private->area->height;
WRITE_BOX (vertices, x1, y1, x2, y2,
&entries[i]->p1, &entries[i]->p2);
entries[i]->locked = TRUE;
&glyph_private->p1, &glyph_private->p2);
glyph_private->locked = TRUE;
cached_glyphs++;
}
}
@ -1978,96 +1970,65 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (remaining_glyps)
{
cairo_cache_t *image_cache;
cairo_image_glyph_cache_entry_t *image_entry;
cairo_surface_t *image;
cairo_glitz_surface_t *clone;
_cairo_lock_global_image_glyph_cache ();
cairo_surface_t *image;
cairo_glitz_surface_t *clone;
image_cache = _cairo_get_global_image_glyph_cache ();
if (!image_cache)
{
_cairo_unlock_global_image_glyph_cache ();
status = CAIRO_STATUS_NO_MEMORY;
goto UNLOCK;
}
for (i = 0; i < num_glyphs; i++)
{
if (!entries[i]->area)
glyph_private = scaled_glyphs[i]->surface_private;
if (!glyph_private || !glyph_private->area)
{
key.index = glyphs[i].index;
status = _cairo_cache_lookup (image_cache,
&key,
(void **) &image_entry,
NULL);
status = _cairo_glitz_surface_add_glyph (dst,
scaled_font,
scaled_glyphs[i]);
if (status)
{
_cairo_unlock_global_image_glyph_cache ();
goto UNLOCK;
}
status = _cairo_glitz_cache_glyph (cache,
entries[i],
image_entry);
if (status)
{
_cairo_unlock_global_image_glyph_cache ();
goto UNLOCK;
}
glyph_private = scaled_glyphs[i]->surface_private;
}
x1 = floor (glyphs[i].x + 0.5);
y1 = floor (glyphs[i].y + 0.5);
if (entries[i]->area)
x_offset = scaled_glyphs[i]->surface->base.device_x_offset;
y_offset = scaled_glyphs[i]->surface->base.device_y_offset;
x1 = floor (glyphs[i].x + 0.5) + x_offset;
y1 = floor (glyphs[i].y + 0.5) + y_offset;
if (glyph_private->area)
{
if (entries[i]->area->width)
if (glyph_private->area->width)
{
x1 += entries[i]->size.x;
y1 += entries[i]->size.y;
x2 = x1 + entries[i]->size.width;
y2 = y1 + entries[i]->size.height;
x2 = x1 + glyph_private->area->width;
y2 = y1 + glyph_private->area->height;
WRITE_BOX (vertices, x1, y1, x2, y2,
&entries[i]->p1, &entries[i]->p2);
entries[i]->locked = TRUE;
&glyph_private->p1, &glyph_private->p2);
glyph_private->locked = TRUE;
cached_glyphs++;
}
}
else
{
x1 += image_entry->size.x;
y1 += image_entry->size.y;
if (!image_entry->image)
continue;
image = &image_entry->image->base;
image = &scaled_glyphs[i]->surface->base;
status =
_cairo_glitz_surface_clone_similar (abstract_surface,
image,
(cairo_surface_t **)
&clone);
if (status)
{
_cairo_unlock_global_image_glyph_cache ();
goto UNLOCK;
}
glitz_composite (_glitz_operator (op),
src->surface,
glitz_composite (_glitz_operator (op),
src->surface,
clone->surface,
dst->surface,
src_x + attributes.base.x_offset + x1,
src_y + attributes.base.y_offset + y1,
0, 0,
x1, y1,
image_entry->size.width,
image_entry->size.height);
scaled_glyphs[i]->surface->width,
scaled_glyphs[i]->surface->height);
cairo_surface_destroy (&clone->base);
@ -2075,17 +2036,16 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
GLITZ_STATUS_NOT_SUPPORTED)
{
status = CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_unlock_global_image_glyph_cache ();
goto UNLOCK;
}
}
}
_cairo_unlock_global_image_glyph_cache ();
}
if (cached_glyphs)
{
cairo_glitz_surface_font_private_t *font_private;
glitz_set_geometry (dst->surface,
GLITZ_GEOMETRY_TYPE_VERTEX,
(glitz_geometry_format_t *) &format,
@ -2093,9 +2053,11 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
glitz_set_array (dst->surface, 0, 4, cached_glyphs * 4, 0, 0);
font_private = scaled_font->surface_private;
glitz_composite (_glitz_operator (op),
src->surface,
cache->surface,
font_private->surface,
dst->surface,
src_x + attributes.base.x_offset,
src_y + attributes.base.y_offset,
@ -2107,22 +2069,23 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
GLITZ_GEOMETRY_TYPE_NONE,
NULL, NULL);
}
UNLOCK:
if (cached_glyphs)
{
for (i = 0; i < num_glyphs; i++)
entries[i]->locked = FALSE;
{
glyph_private = scaled_glyphs[i]->surface_private;
if (glyph_private)
glyph_private->locked = FALSE;
}
}
for (i = 0; i < num_glyphs; i++)
_cairo_glitz_glyph_cache_destroy_entry (cache, entries[i]);
glitz_buffer_destroy (buffer);
FAIL2:
if (num_glyphs > N_STACK_BUF)
free (entries);
free (scaled_glyphs);
FAIL1:
if (attributes.n_params)
@ -2132,10 +2095,10 @@ UNLOCK:
if (status)
return status;
if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
}
@ -2155,9 +2118,21 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_glitz_surface_get_extents,
_cairo_glitz_surface_show_glyphs
_cairo_glitz_surface_show_glyphs,
NULL, /* fill_path */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
_cairo_glitz_surface_scaled_font_fini,
_cairo_glitz_surface_scaled_glyph_fini
};
static const cairo_surface_backend_t *
_cairo_glitz_surface_get_backend (void)
{
return &cairo_glitz_surface_backend;
}
cairo_surface_t *
cairo_glitz_surface_create (glitz_surface_t *surface)
{
@ -2175,10 +2150,10 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend);
glitz_surface_reference (surface);
crsurface->surface = surface;
crsurface->format = glitz_surface_get_format (surface);
crsurface->clip = NULL;
return (cairo_surface_t *) crsurface;
}