Bug 1251995 part 5 - Unify units of dirty rect used for painting text frame. draft
authorXidorn Quan <quanxunzhen@gmail.com>
Tue, 01 Mar 2016 16:28:27 +0800
changeset 337293 931243b0a6fa86f8448675467ebef3f50bb070a9
parent 337292 b8c207e835b72876eccf2cc4ab1992909ff1302c
child 337294 9ba0ca774b229cb2f265a27331488555ef4f310f
push id12307
push userxquan@mozilla.com
push dateMon, 07 Mar 2016 02:21:17 +0000
bugs1251995
milestone47.0a1
Bug 1251995 part 5 - Unify units of dirty rect used for painting text frame. 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 {