gecko-dev/gfx/cairo/cairo-win32-clip.patch

236 lines
7.1 KiB
Diff

Index: cairo-glitz/src/cairo-surface.c
===================================================================
--- cairo-glitz.orig/src/cairo-surface.c
+++ cairo-glitz/src/cairo-surface.c
@@ -502,6 +502,10 @@ cairo_surface_mark_dirty (cairo_surface_
* Like cairo_surface_mark_dirty(), but drawing has been done only to
* the specified rectangle, so that cairo can retain cached contents
* for other parts of the surface.
+ *
+ * Any cached clip set on the surface will be reset by this function,
+ * to make sure that future cairo calls have the clip set that they
+ * expect.
*/
void
cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
@@ -520,6 +524,12 @@ cairo_surface_mark_dirty_rectangle (cair
return;
}
+ /* Always reset the clip here, to avoid having a SaveDC/RestoreDC around
+ * cairo calls that update the surface clip resulting in a desync between
+ * the cairo clip and the backend clip.
+ */
+ surface->current_clip_serial = -1;
+
if (surface->backend->mark_dirty_rectangle) {
cairo_status_t status;
@@ -1329,6 +1339,12 @@ _cairo_surface_set_clip (cairo_surface_t
if (!surface)
return CAIRO_STATUS_NULL_POINTER;
+ if (surface->status)
+ return surface->status;
+
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+
if (clip) {
serial = clip->serial;
if (serial == 0)
@@ -1336,7 +1352,7 @@ _cairo_surface_set_clip (cairo_surface_t
}
surface->clip = clip;
-
+
if (serial == _cairo_surface_get_current_clip_serial (surface))
return CAIRO_STATUS_SUCCESS;
Index: cairo-glitz/src/cairo-win32-private.h
===================================================================
--- cairo-glitz.orig/src/cairo-win32-private.h
+++ cairo-glitz/src/cairo-win32-private.h
@@ -62,9 +62,9 @@ typedef struct _cairo_win32_surface {
cairo_rectangle_t clip_rect;
- int set_clip;
HRGN saved_clip;
+ cairo_rectangle_t extents;
} cairo_win32_surface_t;
cairo_status_t
Index: cairo-glitz/src/cairo-win32-surface.c
===================================================================
--- cairo-glitz.orig/src/cairo-win32-surface.c
+++ cairo-glitz/src/cairo-win32-surface.c
@@ -274,9 +274,14 @@ _cairo_win32_surface_create_for_dc (HDC
surface->clip_rect.width = width;
surface->clip_rect.height = height;
- surface->set_clip = 0;
- surface->saved_clip = NULL;
-
+ surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
+ if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
+ DeleteObject(surface->saved_clip);
+ surface->saved_clip = NULL;
+ }
+
+ surface->extents = surface->clip_rect;
+
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
return (cairo_surface_t *)surface;
@@ -340,9 +345,8 @@ _cairo_win32_surface_finish (void *abstr
if (surface->image)
cairo_surface_destroy (surface->image);
- if (surface->saved_clip) {
+ if (surface->saved_clip)
DeleteObject (surface->saved_clip);
- }
/* If we created the Bitmap and DC, destroy them */
if (surface->bitmap) {
@@ -403,7 +407,7 @@ _cairo_win32_surface_acquire_source_imag
cairo_win32_surface_t *surface = abstract_surface;
cairo_win32_surface_t *local = NULL;
cairo_status_t status;
-
+
if (surface->image) {
*image_out = (cairo_image_surface_t *)surface->image;
*image_extra = NULL;
@@ -446,7 +450,7 @@ _cairo_win32_surface_acquire_dest_image
cairo_status_t status;
RECT clip_box;
int x1, y1, x2, y2;
-
+
if (surface->image) {
image_rect->x = 0;
image_rect->y = 0;
@@ -461,12 +465,12 @@ _cairo_win32_surface_acquire_dest_image
if (GetClipBox (surface->dc, &clip_box) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
-
+
x1 = clip_box.left;
x2 = clip_box.right;
y1 = clip_box.top;
y2 = clip_box.bottom;
-
+
if (interest_rect->x > x1)
x1 = interest_rect->x;
if (interest_rect->y > y1)
@@ -855,19 +859,9 @@ _cairo_win32_surface_set_clip_region (vo
if (region == NULL) {
/* Clear any clip set by cairo, return to the original */
-
- if (surface->set_clip) {
- if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
- return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
-
- if (surface->saved_clip) {
- DeleteObject (surface->saved_clip);
- surface->saved_clip = NULL;
- }
+ if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
+ return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");
- surface->set_clip = 0;
- }
-
return CAIRO_STATUS_SUCCESS;
} else {
@@ -910,36 +904,16 @@ _cairo_win32_surface_set_clip_region (vo
if (!gdi_region)
return CAIRO_STATUS_NO_MEMORY;
- if (surface->set_clip) {
- /* Combine the new region with the original clip */
+ /* Combine the new region with the original clip */
- if (surface->saved_clip) {
- if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
- goto FAIL;
- }
-
- if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
+ if (surface->saved_clip) {
+ if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
goto FAIL;
-
- } else {
- /* Save the the current region */
-
- surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
- if (!surface->saved_clip) {
- goto FAIL; }
-
- /* This function has no error return! */
- if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { /* No clip */
- DeleteObject (surface->saved_clip);
- surface->saved_clip = NULL;
- }
-
- if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
- goto FAIL;
-
- surface->set_clip = 1;
}
+ if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
+ goto FAIL;
+
DeleteObject (gdi_region);
return CAIRO_STATUS_SUCCESS;
@@ -955,15 +929,8 @@ _cairo_win32_surface_get_extents (void
cairo_rectangle_t *rectangle)
{
cairo_win32_surface_t *surface = abstract_surface;
- 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;
+ *rectangle = surface->extents;
return CAIRO_STATUS_SUCCESS;
}
@@ -1007,8 +974,19 @@ cairo_win32_surface_create (HDC hdc)
surface->clip_rect.width = rect.right - rect.left;
surface->clip_rect.height = rect.bottom - rect.top;
- surface->set_clip = 0;
- surface->saved_clip = NULL;
+ if (surface->clip_rect.width == 0 ||
+ surface->clip_rect.height == 0)
+ {
+ surface->saved_clip = NULL;
+ } else {
+ surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
+ if (GetClipRgn (hdc, surface->saved_clip) == 0) {
+ DeleteObject(surface->saved_clip);
+ surface->saved_clip = NULL;
+ }
+ }
+
+ surface->extents = surface->clip_rect;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);