Issue #1826 - Parse calc() weights in color-mix

This commit is contained in:
Basilisk-Dev 2026-05-11 15:16:48 -04:00 • committed by EAZYBLACK
commit 6a37c361c2
2 changed files with 46 additions and 24 deletions

View file

@ -1493,6 +1493,7 @@ protected:
const nsCSSPropertyID aPropIDs[], int32_t aNumIDs); const nsCSSPropertyID aPropIDs[], int32_t aNumIDs);
CSSParseResult ParseColor(nsCSSValue& aValue); CSSParseResult ParseColor(nsCSSValue& aValue);
CSSParseResult ParseColorMixPercentage(float& aWeight);
template<typename ComponentType> template<typename ComponentType>
bool ParseRGBColor(ComponentType& aR, bool ParseRGBColor(ComponentType& aR,
@ -7680,6 +7681,37 @@ CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags, nsCSSContextType aContext)
return declaration.forget(); return declaration.forget();
} }
CSSParseResult
CSSParserImpl::ParseColorMixPercentage(float& aWeight)
{
if (!GetToken(true)) {
return CSSParseResult::NotFound;
}
if (mToken.mType == eCSSToken_Percentage) {
aWeight = mToken.mNumber;
} else if (IsCalcFunctionToken(mToken)) {
nsCSSValue calcValue;
uint32_t calcResultVariantMask = VARIANT_PERCENT;
if (!ParseCalc(calcValue, VARIANT_PERCENT, &calcResultVariantMask) ||
!(calcResultVariantMask & VARIANT_PERCENT)) {
return CSSParseResult::Error;
}
ReducePercentageCalcOps ops;
aWeight = mozilla::css::ComputeCalc(calcValue, ops);
} else {
UngetToken();
return CSSParseResult::NotFound;
}
if (aWeight < 0.0f || aWeight > 1.0f) {
return CSSParseResult::Error;
}
return CSSParseResult::Ok;
}
CSSParseResult CSSParseResult
CSSParserImpl::ParseColor(nsCSSValue& aValue) CSSParserImpl::ParseColor(nsCSSValue& aValue)
{ {
@ -7781,18 +7813,12 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
// parse optional weight for first color // parse optional weight for first color
bool w1_specified = false; bool w1_specified = false;
float w1 = 0.5f; // Default to 50% float w1 = 0.5f; // Default to 50%
if (GetToken(true)) { CSSParseResult weightResult = ParseColorMixPercentage(w1);
if (mToken.mType == eCSSToken_Percentage) { if (weightResult == CSSParseResult::Ok) {
w1 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0) w1_specified = true;
w1_specified = true; } else if (weightResult == CSSParseResult::Error) {
// Reject invalid percentages (outside 0-100% range) SkipUntil(')');
if (w1 < 0.0f || w1 > 1.0f) { return CSSParseResult::Error;
SkipUntil(')');
return CSSParseResult::Error;
}
} else {
UngetToken();
}
} }
if (!ExpectSymbol(',', true)) { if (!ExpectSymbol(',', true)) {
@ -7809,18 +7835,12 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
// parse optional weight for second color // parse optional weight for second color
bool w2_specified = false; bool w2_specified = false;
float w2 = 0.5f; // default to 50% float w2 = 0.5f; // default to 50%
if (GetToken(true)) { weightResult = ParseColorMixPercentage(w2);
if (mToken.mType == eCSSToken_Percentage) { if (weightResult == CSSParseResult::Ok) {
w2 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0) w2_specified = true;
w2_specified = true; } else if (weightResult == CSSParseResult::Error) {
// Reject invalid percentages (outside 0-100% range) SkipUntil(')');
if (w2 < 0.0f || w2 > 1.0f) { return CSSParseResult::Error;
SkipUntil(')');
return CSSParseResult::Error;
}
} else {
UngetToken();
}
} }
if (w1_specified && !w2_specified) { if (w1_specified && !w2_specified) {

View file

@ -417,6 +417,8 @@ var noframe_container = document.getElementById("content");
["color-mix(in oklab, red, blue)", "rgb(140, 83, 162)"], ["color-mix(in oklab, red, blue)", "rgb(140, 83, 162)"],
["color-mix(in oklch, red, blue)", "rgb(183, 0, 190)"], ["color-mix(in oklch, red, blue)", "rgb(183, 0, 190)"],
["color-mix(in oklab, red, transparent)", "rgba(255, 0, 0, 0.5)"], ["color-mix(in oklab, red, transparent)", "rgba(255, 0, 0, 0.5)"],
["color-mix(in srgb, red, transparent calc(100% - 100%*1))", "rgb(255, 0, 0)"],
["color-mix(in srgb, red, transparent calc(50%))", "rgba(255, 0, 0, 0.5)"],
["color-mix(in oklab, oklab(0.1 0.2 0.3), oklab(0.5 0.6 0.7))", "rgb(83, 24, 0)"], ["color-mix(in oklab, oklab(0.1 0.2 0.3), oklab(0.5 0.6 0.7))", "rgb(83, 24, 0)"],
["color-mix(in oklch, oklch(0.1 0.2 30), oklch(0.5 0.6 70))", "rgb(84, 23, 0)"], ["color-mix(in oklch, oklch(0.1 0.2 30), oklch(0.5 0.6 70))", "rgb(84, 23, 0)"],
]; ];