Skip to content
Permalink
Browse files
[web-animations] additive/accumulative color blending fails to yield …
…intermediary out-of-bounds values

https://bugs.webkit.org/show_bug.cgi?id=242185
<rdar://96593559>

Reviewed by Antoine Quint.

Additive (and Accumulative, which is identical for colors) blending in web animations is
implemented by calling the blend function two extra times:

1. First to add the 'base' color to the 'from' color, giving us 'additive-from'.
    e.g. blend(base, from, add-operation)
2. Second to add the 'base' color to the 'to' color, giving us the 'additive-to'.
    e.g. blend(base, to, add-operation)

It then interpolates 'additive-from' to 'additive-to', using the normal, 'replace', blend
path. Further, it expects 'additive-from' and 'additive-to' to be unclamped color values.

To support this scheme, the blend function for Color was updated to implement support for
the add operation, using a new addColorComponents helper (which is just a wrapper around
interpolatColorComponents that specifies 100% of each color) which uses ExtendedSRGBA to
avoid clamping. The normal, replace, blend path was changed to use the now standard color
interpolation function, interpolateColorComponents, which supports all interpolation methods
not just SRGB, to make it match convention. To maintain compatability with existing animmation
interpolation, the result of the replace blend is clipped to the sRGB gamut. This clipping
is suspect, but the tests currently require this. Additional discussion with the WG is
needed to deterimine the best path forward.

* LayoutTests/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-001-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-001-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt:
* Source/WebCore/platform/graphics/ColorBlending.cpp:
(WebCore::blend):
* Source/WebCore/platform/graphics/ColorInterpolation.h:
(WebCore::interpolateAlphaPremulitplied): Add a clamp, needed for the additive blend, as alpha > 1 doesn't really make sense.
(WebCore::addColorComponents):

Canonical link: https://commits.webkit.org/254850@main
  • Loading branch information
weinig authored and graouts committed Sep 26, 2022
1 parent 201eb35 commit 35a0ba08385cfdc1e374a1622a229ccbe618f0ed
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 38 deletions.
@@ -16,7 +16,7 @@ PASS background-attachment (type: discrete) has testAccumulation function
PASS background-attachment: "local" onto "fixed"
PASS background-attachment: "fixed" onto "local"
PASS background-color (type: color) has testAccumulation function
FAIL background-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS background-color supports animating as color of rgb() with overflowed from and to values
PASS background-color supports animating as color of #RGB
PASS background-color supports animating as color of hsl()
PASS background-color supports animating as color of #RGBa
@@ -38,7 +38,7 @@ PASS background-repeat (type: discrete) has testAccumulation function
PASS background-repeat: "round" onto "space"
PASS background-repeat: "space" onto "round"
PASS border-bottom-color (type: color) has testAccumulation function
FAIL border-bottom-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-bottom-color supports animating as color of rgb() with overflowed from and to values
PASS border-bottom-color supports animating as color of #RGB
PASS border-bottom-color supports animating as color of hsl()
PASS border-bottom-color supports animating as color of #RGBa
@@ -60,7 +60,7 @@ PASS border-image-source (type: discrete) has testAccumulation function
PASS border-image-source: "url("http://localhost/test-2")" onto "url("http://localhost/test-1")"
PASS border-image-source: "url("http://localhost/test-1")" onto "url("http://localhost/test-2")"
PASS border-left-color (type: color) has testAccumulation function
FAIL border-left-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-left-color supports animating as color of rgb() with overflowed from and to values
PASS border-left-color supports animating as color of #RGB
PASS border-left-color supports animating as color of hsl()
PASS border-left-color supports animating as color of #RGBa
@@ -73,7 +73,7 @@ PASS border-left-width (type: length) has testAccumulation function
PASS border-left-width: length
PASS border-left-width: length of rem
PASS border-right-color (type: color) has testAccumulation function
FAIL border-right-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-right-color supports animating as color of rgb() with overflowed from and to values
PASS border-right-color supports animating as color of #RGB
PASS border-right-color supports animating as color of hsl()
PASS border-right-color supports animating as color of #RGBa
@@ -89,7 +89,7 @@ PASS border-spacing (type: lengthPair) has testAccumulation function
PASS border-spacing: length pair
PASS border-spacing: length pair of rem
PASS border-top-color (type: color) has testAccumulation function
FAIL border-top-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-top-color supports animating as color of rgb() with overflowed from and to values
PASS border-top-color supports animating as color of #RGB
PASS border-top-color supports animating as color of hsl()
PASS border-top-color supports animating as color of #RGBa
@@ -110,7 +110,7 @@ PASS caption-side (type: discrete) has testAccumulation function
PASS caption-side: "bottom" onto "top"
PASS caption-side: "top" onto "bottom"
PASS caret-color (type: color) has testAccumulation function
FAIL caret-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS caret-color supports animating as color of rgb() with overflowed from and to values
PASS caret-color supports animating as color of #RGB
PASS caret-color supports animating as color of hsl()
PASS caret-color supports animating as color of #RGBa
@@ -130,7 +130,7 @@ PASS clip-rule (type: discrete) has testAccumulation function
PASS clip-rule: "nonzero" onto "evenodd"
PASS clip-rule: "evenodd" onto "nonzero"
PASS color (type: color) has testAccumulation function
FAIL color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS color supports animating as color of rgb() with overflowed from and to values
PASS color supports animating as color of #RGB
PASS color supports animating as color of hsl()
PASS color supports animating as color of #RGBa
@@ -154,7 +154,7 @@ PASS column-gap (type: discrete) has testAccumulation function
PASS column-gap: "200px" onto "normal"
PASS column-gap: "normal" onto "200px"
PASS column-rule-color (type: color) has testAccumulation function
FAIL column-rule-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS column-rule-color supports animating as color of rgb() with overflowed from and to values
PASS column-rule-color supports animating as color of #RGB
PASS column-rule-color supports animating as color of hsl()
PASS column-rule-color supports animating as color of #RGBa
@@ -225,7 +225,7 @@ PASS flex-wrap (type: discrete) has testAccumulation function
PASS flex-wrap: "wrap" onto "nowrap"
PASS flex-wrap: "nowrap" onto "wrap"
PASS flood-color (type: color) has testAccumulation function
FAIL flood-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS flood-color supports animating as color of rgb() with overflowed from and to values
PASS flood-color supports animating as color of #RGB
PASS flood-color supports animating as color of hsl()
PASS flood-color supports animating as color of #RGBa
@@ -16,7 +16,7 @@ PASS letter-spacing (type: length) has testAccumulation function
PASS letter-spacing: length
PASS letter-spacing: length of rem
PASS lighting-color (type: color) has testAccumulation function
FAIL lighting-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS lighting-color supports animating as color of rgb() with overflowed from and to values
PASS lighting-color supports animating as color of #RGB
PASS lighting-color supports animating as color of hsl()
PASS lighting-color supports animating as color of #RGBa
@@ -85,7 +85,7 @@ PASS offset-distance: calc
PASS order (type: integer) has testAccumulation function
PASS order: integer
PASS outline-color (type: color) has testAccumulation function
FAIL outline-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS outline-color supports animating as color of rgb() with overflowed from and to values
PASS outline-color supports animating as color of #RGB
PASS outline-color supports animating as color of hsl()
PASS outline-color supports animating as color of #RGBa
@@ -150,7 +150,7 @@ PASS shape-rendering (type: discrete) has testAccumulation function
PASS shape-rendering: "crispEdges" onto "optimizeSpeed"
PASS shape-rendering: "optimizeSpeed" onto "crispEdges"
PASS stop-color (type: color) has testAccumulation function
FAIL stop-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS stop-color supports animating as color of rgb() with overflowed from and to values
PASS stop-color supports animating as color of #RGB
PASS stop-color supports animating as color of hsl()
PASS stop-color supports animating as color of #RGBa
@@ -188,7 +188,7 @@ PASS text-anchor (type: discrete) has testAccumulation function
PASS text-anchor: "end" onto "middle"
PASS text-anchor: "middle" onto "end"
PASS text-decoration-color (type: color) has testAccumulation function
FAIL text-decoration-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS text-decoration-color supports animating as color of rgb() with overflowed from and to values
PASS text-decoration-color supports animating as color of #RGB
PASS text-decoration-color supports animating as color of hsl()
PASS text-decoration-color supports animating as color of #RGBa
@@ -201,7 +201,7 @@ PASS text-decoration-style (type: discrete) has testAccumulation function
PASS text-decoration-style: "dotted" onto "solid"
PASS text-decoration-style: "solid" onto "dotted"
PASS text-emphasis-color (type: color) has testAccumulation function
FAIL text-emphasis-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS text-emphasis-color supports animating as color of rgb() with overflowed from and to values
PASS text-emphasis-color supports animating as color of #RGB
PASS text-emphasis-color supports animating as color of hsl()
PASS text-emphasis-color supports animating as color of #RGBa
@@ -16,7 +16,7 @@ PASS background-attachment (type: discrete) has testAddition function
PASS background-attachment: "local" onto "fixed"
PASS background-attachment: "fixed" onto "local"
PASS background-color (type: color) has testAddition function
FAIL background-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS background-color supports animating as color of rgb() with overflowed from and to values
PASS background-color supports animating as color of #RGB
PASS background-color supports animating as color of hsl()
PASS background-color supports animating as color of #RGBa
@@ -38,7 +38,7 @@ PASS background-repeat (type: discrete) has testAddition function
PASS background-repeat: "round" onto "space"
PASS background-repeat: "space" onto "round"
PASS border-bottom-color (type: color) has testAddition function
FAIL border-bottom-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-bottom-color supports animating as color of rgb() with overflowed from and to values
PASS border-bottom-color supports animating as color of #RGB
PASS border-bottom-color supports animating as color of hsl()
PASS border-bottom-color supports animating as color of #RGBa
@@ -60,7 +60,7 @@ PASS border-image-source (type: discrete) has testAddition function
PASS border-image-source: "url("http://localhost/test-2")" onto "url("http://localhost/test-1")"
PASS border-image-source: "url("http://localhost/test-1")" onto "url("http://localhost/test-2")"
PASS border-left-color (type: color) has testAddition function
FAIL border-left-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-left-color supports animating as color of rgb() with overflowed from and to values
PASS border-left-color supports animating as color of #RGB
PASS border-left-color supports animating as color of hsl()
PASS border-left-color supports animating as color of #RGBa
@@ -73,7 +73,7 @@ PASS border-left-width (type: length) has testAddition function
PASS border-left-width: length
PASS border-left-width: length of rem
PASS border-right-color (type: color) has testAddition function
FAIL border-right-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-right-color supports animating as color of rgb() with overflowed from and to values
PASS border-right-color supports animating as color of #RGB
PASS border-right-color supports animating as color of hsl()
PASS border-right-color supports animating as color of #RGBa
@@ -89,7 +89,7 @@ PASS border-spacing (type: lengthPair) has testAddition function
PASS border-spacing: length pair
PASS border-spacing: length pair of rem
PASS border-top-color (type: color) has testAddition function
FAIL border-top-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS border-top-color supports animating as color of rgb() with overflowed from and to values
PASS border-top-color supports animating as color of #RGB
PASS border-top-color supports animating as color of hsl()
PASS border-top-color supports animating as color of #RGBa
@@ -110,7 +110,7 @@ PASS caption-side (type: discrete) has testAddition function
PASS caption-side: "bottom" onto "top"
PASS caption-side: "top" onto "bottom"
PASS caret-color (type: color) has testAddition function
FAIL caret-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS caret-color supports animating as color of rgb() with overflowed from and to values
PASS caret-color supports animating as color of #RGB
PASS caret-color supports animating as color of hsl()
PASS caret-color supports animating as color of #RGBa
@@ -130,7 +130,7 @@ PASS clip-rule (type: discrete) has testAddition function
PASS clip-rule: "nonzero" onto "evenodd"
PASS clip-rule: "evenodd" onto "nonzero"
PASS color (type: color) has testAddition function
FAIL color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS color supports animating as color of rgb() with overflowed from and to values
PASS color supports animating as color of #RGB
PASS color supports animating as color of hsl()
PASS color supports animating as color of #RGBa
@@ -154,7 +154,7 @@ PASS column-gap (type: discrete) has testAddition function
PASS column-gap: "200px" onto "normal"
PASS column-gap: "normal" onto "200px"
PASS column-rule-color (type: color) has testAddition function
FAIL column-rule-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS column-rule-color supports animating as color of rgb() with overflowed from and to values
PASS column-rule-color supports animating as color of #RGB
PASS column-rule-color supports animating as color of hsl()
PASS column-rule-color supports animating as color of #RGBa
@@ -225,7 +225,7 @@ PASS flex-wrap (type: discrete) has testAddition function
PASS flex-wrap: "wrap" onto "nowrap"
PASS flex-wrap: "nowrap" onto "wrap"
PASS flood-color (type: color) has testAddition function
FAIL flood-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS flood-color supports animating as color of rgb() with overflowed from and to values
PASS flood-color supports animating as color of #RGB
PASS flood-color supports animating as color of hsl()
PASS flood-color supports animating as color of #RGBa
@@ -16,7 +16,7 @@ PASS letter-spacing (type: length) has testAddition function
PASS letter-spacing: length
PASS letter-spacing: length of rem
PASS lighting-color (type: color) has testAddition function
FAIL lighting-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS lighting-color supports animating as color of rgb() with overflowed from and to values
PASS lighting-color supports animating as color of #RGB
PASS lighting-color supports animating as color of hsl()
PASS lighting-color supports animating as color of #RGBa
@@ -85,7 +85,7 @@ PASS offset-distance: calc
PASS order (type: integer) has testAddition function
PASS order: integer
PASS outline-color (type: color) has testAddition function
FAIL outline-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS outline-color supports animating as color of rgb() with overflowed from and to values
PASS outline-color supports animating as color of #RGB
PASS outline-color supports animating as color of hsl()
PASS outline-color supports animating as color of #RGBa
@@ -150,7 +150,7 @@ PASS shape-rendering (type: discrete) has testAddition function
PASS shape-rendering: "crispEdges" onto "optimizeSpeed"
PASS shape-rendering: "optimizeSpeed" onto "crispEdges"
PASS stop-color (type: color) has testAddition function
FAIL stop-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS stop-color supports animating as color of rgb() with overflowed from and to values
PASS stop-color supports animating as color of #RGB
PASS stop-color supports animating as color of hsl()
PASS stop-color supports animating as color of #RGBa
@@ -188,7 +188,7 @@ PASS text-anchor (type: discrete) has testAddition function
PASS text-anchor: "end" onto "middle"
PASS text-anchor: "middle" onto "end"
PASS text-decoration-color (type: color) has testAddition function
FAIL text-decoration-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS text-decoration-color supports animating as color of rgb() with overflowed from and to values
PASS text-decoration-color supports animating as color of #RGB
PASS text-decoration-color supports animating as color of hsl()
PASS text-decoration-color supports animating as color of #RGBa
@@ -201,7 +201,7 @@ PASS text-decoration-style (type: discrete) has testAddition function
PASS text-decoration-style: "dotted" onto "solid"
PASS text-decoration-style: "solid" onto "dotted"
PASS text-emphasis-color (type: color) has testAddition function
FAIL text-emphasis-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 255) at 500ms expected "rgb(255, 128, 255)" but got "rgb(192, 128, 192)"
PASS text-emphasis-color supports animating as color of rgb() with overflowed from and to values
PASS text-emphasis-color supports animating as color of #RGB
PASS text-emphasis-color supports animating as color of hsl()
PASS text-emphasis-color supports animating as color of #RGBa

0 comments on commit 35a0ba0

Please sign in to comment.