Bug 686281 - Remove nsStyleSVGReset::mMask; r?dbaron draft
authorCJKu <cku@mozilla.com>
Mon, 21 Dec 2015 11:32:35 +0800
changeset 316600 165a29e74256176d1c4acdf075d094900e28d7af
parent 316599 ce9056784fadba83cb0b37c37bfc4faaca2aa49a
child 316601 3e1b648f1945a520d42710c3f5abbacfe9988685
push id8575
push usercku@mozilla.com
push dateMon, 21 Dec 2015 03:33:13 +0000
reviewersdbaron
bugs686281
milestone45.0a1
Bug 686281 - Remove nsStyleSVGReset::mMask; r?dbaron
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsSVGEffects.cpp
layout/svg/nsSVGIntegrationUtils.cpp
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -5848,21 +5848,21 @@ nsComputedDOMStyle::DoGetMask()
       firstLayer.mMaskMode != NS_STYLE_MASK_MODE_AUTO ||
       !nsStyleImageLayers::Position::IsInitialValue(firstLayer.mPosition) ||
       !nsStyleImageLayers::Repeat::IsInitialValue(firstLayer.mRepeat) ||
       !nsStyleImageLayers::Size::IsInitialValue(firstLayer.mSize)){
     return nullptr;
   }
 
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
-
-  if (svg->mMask)
-    val->SetURI(svg->mMask);
-  else
+  if (firstLayer.mSourceURI) {
+    val->SetURI(firstLayer.mSourceURI);
+  } else {
     val->SetIdent(eCSSKeyword_none);
+  }
 
   return val;
 }
 
 CSSValue*
 nsComputedDOMStyle::DoGetMaskClip()
 {
   return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -6435,16 +6435,31 @@ struct BackgroundItemComputer<nsCSSValue
                            nsStyleImage& aComputedValue,
                            RuleNodeCacheConditions& aConditions)
   {
     SetStyleImage(aStyleContext, aSpecifiedValue->mValue, aComputedValue,
                   aConditions);
   }
 };
 
+template <>
+struct BackgroundItemComputer<nsCSSValueList, nsCOMPtr<nsIURI> >
+{
+  static void ComputeValue(nsStyleContext* aStyleContext,
+                           const nsCSSValueList* aSpecifiedValue,
+                           nsCOMPtr<nsIURI>& aComputedValue,
+                           RuleNodeCacheConditions& aConditions)
+  {
+    if (eCSSUnit_URL == aSpecifiedValue->mValue.GetUnit() ||
+       eCSSUnit_Image == aSpecifiedValue->mValue.GetUnit()) {
+      aComputedValue = aSpecifiedValue->mValue.GetURLValue();
+    }
+  }
+};
+
 /* Helper function for ComputePositionValue.
  * This function computes a single PositionCoord from two nsCSSValue objects,
  * which represent an edge and an offset from that edge.
  */
 typedef nsStyleImageLayers::Position::PositionCoord PositionCoord;
 static void
 ComputePositionCoord(nsStyleContext* aStyleContext,
                      const nsCSSValue& aEdge,
@@ -6666,16 +6681,17 @@ SetImageLayerList(nsStyleContext* aStyle
     aItemCount = aParentItemCount;
     for (uint32_t i = 0; i < aParentItemCount; ++i) {
       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
     }
     break;
 
   case eCSSUnit_Initial:
   case eCSSUnit_Unset:
+  case eCSSUnit_None:
     aRebuild = true;
     aItemCount = 1;
     aLayers[0].*aResultLocation = aInitialValue;
     break;
 
   case eCSSUnit_List:
   case eCSSUnit_ListDep: {
     aRebuild = true;
@@ -6733,16 +6749,17 @@ SetImageLayerPairList(nsStyleContext* aS
     aItemCount = aParentItemCount;
     for (uint32_t i = 0; i < aParentItemCount; ++i) {
       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
     }
     break;
 
   case eCSSUnit_Initial:
   case eCSSUnit_Unset:
+  case eCSSUnit_None:
     aRebuild = true;
     aItemCount = 1;
     aLayers[0].*aResultLocation = aInitialValue;
     break;
 
   case eCSSUnit_PairList:
   case eCSSUnit_PairListDep: {
     aRebuild = true;
@@ -9673,34 +9690,16 @@ nsRuleNode::ComputeSVGResetData(void* aS
         cur = cur->mNext;
       }
       break;
     }
     default:
       NS_NOTREACHED("unexpected unit");
   }
 
-  // mask: url, none, inherit
-  const nsCSSValue* maskValue = aRuleData->ValueForMaskImage();
-  if (eCSSUnit_List == maskValue->GetUnit() ||
-      eCSSUnit_ListDep == maskValue->GetUnit()) {
-    const nsCSSValue& item = maskValue->GetListValue()->mValue;
-    if (eCSSUnit_URL == item.GetUnit() ||
-        eCSSUnit_Image == item.GetUnit()) {
-      svgReset->mMask = item.GetURLValue();
-    }
-  } else if (eCSSUnit_None == maskValue->GetUnit() ||
-             eCSSUnit_Initial == maskValue->GetUnit() ||
-             eCSSUnit_Unset == maskValue->GetUnit()) {
-    svgReset->mMask = nullptr;
-  } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
-    conditions.SetUncacheable();
-    svgReset->mMask = parentSVGReset->mMask;
-  }
-
   // mask-type: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForMaskType(),
               svgReset->mMaskType,
               conditions,
               SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
               parentSVGReset->mMaskType,
               NS_STYLE_MASK_TYPE_LUMINANCE, 0, 0, 0, 0);
 
@@ -9711,16 +9710,23 @@ nsRuleNode::ComputeSVGResetData(void* aS
   nsStyleImage initialImage;
   SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
                     svgReset->mLayers.mLayers,
                     parentSVGReset->mLayers.mLayers,
                     &nsStyleImageLayers::Layer::mImage,
                     initialImage, parentSVGReset->mLayers.mImageCount,
                     svgReset->mLayers.mImageCount,
                     maxItemCount, rebuild, conditions);
+  SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
+                    svgReset->mLayers.mLayers,
+                    parentSVGReset->mLayers.mLayers,
+                    &nsStyleImageLayers::Layer::mSourceURI,
+                    nsCOMPtr<nsIURI>(), parentSVGReset->mLayers.mImageCount,
+                    svgReset->mLayers.mImageCount,
+                    maxItemCount, rebuild, conditions);
 
   // mask-repeat: enum, inherit, initial [pair list]
   nsStyleImageLayers::Repeat initialRepeat;
   initialRepeat.SetInitialValues();
   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
                         svgReset->mLayers.mLayers,
                         parentSVGReset->mLayers.mLayers,
                         &nsStyleImageLayers::Layer::mRepeat,
