From 08b8ea9a74d2fd374cb7647beb74f9b4fc4af848 Mon Sep 17 00:00:00 2001 From: cku Date: Sat, 28 Jan 2017 02:54:38 +0800 Subject: [PATCH] Bug 1334554 - Handle the return value of nsFilterInstance::PaintFilteredFrame r=mstange MozReview-Commit-ID: 79gddAmRjnp --HG-- extra : rebase_source : a5652db96f271c5e367aedda1e2e607bec404fe4 --- layout/svg/nsFilterInstance.cpp | 99 ++++++++++++++++------------ layout/svg/nsFilterInstance.h | 20 +++--- layout/svg/nsSVGIntegrationUtils.cpp | 7 +- layout/svg/nsSVGUtils.cpp | 7 +- 4 files changed, 76 insertions(+), 57 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index 5931b4308625..35c4ae14e789 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -59,7 +59,7 @@ UserSpaceMetricsForFrame(nsIFrame* aFrame) return MakeUnique(aFrame); } -nsresult +DrawResult nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, DrawTarget* aDrawTarget, const gfxMatrix& aTransform, @@ -74,8 +74,9 @@ nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, filterChain, /* InputIsTainted */ true, aPaintCallback, aTransform, aDirtyArea, nullptr, nullptr, nullptr); if (!instance.IsInitialized()) { - return NS_OK; + return DrawResult::BAD_IMAGE; } + return instance.Render(aDrawTarget); } @@ -230,11 +231,6 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, return; } - if (mPrimitiveDescriptions.IsEmpty()) { - // Nothing should be rendered. - return; - } - // Convert the passed in rects from frame space to filter space: mPostFilterDirtyRegion = FrameSpaceToFilterSpace(aPostFilterDirtyRegion); mPreFilterDirtyRegion = FrameSpaceToFilterSpace(aPreFilterDirtyRegion); @@ -365,7 +361,7 @@ nsFilterInstance::ComputeNeededBoxes() mStrokePaint.mNeededBounds = strokePaintNeededRegion.GetBounds(); } -nsresult +DrawResult nsFilterInstance::BuildSourcePaint(SourceInfo *aSource, DrawTarget* aTargetDT) { @@ -376,13 +372,16 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource, gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( neededRect.Size(), SurfaceFormat::B8G8R8A8); if (!offscreenDT || !offscreenDT->IsValid()) { - return NS_ERROR_OUT_OF_MEMORY; + return DrawResult::TEMPORARY_ERROR; } gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform(); - if (!deviceToFilterSpace.Invert()) { - return NS_ERROR_FAILURE; - } + DebugOnly invertible = deviceToFilterSpace.Invert(); + MOZ_ASSERT(invertible, + "The returning matix of GetFilterSpaceToDeviceSpaceTransform must" + "be an invertible matrix(not a singular one), since we already" + "checked it and early return if it's not from the caller side" + "(nsFilterInstance::Render)"); if (!mPaintTransform.IsSingular()) { RefPtr gfx = gfxContext::CreateOrNull(offscreenDT); @@ -407,48 +406,52 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource, aSource->mSourceSurface = offscreenDT->Snapshot(); aSource->mSurfaceRect = neededRect; - return NS_OK; + return DrawResult::SUCCESS; } -nsresult +DrawResult nsFilterInstance::BuildSourcePaints(DrawTarget* aTargetDT) { - nsresult rv = NS_OK; - if (!mFillPaint.mNeededBounds.IsEmpty()) { - rv = BuildSourcePaint(&mFillPaint, aTargetDT); - NS_ENSURE_SUCCESS(rv, rv); + DrawResult result = BuildSourcePaint(&mFillPaint, aTargetDT); + if (result != DrawResult::SUCCESS) { + return result; + } } if (!mStrokePaint.mNeededBounds.IsEmpty()) { - rv = BuildSourcePaint(&mStrokePaint, aTargetDT); - NS_ENSURE_SUCCESS(rv, rv); + DrawResult result = BuildSourcePaint(&mStrokePaint, aTargetDT); + if (result != DrawResult::SUCCESS) { + return result; + } } - return rv; + + return DrawResult::SUCCESS; } -nsresult +DrawResult nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT) { MOZ_ASSERT(mTargetFrame); nsIntRect neededRect = mSourceGraphic.mNeededBounds; if (neededRect.IsEmpty()) { - return NS_OK; + return DrawResult::SUCCESS; } RefPtr offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( neededRect.Size(), SurfaceFormat::B8G8R8A8); if (!offscreenDT || !offscreenDT->IsValid()) { - return NS_ERROR_OUT_OF_MEMORY; + return DrawResult::TEMPORARY_ERROR; } gfxRect r = FilterSpaceToUserSpace(ThebesRect(neededRect)); r.RoundOut(); nsIntRect dirty; - if (!gfxUtils::GfxRectToIntRect(r, &dirty)) - return NS_ERROR_FAILURE; + if (!gfxUtils::GfxRectToIntRect(r, &dirty)){ + return DrawResult::SUCCESS; + } // SVG graphics paint to device space, so we need to set an initial device // space to filter space transform on the gfxContext that SourceGraphic @@ -462,9 +465,13 @@ nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT) // code more complex while being hard to get right without introducing // subtle bugs, and in practice it probably makes no real difference.) gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform(); - if (!deviceToFilterSpace.Invert()) { - return NS_ERROR_FAILURE; - } + DebugOnly invertible = deviceToFilterSpace.Invert(); + MOZ_ASSERT(invertible, + "The returning matix of GetFilterSpaceToDeviceSpaceTransform must" + "be an invertible matrix(not a singular one), since we already" + "checked it and early return if it's not from the caller side" + "(nsFilterInstance::Render)"); + RefPtr ctx = gfxContext::CreateOrNull(offscreenDT); MOZ_ASSERT(ctx); // already checked the draw target above ctx->SetMatrix( @@ -477,20 +484,25 @@ nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT) mSourceGraphic.mSourceSurface = offscreenDT->Snapshot(); mSourceGraphic.mSurfaceRect = neededRect; - return (result == DrawResult::SUCCESS) ? NS_OK : NS_ERROR_FAILURE; + return result; } -nsresult +DrawResult nsFilterInstance::Render(DrawTarget* aDrawTarget) { MOZ_ASSERT(mTargetFrame, "Need a frame for rendering"); + if (mPrimitiveDescriptions.IsEmpty()) { + // An filter without any primitive. Treat it as success and paint nothing. + return DrawResult::SUCCESS; + } + nsIntRect filterRect = mPostFilterDirtyRegion.GetBounds().Intersect(OutputFilterSpaceBounds()); gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); if (filterRect.IsEmpty() || ctm.IsSingular()) { - return NS_OK; + return DrawResult::SUCCESS; } AutoRestoreTransform autoRestoreTransform(aDrawTarget); @@ -499,13 +511,14 @@ nsFilterInstance::Render(DrawTarget* aDrawTarget) aDrawTarget->SetTransform(newTM); ComputeNeededBoxes(); - - nsresult rv = BuildSourceImage(aDrawTarget); - if (NS_FAILED(rv)) - return rv; - rv = BuildSourcePaints(aDrawTarget); - if (NS_FAILED(rv)) - return rv; + DrawResult result = BuildSourceImage(aDrawTarget); + if (result != DrawResult::SUCCESS){ + return result; + } + result = BuildSourcePaints(aDrawTarget); + if (result != DrawResult::SUCCESS){ + return result; + } FilterSupport::RenderFilterDescription( aDrawTarget, mFilterDescription, IntRectToRect(filterRect), @@ -514,13 +527,13 @@ nsFilterInstance::Render(DrawTarget* aDrawTarget) mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect, mInputImages, Point(0, 0)); - return NS_OK; + return DrawResult::SUCCESS; } nsRegion nsFilterInstance::ComputePostFilterDirtyRegion() { - if (mPreFilterDirtyRegion.IsEmpty()) { + if (mPreFilterDirtyRegion.IsEmpty() || mPrimitiveDescriptions.IsEmpty()) { return nsRegion(); } @@ -533,6 +546,10 @@ nsFilterInstance::ComputePostFilterDirtyRegion() nsRect nsFilterInstance::ComputePostFilterExtents() { + if (mPrimitiveDescriptions.IsEmpty()) { + return nsRect(); + } + nsIntRegion postFilterExtents = FilterSupport::ComputePostFilterExtents(mFilterDescription, mTargetBounds); return FilterSpaceToFrameSpace(postFilterExtents.GetBounds()); diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index f4158f1c766e..2ff8dc433457 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -55,7 +55,7 @@ class nsFilterInstance typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; typedef mozilla::gfx::FilterDescription FilterDescription; typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; - + typedef mozilla::image::DrawResult DrawResult; public: /** * Create a FilterDescription for the supplied filter. All coordinates in @@ -83,11 +83,11 @@ public: * frame space (i.e. relative to its origin, the top-left corner of its * border box). */ - static nsresult PaintFilteredFrame(nsIFrame *aFilteredFrame, - DrawTarget* aDrawTarget, - const gfxMatrix& aTransform, - nsSVGFilterPaintCallback *aPaintCallback, - const nsRegion* aDirtyArea); + static DrawResult PaintFilteredFrame(nsIFrame *aFilteredFrame, + DrawTarget* aDrawTarget, + const gfxMatrix& aTransform, + nsSVGFilterPaintCallback *aPaintCallback, + const nsRegion* aDirtyArea); /** * Returns the post-filter area that could be dirtied when the given @@ -166,7 +166,7 @@ public: * by passing it as the aPostFilterDirtyRegion argument to the * nsFilterInstance constructor. */ - nsresult Render(DrawTarget* aDrawTarget); + DrawResult Render(DrawTarget* aDrawTarget); const FilterDescription& ExtractDescriptionAndAdditionalImages(nsTArray>& aOutAdditionalImages) { @@ -228,7 +228,7 @@ private: * Creates a SourceSurface for either the FillPaint or StrokePaint graph * nodes */ - nsresult BuildSourcePaint(SourceInfo *aPrimitive, + DrawResult BuildSourcePaint(SourceInfo *aPrimitive, DrawTarget* aTargetDT); /** @@ -236,13 +236,13 @@ private: * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and * mStrokePaint.mSourceSurface respectively. */ - nsresult BuildSourcePaints(DrawTarget* aTargetDT); + DrawResult BuildSourcePaints(DrawTarget* aTargetDT); /** * Creates the SourceSurface for the SourceGraphic graph node, paints its * contents, and assigns it to mSourceGraphic.mSourceSurface. */ - nsresult BuildSourceImage(DrawTarget* aTargetDT); + DrawResult BuildSourceImage(DrawTarget* aTargetDT); /** * Build the list of FilterPrimitiveDescriptions that describes the filter's diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index bb3f52c1e371..90f3c8f4e422 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -1115,14 +1115,15 @@ nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams) offsetToUserSpace); nsRegion dirtyRegion = aParams.dirtyRect - offsetToBoundingBox; gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(frame); - nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(), - tm, &callback, &dirtyRegion); + DrawResult result = + nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(), + tm, &callback, &dirtyRegion); if (opacity != 1.0f) { context.PopGroupAndBlend(); } - return DrawResult::SUCCESS; + return result; } gfxMatrix diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 9feeb03438f2..f11c55c17995 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -860,9 +860,10 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame, dirtyRegion = &tmpDirtyRegion; } SVGPaintCallback paintCallback; - nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(), - aTransform, &paintCallback, - dirtyRegion); + result = + nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(), + aTransform, &paintCallback, + dirtyRegion); } else { result = svgChildFrame->PaintSVG(*target, aTransform, aDirtyRect); }