Bug 1251995 part 5 - Unify units of dirty rect used for painting text frame. r=jfkthame
☠☠ backed out by 6eb75d38d55e ☠ ☠
authorXidorn Quan <quanxunzhen@gmail.com>
Tue, 01 Mar 2016 16:28:27 +0800
changeset 287013 ac1d42c669be7fe41561059c51cef6c522538130
parent 287012 9b31d6fb1fcbda3393045ad53f80b7bf52b8207b
child 287014 c36e12ded84548c84e8442ae9e044d0ed136461c
push id73001
push userxquan@mozilla.com
push dateMon, 07 Mar 2016 09:05:57 +0000
treeherdermozilla-inbound@734559c25cb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1251995
milestone47.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 1251995 part 5 - Unify units of dirty rect used for painting text frame. r=jfkthame MozReview-Commit-ID: BK7j6y7lBV3
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/svg/SVGTextFrame.cpp
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -138,31 +138,16 @@ struct TabwidthAdaptor
   const nsTArray<TabWidth>& mWidths;
   explicit TabwidthAdaptor(const nsTArray<TabWidth>& aWidths)
     : mWidths(aWidths) {}
   uint32_t operator[](size_t aIdx) const {
     return mWidths[aIdx].mOffset;
   }
 };
 
-/**
- * Helper that is useful to help port the code is this file to typed rects.
- * The code here is particularly horrible because it uses gfxRect to
- * store app unit values (because we want fractional app unit values), but
- * virtually everywhere else gfxRect is in device pixels. :-/
- */
-LayoutDeviceRect AppUnitGfxRectToDevRect(gfxRect aRect,
-                                         int32_t aAppUnitsPerDevPixel)
-{
-  return LayoutDeviceRect(aRect.x / aAppUnitsPerDevPixel,
-                          aRect.y / aAppUnitsPerDevPixel,
-                          aRect.width / aAppUnitsPerDevPixel,
-                          aRect.height / aAppUnitsPerDevPixel);
-}
-
 } // namespace
 
 void
 TabWidthStore::ApplySpacing(gfxTextRun::PropertyProvider::Spacing *aSpacing,
                             uint32_t aOffset, uint32_t aLength)
 {
   size_t i = 0;
   const size_t len = mWidths.Length();
@@ -4794,28 +4779,28 @@ void
 nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) {
   PROFILER_LABEL("nsDisplayText", "Paint",
     js::ProfileEntry::Category::GRAPHICS);
 
   // Add 1 pixel of dirty area around mVisibleRect to allow us to paint
   // antialiased pixels beyond the measured text extents.
   // This is temporary until we do this in the actual calculation of text extents.
-  nsRect extraVisible = mVisibleRect;
-  nscoord appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
-  extraVisible.Inflate(appUnitsPerDevPixel, appUnitsPerDevPixel);
+  LayoutDeviceRect extraVisible = LayoutDeviceRect::FromAppUnits(
+    mVisibleRect, mFrame->PresContext()->AppUnitsPerDevPixel());
+  extraVisible.Inflate(1);
   nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
 
   DrawTargetAutoDisableSubpixelAntialiasing disable(aCtx->GetDrawTarget(),
                                                     mDisableSubpixelAA);
   gfxContext* ctx = aCtx->ThebesContext();
   gfxContextAutoSaveRestore save(ctx);
 
-  gfxRect pixelVisible =
-    nsLayoutUtils::RectToGfxRect(extraVisible, appUnitsPerDevPixel);
+  gfxRect pixelVisible(extraVisible.x, extraVisible.y,
+                       extraVisible.width, extraVisible.height);
   pixelVisible.Inflate(2);
   pixelVisible.RoundOut();
 
   ctx->NewPath();
   ctx->Rectangle(pixelVisible);
   ctx->Clip();
 
   NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
@@ -5475,56 +5460,56 @@ nsTextFrame::ComputeSelectionUnderlineHe
     default:
       NS_WARNING("Requested underline style is not valid");
       return aFontMetrics.underlineSize;
   }
 }
 
 void
 nsTextFrame::PaintDecorationLine(gfxContext* const aCtx,
-                                 const gfxRect& aDirtyRect,
+                                 const LayoutDeviceRect& aDirtyRect,
                                  nscolor aColor,
                                  const nscolor* aOverrideColor,
                                  const Point& aPt,
                                  gfxFloat aICoordInFrame,
                                  const Size& aLineSize,
                                  gfxFloat aAscent,
                                  gfxFloat aOffset,
                                  uint8_t aDecoration,
                                  uint8_t aStyle,
                                  DecorationType aDecorationType,
                                  DrawPathCallbacks* aCallbacks,
                                  bool aVertical,
                                  gfxFloat aDescentLimit /* = -1.0 */)
 {
   nscolor lineColor = aOverrideColor ? *aOverrideColor : aColor;
   if (aCallbacks) {
-    Rect path = nsCSSRendering::DecorationLineToPath(ToRect(aDirtyRect),
-      aPt, aLineSize, aAscent, aOffset, aDecoration, aStyle,
-      aVertical, aDescentLimit);
+    Rect path = nsCSSRendering::DecorationLineToPath(
+      aDirtyRect.ToUnknownRect(), aPt, aLineSize, aAscent,
+      aOffset, aDecoration, aStyle, aVertical, aDescentLimit);
     if (aDecorationType == eNormalDecoration) {
       aCallbacks->PaintDecorationLine(path, lineColor);
     } else {
       aCallbacks->PaintSelectionDecorationLine(path, lineColor);
     }
   } else {
-    nsCSSRendering::PaintDecorationLine(this, *aCtx->GetDrawTarget(),
-                                        ToRect(aDirtyRect), lineColor,
+    nsCSSRendering::PaintDecorationLine(
+      this, *aCtx->GetDrawTarget(), aDirtyRect.ToUnknownRect(), lineColor,
       aPt, Float(aICoordInFrame), aLineSize, aAscent, aOffset, aDecoration, aStyle,
       aVertical, aDescentLimit);
   }
 }
 
 /**
  * This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
  * drawing text decoration for selections.
  */
 void
 nsTextFrame::DrawSelectionDecorations(gfxContext* aContext,
-                                      const gfxRect& aDirtyRect,
+                                      const LayoutDeviceRect& aDirtyRect,
                                       SelectionType aType,
                                       nsTextPaintStyle& aTextPaintStyle,
                                       const TextRangeStyle &aRangeStyle,
                                       const Point& aPt,
                                       gfxFloat aICoordInFrame,
                                       gfxFloat aWidth,
                                       gfxFloat aAscent,
                                       const gfxFont::Metrics& aFontMetrics,
@@ -5844,17 +5829,18 @@ AddHyphenToMetrics(nsTextFrame* aTextFra
     hyphenMetrics.mBoundingBox.y = -hyphenMetrics.mBoundingBox.YMost();
   }
   aMetrics->CombineWith(hyphenMetrics, aBaseTextRun->IsRightToLeft());
 }
 
 void
 nsTextFrame::PaintOneShadow(Range aRange,
                             nsCSSShadowItem* aShadowDetails,
-                            PropertyProvider* aProvider, const nsRect& aDirtyRect,
+                            PropertyProvider* aProvider,
+                            const LayoutDeviceRect& aDirtyRect,
                             const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
                             gfxContext* aCtx, const nscolor& aForegroundColor,
                             const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                             nscoord aLeftSideOffset, gfxRect& aBoundingBox,
                             uint32_t aBlurFlags)
 {
   PROFILER_LABEL("nsTextFrame", "PaintOneShadow",
     js::ProfileEntry::Category::GRAPHICS);
@@ -5885,20 +5871,20 @@ nsTextFrame::PaintOneShadow(Range aRange
   shadowGfxRect += shadowOffset;
 
   nsRect shadowRect(NSToCoordRound(shadowGfxRect.X()),
                     NSToCoordRound(shadowGfxRect.Y()),
                     NSToCoordRound(shadowGfxRect.Width()),
                     NSToCoordRound(shadowGfxRect.Height()));
 
   nsContextBoxBlur contextBoxBlur;
-  gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
-                                                  PresContext()->AppUnitsPerDevPixel(),
-                                                  aCtx, aDirtyRect, nullptr,
-                                                  aBlurFlags);
+  const auto A2D = PresContext()->AppUnitsPerDevPixel();
+  gfxContext* shadowContext = contextBoxBlur.Init(
+    shadowRect, 0, blurRadius, A2D, aCtx,
+    LayoutDevicePixel::ToAppUnits(aDirtyRect, A2D), nullptr, aBlurFlags);
   if (!shadowContext)
     return;
 
   nscolor shadowColor;
   const nscolor* decorationOverrideColor;
   if (aShadowDetails->mHasColor) {
     shadowColor = aShadowDetails->mColor;
     decorationOverrideColor = &shadowColor;
@@ -5913,18 +5899,17 @@ nsTextFrame::PaintOneShadow(Range aRange
 
   // Draw the text onto our alpha-only surface to capture the alpha values.
   // Remember that the box blur context has a device offset on it, so we don't need to
   // translate any coordinates to fit on the surface.
   gfxFloat advanceWidth;
   nsTextPaintStyle textPaintStyle(this);
   DrawTextParams params(shadowContext);
   params.advanceWidth = &advanceWidth;
-  params.dirtyRect = gfxRect(aDirtyRect.x, aDirtyRect.y,
-                             aDirtyRect.width, aDirtyRect.height);
+  params.dirtyRect = aDirtyRect;
   params.framePt = aFramePt + shadowOffset;
   params.provider = aProvider;
   params.textStyle = &textPaintStyle;
   params.textColor = aCtx == shadowContext ? shadowColor : NS_RGB(0, 0, 0);
   params.clipEdges = &aClipEdges;
   params.drawSoftHyphen = (GetStateBits() & TEXT_HYPHEN_BREAK) != 0;
   params.decorationOverrideColor = decorationOverrideColor;
   DrawText(aRange, aTextBaselinePt + shadowOffset, params);
@@ -5933,17 +5918,17 @@ nsTextFrame::PaintOneShadow(Range aRange
   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 gfxRect& aDirtyRect,
+    const LayoutDeviceRect& aDirtyRect,
     PropertyProvider& aProvider,
     Range aContentRange,
     nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
     SelectionType* aAllTypes,
     const nsCharClipDisplayItem::ClipEdges& aClipEdges,
     nsTextFrame::DrawPathCallbacks* aCallbacks)
 {
   // Figure out which selections control the colors to use for each character.
@@ -5998,40 +5983,40 @@ nsTextFrame::PaintTextWithSelectionColor
     aTextBaselinePt.y - aFramePt.y : aTextBaselinePt.x - aFramePt.x;
   gfxFloat iOffset, hyphenWidth;
   Range range; // in transformed string
   SelectionType type;
   TextRangeStyle rangeStyle;
   // Draw background colors
   if (anyBackgrounds) {
     int32_t appUnitsPerDevPixel = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
-    LayoutDeviceRect dirtyRect = AppUnitGfxRectToDevRect(aDirtyRect, appUnitsPerDevPixel);
     SelectionIterator iterator(prevailingSelections, aContentRange,
                                aProvider, mTextRun, startIOffset);
     while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
                                    &type, &rangeStyle)) {
       nscolor foreground, background;
       GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
                              &foreground, &background);
       // Draw background color
       gfxFloat advance = hyphenWidth +
         mTextRun->GetAdvanceWidth(range, &aProvider);
       if (NS_GET_A(background) > 0) {
-        gfxRect bgRect;
+        nsRect bgRect;
         gfxFloat offs = iOffset - (mTextRun->IsInlineReversed() ? advance : 0);
         if (vertical) {
-          bgRect = gfxRect(aFramePt.x, aFramePt.y + offs,
-                           GetSize().width, advance);
+          bgRect = nsRect(aFramePt.x, aFramePt.y + offs,
+                          GetSize().width, advance);
         } else {
-          bgRect = gfxRect(aFramePt.x + offs, aFramePt.y,
-                           advance, GetSize().height);
+          bgRect = nsRect(aFramePt.x + offs, aFramePt.y,
+                          advance, GetSize().height);
         }
-        PaintSelectionBackground(*aCtx->GetDrawTarget(), background, dirtyRect,
-                                 AppUnitGfxRectToDevRect(bgRect, appUnitsPerDevPixel),
-                                 aCallbacks);
+        PaintSelectionBackground(
+          *aCtx->GetDrawTarget(), background, aDirtyRect,
+          LayoutDeviceRect::FromAppUnits(bgRect, appUnitsPerDevPixel),
+          aCallbacks);
       }
       iterator.UpdateWithAdvance(advance);
     }
   }
 
   gfxFloat advance;
   DrawTextParams params(aCtx);
   params.dirtyRect = aDirtyRect;
@@ -6039,18 +6024,16 @@ nsTextFrame::PaintTextWithSelectionColor
   params.provider = &aProvider;
   params.textStyle = &aTextPaintStyle;
   params.clipEdges = &aClipEdges;
   params.advanceWidth = &advance;
   params.callbacks = aCallbacks;
   
   // Draw text
   const nsStyleText* textStyle = StyleText();
-  nsRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
-                   aDirtyRect.width, aDirtyRect.height);
   SelectionIterator iterator(prevailingSelections, aContentRange,
                              aProvider, mTextRun, startIOffset);
   while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
                                  &type, &rangeStyle)) {
     nscolor foreground, background;
     GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
                            &foreground, &background);
     gfxPoint textBaselinePt = vertical ?
