diff --git a/layout/style/ServoBindings.cpp b/layout/style/ServoBindings.cpp index 6072f13f8fee..bea37bf42e76 100644 --- a/layout/style/ServoBindings.cpp +++ b/layout/style/ServoBindings.cpp @@ -1542,7 +1542,7 @@ void Gecko_nsStyleSVGPaint_SetURLValue(nsStyleSVGPaint* aPaint, ServoBundledURI aURI) { RefPtr url = aURI.IntoCssUrl(); - aPaint->SetPaintServer(url.get(), NS_RGB(0, 0, 0)); + aPaint->SetPaintServer(url.get()); } void Gecko_nsStyleSVGPaint_Reset(nsStyleSVGPaint* aPaint) diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index 75ed6eb42426..7984b5d7b0b2 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -4192,6 +4192,16 @@ StyleClipBasicShapeToCSSArray(const StyleShapeSource& aClipPath, return true; } +static void +SetFallbackValue(nsCSSValuePair* aPair, const nsStyleSVGPaint& aPaint) +{ + if (aPaint.GetFallbackType() == eStyleSVGFallbackType_Color) { + aPair->mYValue.SetColorValue(aPaint.GetFallbackColor()); + } else { + aPair->mYValue.SetNoneValue(); + } +} + bool StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty, nsStyleContext* aStyleContext, @@ -4709,22 +4719,33 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty, NS_WARNING("Null paint server"); return false; } - nsAutoPtr pair(new nsCSSValuePair); - pair->mXValue.SetURLValue(url); - pair->mYValue.SetColorValue(paint.GetFallbackColor()); - aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(), - eUnit_CSSValuePair); + if (paint.GetFallbackType() != eStyleSVGFallbackType_NotSet) { + nsAutoPtr pair(new nsCSSValuePair); + pair->mXValue.SetURLValue(url); + SetFallbackValue(pair, paint); + aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(), + eUnit_CSSValuePair); + } else { + auto result = MakeUnique(); + result->SetURLValue(url); + aComputedValue.SetAndAdoptCSSValueValue( + result.release(), eUnit_URL); + } return true; } case eStyleSVGPaintType_ContextFill: case eStyleSVGPaintType_ContextStroke: { - nsAutoPtr pair(new nsCSSValuePair); - pair->mXValue.SetIntValue(paint.Type() == eStyleSVGPaintType_ContextFill ? - NS_COLOR_CONTEXT_FILL : NS_COLOR_CONTEXT_STROKE, - eCSSUnit_Enumerated); - pair->mYValue.SetColorValue(paint.GetFallbackColor()); - aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(), - eUnit_CSSValuePair); + int32_t value = paint.Type() == eStyleSVGPaintType_ContextFill ? + NS_COLOR_CONTEXT_FILL : NS_COLOR_CONTEXT_STROKE; + if (paint.GetFallbackType() != eStyleSVGFallbackType_NotSet) { + nsAutoPtr pair(new nsCSSValuePair); + pair->mXValue.SetIntValue(value, eCSSUnit_Enumerated); + SetFallbackValue(pair, paint); + aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(), + eUnit_CSSValuePair); + } else { + aComputedValue.SetIntValue(value, eUnit_Enumerated); + } return true; } default: diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index f478fce5a9ac..f400bf29c9e0 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -17302,6 +17302,7 @@ CSSParserImpl::ParsePaint(nsCSSPropertyID aPropID) return false; } + bool hasFallback = false; bool canHaveFallback = x.GetUnit() == eCSSUnit_URL || x.GetUnit() == eCSSUnit_Enumerated; if (canHaveFallback) { @@ -17309,17 +17310,16 @@ CSSParserImpl::ParsePaint(nsCSSPropertyID aPropID) ParseVariant(y, VARIANT_COLOR | VARIANT_NONE, nullptr); if (result == CSSParseResult::Error) { return false; - } else if (result == CSSParseResult::NotFound) { - y.SetNoneValue(); } + hasFallback = (result != CSSParseResult::NotFound); } - if (!canHaveFallback) { - AppendValue(aPropID, x); - } else { + if (hasFallback) { nsCSSValue val; val.SetPairValue(x, y); AppendValue(aPropID, val); + } else { + AppendValue(aPropID, x); } return true; } diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 16a07d46a45e..b61f04dae06d 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -5768,18 +5768,25 @@ nsComputedDOMStyle::GetFrameBoundsHeightForTransform(nscoord& aHeight) return true; } +already_AddRefed +nsComputedDOMStyle::GetFallbackValue(const nsStyleSVGPaint* aPaint) +{ + RefPtr fallback = new nsROCSSPrimitiveValue; + if (aPaint->GetFallbackType() == eStyleSVGFallbackType_Color) { + SetToRGBAColor(fallback, aPaint->GetFallbackColor()); + } else { + fallback->SetIdent(eCSSKeyword_none); + } + return fallback.forget(); +} + already_AddRefed nsComputedDOMStyle::GetSVGPaintFor(bool aFill) { RefPtr val = new nsROCSSPrimitiveValue; const nsStyleSVG* svg = StyleSVG(); - const nsStyleSVGPaint* paint = nullptr; - - if (aFill) - paint = &svg->mFill; - else - paint = &svg->mStroke; + const nsStyleSVGPaint* paint = aFill ? &svg->mFill : &svg->mStroke; nsAutoString paintString; @@ -5791,23 +5798,29 @@ nsComputedDOMStyle::GetSVGPaintFor(bool aFill) SetToRGBAColor(val, paint->GetColor()); break; case eStyleSVGPaintType_Server: { - RefPtr valueList = GetROCSSValueList(false); - RefPtr fallback = new nsROCSSPrimitiveValue; SetValueToURLValue(paint->GetPaintServer(), val); - SetToRGBAColor(fallback, paint->GetFallbackColor()); - - valueList->AppendCSSValue(val.forget()); - valueList->AppendCSSValue(fallback.forget()); - return valueList.forget(); + if (paint->GetFallbackType() != eStyleSVGFallbackType_NotSet) { + RefPtr valueList = GetROCSSValueList(false); + RefPtr fallback = GetFallbackValue(paint); + valueList->AppendCSSValue(val.forget()); + valueList->AppendCSSValue(fallback.forget()); + return valueList.forget(); + } + break; } case eStyleSVGPaintType_ContextFill: - val->SetIdent(eCSSKeyword_context_fill); - // XXXheycam context-fill and context-stroke can have fallback colors, - // so they should be serialized here too - break; - case eStyleSVGPaintType_ContextStroke: - val->SetIdent(eCSSKeyword_context_stroke); + case eStyleSVGPaintType_ContextStroke: { + val->SetIdent(paint->Type() == eStyleSVGPaintType_ContextFill ? + eCSSKeyword_context_fill : eCSSKeyword_context_stroke); + if (paint->GetFallbackType() != eStyleSVGFallbackType_NotSet) { + RefPtr valueList = GetROCSSValueList(false); + RefPtr fallback = GetFallbackValue(paint); + valueList->AppendCSSValue(val.forget()); + valueList->AppendCSSValue(fallback.forget()); + return valueList.forget(); + } break; + } } return val.forget(); diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 888b8121b2ff..7ef01c66e320 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -198,6 +198,8 @@ private: already_AddRefed GetMarginWidthFor(mozilla::Side aSide); + already_AddRefed GetFallbackValue(const nsStyleSVGPaint* aPaint); + already_AddRefed GetSVGPaintFor(bool aFill); // Appends all aLineNames (may be empty) space-separated to aResult. diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 63e7ac487d20..568ba3026281 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -9357,32 +9357,51 @@ SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint, } else { aResult.SetColor(NS_RGB(0, 0, 0)); } + } else if (aValue.GetUnit() == eCSSUnit_URL) { + aResult.SetPaintServer(aValue.GetURLStructValue()); + } else if (aValue.GetUnit() == eCSSUnit_Enumerated) { + switch (aValue.GetIntValue()) { + case NS_COLOR_CONTEXT_FILL: + aResult.SetContextValue(eStyleSVGPaintType_ContextFill); + break; + case NS_COLOR_CONTEXT_STROKE: + aResult.SetContextValue(eStyleSVGPaintType_ContextStroke); + break; + default: + NS_NOTREACHED("unknown keyword as paint server value"); + } } else if (SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aContext, color, aConditions)) { aResult.SetColor(color); } else if (aValue.GetUnit() == eCSSUnit_Pair) { const nsCSSValuePair& pair = aValue.GetPairValue(); + nsStyleSVGFallbackType fallbackType; nscolor fallback; if (pair.mYValue.GetUnit() == eCSSUnit_None) { + fallbackType = eStyleSVGFallbackType_None; fallback = NS_RGBA(0, 0, 0, 0); } else { MOZ_ASSERT(pair.mYValue.GetUnit() != eCSSUnit_Inherit, "cannot inherit fallback colour"); + fallbackType = eStyleSVGFallbackType_Color; SetColor(pair.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext, fallback, aConditions); } if (pair.mXValue.GetUnit() == eCSSUnit_URL) { - aResult.SetPaintServer(pair.mXValue.GetURLStructValue(), fallback); + aResult.SetPaintServer(pair.mXValue.GetURLStructValue(), + fallbackType, fallback); } else if (pair.mXValue.GetUnit() == eCSSUnit_Enumerated) { switch (pair.mXValue.GetIntValue()) { case NS_COLOR_CONTEXT_FILL: - aResult.SetContextValue(eStyleSVGPaintType_ContextFill, fallback); + aResult.SetContextValue(eStyleSVGPaintType_ContextFill, + fallbackType, fallback); break; case NS_COLOR_CONTEXT_STROKE: - aResult.SetContextValue(eStyleSVGPaintType_ContextStroke, fallback); + aResult.SetContextValue(eStyleSVGPaintType_ContextStroke, + fallbackType, fallback); break; default: NS_NOTREACHED("unknown keyword as paint server value"); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index f020c477456d..34ed23b70cb4 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1320,11 +1320,14 @@ nsStyleSVGPaint::Assign(const nsStyleSVGPaint& aOther) break; case eStyleSVGPaintType_Server: SetPaintServer(aOther.mPaint.mPaintServer, + aOther.mFallbackType, aOther.mFallbackColor); break; case eStyleSVGPaintType_ContextFill: case eStyleSVGPaintType_ContextStroke: - SetContextValue(aOther.mType, aOther.mFallbackColor); + SetContextValue(aOther.mType, + aOther.mFallbackType, + aOther.mFallbackColor); break; } } @@ -1338,12 +1341,14 @@ nsStyleSVGPaint::SetNone() void nsStyleSVGPaint::SetContextValue(nsStyleSVGPaintType aType, + nsStyleSVGFallbackType aFallbackType, nscolor aFallbackColor) { MOZ_ASSERT(aType == eStyleSVGPaintType_ContextFill || aType == eStyleSVGPaintType_ContextStroke); Reset(); mType = aType; + mFallbackType = aFallbackType; mFallbackColor = aFallbackColor; } @@ -1357,6 +1362,7 @@ nsStyleSVGPaint::SetColor(nscolor aColor) void nsStyleSVGPaint::SetPaintServer(css::URLValue* aPaintServer, + nsStyleSVGFallbackType aFallbackType, nscolor aFallbackColor) { MOZ_ASSERT(aPaintServer); @@ -1364,6 +1370,7 @@ nsStyleSVGPaint::SetPaintServer(css::URLValue* aPaintServer, mType = eStyleSVGPaintType_Server; mPaint.mPaintServer = aPaintServer; mPaint.mPaintServer->AddRef(); + mFallbackType = aFallbackType; mFallbackColor = aFallbackColor; } @@ -1378,10 +1385,12 @@ bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const case eStyleSVGPaintType_Server: return DefinitelyEqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) && + mFallbackType == aOther.mFallbackType && mFallbackColor == aOther.mFallbackColor; case eStyleSVGPaintType_ContextFill: case eStyleSVGPaintType_ContextStroke: - return mFallbackColor == aOther.mFallbackColor; + return mFallbackType == aOther.mFallbackType && + mFallbackColor == aOther.mFallbackColor; default: MOZ_ASSERT(mType == eStyleSVGPaintType_None, "Unexpected SVG paint type"); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 01ed60ee52dd..29c74841ff33 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -3410,9 +3410,18 @@ public: void SetNone(); void SetColor(nscolor aColor); void SetPaintServer(mozilla::css::URLValue* aPaintServer, + nsStyleSVGFallbackType aFallbackType, nscolor aFallbackColor); + void SetPaintServer(mozilla::css::URLValue* aPaintServer) { + SetPaintServer(aPaintServer, eStyleSVGFallbackType_NotSet, + NS_RGB(0, 0, 0)); + } void SetContextValue(nsStyleSVGPaintType aType, + nsStyleSVGFallbackType aFallbackType, nscolor aFallbackColor); + void SetContextValue(nsStyleSVGPaintType aType) { + SetContextValue(aType, eStyleSVGFallbackType_NotSet, NS_RGB(0, 0, 0)); + } nscolor GetColor() const { MOZ_ASSERT(mType == eStyleSVGPaintType_Color); diff --git a/layout/style/test/stylo-failures.md b/layout/style/test/stylo-failures.md index dadc5b6796a3..f003be142f4a 100644 --- a/layout/style/test/stylo-failures.md +++ b/layout/style/test/stylo-failures.md @@ -74,8 +74,6 @@ to mochitest command. * test_animations_event_order.html [2] * test_computed_style.html `gradient`: -moz- and -webkit-prefixed gradient values [35] * ... `mask`: mask-image isn't set properly bug 1341667 [10] -* ... `fill`: svg paint should distinguish whether there is fallback bug 1347409 [2] -* ... `stroke`: svg paint should distinguish whether there is fallback bug 1347409 [2] * character not properly escaped servo/servo#15947 * test_parse_url.html [1] * test_bug829816.html [8] diff --git a/layout/style/test/test_computed_style.html b/layout/style/test/test_computed_style.html index 8290ac5b6e36..665e6af43621 100644 --- a/layout/style/test/test_computed_style.html +++ b/layout/style/test/test_computed_style.html @@ -470,22 +470,22 @@ var noframe_container = document.getElementById("content"); var nonLocalURL = "url(\"foo.svg#foo\")"; var resolvedNonLocalURL = "url(\"" + docPath + "foo.svg#foo\")"; - var testStyles = { - "mask" : "", - "markerStart" : "", - "markerMid" : "", - "markerEnd" : "", - "clipPath" : "", - "filter" : "", - "fill" : " rgba(0, 0, 0, 0)", - "stroke" : " rgba(0, 0, 0, 0)", - }; + var testStyles = [ + "mask", + "markerStart", + "markerMid", + "markerEnd", + "clipPath", + "filter", + "fill", + "stroke", + ]; - for (var prop in testStyles) { + for (var prop of testStyles) { p.style[prop] = localURL; - is(cs[prop], localURL + testStyles[prop], "computed value of " + prop); + is(cs[prop], localURL, "computed value of " + prop); p.style[prop] = nonLocalURL; - is(cs[prop], resolvedNonLocalURL + testStyles[prop], "computed value of " + prop); + is(cs[prop], resolvedNonLocalURL, "computed value of " + prop); } p.remove(); diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 869c4146bb9e..6a5c7cf22142 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -1453,10 +1453,18 @@ nsSVGUtils::GetFallbackOrPaintColor(nsStyleContext *aStyleContext, { const nsStyleSVGPaint &paint = aStyleContext->StyleSVG()->*aFillOrStroke; nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited(); - bool isServer = paint.Type() == eStyleSVGPaintType_Server || - paint.Type() == eStyleSVGPaintType_ContextFill || - paint.Type() == eStyleSVGPaintType_ContextStroke; - nscolor color = isServer ? paint.GetFallbackColor() : paint.GetColor(); + nscolor color; + switch (paint.Type()) { + case eStyleSVGPaintType_Server: + case eStyleSVGPaintType_ContextFill: + case eStyleSVGPaintType_ContextStroke: + color = paint.GetFallbackType() == eStyleSVGFallbackType_Color ? + paint.GetFallbackColor() : NS_RGBA(0, 0, 0, 0); + break; + default: + color = paint.GetColor(); + break; + } if (styleIfVisited) { const nsStyleSVGPaint &paintIfVisited = styleIfVisited->StyleSVG()->*aFillOrStroke; @@ -1542,6 +1550,10 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame* aFrame, } } + if (style->mFill.GetFallbackType() == eStyleSVGFallbackType_None) { + return DrawResult::SUCCESS; + } + // On failure, use the fallback colour in case we have an // objectBoundingBox where the width or height of the object is zero. // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox @@ -1618,6 +1630,10 @@ nsSVGUtils::MakeStrokePatternFor(nsIFrame* aFrame, } } + if (style->mStroke.GetFallbackType() == eStyleSVGFallbackType_None) { + return DrawResult::SUCCESS; + } + // On failure, use the fallback colour in case we have an // objectBoundingBox where the width or height of the object is zero. // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox