Bug 814828. DEST_OUT has no affect outside the source; r=bas
authorNicholas Cameron <ncameron@mozilla.com>
Wed, 05 Dec 2012 13:02:52 +1300
changeset 120555 e5e6d25fdc572cbff5a66a40094ca093c478e8c2
parent 120554 5d321d9cd977968969c4a8592f03d35b4e3d191a
child 120556 e9bfe1b6ab083c86f0c931d0fec8dfa5a6265b99
push idunknown
push userunknown
push dateunknown
reviewersbas
bugs814828
milestone20.0a1
Bug 814828. DEST_OUT has no affect outside the source; r=bas
gfx/2d/DrawTargetCairo.cpp
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -271,31 +271,16 @@ GfxPatternToCairoPattern(const Pattern& 
       // We should support all pattern types!
       MOZ_ASSERT(false);
     }
   }
 
   return pat;
 }
 
-/**
- * Returns true iff the the given operator should affect areas of the
- * destination where the source is transparent. Among other things, this
- * implies that a fully transparent source would still affect the canvas.
- */
-static bool
-OperatorAffectsUncoveredAreas(CompositionOp op)
-{
-  return op == OP_IN ||
-         op == OP_OUT ||
-         op == OP_DEST_IN ||
-         op == OP_DEST_ATOP ||
-         op == OP_DEST_OUT;
-}
-
 static bool
 NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
 {
   // We pre-multiply colours' alpha by the global alpha, so we don't need to
   // use an intermediate surface for them.
   if (aPattern.GetType() == PATTERN_COLOR)
     return false;
 
@@ -380,29 +365,28 @@ DrawTargetCairo::DrawSurface(SourceSurfa
   cairo_surface_destroy(surf);
 
   cairo_pattern_set_matrix(pat, &src_mat);
   cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
   cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_translate(mContext, aDest.X(), aDest.Y());
 
-  if (OperatorAffectsUncoveredAreas(aOptions.mCompositionOp) ||
-      aOptions.mCompositionOp == OP_SOURCE) {
+  if (IsOperatorBoundByMask(aOptions.mCompositionOp)) {
+    cairo_new_path(mContext);
+    cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
+    cairo_clip(mContext);
+    cairo_set_source(mContext, pat);
+  } else {
     cairo_push_group(mContext);
       cairo_new_path(mContext);
       cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
       cairo_set_source(mContext, pat);
       cairo_fill(mContext);
     cairo_pop_group_to_source(mContext);
-  } else {
-    cairo_new_path(mContext);
-    cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
-    cairo_clip(mContext);
-    cairo_set_source(mContext, pat);
   }
 
   cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
   cairo_paint_with_alpha(mContext, aOptions.mAlpha);
 
   cairo_pattern_destroy(pat);
 }
@@ -448,38 +432,37 @@ DrawTargetCairo::DrawSurfaceWithShadow(S
   WillChange();
   ClearSurfaceForUnboundedSource(aOperator);
 
   cairo_save(mContext);
   cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
 
-  if (OperatorAffectsUncoveredAreas(aOperator) ||
-      aOperator == OP_SOURCE){
+  if (IsOperatorBoundByMask(aOperator)){
+    cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
+    cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
+
+    // Now that the shadow has been drawn, we can draw the surface on top.
+    cairo_set_source_surface(mContext, surf, 0, 0);
+    cairo_new_path(mContext);
+    cairo_rectangle(mContext, 0, 0, width, height);
+    cairo_fill(mContext);
+  } else {
     cairo_push_group(mContext);
       cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
       cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
 
       // Now that the shadow has been drawn, we can draw the surface on top.
       cairo_set_source_surface(mContext, surf, 0, 0);
       cairo_new_path(mContext);
       cairo_rectangle(mContext, 0, 0, width, height);
       cairo_fill(mContext);
     cairo_pop_group_to_source(mContext);
     cairo_paint(mContext);
-  } else {
-    cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
-    cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
-
-    // Now that the shadow has been drawn, we can draw the surface on top.
-    cairo_set_source_surface(mContext, surf, 0, 0);
-    cairo_new_path(mContext);
-    cairo_rectangle(mContext, 0, 0, width, height);
-    cairo_fill(mContext);
   }
 
   cairo_restore(mContext);
 }
 
 void
 DrawTargetCairo::DrawPattern(const Pattern& aPattern,
                              const StrokeOptions& aStrokeOptions,
@@ -489,17 +472,17 @@ DrawTargetCairo::DrawPattern(const Patte
   if (!PatternIsCompatible(aPattern)) {
     return;
   }
 
   cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
   cairo_set_source(mContext, pat);
 
   if (NeedIntermediateSurface(aPattern, aOptions) ||
-      OperatorAffectsUncoveredAreas(aOptions.mCompositionOp)) {
+      !IsOperatorBoundByMask(aOptions.mCompositionOp)) {
     cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
 
     ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
 
     // Don't want operators to be applied twice
     cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
 
     if (aDrawType == DRAW_STROKE) {