Bug 1301245 - Part 2. Do not resolve a style image if the given url has a fragment.
MozReview-Commit-ID: 18LFjlWZBLl
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -843,44 +843,45 @@ AddAndRemoveImageAssociations(nsFrame* a
// We want to do this conservatively because some frames paint their
// backgrounds from some other frame's style data, and we don't want
// to clear those notifiers unless we have to. (They'll be reset
// when we paint, although we could miss a notification in that
// interval.)
if (aOldLayers) {
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aOldLayers)) {
+ const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
+ if (oldImage.GetType() != eStyleImageType_Image ||
+ !oldImage.IsResolved()) {
+ continue;
+ }
+
// If there is an image in oldBG that's not in newBG, drop it.
if (i >= aNewLayers->mImageCount ||
- !aOldLayers->mLayers[i].mImage.ImageDataEquals(
- aNewLayers->mLayers[i].mImage)) {
- const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
- if (oldImage.GetType() != eStyleImageType_Image) {
- continue;
- }
+ !oldImage.ImageDataEquals(aNewLayers->mLayers[i].mImage)) {
if (aFrame->HasImageRequest()) {
if (imgRequestProxy* req = oldImage.GetImageData()) {
imageLoader->DisassociateRequestFromFrame(req, aFrame);
}
}
}
}
}
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
+ const nsStyleImage& newImage = aNewLayers->mLayers[i].mImage;
+ if (newImage.GetType() != eStyleImageType_Image ||
+ !newImage.IsResolved()) {
+ continue;
+ }
+
// 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) {
- continue;
- }
-
+ !newImage.ImageDataEquals(aOldLayers->mLayers[i].mImage)) {
if (imgRequestProxy* req = newImage.GetImageData()) {
imageLoader->AssociateRequestToFrame(req, aFrame);
}
}
}
}
// Subclass hook for style post processing
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8550,16 +8550,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
@@ -1200,17 +1200,28 @@ nsStyleSVGReset::Destroy(nsPresContext*
}
void
nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
- mMask.ResolveImages(aPresContext);
+ NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
+ nsStyleImage& image = mMask.mLayers[i].mImage;
+ if (image.GetType() == eStyleImageType_Image) {
+ // If the url of mask resource contains a reference('#'), it should be a
+ // <mask-source>, mostly. For a <mask-source>, there is no need to
+ // resolve this style image, since we do not depend on it to get the
+ // SVG mask resource.
+ if (!image.GetURLValue()->HasRef()) {
+ image.ResolveImage(aPresContext);
+ }
+ }
+ }
}
nsChangeHint
nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
{
nsChangeHint hint = nsChangeHint(0);
if (!mClipPath.DefinitelyEquals(aNewData.mClipPath)) {
@@ -2455,16 +2466,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/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -478,33 +478,35 @@ PaintMaskSurface(const PaintFramesParams
if (svgMask) {
gfxContextMatrixAutoSaveRestore matRestore(maskContext);
maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
aMaskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
Point(0, 0),
DrawOptions(1.0, compositionOp));
}
- } else {
+ } else if (svgReset->mMask.mLayers[i].mImage.IsResolved()) {
gfxContextMatrixAutoSaveRestore matRestore(maskContext);
maskContext->Multiply(gfxMatrix::Translation(-devPixelOffsetToUserSpace));
nsCSSRendering::PaintBGParams params =
nsCSSRendering::PaintBGParams::ForSingleLayer(*presContext,
aParams.dirtyRect,
aParams.borderArea,
aParams.frame,
aParams.builder->GetBackgroundPaintFlags() |
nsCSSRendering::PAINTBG_MASK_IMAGE,
i, compositionOp,
aOpacity);
aParams.imgParams.result &=
nsCSSRendering::PaintStyleImageLayerWithSC(params, *maskContext, aSC,
*aParams.frame->StyleBorder());
+ } else {
+ aParams.imgParams.result &= DrawResult::NOT_READY;
}
}
}
struct MaskPaintResult {
RefPtr<SourceSurface> maskSurface;
Matrix maskTransform;
bool transparentBlackMask;