@@ -9794,16 +9800,19 @@ nsRuleNode::ComputeSVGResetData(void* aS
     svgReset->mLayers.mLayers.TruncateLength(maxItemCount);
 
     uint32_t fillCount = svgReset->mLayers.mImageCount;
 
     FillBackgroundList(svgReset->mLayers.mLayers,
                        &nsStyleImageLayers::Layer::mImage,
                        svgReset->mLayers.mImageCount, fillCount);
     FillBackgroundList(svgReset->mLayers.mLayers,
+                       &nsStyleImageLayers::Layer::mSourceURI,
+                       svgReset->mLayers.mImageCount, fillCount);
+    FillBackgroundList(svgReset->mLayers.mLayers,
                        &nsStyleImageLayers::Layer::mRepeat,
                        svgReset->mLayers.mRepeatCount, fillCount);
     FillBackgroundList(svgReset->mLayers.mLayers,
                        &nsStyleImageLayers::Layer::mClip,
                        svgReset->mLayers.mClipCount, fillCount);
     FillBackgroundList(svgReset->mLayers.mLayers,
                        &nsStyleImageLayers::Layer::mOrigin,
                        svgReset->mLayers.mOriginCount, fillCount);
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1275,17 +1275,16 @@ nsStyleFilter::SetDropShadow(nsCSSShadow
 // nsStyleSVGReset
 //
 nsStyleSVGReset::nsStyleSVGReset()
 {
   MOZ_COUNT_CTOR(nsStyleSVGReset);
   mStopColor               = NS_RGB(0,0,0);
   mFloodColor              = NS_RGB(0,0,0);
   mLightingColor           = NS_RGB(255,255,255);
-  mMask                    = nullptr;
   mStopOpacity             = 1.0f;
   mFloodOpacity            = 1.0f;
   mDominantBaseline        = NS_STYLE_DOMINANT_BASELINE_AUTO;
   mVectorEffect            = NS_STYLE_VECTOR_EFFECT_NONE;
   mMaskType                = NS_STYLE_MASK_TYPE_LUMINANCE;
 }
 
 nsStyleSVGReset::~nsStyleSVGReset()
@@ -1297,17 +1296,16 @@ nsStyleSVGReset::nsStyleSVGReset(const n
   : mLayers(aSource.mLayers)
 {
   MOZ_COUNT_CTOR(nsStyleSVGReset);
   mStopColor = aSource.mStopColor;
   mFloodColor = aSource.mFloodColor;
   mLightingColor = aSource.mLightingColor;
   mClipPath = aSource.mClipPath;
   mFilters = aSource.mFilters;
-  mMask = aSource.mMask;
   mStopOpacity = aSource.mStopOpacity;
   mFloodOpacity = aSource.mFloodOpacity;
   mDominantBaseline = aSource.mDominantBaseline;
   mVectorEffect = aSource.mVectorEffect;
   mMaskType = aSource.mMaskType;
 }
 
 void nsStyleSVGReset::Destroy(nsPresContext* aContext) {
@@ -1318,23 +1316,22 @@ void nsStyleSVGReset::Destroy(nsPresCont
     FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
 }
 
 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   if (mClipPath != aOther.mClipPath ||
-      !EqualURIs(mMask, aOther.mMask) ||
       mFilters != aOther.mFilters) {
     NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
     NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
     // We only actually need to update the overflow area for filter
-    // changes.  However, mask and clip-path changes require that we
-    // update the PreEffectsBBoxProperty, which is done during overflow
+    // changes.  However, clip-path changes require that we update
+    // the PreEffectsBBoxProperty, which is done during overflow
     // computation.
     NS_UpdateHint(hint, nsChangeHint_UpdateOverflow);
   }
 
   if (mDominantBaseline != aOther.mDominantBaseline) {
     // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
     NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
   } else if (mVectorEffect  != aOther.mVectorEffect) {
@@ -2408,17 +2405,17 @@ nsStyleImageLayers::CalcDifference(const
     NS_UpdateHint(aHint, nsChangeHint_NeutralChange);
   }
 }
 
 bool
 nsStyleImageLayers::HasValidLayers() const
 {
   for (uint32_t i = 0; i < mImageCount; i++) {
-    if (!mLayers[i].mImage.IsEmpty()) {
+    if (mLayers[i].mSourceURI) {
       return true;
     }
   }
 
   return false;
 }
 
 /* static */
@@ -2613,37 +2610,46 @@ nsStyleImageLayers::Layer::operator==(co
          mClip == aOther.mClip &&
          mOrigin == aOther.mOrigin &&
          mRepeat == aOther.mRepeat &&
          mBlendMode == aOther.mBlendMode &&
          mPosition == aOther.mPosition &&
          mSize == aOther.mSize &&
          mImage == aOther.mImage &&
          mMaskMode == aOther.mMaskMode &&
-         mComposite == aOther.mComposite;
+         mComposite == aOther.mComposite &&
+         EqualURIs(mSourceURI, aOther.mSourceURI);
 }
 
 nsChangeHint
 nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aOther) const
 {
   nsChangeHint hint = nsChangeHint(0);
-  if (mAttachment != aOther.mAttachment ||
-      mClip != aOther.mClip ||
-      mOrigin != aOther.mOrigin ||
-      mRepeat != aOther.mRepeat ||
-      mBlendMode != aOther.mBlendMode ||
-      mSize != aOther.mSize ||
-      mImage != aOther.mImage ||
-      mMaskMode != aOther.mMaskMode ||
-      mComposite != aOther.mComposite) {
+  if (!EqualURIs(mSourceURI, aOther.mSourceURI)) {
+    NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
+    NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+    // Mask changes require that we update the PreEffectsBBoxProperty,
+    // which is done during overflow computation.
+    NS_UpdateHint(hint, nsChangeHint_UpdateOverflow);
+  } else if (mAttachment != aOther.mAttachment ||
+             mClip != aOther.mClip ||
+             mOrigin != aOther.mOrigin ||
+             mRepeat != aOther.mRepeat ||
+             mBlendMode != aOther.mBlendMode ||
+             mSize != aOther.mSize ||
+             mImage != aOther.mImage ||
+             mMaskMode != aOther.mMaskMode ||
+             mComposite != aOther.mComposite) {
     hint |= nsChangeHint_RepaintFrame;
   }
+
   if (mPosition != aOther.mPosition) {
     hint |= nsChangeHint_SchedulePaint;
   }
+
   return hint;
 }
 
 // --------------------
 // nsStyleBackground
 //
 
 nsStyleBackground::nsStyleBackground()
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -351,16 +351,17 @@ private:
   nsCOMArray<imgIContainer> mSubImages;
 
   nsStyleImageType mType;
   union {
     imgRequestProxy* mImage;
     nsStyleGradient* mGradient;
     char16_t* mElementId;
   };
+
   // This is _currently_ used only in conjunction with eStyleImageType_Image.
   nsAutoPtr<nsStyleSides> mCropRect;
 #ifdef DEBUG
   bool mImageTracked;
 #endif
 };
 
 struct nsStyleColor {
@@ -533,16 +534,23 @@ struct nsStyleImageLayers {
       return !(*this == aOther);
     }
   };
 
   struct Layer;
   friend struct Layer;
   struct Layer {
     nsStyleImage  mImage;         // [reset]
+    nsCOMPtr<nsIURI> mSourceURI;  // [reset]
+                                  // mask-only property
+                                  // This property is used for mask layer only.
+                                  // For a background layer, it should always
+                                  // be the initial value, which is nullptr.
+                                  // Store mask-image URI so that we can resolve
+                                  // SVG mask path later.
     Position      mPosition;      // [reset] See nsStyleConsts.h
     Size          mSize;          // [reset]
     uint8_t       mClip;          // [reset] See nsStyleConsts.h
     uint8_t       mOrigin;        // [reset] See nsStyleConsts.h
     uint8_t       mAttachment;    // [reset] See nsStyleConsts.h
                                   // background-only property
                                   // This property is used for background layer
                                   // only. For a mask layer, it should always
@@ -3404,17 +3412,16 @@ struct nsStyleSVGReset {
 
   bool HasNonScalingStroke() const {
     return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
   }
 
   nsStyleImageLayers    mLayers;
   nsStyleClipPath mClipPath;          // [reset]
   nsTArray<nsStyleFilter> mFilters;   // [reset]
-  nsCOMPtr<nsIURI> mMask;             // [reset]
   nscolor          mStopColor;        // [reset]
   nscolor          mFloodColor;       // [reset]
   nscolor          mLightingColor;    // [reset]
 
   float            mStopOpacity;      // [reset]
   float            mFloodOpacity;     // [reset]
 
   uint8_t          mDominantBaseline; // [reset] see nsStyleConsts.h
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -547,27 +547,34 @@ nsSVGEffects::GetPaintingPropertyForURI(
           GetEffectPropertyForURI(aURI, aFrame, aProp, CreatePaintingProperty));
 }
 
 nsSVGEffects::EffectProperties
 nsSVGEffects::GetEffectProperties(nsIFrame *aFrame)
 {
   NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
 
-  EffectProperties result;
+  EffectProperties result{nullptr, nullptr, nullptr};
   const nsStyleSVGReset *style = aFrame->StyleSVGReset();
   result.mFilter = GetOrCreateFilterProperty(aFrame);
   if (style->mClipPath.GetType() == NS_STYLE_CLIP_PATH_URL) {
     result.mClipPath =
       GetPaintingProperty(style->mClipPath.GetURL(), aFrame, ClipPathProperty());
   } else {
     result.mClipPath = nullptr;
   }
-  result.mMask =
-    GetPaintingProperty(style->mMask, aFrame, MaskProperty());
+
+  // FIXME: Bug 1228280.
+  // Before fixing bug 1228280, we support only single svg mask as before.
+  MOZ_ASSERT(style->mLayers.mImageCount > 0);
+  nsCOMPtr<nsIURI> uri = style->mLayers.mLayers[0].mSourceURI;
+  if (uri) {
+    result.mMask = GetPaintingProperty(uri, aFrame, MaskProperty());
+  }
+
   return result;
 }
 
 nsSVGPaintServerFrame *
 nsSVGEffects::GetPaintServer(nsIFrame *aTargetFrame, const nsStyleSVGPaint *aPaint,
                              const FramePropertyDescriptor *aType)
 {
   if (aPaint->mType != eStyleSVGPaintType_Server)
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -150,19 +150,18 @@ nsSVGIntegrationUtils::UsingEffectsForFr
 {
   // Even when SVG display lists are disabled, returning true for SVG frames
   // does not adversely affect any of our callers. Therefore we don't bother
   // checking the SDL prefs here, since we don't know if we're being called for
   // painting or hit-testing anyway.
   const nsStyleSVGReset *style = aFrame->StyleSVGReset();
   bool hasValidLayers = style->mLayers.HasValidLayers();
 
-  return (style->HasFilters() || style->mMask ||
-          (style->mClipPath.GetType() != NS_STYLE_CLIP_PATH_NONE) ||
-          hasValidLayers);
+  return (style->HasFilters() || hasValidLayers ||
+          (style->mClipPath.GetType() != NS_STYLE_CLIP_PATH_NONE));
 }
 
 // For non-SVG frames, this gives the offset to the frame's "user space".
 // For SVG frames, this returns a zero offset.
 static nsPoint
 GetOffsetToBoundingBox(nsIFrame* aFrame)
 {
   if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {