mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 03:18:05 +02:00
[xlib] implement _cairo_xlib_surface_show_glyphs
Avoid using the fallback paths as much as possible; implement real show_glyphs, falling back for OPERATOR_SOURCE (due to Render bug), and all unbounded operators (let the fallback code deal with fixup). Also fall back if we have a fallback mask clip set. (cherry picked from 3225a4ec820fd4051dd893ffc4258b182bd62dca commit)
This commit is contained in:
parent
3487191b22
commit
108431414f
1 changed files with 152 additions and 124 deletions
|
|
@ -40,6 +40,7 @@
|
|||
#include "cairo-xlib-xrender.h"
|
||||
#include "cairo-xlib-test.h"
|
||||
#include "cairo-xlib-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/renderproto.h>
|
||||
|
||||
|
|
@ -64,6 +65,14 @@ _cairo_surface_is_xlib (cairo_surface_t *surface);
|
|||
static cairo_bool_t
|
||||
_native_byte_order_lsb (void);
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *src_pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
/*
|
||||
* Instead of taking two round trips for each blending request,
|
||||
* assume that if a particular drawable fails GetImage that it will
|
||||
|
|
@ -1711,20 +1720,6 @@ _cairo_xlib_surface_get_font_options (void *abstract_surface,
|
|||
options->antialias = CAIRO_ANTIALIAS_GRAY;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
void *abstract_surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
static void
|
||||
_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
|
|
@ -1749,12 +1744,19 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
|||
_cairo_xlib_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_xlib_surface_get_extents,
|
||||
_cairo_xlib_surface_old_show_glyphs,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_xlib_surface_get_font_options,
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
_cairo_xlib_surface_scaled_font_fini,
|
||||
_cairo_xlib_surface_scaled_glyph_fini,
|
||||
|
||||
NULL, /* paint */
|
||||
NULL, /* mask */
|
||||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
_cairo_xlib_surface_show_glyphs,
|
||||
NULL /* snapshot */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2363,14 +2365,13 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
#define N_STACK_BUF 1024
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_old_show_glyphs8 (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_xlib_surface_t *self,
|
||||
int source_x,
|
||||
int source_y,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
_cairo_xlib_surface_show_glyphs8 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt8 *elts = NULL;
|
||||
|
|
@ -2409,13 +2410,13 @@ _cairo_xlib_surface_old_show_glyphs8 (cairo_scaled_font_t *scaled_font,
|
|||
lastY = thisY;
|
||||
}
|
||||
|
||||
XRenderCompositeText8 (self->dpy,
|
||||
XRenderCompositeText8 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
self->dst_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
source_x + elts[0].xOff, source_y + elts[0].yOff,
|
||||
0, 0,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
|
||||
if (elts != stack_elts)
|
||||
|
|
@ -2425,14 +2426,13 @@ _cairo_xlib_surface_old_show_glyphs8 (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_old_show_glyphs16 (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_xlib_surface_t *self,
|
||||
int source_x,
|
||||
int source_y,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
_cairo_xlib_surface_show_glyphs16 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt16 *elts = NULL;
|
||||
|
|
@ -2471,13 +2471,13 @@ _cairo_xlib_surface_old_show_glyphs16 (cairo_scaled_font_t *scaled_font,
|
|||
lastY = thisY;
|
||||
}
|
||||
|
||||
XRenderCompositeText16 (self->dpy,
|
||||
XRenderCompositeText16 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
self->dst_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
source_x + elts[0].xOff, source_y + elts[0].yOff,
|
||||
0, 0,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
|
||||
if (elts != stack_elts)
|
||||
|
|
@ -2487,14 +2487,13 @@ _cairo_xlib_surface_old_show_glyphs16 (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_old_show_glyphs32 (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_xlib_surface_t *self,
|
||||
int source_x,
|
||||
int source_y,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
_cairo_xlib_surface_show_glyphs32 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt32 *elts = NULL;
|
||||
|
|
@ -2533,13 +2532,13 @@ _cairo_xlib_surface_old_show_glyphs32 (cairo_scaled_font_t *scaled_font,
|
|||
lastY = thisY;
|
||||
}
|
||||
|
||||
XRenderCompositeText32 (self->dpy,
|
||||
XRenderCompositeText32 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
self->dst_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
source_x + elts[0].xOff, source_y + elts[0].yOff,
|
||||
0, 0,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
|
||||
if (elts != stack_elts)
|
||||
|
|
@ -2548,63 +2547,113 @@ _cairo_xlib_surface_old_show_glyphs32 (cairo_scaled_font_t *scaled_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef cairo_status_t (*cairo_xlib_surface_show_glyphs_func_t)
|
||||
(cairo_xlib_surface_t *, cairo_operator_t, cairo_xlib_surface_t *, int, int,
|
||||
const cairo_glyph_t *, int, cairo_scaled_font_t *);
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
void *abstract_surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *src_pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_surface_attributes_t attributes;
|
||||
cairo_int_status_t status;
|
||||
cairo_xlib_surface_t *self = abstract_surface;
|
||||
cairo_xlib_surface_t *src;
|
||||
cairo_int_status_t status;
|
||||
cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst;
|
||||
|
||||
composite_operation_t operation;
|
||||
cairo_surface_attributes_t attributes;
|
||||
cairo_xlib_surface_t *src = NULL;
|
||||
|
||||
const cairo_glyph_t *glyphs_chunk;
|
||||
int glyphs_remaining, chunk_size, max_chunk_size;
|
||||
composite_operation_t operation;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_xlib_surface_font_private_t *font_private;
|
||||
|
||||
cairo_rectangle_fixed_t glyph_extents;
|
||||
|
||||
int i;
|
||||
unsigned long max_index = 0;
|
||||
|
||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->xrender_format)
|
||||
|
||||
cairo_xlib_surface_show_glyphs_func_t show_glyphs_func;
|
||||
|
||||
cairo_pattern_union_t solid_pattern;
|
||||
|
||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
operation = _categorize_composite_operation (self, op, pattern, TRUE);
|
||||
/* Just let unbounded operators go through the fallback code
|
||||
* instead of trying to do the fixups here */
|
||||
if (!_cairo_operator_bounded_by_mask (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs --
|
||||
* the solid source seems to be multiplied by the glyph mask, and
|
||||
* then the entire thing is copied to the destination surface,
|
||||
* including the fully transparent "background" of the rectangular
|
||||
* glyph surface. */
|
||||
if (op == CAIRO_OPERATOR_SOURCE &&
|
||||
!CAIRO_SURFACE_RENDER_AT_LEAST(dst, 0, 11))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* We can only use our code if we either have no clip or
|
||||
* have a real native clip region set. If we're using
|
||||
* fallback clip masking, we have to go through the full
|
||||
* fallback path.
|
||||
*/
|
||||
if (dst->base.clip &&
|
||||
(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
|
||||
dst->base.clip->surface != NULL))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
operation = _categorize_composite_operation (dst, op, src_pattern, TRUE);
|
||||
if (operation == DO_UNSUPPORTED)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
||||
font_private = scaled_font->surface_private;
|
||||
if ((scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
|
||||
(font_private != NULL && font_private->dpy != self->dpy))
|
||||
(font_private != NULL && font_private->dpy != dst->dpy))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_pattern_acquire_surface (pattern, &self->base,
|
||||
source_x, source_y, width, height,
|
||||
(cairo_surface_t **) &src,
|
||||
&attributes);
|
||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||
glyphs,
|
||||
num_glyphs,
|
||||
&glyph_extents);
|
||||
if (status)
|
||||
return status;
|
||||
return status;
|
||||
|
||||
operation = _recategorize_composite_operation (self, op, src, &attributes, TRUE);
|
||||
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
||||
* the mask (the glyphs). This code below was executed as a side effect
|
||||
* of going through the _clip_and_composite fallback code for old_show_glyphs,
|
||||
* so PictOpClear was never used with CompositeText before.
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
src_pattern = &solid_pattern.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
||||
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
|
||||
glyph_extents.x, glyph_extents.y,
|
||||
glyph_extents.width, glyph_extents.height,
|
||||
(cairo_surface_t **) &src,
|
||||
&attributes);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
|
||||
if (operation == DO_UNSUPPORTED) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
|
||||
status = _cairo_xlib_surface_set_attributes (src, &attributes);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
/* Send all unsent glyphs to the server */
|
||||
goto FAIL;
|
||||
|
||||
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
if (glyphs[i].index > max_index)
|
||||
max_index = glyphs[i].index;
|
||||
|
|
@ -2615,20 +2664,24 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
_cairo_xlib_surface_add_glyph (self->dpy, scaled_font, scaled_glyph);
|
||||
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
|
||||
scaled_glyph->surface_private = (void *) 1;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_xlib_surface_ensure_dst_picture (self);
|
||||
|
||||
max_chunk_size = XMaxRequestSize (self->dpy);
|
||||
if (max_index < 256)
|
||||
_cairo_xlib_surface_ensure_dst_picture (dst);
|
||||
|
||||
max_chunk_size = XMaxRequestSize (dst->dpy);
|
||||
if (max_index < 256) {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
|
||||
else if (max_index < 65536)
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs8;
|
||||
} else if (max_index < 65536) {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
|
||||
else
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs16;
|
||||
} else {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs32;
|
||||
}
|
||||
max_chunk_size /= sz_xGlyphElt;
|
||||
|
||||
for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs;
|
||||
|
|
@ -2637,43 +2690,18 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
{
|
||||
chunk_size = MIN (glyphs_remaining, max_chunk_size);
|
||||
|
||||
/* Call the appropriate sub-function. */
|
||||
if (max_index < 256)
|
||||
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
else if (max_index < 65536)
|
||||
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
else
|
||||
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
status = show_glyphs_func (dst, op, src,
|
||||
attributes.x_offset, attributes.y_offset,
|
||||
glyphs_chunk, chunk_size, scaled_font);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_fixed_t extents;
|
||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||
glyphs,
|
||||
num_glyphs,
|
||||
&extents);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_surface_composite_shape_fixup_unbounded
|
||||
(&self->base, &attributes, src->width, src->height,
|
||||
extents.width, extents.height,
|
||||
source_x, source_y,
|
||||
dest_x - extents.x, dest_y - extents.y,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
}
|
||||
FAIL:
|
||||
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
|
||||
|
||||
FAIL:
|
||||
if (src)
|
||||
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
|
||||
if (src_pattern == &solid_pattern.base)
|
||||
_cairo_pattern_fini (&solid_pattern.base);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue