Bug 1245499 - Composite mask only if has drawable mask source. draft
authorCJKu <cku@mozilla.com>
Wed, 24 Feb 2016 01:50:28 +0800
changeset 333407 79a3e3041dcfe2964f46348707f0aaf67cd23537
parent 333406 2b7880d173e8522f0be9d771c29d9156600d7ebe
child 514736 69d6c90d5f7f62ea4e0cc2f01f05f7e63df0d1af
push id11355
push usercku@mozilla.com
push dateTue, 23 Feb 2016 17:51:02 +0000
bugs1245499
milestone47.0a1
Bug 1245499 - Composite mask only if has drawable mask source. MozReview-Commit-ID: P0QMPHgwI0
layout/svg/nsSVGIntegrationUtils.cpp
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -510,46 +510,56 @@ nsSVGIntegrationUtils::PaintFramesWithEf
 
   gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(aFrame);
 
   const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
   // Keep moving forward even if svgMaskFrame is nullptr or isOK is false.
   // This source is not a svg mask, but it still can be a correct mask image.
   nsSVGMaskFrame *svgMaskFrame = effectProperties.GetMaskFrame(&isOK);
 
-  bool complexEffects = false;
-  bool hasValidLayers = svgReset->mMask.HasLayerWithImage();
 
   // These are used if we require a temporary surface for a custom blend mode.
   RefPtr<gfxContext> target = &aContext;
   IntPoint targetOffset;
 
+  bool hasMaskToDraw = svgMaskFrame ? true : false;
+  if (!hasMaskToDraw) {
+    NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
+      if (!svgReset->mMask.mLayers[i].mImage.IsEmpty()) {
+        hasMaskToDraw = true;
+        break;
+      }
+    }
+  }
+
+  bool complexEffects = false;
   /* Check if we need to do additional operations on this child's
    * rendering, which necessitates rendering into another surface. */
   if (opacity != 1.0f ||  (clipPathFrame && !isTrivialClip)
       || aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
-      || svgMaskFrame || hasValidLayers) {
+      || hasMaskToDraw) {
     complexEffects = true;
 
     aContext.Save();
     nsRect clipRect =
       aFrame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
     aContext.Clip(NSRectToSnappedRect(clipRect,
                                   aFrame->PresContext()->AppUnitsPerDevPixel(),
                                   *drawTarget));
 
     Matrix maskTransform;
     RefPtr<SourceSurface> maskSurface;
+
     if (svgMaskFrame) {
       maskSurface = svgMaskFrame->GetMaskForMaskedFrame(&aContext,
-                                                     aFrame,
-                                                     cssPxToDevPxMatrix,
-                                                     opacity,
-                                                     &maskTransform);
-    } else if (hasValidLayers) {
+                                                        aFrame,
+                                                        cssPxToDevPxMatrix,
+                                                        opacity,
+                                                        &maskTransform);
+    } else if (hasMaskToDraw) {
       gfxRect clipRect = aContext.GetClipExtents();
       {
         gfxContextMatrixAutoSaveRestore matRestore(&aContext);
 
         aContext.SetMatrix(gfxMatrix());
         clipRect = aContext.GetClipExtents();
       }
       IntRect drawRect = RoundedOut(ToRect(clipRect));
@@ -579,17 +589,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
       maskSurface = targetDT->Snapshot();
 
       // Compute mask transform.
       Matrix mat = ToMatrix(aContext.CurrentMatrix());
       mat.Invert();
       maskTransform = Matrix::Translation(drawRect.x, drawRect.y) * mat;
     }
 
-    if ((svgMaskFrame || hasValidLayers) && !maskSurface) {
+    if (hasMaskToDraw && !maskSurface) {
       // Entire surface is clipped out.
       aContext.Restore();
       return;
     }
 
     if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
       // Create a temporary context to draw to so we can blend it back with
       // another operator.
@@ -619,18 +629,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
                                                                          &clippedMaskTransform, maskSurface, maskTransform);
 
       if (clipMaskSurface) {
         maskSurface = clipMaskSurface;
         maskTransform = clippedMaskTransform;
       }
     }
 
-    if (opacity != 1.0f || svgMaskFrame  || hasValidLayers ||
-        (clipPathFrame && !isTrivialClip)) {
+    if (opacity != 1.0f || hasMaskToDraw || (clipPathFrame && !isTrivialClip)) {
       target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
     }
   }
 
   /* If this frame has only a trivial clipPath, set up cairo's clipping now so
    * we can just do normal painting and get it clipped appropriately.
    */
   if (clipPathFrame && isTrivialClip) {
@@ -664,18 +673,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
     aContext.Restore();
   }
 
   /* No more effects, we're done. */
   if (!complexEffects) {
     return;
   }
 
-  if (opacity != 1.0f || svgMaskFrame || hasValidLayers ||
-      (clipPathFrame && !isTrivialClip)) {
+  if (opacity != 1.0f || hasMaskToDraw || (clipPathFrame && !isTrivialClip)) {
     target->PopGroupAndBlend();
   }
 
   if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
     RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
     target = nullptr;
     RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();