commit 857df0583365228150b3319475efc43b22077d06
Author: Jeff Muizelaar <jmuizelaar@mozilla.com>
Date:   Tue Apr 20 15:43:54 2010 -0400

    native clipping

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index df063bf..819e53e 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -39,6 +39,8 @@
 
 #include "cairo-quartz-private.h"
 #include "cairo-surface-clipper-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-private.h"
 
 #include <dlfcn.h>
 
@@ -3095,6 +3097,61 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface)
     return quartz->cgContext;
 }
 
+CGContextRef
+cairo_quartz_get_cg_context_with_clip (cairo_t *cr)
+{
+
+    cairo_surface_t *surface = cr->gstate->target;
+    cairo_clip_t *clip = &cr->gstate->clip;
+    cairo_status_t status;
+
+    cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface;
+
+    if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ)
+	return NULL;
+
+    if (!clip->path) {
+	if (clip->all_clipped) {
+	    /* Save the state before we set an empty clip rect so that
+	     * our previous clip will be restored */
+	    CGContextSaveGState (quartz->cgContext);
+
+	    /* _cairo_surface_clipper_set_clip doesn't deal with
+	     * clip->all_clipped because drawing is normally discarded earlier */
+	    CGRect empty = {{0,0}, {0,0}};
+	    CGContextClipToRect (quartz->cgContext, empty);
+
+	    return quartz->cgContext;
+	}
+
+	/* an empty clip is represented by NULL */
+	clip = NULL;
+    }
+
+    status = _cairo_surface_clipper_set_clip (&quartz->clipper, clip);
+
+    /* Save the state after we set the clip so that it persists
+     * after we restore */
+    CGContextSaveGState (quartz->cgContext);
+
+    if (unlikely (status))
+	return NULL;
+
+    return quartz->cgContext;
+}
+
+void
+cairo_quartz_finish_cg_context_with_clip (cairo_t *cr)
+{
+    cairo_surface_t *surface = cr->gstate->target;
+
+    cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface;
+
+    if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ)
+	return;
+
+    CGContextRestoreGState (quartz->cgContext);
+}
 
 /* Debug stuff */
 
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index e8b71ba..aa1cdd2 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -57,6 +57,12 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
 cairo_public CGContextRef
 cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
 
+cairo_public CGContextRef
+cairo_quartz_get_cg_context_with_clip (cairo_t *cr);
+
+cairo_public void
+cairo_quartz_finish_cg_context_with_clip (cairo_t *cr);
+
 #if CAIRO_HAS_QUARTZ_FONT
 
 /*
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index d4575a3..c10e134 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -52,7 +52,9 @@
 #include "cairo-win32-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-surface-fallback-private.h"
-
+#include "cairo-surface-clipper-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-private.h"
 #include <wchar.h>
 #include <windows.h>
 
@@ -1914,6 +1916,61 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
     return NULL;
 }
 
+
+HDC
+cairo_win32_get_dc_with_clip (cairo_t *cr)
+{
+    cairo_surface_t *surface = cr->gstate->target;
+    cairo_clip_t clip;
+    _cairo_clip_init_copy(&clip, &cr->gstate->clip);
+
+    if (_cairo_surface_is_win32 (surface)){
+	cairo_win32_surface_t *winsurf = (cairo_win32_surface_t *) surface;
+	cairo_region_t *clip_region = NULL;
+	cairo_status_t status;
+
+	if (clip.path) {
+	    status = _cairo_clip_get_region (&clip, &clip_region);
+	    assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
+	    if (status) {
+		_cairo_clip_fini(&clip);
+		return NULL;
+	    }
+	}
+	_cairo_win32_surface_set_clip_region (winsurf, clip_region);
+
+	_cairo_clip_fini(&clip);
+	return winsurf->dc;
+    }
+
+    if (_cairo_surface_is_paginated (surface)) {
+	cairo_surface_t *target;
+
+	target = _cairo_paginated_surface_get_target (surface);
+
+#ifndef CAIRO_OMIT_WIN32_PRINTING
+	if (_cairo_surface_is_win32_printing (target)) {
+	    cairo_status_t status;
+	    cairo_win32_surface_t *winsurf = (cairo_win32_surface_t *) target;
+
+	    status = _cairo_surface_clipper_set_clip (&winsurf->clipper, &clip);
+
+	    _cairo_clip_fini(&clip);
+
+	    if (status)
+		return NULL;
+
+	    return winsurf->dc;
+	}
+#endif
+    }
+
+    _cairo_clip_fini(&clip);
+    return NULL;
+}
+
+
+
 /**
  * cairo_win32_surface_get_image
  * @surface: a #cairo_surface_t
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 7d04d2a..c304f92 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -65,6 +65,9 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
 cairo_public HDC
 cairo_win32_surface_get_dc (cairo_surface_t *surface);
 
+cairo_public HDC
+cairo_win32_get_dc_with_clip (cairo_t *cr);
+
 cairo_public cairo_surface_t *
 cairo_win32_surface_get_image (cairo_surface_t *surface);
 
