Bug 1301245 - Part 4. Delay image mask download.
Kick off image mask download after we failed to get the specific SVG mask
resource.
MozReview-Commit-ID: DM0xVjAFrC9
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -867,17 +867,18 @@ AddAndRemoveImageAssociations(nsFrame* a
}
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
// If there is an image in newBG that's not in oldBG, add it.
if (!aOldLayers || i >= aOldLayers->mImageCount ||
!aNewLayers->mLayers[i].mImage.ImageDataEquals(
aOldLayers->mLayers[i].mImage)) {
const nsStyleImage& newImage = aNewLayers->mLayers[i].mImage;
- if (newImage.GetType() != eStyleImageType_Image) {
+ if (newImage.GetType() != eStyleImageType_Image ||
+ !newImage.IsResolved()) {
continue;
}
if (imgRequestProxy* req = newImage.GetImageData()) {
imageLoader->AssociateRequestToFrame(req, aFrame);
}
}
}
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8434,16 +8434,19 @@ nsDisplayMask::nsDisplayMask(nsDisplayLi
{
MOZ_COUNT_CTOR(nsDisplayMask);
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags() |
nsCSSRendering::PAINTBG_MASK_IMAGE;
const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
+ if (!svgReset->mMask.mLayers[i].mImage.IsResolved()) {
+ continue;
+ }
bool isTransformedFixed;
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, aFrame, flags,
mFrame->GetRectRelativeToSelf(),
mFrame->GetRectRelativeToSelf(),
svgReset->mMask.mLayers[i],
&isTransformedFixed);
mDestRects.AppendElement(state.mDestArea);
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2455,16 +2455,19 @@ nsStyleImage::IsComplete() const
switch (mType) {
case eStyleImageType_Null:
return false;
case eStyleImageType_Gradient:
case eStyleImageType_Element:
case eStyleImageType_URL:
return true;
case eStyleImageType_Image: {
+ if (!IsResolved()) {
+ return false;
+ }
imgRequestProxy* req = GetImageData();
if (!req) {
return false;
}
uint32_t status = imgIRequest::STATUS_ERROR;
return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
(status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
(status & imgIRequest::STATUS_FRAME_COMPLETE);
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -14,16 +14,17 @@
#include "nsSVGClipPathFrame.h"
#include "nsSVGPaintServerFrame.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsIReflowCallback.h"
#include "nsCycleCollectionParticipant.h"
#include "SVGGeometryElement.h"
#include "SVGUseElement.h"
+#include "ImageLoader.h"
using namespace mozilla;
using namespace mozilla::dom;
void
nsSVGRenderingObserver::StartListening()
{
Element* target = GetTarget();
@@ -387,16 +388,17 @@ nsSVGMarkerProperty::DoUpdate()
}
frame->PresContext()->RestyleManager()->PostRestyleEvent(
frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
}
NS_IMPL_ISUPPORTS(nsSVGMaskProperty, nsISupports)
nsSVGMaskProperty::nsSVGMaskProperty(nsIFrame* aFrame)
+ : mFrame(aFrame)
{
const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
for (uint32_t i = 0; i < svgReset->mMask.mImageCount; i++) {
nsCOMPtr<nsIURI> maskUri = nsSVGEffects::GetMaskURI(aFrame, i);
bool hasRef = false;
if (maskUri) {
maskUri->GetHasRef(&hasRef);
@@ -408,16 +410,37 @@ nsSVGMaskProperty::nsSVGMaskProperty(nsI
} else {
nsSVGPaintingProperty* prop = new nsSVGPaintingProperty(maskUri, aFrame,
false);
mProperties.AppendElement(prop);
}
}
}
+void
+nsSVGMaskProperty::ResolveImage(uint32_t aIndex)
+{
+ const nsStyleSVGReset *svgReset = mFrame->StyleSVGReset();
+ MOZ_ASSERT(aIndex <= svgReset->mMask.mImageCount);
+
+ nsStyleImage& image =
+ const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
+
+ if (!image.IsResolved()) {
+ MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
+ image.ResolveImage(mFrame->PresContext());
+
+ mozilla::css::ImageLoader* imageLoader =
+ mFrame->PresContext()->Document()->StyleImageLoader();
+ if (imgRequestProxy* req = image.GetImageData()) {
+ imageLoader->AssociateRequestToFrame(req, mFrame);
+ }
+ }
+}
+
bool
nsSVGTextPathProperty::TargetIsValid()
{
Element* target = GetTarget();
return target && target->IsSVGElement(nsGkAtoms::path);
}
void
@@ -672,22 +695,30 @@ nsSVGEffects::EffectProperties::GetMaskS
bool ok = true;
maskFrame = static_cast<nsSVGMaskFrame*>(
props[i]->GetReferencedFrame(LayoutFrameType::SVGMask, &ok));
MOZ_ASSERT(!maskFrame || ok);
MOZ_ASSERT_IF(!ok, !maskFrame);
if (!ok) {
type = MaskSourceType::ImageMask;
+ // We can not find the specific SVG mask resoruce after the external
+ // resoruce was downloaded and parsed.
+ // It's right time to kick off style image download.
+ mMask->ResolveImage(i);
} else {
type = maskFrame ? MaskSourceType::SVGMask
: MaskSourceType::Uncertain;
}
} else {
type = MaskSourceType::ImageMask;
+ // props[i] is nullptr, which means we already know the given mask URL
+ // can not be an SVG mask. (See the comment in
+ // nsSVGMaskProperty::nsSVGMaskProperty)
+ mMask->ResolveImage(i);
}
MOZ_ASSERT_IF(type == MaskSourceType::SVGMask, maskFrame);
MOZ_ASSERT_IF(type == MaskSourceType::ImageMask ||
type == MaskSourceType::Uncertain, !maskFrame);
result.AppendElement(MakePair(type, maskFrame));
}
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -350,19 +350,22 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
const nsTArray<RefPtr<nsSVGPaintingProperty>>& GetProps() const
{
return mProperties;
}
+ void ResolveImage(uint32_t aIndex);
+
private:
virtual ~nsSVGMaskProperty() {}
nsTArray<RefPtr<nsSVGPaintingProperty>> mProperties;
+ nsIFrame* mFrame;
};
/**
* A manager for one-shot nsSVGRenderingObserver tracking.
* nsSVGRenderingObservers can be added or removed. They are not strongly
* referenced so an observer must be removed before it dies.
* When InvalidateAll is called, all outstanding references get
* InvalidateViaReferencedElement()