Bug 1091321, part 1 - Convert nsSVGClipPathFrame::ApplyClipOrPaintClipMask and related code from nsRenderingContext to gfxContext. r=longsonr
authorJonathan Watt <jwatt@jwatt.org>
Fri, 31 Oct 2014 20:08:53 +0000
changeset 213380 e84b632bc007f317b619235985dfabf116a71a33
parent 213379 097629b2eb2ac994b54da0977e1c0cafc94be0fc
child 213381 1653558849c3b01a3a820f5e3822d964e3891551
push id51228
push userjwatt@jwatt.org
push dateFri, 31 Oct 2014 20:07:52 +0000
treeherdermozilla-inbound@544fe2d91fcd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1091321
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1091321, part 1 - Convert nsSVGClipPathFrame::ApplyClipOrPaintClipMask and related code from nsRenderingContext to gfxContext. r=longsonr
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGClipPathFrame.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGUtils.cpp
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -27,92 +27,86 @@ nsIFrame*
 NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGClipPathFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGClipPathFrame)
 
 nsresult
-nsSVGClipPathFrame::ApplyClipOrPaintClipMask(nsRenderingContext* aContext,
+nsSVGClipPathFrame::ApplyClipOrPaintClipMask(gfxContext& aContext,
                                              nsIFrame* aClippedFrame,
                                              const gfxMatrix& aMatrix)
 {
+  DrawTarget& aDrawTarget = *aContext.GetDrawTarget();
+
   // If the flag is set when we get here, it means this clipPath frame
   // has already been used painting the current clip, and the document
   // has a clip reference loop.
   if (mInUse) {
     NS_WARNING("Clip loop detected!");
     return NS_OK;
   }
   AutoClipPathReferencer clipRef(this);
 
   mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
 
-  gfxContext* gfx = aContext->ThebesContext();
-
   nsISVGChildFrame* singleClipPathChild = nullptr;
 
   if (IsTrivial(&singleClipPathChild)) {
-    gfxContextMatrixAutoSaveRestore autoRestore(gfx);
+    gfxContextMatrixAutoSaveRestore autoRestore(&aContext);
     RefPtr<Path> clipPath;
     if (singleClipPathChild) {
       nsSVGPathGeometryFrame* pathFrame = do_QueryFrame(singleClipPathChild);
       if (pathFrame) {
         nsSVGPathGeometryElement* pathElement =
           static_cast<nsSVGPathGeometryElement*>(pathFrame->GetContent());
         gfxMatrix toChildsUserSpace = pathElement->
           PrependLocalTransformsTo(mMatrixForChildren,
                                    nsSVGElement::eUserSpaceToParent);
         gfxMatrix newMatrix =
-          gfx->CurrentMatrix().PreMultiply(toChildsUserSpace).NudgeToIntegers();
+          aContext.CurrentMatrix().PreMultiply(toChildsUserSpace).NudgeToIntegers();
         if (!newMatrix.IsSingular()) {
-          gfx->SetMatrix(newMatrix);
-          clipPath = pathElement->GetOrBuildPath(*gfx->GetDrawTarget(),
+          aContext.SetMatrix(newMatrix);
+          clipPath = pathElement->GetOrBuildPath(aDrawTarget,
                                                  nsSVGUtils::ToFillRule(pathFrame->StyleSVG()->mClipRule));
         }
       }
     }
-    gfx->NewPath();
     if (clipPath) {
-      gfx->SetPath(clipPath);
-      // gfxContext::Clip() resets the FillRule on any Path set by
-      // gfxContext::SetPath() call to the contexts own current FillRule.
-      // So as long as we're doing the clipping via the gfxContext we need to
-      // set the FillRule on the context (even though that's a Path state):
-      gfx->SetFillRule(clipPath->GetFillRule());
+      aContext.Clip(clipPath);
     } else {
       // The spec says clip away everything if we have no children or the
       // clipping path otherwise can't be resolved:
-      gfx->Rectangle(gfxRect());
+      aContext.Clip(Rect());
     }
-    gfx->Clip();
-    gfx->NewPath();
     return NS_OK;
   }
 
   // This is a non-trivial clipPath, so we need to paint its contents into a
   // temporary surface and use that to mask the clipped content.  Note that
   // nsSVGPathGeometryFrame::Render checks for the NS_STATE_SVG_CLIPPATH_CHILD
   // state bit and paints into our mask surface using opaque black in that case.
 
   // Check if this clipPath is itself clipped by another clipPath:
   nsSVGClipPathFrame *clipPathFrame =
     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nullptr);
   bool referencedClipIsTrivial;
   if (clipPathFrame) {
     referencedClipIsTrivial = clipPathFrame->IsTrivial();
-    gfx->Save();
+    aContext.Save();
     if (referencedClipIsTrivial) {
       clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
     } else {
-      gfx->PushGroup(gfxContentType::ALPHA);
+      aContext.PushGroup(gfxContentType::ALPHA);
     }
   }
 
+  nsRenderingContext rendCtx(&aContext);
+
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
     nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
     if (SVGFrame) {
       // The CTM of each frame referencing us can be different.
       SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
 
       bool isOK = true;
@@ -121,69 +115,69 @@ nsSVGClipPathFrame::ApplyClipOrPaintClip
       if (!isOK) {
         continue;
       }
 
       bool isTrivial;
 
       if (clipPathFrame) {
         isTrivial = clipPathFrame->IsTrivial();
-        gfx->Save();
+        aContext.Save();
         if (isTrivial) {
           clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
         } else {
-          gfx->PushGroup(gfxContentType::ALPHA);
+          aContext.PushGroup(gfxContentType::ALPHA);
         }
       }
 
       gfxMatrix toChildsUserSpace = mMatrixForChildren;
       nsIFrame* child = do_QueryFrame(SVGFrame);
       nsIContent* childContent = child->GetContent();
       if (childContent->IsSVG()) {
         toChildsUserSpace =
           static_cast<const nsSVGElement*>(childContent)->
             PrependLocalTransformsTo(mMatrixForChildren,
                                      nsSVGElement::eUserSpaceToParent);
       }
-      SVGFrame->PaintSVG(aContext, toChildsUserSpace);
+      SVGFrame->PaintSVG(&rendCtx, toChildsUserSpace);
 
       if (clipPathFrame) {
         if (!isTrivial) {
-          gfx->PopGroupToSource();
+          aContext.PopGroupToSource();
 
-          gfx->PushGroup(gfxContentType::ALPHA);
+          aContext.PushGroup(gfxContentType::ALPHA);
 
           clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
           Matrix maskTransform;
-          RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&maskTransform);
+          RefPtr<SourceSurface> clipMaskSurface = aContext.PopGroupToSurface(&maskTransform);
 
           if (clipMaskSurface) {
-            gfx->Mask(clipMaskSurface, maskTransform);
+            aContext.Mask(clipMaskSurface, maskTransform);
           }
         }
-        gfx->Restore();
+        aContext.Restore();
       }
     }
   }
 
   if (clipPathFrame) {
     if (!referencedClipIsTrivial) {
-      gfx->PopGroupToSource();
+      aContext.PopGroupToSource();
 
-      gfx->PushGroup(gfxContentType::ALPHA);
+      aContext.PushGroup(gfxContentType::ALPHA);
 
       clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
       Matrix maskTransform;
-      RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&maskTransform);
+      RefPtr<SourceSurface> clipMaskSurface = aContext.PopGroupToSurface(&maskTransform);
 
       if (clipMaskSurface) {
-        gfx->Mask(clipMaskSurface, maskTransform);
+        aContext.Mask(clipMaskSurface, maskTransform);
       }
     }
