Title: [275826] trunk
Revision
275826
Author
wei...@apple.com
Date
2021-04-12 09:53:16 -0700 (Mon, 12 Apr 2021)

Log Message

Update color-contrast() to support a target contrast ratio
https://bugs.webkit.org/show_bug.cgi?id=224411

Reviewed by Antti Koivisto.

Source/WebCore:

Updated fast/css/parsing-color-contrast.html with new test cases.

* css/CSSValueKeywords.in:
Add new keywords, AA and AA-large which are constants for contrast ratios of 4.5
and 3.0 respectively.

* css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):
Remove now incorrect comment about adding support for fallback as fallback
has been removed from the spec.

(WebCore::CSSPropertyParserHelpers::selectFirstColorThatMeetsOrExceedsTargetContrast):
(WebCore::CSSPropertyParserHelpers::selectFirstColorWithHighestContrast):
(WebCore::CSSPropertyParserHelpers::parseColorContrastFunctionParameters):
Add support for the new optional target contrast ratio in color-contrast() that was
recently added to CSS Color 5.

LayoutTests:

Add tests and update results for target contrast ratios in color-contrast().

* fast/css/parsing-color-contrast-expected.txt:
* fast/css/parsing-color-contrast.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (275825 => 275826)


--- trunk/LayoutTests/ChangeLog	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/LayoutTests/ChangeLog	2021-04-12 16:53:16 UTC (rev 275826)
@@ -1,3 +1,15 @@
+2021-04-12  Sam Weinig  <wei...@apple.com>
+
+        Update color-contrast() to support a target contrast ratio
+        https://bugs.webkit.org/show_bug.cgi?id=224411
+
+        Reviewed by Antti Koivisto.
+
+        Add tests and update results for target contrast ratios in color-contrast().
+
+        * fast/css/parsing-color-contrast-expected.txt:
+        * fast/css/parsing-color-contrast.html:
+
 2021-04-12  Antti Koivisto  <an...@apple.com>
 
         Descendant style relations are sometimes reset when they shouldn't

Modified: trunk/LayoutTests/fast/css/parsing-color-contrast-expected.txt (275825 => 275826)


--- trunk/LayoutTests/fast/css/parsing-color-contrast-expected.txt	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/LayoutTests/fast/css/parsing-color-contrast-expected.txt	2021-04-12 16:53:16 UTC (rev 275826)
@@ -3,7 +3,9 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-color-contrast(... vs ..., ...)
+color-contrast(... vs ..., ... [to ...])
+
+Test with no specified target contrast
 PASS computedStyle("background-color", "color-contrast(white vs red, blue)") is "rgb(0, 0, 255)"
 PASS computedStyle("background-color", "color-contrast(white vs blue, red)") is "rgb(0, 0, 255)"
 PASS computedStyle("background-color", "color-contrast(white vs red, blue, green)") is "rgb(0, 0, 255)"
@@ -15,6 +17,15 @@
 PASS computedStyle("background-color", "color-contrast(black vs white, white)") is "rgb(255, 255, 255)"
 PASS computedStyle("background-color", "color-contrast(red vs blue, rgb(255, 255, 255, .5))") is "rgba(255, 255, 255, 0.5)"
 
+Test with specified target contrast
+PASS computedStyle("background-color", "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)") is "rgb(0, 100, 0)"
+PASS computedStyle("background-color", "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA-large)") is "rgb(128, 128, 0)"
+PASS computedStyle("background-color", "color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)") is "rgb(128, 0, 0)"
+
+Test with specified target contrast that none meet
+PASS computedStyle("background-color", "color-contrast(wheat vs bisque, darkgoldenrod, olive to 100)") is "rgb(0, 0, 0)"
+PASS computedStyle("background-color", "color-contrast(green vs bisque, darkgoldenrod, olive to 100)") is "rgb(255, 255, 255)"
+
 Test non-sRGB colors
 PASS computedStyle("background-color", "color-contrast(green vs color(display-p3 0 1 0), color(display-p3 0 0 1))") is "color(display-p3 0 1 0)"
 PASS computedStyle("background-color", "color-contrast(color(display-p3 1 1 0) vs color(display-p3 0 1 0), color(display-p3 0 0 1))") is "color(display-p3 0 0 1)"
