Bug 1302551 - Add nsDisplaySolidColorRegion and create it for elements that have the cutoutregion property set on them. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Wed, 14 Sep 2016 23:18:30 -0400
changeset 314323 eb2ab5bb69304f6081e1e33b20a7e1cf6abe23e2
parent 314322 11f62de653a855b1e96c4e9460e5045917221cb5
child 314324 4e8e39b7c8ed539688c6b7bf4b3e8ebff013e936
push id30718
push userphilringnalda@gmail.com
push dateSat, 17 Sep 2016 20:44:56 +0000
treeherdermozilla-central@eaf5eb6f8fa0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1302551
milestone51.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 1302551 - Add nsDisplaySolidColorRegion and create it for elements that have the cutoutregion property set on them. r=mattwoodrow MozReview-Commit-ID: LtXrks9Su73
layout/base/nsDisplayItemTypesList.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsDisplayListInvalidation.cpp
layout/base/nsDisplayListInvalidation.h
--- a/layout/base/nsDisplayItemTypesList.h
+++ b/layout/base/nsDisplayItemTypesList.h
@@ -45,16 +45,17 @@ DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_VIDEO)
 DECLARE_DISPLAY_ITEM_TYPE(PRINT_PLUGIN)
 DECLARE_DISPLAY_ITEM_TYPE(RANGE_FOCUS_RING)
 DECLARE_DISPLAY_ITEM_TYPE(REMOTE)
 DECLARE_DISPLAY_ITEM_TYPE(REMOTE_SHADOW)
 DECLARE_DISPLAY_ITEM_TYPE(RESOLUTION)
 DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
 DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
 DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
+DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR_REGION)
 DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT)
 DECLARE_DISPLAY_ITEM_TYPE(MASK)
 DECLARE_DISPLAY_ITEM_TYPE(FILTER)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_GLYPHS)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
 DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2383,16 +2383,47 @@ nsDisplaySolidColor::WriteDebugInfo(std:
 {
   aStream << " (rgba "
           << (int)NS_GET_R(mColor) << ","
           << (int)NS_GET_G(mColor) << ","
           << (int)NS_GET_B(mColor) << ","
           << (int)NS_GET_A(mColor) << ")";
 }
 
+nsRect
+nsDisplaySolidColorRegion::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
+{
+  *aSnap = true;
+  return mRegion.GetBounds();
+}
+
+void
+nsDisplaySolidColorRegion::Paint(nsDisplayListBuilder* aBuilder,
+                                 nsRenderingContext* aCtx)
+{
+  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  DrawTarget* drawTarget = aCtx->GetDrawTarget();
+  ColorPattern color(mColor);
+  for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
+    Rect rect =
+      NSRectToSnappedRect(iter.Get(), appUnitsPerDevPixel, *drawTarget);
+    drawTarget->FillRect(rect, color);
+  }
+}
+
+void
+nsDisplaySolidColorRegion::WriteDebugInfo(std::stringstream& aStream)
+{
+  aStream << " (rgba "
+          << int(mColor.r * 255) << ","
+          << int(mColor.g * 255) << ","
+          << int(mColor.b * 255) << ","
+          << mColor.a << ")";
+}
+
 static void
 RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                       nsITheme::ThemeGeometryType aType)
 {
   if (aBuilder->IsInRootChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
     nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
     nsRect borderBox(aFrame->GetOffsetTo(displayRoot), aFrame->GetSize());
     aBuilder->RegisterThemeGeometry(aType,
@@ -2509,16 +2540,50 @@ SetBackgroundClipRegion(DisplayListClipS
   if (clip.mHasAdditionalBGClipArea) {
     aClipState.ClipContentDescendants(clip.mAdditionalBGClipArea, clip.mBGClipArea,
                                       clip.mHasRoundedCorners ? clip.mRadii : nullptr);
   } else {
     aClipState.ClipContentDescendants(clip.mBGClipArea, clip.mHasRoundedCorners ? clip.mRadii : nullptr);
   }
 }
 
+/**
+ * This is used for the find bar highlighter overlay. It's only accessible
+ * through the AnonymousContent API, so it's not exposed to general web pages.
+ */
+static bool
+SpecialCutoutRegionCase(nsDisplayListBuilder* aBuilder,
+                        nsIFrame* aFrame,
+                        const nsRect& aBackgroundRect,
+                        nsDisplayList* aList,
+                        nscolor aColor)
+{
+  nsIContent* content = aFrame->GetContent();
+  if (!content) {
+    return false;
+  }
+
+  void* cutoutRegion = content->GetProperty(nsGkAtoms::cutoutregion);
+  if (!cutoutRegion) {
+    return false;
+  }
+
+  if (NS_GET_A(aColor) == 0) {
+    return true;
+  }
+
+  nsRegion region;
+  region.Sub(aBackgroundRect, *static_cast<nsRegion*>(cutoutRegion));
+  region.MoveBy(aBuilder->ToReferenceFrame(aFrame));
+  aList->AppendNewToTop(
+    new (aBuilder) nsDisplaySolidColorRegion(aBuilder, aFrame, region, aColor));
+
+  return true;
+}
+
 
 /*static*/ bool
 nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
                                                      nsIFrame* aFrame,
                                                      const nsRect& aBackgroundRect,
                                                      nsDisplayList* aList,
                                                      bool aAllowWillPaintBorderOptimization)
 {
@@ -2540,16 +2605,20 @@ nsDisplayBackgroundImage::AppendBackgrou
   nscolor color = NS_RGBA(0,0,0,0);
   if (!nsCSSRendering::IsCanvasFrame(aFrame) && bg) {
     bool drawBackgroundImage;
     color =
       nsCSSRendering::DetermineBackgroundColor(presContext, bgSC, aFrame,
                                                drawBackgroundImage, drawBackgroundColor);
   }
 
+  if (SpecialCutoutRegionCase(aBuilder, aFrame, aBackgroundRect, aList, color)) {
+    return false;
+  }
+
   const nsStyleBorder* borderStyle = aFrame->StyleBorder();
   const nsStyleEffects* effectsStyle = aFrame->StyleEffects();
   bool hasInsetShadow = effectsStyle->mBoxShadow &&
                         effectsStyle->mBoxShadow->HasShadowWithInset(true);
   bool willPaintBorder = aAllowWillPaintBorderOptimization &&
                          !isThemed && !hasInsetShadow &&
                          borderStyle->HasBorder();
 
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2650,16 +2650,69 @@ public:
 
   NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
 
 private:
   nsRect  mBounds;
 };
 
 /**
+ * A display item that renders a solid color over a region. This is not
+ * exposed through CSS, its only purpose is efficient invalidation of
+ * the find bar highlighter dimmer.
+ */
+class nsDisplaySolidColorRegion : public nsDisplayItem {
+  typedef mozilla::gfx::Color Color;
+
+public:
+  nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
+                            const nsRegion& aRegion, nscolor aColor)
+    : nsDisplayItem(aBuilder, aFrame), mRegion(aRegion), mColor(Color::FromABGR(aColor))
+  {
+    NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColorRegions!");
+    MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
+  }
+#ifdef NS_BUILD_REFCNT_LOGGING
+  virtual ~nsDisplaySolidColorRegion() {
+    MOZ_COUNT_DTOR(nsDisplaySolidColorRegion);
+  }
+#endif
+
+  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
+  {
+    return new nsDisplaySolidColorRegionGeometry(this, aBuilder, mRegion, mColor);
+  }
+
+  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
+                                         const nsDisplayItemGeometry* aGeometry,
+                                         nsRegion* aInvalidRegion) override
+  {
+    const nsDisplaySolidColorRegionGeometry* geometry =
+      static_cast<const nsDisplaySolidColorRegionGeometry*>(aGeometry);
+    if (mColor == geometry->mColor) {
+      aInvalidRegion->Xor(geometry->mRegion, mRegion);
+    } else {
+      aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
+    }
+  }
+
+protected:
+
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
+  virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
+  virtual void WriteDebugInfo(std::stringstream& aStream) override;
+
+  NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
+
+private:
+  nsRegion mRegion;
+  Color mColor;
+};
+
+/**
  * A display item to paint one background-image for a frame. Each background
  * image layer gets its own nsDisplayBackgroundImage.
  */
 class nsDisplayBackgroundImage : public nsDisplayImageContainer {
 public:
   /**
    * aLayer signifies which background layer this item represents.
    * aIsThemed should be the value of aFrame->IsThemed.
--- a/layout/base/nsDisplayListInvalidation.cpp
+++ b/layout/base/nsDisplayListInvalidation.cpp
@@ -101,16 +101,23 @@ nsDisplayBoxShadowInnerGeometry::MoveBy(
 }
 
 nsDisplayBoxShadowOuterGeometry::nsDisplayBoxShadowOuterGeometry(nsDisplayItem* aItem,
     nsDisplayListBuilder* aBuilder, float aOpacity)
   : nsDisplayItemGenericGeometry(aItem, aBuilder)
   , mOpacity(aOpacity)
 {}
 
+void
+nsDisplaySolidColorRegionGeometry::MoveBy(const nsPoint& aOffset)
+{
+  nsDisplayItemGeometry::MoveBy(aOffset);
+  mRegion.MoveBy(aOffset);
+}
+
 nsDisplaySVGEffectsGeometry::nsDisplaySVGEffectsGeometry(nsDisplaySVGEffects* aItem, nsDisplayListBuilder* aBuilder)
   : nsDisplayItemGeometry(aItem, aBuilder)
   , nsImageGeometryMixin(aItem, aBuilder)
   , mBBox(aItem->BBoxInUserSpace())
   , mUserSpaceOffset(aItem->UserSpaceOffset())
   , mFrameOffsetToReferenceFrame(aItem->ToReferenceFrame())
 {}
 
--- a/layout/base/nsDisplayListInvalidation.h
+++ b/layout/base/nsDisplayListInvalidation.h
@@ -16,16 +16,22 @@
 class nsDisplayBackgroundImage;
 class nsCharClipDisplayItem;
 class nsDisplayItem;
 class nsDisplayListBuilder;
 class nsDisplaySVGEffects;
 class nsDisplayTableItem;
 class nsDisplayThemedBackground;
 
+namespace mozilla {
+namespace gfx {
+struct Color;
+}
+}
+
 /**
  * This stores the geometry of an nsDisplayItem, and the area
  * that will be affected when painting the item.
  *
  * It is used to retain information about display items so they
  * can be compared against new display items in the next paint.
  */
 class nsDisplayItemGeometry
@@ -236,16 +242,34 @@ public:
                               nscolor aColor)
     : nsDisplayItemBoundsGeometry(aItem, aBuilder)
     , mColor(aColor)
   { }
 
   nscolor mColor;
 };
 
+class nsDisplaySolidColorRegionGeometry : public nsDisplayItemBoundsGeometry
+{
+public:
+  nsDisplaySolidColorRegionGeometry(nsDisplayItem* aItem,
+                                    nsDisplayListBuilder* aBuilder,
+                                    const nsRegion& aRegion,
+                                    mozilla::gfx::Color aColor)
+    : nsDisplayItemBoundsGeometry(aItem, aBuilder)
+    , mRegion(aRegion)
+    , mColor(aColor)
+  { }
+
+  virtual void MoveBy(const nsPoint& aOffset) override;
+
+  nsRegion mRegion;
+  mozilla::gfx::Color mColor;
+};
+
 class nsDisplaySVGEffectsGeometry : public nsDisplayItemGeometry
   , public nsImageGeometryMixin<nsDisplaySVGEffectsGeometry>
 {
 public:
   nsDisplaySVGEffectsGeometry(nsDisplaySVGEffects* aItem, nsDisplayListBuilder* aBuilder);
 
   virtual void MoveBy(const nsPoint& aOffset) override;