Bug 1258636 part 1 - Use structs to pass params for decoration-related functions in nsCSSRendering. r=jfkthame
authorXidorn Quan <quanxunzhen@gmail.com>
Tue, 22 Mar 2016 16:51:15 +0800
changeset 290040 cf926fcefda2016403b812cc5dd26daa4bbc661e
parent 290020 b79f70a20d4a380715f1fc79a986aac6703d993a
child 290041 e4d32bd5e11e3612f91cea4fc8fd799019304351
push id30114
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:15:54 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1258636
milestone48.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 1258636 part 1 - Use structs to pass params for decoration-related functions in nsCSSRendering. r=jfkthame MozReview-Commit-ID: 5EJJVmM1pyK
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/generic/nsTextFrame.cpp
layout/xul/nsTextBoxFrame.cpp
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -4220,73 +4220,60 @@ nsCSSRendering::ExpandPaintingRectForDec
   } else {
     rect.x -= extraStartEdge;
     rect.width += extraStartEdge;
   }
   return rect;
 }
 
 void
-nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
-                                    DrawTarget& aDrawTarget,
-                                    const Rect& aDirtyRect,
-                                    const nscolor aColor,
-                                    const Point& aPt,
-                                    const Float aICoordInFrame,
-                                    const Size& aLineSize,
-                                    const gfxFloat aAscent,
-                                    const gfxFloat aOffset,
-                                    const uint8_t aDecoration,
-                                    const uint8_t aStyle,
-                                    bool aVertical,
-                                    const gfxFloat aDescentLimit)
+nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+                                    const PaintDecorationLineParams& aParams)
 {
-  NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
-
-  Rect rect = ToRect(
-    GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
-                                  aDecoration, aStyle, aVertical,
-                                  aDescentLimit));
-  if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) {
+  NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
+               "aStyle is none");
+
+  Rect rect = ToRect(GetTextDecorationRectInternal(aParams.pt, aParams));
+  if (rect.IsEmpty() || !rect.Intersects(aParams.dirtyRect)) {
     return;
   }
 
-  if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
+  if (aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
+      aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
+      aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
     NS_ERROR("Invalid decoration value!");
     return;
   }
 
-  Float lineThickness = std::max(NS_round(aLineSize.height), 1.0);
-
-  ColorPattern color(ToDeviceColor(aColor));
+  Float lineThickness = std::max(NS_round(aParams.lineSize.height), 1.0);
+
+  ColorPattern color(ToDeviceColor(aParams.color));
   StrokeOptions strokeOptions(lineThickness);
   DrawOptions drawOptions;
 
   Float dash[2];
 
   AutoPopClips autoPopClips(&aDrawTarget);
 
-  switch (aStyle) {
+  switch (aParams.style) {
     case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
     case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
       break;
     case NS_STYLE_TEXT_DECORATION_STYLE_DASHED: {
       autoPopClips.PushClipRect(rect);
       Float dashWidth = lineThickness * DOT_LENGTH * DASH_LENGTH;
       dash[0] = dashWidth;
       dash[1] = dashWidth;
       strokeOptions.mDashPattern = dash;
       strokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
       strokeOptions.mLineCap = CapStyle::BUTT;
-      rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
-                                                 aICoordInFrame,
+      rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style,
+                                                 rect, aParams.icoordInFrame,
                                                  dashWidth * 2,
-                                                 aVertical);
+                                                 aParams.vertical);
       // We should continue to draw the last dash even if it is not in the rect.
       rect.width += dashWidth;
       break;
     }
     case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED: {
       autoPopClips.PushClipRect(rect);
       Float dashWidth = lineThickness * DOT_LENGTH;
       if (lineThickness > 2.0) {
@@ -4294,20 +4281,20 @@ nsCSSRendering::PaintDecorationLine(nsIF
         dash[1] = dashWidth * 2.f;
         strokeOptions.mLineCap = CapStyle::ROUND;
       } else {
         dash[0] = dashWidth;
         dash[1] = dashWidth;
       }
       strokeOptions.mDashPattern = dash;
       strokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
-      rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
-                                                 aICoordInFrame,
+      rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style,
+                                                 rect, aParams.icoordInFrame,
                                                  dashWidth * 2,
-                                                 aVertical);
+                                                 aParams.vertical);
       // We should continue to draw the last dot even if it is not in the rect.
       rect.width += dashWidth;
       break;
     }
     case NS_STYLE_TEXT_DECORATION_STYLE_WAVY:
       autoPopClips.PushClipRect(rect);
       if (lineThickness > 2.0) {
         drawOptions.mAntialiasMode = AntialiasMode::SUBPIXEL;
@@ -4319,28 +4306,28 @@ nsCSSRendering::PaintDecorationLine(nsIF
       }
       break;
     default:
       NS_ERROR("Invalid style value!");
       return;
   }
 
   // The block-direction position should be set to the middle of the line.
