Add new cairo_paint function.

Add new get_extents function to the surface backend interface.
Add function to query current clip_extents.
Implement the new get_extents function for each backend.
Save the clip extents from set_clip_region and implement _cairo_surface_get_clip_extents.
Abstract away the evil XGetGeometry roundtrip in _cairo_xlib_surface_get_size.
Rewrite a couple of tests to call cairo_paint.
This commit is contained in:
Carl Worth 2005-04-19 16:29:04 +00:00
parent 60ec322241
commit 9c10b54e5e
16 changed files with 358 additions and 75 deletions

View file

@ -1,3 +1,38 @@
2005-04-19 Carl Worth <cworth@cworth.org>
* src/cairo.c: (cairo_paint):
* src/cairo.h: Add new cairo_paint function.
* src/cairoint.h: Add new get_extents function to the surface
backend interface.
* src/cairo-gstate.c: (_cairo_gstate_get_clip_extents): Add
function to query current clip_extents.
* src/cairo-glitz-surface.c: (_cairo_glitz_surface_get_extents):
* src/cairo-image-surface.c: (_cairo_image_surface_get_extents),
(_cairo_image_abstract_surface_get_extents):
* src/cairo-pdf-surface.c: (_cairo_pdf_surface_get_extents):
* src/cairo-ps-surface.c: (_cairo_ps_surface_get_extents):
* src/cairo-quartz-surface.c: (_cairo_quartz_surface_get_extents):
* src/cairo-win32-surface.c: (_cairo_win32_get_extents):
* src/cairo-xcb-surface.c: (_cairo_xcb_surface_get_extents):
* src/cairo-xlib-surface.c: (_cairo_xlib_surface_get_extents):
Implement the new get_extents function for each backend.
* src/cairo-surface.c: (_cairo_surface_init),
(_cairo_surface_set_clip_region),
(_cairo_surface_get_clip_extents): Save the clip extents from
set_clip_region and implement _cairo_surface_get_clip_extents.
* src/cairo-xlib-surface.c: (_cairo_xlib_surface_get_size),
(_get_image_surface): Abstract away the evil XGetGeometry
roundtrip in _cairo_xlib_surface_get_size.
* test/gradient-alpha.c: (draw):
* test/linear-gradient.c: (draw): Rewrite a couple of tests to
call cairo_paint.
2005-04-19 Carl Worth <cworth@cworth.org>
* TODO: Update API Shakeup chart to indicate that cairo_paint and

View file

@ -1199,6 +1199,20 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_glitz_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_glitz_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = glitz_surface_get_width (surface->surface);
rectangle->height = glitz_surface_get_height (surface->surface);
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_create_similar,
_cairo_glitz_surface_finish,
@ -1213,6 +1227,7 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_glitz_surface_set_clip_region,
_cairo_glitz_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -1297,6 +1297,13 @@ _cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
_cairo_pattern_transform (pattern, &tmp_matrix);
}
cairo_status_t
_cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_t *rectangle)
{
return _cairo_surface_get_clip_extents (gstate->surface, rectangle);
}
cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate)
{

View file

@ -626,6 +626,27 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_get_extents (cairo_image_surface_t *surface,
cairo_rectangle_t *rectangle)
{
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_get_extents (surface, rectangle);
}
/**
* _cairo_surface_is_image:
* @surface: a #cairo_surface_t
@ -654,5 +675,6 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_image_abstract_surface_set_clip_region,
_cairo_image_abstract_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -1712,6 +1712,25 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
return status;
}
static cairo_int_status_t
_cairo_pdf_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_pdf_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
/* XXX: The conversion to integers here is pretty bogus, (not to
* mention the aribitray limitation of width to a short(!). We
* may need to come up with a better interface for get_size.
*/
rectangle->width = (int) (surface->width_inches * 72.0 + 1.0);
rectangle->height = (int) (surface->height_inches * 72.0 + 1.0);
return CAIRO_STATUS_SUCCESS;
}
static cairo_pdf_font_t *
_cairo_pdf_document_get_font (cairo_pdf_document_t *document,
cairo_scaled_font_t *scaled_font)
@ -1743,7 +1762,7 @@ _cairo_pdf_document_get_font (cairo_pdf_document_t *document,
return pdf_font;
}
static cairo_status_t
static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
@ -1807,6 +1826,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_copy_page,
_cairo_pdf_surface_show_page,
NULL, /* set_clip_region */
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs
};

