From 80b30a81778e28e3da88c8af88e99c8d15816dfb Mon Sep 17 00:00:00 2001 From: Moonchild Date: Fri, 28 Mar 2025 23:05:50 +0100 Subject: [PATCH] Issue #2720 - Implement two-location color stop logic. This allows for two-location color stops (`color x% y%`) which is shorthand for `color x%, color y%` where both colors are equal. (pct/length accepted) See code comment for the reason it's implemented the way it is. Resolves #2720 --- layout/style/nsCSSParser.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index dd6f0f4a3d..f9a2bc9f50 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -10542,7 +10542,7 @@ CSSParserImpl::ParsePlaceSelf() return true; } -// : [ | ]? +// : [ | ]? [ | ]? bool CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient) { @@ -10565,6 +10565,27 @@ CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient) } stop->mLocation.SetNoneValue(); } + + // Parse double-location stop second arg if present, no error if missing (normal stop). + // First, append another stop. For the parsing logic to work, we always need to append + // a stop first so the parsed values have somewhere to go. This does mean we're losing + // some performance because if the shorthand isn't present the stop has to be removed + // again, causing unnecessary array element juggling. + // See issue #2720 + nsCSSValueGradientStop* stop2 = aGradient->mStops.AppendElement(); + result = ParseVariant(stop2->mLocation, VARIANT_LP | VARIANT_CALC, nullptr); + if (result != CSSParseResult::NotFound) { + if (result == CSSParseResult::Error) { + // We didn't get a parseable stop, remove the additional stop again and throw. + aGradient->mStops.SetLength(aGradient->mStops.Length()-1); + return false; + } + stop2->mColor = stop->mColor; // copy color from first stop arg + } else { + // We didn't get a second stop after all, remove the additional stop again. + aGradient->mStops.SetLength(aGradient->mStops.Length()-1); + } + return true; }