-  if (aVertical) {
+  if (aParams.vertical) {
     rect.x += lineThickness / 2;
   } else {
     rect.y += lineThickness / 2;
   }
 
-  switch (aStyle) {
+  switch (aParams.style) {
     case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
     case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
     case NS_STYLE_TEXT_DECORATION_STYLE_DASHED: {
       Point p1 = rect.TopLeft();
-      Point p2 = aVertical ? rect.BottomLeft() : rect.TopRight();
+      Point p2 = aParams.vertical ? rect.BottomLeft() : rect.TopRight();
       aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
       return;
     }
     case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE: {
       /**
        *  We are drawing double line as:
        *
        * +-------------------------------------------+
@@ -4350,26 +4337,26 @@ nsCSSRendering::PaintDecorationLine(nsIF
        * |                                           |
        * |                                           |
        * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
        * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineThickness
        * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
        * +-------------------------------------------+
        */
       Point p1 = rect.TopLeft();
-      Point p2 = aVertical ? rect.BottomLeft() : rect.TopRight();
+      Point p2 = aParams.vertical ? rect.BottomLeft() : rect.TopRight();
       aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
 
-      if (aVertical) {
+      if (aParams.vertical) {
         rect.width -= lineThickness;
       } else {
         rect.height -= lineThickness;
       }
 
-      p1 = aVertical ? rect.TopRight() : rect.BottomLeft();
+      p1 = aParams.vertical ? rect.TopRight() : rect.BottomLeft();
       p2 = rect.BottomRight();
       aDrawTarget.StrokeLine(p1, p2, color, strokeOptions, drawOptions);
       return;
     }
     case NS_STYLE_TEXT_DECORATION_STYLE_WAVY: {
       /**
        *  We are drawing wavy line as:
        *
@@ -4397,50 +4384,51 @@ nsCSSRendering::PaintDecorationLine(nsIF
        *  5. Goes up to top of the area at 45 degrees.
        *  6. Slides to right horizontaly.
        *  7. Repeat from 2 until reached to right-most edge of the area.
        *
        * In the vertical case, swap horizontal and vertical coordinates and
        * directions in the above description.
        */
 
-      Float& rectICoord = aVertical ? rect.y : rect.x;
-      Float& rectISize = aVertical ? rect.height : rect.width;
-      const Float rectBSize = aVertical ? rect.width : rect.height;
+      Float& rectICoord = aParams.vertical ? rect.y : rect.x;
+      Float& rectISize = aParams.vertical ? rect.height : rect.width;
+      const Float rectBSize = aParams.vertical ? rect.width : rect.height;
 
       const Float adv = rectBSize - lineThickness;
       const Float flatLengthAtVertex =
         std::max((lineThickness - 1.0) * 2.0, 1.0);
 
       // Align the start of wavy lines to the nearest ancestor block.
       const Float cycleLength = 2 * (adv + flatLengthAtVertex);
-      rect = ExpandPaintingRectForDecorationLine(aFrame, aStyle, rect,
-                                                 aICoordInFrame, cycleLength,
-                                                 aVertical);
+      rect = ExpandPaintingRectForDecorationLine(aFrame, aParams.style, rect,
+                                                 aParams.icoordInFrame,
+                                                 cycleLength, aParams.vertical);
       // figure out if we can trim whole cycles from the left and right edges
       // of the line, to try and avoid creating an unnecessarily long and
       // complex path
-      const Float dirtyRectICoord = aVertical ? aDirtyRect.y : aDirtyRect.x;
+      const Float dirtyRectICoord = aParams.vertical ? aParams.dirtyRect.y
+                                                     : aParams.dirtyRect.x;
       int32_t skipCycles = floor((dirtyRectICoord - rectICoord) / cycleLength);
       if (skipCycles > 0) {
         rectICoord += skipCycles * cycleLength;
         rectISize -= skipCycles * cycleLength;
       }
 
       rectICoord += lineThickness / 2.0;
       Point pt(rect.TopLeft());
-      Float& ptICoord = aVertical ? pt.y : pt.x;
-      Float& ptBCoord = aVertical ? pt.x : pt.y;
-      if (aVertical) {
+      Float& ptICoord = aParams.vertical ? pt.y : pt.x;
+      Float& ptBCoord = aParams.vertical ? pt.x : pt.y;
+      if (aParams.vertical) {
         ptBCoord += adv + lineThickness / 2.0;
       }
       Float iCoordLimit = ptICoord + rectISize + lineThickness;
 
-      const Float dirtyRectIMost = aVertical ?
-        aDirtyRect.YMost() : aDirtyRect.XMost();
+      const Float dirtyRectIMost = aParams.vertical ?
+        aParams.dirtyRect.YMost() : aParams.dirtyRect.XMost();
       skipCycles = floor((iCoordLimit - dirtyRectIMost) / cycleLength);
       if (skipCycles > 0) {
         iCoordLimit -= skipCycles * cycleLength;
       }
 
       RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
       RefPtr<Path> path;
 
@@ -4448,17 +4436,17 @@ nsCSSRendering::PaintDecorationLine(nsIF
       builder->MoveTo(pt); // 1
 
       ptICoord = rectICoord;
       builder->LineTo(pt); // 2
 
       // In vertical mode, to go "down" relative to the text we need to
       // decrease the block coordinate, whereas in horizontal we increase
       // it. So the sense of this flag is effectively inverted.
-      bool goDown = aVertical ? false : true;
+      bool goDown = aParams.vertical ? false : true;
       uint32_t iter = 0;
       while (ptICoord < iCoordLimit) {
         if (++iter > 1000) {
           // stroke the current path and start again, to avoid pathological
           // behavior in cairo with huge numbers of path segments
           path = builder->Finish();
           aDrawTarget.Stroke(path, color, strokeOptions, drawOptions);
           builder = aDrawTarget.CreatePathBuilder();
@@ -4480,134 +4468,109 @@ nsCSSRendering::PaintDecorationLine(nsIF
       return;
     }
     default:
       NS_ERROR("Invalid style value!");
   }
 }
 
 Rect
-nsCSSRendering::DecorationLineToPath(const Rect& aDirtyRect,
-                                     const Point& aPt,
-                                     const Size& aLineSize,
-                                     const Float aAscent,
-                                     const Float aOffset,
-                                     const uint8_t aDecoration,
-                                     const uint8_t aStyle,
-                                     bool aVertical,
-                                     const Float aDescentLimit)
+nsCSSRendering::DecorationLineToPath(const PaintDecorationLineParams& aParams)
 {
-  NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
+  NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
+               "aStyle is none");
 
   Rect path; // To benefit from RVO, we return this from all return points
 
-  Rect rect = ToRect(
-    GetTextDecorationRectInternal(aPt, aLineSize,
-                                  aAscent, aOffset,
-                                  aDecoration, aStyle, aVertical,
-                                  aDescentLimit));
-  if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) {
+  Rect rect = ToRect(GetTextDecorationRectInternal(aParams.pt, aParams));
+  if (rect.IsEmpty() || !rect.Intersects(aParams.dirtyRect)) {
     return path;
   }
 
-  if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
+  if (aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
+      aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
+      aParams.decoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
     NS_ERROR("Invalid decoration value!");
     return path;
   }
 
-  if (aStyle != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
+  if (aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
     // For the moment, we support only solid text decorations.
     return path;
   }
 
-  Float lineThickness = std::max(NS_round(aLineSize.height), 1.0);
+  Float lineThickness = std::max(NS_round(aParams.lineSize.height), 1.0);
 
   // The block-direction position should be set to the middle of the line.
-  if (aVertical) {
+  if (aParams.vertical) {
     rect.x += lineThickness / 2;
     path = Rect(rect.TopLeft() - Point(lineThickness / 2, 0.0),
                 Size(lineThickness, rect.Height()));
   } else {
     rect.y += lineThickness / 2;
     path = Rect(rect.TopLeft() - Point(0.0, lineThickness / 2),
                 Size(rect.Width(), lineThickness));
   }
 
   return path;
 }
 
 nsRect
 nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
-                                      const Size& aLineSize,
-                                      const gfxFloat aAscent,
-                                      const gfxFloat aOffset,
-                                      const uint8_t aDecoration,
-                                      const uint8_t aStyle,
-                                      bool aVertical,
-                                      const gfxFloat aDescentLimit)
+                                      const DecorationRectParams& aParams)
 {
   NS_ASSERTION(aPresContext, "aPresContext is null");
-  NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
-
-  gfxRect rect =
-    GetTextDecorationRectInternal(Point(0, 0), aLineSize, aAscent, aOffset,
-                                  aDecoration, aStyle, aVertical,
-                                  aDescentLimit);
+  NS_ASSERTION(aParams.style != NS_STYLE_TEXT_DECORATION_STYLE_NONE,
+               "aStyle is none");
+
+  gfxRect rect = GetTextDecorationRectInternal(Point(0, 0), aParams);
   // The rect values are already rounded to nearest device pixels.
   nsRect r;
   r.x = aPresContext->GfxUnitsToAppUnits(rect.X());
   r.y = aPresContext->GfxUnitsToAppUnits(rect.Y());
   r.width = aPresContext->GfxUnitsToAppUnits(rect.Width());
   r.height = aPresContext->GfxUnitsToAppUnits(rect.Height());
   return r;
 }
 
 gfxRect
 nsCSSRendering::GetTextDecorationRectInternal(const Point& aPt,
-                                              const Size& aLineSize,
-                                              const gfxFloat aAscent,
-                                              const gfxFloat aOffset,
-                                              const uint8_t aDecoration,
-                                              const uint8_t aStyle,
-                                              bool aVertical,
-                                              const gfxFloat aDescentLimit)
+                                              const DecorationRectParams& aParams)
 {
-  NS_ASSERTION(aStyle <= NS_STYLE_TEXT_DECORATION_STYLE_WAVY,
+  NS_ASSERTION(aParams.style <= NS_STYLE_TEXT_DECORATION_STYLE_WAVY,
                "Invalid aStyle value");
 
-  if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE)
+  if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE)
     return gfxRect(0, 0, 0, 0);
 
-  bool canLiftUnderline = aDescentLimit >= 0.0;
-
-  gfxFloat iCoord = aVertical ? aPt.y : aPt.x;
-  gfxFloat bCoord = aVertical ? aPt.x : aPt.y;
+  bool canLiftUnderline = aParams.descentLimit >= 0.0;
+
+  gfxFloat iCoord = aParams.vertical ? aPt.y : aPt.x;
+  gfxFloat bCoord = aParams.vertical ? aPt.x : aPt.y;
 
   // 'left' and 'right' are relative to the line, so for vertical writing modes
   // they will actually become top and bottom of the rendered line.
   // Similarly, aLineSize.width and .height are actually length and thickness
   // of the line, which runs horizontally or vertically according to aVertical.
   const gfxFloat left  = floor(iCoord + 0.5),
-                 right = floor(iCoord + aLineSize.width + 0.5);
+                 right = floor(iCoord + aParams.lineSize.width + 0.5);
 
   // We compute |r| as if for a horizontal text run, and then swap vertical
   // and horizontal coordinates at the end if vertical was requested.
   gfxRect r(left, 0, right - left, 0);
 
-  gfxFloat lineThickness = NS_round(aLineSize.height);
+  gfxFloat lineThickness = NS_round(aParams.lineSize.height);
   lineThickness = std::max(lineThickness, 1.0);
 
-  gfxFloat ascent = NS_round(aAscent);
-  gfxFloat descentLimit = floor(aDescentLimit);
+  gfxFloat ascent = NS_round(aParams.ascent);
+  gfxFloat descentLimit = floor(aParams.descentLimit);
 
   gfxFloat suggestedMaxRectHeight = std::max(std::min(ascent, descentLimit), 1.0);
   r.height = lineThickness;
-  if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE) {
+  if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE) {
     /**
      *  We will draw double line as:
      *
      * +-------------------------------------------+
      * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
      * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineThickness
      * |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
      * |                                           | ^
@@ -4623,17 +4586,17 @@ nsCSSRendering::GetTextDecorationRectInt
     r.height = lineThickness * 2.0 + gap;
     if (canLiftUnderline) {
       if (r.Height() > suggestedMaxRectHeight) {
         // Don't shrink the line height, because the thickness has some meaning.
         // We can just shrink the gap at this time.
         r.height = std::max(suggestedMaxRectHeight, lineThickness * 2.0 + 1.0);
       }
     }
-  } else if (aStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
+  } else if (aParams.style == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
     /**
      *  We will draw wavy line as:
      *
      * +-------------------------------------------+
      * |XXXXX            XXXXXX            XXXXXX  | ^
      * |XXXXXX          XXXXXXXX          XXXXXXXX | | lineThickness
      * |XXXXXXX        XXXXXXXXXX        XXXXXXXXXX| v
      * |     XXX      XXX      XXX      XXX      XX|
@@ -4649,47 +4612,47 @@ nsCSSRendering::GetTextDecorationRectInt
         // because the thickness has some meaning.  E.g., the 1px wavy line and
         // 2px wavy line can be used for different meaning in IME selections
         // at same time.
         r.height = std::max(suggestedMaxRectHeight, lineThickness * 2.0);
       }
     }
   }
 
-  gfxFloat baseline = floor(bCoord + aAscent + 0.5);
+  gfxFloat baseline = floor(bCoord + aParams.ascent + 0.5);
   gfxFloat offset = 0.0;
-  switch (aDecoration) {
+  switch (aParams.decoration) {
     case NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE:
-      offset = aOffset;
+      offset = aParams.offset;
       if (canLiftUnderline) {
         if (descentLimit < -offset + r.Height()) {
           // If we can ignore the offset and the decoration line is overflowing,
           // we should align the bottom edge of the decoration line rect if it's
           // possible.  Otherwise, we should lift up the top edge of the rect as
           // far as possible.
           gfxFloat offsetBottomAligned = -descentLimit + r.Height();
           gfxFloat offsetTopAligned = 0.0;
           offset = std::min(offsetBottomAligned, offsetTopAligned);
         }
       }
       break;
     case NS_STYLE_TEXT_DECORATION_LINE_OVERLINE:
-      offset = aOffset - lineThickness + r.Height();
+      offset = aParams.offset - lineThickness + r.Height();
       break;
     case NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH: {
       gfxFloat extra = floor(r.Height() / 2.0 + 0.5);
       extra = std::max(extra, lineThickness);
-      offset = aOffset - lineThickness + extra;
+      offset = aParams.offset - lineThickness + extra;
       break;
     }
     default:
       NS_ERROR("Invalid decoration value!");
   }
 
-  if (aVertical) {
+  if (aParams.vertical) {
     r.y = baseline + floor(offset + 0.5);
     Swap(r.x, r.y);
     Swap(r.width, r.height);
   } else {
     r.y = baseline - floor(offset + 0.5);
   }
 
   return r;
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -663,132 +663,92 @@ struct nsCSSRendering {
                                      const nsRect&        aBorderRect,
                                      int32_t              aAppUnitsPerDevPixel,
                                      int32_t              aAppUnitsPerCSSPixel,
                                      uint8_t              aStartBevelSide = 0,
                                      nscoord              aStartBevelOffset = 0,
                                      uint8_t              aEndBevelSide = 0,
                                      nscoord              aEndBevelOffset = 0);
 
+  // NOTE: pt, dirtyRect, lineSize, ascent, offset in the following
+  //       structs are non-rounded device pixels, not app units.
+  struct DecorationRectParams
+  {
+    // The width [length] and the height [thickness] of the decoration
+    // line. This is a "logical" size in textRun orientation, so that
+    // for a vertical textrun, width will actually be a physical height;
+    // and conversely, height will be a physical width.
+    Size lineSize;
+    // The ascent of the text.
+    Float ascent = 0.0f;
+    // The offset of the decoration line from the baseline of the text
+    // (if the value is positive, the line is lifted up).
+    Float offset = 0.0f;
+    // If descentLimit is zero or larger and the underline overflows
+    // from the descent space, the underline should be lifted up as far
+    // as possible.  Note that this does not mean the underline never
+    // overflows from this limitation, because if the underline is
+    // positioned to the baseline or upper, it causes unreadability.
+    // Note that if this is zero or larger, the underline rect may be
+    // shrunken if it's possible.  Therefore, this value is used for
+    // strikeout line and overline too.
+    Float descentLimit = -1.0f;
+    // Which line will be painted. The value can be
+    // NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
+    // NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
+    // NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
+    uint8_t decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
+    // The style of the decoration line such as
+    // NS_STYLE_TEXT_DECORATION_STYLE_*.
+    uint8_t style = NS_STYLE_TEXT_DECORATION_STYLE_NONE;
+    bool vertical = false;
+  };
+  struct PaintDecorationLineParams : DecorationRectParams
+  {
+    // No need to paint outside this rect.
+    Rect dirtyRect;
+    // The top/left edge of the text.
+    Point pt;
+    // The color of the decoration line.
+    nscolor color = NS_RGBA(0, 0, 0, 0);
+    // The distance between the left edge of the given frame and the
+    // position of the text as positioned without offset of the shadow.
+    Float icoordInFrame = 0.0f;
+  };
+
   /**
    * Function for painting the decoration lines for the text.
-   * NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
-   *       not app units.
-   * NOTE: aLineSize is a "logical" size in textRun orientation, so that for
-   *       a vertical textrun, aLineSize.width (which is the decoration line
-   *       length) will actually be a physical height; and conversely,
-   *       aLineSize.height [thickness] will be a physical width. The alternate
-   *       names in [brackets] in the comments here apply to the vertical case.
    *
    *   input:
    *     @param aFrame            the frame which needs the decoration line
    *     @param aGfxContext
-   *     @param aDirtyRect        no need to paint outside this rect
-   *     @param aColor            the color of the decoration line
-   *     @param aPt               the top/left edge of the text
-   *     @param aICoordInFrame    the distance between aPt.x [y] and left [top]
-   *                              edge of aFrame. If the decoration line is for
-   *                              shadow, set the distance between the left edge
-   *                              of the aFrame and the position of the text as
-   *                              positioned without offset of the shadow.
-   *     @param aLineSize         the width [length] and the height [thickness]
-   *                              of the decoration line
-   *     @param aAscent           the ascent of the text
-   *     @param aOffset           the offset of the decoration line from
-   *                              the baseline of the text (if the value is
-   *                              positive, the line is lifted up [right])
-   *     @param aDecoration       which line will be painted. The value can be
-   *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
-   *     @param aStyle            the style of the decoration line such as
-   *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
-   *     @param aDescentLimit     If aDescentLimit is zero or larger and the
-   *                              underline overflows from the descent space,
-   *                              the underline should be lifted up as far as
-   *                              possible.  Note that this does not mean the
-   *                              underline never overflows from this
-   *                              limitation.  Because if the underline is
-   *                              positioned to the baseline or upper, it causes
-   *                              unreadability.  Note that if this is zero
-   *                              or larger, the underline rect may be shrunken
-   *                              if it's possible.  Therefore, this value is
-   *                              used for strikeout line and overline too.
    */
-  static void PaintDecorationLine(nsIFrame* aFrame,
-                                  DrawTarget& aDrawTarget,
-                                  const Rect& aDirtyRect,
-                                  const nscolor aColor,
-                                  const Point& aPt,
-                                  const Float aICoordInFrame,
-                                  const Size& aLineSize,
-                                  const gfxFloat aAscent,
-                                  const gfxFloat aOffset,
-                                  const uint8_t aDecoration,
-                                  const uint8_t aStyle,
-                                  bool aVertical,
-                                  const gfxFloat aDescentLimit = -1.0);
+  static void PaintDecorationLine(nsIFrame* aFrame, DrawTarget& aDrawTarget,
+                                  const PaintDecorationLineParams& aParams);
 
   /**
    * Returns a Rect corresponding to the outline of the decoration line for the
    * given text metrics.  Arguments have the same meaning as for
    * PaintDecorationLine.  Currently this only works for solid
    * decorations; for other decoration styles the returned Rect will be empty.
    */
-  static Rect DecorationLineToPath(const Rect& aDirtyRect,
-                                   const Point& aPt,
-                                   const Size& aLineSize,
-                                   const Float aAscent,
-                                   const Float aOffset,
-                                   const uint8_t aDecoration,
-                                   const uint8_t aStyle,
-                                   bool aVertical,
-                                   const Float aDescentLimit = -1.0);
+  static Rect DecorationLineToPath(const PaintDecorationLineParams& aParams);
 
   /**
    * Function for getting the decoration line rect for the text.
    * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels,
    *       not app units.
    *   input:
    *     @param aPresContext
-   *     @param aLineSize         the width and the height of the decoration
-   *                              line
-   *     @param aAscent           the ascent of the text
-   *     @param aOffset           the offset of the decoration line from
-   *                              the baseline of the text (if the value is
-   *                              positive, the line is lifted up)
-   *     @param aDecoration       which line will be painted. The value can be
-   *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
-   *     @param aStyle            the style of the decoration line such as
-   *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
-   *     @param aDescentLimit     If aDescentLimit is zero or larger and the
-   *                              underline overflows from the descent space,
-   *                              the underline should be lifted up as far as
-   *                              possible.  Note that this does not mean the
-   *                              underline never overflows from this
-   *                              limitation.  Because if the underline is
-   *                              positioned to the baseline or upper, it causes
-   *                              unreadability.  Note that if this is zero
-   *                              or larger, the underline rect may be shrunken
-   *                              if it's possible.  Therefore, this value is
-   *                              used for strikeout line and overline too.
    *   output:
    *     @return                  the decoration line rect for the input,
    *                              the each values are app units.
    */
   static nsRect GetTextDecorationRect(nsPresContext* aPresContext,
-                                      const Size& aLineSize,
-                                      const gfxFloat aAscent,
-                                      const gfxFloat aOffset,
-                                      const uint8_t aDecoration,
-                                      const uint8_t aStyle,
-                                      bool aVertical,
-                                      const gfxFloat aDescentLimit = -1.0);
+                                      const DecorationRectParams& aParams);
 
   static CompositionOp GetGFXBlendMode(uint8_t mBlendMode) {
     switch (mBlendMode) {
       case NS_STYLE_BLEND_NORMAL:      return CompositionOp::OP_OVER;
       case NS_STYLE_BLEND_MULTIPLY:    return CompositionOp::OP_MULTIPLY;
       case NS_STYLE_BLEND_SCREEN:      return CompositionOp::OP_SCREEN;
       case NS_STYLE_BLEND_OVERLAY:     return CompositionOp::OP_OVERLAY;
       case NS_STYLE_BLEND_DARKEN:      return CompositionOp::OP_DARKEN;
@@ -813,24 +773,18 @@ struct nsCSSRendering {
       case NS_STYLE_MASK_COMPOSITE_SUBSTRACT:  return CompositionOp::OP_OUT;
       case NS_STYLE_MASK_COMPOSITE_INTERSECT:  return CompositionOp::OP_IN;
       case NS_STYLE_MASK_COMPOSITE_EXCLUDE:    return CompositionOp::OP_XOR;
       default:              MOZ_ASSERT(false); return CompositionOp::OP_OVER;
     }
 
   }
 protected:
-  static gfxRect GetTextDecorationRectInternal(const Point& aPt,
-                                               const Size& aLineSize,
-                                               const gfxFloat aAscent,
-                                               const gfxFloat aOffset,
-                                               const uint8_t aDecoration,
-                                               const uint8_t aStyle,
-                                               bool aVertical,
-                                               const gfxFloat aDescentLimit);
+  static gfxRect GetTextDecorationRectInternal(
+      const Point& aPt, const DecorationRectParams& aParams);
 
   /**
    * Returns inflated rect for painting a decoration line.
    * Complex style decoration lines should be painted from leftmost of nearest
    * ancestor block box because that makes better look of connection of lines
    * for different nodes.  ExpandPaintingRectForDecorationLine() returns
    * a rect for actual painting rect for the clipped rect.
    *
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5230,33 +5230,35 @@ nsTextFrame::UnionAdditionalOverflow(nsP
       decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
     }
     nsFontMetrics* fontMetrics = aProvider.GetFontMetrics();
     nscoord underlineOffset, underlineSize;
     fontMetrics->GetUnderline(underlineOffset, underlineSize);
     nscoord maxAscent = inverted ? fontMetrics->MaxDescent()
                                  : fontMetrics->MaxAscent();
 
+    nsCSSRendering::DecorationRectParams params;
     gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel();
     Float gfxWidth =
       (verticalRun ? aVisualOverflowRect->height
                    : aVisualOverflowRect->width) /
       appUnitsPerDevUnit;
-    gfxFloat gfxAscent = gfxFloat(mAscent) / appUnitsPerDevUnit;
-    gfxFloat gfxMaxAscent = maxAscent / appUnitsPerDevUnit;
-    Float gfxUnderlineSize = underlineSize / appUnitsPerDevUnit;
-    gfxFloat gfxUnderlineOffset = underlineOffset / appUnitsPerDevUnit;
+    params.lineSize = Size(gfxWidth, underlineSize / appUnitsPerDevUnit);
+    params.ascent = gfxFloat(mAscent) / appUnitsPerDevUnit;
+    params.style = decorationStyle;
+    params.vertical = verticalRun;
+
+    params.offset = underlineOffset / appUnitsPerDevUnit;
+    params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
     nsRect underlineRect =
-      nsCSSRendering::GetTextDecorationRect(aPresContext,
-        Size(gfxWidth, gfxUnderlineSize), gfxAscent, gfxUnderlineOffset,
-        NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle, verticalRun);
+      nsCSSRendering::GetTextDecorationRect(aPresContext, params);
+    params.offset = maxAscent / appUnitsPerDevUnit;
+    params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
     nsRect overlineRect =
-      nsCSSRendering::GetTextDecorationRect(aPresContext,
-        Size(gfxWidth, gfxUnderlineSize), gfxAscent, gfxMaxAscent,
-        NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle, verticalRun);
+      nsCSSRendering::GetTextDecorationRect(aPresContext, params);
 
     aVisualOverflowRect->UnionRect(*aVisualOverflowRect, underlineRect);
     aVisualOverflowRect->UnionRect(*aVisualOverflowRect, overlineRect);
 
     // XXX If strikeoutSize is much thicker than the underlineSize, it may
     //     cause overflowing from the overflow rect.  However, such case
     //     isn't realistic, we don't need to compute it now.
   }
@@ -5274,105 +5276,107 @@ nsTextFrame::UnionAdditionalOverflow(nsP
       const nscoord measure = verticalRun ? GetSize().height : GetSize().width;
       const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(),
                      gfxWidth = measure / appUnitsPerDevUnit;
       gfxFloat ascent = gfxFloat(mAscent) / appUnitsPerDevUnit;
       if (wm.IsVerticalRL()) {
         ascent = -ascent;
       }
 
+      nsCSSRendering::DecorationRectParams params;
+      params.lineSize = Size(gfxWidth, 0);
+      params.ascent = ascent;
+      params.vertical = verticalRun;
+
       nscoord topOrLeft(nscoord_MAX), bottomOrRight(nscoord_MIN);
       // Below we loop through all text decorations and compute the rectangle
       // containing all of them, in this frame's coordinate space
+      params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
       for (uint32_t i = 0; i < textDecs.mUnderlines.Length(); ++i) {
         const LineDecoration& dec = textDecs.mUnderlines[i];
-        uint8_t decorationStyle = dec.mStyle;
+        params.style = dec.mStyle;
         // If the style is solid, let's include decoration line rect of solid
         // style since changing the style from none to solid/dotted/dashed
         // doesn't cause reflow.
-        if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
-          decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
+        if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
+          params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
         }
 
         float inflation =
           GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
         const gfxFont::Metrics metrics =
           GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                               useVerticalMetrics);
 
+        params.lineSize.height = metrics.underlineSize;
+        params.offset = metrics.underlineOffset;
         const nsRect decorationRect =
-          nsCSSRendering::GetTextDecorationRect(aPresContext,
-            Size(gfxWidth, metrics.underlineSize),
-            ascent, metrics.underlineOffset,
-            NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle,
-            verticalRun) +
+          nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
           nsPoint(0, -dec.mBaselineOffset);
 
         if (verticalRun) {
           topOrLeft = std::min(decorationRect.x, topOrLeft);
           bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight);
         } else {
           topOrLeft = std::min(decorationRect.y, topOrLeft);
           bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight);
         }
       }
+      params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
       for (uint32_t i = 0; i < textDecs.mOverlines.Length(); ++i) {
         const LineDecoration& dec = textDecs.mOverlines[i];
-        uint8_t decorationStyle = dec.mStyle;
+        params.style = dec.mStyle;
         // If the style is solid, let's include decoration line rect of solid
         // style since changing the style from none to solid/dotted/dashed
         // doesn't cause reflow.
-        if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
-          decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
+        if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
+          params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
         }
 
         float inflation =
           GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
         const gfxFont::Metrics metrics =
           GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                               useVerticalMetrics);
 
+        params.lineSize.height = metrics.underlineSize;
+        params.offset = metrics.maxAscent;
         const nsRect decorationRect =
-          nsCSSRendering::GetTextDecorationRect(aPresContext,
-            Size(gfxWidth, metrics.underlineSize),
-            ascent, metrics.maxAscent,
-            NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle,
-            verticalRun) +
+          nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
           nsPoint(0, -dec.mBaselineOffset);
 
         if (verticalRun) {
           topOrLeft = std::min(decorationRect.x, topOrLeft);
           bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight);
         } else {
           topOrLeft = std::min(decorationRect.y, topOrLeft);
           bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight);
         }
       }
+      params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
       for (uint32_t i = 0; i < textDecs.mStrikes.Length(); ++i) {
         const LineDecoration& dec = textDecs.mStrikes[i];
-        uint8_t decorationStyle = dec.mStyle;
+        params.style = dec.mStyle;
         // If the style is solid, let's include decoration line rect of solid
         // style since changing the style from none to solid/dotted/dashed
         // doesn't cause reflow.
-        if (decorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
-          decorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
+        if (params.style == NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
+          params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
         }
 
         float inflation =
           GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
         const gfxFont::Metrics metrics =
           GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                               useVerticalMetrics);
 
+        params.lineSize.height = metrics.strikeoutSize;
+        params.offset = metrics.strikeoutOffset;
         const nsRect decorationRect =
-          nsCSSRendering::GetTextDecorationRect(aPresContext,
-            Size(gfxWidth, metrics.strikeoutSize),
-            ascent, metrics.strikeoutOffset,
-            NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorationStyle,
-            verticalRun) +
+          nsCSSRendering::GetTextDecorationRect(aPresContext, params) +
           nsPoint(0, -dec.mBaselineOffset);
 
         if (verticalRun) {
           topOrLeft = std::min(decorationRect.x, topOrLeft);
           bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight);
         } else {
           topOrLeft = std::min(decorationRect.y, topOrLeft);
           bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight);
@@ -5474,31 +5478,37 @@ nsTextFrame::PaintDecorationLine(gfxCont
                                  gfxFloat aOffset,
                                  uint8_t aDecoration,
                                  uint8_t aStyle,
                                  DecorationType aDecorationType,
                                  DrawPathCallbacks* aCallbacks,
                                  bool aVertical,
                                  gfxFloat aDescentLimit /* = -1.0 */)
 {
-  nscolor lineColor = aOverrideColor ? *aOverrideColor : aColor;
+  nsCSSRendering::PaintDecorationLineParams params;
+  params.dirtyRect = aDirtyRect.ToUnknownRect();
+  params.pt = aPt;
+  params.color = aOverrideColor ? *aOverrideColor : aColor;
+  params.icoordInFrame = Float(aICoordInFrame);
+  params.lineSize = aLineSize;
+  params.ascent = aAscent;
+  params.offset = aOffset;
+  params.decoration = aDecoration;
+  params.style = aStyle;
+  params.vertical = aVertical;
+  params.descentLimit = aDescentLimit;
   if (aCallbacks) {
-    Rect path = nsCSSRendering::DecorationLineToPath(
-      aDirtyRect.ToUnknownRect(), aPt, aLineSize, aAscent,
-      aOffset, aDecoration, aStyle, aVertical, aDescentLimit);
+    Rect path = nsCSSRendering::DecorationLineToPath(params);
     if (aDecorationType == eNormalDecoration) {
-      aCallbacks->PaintDecorationLine(path, lineColor);
+      aCallbacks->PaintDecorationLine(path, params.color);
     } else {
-      aCallbacks->PaintSelectionDecorationLine(path, lineColor);
+      aCallbacks->PaintSelectionDecorationLine(path, params.color);
     }
   } else {
-    nsCSSRendering::PaintDecorationLine(
-      this, *aCtx->GetDrawTarget(), aDirtyRect.ToUnknownRect(), lineColor,
-      aPt, Float(aICoordInFrame), aLineSize, aAscent, aOffset, aDecoration, aStyle,
-      aVertical, aDescentLimit);
+    nsCSSRendering::PaintDecorationLine(this, *aCtx->GetDrawTarget(), params);
   }
 }
 
 /**
  * This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
  * drawing text decoration for selections.
  */
 void
@@ -6946,61 +6956,63 @@ nsTextFrame::CombineSelectionUnderlineRe
   gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   gfxFont* firstFont = fontGroup->GetFirstValidFont();
   WritingMode wm = GetWritingMode();
   bool verticalRun = wm.IsVertical();
   bool useVerticalMetrics = verticalRun && !wm.IsSideways();
   const gfxFont::Metrics& metrics =
     firstFont->GetMetrics(useVerticalMetrics ? gfxFont::eVertical
                                              : gfxFont::eHorizontal);
-  gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
-  gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
-  gfxFloat descentLimit =
+
+  nsCSSRendering::DecorationRectParams params;
+  params.ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
+  params.offset = fontGroup->GetUnderlineOffset();
+  params.descentLimit =
     ComputeDescentLimitForSelectionUnderline(aPresContext, metrics);
+  params.vertical = verticalRun;
 
   SelectionDetails *details = GetSelectionDetails();
   for (SelectionDetails *sd = details; sd; sd = sd->mNext) {
     if (sd->mStart == sd->mEnd || !(sd->mType & SelectionTypesWithDecorations))
       continue;
 
-    uint8_t style;
     float relativeSize;
     int32_t index =
       nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(sd->mType);
     if (sd->mType == nsISelectionController::SELECTION_SPELLCHECK) {
       if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index, nullptr,
-                                                   &relativeSize, &style)) {
+                                                   &relativeSize,
+                                                   &params.style)) {
         continue;
       }
     } else {
       // IME selections
       TextRangeStyle& rangeStyle = sd->mTextRangeStyle;
       if (rangeStyle.IsDefined()) {
         if (!rangeStyle.IsLineStyleDefined() ||
             rangeStyle.mLineStyle == TextRangeStyle::LINESTYLE_NONE) {
           continue;
         }
-        style = rangeStyle.mLineStyle;
+        params.style = rangeStyle.mLineStyle;
         relativeSize = rangeStyle.mIsBoldLine ? 2.0f : 1.0f;
       } else if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index,
                                                           nullptr, &relativeSize,
-                                                          &style)) {
+                                                          &params.style)) {
         continue;
       }
     }
     nsRect decorationArea;
