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
This commit is contained in:
Xidorn Quan 2017-09-20 22:52:20 +10:00
Родитель 2d38252072
Коммит 4599882448
13 изменённых файлов: 99 добавлений и 213 удалений

Просмотреть файл

@ -237,8 +237,6 @@ function treatAsSafeArgument(entry, varName, csuName)
["Gecko_CounterStyle_GetName", "aResult", null], ["Gecko_CounterStyle_GetName", "aResult", null],
["Gecko_CounterStyle_GetSingleString", "aResult", null], ["Gecko_CounterStyle_GetSingleString", "aResult", null],
["Gecko_EnsureMozBorderColors", "aBorder", null], ["Gecko_EnsureMozBorderColors", "aBorder", null],
["Gecko_ClearMozBorderColors", "aBorder", null],
["Gecko_AppendMozBorderColors", "aBorder", null],
["Gecko_CopyMozBorderColors", "aDest", null], ["Gecko_CopyMozBorderColors", "aDest", null],
]; ];
for (var [entryMatch, varMatch, csuMatch] of whitelist) { for (var [entryMatch, varMatch, csuMatch] of whitelist) {
@ -470,9 +468,6 @@ function ignoreContents(entry)
// Unable to trace through dataflow, but straightforward if inspected. // Unable to trace through dataflow, but straightforward if inspected.
"Gecko_NewNoneTransform", "Gecko_NewNoneTransform",
// Bug 1400438
"Gecko_AppendMozBorderColors",
// Need main thread assertions or other fixes. // Need main thread assertions or other fixes.
/EffectCompositor::GetServoAnimationRule/, /EffectCompositor::GetServoAnimationRule/,
/LookAndFeel::GetColor/, /LookAndFeel::GetColor/,

Просмотреть файл

@ -0,0 +1,9 @@
<!DOCTYPE html>
<style>
div {
width: 100px; height: 100px;
border-left: 10px solid;
-moz-border-left-colors: red green;
}
</style>
<div></div>

Просмотреть файл

@ -501,4 +501,5 @@ load 1397398-1.html
load 1397398-2.html load 1397398-2.html
load 1397398-3.html load 1397398-3.html
load 1398500.html load 1398500.html
load 1400438-1.html
load 1400599-1.html load 1400599-1.html

Просмотреть файл

@ -761,13 +761,11 @@ ConstructBorderRenderer(nsPresContext* aPresContext,
uint8_t borderStyles[4]; uint8_t borderStyles[4];
nscolor borderColors[4]; nscolor borderColors[4];
nsBorderColors* compositeColors[4];
// pull out styles, colors, composite colors // pull out styles, colors
NS_FOR_CSS_SIDES (i) { NS_FOR_CSS_SIDES (i) {
borderStyles[i] = aStyleBorder.GetBorderStyle(i); borderStyles[i] = aStyleBorder.GetBorderStyle(i);
borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[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]); PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
@ -787,7 +785,7 @@ ConstructBorderRenderer(nsPresContext* aPresContext,
borderWidths, borderWidths,
bgRadii, bgRadii,
borderColors, borderColors,
compositeColors, aStyleBorder.mBorderColors.get(),
bgColor); bgColor);
} }

Просмотреть файл

@ -90,9 +90,6 @@ static Color ComputeColorForLine(uint32_t aLineIndex,
nscolor aBorderColor, nscolor aBorderColor,
nscolor aBackgroundColor); nscolor aBackgroundColor);
static Color ComputeCompositeColorForLine(uint32_t aLineIndex,
const nsBorderColors* aBorderColors);
// little helper function to check if the array of 4 floats given are // little helper function to check if the array of 4 floats given are
// equal to the given value // equal to the given value
static bool static bool
@ -178,7 +175,7 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(nsPresContext* aPresContext,
const Float* aBorderWidths, const Float* aBorderWidths,
RectCornerRadii& aBorderRadii, RectCornerRadii& aBorderRadii,
const nscolor* aBorderColors, const nscolor* aBorderColors,
nsBorderColors* const* aCompositeColors, const nsBorderColors* aCompositeColors,
nscolor aBackgroundColor) nscolor aBackgroundColor)
: mPresContext(aPresContext), : mPresContext(aPresContext),
mDocument(aDocument), mDocument(aDocument),
@ -191,11 +188,12 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(nsPresContext* aPresContext,
PodCopy(mBorderStyles, aBorderStyles, 4); PodCopy(mBorderStyles, aBorderStyles, 4);
PodCopy(mBorderWidths, aBorderWidths, 4); PodCopy(mBorderWidths, aBorderWidths, 4);
PodCopy(mBorderColors, aBorderColors, 4); PodCopy(mBorderColors, aBorderColors, 4);
if (aCompositeColors) { NS_FOR_CSS_SIDES(side) {
PodCopy(mCompositeColors, aCompositeColors, 4); if (aCompositeColors && !(*aCompositeColors)[side].IsEmpty()) {
mCompositeColors[side] = &(*aCompositeColors)[side];
} else { } else {
static nsBorderColors * const noColors[4] = { nullptr }; mCompositeColors[side] = nullptr;
PodCopy(mCompositeColors, noColors, 4); }
} }
mInnerRect = mOuterRect; mInnerRect = mOuterRect;
@ -319,10 +317,12 @@ nsCSSBorderRenderer::AreBorderSideFinalStylesSame(uint8_t aSides)
if (mBorderStyles[firstStyle] != mBorderStyles[i] || if (mBorderStyles[firstStyle] != mBorderStyles[i] ||
mBorderColors[firstStyle] != mBorderColors[i] || mBorderColors[firstStyle] != mBorderColors[i] ||
!nsBorderColors::Equal(mCompositeColors[firstStyle], !mCompositeColors[firstStyle] != !mCompositeColors[i] ||
mCompositeColors[i])) (mCompositeColors[firstStyle] &&
*mCompositeColors[firstStyle] != *mCompositeColors[i])) {
return false; return false;
} }
}
/* Then if it's one of the two-tone styles and we're not /* Then if it's one of the two-tone styles and we're not
* just comparing the TL or BR sides */ * just comparing the TL or BR sides */
@ -1265,18 +1265,9 @@ ComputeColorForLine(uint32_t aLineIndex,
aBorderColorStyle[aLineIndex]); aBorderColorStyle[aLineIndex]);
} }
Color
ComputeCompositeColorForLine(uint32_t aLineIndex,
const nsBorderColors* aBorderColors)
{
while (aLineIndex-- && aBorderColors->mNext)
aBorderColors = aBorderColors->mNext;
return Color::FromABGR(aBorderColors->mColor);
}
void void
nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *aCompositeColors) nsCSSBorderRenderer::DrawBorderSidesCompositeColors(
int aSides, const nsTArray<nscolor>& aCompositeColors)
{ {
RectCornerRadii radii = mBorderRadii; RectCornerRadii radii = mBorderRadii;
@ -1292,9 +1283,14 @@ nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderCo
Point itl = mInnerRect.TopLeft(); Point itl = mInnerRect.TopLeft();
Point ibr = mInnerRect.BottomRight(); Point ibr = mInnerRect.BottomRight();
MOZ_ASSERT(!aCompositeColors.IsEmpty());
Color compositeColor;
for (uint32_t i = 0; i < uint32_t(maxBorderWidth); i++) { for (uint32_t i = 0; i < uint32_t(maxBorderWidth); i++) {
ColorPattern color(ToDeviceColor( // advance to next color if exists.
ComputeCompositeColorForLine(i, aCompositeColors))); if (i < aCompositeColors.Length()) {
compositeColor = ToDeviceColor(Color::FromABGR(aCompositeColors[i]));
}
ColorPattern color(compositeColor);
Rect siRect = soRect; Rect siRect = soRect;
siRect.Deflate(1.0); siRect.Deflate(1.0);
@ -1334,7 +1330,7 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides)
uint8_t borderRenderStyle = NS_STYLE_BORDER_STYLE_NONE; uint8_t borderRenderStyle = NS_STYLE_BORDER_STYLE_NONE;
nscolor borderRenderColor; nscolor borderRenderColor;
const nsBorderColors *compositeColors = nullptr; const nsTArray<nscolor>* compositeColors = nullptr;
uint32_t borderColorStyleCount = 0; uint32_t borderColorStyleCount = 0;
BorderColorStyle borderColorStyleTopLeft[3], borderColorStyleBottomRight[3]; BorderColorStyle borderColorStyleTopLeft[3], borderColorStyleBottomRight[3];
@ -1392,7 +1388,7 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides)
maxBorderWidth = std::max(maxBorderWidth, mBorderWidths[i]); maxBorderWidth = std::max(maxBorderWidth, mBorderWidths[i]);
} }
if (maxBorderWidth <= MAX_COMPOSITE_BORDER_WIDTH) { if (maxBorderWidth <= MAX_COMPOSITE_BORDER_WIDTH) {
DrawBorderSidesCompositeColors(aSides, compositeColors); DrawBorderSidesCompositeColors(aSides, *compositeColors);
return; return;
} }
NS_WARNING("DrawBorderSides: too large border width for composite colors"); NS_WARNING("DrawBorderSides: too large border width for composite colors");
@ -3145,8 +3141,10 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
void void
nsCSSBorderRenderer::DrawRectangularCompositeColors() nsCSSBorderRenderer::DrawRectangularCompositeColors()
{ {
nsBorderColors *currentColors[4]; nscolor currentColors[4];
memcpy(currentColors, mCompositeColors, sizeof(nsBorderColors*) * 4); NS_FOR_CSS_SIDES(side) {
currentColors[side] = mBorderColors[side];
}
Rect rect = mOuterRect; Rect rect = mOuterRect;
rect.Deflate(0.5); rect.Deflate(0.5);
@ -3156,23 +3154,26 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors()
{ 0, -0.5 } }; { 0, -0.5 } };
for (int i = 0; i < mBorderWidths[0]; i++) { 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) { NS_FOR_CSS_SIDES(side) {
int sideNext = (side + 1) % 4; int sideNext = (side + 1) % 4;
Point firstCorner = rect.CCWCorner(side) + cornerAdjusts[side]; Point firstCorner = rect.CCWCorner(side) + cornerAdjusts[side];
Point secondCorner = rect.CWCorner(side) - cornerAdjusts[side]; Point secondCorner = rect.CWCorner(side) - cornerAdjusts[side];
Color currentColor = Color::FromABGR( Color currentColor = Color::FromABGR(currentColors[side]);
currentColors[side] ? currentColors[side]->mColor
: mBorderColors[side]);
mDrawTarget->StrokeLine(firstCorner, secondCorner, mDrawTarget->StrokeLine(firstCorner, secondCorner,
ColorPattern(ToDeviceColor(currentColor))); ColorPattern(ToDeviceColor(currentColor)));
Point cornerTopLeft = rect.CWCorner(side) - Point(0.5, 0.5); Point cornerTopLeft = rect.CWCorner(side) - Point(0.5, 0.5);
Color nextColor = Color::FromABGR( Color nextColor = Color::FromABGR(currentColors[sideNext]);
currentColors[sideNext] ? currentColors[sideNext]->mColor
: mBorderColors[sideNext]);
Color cornerColor((currentColor.r + nextColor.r) / 2.f, Color cornerColor((currentColor.r + nextColor.r) / 2.f,
(currentColor.g + nextColor.g) / 2.f, (currentColor.g + nextColor.g) / 2.f,
@ -3180,17 +3181,6 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors()
(currentColor.a + nextColor.a) / 2.f); (currentColor.a + nextColor.a) / 2.f);
mDrawTarget->FillRect(Rect(cornerTopLeft, Size(1, 1)), mDrawTarget->FillRect(Rect(cornerTopLeft, Size(1, 1)),
ColorPattern(ToDeviceColor(cornerColor))); 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); rect.Deflate(1);
} }
@ -3206,9 +3196,8 @@ nsCSSBorderRenderer::DrawBorders()
(mBorderStyles[0] == NS_STYLE_BORDER_STYLE_NONE || (mBorderStyles[0] == NS_STYLE_BORDER_STYLE_NONE ||
mBorderStyles[0] == NS_STYLE_BORDER_STYLE_HIDDEN || mBorderStyles[0] == NS_STYLE_BORDER_STYLE_HIDDEN ||
mBorderColors[0] == NS_RGBA(0,0,0,0))) || mBorderColors[0] == NS_RGBA(0,0,0,0))) ||
(mCompositeColors[0] && (mCompositeColors[0] && mCompositeColors[0]->Length() == 1 &&
(mCompositeColors[0]->mColor == NS_RGBA(0,0,0,0) && (*mCompositeColors[0])[0] == NS_RGBA(0,0,0,0))))
!mCompositeColors[0]->mNext))))
{ {
// All borders are the same style, and the style is either none or hidden, or the color // All borders are the same style, and the style is either none or hidden, or the color
// is transparent. // is transparent.

Просмотреть файл

@ -100,7 +100,7 @@ public:
const Float* aBorderWidths, const Float* aBorderWidths,
RectCornerRadii& aBorderRadii, RectCornerRadii& aBorderRadii,
const nscolor* aBorderColors, const nscolor* aBorderColors,
nsBorderColors* const* aCompositeColors, const nsBorderColors* aCompositeColors,
nscolor aBackgroundColor); nscolor aBackgroundColor);
// draw the entire border // draw the entire border
@ -151,7 +151,9 @@ private:
nscolor mBorderColors[4]; nscolor mBorderColors[4];
// the lists of colors for '-moz-border-top-colors' et. al. // 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<nscolor>* mCompositeColors[4];
// the background color // the background color
nscolor mBackgroundColor; nscolor mBackgroundColor;
@ -235,7 +237,8 @@ private:
void DrawBorderSides (int aSides); void DrawBorderSides (int aSides);
// function used by the above to handle -moz-border-colors // function used by the above to handle -moz-border-colors
void DrawBorderSidesCompositeColors(int aSides, const nsBorderColors *compositeColors); void DrawBorderSidesCompositeColors(
int aSides, const nsTArray<nscolor>& compositeColors);
// Setup the stroke options for the given dashed/dotted side // Setup the stroke options for the given dashed/dotted side
void SetupDashedOptions(StrokeOptions* aStrokeOptions, void SetupDashedOptions(StrokeOptions* aStrokeOptions,

Просмотреть файл

@ -1256,34 +1256,18 @@ Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder)
aBorder->EnsureBorderColors(); 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 void
Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc, Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
mozilla::Side aSide) mozilla::Side aSide)
{ {
if (aSrc->mBorderColors) { 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 void
Gecko_FontFamilyList_Clear(FontFamilyList* aList) { Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
aList->Clear(); aList->Clear();

Просмотреть файл

@ -282,13 +282,8 @@ bool Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_
// Border style // Border style
void Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder); 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, void Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
mozilla::Side aSide); mozilla::Side aSide);
const nsBorderColors* Gecko_GetMozBorderColors(const nsStyleBorder* aBorder,
mozilla::Side aSide);
// Font style // Font style
void Gecko_FontFamilyList_Clear(FontFamilyList* aList); void Gecko_FontFamilyList_Clear(FontFamilyList* aList);

Просмотреть файл

@ -190,7 +190,6 @@ whitelist-types = [
"Keyframe", "Keyframe",
"nsAttrName", "nsAttrName",
"nsAttrValue", "nsAttrValue",
"nsBorderColors",
"nscolor", "nscolor",
"nsChangeHint", "nsChangeHint",
"nsCSSCounterDesc", "nsCSSCounterDesc",
@ -443,7 +442,6 @@ structs-types = [
"StyleShapeSource", "StyleShapeSource",
"StyleTransition", "StyleTransition",
"gfxFontFeatureValueSet", "gfxFontFeatureValueSet",
"nsBorderColors",
"nsCSSCounterStyleRule", "nsCSSCounterStyleRule",
"nsCSSFontFaceRule", "nsCSSFontFaceRule",
"nsCSSKeyword", "nsCSSKeyword",

Просмотреть файл

@ -5490,19 +5490,14 @@ nsComputedDOMStyle::GetBorderColorsFor(mozilla::Side aSide)
const nsStyleBorder *border = StyleBorder(); const nsStyleBorder *border = StyleBorder();
if (border->mBorderColors) { if (border->mBorderColors) {
nsBorderColors* borderColors = border->mBorderColors[aSide]; const nsTArray<nscolor>& borderColors = (*border->mBorderColors)[aSide];
if (borderColors) { if (!borderColors.IsEmpty()) {
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false); RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
for (nscolor color : borderColors) {
do {
RefPtr<nsROCSSPrimitiveValue> primitive = new nsROCSSPrimitiveValue; RefPtr<nsROCSSPrimitiveValue> primitive = new nsROCSSPrimitiveValue;
SetToRGBAColor(primitive, color);
SetToRGBAColor(primitive, borderColors->mColor);
valueList->AppendCSSValue(primitive.forget()); valueList->AppendCSSValue(primitive.forget());
borderColors = borderColors->mNext; }
} while (borderColors);
return valueList.forget(); return valueList.forget();
} }
} }

Просмотреть файл

@ -7748,13 +7748,10 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
case eCSSUnit_Inherit: { case eCSSUnit_Inherit: {
conditions.SetUncacheable(); conditions.SetUncacheable();
border->ClearBorderColors(side); border->ClearBorderColors(side);
if (parentContext) { if (parentBorder->mBorderColors) {
nsBorderColors *parentColors;
parentBorder->GetCompositeColors(side, &parentColors);
if (parentColors) {
border->EnsureBorderColors(); border->EnsureBorderColors();
border->mBorderColors[side] = parentColors->Clone(); border->mBorderColors->mColors[side] =
} parentBorder->mBorderColors->mColors[side];
} }
break; break;
} }
@ -7769,7 +7766,7 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
while (list) { while (list) {
if (SetColor(list->mValue, unused, mPresContext, if (SetColor(list->mValue, unused, mPresContext,
aContext, borderColor, conditions)) aContext, borderColor, conditions))
border->AppendBorderColor(side, borderColor); border->mBorderColors->mColors[side].AppendElement(borderColor);
else { else {
NS_NOTREACHED("unexpected item in -moz-border-*-colors list"); NS_NOTREACHED("unexpected item in -moz-border-*-colors list");
} }

Просмотреть файл

@ -320,8 +320,7 @@ nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const
} }
nsStyleBorder::nsStyleBorder(const nsPresContext* aContext) 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) , mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
, mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH) , mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
, mFloatEdge(StyleFloatEdge::ContentBox) , mFloatEdge(StyleFloatEdge::ContentBox)
@ -349,27 +348,8 @@ nsStyleBorder::nsStyleBorder(const nsPresContext* aContext)
mTwipsPerPixel = aContext->DevPixelsToAppUnits(1); 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) nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
: mBorderColors(nullptr) : mBorderRadius(aSrc.mBorderRadius)
, mBorderRadius(aSrc.mBorderRadius)
, mBorderImageSource(aSrc.mBorderImageSource) , mBorderImageSource(aSrc.mBorderImageSource)
, mBorderImageSlice(aSrc.mBorderImageSlice) , mBorderImageSlice(aSrc.mBorderImageSlice)
, mBorderImageWidth(aSrc.mBorderImageWidth) , mBorderImageWidth(aSrc.mBorderImageWidth)
@ -385,9 +365,7 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
{ {
MOZ_COUNT_CTOR(nsStyleBorder); MOZ_COUNT_CTOR(nsStyleBorder);
if (aSrc.mBorderColors) { if (aSrc.mBorderColors) {
NS_FOR_CSS_SIDES(side) { mBorderColors.reset(new nsBorderColors(*aSrc.mBorderColors));
CopyBorderColorsFrom(aSrc.mBorderColors[side], side);
}
} }
NS_FOR_CSS_SIDES(side) { NS_FOR_CSS_SIDES(side) {
@ -399,12 +377,6 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
nsStyleBorder::~nsStyleBorder() nsStyleBorder::~nsStyleBorder()
{ {
MOZ_COUNT_DTOR(nsStyleBorder); MOZ_COUNT_DTOR(nsStyleBorder);
if (mBorderColors) {
for (int32_t i = 0; i < 4; i++) {
delete mBorderColors[i];
}
delete [] mBorderColors;
}
} }
void void
@ -516,9 +488,8 @@ nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
// Note that at this point if mBorderColors is non-null so is // Note that at this point if mBorderColors is non-null so is
// aNewData.mBorderColors // aNewData.mBorderColors
if (mBorderColors) { if (mBorderColors) {
NS_FOR_CSS_SIDES(ix) { NS_FOR_CSS_SIDES(side) {
if (!nsBorderColors::Equal(mBorderColors[ix], if ((*mBorderColors)[side] != (*aNewData.mBorderColors)[side]) {
aNewData.mBorderColors[ix])) {
return nsChangeHint_RepaintFrame; return nsChangeHint_RepaintFrame;
} }
} }

Просмотреть файл

@ -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 struct nsCSSShadowItem
{ {
nscoord mXOffset; nscoord mXOffset;
@ -1142,6 +1110,26 @@ static bool IsVisibleBorderStyle(uint8_t aStyle)
aStyle != NS_STYLE_BORDER_STYLE_HIDDEN); 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<nscolor>& operator[](mozilla::Side aSide) const {
return mColors[aSide];
}
nsTArray<nscolor> mColors[4];
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
{ {
explicit nsStyleBorder(const nsPresContext* aContext); explicit nsStyleBorder(const nsPresContext* aContext);
@ -1165,27 +1153,13 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
void EnsureBorderColors() { void EnsureBorderColors() {
if (!mBorderColors) { if (!mBorderColors) {
mBorderColors = new nsBorderColors*[4]; mBorderColors.reset(new nsBorderColors);
if (mBorderColors) {
for (int32_t i = 0; i < 4; i++) {
mBorderColors[i] = nullptr;
}
}
} }
} }
void ClearBorderColors(mozilla::Side aSide) { void ClearBorderColors(mozilla::Side aSide) {
if (mBorderColors && mBorderColors[aSide]) { if (mBorderColors) {
delete mBorderColors[aSide]; mBorderColors->mColors[aSide].Clear();
mBorderColors[aSide] = nullptr;
}
}
void CopyBorderColorsFrom(const nsBorderColors* aSrcBorderColors, mozilla::Side aSide) {
if (aSrcBorderColors) {
EnsureBorderColors();
ClearBorderColors(aSide);
mBorderColors[aSide] = aSrcBorderColors->Clone();
} }
} }
@ -1260,30 +1234,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
nsMargin GetImageOutset() const; 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 imgIRequest* GetBorderImageRequest() const
{ {
if (mBorderImageSource.GetType() == eStyleImageType_Image) { if (mBorderImageSource.GetType() == eStyleImageType_Image) {
@ -1293,7 +1243,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
} }
public: public:
nsBorderColors** mBorderColors; // [reset] composite (stripe) colors // [reset] composite (stripe) colors
mozilla::UniquePtr<nsBorderColors> mBorderColors;
nsStyleCorners mBorderRadius; // [reset] coord, percent nsStyleCorners mBorderRadius; // [reset] coord, percent
nsStyleImage mBorderImageSource; // [reset] nsStyleImage mBorderImageSource; // [reset]
nsStyleSides mBorderImageSlice; // [reset] factor, percent nsStyleSides mBorderImageSlice; // [reset] factor, percent