Bug 1370449 - Simplify SVGTextDrawPathCallbacks by passing in data that more closely matches what it uses. r=heycam
authorRobert Longson <longsonr@gmail.com>
Wed, 07 Jun 2017 20:38:59 +0100
changeset 413224 76a3d885e36b81e87aa7cc7a5d6ee7631bc92b5a
parent 413223 fd35e2ebf019d75c648d8ec5663bf58f1a444621
child 413225 6fd10955e89903caf8f92e2c600aa2aa4a2be496
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1370449
milestone55.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 1370449 - Simplify SVGTextDrawPathCallbacks by passing in data that more closely matches what it uses. r=heycam
layout/svg/SVGTextFrame.cpp
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2734,29 +2734,32 @@ public:
 class SVGTextDrawPathCallbacks : public nsTextFrame::DrawPathCallbacks
 {
   typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
 public:
   /**
    * Constructs an SVGTextDrawPathCallbacks.
    *
+   * @param aSVGTextFrame The ancestor text frame.
    * @param aContext The context to use for painting.
    * @param aFrame The nsTextFrame to paint.
    * @param aCanvasTM The transformation matrix to set when painting; this
    *   should be the FOR_OUTERSVG_TM canvas TM of the text, so that
    *   paint servers are painted correctly.
    * @param aShouldPaintSVGGlyphs Whether SVG glyphs should be painted.
    */
-  SVGTextDrawPathCallbacks(nsRenderingContext* aContext,
+  SVGTextDrawPathCallbacks(SVGTextFrame* aSVGTextFrame,
+                           gfxContext& aContext,
                            nsTextFrame* aFrame,
                            const gfxMatrix& aCanvasTM,
                            bool aShouldPaintSVGGlyphs)
     : DrawPathCallbacks(aShouldPaintSVGGlyphs),
-      gfx(aContext->ThebesContext()),
+      mSVGTextFrame(aSVGTextFrame),
+      mContext(aContext),
       mFrame(aFrame),
       mCanvasTM(aCanvasTM)
   {
   }
 
   void NotifySelectionBackgroundNeedsFill(const Rect& aBackgroundRect,
                                           nscolor aColor,
                                           DrawTarget& aDrawTarget) override;
@@ -2765,19 +2768,17 @@ public:
   void NotifyBeforeText(nscolor aColor) override;
   void NotifyGlyphPathEmitted() override;
   void NotifyAfterText() override;
 
 private:
   void SetupContext();
 
   bool IsClipPathChild() const {
-    return nsLayoutUtils::GetClosestFrameOfType
-             (mFrame->GetParent(), LayoutFrameType::SVGText)->GetStateBits() &
-             NS_STATE_SVG_CLIPPATH_CHILD;
+    return mSVGTextFrame->HasAnyStateBits(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();
 
@@ -2799,17 +2800,18 @@ private:
    */
   void FillGeometry();
 
   /**
    * Strokes a piece of text geometry.
    */
   void StrokeGeometry();
 
-  gfxContext* gfx;
+  SVGTextFrame* mSVGTextFrame;
+  gfxContext& mContext;
   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.
@@ -2840,124 +2842,124 @@ SVGTextDrawPathCallbacks::NotifySelectio
   }
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyBeforeText(nscolor aColor)
 {
   mColor = aColor;
   SetupContext();
-  gfx->NewPath();
+  mContext.NewPath();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyGlyphPathEmitted()
 {
   HandleTextGeometry();
-  gfx->NewPath();
+  mContext.NewPath();
 }
 
 void
 SVGTextDrawPathCallbacks::NotifyAfterText()
 {
-  gfx->Restore();
+  mContext.Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::PaintDecorationLine(Rect aPath, nscolor aColor)
 {
   mColor = aColor;
   AntialiasMode aaMode =
     nsSVGUtils::ToAntialiasMode(mFrame->StyleText()->mTextRendering);
 
-  gfx->Save();
-  gfx->NewPath();
-  gfx->SetAntialiasMode(aaMode);
-  gfx->Rectangle(ThebesRect(aPath));
+  mContext.Save();
+  mContext.NewPath();
+  mContext.SetAntialiasMode(aaMode);
+  mContext.Rectangle(ThebesRect(aPath));
   HandleTextGeometry();
-  gfx->NewPath();
-  gfx->Restore();
+  mContext.NewPath();
+  mContext.Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::PaintSelectionDecorationLine(Rect aPath,
                                                        nscolor aColor)
 {
   if (IsClipPathChild()) {
     // Don't paint selection decorations when in a clip path.
     return;
   }
 
   mColor = aColor;
 
-  gfx->Save();
-  gfx->NewPath();
-  gfx->Rectangle(ThebesRect(aPath));
+  mContext.Save();
+  mContext.NewPath();
+  mContext.Rectangle(ThebesRect(aPath));
   FillAndStrokeGeometry();
-  gfx->Restore();
+  mContext.Restore();
 }
 
 void
 SVGTextDrawPathCallbacks::SetupContext()
 {
-  gfx->Save();
+  mContext.Save();
 
   // XXX This is copied from nsSVGGlyphFrame::Render, but cairo doesn't actually
   // seem to do anything with the antialias mode.  So we can perhaps remove it,
   // or make SetAntialiasMode set cairo text antialiasing too.
   switch (mFrame->StyleText()->mTextRendering) {
   case NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED:
-    gfx->SetAntialiasMode(AntialiasMode::NONE);
+    mContext.SetAntialiasMode(AntialiasMode::NONE);
     break;
   default:
-    gfx->SetAntialiasMode(AntialiasMode::SUBPIXEL);
+    mContext.SetAntialiasMode(AntialiasMode::SUBPIXEL);
     break;
   }
 }
 
 void
 SVGTextDrawPathCallbacks::HandleTextGeometry()
 {
   if (IsClipPathChild()) {
-    RefPtr<Path> path = gfx->GetPath();
+    RefPtr<Path> path = mContext.GetPath();
     ColorPattern white(Color(1.f, 1.f, 1.f, 1.f)); // for masking, so no ToDeviceColor
-    gfx->GetDrawTarget()->Fill(path, white);
+    mContext.GetDrawTarget()->Fill(path, white);
   } else {
     // Normal painting.
-    gfxContextMatrixAutoSaveRestore saveMatrix(gfx);
-    gfx->SetMatrix(mCanvasTM);
+    gfxContextMatrixAutoSaveRestore saveMatrix(&mContext);
+    mContext.SetMatrix(mCanvasTM);
 
     FillAndStrokeGeometry();
   }
 }
 
 void
 SVGTextDrawPathCallbacks::MakeFillPattern(GeneralPattern* aOutPattern,
                                           imgDrawingParams& aImgParams)
 {
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
-    nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern, aImgParams);
+    nsSVGUtils::MakeFillPatternFor(mFrame, &mContext, aOutPattern, aImgParams);
     return;
   }
 
   if (mColor == NS_TRANSPARENT) {
     return;
   }
 
   aOutPattern->InitColorPattern(ToDeviceColor(mColor));
 }
 
 void
 SVGTextDrawPathCallbacks::FillAndStrokeGeometry()
 {
   bool pushedGroup = false;
   if (mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     pushedGroup = true;
-    gfx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 0.4f);
+    mContext.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 0.4f);
   }
 
   uint32_t paintOrder = mFrame->StyleSVG()->mPaintOrder;
   if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
     FillGeometry();
     StrokeGeometry();
   } else {
     while (paintOrder) {
@@ -2971,77 +2973,77 @@ SVGTextDrawPathCallbacks::FillAndStrokeG
           StrokeGeometry();
           break;
       }
       paintOrder >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
     }
   }
 
   if (pushedGroup) {
-    gfx->PopGroupAndBlend();
+    mContext.PopGroupAndBlend();
   }
 }
 
 void
 SVGTextDrawPathCallbacks::FillGeometry()
 {
   GeneralPattern fillPattern;
   // XXX cku Bug 1362417 we should pass imgDrawingParams from nsTextFrame.
   imgDrawingParams imgParams;
   MakeFillPattern(&fillPattern, imgParams);
   if (fillPattern.GetPattern()) {
-    RefPtr<Path> path = gfx->GetPath();
+    RefPtr<Path> path = mContext.GetPath();
     FillRule fillRule = nsSVGUtils::ToFillRule(IsClipPathChild() ?
                           mFrame->StyleSVG()->mClipRule :
                           mFrame->StyleSVG()->mFillRule);
     if (fillRule != path->GetFillRule()) {
       RefPtr<PathBuilder> builder = path->CopyToBuilder(fillRule);
       path = builder->Finish();
     }
-    gfx->GetDrawTarget()->Fill(path, fillPattern);
+    mContext.GetDrawTarget()->Fill(path, fillPattern);
   }
 }
 
 void
 SVGTextDrawPathCallbacks::StrokeGeometry()
 {
   // We don't paint the stroke when we are filling with a selection color.
   if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     if (nsSVGUtils::HasStroke(mFrame, /*aContextPaint*/ nullptr)) {
       GeneralPattern strokePattern;
       // XXX cku Bug 1362417 we should pass imgDrawingParams from nsTextFrame.
       imgDrawingParams imgParams;
-      nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern, imgParams,
-                                       /*aContextPaint*/ nullptr);
+      nsSVGUtils::MakeStrokePatternFor(mFrame, &mContext, &strokePattern,
+                                       imgParams, /*aContextPaint*/ nullptr);
       if (strokePattern.GetPattern()) {
         if (!mFrame->GetParent()->GetContent()->IsSVGElement()) {
           // The cast that follows would be unsafe
           MOZ_ASSERT(false, "Our nsTextFrame's parent's content should be SVG");
           return;
         }
         nsSVGElement* svgOwner =
           static_cast<nsSVGElement*>(mFrame->GetParent()->GetContent());
 
         // Apply any stroke-specific transform
         gfxMatrix outerSVGToUser;
         if (nsSVGUtils::GetNonScalingStrokeTransform(mFrame, &outerSVGToUser) &&
             outerSVGToUser.Invert()) {
-          gfx->Multiply(outerSVGToUser);
+          mContext.Multiply(outerSVGToUser);
         }
 
-        RefPtr<Path> path = gfx->GetPath();
+        RefPtr<Path> path = mContext.GetPath();
         SVGContentUtils::AutoStrokeOptions strokeOptions;
         SVGContentUtils::GetStrokeOptions(&strokeOptions, svgOwner,
                                           mFrame->StyleContext(),
                                           /*aContextPaint*/ nullptr);
         DrawOptions drawOptions;
         drawOptions.mAntialiasMode =
           nsSVGUtils::ToAntialiasMode(mFrame->StyleText()->mTextRendering);
-        gfx->GetDrawTarget()->Stroke(path, strokePattern, strokeOptions);
+        mContext.GetDrawTarget()->Stroke(path, strokePattern, strokeOptions);
       }
     }
   }
 }
 
 } // namespace mozilla
 
 
@@ -3648,17 +3650,16 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
   nsIFrame* caretFrame = caret->GetPaintGeometry(&caretRect);
 
   TextRenderedRunIterator it(this, TextRenderedRunIterator::eVisibleFrames);
   TextRenderedRun run = it.Current();
 
   SVGContextPaint* outerContextPaint =
     SVGContextPaint::GetContextPaint(mContent);
 
-  nsRenderingContext rendCtx(&aContext);
   while (run.mFrame) {
     nsTextFrame* frame = run.mFrame;
 
     // Determine how much of the left and right edges of the text frame we
     // need to ignore.
     SVGCharClipDisplayItem item(run);
 
     // Set up the fill and stroke so that SVG glyphs can get painted correctly
@@ -3680,23 +3681,23 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     // indicated by the run.
     gfxMatrix runTransform =
       run.GetTransformFromUserSpaceForPainting(presContext, item) *
       currentMatrix;
     aContext.SetMatrix(runTransform);
 
     if (drawMode != DrawMode(0)) {
       bool paintSVGGlyphs;
-      nsTextFrame::PaintTextParams params(rendCtx.ThebesContext());
+      nsTextFrame::PaintTextParams params(&aContext);
       params.framePt = gfxPoint();
       params.dirtyRect = LayoutDevicePixel::
         FromAppUnits(frame->GetVisualOverflowRect(), auPerDevPx);
       params.contextPaint = contextPaint;
       if (ShouldRenderAsPath(frame, paintSVGGlyphs)) {
-        SVGTextDrawPathCallbacks callbacks(&rendCtx, frame,
+        SVGTextDrawPathCallbacks callbacks(this, aContext, frame,
                                            matrixForPaintServers,
                                            paintSVGGlyphs);
         params.callbacks = &callbacks;
         frame->PaintText(params, item);
       } else {
         frame->PaintText(params, item);
       }
     }