-    Size size(aPresContext->AppUnitsToGfxUnits(aRect.width),
-              ComputeSelectionUnderlineHeight(aPresContext,
-                                              metrics, sd->mType));
+
+    params.lineSize = Size(aPresContext->AppUnitsToGfxUnits(aRect.width),
+                           ComputeSelectionUnderlineHeight(aPresContext,
+                                                           metrics, sd->mType));
     relativeSize = std::max(relativeSize, 1.0f);
-    size.height *= relativeSize;
+    params.lineSize.height *= relativeSize;
     decorationArea =
-      nsCSSRendering::GetTextDecorationRect(aPresContext, size,
-        ascent, underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
-        style, verticalRun, descentLimit);
+      nsCSSRendering::GetTextDecorationRect(aPresContext, params);
     aRect.UnionRect(aRect, decorationArea);
   }
   DestroySelectionDetails(details);
 
   return !aRect.IsEmpty() && !givenRect.Contains(aRect);
 }
 
 bool
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -474,53 +474,53 @@ nsTextBoxFrame::DrawText(nsRenderingCont
             (wm.IsVerticalRL() ? aTextRect.width - ascent : ascent));
       baselinePt.y = aTextRect.y;
     } else {
       baselinePt.x = aTextRect.x;
       baselinePt.y =
         presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent);
     }
 