@@ -27,6 +38,9 @@
 PASS computedStyle("background-color", "color-contrast(white vs )") is "rgba(0, 0, 0, 0)"
 PASS computedStyle("background-color", "color-contrast(white)") is "rgba(0, 0, 0, 0)"
 PASS computedStyle("background-color", "color-contrast(white vs red green)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color-contrast(white vs red, green to)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color-contrast(white vs red, green to invalid)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "color-contrast(white vs red to AA)") is "rgba(0, 0, 0, 0)"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/css/parsing-color-contrast.html (275825 => 275826)


--- trunk/LayoutTests/fast/css/parsing-color-contrast.html	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/LayoutTests/fast/css/parsing-color-contrast.html	2021-04-12 16:53:16 UTC (rev 275826)
@@ -26,8 +26,11 @@
         testComputedProperty("background-color", value, expected);
     }
 
-    debug('color-contrast(... vs ..., ...)');
+    debug('color-contrast(... vs ..., ... [to ...])');
 
+    debug('');
+    debug('Test with no specified target contrast')
+
     testComputed(`color-contrast(white vs red, blue)`, `rgb(0, 0, 255)`);
     testComputed(`color-contrast(white vs blue, red)`, `rgb(0, 0, 255)`);
     testComputed(`color-contrast(white vs red, blue, green)`, `rgb(0, 0, 255)`);
@@ -40,6 +43,19 @@
     testComputed(`color-contrast(red vs blue, rgb(255, 255, 255, .5))`, `rgba(255, 255, 255, 0.5)`);
 
     debug('');
+    debug('Test with specified target contrast')
+
+    testComputed(`color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)`, `rgb(0, 100, 0)`); // darkgreen
+    testComputed(`color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA-large)`, `rgb(128, 128, 0)`); // olive
+    testComputed(`color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)`, `rgb(128, 0, 0)`); // olive maroon
+    
+    debug('');
+    debug('Test with specified target contrast that none meet')
+    testComputed(`color-contrast(wheat vs bisque, darkgoldenrod, olive to 100)`, `rgb(0, 0, 0)`); // black
+    testComputed(`color-contrast(green vs bisque, darkgoldenrod, olive to 100)`, `rgb(255, 255, 255)`); // white
+
+
+    debug('');
     debug('Test non-sRGB colors');
 
     testComputed(`color-contrast(green vs color(display-p3 0 1 0), color(display-p3 0 0 1))`, `color(display-p3 0 1 0)`);
@@ -55,6 +71,9 @@
     testComputed(`color-contrast(white vs )`, `rgba(0, 0, 0, 0)`);
     testComputed(`color-contrast(white)`, `rgba(0, 0, 0, 0)`);
     testComputed(`color-contrast(white vs red green)`, `rgba(0, 0, 0, 0)`);
+    testComputed(`color-contrast(white vs red, green to)`, `rgba(0, 0, 0, 0)`);
+    testComputed(`color-contrast(white vs red, green to invalid)`, `rgba(0, 0, 0, 0)`);
+    testComputed(`color-contrast(white vs red to AA)`, `rgba(0, 0, 0, 0)`);
 
 </script>
     

Modified: trunk/Source/WebCore/ChangeLog (275825 => 275826)


--- trunk/Source/WebCore/ChangeLog	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/Source/WebCore/ChangeLog	2021-04-12 16:53:16 UTC (rev 275826)
@@ -1,3 +1,27 @@
+2021-04-12  Sam Weinig  <wei...@apple.com>
+
+        Update color-contrast() to support a target contrast ratio
+        https://bugs.webkit.org/show_bug.cgi?id=224411
+
+        Reviewed by Antti Koivisto.
+
+        Updated fast/css/parsing-color-contrast.html with new test cases.
+
+        * css/CSSValueKeywords.in:
+        Add new keywords, AA and AA-large which are constants for contrast ratios of 4.5
+        and 3.0 respectively.
+
+        * css/parser/CSSPropertyParserHelpers.cpp:
+        (WebCore::CSSPropertyParserHelpers::parseColorFunctionParameters):
+        Remove now incorrect comment about adding support for fallback as fallback
+        has been removed from the spec. 
+        
+        (WebCore::CSSPropertyParserHelpers::selectFirstColorThatMeetsOrExceedsTargetContrast):
+        (WebCore::CSSPropertyParserHelpers::selectFirstColorWithHighestContrast):
+        (WebCore::CSSPropertyParserHelpers::parseColorContrastFunctionParameters):
+        Add support for the new optional target contrast ratio in color-contrast() that was
+        recently added to CSS Color 5.
+
 2021-04-12  Antti Koivisto  <an...@apple.com>
 
         Descendant style relations are sometimes reset when they shouldn't

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (275825 => 275826)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-04-12 16:53:16 UTC (rev 275826)
@@ -1438,6 +1438,8 @@
 // color-contast()
 color-contrast
 vs
+AA
+AA-large
 
 // color-mix()
 color-mix

Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (275825 => 275826)


--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-04-12 16:49:52 UTC (rev 275825)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp	2021-04-12 16:53:16 UTC (rev 275826)
@@ -1502,8 +1502,6 @@
     if (!color.isValid())
         return { };
 
-    // FIXME: Support the comma-separated list of fallback color values.
-
     if (!args.atEnd())
         return { };
 
@@ -1511,6 +1509,40 @@
     return color;
 }
 
+static Color selectFirstColorThatMeetsOrExceedsTargetContrast(const Color& originBackgroundColor, const Vector<Color>& colorsToCompareAgainst, double targetContrast)
+{
+    auto originBackgroundColorLuminance = originBackgroundColor.luminance();
+
+    for (auto& color : colorsToCompareAgainst) {
+        auto contrastRatio = WebCore::contrastRatio(originBackgroundColorLuminance, color.luminance());
+        if (contrastRatio >= targetContrast)
+            return color;
+    }
+    
+    // If there is a target contrast, and the end of the list is reached without meeting that target,
+    // either white or black is returned, whichever has the higher contrast.
+    auto contrastRatioWithWhite = WebCore::contrastRatio(originBackgroundColorLuminance, 1.0f);
+    auto contrastRatioWithBlack = WebCore::contrastRatio(originBackgroundColorLuminance, 0.0f);
+    return contrastRatioWithWhite > contrastRatioWithBlack ? Color::white : Color::black;
+}
+
+static Color selectFirstColorWithHighestContrast(const Color& originBackgroundColor, const Vector<Color>& colorsToCompareAgainst)
+{
+    auto originBackgroundColorLuminance = originBackgroundColor.luminance();
+
+    size_t indexOfColorWithHigestContrastRatio = 0;
+    float highestContrastRatioSoFar = 0;
+    for (size_t i = 0; i < colorsToCompareAgainst.size(); ++i) {
+        auto contrastRatio = WebCore::contrastRatio(originBackgroundColorLuminance, colorsToCompareAgainst[i].luminance());
+        if (contrastRatio > highestContrastRatioSoFar) {
+            highestContrastRatioSoFar = contrastRatio;
+            indexOfColorWithHigestContrastRatio = i;
+        }
+    }
+
+    return colorsToCompareAgainst[indexOfColorWithHigestContrastRatio];
+}
+
 static Color parseColorContrastFunctionParameters(CSSParserTokenRange& range, const CSSParserContext& context)
 {
     ASSERT(range.peek().functionId() == CSSValueColorContrast);
@@ -1528,6 +1560,7 @@
         return { };
 
     Vector<Color> colorsToCompareAgainst;
+    bool consumedTo = false;
     do {
         auto colorToCompareAgainst = consumeOriginColor(args, context);
         if (!colorToCompareAgainst.isValid())
@@ -1534,24 +1567,34 @@
             return { };
 
         colorsToCompareAgainst.append(WTFMove(colorToCompareAgainst));
+
+        if (consumeIdentRaw<CSSValueTo>(args)) {
+            consumedTo = true;
+            break;
+        }
     } while (consumeCommaIncludingWhitespace(args));
 
     if (colorsToCompareAgainst.size() == 1)
         return { };
 
-    auto originBackgroundColorLuminance = originBackgroundColor.luminance();
+    if (consumedTo) {
+        auto targetContrast = [&] () -> Optional<double> {
+            if (consumeIdentRaw<CSSValueAA>(args))
+                return 4.5;
+            if (consumeIdentRaw<CSSValueAALarge>(args))
+                return 3.0;
+            return consumeNumberRaw(args);
+        }();
 
-    size_t indexOfColorWithHigestContrastRatio = 0;
-    float highestContrastRatioSoFar = 0;
-    for (size_t i = 0; i < colorsToCompareAgainst.size(); ++i) {
-        auto contrastRatio = WebCore::contrastRatio(originBackgroundColorLuminance, colorsToCompareAgainst[i].luminance());
-        if (contrastRatio > highestContrastRatioSoFar) {
-            highestContrastRatioSoFar = contrastRatio;
-            indexOfColorWithHigestContrastRatio = i;
-        }
+        if (!targetContrast)
+            return { };
+        
+        // When a target constast is specified, we select "the first color color to meet or exceed the target contrast."
+        return selectFirstColorThatMeetsOrExceedsTargetContrast(originBackgroundColor, colorsToCompareAgainst, *targetContrast);
     }
 
-    return colorsToCompareAgainst[indexOfColorWithHigestContrastRatio];
+    // When a target constast is NOT specified, we select "the first color with the highest contrast to the single color."
+    return selectFirstColorWithHighestContrast(originBackgroundColor, colorsToCompareAgainst);
 }
 
 enum class ColorMixColorSpace {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to