View file

@ -303,6 +303,25 @@ _cairo_ps_surface_set_clip_region (void *abstract_surface,
return _cairo_image_surface_set_clip_region (surface->image, region);
}
static cairo_int_status_t
_cairo_ps_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_ps_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
/* XXX: The conversion to integers here is pretty bogus, (not to
* mention the aribitray limitation of width to a short(!). We
* may need to come up with a better interface for get_size.
*/
rectangle->width = (surface->width_inches * 72.0 + 0.5);
rectangle->height = (surface->height_inches * 72.0 + 0.5);
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_create_similar,
_cairo_ps_surface_finish,
@ -317,5 +336,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region,
_cairo_ps_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -82,7 +82,6 @@ cairo_set_target_quartz_context(cairo_t * cr,
cairo_surface_destroy(surface);
}
static cairo_surface_t *_cairo_quartz_surface_create_similar(void
*abstract_src,
cairo_format_t
@ -94,7 +93,6 @@ static cairo_surface_t *_cairo_quartz_surface_create_similar(void
return NULL;
}
static void _cairo_quartz_surface_finish(void *abstract_surface)
{
cairo_quartz_surface_t *surface = abstract_surface;
@ -222,6 +220,15 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface,
return _cairo_image_surface_set_clip_region(surface->image, region);
}
static void
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_t * rectangle)
{
cairo_quartz_surface_t *surface = abstract_surface;
_cairo_image_surface_get_extents(surface->image, rectangle);
}
static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
_cairo_quartz_surface_create_similar,
_cairo_quartz_surface_finish,
@ -236,6 +243,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_quartz_surface_set_clip_region,
_cairo_quartz_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -56,6 +56,12 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->device_x_offset = 0;
surface->device_y_offset = 0;
surface->is_clipped = 0;
surface->clip_extents.x = 0;
surface->clip_extents.y = 0;
surface->clip_extents.width = 0;
surface->clip_extents.height = 0;
}
cairo_surface_t *
@ -850,12 +856,43 @@ _cairo_surface_show_page (cairo_surface_t *surface)
}
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region)
_cairo_surface_set_clip_region (cairo_surface_t *surface,
pixman_region16_t *region)
{
pixman_box16_t *box;
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
if (region) {
box = pixman_region_extents (region);
surface->clip_extents.x = box->x1;
surface->clip_extents.y = box->y1;
surface->clip_extents.width = box->x2 - box->x1;
surface->clip_extents.height = box->y2 - box->y1;
surface->is_clipped = 1;
} else {
surface->is_clipped = 0;
}
return surface->backend->set_clip_region (surface, region);
}
cairo_status_t
_cairo_surface_get_clip_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle)
{
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
return surface->backend->set_clip_region (surface, region);
if (surface->is_clipped) {
*rectangle = surface->clip_extents;
return CAIRO_STATUS_SUCCESS;
}
return surface->backend->get_extents (surface, rectangle);
}
cairo_status_t

View file

@ -780,6 +780,23 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
}
}
static cairo_int_status_t
_cairo_win32_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
RECT clip_box;
if (GetClipBox (surface->dc, &clip_box) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
rectangle->x = clip_box.left;
rectangle->y = clip_box.top;
rectangle->width = clip_box.right - clip_box.left;
rectangle->height = clip_box.bottom - clip_box.top;
return CAIRO_STATUS_SUCCESS;
}
cairo_surface_t *
cairo_win32_surface_create (HDC hdc)
{
@ -844,5 +861,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_win32_surface_set_clip_region,
_cairo_win32_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -848,6 +848,20 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_xlib_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
_cairo_xcb_surface_create_similar,
_cairo_xcb_surface_finish,
@ -862,6 +876,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_xcb_surface_set_clip_region,
_cairo_xcb_surface_get_extents,
NULL /* show_glyphs */
};