@@ -6062,34 +6045,34 @@ nsTextFrame::PaintTextWithSelectionColor
     nsCSSShadowArray* shadow = textStyle->GetTextShadow();
     GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
     if (shadow) {
       nscoord startEdge = iOffset;
       if (mTextRun->IsInlineReversed()) {
         startEdge -= hyphenWidth +
           mTextRun->GetAdvanceWidth(range, &aProvider);
       }
-      PaintShadows(shadow, range, dirtyRect, aFramePt, textBaselinePt,
+      PaintShadows(shadow, range, aDirtyRect, aFramePt, textBaselinePt,
           startEdge, aProvider, foreground, aClipEdges, aCtx);
     }
 
     // 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 gfxRect& aDirtyRect,
+    const gfxPoint& aTextBaselinePt, const LayoutDeviceRect& aDirtyRect,
     PropertyProvider& aProvider, Range aContentRange,
     nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
     SelectionType aSelectionType,
     nsTextFrame::DrawPathCallbacks* aCallbacks)
 {
   // Hide text decorations if we're currently hiding @font-face fallback text
   if (aProvider.GetFontGroup()->ShouldSkipDrawing())
     return;
@@ -6144,18 +6127,16 @@ nsTextFrame::PaintTextSelectionDecoratio
   int32_t app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
   // XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint?
   Point pt;
   if (verticalRun) {
     pt.x = (aTextBaselinePt.x - mAscent) / app;
   } else {
     pt.y = (aTextBaselinePt.y - mAscent) / app;
   }
-  gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app,
-                    aDirtyRect.width / app, aDirtyRect.height / 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);
     if (type == aSelectionType) {
@@ -6163,30 +6144,30 @@ nsTextFrame::PaintTextSelectionDecoratio
         pt.y = (aFramePt.y + iOffset -
                (mTextRun->IsInlineReversed() ? advance : 0)) / app;
       } else {
         pt.x = (aFramePt.x + iOffset -
                (mTextRun->IsInlineReversed() ? advance : 0)) / app;
       }
       gfxFloat width = Abs(advance) / app;
       gfxFloat xInFrame = pt.x - (aFramePt.x / app);
