mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 562334. cairo: Fix cairo_quartz_get_cg_context_with_clip. r=vlad
A problem happens when clip->all_clipped is set and we go to get a clipped context. Normally backends don't see operations with clip->all_clipped and so _cairo_surface_clipper_set_clip is designed with the assumption that clip->all_clipped is never true. I added a work-around by manually setting the CGContextClip with an empty rectangle, however this caused cairo to be confused about what the actual clip was. This patch fixes the problem by adding a new function cairo_quartz_finish_cg_context_with_clip that is called after we're done with the native context. It moves the CGContextSave/RestoreGState calls out of gfxNativeDrawing into cairo and uses them to ensure that the clip remains consistent with cairo's model of them.
This commit is contained in:
parent
ef1655d6e9
commit
c6adb55bed
@ -3112,10 +3112,14 @@ cairo_quartz_get_cg_context_with_clip (cairo_t *cr)
|
||||
|
||||
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 */
|
||||
|
||||
/* _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);
|
||||
CGContextSaveGState (quartz->cgContext);
|
||||
|
||||
return quartz->cgContext;
|
||||
}
|
||||
@ -3125,13 +3129,29 @@ cairo_quartz_get_cg_context_with_clip (cairo_t *cr)
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -60,6 +60,9 @@ 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
|
||||
|
||||
/*
|
||||
|
@ -1,11 +1,11 @@
|
||||
commit 59038972ece5b3f6754ba8e46ce63718931fa415
|
||||
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..14e4092 100644
|
||||
index df063bf..819e53e 100644
|
||||
--- a/src/cairo-quartz-surface.c
|
||||
+++ b/src/cairo-quartz-surface.c
|
||||
@@ -39,6 +39,8 @@
|
||||
@ -17,7 +17,7 @@ index df063bf..14e4092 100644
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -3095,6 +3097,41 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface)
|
||||
@@ -3095,6 +3097,61 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface)
|
||||
return quartz->cgContext;
|
||||
}
|
||||
|
||||
@ -36,10 +36,14 @@ index df063bf..14e4092 100644
|
||||
+
|
||||
+ 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 */
|
||||
+
|
||||
+ /* _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);
|
||||
+ CGContextSaveGState (quartz->cgContext);
|
||||
+
|
||||
+ return quartz->cgContext;
|
||||
+ }
|
||||
@ -49,26 +53,45 @@ index df063bf..14e4092 100644
|
||||
+ }
|
||||
+
|
||||
+ 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..7117987 100644
|
||||
index e8b71ba..aa1cdd2 100644
|
||||
--- a/src/cairo-quartz.h
|
||||
+++ b/src/cairo-quartz.h
|
||||
@@ -57,6 +57,9 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
|
||||
@@ -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
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include "gfxQuartzNativeDrawing.h"
|
||||
#include "gfxQuartzSurface.h"
|
||||
|
||||
#include "cairo-quartz.h"
|
||||
// see cairo-quartz-surface.c for the complete list of these
|
||||
enum {
|
||||
kPrivateCGCompositeSourceOver = 2
|
||||
@ -83,12 +83,11 @@ gfxQuartzNativeDrawing::BeginNativeDrawing()
|
||||
}
|
||||
|
||||
// grab the CGContextRef
|
||||
mCGContext = mQuartzSurface->GetCGContextWithClip(mContext);
|
||||
mCGContext = cairo_quartz_get_cg_context_with_clip(mContext->GetCairo());
|
||||
if (!mCGContext)
|
||||
return nsnull;
|
||||
|
||||
gfxMatrix m = mContext->CurrentMatrix();
|
||||
CGContextSaveGState(mCGContext);
|
||||
CGContextTranslateCTM(mCGContext, deviceOffset.x, deviceOffset.y);
|
||||
|
||||
// I -think- that this context will always have an identity
|
||||
@ -121,8 +120,7 @@ gfxQuartzNativeDrawing::EndNativeDrawing()
|
||||
{
|
||||
NS_ASSERTION(mQuartzSurface, "EndNativeDrawing called without BeginNativeDrawing");
|
||||
|
||||
// we drew directly to a shared CGContextRef; restore previous context state
|
||||
CGContextRestoreGState(mCGContext);
|
||||
cairo_quartz_finish_cg_context_with_clip(mContext->GetCairo());
|
||||
mQuartzSurface->MarkDirty();
|
||||
mQuartzSurface = nsnull;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user