Bug 1493353 - Clip TextDrawTarget to the visible rect, and avoid emitting display items that are outside the clipped area. r=jrmuizel
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 14 Dec 2018 22:30:08 +0000
changeset 450604 d8a944c012a7a814ee5a5fea4c9075969451a48b
parent 450603 166eac2f9e58007dc36694d30523001b0bb30a8b
child 450810 d86d184dc7d6aa246ada69063e07dbb503c33092
child 450811 4f56dfffb7594b7a3b88109549fe251324013a09
push id35207
push useraciure@mozilla.com
push dateSat, 15 Dec 2018 02:27:37 +0000
treeherdermozilla-central@d8a944c012a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1493353
milestone66.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 1493353 - Clip TextDrawTarget to the visible rect, and avoid emitting display items that are outside the clipped area. r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D14367
gfx/thebes/gfxFontMissingGlyphs.cpp
layout/generic/TextDrawTarget.h
layout/generic/nsTextFrame.cpp
--- a/gfx/thebes/gfxFontMissingGlyphs.cpp
+++ b/gfx/thebes/gfxFontMissingGlyphs.cpp
@@ -332,18 +332,18 @@ static void DrawHexChar(uint32_t aDigit,
       bounds.height = fabs(bounds.height);
       dest = aMat->TransformRect(dest);
       dest.x += std::min(dest.width, 0.0f);
       dest.y += std::min(dest.height, 0.0f);
       dest.width = fabs(dest.width);
       dest.height = fabs(dest.height);
     }
     // Finally, push the colored image with point filtering.
-    tdt->PushImage(key, wr::ToLayoutRect(bounds), wr::ToLayoutRect(dest),
-                   wr::ImageRendering::Pixelated, wr::ToColorF(aColor));
+    tdt->PushImage(key, bounds, dest, wr::ImageRendering::Pixelated,
+                   wr::ToColorF(aColor));
   } else {
     // For the normal case, just draw the given digit from the atlas. Point
     // filtering is used to ensure the mini-font rectangles stay sharp with any
     // scaling. Handle any transparency here as well.
     aDrawTarget.DrawSurface(
         aAtlas, dest,
         Rect(aDigit * MINIFONT_WIDTH, 0, MINIFONT_WIDTH, MINIFONT_HEIGHT),
         DrawSurfaceOptions(SamplingFilter::POINT),
--- a/layout/generic/TextDrawTarget.h
+++ b/layout/generic/TextDrawTarget.h
@@ -325,26 +325,30 @@ class TextDrawTarget : public DrawTarget
     wr::ImageDescriptor desc(aSize, aStride, aFormat);
     Range<uint8_t> bytes(const_cast<uint8_t*>(aData), aStride * aSize.height);
     if (mResources->AddImage(key, desc, bytes)) {
       return Some(key);
     }
     return Nothing();
   }
 
-  void PushImage(wr::ImageKey aKey, const wr::LayoutRect& aBounds,
-                 const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
-                 const wr::ColorF& aColor) {
-    mBuilder.PushImage(aBounds, aClip, true, aFilter, aKey, true, aColor);
+  void PushImage(wr::ImageKey aKey, const Rect& aBounds, const Rect& aClip,
+                 wr::ImageRendering aFilter, const wr::ColorF& aColor) {
+    if (!aClip.Intersects(GeckoClipRect().ToUnknownRect())) {
+      return;
+    }
+    mBuilder.PushImage(wr::ToLayoutRect(aBounds), wr::ToLayoutRect(aClip), true,
+                       aFilter, aKey, true, aColor);
   }
 
  private:
   wr::LayoutRect ClipRect() {
     return wr::ToRoundedLayoutRect(mClipStack.LastElement());
   }
+  LayoutDeviceRect GeckoClipRect() { return mClipStack.LastElement(); }
   // Whether anything unsupported was encountered. Currently:
   //
   // * Synthetic bold/italics
   // * SVG fonts
   // * Unserializable fonts
   // * Tofu glyphs
   // * Pratial ligatures
   // * Text writing-mode
@@ -433,16 +437,19 @@ class TextDrawTarget : public DrawTarget
                    const IntPoint& aDestination) override {
     MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
   }
 
   void FillRect(const Rect& aRect, const Pattern& aPattern,
                 const DrawOptions& aOptions = DrawOptions()) override {
     MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
 
+    if (!aRect.Intersects(GeckoClipRect().ToUnknownRect())) {
+      return;
+    }
     auto rect =
         wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
     auto color =
         wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
     mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
   }
 
   void StrokeRect(const Rect& aRect, const Pattern& aPattern,
@@ -456,20 +463,22 @@ class TextDrawTarget : public DrawTarget
         aStrokeOptions.mLineWidth, aStrokeOptions.mLineWidth};
     wr::ColorF color =
         wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
     wr::BorderSide sides[4] = {{color, wr::BorderStyle::Solid},
                                {color, wr::BorderStyle::Solid},
                                {color, wr::BorderStyle::Solid},
                                {color, wr::BorderStyle::Solid}};
     wr::BorderRadius radius = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
-    Rect rect(aRect);
+    LayoutDeviceRect rect = LayoutDeviceRect::FromUnknownRect(aRect);
     rect.Inflate(aStrokeOptions.mLineWidth / 2);
-    wr::LayoutRect bounds =
-        wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(rect));
+    if (!rect.Intersects(GeckoClipRect())) {
+      return;
+    }
+    wr::LayoutRect bounds = wr::ToRoundedLayoutRect(rect);
     mBuilder.PushBorder(bounds, ClipRect(), true, widths,
                         Range<const wr::BorderSide>(sides, 4), radius);
   }
 
   void StrokeLine(const Point& aStart, const Point& aEnd,
                   const Pattern& aPattern, const StrokeOptions& aStrokeOptions,
                   const DrawOptions& aOptions) override {
     MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4949,18 +4949,23 @@ bool nsDisplayText::CreateWebRenderComma
     return true;
   }
 
   auto appUnitsPerDevPixel = Frame()->PresContext()->AppUnitsPerDevPixel();
   gfx::Point deviceOffset =
       LayoutDevicePoint::FromAppUnits(mBounds.TopLeft(), appUnitsPerDevPixel)
           .ToUnknownPoint();
 
+  nsRect visible = GetPaintRect();
+  visible.Inflate(3 * appUnitsPerDevPixel);
+
+  visible = visible.Intersect(mBounds);
+
   RefPtr<gfxContext> textDrawer = aBuilder.GetTextContext(
-      aResources, aSc, aManager, this, mBounds, deviceOffset);
+      aResources, aSc, aManager, this, visible, deviceOffset);
 
   RenderToContext(textDrawer, aDisplayListBuilder, true);
 
   return textDrawer->GetTextDrawer()->Finish();
 }
 
 void nsDisplayText::RenderToContext(gfxContext* aCtx,
                                     nsDisplayListBuilder* aBuilder,