-      DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType,
+      DrawSelectionDecorations(aCtx, aDirtyRect, aSelectionType,
                                aTextPaintStyle, selectedStyle, pt, xInFrame,
                                width, mAscent / app, decorationMetrics,
                                aCallbacks, verticalRun, decorationOffsetDir,
                                kDecoration);
     }
     iterator.UpdateWithAdvance(advance);
   }
 }
 
 bool
 nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
     const gfxPoint& aFramePt,
-    const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect,
+    const gfxPoint& aTextBaselinePt, const LayoutDeviceRect& aDirtyRect,
     PropertyProvider& aProvider,
     Range aContentRange,
     nsTextPaintStyle& aTextPaintStyle,
     const nsCharClipDisplayItem::ClipEdges& aClipEdges,
     gfxTextContextPaint* aContextPaint,
     nsTextFrame::DrawPathCallbacks* aCallbacks)
 {
   NS_ASSERTION(GetContent()->IsSelectionDescendant(), "wrong paint path");
@@ -6425,17 +6406,17 @@ nsTextFrame::MeasureCharClippedText(Prop
   }
   *aMaxLength = maxLength;
   return maxLength != 0;
 }
 
 void
 nsTextFrame::PaintShadows(nsCSSShadowArray* aShadow,
                           Range aRange,
-                          const nsRect& aDirtyRect,
+                          const LayoutDeviceRect& aDirtyRect,
                           const gfxPoint& aFramePt,
                           const gfxPoint& aTextBaselinePt,
                           nscoord aLeftEdgeOffset,
                           PropertyProvider& aProvider,
                           nscolor aForegroundColor,
                           const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                           gfxContext* aCtx)
 {
@@ -6485,17 +6466,17 @@ nsTextFrame::PaintShadows(nsCSSShadowArr
                    aLeftEdgeOffset,
                    shadowMetrics.mBoundingBox,
                    blurFlags);
   }
 }
 
 void
 nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
