Bug 1302551 - Add nsDisplaySolidColorRegion and create it for elements that have the cutoutregion property set on them. r?mattwoodrow
MozReview-Commit-ID: LtXrks9Su73
--- 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;