-    gfx->Restore();
+    aContext.Restore();
   }
 
   return NS_OK;
 }
 
 bool
 nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
                                           const gfxPoint &aPoint)
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -6,17 +6,17 @@
 #ifndef __NS_SVGCLIPPATHFRAME_H__
 #define __NS_SVGCLIPPATHFRAME_H__
 
 #include "mozilla/Attributes.h"
 #include "gfxMatrix.h"
 #include "nsSVGContainerFrame.h"
 #include "nsSVGUtils.h"
 
-class nsRenderingContext;
+class gfxContext;
 class nsISVGChildFrame;
 
 typedef nsSVGContainerFrame nsSVGClipPathFrameBase;
 
 class nsSVGClipPathFrame : public nsSVGClipPathFrameBase
 {
   friend nsIFrame*
   NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
@@ -44,17 +44,17 @@ public:
    * SVG clipPath is not simple then calling this method will paint the
    * clipPath's contents (geometry being filled only, with opaque black) to the
    * DrawTarget.  In this latter case callers are expected to first push a
    * group before calling this method, then pop the group after calling and use
    * it as a mask to mask the clipped frame.
    *
    * XXXjwatt Maybe split this into two methods.
    */
-  nsresult ApplyClipOrPaintClipMask(nsRenderingContext* aContext,
+  nsresult ApplyClipOrPaintClipMask(gfxContext& aContext,
                                     nsIFrame* aClippedFrame,
                                     const gfxMatrix &aMatrix);
 
   /**
    * aPoint is expected to be in aClippedFrame's SVG user space.
    */
   bool PointIsInsideClipPath(nsIFrame* aClippedFrame, const gfxPoint &aPoint);
 
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -528,17 +528,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
     gfx->PushGroup(gfxContentType::COLOR_ALPHA);
   }
 
   /* 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) {
     gfx->Save();
-    clipPathFrame->ApplyClipOrPaintClipMask(aCtx, aFrame, cssPxToDevPxMatrix);
+    clipPathFrame->ApplyClipOrPaintClipMask(*gfx, aFrame, cssPxToDevPxMatrix);
   }
 
   /* Paint the child */
   if (effectProperties.HasValidFilter()) {
     RegularFramePaintCallback callback(aBuilder, aLayerManager,
                                        offsetToUserSpace);
 
     nsRegion dirtyRegion = aDirtyRect - offsetToBoundingBox;
@@ -566,17 +566,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
     maskFrame ? maskFrame->GetMaskForMaskedFrame(aCtx->ThebesContext(),
                                                  aFrame, cssPxToDevPxMatrix,
                                                  opacity, &maskTransform)
               : nullptr;
 
   if (clipPathFrame && !isTrivialClip) {
     gfx->PushGroup(gfxContentType::COLOR_ALPHA);
 
-    nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(aCtx, aFrame, cssPxToDevPxMatrix);
+    nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(*gfx, aFrame, cssPxToDevPxMatrix);
     Matrix clippedMaskTransform;
     RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&clippedMaskTransform);
 
     if (NS_SUCCEEDED(rv) && clipMaskSurface) {
       // Still more set after clipping, so clip to another surface
       if (maskSurface || opacity != 1.0f) {
         gfx->PushGroup(gfxContentType::COLOR_ALPHA);
         gfx->Mask(clipMaskSurface, clippedMaskTransform);
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -596,17 +596,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
     gfx->PushGroup(gfxContentType::COLOR_ALPHA);
   }
 
   /* 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) {
     gfx->Save();
-    clipPathFrame->ApplyClipOrPaintClipMask(aContext, aFrame, aTransform);
+    clipPathFrame->ApplyClipOrPaintClipMask(*gfx, aFrame, aTransform);
   }
 
   /* Paint the child */
   if (effectProperties.HasValidFilter()) {
     nsRegion* dirtyRegion = nullptr;
     nsRegion tmpDirtyRegion;
     if (aDirtyRect) {
       // aDirtyRect is in outer-<svg> device pixels, but the filter code needs
@@ -647,17 +647,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
   RefPtr<SourceSurface> maskSurface =
     maskFrame ? maskFrame->GetMaskForMaskedFrame(aContext->ThebesContext(),
                                                  aFrame, aTransform, opacity, &maskTransform)
               : nullptr;
 
   if (clipPathFrame && !isTrivialClip) {
     gfx->PushGroup(gfxContentType::COLOR_ALPHA);
 
-    nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(aContext, aFrame, aTransform);
+    nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(*gfx, aFrame, aTransform);
     Matrix clippedMaskTransform;
     RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&clippedMaskTransform);
 
     if (NS_SUCCEEDED(rv) && clipMaskSurface) {
       // Still more set after clipping, so clip to another surface
       if (maskSurface || opacity != 1.0f) {
         gfx->PushGroup(gfxContentType::COLOR_ALPHA);
         gfx->Mask(clipMaskSurface, clippedMaskTransform);