View file

@ -159,6 +159,40 @@ _cairo_xlib_surface_finish (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_xlib_surface_get_size (cairo_xlib_surface_t *surface,
int *width,
int *height)
{
unsigned int width_u, height_u;
Window root_ignore;
int x_ignore, y_ignore;
unsigned int bwidth_ignore, depth_ignore;
if (surface->width >= 0 && surface->height >= 0) {
*width = surface->width;
*height = surface->height;
return;
}
XGetGeometry (surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&width_u, &height_u,
&bwidth_ignore, &depth_ignore);
/* The size of a pixmap can't change, so we store
* the information to avoid having to get it again
*/
if (surface->type == CAIRO_XLIB_PIXMAP) {
surface->width = width_u;
surface->height = height_u;
}
*width = width_u;
*height = height_u;
}
static cairo_status_t
_get_image_surface (cairo_xlib_surface_t *surface,
cairo_rectangle_t *interest_rect,
@ -171,33 +205,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
x1 = 0;
y1 = 0;
if (surface->width >= 0 && surface->height >= 0) {
x2 = surface->width;
y2 = surface->height;
} else {
unsigned int width, height;
Window root_ignore;
int x_ignore, y_ignore;
unsigned int bwidth_ignore, depth_ignore;
XGetGeometry (surface->dpy,
surface->drawable,
&root_ignore, &x_ignore, &y_ignore,
&width, &height,
&bwidth_ignore, &depth_ignore);
/* The size of a pixmap can't change, so we store
* the information to avoid having to get it again
*/
if (surface->type == CAIRO_XLIB_PIXMAP) {
surface->width = width;
surface->height = height;
}
x2 = width;
y2 = height;
}
_cairo_xlib_surface_get_size (surface, &x2, &y2);
if (interest_rect) {
cairo_rectangle_t rect;
@ -835,7 +844,26 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static cairo_int_status_t
_cairo_xlib_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_xlib_surface_t *surface = abstract_surface;
int width, height;
rectangle->x = 0;
rectangle->y = 0;
_cairo_xlib_surface_get_size (surface,
&width, &height);
rectangle->width = width;
rectangle->height = height;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
@ -863,6 +891,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_xlib_surface_set_clip_region,
_cairo_xlib_surface_get_extents,
_cairo_xlib_surface_show_glyphs
};
@ -1553,7 +1582,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
}
static cairo_status_t
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,

View file

@ -1362,7 +1362,7 @@ cairo_rectangle (cairo_t *cr,
/* XXX: NYI
void
cairo_stroke_path (cairo_t *cr)
cairo_stroke_to_path (cairo_t *cr)
{
if (cr->status)
return;
@ -1383,6 +1383,35 @@ cairo_close_path (cairo_t *cr)
}
slim_hidden_def(cairo_close_path);
/**
* cairo_paint:
* @cr: a cairo context
*
* A drawing operator that paints the current source everywhere within
* the current clip region.
**/
void
cairo_paint (cairo_t *cr)
{
cairo_rectangle_t rectangle;
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
cr->status = _cairo_gstate_get_clip_extents (cr->gstate, &rectangle);
if (cr->status)
return;
cairo_rectangle (cr,
rectangle.x, rectangle.y,
rectangle.width, rectangle.height);
cairo_fill (cr);
CAIRO_CHECK_SANITY (cr);
}
void
cairo_stroke (cairo_t *cr)
{

View file

@ -427,6 +427,9 @@ void
cairo_close_path (cairo_t *cr);
/* Painting functions */
void
cairo_paint (cairo_t *cr);
void
cairo_stroke (cairo_t *cr);

View file

@ -176,7 +176,7 @@ typedef struct _cairo_trapezoid {
cairo_line_t left, right;
} cairo_trapezoid_t;
typedef struct _cairo_rectangle_int {
typedef struct _cairo_rectangle {
short x, y;
unsigned short width, height;
} cairo_rectangle_t, cairo_glyph_size_t;
@ -565,21 +565,21 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_
typedef struct _cairo_surface_backend {
cairo_surface_t *
(*create_similar) (void *surface,
cairo_format_t format,
int drawable,
int width,
int height);
cairo_format_t format,
int drawable,
int width,
int height);
cairo_status_t
(*finish) (void *surface);
cairo_status_t
(* acquire_source_image) (void *abstract_surface,
(*acquire_source_image) (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra);
void
(* release_source_image) (void *abstract_surface,
(*release_source_image) (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra);
@ -604,39 +604,39 @@ typedef struct _cairo_surface_backend {
/* XXX: dst should be the first argument for consistency */
cairo_int_status_t
(*composite) (cairo_operator_t operator,
(*composite) (cairo_operator_t operator,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height);
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height);
cairo_int_status_t
(*fill_rectangles) (void *surface,
cairo_operator_t operator,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
int num_rects);
/* XXX: dst should be the first argument for consistency */
cairo_int_status_t
(*composite_trapezoids) (cairo_operator_t operator,
(*composite_trapezoids) (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *dst,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int num_traps);
int num_traps);
cairo_int_status_t
(*copy_page) (void *surface);
@ -647,24 +647,39 @@ typedef struct _cairo_surface_backend {
cairo_int_status_t
(*set_clip_region) (void *surface,
pixman_region16_t *region);
/* Get the extents of the current surface. For many surface types
* this will be as simple as { x=0, y=0, width=surface->width,
* height=surface->height}.
*
* This function need not take account of any clipping from
* set_clip_region since the generic version of set_clip_region
* saves those, and the generic get_clip_extents will only call
* into the specific surface->get_extents if there is no current
* clip.
*/
cairo_int_status_t
(*get_extents) (void *surface,
cairo_rectangle_t *rectangle);
/*
* This is an optional entry to let the surface manage its own glyph
* resources. If null, the font will be asked to render against this
* surface, using image surfaces as glyphs.
*/
cairo_status_t
(*show_glyphs) (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_int_status_t
(*show_glyphs) (cairo_scaled_font_t *font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
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);
int num_glyphs);
} cairo_surface_backend_t;
typedef struct _cairo_format_masks {
@ -688,6 +703,9 @@ struct _cairo_surface {
double device_x_offset;
double device_y_offset;
int is_clipped;
cairo_rectangle_t clip_extents;
};
struct _cairo_image_surface {
@ -1082,6 +1100,10 @@ _cairo_gstate_interpret_path (cairo_gstate_t *gstate,
cairo_close_path_func_t *close_path,
void *closure);
cairo_private cairo_status_t
_cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_t *rectangle);
cairo_private cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate);
@ -1485,7 +1507,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t **clone_out);
cairo_private cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface, pixman_region16_t *region);
_cairo_surface_set_clip_region (cairo_surface_t *surface,
pixman_region16_t *region);
cairo_private cairo_status_t
_cairo_surface_get_clip_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle);
cairo_private cairo_status_t
_cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,

View file

@ -47,8 +47,7 @@ draw (cairo_t *cr, int width, int height)
cairo_set_pattern (cr, gradient);
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
cairo_paint (cr);
cairo_pattern_destroy (gradient);

View file

@ -109,8 +109,7 @@ draw (cairo_t *cr, int width, int height)
int i, j, k;
cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
cairo_paint (cr);
for (i = 0; i < N_GRADIENT_ANGLES; i++)
for (j = 0; j < N_ROTATE_ANGLES; j++)