diff options
Diffstat (limited to 'layout')
-rw-r--r-- | layout/base/nsRefreshDriver.cpp | 45 | ||||
-rw-r--r-- | layout/reftests/svg/reftest.list | 1 | ||||
-rw-r--r-- | layout/reftests/svg/use-localRef-link.html | 16 | ||||
-rw-r--r-- | layout/svg/nsSVGEffects.cpp | 46 | ||||
-rw-r--r-- | layout/svg/nsSVGEffects.h | 14 | ||||
-rw-r--r-- | layout/svg/nsSVGOuterSVGFrame.cpp | 9 |
6 files changed, 90 insertions, 41 deletions
diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index bc1a27852..b975a69dd 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -143,11 +143,7 @@ public: { } - virtual ~RefreshDriverTimer() - { - MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); - MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); - } + NS_INLINE_DECL_REFCOUNTING(RefreshDriverTimer) virtual void AddRefreshDriver(nsRefreshDriver* aDriver) { @@ -253,6 +249,12 @@ public: } protected: + virtual ~RefreshDriverTimer() + { + MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); + MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); + } + virtual void StartTimer() = 0; virtual void StopTimer() = 0; virtual void ScheduleNextTick(TimeStamp aNowTime) = 0; @@ -335,10 +337,11 @@ protected: nsTArray<RefPtr<nsRefreshDriver> > mRootRefreshDrivers; // useful callback for nsITimer-based derived classes, here - // bacause of c++ protected shenanigans + // because of c++ protected shenanigans static void TimerTick(nsITimer* aTimer, void* aClosure) { - RefreshDriverTimer *timer = static_cast<RefreshDriverTimer*>(aClosure); + RefPtr<RefreshDriverTimer> timer = + static_cast<RefreshDriverTimer*>(aClosure); timer->Tick(); } }; @@ -459,9 +462,7 @@ public: private: // Since VsyncObservers are refCounted, but the RefreshDriverTimer are // explicitly shutdown. We create an inner class that has the VsyncObserver - // and is shutdown when the RefreshDriverTimer is deleted. The alternative is - // to (a) make all RefreshDriverTimer RefCounted or (b) use different - // VsyncObserver types. + // and is shutdown when the RefreshDriverTimer is deleted. class RefreshDriverVsyncObserver final : public VsyncObserver { public: @@ -478,6 +479,9 @@ private: bool NotifyVsync(TimeStamp aVsyncTimestamp) override { + // IMPORTANT: All paths through this method MUST hold a strong ref on + // |this| for the duration of the TickRefreshDriver callback. + if (!NS_IsMainThread()) { MOZ_ASSERT(XRE_IsParentProcess()); // Compress vsync notifications such that only 1 may run at a time @@ -498,6 +502,7 @@ private: aVsyncTimestamp); NS_DispatchToMainThread(vsyncEvent); } else { + RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this); TickRefreshDriver(aVsyncTimestamp); } @@ -572,7 +577,9 @@ private: // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer // before use. if (mVsyncRefreshDriverTimer) { - mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp); + RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer; + timer->RunRefreshDrivers(aVsyncTimestamp); + // Note: mVsyncRefreshDriverTimer might be null now. } } @@ -825,7 +832,8 @@ protected: static void TimerTickOne(nsITimer* aTimer, void* aClosure) { - InactiveRefreshDriverTimer *timer = static_cast<InactiveRefreshDriverTimer*>(aClosure); + RefPtr<InactiveRefreshDriverTimer> timer = + static_cast<InactiveRefreshDriverTimer*>(aClosure); timer->TickOne(); } @@ -877,8 +885,8 @@ NS_IMPL_ISUPPORTS(VsyncChildCreateCallback, nsIIPCBackgroundChildCreateCallback) } // namespace mozilla -static RefreshDriverTimer* sRegularRateTimer; -static InactiveRefreshDriverTimer* sThrottledRateTimer; +static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer; +static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer; #ifdef XP_WIN static int32_t sHighPrecisionTimerRequests = 0; @@ -960,8 +968,6 @@ GetFirstFrameDelay(imgIRequest* req) nsRefreshDriver::Shutdown() { // clean up our timers - delete sRegularRateTimer; - delete sThrottledRateTimer; sRegularRateTimer = nullptr; sThrottledRateTimer = nullptr; @@ -2225,16 +2231,15 @@ nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!XRE_IsParentProcess()); - auto* vsyncRefreshDriverTimer = - new VsyncRefreshDriverTimer(aVsyncChild); + RefPtr<RefreshDriverTimer> vsyncRefreshDriverTimer = + new VsyncRefreshDriverTimer(aVsyncChild); // If we are using software timer, swap current timer to // VsyncRefreshDriverTimer. if (sRegularRateTimer) { sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer); - delete sRegularRateTimer; } - sRegularRateTimer = vsyncRefreshDriverTimer; + sRegularRateTimer = vsyncRefreshDriverTimer.forget(); } void diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 520adc9e6..096628681 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -396,6 +396,7 @@ fuzzy-if(skiaContent,1,300) == tspan-xy-05.svg tspan-xy-ref.svg # bug 773482 fuzzy-if(skiaContent,1,300) == tspan-xy-06.svg tspan-xy-ref.svg # bug 773482 fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-ref.svg # bug 773482 fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-ref.svg # bug 773482 +== use-localRef-link.html pass.svg == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg == viewBox-and-pattern-01.svg pass.svg == viewBox-and-pattern-02.svg pass.svg diff --git a/layout/reftests/svg/use-localRef-link.html b/layout/reftests/svg/use-localRef-link.html new file mode 100644 index 000000000..672e9ffaa --- /dev/null +++ b/layout/reftests/svg/use-localRef-link.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<head> +<base href="/test"> +</head> +<body style="background-color: lime;"> + <svg width="100" height="100"> + <defs> + <rect id="a" x="0" y="0" width="50" height="50" fill="lime"/> + </defs> + <rect x="0" y="0" width="50" height="50" fill="red"/> + <use xlink:href="#a"/> + </svg> +</body> +</html> + + diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp index eac094a91..e75c973c8 100644 --- a/layout/svg/nsSVGEffects.cpp +++ b/layout/svg/nsSVGEffects.cpp @@ -888,24 +888,13 @@ nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame* aFrame, uint32_t aFla } } -static already_AddRefed<nsIURI> -ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) +already_AddRefed<nsIURI> +nsSVGEffects::GetBaseURLForLocalRef(nsIContent* content, nsIURI* aDocURI) { - MOZ_ASSERT(aFrame); - - if (!aURL) { - return nullptr; - } - - // Non-local-reference URL. - if (!aURL->IsLocalRef()) { - nsCOMPtr<nsIURI> result = aURL->GetURI(); - return result.forget(); - } + MOZ_ASSERT(content); // For a local-reference URL, resolve that fragment against the current // document that relative URLs are resolved against. - nsIContent* content = aFrame->GetContent(); nsCOMPtr<nsIURI> baseURI = content->OwnerDoc()->GetDocumentURI(); if (content->IsInAnonymousSubtree()) { @@ -933,12 +922,37 @@ ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) } } - if (originalURI && aURL->EqualsExceptRef(originalURI)) { - baseURI = originalURI; + if (originalURI) { + bool isEqualsExceptRef = false; + aDocURI->EqualsExceptRef(originalURI, &isEqualsExceptRef); + if (isEqualsExceptRef) { + baseURI = originalURI; + } } } } + return baseURI.forget(); +} + +static already_AddRefed<nsIURI> +ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) +{ + MOZ_ASSERT(aFrame); + + if (!aURL) { + return nullptr; + } + + // Non-local-reference URL. + if (!aURL->IsLocalRef()) { + nsCOMPtr<nsIURI> result = aURL->GetURI(); + return result.forget(); + } + + nsCOMPtr<nsIURI> baseURI = + nsSVGEffects::GetBaseURLForLocalRef(aFrame->GetContent(), aURL->GetURI()); + return aURL->ResolveLocalRef(baseURI); } diff --git a/layout/svg/nsSVGEffects.h b/layout/svg/nsSVGEffects.h index 9dd92fd31..0cf9b1500 100644 --- a/layout/svg/nsSVGEffects.h +++ b/layout/svg/nsSVGEffects.h @@ -626,11 +626,23 @@ public: static already_AddRefed<nsIURI> GetPaintURI(nsIFrame* aFrame, nsStyleSVGPaint nsStyleSVG::* aPaint); - /** + /** * A helper function to resolve SVG mask URL. */ static already_AddRefed<nsIURI> GetMaskURI(nsIFrame* aFrame, uint32_t aIndex); + + /** + * Return a baseURL for resolving a local-ref URL. + * + * @param aContent an element which uses a local-ref property. Here are some + * examples: + * <rect fill=url(#foo)> + * <circle clip-path=url(#foo)> + * <use xlink:href="#foo"> + */ + static already_AddRefed<nsIURI> + GetBaseURLForLocalRef(nsIContent* aContent, nsIURI* aDocURI); }; #endif /*NSSVGEFFECTS_H_*/ diff --git a/layout/svg/nsSVGOuterSVGFrame.cpp b/layout/svg/nsSVGOuterSVGFrame.cpp index aeadccbc5..e1b97bb40 100644 --- a/layout/svg/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/nsSVGOuterSVGFrame.cpp @@ -241,8 +241,9 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio() nsSVGLength2 &height = content->mLengthAttributes[SVGSVGElement::ATTR_HEIGHT]; if (!width.IsPercentage() && !height.IsPercentage()) { - nsSize ratio(NSToCoordRoundWithClamp(width.GetAnimValue(content)), - NSToCoordRoundWithClamp(height.GetAnimValue(content))); + nsSize ratio( + nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(content)), + nsPresContext::CSSPixelsToAppUnits(height.GetAnimValue(content))); if (ratio.width < 0) { ratio.width = 0; } @@ -272,8 +273,8 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio() if (viewBoxHeight < 0.0f) { viewBoxHeight = 0.0f; } - return nsSize(NSToCoordRoundWithClamp(viewBoxWidth), - NSToCoordRoundWithClamp(viewBoxHeight)); + return nsSize(nsPresContext::CSSPixelsToAppUnits(viewBoxWidth), + nsPresContext::CSSPixelsToAppUnits(viewBoxHeight)); } return nsSVGDisplayContainerFrame::GetIntrinsicRatio(); |