From 756b5124bcfe05ee67e1e578f094cb75a7d04cae Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 18 Mar 2019 16:24:20 +0000 Subject: [PATCH] Bug 1525372 - Add background-clip:text rendering observer so that we get notified of changes to the clipped contents. r=jwatt Differential Revision: https://phabricator.services.mozilla.com/D20110 --HG-- extra : moz-landing-system : lando --- layout/painting/nsDisplayList.cpp | 2 ++ layout/svg/SVGObserverUtils.cpp | 43 +++++++++++++++++++++++++++++++ layout/svg/SVGObserverUtils.h | 6 +++++ 3 files changed, 51 insertions(+) diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 65af591267fd..9ff2e2cfc4ab 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -813,6 +813,8 @@ static bool GenerateAndPushTextMask(nsIFrame* aFrame, gfxContext* aContext, return false; } + SVGObserverUtils::GetAndObserveBackgroundClip(aFrame); + // The main function of enabling background-clip:text property value. // When a nsDisplayBackgroundImage detects "text" bg-clip style, it will call // this function to diff --git a/layout/svg/SVGObserverUtils.cpp b/layout/svg/SVGObserverUtils.cpp index 5b0b6f70f89d..a17a52682b62 100644 --- a/layout/svg/SVGObserverUtils.cpp +++ b/layout/svg/SVGObserverUtils.cpp @@ -459,6 +459,34 @@ class SVGMozElementObserver final : public nsSVGPaintingProperty { bool ObservesReflow() override { return true; } }; +class BackgroundClipRenderingObserver : public SVGRenderingObserver { + public: + explicit BackgroundClipRenderingObserver(nsIFrame* aFrame) : mFrame(aFrame) {} + + NS_DECL_ISUPPORTS + + private: + virtual ~BackgroundClipRenderingObserver() { StopObserving(); } + + Element* GetReferencedElementWithoutObserving() final { + return mFrame->GetContent()->AsElement(); + } + + void OnRenderingChange() final; + bool ObservesReflow() final { return true; } + + nsIFrame* mFrame; +}; + +NS_IMPL_ISUPPORTS(BackgroundClipRenderingObserver, nsIMutationObserver) + +void BackgroundClipRenderingObserver::OnRenderingChange() { + for (nsIFrame* f = mFrame; f; + f = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(f)) { + f->InvalidateFrame(); + } +} + /** * In a filter chain, there can be multiple SVG reference filters. * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2); @@ -991,6 +1019,8 @@ NS_DECLARE_FRAME_PROPERTY_RELEASABLE(HrefAsTextPathProperty, SVGTextPathObserver) NS_DECLARE_FRAME_PROPERTY_DELETABLE(BackgroundImageProperty, URIObserverHashtable) +NS_DECLARE_FRAME_PROPERTY_RELEASABLE(BackgroundClipObserverProperty, + BackgroundClipRenderingObserver) template static T* GetEffectProperty( @@ -1355,6 +1385,19 @@ Element* SVGObserverUtils::GetAndObserveBackgroundImage(nsIFrame* aFrame, return observer->GetAndObserveReferencedElement(); } +Element* SVGObserverUtils::GetAndObserveBackgroundClip(nsIFrame* aFrame) { + bool found; + BackgroundClipRenderingObserver* obs = + aFrame->GetProperty(BackgroundClipObserverProperty(), &found); + if (!found) { + obs = new BackgroundClipRenderingObserver(aFrame); + NS_ADDREF(obs); + aFrame->AddProperty(BackgroundClipObserverProperty(), obs); + } + + return obs->GetAndObserveReferencedElement(); +} + nsSVGPaintServerFrame* SVGObserverUtils::GetAndObservePaintServer( nsIFrame* aTargetFrame, nsStyleSVGPaint nsStyleSVG::*aPaint) { // If we're looking at a frame within SVG text, then we need to look up diff --git a/layout/svg/SVGObserverUtils.h b/layout/svg/SVGObserverUtils.h index 75fea6dedccf..145ef781e417 100644 --- a/layout/svg/SVGObserverUtils.h +++ b/layout/svg/SVGObserverUtils.h @@ -393,6 +393,12 @@ class SVGObserverUtils { static Element* GetAndObserveBackgroundImage(nsIFrame* aFrame, const nsAtom* aHref); + /** + * Gets an arbitrary element and starts observing it. Used to detect + * invalidation changes for background-clip:text. + */ + static Element* GetAndObserveBackgroundClip(nsIFrame* aFrame); + /** * A helper function to resolve filter URL. */