Bug 1301245 - Part 2. Do not resolve a style image if the given url has a fragment. r=heycam
authorcku <cku@mozilla.com>
Wed, 26 Jul 2017 11:21:30 +0800
changeset 422201 ebe4713f3fbac2e08c36ab6b85bec40d198ce719
parent 422200 76ec2bd0f25126da421ce9c9150a6a92450f5ce1
child 422202 319bc66e5d3a6599a61b686bc58ee399dac77b65
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1301245
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1301245 - Part 2. Do not resolve a style image if the given url has a fragment. r=heycam MozReview-Commit-ID: 18LFjlWZBLl
layout/generic/nsFrame.cpp
layout/painting/nsDisplayList.cpp
layout/style/nsStyleStruct.cpp
layout/svg/nsSVGIntegrationUtils.cpp
--- 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;