[cairo-commit] cairo/src cairo-glitz-surface.c, 1.45,
1.46 cairo-gstate-private.h, 1.11, 1.12 cairo-gstate.c, 1.141,
1.142 cairo-image-surface.c, 1.45, 1.46 cairo-pdf-surface.c,
1.45, 1.46 cairo-ps-surface.c, 1.36,
1.37 cairo-quartz-surface.c, 1.11, 1.12 cairo-surface.c, 1.73,
1.74 cairo-win32-surface.c, 1.25, 1.26 cairo-xcb-surface.c,
1.35, 1.36 cairo-xlib-surface.c, 1.78, 1.79 cairoint.h, 1.154, 1.155
Kristian Hogsberg
commit at pdx.freedesktop.org
Tue Jun 14 19:45:25 PDT 2005
Committed by: krh
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv31124/src
Modified Files:
cairo-glitz-surface.c cairo-gstate-private.h cairo-gstate.c
cairo-image-surface.c cairo-pdf-surface.c cairo-ps-surface.c
cairo-quartz-surface.c cairo-surface.c cairo-win32-surface.c
cairo-xcb-surface.c cairo-xlib-surface.c cairoint.h
Log Message:
2005-06-14 Kristian Høgsberg <krh at redhat.com>
* src/cairo-gstate-private.h:
* src/cairo-gstate.c: (_cairo_gstate_init),
(_cairo_gstate_init_copy), (_cairo_gstate_fini),
(_cairo_gstate_set_clip), (_composite_trap_region),
(_cairo_gstate_fill), (_cairo_gstate_reset_clip),
(_cairo_gstate_intersect_clip_path), (_cairo_clip_path_reference),
(_cairo_clip_path_destroy), (_cairo_gstate_intersect_clip_region),
(_cairo_gstate_intersect_clip_mask), (_cairo_gstate_clip):
* src/cairo-pdf-surface.c:
(_cairo_pdf_surface_create_for_document),
(_cairo_pdf_path_move_to), (_cairo_pdf_path_line_to),
(_cairo_pdf_path_close_path), (_cairo_pdf_surface_fill_path),
(_cairo_pdf_surface_intersect_clip_path),
(_cairo_pdf_document_add_page):
* src/cairo-surface.c: (_cairo_surface_get_clip_mode),
(_cairo_surface_fill_path), (_cairo_surface_reset_clip),
(_cairo_surface_set_clip_path_recursive),
(_cairo_surface_set_clip_path):
* src/cairoint.h: Implement path clipping and refactor
_cairo_gstate_clip() out in three different functions
corresponding to the three different clipping modes.
* src/cairo-glitz-surface.c:
* src/cairo-ps-surface.c:
* src/cairo-win32-surface.c:
* src/cairo-xcb-surface.c:
* src/cairo-xlib-surface.c:
* src/cairo-image-surface.c:
* src/cairo-quartz-surface.c: Add NULL pointers for
intersect_clip_path.
* test/Makefile.am:
* test/pdf-clip.c: New test case to exercise PDF clipping code.
Index: cairo-glitz-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-glitz-surface.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- cairo-glitz-surface.c 14 Jun 2005 22:38:15 -0000 1.45
+++ cairo-glitz-surface.c 15 Jun 2005 02:45:23 -0000 1.46
@@ -2132,6 +2132,7 @@
NULL, /* copy_page */
NULL, /* show_page */
_cairo_glitz_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_glitz_surface_get_extents,
_cairo_glitz_surface_show_glyphs
};
Index: cairo-gstate-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate-private.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- cairo-gstate-private.h 3 Jun 2005 22:54:40 -0000 1.11
+++ cairo-gstate-private.h 15 Jun 2005 02:45:23 -0000 1.12
@@ -36,7 +36,19 @@
#ifndef CAIRO_GSTATE_PRIVATE_H
#define CAIRO_GSTATE_PRIVATE_H
+#include "cairo-path-fixed-private.h"
+
+struct _cairo_clip_path {
+ unsigned int ref_count;
+ cairo_path_fixed_t path;
+ cairo_fill_rule_t fill_rule;
+ double tolerance;
+ cairo_clip_path_t *prev;
+};
+
typedef struct _cairo_clip {
+ cairo_clip_mode_t mode;
+
/*
* Mask-based clipping for cases where the backend
* clipping isn't sufficiently able.
@@ -59,8 +71,10 @@
*/
pixman_region16_t *region;
/*
- * XXX add clip paths here
+ * If the surface supports path clipping, we store the list of
+ * clipping paths that has been set here as a linked list.
*/
+ cairo_clip_path_t *path;
} cairo_clip_t;
struct _cairo_gstate {
Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.141
retrieving revision 1.142
diff -u -d -r1.141 -r1.142
--- cairo-gstate.c 13 Jun 2005 23:36:40 -0000 1.141
+++ cairo-gstate.c 15 Jun 2005 02:45:23 -0000 1.142
@@ -70,6 +70,12 @@
static void
_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src);
+static void
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
+
cairo_gstate_t *
_cairo_gstate_create (cairo_surface_t *target)
{
@@ -116,9 +122,11 @@
CAIRO_GSTATE_DEFAULT_FONT_SIZE,
CAIRO_GSTATE_DEFAULT_FONT_SIZE);
+ gstate->clip.mode = _cairo_surface_get_clip_mode (target);
gstate->clip.region = NULL;
gstate->clip.surface = NULL;
gstate->clip.serial = 0;
+ gstate->clip.path = NULL;
_cairo_gstate_identity_matrix (gstate);
@@ -168,6 +176,7 @@
cairo_surface_reference (gstate->target);
cairo_surface_reference (gstate->clip.surface);
+ _cairo_clip_path_reference (gstate->clip.path);
cairo_pattern_reference (gstate->source);
@@ -205,6 +214,10 @@
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
+ if (gstate->clip.path)
+ _cairo_clip_path_destroy (gstate->clip.path);
+ gstate->clip.path = NULL;
+
if (gstate->clip.region)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
@@ -338,7 +351,10 @@
if (gstate->clip.serial == _cairo_surface_get_current_clip_serial (surface))
return CAIRO_STATUS_SUCCESS;
- /* check for path clipping here */
+ if (gstate->clip.path)
+ return _cairo_surface_set_clip_path (surface,
+ gstate->clip.path,
+ gstate->clip.serial);
if (gstate->clip.region)
return _cairo_surface_set_clip_region (surface,
@@ -1142,9 +1158,8 @@
if (num_rects > 1) {
- status = _cairo_surface_can_clip_region (gstate->target);
- if (status)
- return status;
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
clip_serial = _cairo_surface_allocate_clip_serial (gstate->target);
status = _cairo_surface_set_clip_region (gstate->target,
@@ -1438,7 +1453,9 @@
status = _cairo_surface_fill_path (gstate->operator,
gstate->source,
gstate->target,
- path);
+ path,
+ gstate->fill_rule,
+ gstate->tolerance);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -1583,83 +1600,124 @@
if (gstate->clip.region)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
+
+ if (gstate->clip.path)
+ _cairo_clip_path_destroy (gstate->clip.path);
+ gstate->clip.path = NULL;
+
gstate->clip.serial = 0;
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
+static cairo_status_t
+_cairo_gstate_intersect_clip_path (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path)
{
+ cairo_clip_path_t *clip_path;
cairo_status_t status;
- cairo_pattern_union_t pattern;
- cairo_traps_t traps;
- cairo_rectangle_t surface_rect;
- cairo_box_t extents;
- cairo_surface_t *surface;
- pixman_region16_t *region;
- /* Fill the clip region as traps. */
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_PATH)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- _cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
- if (status) {
- _cairo_traps_fini (&traps);
+ clip_path = malloc (sizeof (cairo_clip_path_t));
+ if (clip_path == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = _cairo_path_fixed_init_copy (&clip_path->path, path);
+ if (status)
return status;
- }
- status = _cairo_surface_can_clip_region (gstate->target);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
- if (status)
- return status;
-
- /* Check to see if we can represent these traps as a PixRegion. */
+ clip_path->ref_count = 1;
+ clip_path->fill_rule = gstate->fill_rule;
+ clip_path->tolerance = gstate->tolerance;
+ clip_path->prev = gstate->clip.path;
+ gstate->clip.path = clip_path;
+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (gstate->target);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
+{
+ if (clip_path == NULL)
+ return;
+
+ clip_path->ref_count++;
+}
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
+{
+ if (clip_path == NULL)
+ return;
+
+ clip_path->ref_count--;
+ if (clip_path->ref_count)
+ return;
+
+ _cairo_path_fixed_fini (&clip_path->path);
+ _cairo_clip_path_destroy (clip_path->prev);
+ free (clip_path);
+}
+
+static cairo_status_t
+_cairo_gstate_intersect_clip_region (cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
+{
+ pixman_region16_t *region;
+ cairo_status_t status;
+
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- status = _cairo_traps_extract_region (&traps, ®ion);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
+ status = _cairo_traps_extract_region (traps, ®ion);
+ if (status)
+ return status;
- if (region) {
- status = CAIRO_STATUS_SUCCESS;
-
- if (gstate->clip.region == NULL) {
- gstate->clip.region = region;
- } else {
- pixman_region16_t *intersection = pixman_region_create();
+ if (region == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = CAIRO_STATUS_SUCCESS;
+ if (gstate->clip.region == NULL) {
+ gstate->clip.region = region;
+ } else {
+ pixman_region16_t *intersection = pixman_region_create();
- if (pixman_region_intersect (intersection,
- gstate->clip.region, region)
- == PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (gstate->clip.region);
- gstate->clip.region = intersection;
- } else {
- status = CAIRO_STATUS_NO_MEMORY;
- }
- pixman_region_destroy (region);
- }
- gstate->clip.serial = _cairo_surface_allocate_clip_serial (gstate->target);
-
- _cairo_traps_fini (&traps);
-
- return status;
+ if (pixman_region_intersect (intersection,
+ gstate->clip.region, region)
+ == PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (gstate->clip.region);
+ gstate->clip.region = intersection;
+ } else {
+ status = CAIRO_STATUS_NO_MEMORY;
}
+ pixman_region_destroy (region);
}
+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (gstate->target);
+ return status;
+}
- /* Otherwise represent the clip as a mask surface. We create a
- * new surface the size of the intersection of the old mask
- * surface and the extents of the new clip path. */
+static cairo_status_t
+_cairo_gstate_intersect_clip_mask (cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
+{
+ cairo_pattern_union_t pattern;
+ cairo_box_t extents;
+ cairo_rectangle_t surface_rect;
+ cairo_surface_t *surface;
+ cairo_status_t status;
- if (gstate->clip.surface == NULL) {
- _cairo_traps_extents (&traps, &extents);
- _cairo_box_round_to_rectangle (&extents, &surface_rect);
- } else {
- _cairo_traps_extents (&traps, &extents);
- _cairo_box_round_to_rectangle (&extents, &surface_rect);
+ /* Represent the clip as a mask surface. We create a new surface
+ * the size of the intersection of the old mask surface and the
+ * extents of the new clip path. */
+
+ _cairo_traps_extents (traps, &extents);
+ _cairo_box_round_to_rectangle (&extents, &surface_rect);
+
+ if (gstate->clip.surface != NULL)
_cairo_rectangle_intersect (&surface_rect, &gstate->clip.surface_rect);
- }
surface = _cairo_surface_create_similar_solid (gstate->target,
CAIRO_FORMAT_A8,
@@ -1671,7 +1729,7 @@
/* Render the new clipping path into the new mask surface. */
- translate_traps (&traps, -surface_rect.x, -surface_rect.y);
+ translate_traps (traps, -surface_rect.x, -surface_rect.y);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
@@ -1681,11 +1739,10 @@
0, 0,
surface_rect.width,
surface_rect.height,
- traps.traps,
- traps.num_traps);
+ traps->traps,
+ traps->num_traps);
_cairo_pattern_fini (&pattern.base);
- _cairo_traps_fini (&traps);
if (status) {
cairo_surface_destroy (surface);
@@ -1723,7 +1780,34 @@
gstate->clip.surface = surface;
gstate->clip.surface_rect = surface_rect;
- return CAIRO_STATUS_SUCCESS;
+ return status;
+}
+
+cairo_status_t
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
+{
+ cairo_status_t status;
+ cairo_traps_t traps;
+
+ status = _cairo_gstate_intersect_clip_path (gstate, path);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ _cairo_traps_init (&traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ if (status)
+ goto bail;
+
+ status = _cairo_gstate_intersect_clip_region (gstate, &traps);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto bail;
+
+ status = _cairo_gstate_intersect_clip_mask (gstate, &traps);
+
+ bail:
+ _cairo_traps_fini (&traps);
+
+ return status;
}
static void
Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- cairo-image-surface.c 14 Jun 2005 22:38:15 -0000 1.45
+++ cairo-image-surface.c 15 Jun 2005 02:45:23 -0000 1.46
@@ -713,6 +713,7 @@
NULL, /* copy_page */
NULL, /* show_page */
_cairo_image_abstract_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_image_abstract_surface_get_extents,
NULL /* show_glyphs */
};
Index: cairo-pdf-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pdf-surface.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- cairo-pdf-surface.c 14 Jun 2005 22:38:15 -0000 1.45
+++ cairo-pdf-surface.c 15 Jun 2005 02:45:23 -0000 1.46
@@ -188,6 +188,7 @@
cairo_array_t streams;
cairo_array_t alphas;
cairo_array_t fonts;
+ cairo_bool_t has_clip;
};
#define DEFAULT_DPI 300
@@ -989,6 +990,7 @@
_cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->alphas, sizeof (double));
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_resource_t));
+ surface->has_clip = FALSE;
return &surface->base;
}
@@ -1638,6 +1640,7 @@
typedef struct
{
cairo_output_stream_t *output_stream;
+ cairo_bool_t has_current_point;
} pdf_path_info_t;
static cairo_status_t
@@ -1649,6 +1652,7 @@
"%f %f m ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
+ info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1657,11 +1661,19 @@
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
+ const char *pdf_operator;
+
+ if (info->has_current_point)
+ pdf_operator = "l";
+ else
+ pdf_operator = "m";
_cairo_output_stream_printf (info->output_stream,
- "%f %f l ",
+ "%f %f %s ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y));
+ _cairo_fixed_to_double (point->y),
+ pdf_operator);
+ info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1693,6 +1705,7 @@
_cairo_output_stream_printf (info->output_stream,
"h\r\n");
+ info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1701,15 +1714,16 @@
_cairo_pdf_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
- cairo_path_fixed_t *path)
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
{
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_document_t *document = surface->document;
+ const char *pdf_operator;
cairo_status_t status;
pdf_path_info_t info;
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
emit_pattern (surface, pattern);
/* After the above switch the current stream should belong to this
@@ -1718,6 +1732,7 @@
document->current_stream == surface->current_stream);
info.output_stream = document->output_stream;
+ info.has_current_point = FALSE;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -1727,8 +1742,20 @@
_cairo_pdf_path_close_path,
&info);
+ switch (fill_rule) {
+ case CAIRO_FILL_RULE_WINDING:
+ pdf_operator = "f";
+ break;
+ case CAIRO_FILL_RULE_EVEN_ODD:
+ pdf_operator = "f*";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
_cairo_output_stream_printf (document->output_stream,
- "f\r\n");
+ "%s\r\n",
+ pdf_operator);
return status;
}
@@ -1905,6 +1932,62 @@
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_pdf_surface_intersect_clip_path (void *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
+{
+ cairo_pdf_surface_t *surface = dst;
+ cairo_pdf_document_t *document = surface->document;
+ cairo_output_stream_t *output = document->output_stream;
+ cairo_status_t status;
+ pdf_path_info_t info;
+ const char *pdf_operator;
+
+ _cairo_pdf_surface_ensure_stream (surface);
+
+ if (path == NULL) {
+ if (surface->has_clip)
+ _cairo_output_stream_printf (output, "Q\r\n");
+ surface->has_clip = FALSE;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (!surface->has_clip) {
+ _cairo_output_stream_printf (output, "q ");
+ surface->has_clip = TRUE;
+ }
+
+ info.output_stream = document->output_stream;
+ info.has_current_point = FALSE;
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
+ &info);
+
+ switch (fill_rule) {
+ case CAIRO_FILL_RULE_WINDING:
+ pdf_operator = "W";
+ break;
+ case CAIRO_FILL_RULE_EVEN_ODD:
+ pdf_operator = "W*";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ _cairo_output_stream_printf (document->output_stream,
+ "%s n\r\n",
+ pdf_operator);
+
+ return status;
+}
+
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
@@ -1919,6 +2002,7 @@
_cairo_pdf_surface_copy_page,
_cairo_pdf_surface_show_page,
NULL, /* set_clip_region */
+ _cairo_pdf_surface_intersect_clip_path,
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs,
_cairo_pdf_surface_fill_path
@@ -2237,6 +2321,11 @@
assert (!document->finished);
+ _cairo_pdf_surface_ensure_stream (surface);
+
+ if (surface->has_clip)
+ _cairo_output_stream_printf (output, "Q\r\n");
+
_cairo_pdf_document_close_stream (document);
page_id = _cairo_pdf_document_new_object (document);
Index: cairo-ps-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ps-surface.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- cairo-ps-surface.c 14 Jun 2005 22:38:15 -0000 1.36
+++ cairo-ps-surface.c 15 Jun 2005 02:45:23 -0000 1.37
@@ -372,6 +372,7 @@
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_ps_surface_get_extents,
NULL /* show_glyphs */
};
Index: cairo-quartz-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-quartz-surface.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- cairo-quartz-surface.c 14 Jun 2005 22:38:15 -0000 1.11
+++ cairo-quartz-surface.c 15 Jun 2005 02:45:23 -0000 1.12
@@ -226,6 +226,7 @@
NULL, /* copy_page */
NULL, /* show_page */
_cairo_quartz_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_quartz_surface_get_extents,
NULL /* show_glyphs */
};
Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- cairo-surface.c 14 Jun 2005 22:38:15 -0000 1.73
+++ cairo-surface.c 15 Jun 2005 02:45:23 -0000 1.74
@@ -38,7 +38,7 @@
#include <stdlib.h>
#include "cairoint.h"
-
+#include "cairo-gstate-private.h"
void
_cairo_surface_init (cairo_surface_t *surface,
@@ -115,6 +115,17 @@
return surface;
}
+cairo_clip_mode_t
+_cairo_surface_get_clip_mode (cairo_surface_t *surface)
+{
+ if (surface->backend->intersect_clip_path != NULL)
+ return CAIRO_CLIP_MODE_PATH;
+ else if (surface->backend->set_clip_region != NULL)
+ return CAIRO_CLIP_MODE_REGION;
+ else
+ return CAIRO_CLIP_MODE_MASK;
+}
+
void
cairo_surface_reference (cairo_surface_t *surface)
{
@@ -644,13 +655,16 @@
}
cairo_private cairo_int_status_t
-_cairo_surface_fill_path (cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *dst,
- cairo_path_fixed_t *path)
+_cairo_surface_fill_path (cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
{
if (dst->backend->fill_path)
- return dst->backend->fill_path (operator, pattern, dst, path);
+ return dst->backend->fill_path (operator, pattern, dst, path,
+ fill_rule, tolerance);
else
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -837,13 +851,16 @@
return CAIRO_STATUS_SURFACE_FINISHED;
surface->current_clip_serial = 0;
-#if 0
- if (surface->backend->clip_path) {
- status = surface->backend->clip_path (surface, NULL);
+
+ if (surface->backend->intersect_clip_path) {
+ status = surface->backend->intersect_clip_path (surface,
+ NULL,
+ CAIRO_FILL_RULE_WINDING,
+ 0);
if (status)
return status;
}
-#endif
+
if (surface->backend->set_clip_region != NULL) {
status = surface->backend->set_clip_region (surface, NULL);
if (status)
@@ -853,23 +870,6 @@
}
/**
- * _cairo_surface_can_clip_region:
- * @surface: the #cairo_surface_t to check for region clipping support
- *
- * This function checks whether the specified surface can
- * support region-based clipping.
- */
-cairo_private cairo_status_t
-_cairo_surface_can_clip_region (cairo_surface_t *surface)
-{
- if (surface->finished)
- return CAIRO_STATUS_SURFACE_FINISHED;
- if (surface->backend->set_clip_region == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- return CAIRO_STATUS_SUCCESS;
-}
-
-/**
* _cairo_surface_set_clip_region:
* @surface: the #cairo_surface_t to reset the clip on
* @region: the #pixman_region16_t to use for clipping
@@ -893,22 +893,64 @@
return surface->backend->set_clip_region (surface, region);
}
-#if 0
-/* new interfaces for path-based clipping */
-cairo_private cairo_status_t
-_cairo_surface_can_clip_path (cairo_surface_t *surface)
+static cairo_status_t
+_cairo_surface_set_clip_path_recursive (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path)
{
+ cairo_status_t status;
+
+ if (clip_path == NULL)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_surface_set_clip_path_recursive (surface, clip_path->prev);
+ if (status)
+ return status;
+
+ return surface->backend->intersect_clip_path (surface,
+ &clip_path->path,
+ clip_path->fill_rule,
+ clip_path->tolerance);
}
+
+/**
+ * _cairo_surface_set_clip_path:
+ * @surface: the #cairo_surface_t to reset the clip on
+ * @path: the path to intersect against the current clipping path
+ * @fill_rule: fill rule to use for clipping
+ * @tolerance: tesselation to use for tesselating clipping path
+ * @serial: the clip serial number associated with the region
+ *
+ * Sets the clipping path to be the intersection of the current
+ * clipping path of the surface and the given path.
+ **/
cairo_private cairo_status_t
-_cairo_surface_clip_path (cairo_surface_t *surface,
- cairo_path_fixed_t *path,
- unsigned int serial)
+_cairo_surface_set_clip_path (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path,
+ unsigned int serial)
{
- surface->current_clip_serial = clip_serial;
- return surface->backend->clip_path (surface, path);
+ cairo_status_t status;
+
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
+ assert (surface->backend->intersect_clip_path != NULL);
+
+ status = surface->backend->intersect_clip_path (surface,
+ NULL,
+ CAIRO_FILL_RULE_WINDING,
+ 0);
+ if (status)
+ return status;
+
+ status = _cairo_surface_set_clip_path_recursive (surface, clip_path);
+ if (status)
+ return status;
+
+ surface->current_clip_serial = serial;
+
+ return CAIRO_STATUS_SUCCESS;
}
-#endif
/**
* _cairo_surface_get_extents:
Index: cairo-win32-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-win32-surface.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- cairo-win32-surface.c 14 Jun 2005 22:38:15 -0000 1.25
+++ cairo-win32-surface.c 15 Jun 2005 02:45:23 -0000 1.26
@@ -941,6 +941,7 @@
NULL, /* copy_page */
NULL, /* show_page */
_cairo_win32_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_win32_surface_get_extents,
NULL /* show_glyphs */
};
Index: cairo-xcb-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xcb-surface.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- cairo-xcb-surface.c 14 Jun 2005 22:38:15 -0000 1.35
+++ cairo-xcb-surface.c 15 Jun 2005 02:45:23 -0000 1.36
@@ -1012,6 +1012,7 @@
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* _cairo_xcb_surface_set_clip_region */
+ NULL, /* intersect_clip_path */
_cairo_xcb_surface_get_extents,
NULL /* show_glyphs */
};
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- cairo-xlib-surface.c 14 Jun 2005 22:38:15 -0000 1.78
+++ cairo-xlib-surface.c 15 Jun 2005 02:45:23 -0000 1.79
@@ -1046,6 +1046,7 @@
NULL, /* copy_page */
NULL, /* show_page */
_cairo_xlib_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_xlib_surface_get_extents,
_cairo_xlib_surface_show_glyphs
};
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.154
retrieving revision 1.155
diff -u -d -r1.154 -r1.155
--- cairoint.h 14 Jun 2005 22:38:15 -0000 1.154
+++ cairoint.h 15 Jun 2005 02:45:23 -0000 1.155
@@ -642,10 +642,43 @@
cairo_int_status_t
(*show_page) (void *surface);
+ /* Set given region as the clip region for the surface, replacing
+ * any previously set clip region. Passing in a NULL region will
+ * clear the surface clip region.
+ *
+ * The surface is expected to store the clip region and clip all
+ * following drawing operations against it until the clip region
+ * is cleared of replaced by another clip region.
+ *
+ * Cairo will call this function whenever a clip path can be
+ * represented as a device pixel aligned set of rectangles. When
+ * this is not possible, cairo will use mask surfaces for
+ * clipping.
+ */
cairo_int_status_t
(*set_clip_region) (void *surface,
pixman_region16_t *region);
+ /* Intersect the given path against the clip path currently set in
+ * the surface, using the given fill_rule and tolerance, and set
+ * the result as the new clipping path for the surface. Passing
+ * in a NULL path will clear the surface clipping path.
+ *
+ * The surface is expected to store the resulting clip path and
+ * clip all following drawing operations against it until the clip
+ * path cleared or intersected with a new path.
+ *
+ * If a surface implements this function, set_clip_region() will
+ * never be called and should not be implemented. If this
+ * function is not implemented cairo will use set_clip_region()
+ * (if available) and mask surfaces for clipping.
+ */
+ cairo_int_status_t
+ (*intersect_clip_path) (void *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
+
/* 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}.
@@ -683,7 +716,9 @@
(*fill_path) (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *dst,
- cairo_path_fixed_t *path);
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
} cairo_surface_backend_t;
@@ -695,6 +730,12 @@
unsigned long blue_mask;
} cairo_format_masks_t;
+typedef enum _cairo_clip_mode {
+ CAIRO_CLIP_MODE_PATH,
+ CAIRO_CLIP_MODE_REGION,
+ CAIRO_CLIP_MODE_MASK
+} cairo_clip_mode_t;
+
struct _cairo_surface {
const cairo_surface_backend_t *backend;
@@ -1381,6 +1422,9 @@
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend);
+cairo_private cairo_clip_mode_t
+_cairo_surface_get_clip_mode (cairo_surface_t *surface);
+
cairo_private cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
@@ -1412,10 +1456,12 @@
int num_rects);
cairo_private cairo_int_status_t
-_cairo_surface_fill_path (cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *dst,
- cairo_path_fixed_t *path);
+_cairo_surface_fill_path (cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
cairo_private cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
@@ -1475,23 +1521,16 @@
_cairo_surface_reset_clip (cairo_surface_t *surface);
cairo_private cairo_status_t
-_cairo_surface_can_clip_region (cairo_surface_t *surface);
-
-cairo_private cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface,
pixman_region16_t *region,
unsigned int serial);
-#if 0
-/* new interfaces for path-based clipping */
-cairo_private cairo_status_t
-_cairo_surface_can_clip_path (cairo_surface_t *surface);
+typedef struct _cairo_clip_path cairo_clip_path_t;
cairo_private cairo_status_t
-_cairo_surface_clip_path (cairo_surface_t *surface,
- cairo_path_fixed_t *path,
- unsigned int serial);
-#endif
+_cairo_surface_set_clip_path (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path,
+ unsigned int serial);
cairo_private cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
More information about the cairo-commit
mailing list