From 6a37c361c2d41111ac0acde0b96acad6b9d64ad4 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 11 May 2026 15:16:48 -0400 Subject: [PATCH] Issue #1826 - Parse calc() weights in color-mix --- layout/style/nsCSSParser.cpp | 68 ++++++++++++++-------- layout/style/test/test_computed_style.html | 2 + 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 9383b51ff6..75476c71a2 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -1493,6 +1493,7 @@ protected: const nsCSSPropertyID aPropIDs[], int32_t aNumIDs); CSSParseResult ParseColor(nsCSSValue& aValue); + CSSParseResult ParseColorMixPercentage(float& aWeight); template bool ParseRGBColor(ComponentType& aR, @@ -7680,6 +7681,37 @@ CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags, nsCSSContextType aContext) 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 CSSParserImpl::ParseColor(nsCSSValue& aValue) { @@ -7781,18 +7813,12 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue) // parse optional weight for first color bool w1_specified = false; float w1 = 0.5f; // Default to 50% - if (GetToken(true)) { - if (mToken.mType == eCSSToken_Percentage) { - w1 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0) - w1_specified = true; - // Reject invalid percentages (outside 0-100% range) - if (w1 < 0.0f || w1 > 1.0f) { - SkipUntil(')'); - return CSSParseResult::Error; - } - } else { - UngetToken(); - } + CSSParseResult weightResult = ParseColorMixPercentage(w1); + if (weightResult == CSSParseResult::Ok) { + w1_specified = true; + } else if (weightResult == CSSParseResult::Error) { + SkipUntil(')'); + return CSSParseResult::Error; } if (!ExpectSymbol(',', true)) { @@ -7809,18 +7835,12 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue) // parse optional weight for second color bool w2_specified = false; float w2 = 0.5f; // default to 50% - if (GetToken(true)) { - if (mToken.mType == eCSSToken_Percentage) { - w2 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0) - w2_specified = true; - // Reject invalid percentages (outside 0-100% range) - if (w2 < 0.0f || w2 > 1.0f) { - SkipUntil(')'); - return CSSParseResult::Error; - } - } else { - UngetToken(); - } + weightResult = ParseColorMixPercentage(w2); + if (weightResult == CSSParseResult::Ok) { + w2_specified = true; + } else if (weightResult == CSSParseResult::Error) { + SkipUntil(')'); + return CSSParseResult::Error; } if (w1_specified && !w2_specified) { diff --git a/layout/style/test/test_computed_style.html b/layout/style/test/test_computed_style.html index 5363e1dac5..f3951bc50b 100644 --- a/layout/style/test/test_computed_style.html +++ b/layout/style/test/test_computed_style.html @@ -417,6 +417,8 @@ var noframe_container = document.getElementById("content"); ["color-mix(in oklab, red, blue)", "rgb(140, 83, 162)"], ["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 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 oklch, oklch(0.1 0.2 30), oklch(0.5 0.6 70))", "rgb(84, 23, 0)"], ];