From 4599882448c59a3d2c0fdcbc5ad47b5b7b01f6f4 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Wed, 20 Sep 2017 22:52:20 +1000 Subject: [PATCH] Bug 1400438 - Use array instead of linked list for -moz-border-*-colors. r=heycam,mattwoodrow MozReview-Commit-ID: LPl1Rlg5gRn --HG-- extra : source : 418288301c994faded0993a1cd3d73fc3b6521be extra : amend_source : 7cba1fc0ca13b86782aa05ab4dae4cdc7eb9fbf6 --- .../rootAnalysis/analyzeHeapWrites.js | 5 - layout/base/crashtests/1400438-1.html | 9 ++ layout/base/crashtests/crashtests.list | 1 + layout/painting/nsCSSRendering.cpp | 6 +- layout/painting/nsCSSRenderingBorders.cpp | 85 +++++++--------- layout/painting/nsCSSRenderingBorders.h | 9 +- layout/style/ServoBindings.cpp | 24 +---- layout/style/ServoBindings.h | 5 - layout/style/ServoBindings.toml | 2 - layout/style/nsComputedDOMStyle.cpp | 15 +-- layout/style/nsRuleNode.cpp | 13 +-- layout/style/nsStyleStruct.cpp | 39 +------- layout/style/nsStyleStruct.h | 99 +++++-------------- 13 files changed, 99 insertions(+), 213 deletions(-) create mode 100644 layout/base/crashtests/1400438-1.html diff --git a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js index 3ccc399937d3..5129abe007ec 100644 --- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js +++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js @@ -237,8 +237,6 @@ function treatAsSafeArgument(entry, varName, csuName) ["Gecko_CounterStyle_GetName", "aResult", null], ["Gecko_CounterStyle_GetSingleString", "aResult", null], ["Gecko_EnsureMozBorderColors", "aBorder", null], - ["Gecko_ClearMozBorderColors", "aBorder", null], - ["Gecko_AppendMozBorderColors", "aBorder", null], ["Gecko_CopyMozBorderColors", "aDest", null], ]; for (var [entryMatch, varMatch, csuMatch] of whitelist) { @@ -470,9 +468,6 @@ function ignoreContents(entry) // Unable to trace through dataflow, but straightforward if inspected. "Gecko_NewNoneTransform", - // Bug 1400438 - "Gecko_AppendMozBorderColors", - // Need main thread assertions or other fixes. /EffectCompositor::GetServoAnimationRule/, /LookAndFeel::GetColor/, diff --git a/layout/base/crashtests/1400438-1.html b/layout/base/crashtests/1400438-1.html new file mode 100644 index 000000000000..366e1104ff1f --- /dev/null +++ b/layout/base/crashtests/1400438-1.html @@ -0,0 +1,9 @@ + + +
diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 7da960f9ccf2..913becbd2b6b 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -501,4 +501,5 @@ load 1397398-1.html load 1397398-2.html load 1397398-3.html load 1398500.html +load 1400438-1.html load 1400599-1.html diff --git a/layout/painting/nsCSSRendering.cpp b/layout/painting/nsCSSRendering.cpp index 7f67bab1ef8c..21d5b21e7404 100644 --- a/layout/painting/nsCSSRendering.cpp +++ b/layout/painting/nsCSSRendering.cpp @@ -761,13 +761,11 @@ ConstructBorderRenderer(nsPresContext* aPresContext, uint8_t borderStyles[4]; nscolor borderColors[4]; - nsBorderColors* compositeColors[4]; - // pull out styles, colors, composite colors + // pull out styles, colors NS_FOR_CSS_SIDES (i) { borderStyles[i] = aStyleBorder.GetBorderStyle(i); borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]); - aStyleBorder.GetCompositeColors(i, &compositeColors[i]); } PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]); @@ -787,7 +785,7 @@ ConstructBorderRenderer(nsPresContext* aPresContext, borderWidths, bgRadii, borderColors, - compositeColors, + aStyleBorder.mBorderColors.get(), bgColor); } diff --git a/layout/painting/nsCSSRenderingBorders.cpp b/layout/painting/nsCSSRenderingBorders.cpp index dc34e655155d..d86f8db79418 100644 --- a/layout/painting/nsCSSRenderingBorders.cpp +++ b/layout/painting/nsCSSRenderingBorders.cpp @@ -90,9 +90,6 @@ static Color ComputeColorForLine(uint32_t aLineIndex, nscolor aBorderColor, nscolor aBackgroundColor); -static Color ComputeCompositeColorForLine(uint32_t aLineIndex, - const nsBorderColors* aBorderColors); - // little helper function to check if the array of 4 floats given are // equal to the given value static bool @@ -178,7 +175,7 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(nsPresContext* aPresContext, const Float* aBorderWidths, RectCornerRadii& aBorderRadii, const nscolor* aBorderColors, - nsBorderColors* const* aCompositeColors, + const nsBorderColors* aCompositeColors, nscolor aBackgroundColor) : mPresContext(aPresContext), mDocument(aDocument), @@ -191,11 +188,12 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(nsPresContext* aPresContext, PodCopy(mBorderStyles, aBorderStyles, 4); PodCopy(mBorderWidths, aBorderWidths, 4); PodCopy(mBorderColors, aBorderColors, 4); - if (aCompositeColors) { - PodCopy(mCompositeColors, aCompositeColors, 4); - } else { - static nsBorderColors * const noColors[4] = { nullptr }; - PodCopy(mCompositeColors, noColors, 4); + NS_FOR_CSS_SIDES(side) { + if (aCompositeColors && !(*aCompositeColors)[side].IsEmpty()) { + mCompositeColors[side] = &(*aCompositeColors)[side]; + } else { + mCompositeColors[side] = nullptr; + } } mInnerRect = mOuterRect; @@ -319,9 +317,11 @@ nsCSSBorderRenderer::AreBorderSideFinalStylesSame(uint8_t aSides) if (mBorderStyles[firstStyle] != mBorderStyles[i] || mBorderColors[firstStyle] != mBorderColors[i] || - !nsBorderColors::Equal(mCompositeColors[firstStyle], - mCompositeColors[i])) + !mCompositeColors[firstStyle] != !mCompositeColors[i] || + (mCompositeColors[firstStyle] && + *mCompositeColors[firstStyle] != *mCompositeColors[i])) { return false; + } } /* Then if it's one of the two-tone styles and we're not @@ -1265,18 +1265,9 @@ ComputeColorForLine(uint32_t aLineIndex, aBorderColorStyle[aLineIndex]); } -Color -ComputeCompositeColorForLine(uint32_t aLineIndex, - const nsBorderColors* aBorderColors) -{ - while (aLineIndex-- && aBorderColors->mNext) - aBorderColors = aBorderColors->mNext; - - return Color::FromABGR(aBorderColors->mColor); -} - void -nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *aCompositeColors) +nsCSSBorderRenderer::DrawBorderSidesCompositeColors( + int aSides, const nsTArray& aCompositeColors) { RectCornerRadii radii = mBorderRadii; @@ -1292,9 +1283,14 @@ nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderCo Point itl = mInnerRect.TopLeft(); Point ibr = mInnerRect.BottomRight(); + MOZ_ASSERT(!aCompositeColors.IsEmpty()); + Color compositeColor; for (uint32_t i = 0; i < uint32_t(maxBorderWidth); i++) { - ColorPattern color(ToDeviceColor( - ComputeCompositeColorForLine(i, aCompositeColors))); + // advance to next color if exists. + if (i < aCompositeColors.Length()) { + compositeColor = ToDeviceColor(Color::FromABGR(aCompositeColors[i])); + } + ColorPattern color(compositeColor); Rect siRect = soRect; siRect.Deflate(1.0); @@ -1334,7 +1330,7 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides) uint8_t borderRenderStyle = NS_STYLE_BORDER_STYLE_NONE; nscolor borderRenderColor; - const nsBorderColors *compositeColors = nullptr; + const nsTArray* compositeColors = nullptr; uint32_t borderColorStyleCount = 0; BorderColorStyle borderColorStyleTopLeft[3], borderColorStyleBottomRight[3]; @@ -1392,7 +1388,7 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides) maxBorderWidth = std::max(maxBorderWidth, mBorderWidths[i]); } if (maxBorderWidth <= MAX_COMPOSITE_BORDER_WIDTH) { - DrawBorderSidesCompositeColors(aSides, compositeColors); + DrawBorderSidesCompositeColors(aSides, *compositeColors); return; } NS_WARNING("DrawBorderSides: too large border width for composite colors"); @@ -3145,8 +3141,10 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder() void nsCSSBorderRenderer::DrawRectangularCompositeColors() { - nsBorderColors *currentColors[4]; - memcpy(currentColors, mCompositeColors, sizeof(nsBorderColors*) * 4); + nscolor currentColors[4]; + NS_FOR_CSS_SIDES(side) { + currentColors[side] = mBorderColors[side]; + } Rect rect = mOuterRect; rect.Deflate(0.5); @@ -3156,23 +3154,26 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors() { 0, -0.5 } }; for (int i = 0; i < mBorderWidths[0]; i++) { + NS_FOR_CSS_SIDES(side) { + // advance to the next composite color if one exists + if (mCompositeColors[side] && + uint32_t(i) < mCompositeColors[side]->Length()) { + currentColors[side] = (*mCompositeColors[side])[i]; + } + } NS_FOR_CSS_SIDES(side) { int sideNext = (side + 1) % 4; Point firstCorner = rect.CCWCorner(side) + cornerAdjusts[side]; Point secondCorner = rect.CWCorner(side) - cornerAdjusts[side]; - Color currentColor = Color::FromABGR( - currentColors[side] ? currentColors[side]->mColor - : mBorderColors[side]); + Color currentColor = Color::FromABGR(currentColors[side]); mDrawTarget->StrokeLine(firstCorner, secondCorner, ColorPattern(ToDeviceColor(currentColor))); Point cornerTopLeft = rect.CWCorner(side) - Point(0.5, 0.5); - Color nextColor = Color::FromABGR( - currentColors[sideNext] ? currentColors[sideNext]->mColor - : mBorderColors[sideNext]); + Color nextColor = Color::FromABGR(currentColors[sideNext]); Color cornerColor((currentColor.r + nextColor.r) / 2.f, (currentColor.g + nextColor.g) / 2.f, @@ -3180,17 +3181,6 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors() (currentColor.a + nextColor.a) / 2.f); mDrawTarget->FillRect(Rect(cornerTopLeft, Size(1, 1)), ColorPattern(ToDeviceColor(cornerColor))); - - if (side != 0) { - // We'll have to keep side 0 for the color averaging on side 3. - if (currentColors[side] && currentColors[side]->mNext) { - currentColors[side] = currentColors[side]->mNext; - } - } - } - // Now advance the color for side 0. - if (currentColors[0] && currentColors[0]->mNext) { - currentColors[0] = currentColors[0]->mNext; } rect.Deflate(1); } @@ -3206,9 +3196,8 @@ nsCSSBorderRenderer::DrawBorders() (mBorderStyles[0] == NS_STYLE_BORDER_STYLE_NONE || mBorderStyles[0] == NS_STYLE_BORDER_STYLE_HIDDEN || mBorderColors[0] == NS_RGBA(0,0,0,0))) || - (mCompositeColors[0] && - (mCompositeColors[0]->mColor == NS_RGBA(0,0,0,0) && - !mCompositeColors[0]->mNext)))) + (mCompositeColors[0] && mCompositeColors[0]->Length() == 1 && + (*mCompositeColors[0])[0] == NS_RGBA(0,0,0,0)))) { // All borders are the same style, and the style is either none or hidden, or the color // is transparent. diff --git a/layout/painting/nsCSSRenderingBorders.h b/layout/painting/nsCSSRenderingBorders.h index 499471861ec7..0c697447ffe4 100644 --- a/layout/painting/nsCSSRenderingBorders.h +++ b/layout/painting/nsCSSRenderingBorders.h @@ -100,7 +100,7 @@ public: const Float* aBorderWidths, RectCornerRadii& aBorderRadii, const nscolor* aBorderColors, - nsBorderColors* const* aCompositeColors, + const nsBorderColors* aCompositeColors, nscolor aBackgroundColor); // draw the entire border @@ -151,7 +151,9 @@ private: nscolor mBorderColors[4]; // the lists of colors for '-moz-border-top-colors' et. al. - nsBorderColors* mCompositeColors[4]; + // the pointers here are either nullptr, or referring to a non-empty + // nsTArray, so no additional empty check is needed. + const nsTArray* mCompositeColors[4]; // the background color nscolor mBackgroundColor; @@ -235,7 +237,8 @@ private: void DrawBorderSides (int aSides); // function used by the above to handle -moz-border-colors - void DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *compositeColors); + void DrawBorderSidesCompositeColors( + int aSides, const nsTArray& compositeColors); // Setup the stroke options for the given dashed/dotted side void SetupDashedOptions(StrokeOptions* aStrokeOptions, diff --git a/layout/style/ServoBindings.cpp b/layout/style/ServoBindings.cpp index c49f101f1e97..0b6c441360ac 100644 --- a/layout/style/ServoBindings.cpp +++ b/layout/style/ServoBindings.cpp @@ -1256,34 +1256,18 @@ Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder) aBorder->EnsureBorderColors(); } -void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide) -{ - aBorder->ClearBorderColors(aSide); -} - -void -Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide, - nscolor aColor) -{ - aBorder->AppendBorderColor(aSide, aColor); -} - void Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc, mozilla::Side aSide) { if (aSrc->mBorderColors) { - aDest->CopyBorderColorsFrom(aSrc->mBorderColors[aSide], aSide); + aDest->EnsureBorderColors(); + aDest->mBorderColors->mColors[aSide] = aSrc->mBorderColors->mColors[aSide]; + } else { + aDest->ClearBorderColors(aSide); } } -const nsBorderColors* -Gecko_GetMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide) -{ - MOZ_ASSERT(aBorder); - return aBorder->mBorderColors ? aBorder->mBorderColors[aSide] : nullptr; -} - void Gecko_FontFamilyList_Clear(FontFamilyList* aList) { aList->Clear(); diff --git a/layout/style/ServoBindings.h b/layout/style/ServoBindings.h index c42e44be0392..1833efa252ae 100644 --- a/layout/style/ServoBindings.h +++ b/layout/style/ServoBindings.h @@ -282,13 +282,8 @@ bool Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_ // Border style void Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder); -void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide); -void Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide, - nscolor aColor); void Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc, mozilla::Side aSide); -const nsBorderColors* Gecko_GetMozBorderColors(const nsStyleBorder* aBorder, - mozilla::Side aSide); // Font style void Gecko_FontFamilyList_Clear(FontFamilyList* aList); diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 9f0e5a424707..fc12bde960b7 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -190,7 +190,6 @@ whitelist-types = [ "Keyframe", "nsAttrName", "nsAttrValue", - "nsBorderColors", "nscolor", "nsChangeHint", "nsCSSCounterDesc", @@ -443,7 +442,6 @@ structs-types = [ "StyleShapeSource", "StyleTransition", "gfxFontFeatureValueSet", - "nsBorderColors", "nsCSSCounterStyleRule", "nsCSSFontFaceRule", "nsCSSKeyword", diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index c19026f68d36..062e00ffebc5 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -5490,19 +5490,14 @@ nsComputedDOMStyle::GetBorderColorsFor(mozilla::Side aSide) const nsStyleBorder *border = StyleBorder(); if (border->mBorderColors) { - nsBorderColors* borderColors = border->mBorderColors[aSide]; - if (borderColors) { + const nsTArray& borderColors = (*border->mBorderColors)[aSide]; + if (!borderColors.IsEmpty()) { RefPtr valueList = GetROCSSValueList(false); - - do { + for (nscolor color : borderColors) { RefPtr primitive = new nsROCSSPrimitiveValue; - - SetToRGBAColor(primitive, borderColors->mColor); - + SetToRGBAColor(primitive, color); valueList->AppendCSSValue(primitive.forget()); - borderColors = borderColors->mNext; - } while (borderColors); - + } return valueList.forget(); } } diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 0a6efb602c04..ccccce98009e 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -7748,13 +7748,10 @@ nsRuleNode::ComputeBorderData(void* aStartStruct, case eCSSUnit_Inherit: { conditions.SetUncacheable(); border->ClearBorderColors(side); - if (parentContext) { - nsBorderColors *parentColors; - parentBorder->GetCompositeColors(side, &parentColors); - if (parentColors) { - border->EnsureBorderColors(); - border->mBorderColors[side] = parentColors->Clone(); - } + if (parentBorder->mBorderColors) { + border->EnsureBorderColors(); + border->mBorderColors->mColors[side] = + parentBorder->mBorderColors->mColors[side]; } break; } @@ -7769,7 +7766,7 @@ nsRuleNode::ComputeBorderData(void* aStartStruct, while (list) { if (SetColor(list->mValue, unused, mPresContext, aContext, borderColor, conditions)) - border->AppendBorderColor(side, borderColor); + border->mBorderColors->mColors[side].AppendElement(borderColor); else { NS_NOTREACHED("unexpected item in -moz-border-*-colors list"); } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 87b60b23db67..1c8b9a596340 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -320,8 +320,7 @@ nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const } nsStyleBorder::nsStyleBorder(const nsPresContext* aContext) - : mBorderColors(nullptr) - , mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL) + : mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL) , mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH) , mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH) , mFloatEdge(StyleFloatEdge::ContentBox) @@ -349,27 +348,8 @@ nsStyleBorder::nsStyleBorder(const nsPresContext* aContext) mTwipsPerPixel = aContext->DevPixelsToAppUnits(1); } -nsBorderColors::~nsBorderColors() -{ - NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext); -} - -nsBorderColors* -nsBorderColors::Clone(bool aDeep) const -{ - nsBorderColors* result = new nsBorderColors(mColor); - if (MOZ_UNLIKELY(!result)) { - return result; - } - if (aDeep) { - NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false)); - } - return result; -} - nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc) - : mBorderColors(nullptr) - , mBorderRadius(aSrc.mBorderRadius) + : mBorderRadius(aSrc.mBorderRadius) , mBorderImageSource(aSrc.mBorderImageSource) , mBorderImageSlice(aSrc.mBorderImageSlice) , mBorderImageWidth(aSrc.mBorderImageWidth) @@ -385,9 +365,7 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc) { MOZ_COUNT_CTOR(nsStyleBorder); if (aSrc.mBorderColors) { - NS_FOR_CSS_SIDES(side) { - CopyBorderColorsFrom(aSrc.mBorderColors[side], side); - } + mBorderColors.reset(new nsBorderColors(*aSrc.mBorderColors)); } NS_FOR_CSS_SIDES(side) { @@ -399,12 +377,6 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc) nsStyleBorder::~nsStyleBorder() { MOZ_COUNT_DTOR(nsStyleBorder); - if (mBorderColors) { - for (int32_t i = 0; i < 4; i++) { - delete mBorderColors[i]; - } - delete [] mBorderColors; - } } void @@ -516,9 +488,8 @@ nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const // Note that at this point if mBorderColors is non-null so is // aNewData.mBorderColors if (mBorderColors) { - NS_FOR_CSS_SIDES(ix) { - if (!nsBorderColors::Equal(mBorderColors[ix], - aNewData.mBorderColors[ix])) { + NS_FOR_CSS_SIDES(side) { + if ((*mBorderColors)[side] != (*aNewData.mBorderColors)[side]) { return nsChangeHint_RepaintFrame; } } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 12da571c31f7..7498b1214c6d 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -984,38 +984,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding } }; -struct nsBorderColors -{ - nsBorderColors* mNext; - nscolor mColor; - - nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {} - explicit nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {} - ~nsBorderColors(); - - nsBorderColors* Clone() const { return Clone(true); } - - static bool Equal(const nsBorderColors* c1, - const nsBorderColors* c2) { - if (c1 == c2) { - return true; - } - while (c1 && c2) { - if (c1->mColor != c2->mColor) { - return false; - } - c1 = c1->mNext; - c2 = c2->mNext; - } - // both should be nullptr if these are equal, otherwise one - // has more colors than another - return !c1 && !c2; - } - -private: - nsBorderColors* Clone(bool aDeep) const; -}; - struct nsCSSShadowItem { nscoord mXOffset; @@ -1142,6 +1110,26 @@ static bool IsVisibleBorderStyle(uint8_t aStyle) aStyle != NS_STYLE_BORDER_STYLE_HIDDEN); } +struct nsBorderColors +{ + nsBorderColors() = default; + + // GCC cannot generate this copy constructor correctly, since nsTArray + // has explicit copy constructor, and we use array of nsTArray here. + // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82235 + nsBorderColors(const nsBorderColors& aOther) { + NS_FOR_CSS_SIDES(side) { + mColors[side] = aOther.mColors[side]; + } + } + + const nsTArray& operator[](mozilla::Side aSide) const { + return mColors[aSide]; + } + + nsTArray mColors[4]; +}; + struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder { explicit nsStyleBorder(const nsPresContext* aContext); @@ -1165,27 +1153,13 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder void EnsureBorderColors() { if (!mBorderColors) { - mBorderColors = new nsBorderColors*[4]; - if (mBorderColors) { - for (int32_t i = 0; i < 4; i++) { - mBorderColors[i] = nullptr; - } - } + mBorderColors.reset(new nsBorderColors); } } void ClearBorderColors(mozilla::Side aSide) { - if (mBorderColors && mBorderColors[aSide]) { - delete mBorderColors[aSide]; - mBorderColors[aSide] = nullptr; - } - } - - void CopyBorderColorsFrom(const nsBorderColors* aSrcBorderColors, mozilla::Side aSide) { - if (aSrcBorderColors) { - EnsureBorderColors(); - ClearBorderColors(aSide); - mBorderColors[aSide] = aSrcBorderColors->Clone(); + if (mBorderColors) { + mBorderColors->mColors[aSide].Clear(); } } @@ -1260,30 +1234,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder nsMargin GetImageOutset() const; - void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const - { - if (!mBorderColors) { - *aColors = nullptr; - } else { - *aColors = mBorderColors[aIndex]; - } - } - - void AppendBorderColor(int32_t aIndex, nscolor aColor) - { - NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color"); - nsBorderColors* colorEntry = new nsBorderColors(aColor); - if (!mBorderColors[aIndex]) { - mBorderColors[aIndex] = colorEntry; - } else { - nsBorderColors* last = mBorderColors[aIndex]; - while (last->mNext) { - last = last->mNext; - } - last->mNext = colorEntry; - } - } - imgIRequest* GetBorderImageRequest() const { if (mBorderImageSource.GetType() == eStyleImageType_Image) { @@ -1293,7 +1243,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder } public: - nsBorderColors** mBorderColors; // [reset] composite (stripe) colors + // [reset] composite (stripe) colors + mozilla::UniquePtr mBorderColors; nsStyleCorners mBorderRadius; // [reset] coord, percent nsStyleImage mBorderImageSource; // [reset] nsStyleSides mBorderImageSlice; // [reset] factor, percent