-                       const nsRect& aDirtyRect,
+                       const LayoutDeviceRect& aDirtyRect,
                        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
   // XXX get the block and line passed to us somehow! This is slow!
@@ -6546,26 +6527,24 @@ nsTextFrame::PaintText(nsRenderingContex
   } else {
     textBaselinePt.x += reversed ? -snappedEndEdge : snappedStartEdge;
   }
   nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedStartEdge,
                                              snappedEndEdge);
   nsTextPaintStyle textPaintStyle(this);
   textPaintStyle.SetResolveColors(!aCallbacks);
 
-  gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
-                    aDirtyRect.width, aDirtyRect.height);
   // 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, dirtyRect,
+    if (PaintTextWithSelection(ctx, framePt, textBaselinePt, aDirtyRect,
                                provider, contentRange, textPaintStyle,
                                clipEdges, aContextPaint, aCallbacks)) {
       return;
     }
   }
 
   nscolor foregroundColor = textPaintStyle.GetTextColor();
   if (aOpacity != 1.0f) {
@@ -6579,17 +6558,17 @@ nsTextFrame::PaintText(nsRenderingContex
     const nsStyleText* textStyle = StyleText();
     PaintShadows(
         textStyle->mTextShadow, range, aDirtyRect, framePt, textBaselinePt,
         snappedStartEdge, provider, foregroundColor, clipEdges, ctx);
   }
 
   gfxFloat advanceWidth;
   DrawTextParams params(ctx);
-  params.dirtyRect = dirtyRect;
+  params.dirtyRect = aDirtyRect;
   params.framePt = 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;
@@ -6647,17 +6626,17 @@ nsTextFrame::DrawTextRun(Range aRange, c
 }
 
 void
 nsTextFrame::DrawTextRunAndDecorations(Range aRange,
                                        const gfxPoint& aTextBaselinePt,
                                        const DrawTextParams& aParams,
                                        const TextDecorations& aDecorations)
 {
-    const gfxFloat app =
+    const auto app =
       aParams.textStyle->PresContext()->AppUnitsPerDevPixel();
     bool verticalRun = mTextRun->IsVertical();
     bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline();
 
     // XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint?
     nscoord x = NSToCoordRound(aParams.framePt.x);
     nscoord y = NSToCoordRound(aParams.framePt.y);
 
@@ -6688,21 +6667,16 @@ nsTextFrame::DrawTextRunAndDecorations(R
     // In vertical-rl mode, block coordinates are measured from the right,
     // so we need to adjust here.
     const WritingMode wm = GetWritingMode();
     if (wm.IsVerticalRL()) {
       frameBStart += frameSize.width;
       ascent = -ascent;
     }
 
-    gfxRect dirtyRect(aParams.dirtyRect.x / app,
-                      aParams.dirtyRect.y / app,
-                      aParams.dirtyRect.Width() / app,
-                      aParams.dirtyRect.Height() / app);
-
     nscoord inflationMinFontSize =
       nsLayoutUtils::InflationMinFontSizeFor(this);
 
     // The decoration-line offsets need to be reversed for sideways-lr mode,
     // so we will multiply the values from metrics by this factor.
     gfxFloat decorationOffsetDir = mTextRun->IsSidewaysLeft() ? -1.0 : 1.0;
 
     // Underlines
@@ -6716,17 +6690,17 @@ nsTextFrame::DrawTextRunAndDecorations(R
         GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
       const gfxFont::Metrics metrics =
         GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                             useVerticalMetrics);
 
       decSize.height = metrics.underlineSize;
       bCoord = (frameBStart - dec.mBaselineOffset) / app;
 
-      PaintDecorationLine(aParams.context, dirtyRect, dec.mColor,
+      PaintDecorationLine(aParams.context, aParams.dirtyRect, dec.mColor,
         aParams.decorationOverrideColor, decPt, 0.0, decSize, ascent,
         decorationOffsetDir * metrics.underlineOffset,
         NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
         dec.mStyle, eNormalDecoration, aParams.callbacks, verticalRun);
     }
     // Overlines
     for (uint32_t i = aDecorations.mOverlines.Length(); i-- > 0; ) {
       const LineDecoration& dec = aDecorations.mOverlines[i];
@@ -6738,17 +6712,17 @@ nsTextFrame::DrawTextRunAndDecorations(R
         GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
       const gfxFont::Metrics metrics =
         GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                             useVerticalMetrics);
 
       decSize.height = metrics.underlineSize;
       bCoord = (frameBStart - dec.mBaselineOffset) / app;
 
-      PaintDecorationLine(aParams.context, dirtyRect, dec.mColor,
+      PaintDecorationLine(aParams.context, aParams.dirtyRect, dec.mColor,
         aParams.decorationOverrideColor, decPt, 0.0, decSize, ascent,
         decorationOffsetDir * metrics.maxAscent,
         NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle,
         eNormalDecoration, aParams.callbacks, verticalRun);
     }
 
     // CSS 2.1 mandates that text be painted after over/underlines, and *then*
     // line-throughs
@@ -6769,17 +6743,17 @@ nsTextFrame::DrawTextRunAndDecorations(R
         GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize);
       const gfxFont::Metrics metrics =
         GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation),
                             useVerticalMetrics);
 
       decSize.height = metrics.strikeoutSize;
       bCoord = (frameBStart - dec.mBaselineOffset) / app;
 
-      PaintDecorationLine(aParams.context, dirtyRect, dec.mColor,
+      PaintDecorationLine(aParams.context, aParams.dirtyRect, dec.mColor,
         aParams.decorationOverrideColor, decPt, 0.0, decSize, ascent,
         decorationOffsetDir * metrics.strikeoutOffset,
         NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
         dec.mStyle, eNormalDecoration, aParams.callbacks, verticalRun);
     }
 }
 
 void
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -35,16 +35,17 @@ class nsDisplayText;
 
 class nsTextFrameTextRunCache {
 public:
   static void Init();
   static void Shutdown();
 };
 
 class nsTextFrame : public nsTextFrameBase {
+  typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
   typedef mozilla::TextRangeStyle TextRangeStyle;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Point Point;
   typedef mozilla::gfx::Rect Rect;
   typedef mozilla::gfx::Size Size;
   typedef gfxTextRun::Range Range;
 
 public:
@@ -401,67 +402,68 @@ public:
     bool drawSoftHyphen = false;
     explicit DrawTextRunParams(gfxContext* aContext)
       : context(aContext) {}
   };
 
   struct DrawTextParams : DrawTextRunParams
   {
     gfxPoint framePt;
-    gfxRect dirtyRect;
+    LayoutDeviceRect dirtyRect;
     const nsTextPaintStyle* textStyle = nullptr;
     const nsCharClipDisplayItem::ClipEdges* clipEdges = nullptr;
     const nscolor* decorationOverrideColor = nullptr;
     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 nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem,
+                 const LayoutDeviceRect& aDirtyRect,
+                 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 gfxRect& aDirtyRect,
+                              const LayoutDeviceRect& aDirtyRect,
                               PropertyProvider& aProvider,
                               Range aRange,
                               nsTextPaintStyle& aTextPaintStyle,
                               const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                               gfxTextContextPaint* aContextPaint,
                               DrawPathCallbacks* aCallbacks);
   // 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 gfxRect& aDirtyRect,
+                                    const LayoutDeviceRect& aDirtyRect,
                                     PropertyProvider& aProvider,
                                     Range aContentRange,
                                     nsTextPaintStyle& aTextPaintStyle,
                                     SelectionDetails* aDetails,
                                     SelectionType* aAllTypes,
                              const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                                     DrawPathCallbacks* aCallbacks);
   // helper: paint text decorations for text selected by aSelectionType
   void PaintTextSelectionDecorations(gfxContext* aCtx,
                                      const gfxPoint& aFramePt,
                                      const gfxPoint& aTextBaselinePt,
-                                     const gfxRect& aDirtyRect,
+                                     const LayoutDeviceRect& aDirtyRect,
                                      PropertyProvider& aProvider,
                                      Range aContentRange,
                                      nsTextPaintStyle& aTextPaintStyle,
                                      SelectionDetails* aDetails,
                                      SelectionType aSelectionType,
                                      DrawPathCallbacks* aCallbacks);
 
   void DrawEmphasisMarks(gfxContext* aContext,
@@ -618,29 +620,29 @@ protected:
   // Update information of emphasis marks, and return the visial
   // overflow rect of the emphasis marks.
   nsRect UpdateTextEmphasis(mozilla::WritingMode aWM,
                             PropertyProvider& aProvider);
 
   void PaintOneShadow(Range aRange,
                       nsCSSShadowItem* aShadowDetails,
                       PropertyProvider* aProvider,
-                      const nsRect& aDirtyRect,
+                      const LayoutDeviceRect& aDirtyRect,
                       const gfxPoint& aFramePt,
                       const gfxPoint& aTextBaselinePt,
                       gfxContext* aCtx,
                       const nscolor& aForegroundColor,
                       const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                       nscoord aLeftSideOffset,
                       gfxRect& aBoundingBox,
                       uint32_t aBlurFlags);
 
   void PaintShadows(nsCSSShadowArray* aShadow,
                     Range aRange,
-                    const nsRect& aDirtyRect,
+                    const LayoutDeviceRect& aDirtyRect,
                     const gfxPoint& aFramePt,
                     const gfxPoint& aTextBaselinePt,
                     nscoord aLeftEdgeOffset,
                     PropertyProvider& aProvider,
                     nscolor aForegroundColor,
                     const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                     gfxContext* aCtx);
 
@@ -732,17 +734,17 @@ protected:
   // If the result rect is larger than the given rect, this returns true.
   bool CombineSelectionUnderlineRect(nsPresContext* aPresContext,
                                        nsRect& aRect);
 
   /**
    * Utility methods to paint selection.
    */
   void DrawSelectionDecorations(gfxContext* aContext,
-                                const gfxRect& aDirtyRect,
+                                const LayoutDeviceRect& aDirtyRect,
                                 SelectionType aType,
                                 nsTextPaintStyle& aTextPaintStyle,
                                 const TextRangeStyle &aRangeStyle,
                                 const Point& aPt,
                                 gfxFloat aICoordInFrame,
                                 gfxFloat aWidth,
                                 gfxFloat aAscent,
                                 const gfxFont::Metrics& aFontMetrics,
@@ -751,17 +753,17 @@ protected:
                                 gfxFloat aDecorationOffsetDir,
                                 uint8_t aDecoration);
   enum DecorationType
   {
     eNormalDecoration,
     eSelectionDecoration
   };
   void PaintDecorationLine(gfxContext* const aCtx,
-                           const gfxRect& aDirtyRect,
+                           const LayoutDeviceRect& aDirtyRect,
                            nscolor aColor,
                            const nscolor* aOverrideColor,
                            const Point& aPt,
                            gfxFloat aICoordInFrame,
                            const Size& aLineSize,
                            gfxFloat aAscent,
                            gfxFloat aOffset,
                            uint8_t aDecoration,
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3691,18 +3691,18 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
     if (!canvasRect.Intersects(dirtyRect)) {
       return NS_OK;
     }
   }
 
   // SVG frames' PaintSVG methods paint in CSS px, but normally frames paint in
   // dev pixels. Here we multiply a CSS-px-to-dev-pixel factor onto aTransform
   // so our non-SVG nsTextFrame children paint correctly.
-  float cssPxPerDevPx = presContext->
-    AppUnitsToFloatCSSPixels(presContext->AppUnitsPerDevPixel());
+  auto auPerDevPx = presContext->AppUnitsPerDevPixel();
+  float cssPxPerDevPx = presContext->AppUnitsToFloatCSSPixels(auPerDevPx);
   gfxMatrix canvasTMForChildren = aTransform;
   canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
   initialMatrix.Scale(1 / cssPxPerDevPx, 1 / cssPxPerDevPx);
 
   gfxContextAutoSaveRestore save(&aContext);
   aContext.NewPath();
   aContext.Multiply(canvasTMForChildren);
   gfxMatrix currentMatrix = aContext.CurrentMatrix();
@@ -3744,17 +3744,18 @@ 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)) {
-      nsRect frameRect = frame->GetVisualOverflowRect();
+      LayoutDeviceRect frameRect = LayoutDevicePixel::
+        FromAppUnits(frame->GetVisualOverflowRect(), auPerDevPx);
       bool paintSVGGlyphs;
       if (ShouldRenderAsPath(frame, paintSVGGlyphs)) {
         SVGTextDrawPathCallbacks callbacks(&rendCtx, frame,
                                            matrixForPaintServers,
                                            paintSVGGlyphs);
         frame->PaintText(&rendCtx, nsPoint(), frameRect, item,
                          &contextPaint, &callbacks);
       } else {