-    Point pt(presContext->AppUnitsToGfxUnits(aTextRect.x),
-             presContext->AppUnitsToGfxUnits(aTextRect.y));
-    Float width = presContext->AppUnitsToGfxUnits(aTextRect.width);
-    gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
-    Float xInFrame = Float(PresContext()->AppUnitsToGfxUnits(mTextDrawRect.x));
-    gfxRect dirtyRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
+    nsCSSRendering::PaintDecorationLineParams params;
+    params.dirtyRect = ToRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
+    params.pt = Point(presContext->AppUnitsToGfxUnits(aTextRect.x),
+                      presContext->AppUnitsToGfxUnits(aTextRect.y));
+    params.icoordInFrame =
+      Float(PresContext()->AppUnitsToGfxUnits(mTextDrawRect.x));
+    params.lineSize = Size(presContext->AppUnitsToGfxUnits(aTextRect.width), 0);
+    params.ascent = presContext->AppUnitsToGfxUnits(ascent);
+    params.vertical = vertical;
 
     // XXX todo: vertical-mode support for decorations not tested yet,
     // probably won't be positioned correctly
 
     // Underlines are drawn before overlines, and both before the text
     // itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
     // (We don't apply this rule to the access-key underline because we only
     // find out where that is as a side effect of drawing the text, in the
     // general case -- see below.)
     if (decorations & (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE |
                        NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE)) {
       fontMet->GetUnderline(offset, size);
-      gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
-      Float sizePixel = presContext->AppUnitsToGfxUnits(size);
+      params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
       if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
           underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
-        nsCSSRendering::PaintDecorationLine(this, *drawTarget,
-                                            ToRect(dirtyRect), underColor,
-                          pt, xInFrame, Size(width, sizePixel),
-                          ascentPixel, offsetPixel,
-                          NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle,
-                          vertical);
+        params.color = underColor;
+        params.offset = presContext->AppUnitsToGfxUnits(offset);
+        params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
+        params.style = underStyle;
+        nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
       }
       if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
           overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
