Bug 1251995 part 6 - Use struct to pass params for nsTextFrame::PaintText* functions. r=jfkthame
☠☠ backed out by 0ffb1b561dde ☠ ☠
authorXidorn Quan <quanxunzhen@gmail.com>
Tue, 01 Mar 2016 17:43:06 +0800
changeset 310846 c36e12ded84548c84e8442ae9e044d0ed136461c
parent 310845 ac1d42c669be7fe41561059c51cef6c522538130
child 310847 734559c25cb12f85ceb282b454b65114490e1834
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1251995
milestone47.0a1
Bug 1251995 part 6 - Use struct to pass params for nsTextFrame::PaintText* functions. r=jfkthame MozReview-Commit-ID: NTEUm8TY8N
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/svg/SVGTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4800,18 +4800,22 @@ nsDisplayText::Paint(nsDisplayListBuilde
   pixelVisible.RoundOut();
 
   ctx->NewPath();
   ctx->Rectangle(pixelVisible);
   ctx->Clip();
 
   NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
   NS_ASSERTION(mVisIEndEdge >= 0, "illegal end edge");
-  f->PaintText(aCtx, ToReferenceFrame(), extraVisible, *this,
-               nullptr, nullptr, mOpacity);
+
+  nsPoint framePt = ToReferenceFrame();
+  nsTextFrame::PaintTextParams params(aCtx->ThebesContext());
+  params.framePt = gfxPoint(framePt.x, framePt.y);
+  params.dirtyRect = extraVisible;
+  f->PaintText(params, *this, mOpacity);
 }
 
 void
 nsTextFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
@@ -5916,51 +5920,49 @@ nsTextFrame::PaintOneShadow(Range aRange
 
   contextBoxBlur.DoPaint();
   aCtx->Restore();
 }
 
 // Paints selection backgrounds and text in the correct colors. Also computes
 // aAllTypes, the union of all selection types that are applying to this text.
 bool
-nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
-    const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
-    const LayoutDeviceRect& aDirtyRect,
-    PropertyProvider& aProvider,
-    Range aContentRange,
-    nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
-    SelectionType* aAllTypes,
-    const nsCharClipDisplayItem::ClipEdges& aClipEdges,
-    nsTextFrame::DrawPathCallbacks* aCallbacks)
-{
+nsTextFrame::PaintTextWithSelectionColors(
+    const PaintTextSelectionParams& aParams,
+    SelectionDetails* aDetails, SelectionType* aAllTypes,
+    const nsCharClipDisplayItem::ClipEdges& aClipEdges)
+{
+  const gfxTextRun::Range& contentRange = aParams.contentRange;
+
   // Figure out which selections control the colors to use for each character.
   AutoTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
   SelectionDetails** prevailingSelections =
-    prevailingSelectionsBuffer.AppendElements(aContentRange.Length(), fallible);
+    prevailingSelectionsBuffer.AppendElements(contentRange.Length(), fallible);
   if (!prevailingSelections) {
     return false;
   }
 
   SelectionType allTypes = 0;
-  for (uint32_t i = 0; i < aContentRange.Length(); ++i) {
+  for (uint32_t i = 0; i < contentRange.Length(); ++i) {
     prevailingSelections[i] = nullptr;
   }
 
   SelectionDetails *sdptr = aDetails;
   bool anyBackgrounds = false;
   while (sdptr) {
-    int32_t start = std::max(0, sdptr->mStart - int32_t(aContentRange.start));
-    int32_t end = std::min(int32_t(aContentRange.Length()),
-                           sdptr->mEnd - int32_t(aContentRange.start));
+    int32_t start = std::max(0, sdptr->mStart - int32_t(contentRange.start));
+    int32_t end = std::min(int32_t(contentRange.Length()),
+                           sdptr->mEnd - int32_t(contentRange.start));
     SelectionType type = sdptr->mType;
     if (start < end) {
       allTypes |= type;
       // Ignore selections that don't set colors
       nscolor foreground, background;
-      if (GetSelectionTextColors(type, aTextPaintStyle, sdptr->mTextRangeStyle,
+      if (GetSelectionTextColors(type, *aParams.textPaintStyle,
+                                 sdptr->mTextRangeStyle,
                                  &foreground, &background)) {
         if (NS_GET_A(background) > 0) {
           anyBackgrounds = true;
         }
         for (int32_t i = start; i < end; ++i) {
           // Favour normal selection over IME selections
           if (!prevailingSelections[i] ||
               type < prevailingSelections[i]->mType) {
@@ -5975,236 +5977,226 @@ nsTextFrame::PaintTextWithSelectionColor
 
   if (!allTypes) {
     // Nothing is selected in the given text range. XXX can this still occur?
     return false;
   }
 
   bool vertical = mTextRun->IsVertical();
   const gfxFloat startIOffset = vertical ?
-    aTextBaselinePt.y - aFramePt.y : aTextBaselinePt.x - aFramePt.x;
+    aParams.textBaselinePt.y - aParams.framePt.y :
+    aParams.textBaselinePt.x - aParams.framePt.x;
   gfxFloat iOffset, hyphenWidth;
   Range range; // in transformed string
   SelectionType type;
   TextRangeStyle rangeStyle;
   // Draw background colors
   if (anyBackgrounds) {
-    int32_t appUnitsPerDevPixel = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
-    SelectionIterator iterator(prevailingSelections, aContentRange,
-                               aProvider, mTextRun, startIOffset);
+    int32_t appUnitsPerDevPixel =
+      aParams.textPaintStyle->PresContext()->AppUnitsPerDevPixel();
+    SelectionIterator iterator(prevailingSelections, contentRange,
+                               *aParams.provider, mTextRun, startIOffset);
     while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
                                    &type, &rangeStyle)) {
       nscolor foreground, background;
-      GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
+      GetSelectionTextColors(type, *aParams.textPaintStyle, rangeStyle,
                              &foreground, &background);
       // Draw background color
       gfxFloat advance = hyphenWidth +
-        mTextRun->GetAdvanceWidth(range, &aProvider);
+        mTextRun->GetAdvanceWidth(range, aParams.provider);
       if (NS_GET_A(background) > 0) {
         nsRect bgRect;
         gfxFloat offs = iOffset - (mTextRun->IsInlineReversed() ? advance : 0);
         if (vertical) {
-          bgRect = nsRect(aFramePt.x, aFramePt.y + offs,
+          bgRect = nsRect(aParams.framePt.x, aParams.framePt.y + offs,
                           GetSize().width, advance);
         } else {
-          bgRect = nsRect(aFramePt.x + offs, aFramePt.y,
+          bgRect = nsRect(aParams.framePt.x + offs, aParams.framePt.y,
                           advance, GetSize().height);
         }
         PaintSelectionBackground(
-          *aCtx->GetDrawTarget(), background, aDirtyRect,
+          *aParams.context->GetDrawTarget(), background, aParams.dirtyRect,
           LayoutDeviceRect::FromAppUnits(bgRect, appUnitsPerDevPixel),
-          aCallbacks);
+          aParams.callbacks);
       }
       iterator.UpdateWithAdvance(advance);
     }
   }
 
   gfxFloat advance;
-  DrawTextParams params(aCtx);
-  params.dirtyRect = aDirtyRect;
-  params.framePt = aFramePt;
-  params.provider = &aProvider;
-  params.textStyle = &aTextPaintStyle;
+  DrawTextParams params(aParams.context);
+  params.dirtyRect = aParams.dirtyRect;
+  params.framePt = aParams.framePt;
+  params.provider = aParams.provider;
+  params.textStyle = aParams.textPaintStyle;
   params.clipEdges = &aClipEdges;
   params.advanceWidth = &advance;
-  params.callbacks = aCallbacks;
-  
+  params.callbacks = aParams.callbacks;
+
   // Draw text
   const nsStyleText* textStyle = StyleText();
-  SelectionIterator iterator(prevailingSelections, aContentRange,
-                             aProvider, mTextRun, startIOffset);
+  SelectionIterator iterator(prevailingSelections, contentRange,
+                             *aParams.provider, mTextRun, startIOffset);
   while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
                                  &type, &rangeStyle)) {
     nscolor foreground, background;
-    GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
+    GetSelectionTextColors(type, *aParams.textPaintStyle, rangeStyle,
                            &foreground, &background);
     gfxPoint textBaselinePt = vertical ?
-      gfxPoint(aTextBaselinePt.x, aFramePt.y + iOffset) :
-      gfxPoint(aFramePt.x + iOffset, aTextBaselinePt.y);
+      gfxPoint(aParams.textBaselinePt.x, aParams.framePt.y + iOffset) :
+      gfxPoint(aParams.framePt.x + iOffset, aParams.textBaselinePt.y);
 
     // Determine what shadow, if any, to draw - either from textStyle
     // or from the ::-moz-selection pseudo-class if specified there
     nsCSSShadowArray* shadow = textStyle->GetTextShadow();
-    GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
+    GetSelectionTextShadow(this, type, *aParams.textPaintStyle, &shadow);
     if (shadow) {
       nscoord startEdge = iOffset;
       if (mTextRun->IsInlineReversed()) {
         startEdge -= hyphenWidth +
-          mTextRun->GetAdvanceWidth(range, &aProvider);
-      }
-      PaintShadows(shadow, range, aDirtyRect, aFramePt, textBaselinePt,
-          startEdge, aProvider, foreground, aClipEdges, aCtx);
+          mTextRun->GetAdvanceWidth(range, aParams.provider);
+      }
+      PaintShadows(
+        shadow, range, aParams.dirtyRect, aParams.framePt, textBaselinePt,
+        startEdge, *aParams.provider, foreground, aClipEdges, aParams.context);
     }
 
     // Draw text segment
     params.textColor = foreground;
     params.drawSoftHyphen = hyphenWidth > 0;
     DrawText(range, textBaselinePt, params);
     advance += hyphenWidth;
     iterator.UpdateWithAdvance(advance);
   }
   return true;
 }
 
 void
-nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
-    const gfxPoint& aFramePt,
-    const gfxPoint& aTextBaselinePt, const LayoutDeviceRect& aDirtyRect,
-    PropertyProvider& aProvider, Range aContentRange,
-    nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
-    SelectionType aSelectionType,
-    nsTextFrame::DrawPathCallbacks* aCallbacks)
+nsTextFrame::PaintTextSelectionDecorations(
+    const PaintTextSelectionParams& aParams,
+    SelectionDetails* aDetails, SelectionType aSelectionType)
 {
   // Hide text decorations if we're currently hiding @font-face fallback text
-  if (aProvider.GetFontGroup()->ShouldSkipDrawing())
+  if (aParams.provider->GetFontGroup()->ShouldSkipDrawing())
     return;
 
   // Figure out which characters will be decorated for this selection.
+  const gfxTextRun::Range& contentRange = aParams.contentRange;
   AutoTArray<SelectionDetails*, BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
   SelectionDetails** selectedChars =
-    selectedCharsBuffer.AppendElements(aContentRange.Length(), fallible);
+    selectedCharsBuffer.AppendElements(contentRange.Length(), fallible);
   if (!selectedChars) {
     return;
   }
-  for (uint32_t i = 0; i < aContentRange.Length(); ++i) {
+  for (uint32_t i = 0; i < contentRange.Length(); ++i) {
     selectedChars[i] = nullptr;
   }
 
   SelectionDetails *sdptr = aDetails;
   while (sdptr) {
     if (sdptr->mType == aSelectionType) {
-      int32_t start = std::max(0, sdptr->mStart - int32_t(aContentRange.start));
-      int32_t end = std::min(int32_t(aContentRange.Length()),
-                             sdptr->mEnd - int32_t(aContentRange.start));
+      int32_t start = std::max(0, sdptr->mStart - int32_t(contentRange.start));
+      int32_t end = std::min(int32_t(contentRange.Length()),
+                             sdptr->mEnd - int32_t(contentRange.start));
       for (int32_t i = start; i < end; ++i) {
         selectedChars[i] = sdptr;
       }
     }
     sdptr = sdptr->mNext;
   }
 
-  gfxFont* firstFont = aProvider.GetFontGroup()->GetFirstValidFont();
+  gfxFont* firstFont = aParams.provider->GetFontGroup()->GetFirstValidFont();
   bool verticalRun = mTextRun->IsVertical();
   bool rightUnderline = verticalRun && IsUnderlineRight(this);
   const uint8_t kDecoration =
     rightUnderline ? NS_STYLE_TEXT_DECORATION_LINE_OVERLINE :
                      NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
   bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline();
   gfxFont::Metrics
     decorationMetrics(firstFont->GetMetrics(useVerticalMetrics ?
       gfxFont::eVertical : gfxFont::eHorizontal));
   if (!useVerticalMetrics) {
     // The potential adjustment from using gfxFontGroup::GetUnderlineOffset
     // is only valid for horizontal font metrics.
     decorationMetrics.underlineOffset =
-      aProvider.GetFontGroup()->GetUnderlineOffset();
-  }
-
-  gfxFloat startIOffset =
-    verticalRun ? aTextBaselinePt.y - aFramePt.y : aTextBaselinePt.x - aFramePt.x;
-  SelectionIterator iterator(selectedChars, aContentRange,
-                             aProvider, mTextRun, startIOffset);
+      aParams.provider->GetFontGroup()->GetUnderlineOffset();
+  }
+
+  gfxFloat startIOffset = verticalRun ?
+    aParams.textBaselinePt.y - aParams.framePt.y :
+    aParams.textBaselinePt.x - aParams.framePt.x;
+  SelectionIterator iterator(selectedChars, contentRange,
+                             *aParams.provider, mTextRun, startIOffset);
   gfxFloat iOffset, hyphenWidth;
   Range range;
-  int32_t app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
+  int32_t app = aParams.textPaintStyle->PresContext()->AppUnitsPerDevPixel();
   // XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint?
   Point pt;
   if (verticalRun) {
-    pt.x = (aTextBaselinePt.x - mAscent) / app;
+    pt.x = (aParams.textBaselinePt.x - mAscent) / app;
   } else {
-    pt.y = (aTextBaselinePt.y - mAscent) / app;
+    pt.y = (aParams.textBaselinePt.y - mAscent) / app;
   }
   gfxFloat decorationOffsetDir = mTextRun->IsSidewaysLeft() ? -1.0 : 1.0;
   SelectionType type;
   TextRangeStyle selectedStyle;
   while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
                                  &type, &selectedStyle)) {
     gfxFloat advance = hyphenWidth +
-      mTextRun->GetAdvanceWidth(range, &aProvider);
+      mTextRun->GetAdvanceWidth(range, aParams.provider);
     if (type == aSelectionType) {
       if (verticalRun) {
-        pt.y = (aFramePt.y + iOffset -
+        pt.y = (aParams.framePt.y + iOffset -
                (mTextRun->IsInlineReversed() ? advance : 0)) / app;
       } else {
-        pt.x = (aFramePt.x + iOffset -
+        pt.x = (aParams.framePt.x + iOffset -
                (mTextRun->IsInlineReversed() ? advance : 0)) / app;
       }
       gfxFloat width = Abs(advance) / app;
-      gfxFloat xInFrame = pt.x - (aFramePt.x / app);
-      DrawSelectionDecorations(aCtx, aDirtyRect, aSelectionType,
-                               aTextPaintStyle, selectedStyle, pt, xInFrame,
-                               width, mAscent / app, decorationMetrics,
-                               aCallbacks, verticalRun, decorationOffsetDir,
-                               kDecoration);
+      gfxFloat xInFrame = pt.x - (aParams.framePt.x / app);
+      DrawSelectionDecorations(
+        aParams.context, aParams.dirtyRect, aSelectionType,
+        *aParams.textPaintStyle, selectedStyle, pt, xInFrame,
+        width, mAscent / app, decorationMetrics, aParams.callbacks,
+        verticalRun, decorationOffsetDir, kDecoration);
     }
     iterator.UpdateWithAdvance(advance);
   }
 }
 
 bool
-nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
-    const gfxPoint& aFramePt,
-    const gfxPoint& aTextBaselinePt, const LayoutDeviceRect& aDirtyRect,
-    PropertyProvider& aProvider,
-    Range aContentRange,
-    nsTextPaintStyle& aTextPaintStyle,
-    const nsCharClipDisplayItem::ClipEdges& aClipEdges,
-    gfxTextContextPaint* aContextPaint,
-    nsTextFrame::DrawPathCallbacks* aCallbacks)
+nsTextFrame::PaintTextWithSelection(
+    const PaintTextSelectionParams& aParams,
+    const nsCharClipDisplayItem::ClipEdges& aClipEdges)
 {
   NS_ASSERTION(GetContent()->IsSelectionDescendant(), "wrong paint path");
 
   SelectionDetails* details = GetSelectionDetails();
   if (!details) {
     return false;
   }
 
   SelectionType allTypes;
-  if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
-                                    aProvider, aContentRange,
-                                    aTextPaintStyle, details, &allTypes,
-                                    aClipEdges, aCallbacks)) {
+  if (!PaintTextWithSelectionColors(aParams, details, &allTypes, aClipEdges)) {
     DestroySelectionDetails(details);
     return false;
   }
   // Iterate through just the selection types that paint decorations and
   // paint decorations for any that actually occur in this frame. Paint
   // higher-numbered selection types below lower-numered ones on the
   // general principal that lower-numbered selections are higher priority.
   allTypes &= SelectionTypesWithDecorations;
   for (int32_t i = nsISelectionController::NUM_SELECTIONTYPES - 1;
        i >= 1; --i) {
     SelectionType type = 1 << (i - 1);
     if (allTypes & type) {
       // There is some selection of this type. Try to paint its decorations
       // (there might not be any for this type but that's OK,
       // PaintTextSelectionDecorations will exit early).
-      PaintTextSelectionDecorations(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
-                                    aProvider, aContentRange, aTextPaintStyle,
-                                    details, type, aCallbacks);
+      PaintTextSelectionDecorations(aParams, details, type);
     }
   }
 
   DestroySelectionDetails(details);
   return true;
 }
 
 void
@@ -6465,59 +6457,58 @@ nsTextFrame::PaintShadows(nsCSSShadowArr
                    aForegroundColor, aClipEdges,
                    aLeftEdgeOffset,
                    shadowMetrics.mBoundingBox,
                    blurFlags);
   }
 }
 
 void
-nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
-                       const LayoutDeviceRect& aDirtyRect,
+nsTextFrame::PaintText(const PaintTextParams& aParams,
                        const nsCharClipDisplayItem& aItem,
-                       gfxTextContextPaint* aContextPaint,
-                       nsTextFrame::DrawPathCallbacks* aCallbacks,
                        float aOpacity /* = 1.0f */)
 {
-  // Don't pass in aRenderingContext here, because we need a *reference*
-  // context and aRenderingContext might have some transform in it
+  // Don't pass in the rendering context here, because we need a
+  // *reference* context and rendering context might have some transform
+  // in it
   // XXX get the block and line passed to us somehow! This is slow!
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
     return;
 
   PropertyProvider provider(this, iter, nsTextFrame::eInflated);
   if (aItem.mIsFrameSelected.isNothing()) {
     aItem.mIsFrameSelected.emplace(IsSelected());
   }
   // Trim trailing whitespace, unless we're painting a selection highlight,
   // which should include trailing spaces if present (bug 1146754).
   provider.InitializeForDisplay(!aItem.mIsFrameSelected.value());
 
-  gfxContext* ctx = aRenderingContext->ThebesContext();
   const bool reversed = mTextRun->IsInlineReversed();
   const bool verticalRun = mTextRun->IsVertical();
   WritingMode wm = GetWritingMode();
-  const nscoord frameWidth = GetSize().width;
-  gfxPoint framePt(aPt.x, aPt.y);
+  const gfxFloat frameWidth = GetSize().width;
+  const gfxFloat frameHeight = GetSize().height;
   gfxPoint textBaselinePt;
   if (verticalRun) {
     if (wm.IsVerticalLR()) {
-      textBaselinePt.x =
-        nsLayoutUtils::GetSnappedBaselineX(this, ctx, aPt.x, mAscent);
+      textBaselinePt.x = nsLayoutUtils::GetSnappedBaselineX(
+        this, aParams.context, nscoord(aParams.framePt.x), mAscent);
     } else {
-      textBaselinePt.x =
-        nsLayoutUtils::GetSnappedBaselineX(this, ctx, aPt.x + frameWidth,
-                                           -mAscent);
-    }
-    textBaselinePt.y = reversed ? aPt.y + GetSize().height : aPt.y;
+      textBaselinePt.x = nsLayoutUtils::GetSnappedBaselineX(
+        this, aParams.context, nscoord(aParams.framePt.x) + frameWidth,
+        -mAscent);
+    }
+    textBaselinePt.y = reversed ? aParams.framePt.y + frameHeight
+                                : aParams.framePt.y;
   } else {
     textBaselinePt =
-      gfxPoint(reversed ? gfxFloat(aPt.x + frameWidth) : framePt.x,
-               nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent));
+      gfxPoint(reversed ? aParams.framePt.x + frameWidth : aParams.framePt.x,
+               nsLayoutUtils::GetSnappedBaselineY(
+                 this, aParams.context, aParams.framePt.y, mAscent));
   }
   Range range = ComputeTransformedRange(provider);
   uint32_t startOffset = range.start;
   uint32_t maxLength = range.Length();
   nscoord snappedStartEdge, snappedEndEdge;
   if (!MeasureCharClippedText(provider, aItem.mVisIStartEdge, aItem.mVisIEndEdge,
          &startOffset, &maxLength, &snappedStartEdge, &snappedEndEdge)) {
     return;
@@ -6525,59 +6516,62 @@ nsTextFrame::PaintText(nsRenderingContex
   if (verticalRun) {
     textBaselinePt.y += reversed ? -snappedEndEdge : snappedStartEdge;
   } else {
     textBaselinePt.x += reversed ? -snappedEndEdge : snappedStartEdge;
   }
   nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedStartEdge,
                                              snappedEndEdge);
   nsTextPaintStyle textPaintStyle(this);
-  textPaintStyle.SetResolveColors(!aCallbacks);
+  textPaintStyle.SetResolveColors(!aParams.callbacks);
 
   // Fork off to the (slower) paint-with-selection path if necessary.
   if (aItem.mIsFrameSelected.value()) {
     MOZ_ASSERT(aOpacity == 1.0f, "We don't support opacity with selections!");
     gfxSkipCharsIterator tmp(provider.GetStart());
     Range contentRange(
       uint32_t(tmp.ConvertSkippedToOriginal(startOffset)),
       uint32_t(tmp.ConvertSkippedToOriginal(startOffset + maxLength)));
-    if (PaintTextWithSelection(ctx, framePt, textBaselinePt, aDirtyRect,
-                               provider, contentRange, textPaintStyle,
-                               clipEdges, aContextPaint, aCallbacks)) {
+    PaintTextSelectionParams params(aParams);
+    params.textBaselinePt = textBaselinePt;
+    params.provider = &provider;
+    params.contentRange = contentRange;
+    params.textPaintStyle = &textPaintStyle;
+    if (PaintTextWithSelection(params, clipEdges)) {
       return;
     }
   }
 
   nscolor foregroundColor = textPaintStyle.GetTextColor();
   if (aOpacity != 1.0f) {
     gfx::Color gfxColor = gfx::Color::FromABGR(foregroundColor);
     gfxColor.a *= aOpacity;
     foregroundColor = gfxColor.ToABGR();
   }
 
   range = Range(startOffset, startOffset + maxLength);
-  if (!aCallbacks) {
+  if (!aParams.callbacks) {
     const nsStyleText* textStyle = StyleText();
-    PaintShadows(
-        textStyle->mTextShadow, range, aDirtyRect, framePt, textBaselinePt,
-        snappedStartEdge, provider, foregroundColor, clipEdges, ctx);
+    PaintShadows(textStyle->mTextShadow, range, aParams.dirtyRect,
+                 aParams.framePt, textBaselinePt, snappedStartEdge,
+                 provider, foregroundColor, clipEdges, aParams.context);
   }
 
   gfxFloat advanceWidth;
-  DrawTextParams params(ctx);
-  params.dirtyRect = aDirtyRect;
-  params.framePt = framePt;
+  DrawTextParams params(aParams.context);
+  params.dirtyRect = aParams.dirtyRect;
+  params.framePt = aParams.framePt;
   params.provider = &provider;
   params.advanceWidth = &advanceWidth;
   params.textStyle = &textPaintStyle;
   params.textColor = foregroundColor;
   params.clipEdges = &clipEdges;
   params.drawSoftHyphen = (GetStateBits() & TEXT_HYPHEN_BREAK) != 0;
-  params.contextPaint = aContextPaint;
-  params.callbacks = aCallbacks;
+  params.contextPaint = aParams.contextPaint;
+  params.callbacks = aParams.callbacks;
   DrawText(range, textBaselinePt, params);
 }
 
 static void
 DrawTextRun(gfxTextRun* aTextRun,
             const gfxPoint& aTextBaselinePt,
             gfxTextRun::Range aRange,
             const nsTextFrame::DrawTextRunParams& aParams)
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -386,16 +386,36 @@ public:
 
     /**
      * Called just after a path corresponding to a selection decoration line
      * has been emitted to the gfxContext.
      */
     virtual void NotifySelectionDecorationLinePathEmitted() { }
   };
 
+  struct PaintTextParams
+  {
+    gfxContext* context;
+    gfxPoint framePt;
+    LayoutDeviceRect dirtyRect;
+    gfxTextContextPaint* contextPaint = nullptr;
+    DrawPathCallbacks* callbacks = nullptr;
+    explicit PaintTextParams(gfxContext* aContext) : context(aContext) {}
+  };
+
+  struct PaintTextSelectionParams : PaintTextParams
+  {
+    gfxPoint textBaselinePt;
+    PropertyProvider* provider = nullptr;
+    Range contentRange;
+    nsTextPaintStyle* textPaintStyle = nullptr;
+    explicit PaintTextSelectionParams(const PaintTextParams& aParams)
+      : PaintTextParams(aParams) {}
+  };
+
   struct DrawTextRunParams
   {
     gfxContext* context;
     PropertyProvider* provider = nullptr;
     gfxFloat* advanceWidth = nullptr;
     gfxTextContextPaint* contextPaint = nullptr;
     DrawPathCallbacks* callbacks = nullptr;
     nscolor textColor = NS_RGBA(0, 0, 0, 0);
@@ -414,62 +434,37 @@ public:
     explicit DrawTextParams(gfxContext* aContext)
       : DrawTextRunParams(aContext) {}
   };
 
   // Primary frame paint method called from nsDisplayText.  Can also be used
   // to generate paths rather than paint the frame's text by passing a callback
   // object.  The private DrawText() is what applies the text to a graphics
   // context.
-  void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
-                 const LayoutDeviceRect& aDirtyRect,
+  void PaintText(const PaintTextParams& aParams,
                  const nsCharClipDisplayItem& aItem,
-                 gfxTextContextPaint* aContextPaint = nullptr,
-                 DrawPathCallbacks* aCallbacks = nullptr,
                  float aOpacity = 1.0f);
   // helper: paint text frame when we're impacted by at least one selection.
   // Return false if the text was not painted and we should continue with
   // the fast path.
-  bool PaintTextWithSelection(gfxContext* aCtx,
-                              const gfxPoint& aFramePt,
-                              const gfxPoint& aTextBaselinePt,
-                              const LayoutDeviceRect& aDirtyRect,
-                              PropertyProvider& aProvider,
-                              Range aRange,
-                              nsTextPaintStyle& aTextPaintStyle,
-                              const nsCharClipDisplayItem::ClipEdges& aClipEdges,
-                              gfxTextContextPaint* aContextPaint,
-                              DrawPathCallbacks* aCallbacks);
+  bool PaintTextWithSelection(const PaintTextSelectionParams& aParams,
+                              const nsCharClipDisplayItem::ClipEdges& aClipEdges);
   // helper: paint text with foreground and background colors determined
   // by selection(s). Also computes a mask of all selection types applying to
   // our text, returned in aAllTypes.
   // Return false if the text was not painted and we should continue with
   // the fast path.
-  bool PaintTextWithSelectionColors(gfxContext* aCtx,
-                                    const gfxPoint& aFramePt,
-                                    const gfxPoint& aTextBaselinePt,
-                                    const LayoutDeviceRect& aDirtyRect,
-                                    PropertyProvider& aProvider,
-                                    Range aContentRange,
-                                    nsTextPaintStyle& aTextPaintStyle,
+  bool PaintTextWithSelectionColors(const PaintTextSelectionParams& aParams,
                                     SelectionDetails* aDetails,
                                     SelectionType* aAllTypes,
-                             const nsCharClipDisplayItem::ClipEdges& aClipEdges,
-                                    DrawPathCallbacks* aCallbacks);
+                                    const nsCharClipDisplayItem::ClipEdges& aClipEdges);
   // helper: paint text decorations for text selected by aSelectionType
-  void PaintTextSelectionDecorations(gfxContext* aCtx,
-                                     const gfxPoint& aFramePt,
-                                     const gfxPoint& aTextBaselinePt,
-                                     const LayoutDeviceRect& aDirtyRect,
-                                     PropertyProvider& aProvider,
-                                     Range aContentRange,
-                                     nsTextPaintStyle& aTextPaintStyle,
+  void PaintTextSelectionDecorations(const PaintTextSelectionParams& aParams,
                                      SelectionDetails* aDetails,
-                                     SelectionType aSelectionType,
-                                     DrawPathCallbacks* aCallbacks);
+                                     SelectionType aSelectionType);
 
   void DrawEmphasisMarks(gfxContext* aContext,
                          mozilla::WritingMode aWM,
                          const gfxPoint& aTextBaselinePt,
                          Range aRange,
                          const nscolor* aDecorationOverrideColor,
                          PropertyProvider* aProvider);
 
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3744,28 +3744,30 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     // Set up the transform for painting the text frame for the substring
     // indicated by the run.
     gfxMatrix runTransform =
       run.GetTransformFromUserSpaceForPainting(presContext, item) *
       currentMatrix;
     aContext.SetMatrix(runTransform);
 
     if (drawMode != DrawMode(0)) {
-      LayoutDeviceRect frameRect = LayoutDevicePixel::
+      bool paintSVGGlyphs;
+      nsTextFrame::PaintTextParams params(rendCtx.ThebesContext());
+      params.framePt = gfxPoint();
+      params.dirtyRect = LayoutDevicePixel::
         FromAppUnits(frame->GetVisualOverflowRect(), auPerDevPx);
-      bool paintSVGGlyphs;
+      params.contextPaint = &contextPaint;
       if (ShouldRenderAsPath(frame, paintSVGGlyphs)) {
         SVGTextDrawPathCallbacks callbacks(&rendCtx, frame,
                                            matrixForPaintServers,
                                            paintSVGGlyphs);
-        frame->PaintText(&rendCtx, nsPoint(), frameRect, item,
-                         &contextPaint, &callbacks);
+        params.callbacks = &callbacks;
+        frame->PaintText(params, item);
       } else {
-        frame->PaintText(&rendCtx, nsPoint(), frameRect, item,
-                         &contextPaint, nullptr);
+        frame->PaintText(params, item);
       }
     }
 
     if (frame == caretFrame && ShouldPaintCaret(run, caret)) {
       // XXX Should we be looking at the fill/stroke colours to paint the
       // caret with, rather than using the color property?
       caret->PaintCaret(aDrawTarget, frame, nsPoint());
       aContext.NewPath();