Bug 1234485 - Part 3. Implement nsSVGIntegrationUtils::PaintMask. draft
authorcku <cku@mozilla.com>
Wed, 19 Oct 2016 17:31:36 +0800
changeset 435834 496a0b706d5408fb86b669ea4d3e61146d95264d
parent 435833 88783e02e1191b44d583e93c2840ae00e0c8ab07
child 435835 4dfec6e8d42ce46095d82d688984a8ef5d436119
push id35137
push userbmo:cku@mozilla.com
push dateWed, 09 Nov 2016 09:16:18 +0000
bugs1234485
milestone52.0a1
Bug 1234485 - Part 3. Implement nsSVGIntegrationUtils::PaintMask. Unlike nsSVGIntegrationUtils::PaintMaskAndClipPath, which paints masked content onto aParam.ctx, nsSVGIntegrationUtils::PaintMask paints only mask, no content, onto aParams.ctx. MozReview-Commit-ID: BaRbtHpoHzj
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -745,16 +745,70 @@ nsSVGIntegrationUtils::IsMaskResourceRea
     }
   }
 
   // Either all mask resources are ready, or no mask resource is needed.
   return true;
 }
 
 DrawResult
+nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
+{
+  MaskUsage maskUsage;
+  DetermineMaskUsage(aParams.frame, aParams.handleOpacity, maskUsage);
+  MOZ_ASSERT(maskUsage.shouldGenerateMaskLayer);
+
+  nsIFrame* frame = aParams.frame;
+  DrawResult result = DrawResult::SUCCESS;
+  if (!ValidateSVGFrame(frame)) {
+    return result;
+  }
+
+  if (maskUsage.opacity == 0.0f) {
+    return DrawResult::SUCCESS;
+  }
+
+  gfxContext& ctx = aParams.ctx;
+
+  Matrix maskTransform;
+  RefPtr<SourceSurface> maskSurface;
+
+  gfxContextMatrixAutoSaveRestore matSR(&ctx);
+
+  nsIFrame* firstFrame =
+    nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
+  nsSVGEffects::EffectProperties effectProperties =
+    nsSVGEffects::GetEffectProperties(firstFrame);
+  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
+  bool opacityApplied = false;
+
+  nsPoint offsetToBoundingBox;
+  nsPoint offsetToUserSpace;
+  SetupContextMatrix(frame, aParams, offsetToBoundingBox,
+                     offsetToUserSpace, false);
+  result = GenerateMaskSurface(aParams, maskUsage.opacity,
+                               firstFrame->StyleContext(),
+                               maskFrames, offsetToUserSpace,
+                               maskTransform, maskSurface, opacityApplied);
+  if (!maskSurface) {
+    // Entire surface is clipped out.
+    return result;
+  }
+
+  ctx.Multiply(ThebesMatrix(maskTransform));
+
+  DrawTarget* target = ctx.GetDrawTarget();
+  MOZ_ASSERT(target->GetFormat() == SurfaceFormat::A8);
+  Rect drawingRect(Point(0, 0), Size(target->GetSize()));
+  target->DrawSurface(maskSurface, drawingRect, drawingRect);
+
+  return result;
+}
+
+DrawResult
 nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
 {
   MOZ_ASSERT(UsingMaskOrClipPathForFrame(aParams.frame),
              "Should not use this method when no mask or clipPath effect"
              "on this frame");
 
   /* SVG defines the following rendering model:
    *
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -155,16 +155,23 @@ public:
   };
 
   /**
    * Paint non-SVG frame with mask, clipPath and opacity effect.
    */
   static DrawResult
   PaintMaskAndClipPath(const PaintFramesParams& aParams);
 
+  /**
+   * Paint mask of non-SVG frame onto a given context, aParams.ctx.
+   * aParams.ctx must contain an A8 surface.
+   */
+  static DrawResult
+  PaintMask(const PaintFramesParams& aParams);
+
   struct MaskUsage {
     bool shouldGenerateMaskLayer;
     bool shouldGenerateClipMaskLayer;
     bool shouldApplyClipPath;
     bool shouldApplyBasicShape;
     float opacity;
 
     MaskUsage()