-        nsCSSRendering::PaintDecorationLine(this, *drawTarget,
-                                            ToRect(dirtyRect), overColor,
-                          pt, xInFrame, Size(width, sizePixel),
-                          ascentPixel, ascentPixel,
-                          NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle,
-                          vertical);
+        params.color = overColor;
+        params.offset = params.ascent;
+        params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
+        params.style = overStyle;
+        nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
       }
     }
 
     nsRenderingContext refContext(
         PresContext()->PresShell()->CreateReferenceRenderingContext());
     DrawTarget* refDrawTarget = refContext.GetDrawTarget();
 
     CalculateUnderline(refDrawTarget, *fontMet);
@@ -587,23 +587,22 @@ nsTextBoxFrame::DrawText(nsRenderingCont
       drawTarget->FillRect(devPxRect, color);
     }
 
     // Strikeout is drawn on top of the text, per
     // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
     if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
         strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
       fontMet->GetStrikeout(offset, size);
-      gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
-      gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
-      nsCSSRendering::PaintDecorationLine(this, *drawTarget, ToRect(dirtyRect),
-                                          strikeColor,
-                        pt, xInFrame, Size(width, sizePixel), ascentPixel,
-                        offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
-                        strikeStyle, vertical);
+      params.color = strikeColor;
+      params.lineSize.height = presContext->AppUnitsToGfxUnits(size);
+      params.offset = presContext->AppUnitsToGfxUnits(offset);
+      params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
+      params.style = strikeStyle;
+      nsCSSRendering::PaintDecorationLine(this, *drawTarget, params);
     }
 }
 
 void
 nsTextBoxFrame::CalculateUnderline(DrawTarget* aDrawTarget,
                                    nsFontMetrics& aFontMetrics)
 {
     if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {