Bug 1269175 - Convert nsStyleSVG::mStrokeDasharray to be nsTArray. draft
authorTing-Yu Lin <tlin@mozilla.com>
Thu, 26 May 2016 14:01:58 +0800
changeset 371191 224443cc53362ad5e5433c2e8efbc2e4e6892e21
parent 371122 8d0aadfe7da782d415363880008b4ca027686137
child 521948 d626aaa1f395c904bfb1970c7613586f6db231c6
push id19278
push usertlin@mozilla.com
push dateThu, 26 May 2016 06:02:55 +0000
bugs1269175
milestone49.0a1
Bug 1269175 - Convert nsStyleSVG::mStrokeDasharray to be nsTArray. MozReview-Commit-ID: 5TC8KBD5cO6
dom/svg/SVGContentUtils.cpp
layout/style/StyleAnimationValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsSVGUtils.cpp
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -92,18 +92,18 @@ GetStrokeDashData(SVGContentUtils::AutoS
     for (size_t i = 0; i < dashArrayLength; i++) {
       if (dashSrc[i] < 0.0) {
         return eContinuousStroke; // invalid
       }
       dashPattern[i] = Float(dashSrc[i]);
       (i % 2 ? totalLengthOfGaps : totalLengthOfDashes) += dashSrc[i];
     }
   } else {
-    const nsStyleCoord *dasharray = aStyleSVG->mStrokeDasharray;
-    dashArrayLength = aStyleSVG->mStrokeDasharrayLength;
+    const nsTArray<nsStyleCoord>& dasharray = aStyleSVG->mStrokeDasharray;
+    dashArrayLength = aStyleSVG->mStrokeDasharray.Length();
     if (dashArrayLength <= 0) {
       return eContinuousStroke;
     }
     if (aElement->IsSVGElement(nsGkAtoms::path)) {
       pathScale = static_cast<SVGPathElement*>(aElement)->
         GetPathLengthScale(SVGPathElement::eForStroking);
       if (pathScale <= 0) {
         return eContinuousStroke;
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -3768,25 +3768,20 @@ StyleAnimationValue::ExtractComputedValu
           }
           aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(),
                                                       eUnit_CSSValuePair);
           break;
         }
 
         case eCSSProperty_stroke_dasharray: {
           const nsStyleSVG *svg = static_cast<const nsStyleSVG*>(styleStruct);
-          MOZ_ASSERT((svg->mStrokeDasharray != nullptr) ==
-                     (svg->mStrokeDasharrayLength != 0),
-                     "pointer/length mismatch");
           nsAutoPtr<nsCSSValueList> result;
-          if (svg->mStrokeDasharray) {
-            MOZ_ASSERT(svg->mStrokeDasharrayLength > 0,
-                       "non-null list should have positive length");
+          if (!svg->mStrokeDasharray.IsEmpty()) {
             nsCSSValueList **resultTail = getter_Transfers(result);
-            for (uint32_t i = 0, i_end = svg->mStrokeDasharrayLength;
+            for (uint32_t i = 0, i_end = svg->mStrokeDasharray.Length();
                  i != i_end; ++i) {
               nsCSSValueList *item = new nsCSSValueList;
               *resultTail = item;
               resultTail = &item->mNext;
 
               const nsStyleCoord &coord = svg->mStrokeDasharray[i];
               nsCSSValue &value = item->mValue;
               switch (coord.GetUnit()) {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -5617,25 +5617,25 @@ nsComputedDOMStyle::DoGetMarkerStart()
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetStrokeDasharray()
 {
   const nsStyleSVG* svg = StyleSVG();
 
-  if (!svg->mStrokeDasharrayLength || !svg->mStrokeDasharray) {
+  if (svg->mStrokeDasharray.IsEmpty()) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_none);
     return val.forget();
   }
 
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
 
-  for (uint32_t i = 0; i < svg->mStrokeDasharrayLength; i++) {
+  for (uint32_t i = 0; i < svg->mStrokeDasharray.Length(); i++) {
     RefPtr<nsROCSSPrimitiveValue> dash = new nsROCSSPrimitiveValue;
     SetValueToCoord(dash, svg->mStrokeDasharray[i], true);
     valueList->AppendCSSValue(dash.forget());
   }
 
   return valueList.forget();
 }
 
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9372,76 +9372,53 @@ nsRuleNode::ComputeSVGData(void* aStartS
   switch (strokeDasharrayValue->GetUnit()) {
   case eCSSUnit_Null:
     break;
 
   case eCSSUnit_Inherit:
   case eCSSUnit_Unset:
     conditions.SetUncacheable();
     svg->mStrokeDasharrayFromObject = parentSVG->mStrokeDasharrayFromObject;
-    // only do the copy if weren't already set up by the copy constructor
-    // FIXME Bug 389408: This is broken when aStartStruct is non-null!
-    if (!svg->mStrokeDasharray) {
-      svg->mStrokeDasharrayLength = parentSVG->mStrokeDasharrayLength;
-      if (svg->mStrokeDasharrayLength) {
-        svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
-        if (svg->mStrokeDasharray)
-          memcpy(svg->mStrokeDasharray,
-                 parentSVG->mStrokeDasharray,
-                 svg->mStrokeDasharrayLength * sizeof(nsStyleCoord));
-        else
-          svg->mStrokeDasharrayLength = 0;
-      }
-    }
+    svg->mStrokeDasharray = parentSVG->mStrokeDasharray;
     break;
 
   case eCSSUnit_Enumerated:
     MOZ_ASSERT(strokeDasharrayValue->GetIntValue() ==
                      NS_STYLE_STROKE_PROP_CONTEXT_VALUE,
                "Unknown keyword for stroke-dasharray");
     svg->mStrokeDasharrayFromObject = true;
-    delete [] svg->mStrokeDasharray;
-    svg->mStrokeDasharray = nullptr;
-    svg->mStrokeDasharrayLength = 0;
+    svg->mStrokeDasharray.Clear();
     break;
 
   case eCSSUnit_Initial:
   case eCSSUnit_None:
     svg->mStrokeDasharrayFromObject = false;
-    delete [] svg->mStrokeDasharray;
-    svg->mStrokeDasharray = nullptr;
-    svg->mStrokeDasharrayLength = 0;
+    svg->mStrokeDasharray.Clear();
     break;
 
   case eCSSUnit_List:
   case eCSSUnit_ListDep: {
     svg->mStrokeDasharrayFromObject = false;
-    delete [] svg->mStrokeDasharray;
-    svg->mStrokeDasharray = nullptr;
-    svg->mStrokeDasharrayLength = 0;
+    svg->mStrokeDasharray.Clear();
 
     // count number of values
     const nsCSSValueList *value = strokeDasharrayValue->GetListValue();
-    svg->mStrokeDasharrayLength = ListLength(value);
-
-    NS_ASSERTION(svg->mStrokeDasharrayLength != 0, "no dasharray items");
-
-    svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
-
-    if (svg->mStrokeDasharray) {
-      uint32_t i = 0;
-      while (nullptr != value) {
-        SetCoord(value->mValue,
-                 svg->mStrokeDasharray[i++], nsStyleCoord(),
-                 SETCOORD_LP | SETCOORD_FACTOR,
-                 aContext, mPresContext, conditions);
-        value = value->mNext;
-      }
-    } else {
-      svg->mStrokeDasharrayLength = 0;
+    uint32_t strokeDasharrayLength = ListLength(value);
+
+    MOZ_ASSERT(strokeDasharrayLength != 0, "no dasharray items");
+
+    svg->mStrokeDasharray.SetLength(strokeDasharrayLength);
+
+    uint32_t i = 0;
+    while (nullptr != value) {
+      SetCoord(value->mValue,
+               svg->mStrokeDasharray[i++], nsStyleCoord(),
+               SETCOORD_LP | SETCOORD_FACTOR,
+               aContext, mPresContext, conditions);
+      value = value->mNext;
     }
     break;
   }
 
   default:
     MOZ_ASSERT(false, "unrecognized dasharray unit");
   }
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -814,24 +814,22 @@ nsChangeHint nsStyleColumn::CalcDifferen
 }
 
 // --------------------
 // nsStyleSVG
 //
 nsStyleSVG::nsStyleSVG(StyleStructContext aContext)
   : mFill(eStyleSVGPaintType_Color) // Will be initialized to NS_RGB(0, 0, 0)
   , mStroke(eStyleSVGPaintType_None)
-  , mStrokeDasharray(nullptr)
   , mStrokeDashoffset(0, nsStyleCoord::CoordConstructor)
   , mStrokeWidth(nsPresContext::CSSPixelsToAppUnits(1),
                  nsStyleCoord::CoordConstructor)
   , mFillOpacity(1.0f)
   , mStrokeMiterlimit(4.0f)
   , mStrokeOpacity(1.0f)
-  , mStrokeDasharrayLength(0)
   , mClipRule(NS_STYLE_FILL_RULE_NONZERO)
   , mColorInterpolation(NS_STYLE_COLOR_INTERPOLATION_SRGB)
   , mColorInterpolationFilters(NS_STYLE_COLOR_INTERPOLATION_LINEARRGB)
   , mFillRule(NS_STYLE_FILL_RULE_NONZERO)
   , mPaintOrder(NS_STYLE_PAINT_ORDER_NORMAL)
   , mShapeRendering(NS_STYLE_SHAPE_RENDERING_AUTO)
   , mStrokeLinecap(NS_STYLE_STROKE_LINECAP_BUTT)
   , mStrokeLinejoin(NS_STYLE_STROKE_LINEJOIN_MITER)
@@ -843,61 +841,46 @@ nsStyleSVG::nsStyleSVG(StyleStructContex
   , mStrokeWidthFromObject(false)
 {
   MOZ_COUNT_CTOR(nsStyleSVG);
 }
 
 nsStyleSVG::~nsStyleSVG()
 {
   MOZ_COUNT_DTOR(nsStyleSVG);
-  delete [] mStrokeDasharray;
 }
 
 nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
   : mFill(aSource.mFill)
   , mStroke(aSource.mStroke)
   , mMarkerEnd(aSource.mMarkerEnd)
   , mMarkerMid(aSource.mMarkerMid)
   , mMarkerStart(aSource.mMarkerStart)
-  , mStrokeDasharray(nullptr)
+  , mStrokeDasharray(aSource.mStrokeDasharray)
   , mStrokeDashoffset(aSource.mStrokeDashoffset)
   , mStrokeWidth(aSource.mStrokeWidth)
   , mFillOpacity(aSource.mFillOpacity)
   , mStrokeMiterlimit(aSource.mStrokeMiterlimit)
   , mStrokeOpacity(aSource.mStrokeOpacity)
-  , mStrokeDasharrayLength(0)
   , mClipRule(aSource.mClipRule)
   , mColorInterpolation(aSource.mColorInterpolation)
   , mColorInterpolationFilters(aSource.mColorInterpolationFilters)
   , mFillRule(aSource.mFillRule)
   , mPaintOrder(aSource.mPaintOrder)
   , mShapeRendering(aSource.mShapeRendering)
   , mStrokeLinecap(aSource.mStrokeLinecap)
   , mStrokeLinejoin(aSource.mStrokeLinejoin)
   , mTextAnchor(aSource.mTextAnchor)
   , mFillOpacitySource(aSource.mFillOpacitySource)
   , mStrokeOpacitySource(aSource.mStrokeOpacitySource)
   , mStrokeDasharrayFromObject(aSource.mStrokeDasharrayFromObject)
   , mStrokeDashoffsetFromObject(aSource.mStrokeDashoffsetFromObject)
   , mStrokeWidthFromObject(aSource.mStrokeWidthFromObject)
 {
   MOZ_COUNT_CTOR(nsStyleSVG);
-
-  MOZ_ASSERT(bool(aSource.mStrokeDasharray) ==
-             bool(aSource.mStrokeDasharrayLength),
-             "aSource.mStrokeDasharray has an inconsistent length!");
-  if (aSource.mStrokeDasharray) {
-    mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
-    mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
-    if (mStrokeDasharray) {
-      for (size_t i = 0; i < mStrokeDasharrayLength; i++) {
-        mStrokeDasharray[i] = aSource.mStrokeDasharray[i];
-      }
-    }
-  }
 }
 
 static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1,
                             const nsStyleSVGPaint& aPaint2)
 {
   if (aPaint1.mType != aPaint2.mType) {
     return aPaint1.mType == eStyleSVGPaintType_Server ||
            aPaint2.mType == eStyleSVGPaintType_Server;
@@ -966,32 +949,25 @@ nsChangeHint nsStyleSVG::CalcDifference(
 
   if ( mStrokeDashoffset      != aOther.mStrokeDashoffset      ||
        mClipRule              != aOther.mClipRule              ||
        mColorInterpolation    != aOther.mColorInterpolation    ||
        mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
        mFillRule              != aOther.mFillRule              ||
        mPaintOrder            != aOther.mPaintOrder            ||
        mShapeRendering        != aOther.mShapeRendering        ||
-       mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
+       mStrokeDasharray       != aOther.mStrokeDasharray       ||
        mFillOpacitySource     != aOther.mFillOpacitySource     ||
        mStrokeOpacitySource   != aOther.mStrokeOpacitySource   ||
        mStrokeDasharrayFromObject != aOther.mStrokeDasharrayFromObject ||
        mStrokeDashoffsetFromObject != aOther.mStrokeDashoffsetFromObject ||
        mStrokeWidthFromObject != aOther.mStrokeWidthFromObject) {
     return hint | nsChangeHint_RepaintFrame;
   }
 
-  // length of stroke dasharrays are the same (tested above) - check entries
-  for (uint32_t i=0; i<mStrokeDasharrayLength; i++) {
-    if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i]) {
-      return hint | nsChangeHint_RepaintFrame;
-    }
-  }
-
   return hint;
 }
 
 // --------------------
 // nsStyleBasicShape
 
 nsCSSKeyword
 nsStyleBasicShape::GetShapeTypeName() const
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3248,26 +3248,25 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
     return nsChangeHint_NeedReflow;
   }
 
   nsStyleSVGPaint  mFill;             // [inherited]
   nsStyleSVGPaint  mStroke;           // [inherited]
   nsCOMPtr<nsIURI> mMarkerEnd;        // [inherited]
   nsCOMPtr<nsIURI> mMarkerMid;        // [inherited]
   nsCOMPtr<nsIURI> mMarkerStart;      // [inherited]
-  nsStyleCoord    *mStrokeDasharray;  // [inherited] coord, percent, factor
+  nsTArray<nsStyleCoord> mStrokeDasharray;  // [inherited] coord, percent, factor
 
   nsStyleCoord     mStrokeDashoffset; // [inherited] coord, percent, factor
   nsStyleCoord     mStrokeWidth;      // [inherited] coord, percent, factor
 
   float            mFillOpacity;      // [inherited]
   float            mStrokeMiterlimit; // [inherited]
   float            mStrokeOpacity;    // [inherited]
 
-  uint32_t         mStrokeDasharrayLength;
   uint8_t          mClipRule;         // [inherited]
   uint8_t          mColorInterpolation; // [inherited] see nsStyleConsts.h
   uint8_t          mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
   uint8_t          mFillRule;         // [inherited] see nsStyleConsts.h
   uint8_t          mPaintOrder;       // [inherited] see nsStyleConsts.h
   uint8_t          mShapeRendering;   // [inherited] see nsStyleConsts.h
   uint8_t          mStrokeLinecap;    // [inherited] see nsStyleConsts.h
   uint8_t          mStrokeLinejoin;   // [inherited] see nsStyleConsts.h
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1610,32 +1610,32 @@ GetStrokeDashData(nsIFrame* aFrame,
     for (uint32_t i = 0; i < aDashes.Length(); i++) {
       if (aDashes[i] < 0.0) {
         return false;
       }
       totalLength += aDashes[i];
     }
 
   } else {
-    uint32_t count = style->mStrokeDasharrayLength;
+    uint32_t count = style->mStrokeDasharray.Length();
     if (!count || !aDashes.SetLength(count, fallible)) {
       return false;
     }
 
     gfxFloat pathScale = 1.0;
 
     if (content->IsSVGElement(nsGkAtoms::path)) {
       pathScale = static_cast<SVGPathElement*>(content)->
         GetPathLengthScale(SVGPathElement::eForStroking);
       if (pathScale <= 0) {
         return false;
       }
     }
 
-    const nsStyleCoord *dasharray = style->mStrokeDasharray;
+    const nsTArray<nsStyleCoord>& dasharray = style->mStrokeDasharray;
 
     for (uint32_t i = 0; i < count; i++) {
       aDashes[i] = SVGContentUtils::CoordToFloat(ctx,
                                                  dasharray[i]) * pathScale;
       if (aDashes[i] < 0.0) {
         return false;
       }
       totalLength += aDashes[i];
@@ -1643,17 +1643,17 @@ GetStrokeDashData(nsIFrame* aFrame,
   }
 
   if (aContextPaint && style->mStrokeDashoffsetFromObject) {
     *aDashOffset = aContextPaint->GetStrokeDashOffset();
   } else {
     *aDashOffset = SVGContentUtils::CoordToFloat(ctx,
                                                  style->mStrokeDashoffset);
   }
-  
+
   return (totalLength > 0.0);
 }
 
 void
 nsSVGUtils::SetupCairoStrokeGeometry(nsIFrame* aFrame,
                                      gfxContext *aContext,
                                      gfxTextContextPaint *aContextPaint)
 {