Bug 1078031 - get rid of renderMode. r=jwatt
authorRobert Longson <longsonr@gmail.com>
Sat, 11 Oct 2014 09:24:44 +0100
changeset 209964 f2003d572d536d1ff8d2d9f74f6eb059ae8e0a5a
parent 209963 cdbdea7d3705993ae5fee3b29b9663be07036d76
child 209965 eb92720d6cd21e5cf1cfffee5f2d2e22677abb6d
push id9314
push userryanvm@gmail.com
push dateSat, 11 Oct 2014 20:24:13 +0000
treeherderfx-team@bdba65a0ead7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1078031
milestone35.0a1
Bug 1078031 - get rid of renderMode. r=jwatt
layout/svg/SVGTextFrame.cpp
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGOuterSVGFrame.cpp
layout/svg/nsSVGPathGeometryFrame.cpp
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2704,17 +2704,16 @@ public:
    * @param aShouldPaintSVGGlyphs Whether SVG glyphs should be painted.
    */
   SVGTextDrawPathCallbacks(nsRenderingContext* aContext,
                            nsTextFrame* aFrame,
                            const gfxMatrix& aCanvasTM,
                            bool aShouldPaintSVGGlyphs)
     : DrawPathCallbacks(aShouldPaintSVGGlyphs),
       gfx(aContext->ThebesContext()),
-      mRenderMode(SVGAutoRenderState::GetRenderMode(aContext->GetDrawTarget())),
       mFrame(aFrame),
       mCanvasTM(aCanvasTM)
   {
   }
 
   void NotifyBeforeText(nscolor aColor) MOZ_OVERRIDE;
   void NotifyGlyphPathEmitted() MOZ_OVERRIDE;
   void NotifyBeforeSVGGlyphPainted() MOZ_OVERRIDE;
@@ -2725,16 +2724,23 @@ public:
   void NotifyBeforeDecorationLine(nscolor aColor) MOZ_OVERRIDE;
   void NotifyDecorationLinePathEmitted() MOZ_OVERRIDE;
   void NotifyBeforeSelectionDecorationLine(nscolor aColor) MOZ_OVERRIDE;
   void NotifySelectionDecorationLinePathEmitted() MOZ_OVERRIDE;
 
 private:
   void SetupContext();
 
+  bool IsClipPathChild() const {
+    // parent is the CSS text frame, grand parent must be
+    // an SVG frame of some kind
+    return mFrame->GetParent()->GetParent()->GetStateBits() &
+             NS_STATE_SVG_CLIPPATH_CHILD;
+  }
+
   /**
    * Paints a piece of text geometry.  This is called when glyphs
    * or text decorations have been emitted to the gfxContext.
    */
   void HandleTextGeometry();
 
   /**
    * Sets the gfxContext paint to the appropriate color or pattern
@@ -2754,17 +2760,16 @@ private:
   void FillGeometry();
 
   /**
    * Strokes a piece of text geometry.
    */
   void StrokeGeometry();
 
   gfxContext* gfx;
-  uint16_t mRenderMode;
   nsTextFrame* mFrame;
   const gfxMatrix& mCanvasTM;
 
   /**
    * The color that we were last told from one of the path callback functions.
    * This color can be the special NS_SAME_AS_FOREGROUND_COLOR,
    * NS_40PERCENT_FOREGROUND_COLOR and NS_TRANSPARENT colors when we are
    * painting selections or IME decorations.
@@ -2804,29 +2809,29 @@ void
 SVGTextDrawPathCallbacks::NotifyAfterText()
 {
   gfx->Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyBeforeSelectionBackground(nscolor aColor)
 {
-  if (mRenderMode != SVGAutoRenderState::NORMAL) {
+  if (IsClipPathChild()) {
     // Don't paint selection backgrounds when in a clip path.
     return;
   }
 
   mColor = aColor;
   gfx->Save();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifySelectionBackgroundPathEmitted()
 {
-  if (mRenderMode != SVGAutoRenderState::NORMAL) {
+  if (IsClipPathChild()) {
     // Don't paint selection backgrounds when in a clip path.
     return;
   }
 
   GeneralPattern fillPattern;
   MakeFillPattern(&fillPattern);
   if (fillPattern.GetPattern()) {
     gfx->SetFillRule(nsSVGUtils::ToFillRule(mFrame->StyleSVG()->mFillRule));
@@ -2849,29 +2854,29 @@ SVGTextDrawPathCallbacks::NotifyDecorati
   HandleTextGeometry();
   gfx->NewPath();
   gfx->Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyBeforeSelectionDecorationLine(nscolor aColor)
 {
-  if (mRenderMode != SVGAutoRenderState::NORMAL) {
+  if (IsClipPathChild()) {
     // Don't paint selection decorations when in a clip path.
     return;
   }
 
   mColor = aColor;
   gfx->Save();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifySelectionDecorationLinePathEmitted()
 {
-  if (mRenderMode != SVGAutoRenderState::NORMAL) {
+  if (IsClipPathChild()) {
     // Don't paint selection decorations when in a clip path.
     return;
   }
 
   FillAndStrokeGeometry();
   gfx->Restore();
 }
 
@@ -2891,17 +2896,17 @@ SVGTextDrawPathCallbacks::SetupContext()
     gfx->SetAntialiasMode(AntialiasMode::SUBPIXEL);
     break;
   }
 }
 
 void
 SVGTextDrawPathCallbacks::HandleTextGeometry()
 {
-  if (mRenderMode == SVGAutoRenderState::CLIP_MASK) {
+  if (IsClipPathChild()) {
     gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
     gfx->Fill();
   } else {
     // Normal painting.
     gfxContextMatrixAutoSaveRestore saveMatrix(gfx);
     gfx->SetMatrix(mCanvasTM);
 
     FillAndStrokeGeometry();
@@ -2960,17 +2965,20 @@ SVGTextDrawPathCallbacks::FillAndStrokeG
 }
 
 void
 SVGTextDrawPathCallbacks::FillGeometry()
 {
   GeneralPattern fillPattern;
   MakeFillPattern(&fillPattern);
   if (fillPattern.GetPattern()) {
-    gfx->SetFillRule(nsSVGUtils::ToFillRule(mFrame->StyleSVG()->mFillRule));
+    gfx->SetFillRule(
+      nsSVGUtils::ToFillRule(
+        IsClipPathChild() ?
+          mFrame->StyleSVG()->mClipRule : mFrame->StyleSVG()->mFillRule));
     gfx->Fill(fillPattern);
   }
 }
 
 void
 SVGTextDrawPathCallbacks::StrokeGeometry()
 {
   // We don't paint the stroke when we are filling with a selection color.
@@ -5112,18 +5120,17 @@ SVGTextFrame::DoGlyphPositioning()
 }
 
 bool
 SVGTextFrame::ShouldRenderAsPath(nsRenderingContext* aContext,
                                  nsTextFrame* aFrame,
                                  bool& aShouldPaintSVGGlyphs)
 {
   // Rendering to a clip path.
-  if (SVGAutoRenderState::GetRenderMode(aContext->GetDrawTarget()) !=
-        SVGAutoRenderState::NORMAL) {
+  if (aFrame->GetParent()->GetParent()->GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
     aShouldPaintSVGGlyphs = false;
     return true;
   }
 
   aShouldPaintSVGGlyphs = true;
 
   const nsStyleSVG* style = aFrame->StyleSVG();
 
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -84,21 +84,20 @@ nsSVGClipPathFrame::ApplyClipOrPaintClip
       // clipping path otherwise can't be resolved:
       gfx->Rectangle(gfxRect());
     }
     gfx->Clip();
     gfx->NewPath();
     return NS_OK;
   }
 
-  // Seems like this is a non-trivial clipPath, so we need to use a clip mask.
-
-  // Notify our children that they're painting into a clip mask:
-  SVGAutoRenderState mode(aContext->GetDrawTarget(),
-                          SVGAutoRenderState::CLIP_MASK);
+  // 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();
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -583,20 +583,18 @@ nsDisplayOuterSVG::HitTest(nsDisplayList
 void
 nsDisplayOuterSVG::Paint(nsDisplayListBuilder* aBuilder,
                          nsRenderingContext* aContext)
 {
 #if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
   PRTime start = PR_Now();
 #endif
 
-  // Create an SVGAutoRenderState so we can call SetPaintingToWindow on
-  // it, but do so without changing the render mode:
-  SVGAutoRenderState state(aContext->GetDrawTarget(),
-    SVGAutoRenderState::GetRenderMode(aContext->GetDrawTarget()));
+  // Create an SVGAutoRenderState so we can call SetPaintingToWindow on it.
+  SVGAutoRenderState state(aContext->GetDrawTarget());
 
   if (aBuilder->IsPaintingToWindow()) {
     state.SetPaintingToWindow(true);
   }
 
   nsRect viewportRect =
     mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
 
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -283,32 +283,30 @@ nsSVGPathGeometryFrame::PaintSVG(nsRende
 
 nsIFrame*
 nsSVGPathGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
 {
   FillRule fillRule;
   uint16_t hitTestFlags;
   if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
     hitTestFlags = SVG_HIT_TEST_FILL;
-    fillRule = StyleSVG()->mClipRule == NS_STYLE_FILL_RULE_NONZERO
-                 ? FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
+    fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mClipRule);
   } else {
     hitTestFlags = GetHitTestFlags();
     if (!hitTestFlags) {
       return nullptr;
     }
     if (hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) {
       gfxRect rect =
         nsLayoutUtils::RectToGfxRect(mRect, PresContext()->AppUnitsPerCSSPixel());
       if (!rect.Contains(aPoint)) {
         return nullptr;
       }
     }
-    fillRule = StyleSVG()->mFillRule == NS_STYLE_FILL_RULE_NONZERO
-                 ? FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
+    fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mFillRule);
   }
 
   bool isHit = false;
 
   nsSVGPathGeometryElement* content =
     static_cast<nsSVGPathGeometryElement*>(mContent);
 
   // Using ScreenReferenceDrawTarget() opens us to Moz2D backend specific hit-
@@ -474,18 +472,17 @@ nsSVGPathGeometryFrame::GetBBoxContribut
   nsRefPtr<gfxASurface> refSurf =
     gfxPlatform::GetPlatform()->ScreenReferenceSurface();
   tmpDT = gfxPlatform::GetPlatform()->
     CreateDrawTargetForSurface(refSurf, IntSize(1, 1));
 #else
   tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
 #endif
 
-  FillRule fillRule = StyleSVG()->mFillRule == NS_STYLE_FILL_RULE_NONZERO
-                        ? FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
+  FillRule fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mFillRule);
   RefPtr<Path> pathInUserSpace = element->GetOrBuildPath(*tmpDT, fillRule);
   if (!pathInUserSpace) {
     return bbox;
   }
   RefPtr<Path> pathInBBoxSpace;
   if (aToBBoxUserspace.IsIdentity()) {
     pathInBBoxSpace = pathInUserSpace;
   } else {
@@ -675,24 +672,19 @@ void
 nsSVGPathGeometryFrame::Render(gfxContext* aContext,
                                uint32_t aRenderComponents,
                                const gfxMatrix& aNewTransform)
 {
   MOZ_ASSERT(!aNewTransform.IsSingular());
 
   DrawTarget* drawTarget = aContext->GetDrawTarget();
 
-  uint16_t renderMode = SVGAutoRenderState::GetRenderMode(drawTarget);
-  MOZ_ASSERT(renderMode == SVGAutoRenderState::NORMAL ||
-             renderMode == SVGAutoRenderState::CLIP_MASK,
-             "Unknown render mode");
-
   FillRule fillRule =
-    nsSVGUtils::ToFillRule(renderMode == SVGAutoRenderState::NORMAL ?
-                             StyleSVG()->mFillRule : StyleSVG()->mClipRule);
+    nsSVGUtils::ToFillRule((GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) ?
+                             StyleSVG()->mClipRule : StyleSVG()->mFillRule);
 
   nsSVGPathGeometryElement* element =
     static_cast<nsSVGPathGeometryElement*>(mContent);
 
   RefPtr<Path> path = element->GetOrBuildPath(*drawTarget, fillRule);
   if (!path) {
     return;
   }
@@ -703,17 +695,17 @@ nsSVGPathGeometryFrame::Render(gfxContex
     AntialiasMode::NONE : AntialiasMode::SUBPIXEL;
 
   // We wait as late as possible before setting the transform so that we don't
   // set it unnecessarily if we return early (it's an expensive operation for
   // some backends).
   gfxContextMatrixAutoSaveRestore autoRestoreTransform(aContext);
   aContext->SetMatrix(aNewTransform);
 
-  if (renderMode == SVGAutoRenderState::CLIP_MASK) {
+  if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
     drawTarget->Fill(path, ColorPattern(Color(1.0f, 1.0f, 1.0f, 1.0f)),
                      DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
     return;
   }
 
   gfxTextContextPaint *contextPaint =
     (gfxTextContextPaint*)drawTarget->
       GetUserData(&gfxTextContextPaint::sUserDataKey);
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -85,22 +85,20 @@ NS_SVGNewGetBBoxEnabled()
 {
   return sSVGNewGetBBoxEnabled;
 }
 
 
 // we only take the address of this:
 static mozilla::gfx::UserDataKey sSVGAutoRenderStateKey;
 
-SVGAutoRenderState::SVGAutoRenderState(DrawTarget* aDrawTarget,
-                                       RenderMode aMode
+SVGAutoRenderState::SVGAutoRenderState(DrawTarget* aDrawTarget
                                        MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : mDrawTarget(aDrawTarget)
   , mOriginalRenderState(nullptr)
-  , mMode(aMode)
   , mPaintingToWindow(false)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   mOriginalRenderState =
     aDrawTarget->RemoveUserData(&sSVGAutoRenderStateKey);
   // We always remove ourselves from aContext before it dies, so
   // passing nullptr as the destroy function is okay.
   aDrawTarget->AddUserData(&sSVGAutoRenderStateKey, this, nullptr);
@@ -116,26 +114,16 @@ SVGAutoRenderState::~SVGAutoRenderState(
 }
 
 void
 SVGAutoRenderState::SetPaintingToWindow(bool aPaintingToWindow)
 {
   mPaintingToWindow = aPaintingToWindow;
 }
 
-/* static */ SVGAutoRenderState::RenderMode
-SVGAutoRenderState::GetRenderMode(DrawTarget* aDrawTarget)
-{
-  void *state = aDrawTarget->GetUserData(&sSVGAutoRenderStateKey);
-  if (state) {
-    return static_cast<SVGAutoRenderState*>(state)->mMode;
-  }
-  return NORMAL;
-}
-
 /* static */ bool
 SVGAutoRenderState::IsPaintingToWindow(DrawTarget* aDrawTarget)
 {
   void *state = aDrawTarget->GetUserData(&sSVGAutoRenderStateKey);
   if (state) {
     return static_cast<SVGAutoRenderState*>(state)->mPaintingToWindow;
   }
   return false;
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -145,43 +145,27 @@ private:
 // GRRR WINDOWS HATE HATE HATE
 #undef CLIP_MASK
 
 class MOZ_STACK_CLASS SVGAutoRenderState
 {
   typedef mozilla::gfx::DrawTarget DrawTarget;
 
 public:
-  enum RenderMode {
-    /**
-     * Used to inform SVG frames that they should paint as normal.
-     */
-    NORMAL, 
-    /**
-     * Used to inform SVG frames when they are painting as the child of a
-     * complex clipPath that requires the use of a clip mask. In this case they
-     * should only draw their basic geometry as a path and then fill it using
-     * fully opaque white. They should not stroke, or paint anything else.
-     */
-    CLIP_MASK 
-  };
-
-  SVGAutoRenderState(DrawTarget* aDrawTarget, RenderMode aMode
-                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+  explicit SVGAutoRenderState(DrawTarget* aDrawTarget
+                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
   ~SVGAutoRenderState();
 
   void SetPaintingToWindow(bool aPaintingToWindow);
 
-  static RenderMode GetRenderMode(DrawTarget* aDrawTarget);
   static bool IsPaintingToWindow(DrawTarget* aDrawTarget);
 
 private:
   DrawTarget* mDrawTarget;
   void* mOriginalRenderState;
-  RenderMode mMode;
   bool mPaintingToWindow;
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 
 #define NS_ISVGFILTERREFERENCE_IID \
 { 0x9744ee20, 0x1bcf, 0x4c62, \
  { 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } }