Diff
Modified: trunk/LayoutTests/ChangeLog (278260 => 278261)
--- trunk/LayoutTests/ChangeLog 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/LayoutTests/ChangeLog 2021-05-31 00:29:18 UTC (rev 278261)
@@ -1,3 +1,16 @@
+2021-05-30 Sam Weinig <wei...@apple.com>
+
+ Support calc() on components inside relative color syntax colors
+ https://bugs.webkit.org/show_bug.cgi?id=226272
+
+ Reviewed by Darin Adler.
+
+ Updated test and results for update support including calc()
+ and compoment permutation.
+
+ * fast/css/parsing-relative-color-syntax-expected.txt:
+ * fast/css/parsing-relative-color-syntax.html:
+
2021-05-29 Cameron McCormack <hey...@apple.com>
Rename Internals.mainThreadScrollingReasons to synchronousScrollingReasons
Modified: trunk/LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt (278260 => 278261)
--- trunk/LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt 2021-05-31 00:29:18 UTC (rev 278261)
@@ -42,20 +42,27 @@
PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) 25 g b / 25%)") is "rgba(25, 51, 77, 0.25)"
PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 25 b / 25%)") is "rgba(26, 25, 77, 0.25)"
PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r g 25 / 25%)") is "rgba(26, 51, 25, 0.25)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple g b r)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple b alpha r / g)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple r r r / r)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) g b r)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple r 10% 10)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple r 10 10%)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rebeccapurple 0% 10 10)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple g b r)") is "rgb(51, 153, 102)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple b alpha r / g)") is "rgba(153, 255, 102, 0.2)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r r r / r)") is "rgba(102, 102, 102, 0.4)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple alpha alpha alpha / alpha)") is "rgb(255, 255, 255)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) g b r)") is "rgb(51, 77, 26)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)") is "rgba(77, 102, 26, 0.2)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)") is "rgba(26, 26, 26, 0.1)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(102, 102, 102, 0.4)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r 10% 10)") is "rgb(102, 26, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r 10 10%)") is "rgb(102, 10, 26)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple 0% 10 10)") is "rgb(0, 10, 10)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)") is "rgb(26, 26, 10)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)") is "rgb(26, 10, 26)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)") is "rgb(0, 10, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple calc(r) calc(g) calc(b))") is "rgb(102, 51, 153)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(g * .5) 10)") is "rgb(102, 26, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5) 10)") is "rgb(102, 77, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 + g * .5) 10)") is "rgb(102, 102, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)") is "rgb(102, 51, 10)"
+PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)") is "rgb(102, 51, 10)"
+PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) calc(r) calc(g) calc(b) / calc(alpha))") is "rgba(26, 51, 77, 0.4)"
PASS computedStyle("background-color", "rgb(from rebeccapurple red g b)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "rgb(from rebeccapurple l g b)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "rgb(from rebeccapurple h g b)") is "rgba(0, 0, 0, 0)"
@@ -91,14 +98,24 @@
PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h 25% l / alpha)") is "rgba(39, 51, 64, 0.4)"
PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h s 25% / alpha)") is "rgba(32, 63, 95, 0.4)"
PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h s l / .25)") is "rgba(26, 51, 77, 0.25)"
-PASS computedStyle("background-color", "hsl(from rebeccapurple h l s)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha l / s)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rebeccapurple h l l / l)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l s)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple h l s)") is "rgb(128, 77, 179)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha l / s)") is "rgba(102, 0, 204, 0.5)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple h l l / l)") is "rgba(102, 61, 143, 0.4)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha alpha / alpha)") is "rgb(255, 255, 255)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l s)") is "rgb(101, 126, 152)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)") is "rgba(31, 51, 72, 0.494)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)") is "rgba(41, 51, 62, 0.204)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(61, 101, 143, 0.4)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple s h l)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple s s s / s)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple h h h / h)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) s h l)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hsl(from rebeccapurple calc(h) calc(s) calc(l))") is "rgb(102, 51, 153)"
+PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) calc(h) calc(s) calc(l) / calc(alpha))") is "rgba(26, 51, 77, 0.4)"
PASS computedStyle("background-color", "hsl(from rebeccapurple h 10% 10)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "hsl(from rebeccapurple h 10 10%)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "hsl(from rebeccapurple 10% s l)") is "rgba(0, 0, 0, 0)"
@@ -140,14 +157,24 @@
PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h 25% b / alpha)") is "rgba(64, 70, 77, 0.4)"
PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w 25% / alpha)") is "rgba(26, 107, 191, 0.4)"
PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w b / .25)") is "rgba(26, 51, 77, 0.25)"
-PASS computedStyle("background-color", "hwb(from rebeccapurple h b w)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha w / b)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rebeccapurple h w w / w)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h b w)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple h b w)") is "rgb(153, 102, 204)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha w / b)") is "rgba(213, 213, 213, 0.4)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple h w w / w)") is "rgba(128, 51, 204, 0.2)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha alpha / alpha)") is "rgb(128, 128, 128)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h b w)") is "rgb(178, 203, 229)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)") is "rgba(102, 164, 229, 0.698)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)") is "rgba(26, 126, 229, 0.1)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(102, 127, 153, 0.4)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple w h b)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple b b b / b)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple h h h / h)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) w b h)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "hwb(from rebeccapurple calc(h) calc(w) calc(b))") is "rgb(102, 51, 153)"
+PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) calc(h) calc(w) calc(b) / calc(alpha))") is "rgba(26, 51, 77, 0.4)"
PASS computedStyle("background-color", "hwb(from rebeccapurple h 10% 10)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "hwb(from rebeccapurple h 10 10%)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "hwb(from rebeccapurple 10% w b)") is "rgba(0, 0, 0, 0)"
@@ -182,14 +209,16 @@
PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l 35 b / alpha)") is "lab(25% 35 50 / 0.4)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a 35 / alpha)") is "lab(25% 20 35 / 0.4)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a b / .35)") is "lab(25% 20 50 / 0.35)"
-PASS computedStyle("background-color", "lab(from lab(25% 20 50) l b a)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50) l b a)") is "lab(25% 50 20)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50) l a a / a)") is "lab(25% 20 20)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l b a)") is "lab(25% 50 20)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a a / a)") is "lab(25% 20 20)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50) l alpha a / b)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lab(from lab(25% 20 50) l a a / a)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50) l alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l b a)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l alpha a / b)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a a / a)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50) calc(l) calc(a) calc(b))") is "lab(25% 20 50)"
+PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))") is "lab(25% 20 50 / 0.4)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50) l 10% 10)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50) l 10 10%)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lab(from lab(25% 20 50) 10 a b)") is "rgba(0, 0, 0, 0)"
@@ -231,10 +260,22 @@
PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c 25 / alpha)") is "lch(70% 45 25 / 0.4)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)") is "lch(70% 45 25 / 0.4)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c h / .25)") is "lch(70% 45 30 / 0.25)"
-PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / l)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / alpha)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / l)") is "rgba(0, 0, 0, 0)"
-PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / l)") is "lch(100% 45 30 / 0.7)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) l c c / alpha)") is "lch(70% 45 45)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / alpha)") is "lch(100% 45 30)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c c / alpha)") is "lch(100% 45 45)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / l)") is "lch(40% 45 30 / 0.7)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c c / alpha)") is "lch(70% 45 45 / 0.4)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)") is "lch(40% 45 30 / 0.4)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c c / alpha)") is "lch(40% 45 45 / 0.4)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) h l c / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) c c c / c)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) h l c / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) c c c / c)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30) calc(l) calc(c) calc(h))") is "lch(70% 45 30)"
+PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))") is "lch(70% 45 30 / 0.4)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30) l 10% h)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30) l c 10%)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30) 10 c h)") is "rgba(0, 0, 0, 0)"
@@ -244,6 +285,21 @@
PASS computedStyle("background-color", "lch(from lch(70% 45 30) lightness c h)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30) x c h)") is "rgba(0, 0, 0, 0)"
PASS computedStyle("background-color", "lch(from lch(70% 45 30) l g b)") is "rgba(0, 0, 0, 0)"
+PASS computedStyle("background-color", "rgb(from var(--bg-color) r g b / 80%)") is "rgba(0, 0, 255, 0.8)"
+PASS computedStyle("background-color", "lch(from var(--color) calc(l / 2) c h)") is "lch(23.138971% 67.989716 134.39125)"
+PASS computedStyle("background-color", "rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))") is "rgb(76, 76, 76)"
+PASS computedStyle("background-color", "lch(from var(--color) l 0 h)") is "lch(46.277943% 0 134.39125)"
+PASS computedStyle("background-color", "rgb(from indianred 255 g b)") is "rgb(255, 92, 92)"
+PASS computedStyle("background-color", "hsl(from var(--accent) calc(h + 180deg) s l)") is "rgb(178, 32, 40)"
+PASS computedStyle("background-color", "lab(from var(--mycolor) l a b / 100%)") is "lab(62.751923% 52.45802 -34.117283)"
+PASS computedStyle("background-color", "lab(from var(--mycolor) l a b / calc(alpha * 0.8))") is "lab(62.751923% 52.45802 -34.117283 / 0.8)"
+PASS computedStyle("background-color", "lab(from var(--mycolor) l a b / calc(alpha - 20%))") is "lab(62.751923% 52.45802 -34.117283 / 0.8)"
+PASS computedStyle("background-color", "lab(from var(--mycolor) l 0 0)") is "lab(62.751923% 0 0)"
+PASS computedStyle("background-color", "lch(from peru calc(l * 0.8) c h)") is "lch(49.80138% 54.003296 63.680317)"
+PASS computedStyle("background-color", "LCH(from var(--accent) l c calc(h + 180deg))") is "lch(65.49473% 39.446903 10.114471)"
+PASS computedStyle("background-color", "lch(from var(--mycolor) l 0 h)") is "lch(62.751923% 0 326.96112)"
+PASS computedStyle("background-color", "var(--mygray)") is "lch(62.751923% 0 326.96112)"
+PASS computedStyle("background-color", "lch(from var(--mygray) l 30 h)") is "lch(62.751923% 30 326.96112)"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/css/parsing-relative-color-syntax.html (278260 => 278261)
--- trunk/LayoutTests/fast/css/parsing-relative-color-syntax.html 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/LayoutTests/fast/css/parsing-relative-color-syntax.html 2021-05-31 00:29:18 UTC (rev 278261)
@@ -1,6 +1,15 @@
<!DOCTYPE html><!-- webkit-test-runner [ CSSRelativeColorSyntaxEnabled=true ] -->
<html>
<script src=""
+ <style>
+ html {
+ --bg-color: blue;
+ --color: green;
+ --accent: lightseagreen;
+ --mycolor: orchid;
+ --mygray: lch(from var(--mycolor) l 0 h);
+ }
+ </style>
</head>
<body>
<script>
@@ -95,24 +104,33 @@
testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 25 b / 25%)`, `rgba(26, 25, 77, 0.25)`);
testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r g 25 / 25%)`, `rgba(26, 51, 25, 0.25)`);
- // Testing permutation (unclear if this is allowed per-spec, we disallow it).
- testComputed(`rgb(from rebeccapurple g b r)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rebeccapurple b alpha r / g)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rebeccapurple r r r / r)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) g b r)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ // Testing permutation.
+ testComputed(`rgb(from rebeccapurple g b r)`, `rgb(51, 153, 102)`);
+ testComputed(`rgb(from rebeccapurple b alpha r / g)`, `rgba(153, 255, 102, 0.2)`);
+ testComputed(`rgb(from rebeccapurple r r r / r)`, `rgba(102, 102, 102, 0.4)`);
+ testComputed(`rgb(from rebeccapurple alpha alpha alpha / alpha)`, `rgb(255, 255, 255)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) g b r)`, `rgb(51, 77, 26)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)`, `rgba(77, 102, 26, 0.2)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)`, `rgba(26, 26, 26, 0.1)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(102, 102, 102, 0.4)`);
- // Testing invalid mixes of number and percentage
- testComputed(`rgb(from rebeccapurple r 10% 10)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rebeccapurple r 10 10%)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rebeccapurple 0% 10 10)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)`, `rgba(0, 0, 0, 0)`);
- testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)`, `rgba(0, 0, 0, 0)`);
+ // Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
+ testComputed(`rgb(from rebeccapurple r 10% 10)`, `rgb(102, 26, 10)`);
+ testComputed(`rgb(from rebeccapurple r 10 10%)`, `rgb(102, 10, 26)`);
+ testComputed(`rgb(from rebeccapurple 0% 10 10)`, `rgb(0, 10, 10)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)`, `rgb(26, 26, 10)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)`, `rgb(26, 10, 26)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)`, `rgb(0, 10, 10)`);
+ // Testing with calc().
+ testComputed(`rgb(from rebeccapurple calc(r) calc(g) calc(b))`, `rgb(102, 51, 153)`);
+ testComputed(`rgb(from rebeccapurple r calc(g * .5) 10)`, `rgb(102, 26, 10)`);
+ testComputed(`rgb(from rebeccapurple r calc(b * .5) 10)`, `rgb(102, 77, 10)`);
+ testComputed(`rgb(from rebeccapurple r calc(b * .5 + g * .5) 10)`, `rgb(102, 102, 10)`);
+ testComputed(`rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`);
+ testComputed(`rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`);
+ testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) calc(r) calc(g) calc(b) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`);
+
// Testing invalid component names
testComputed(`rgb(from rebeccapurple red g b)`, `rgba(0, 0, 0, 0)`);
testComputed(`rgb(from rebeccapurple l g b)`, `rgba(0, 0, 0, 0)`);
@@ -161,16 +179,30 @@
testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h s 25% / alpha)`, `rgba(32, 63, 95, 0.4)`);
testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h s l / .25)`, `rgba(26, 51, 77, 0.25)`);
- // Testing permutation (unclear if this is allowed per-spec, we disallow it).
- testComputed(`hsl(from rebeccapurple h l s)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rebeccapurple h alpha l / s)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rebeccapurple h l l / l)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rebeccapurple h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l s)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ // Testing valid permutation (types match).
+ testComputed(`hsl(from rebeccapurple h l s)`, `rgb(128, 77, 179)`);
+ testComputed(`hsl(from rebeccapurple h alpha l / s)`, `rgba(102, 0, 204, 0.5)`);
+ testComputed(`hsl(from rebeccapurple h l l / l)`, `rgba(102, 61, 143, 0.4)`);
+ testComputed(`hsl(from rebeccapurple h alpha alpha / alpha)`, `rgb(255, 255, 255)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l s)`, `rgb(101, 126, 152)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)`, `rgba(31, 51, 72, 0.494)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)`, `rgba(41, 51, 62, 0.204)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(61, 101, 143, 0.4)`);
+ // Testing invalid permutation (types don't match).
+ testComputed(`hsl(from rebeccapurple s h l)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rebeccapurple s s s / s)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rebeccapurple h h h / h)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) s h l)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+
+ // Testing with calc().
+ testComputed(`hsl(from rebeccapurple calc(h) calc(s) calc(l))`, `rgb(102, 51, 153)`);
+ testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) calc(h) calc(s) calc(l) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`);
+
// Testing invalid values.
testComputed(`hsl(from rebeccapurple h 10% 10)`, `rgba(0, 0, 0, 0)`);
testComputed(`hsl(from rebeccapurple h 10 10%)`, `rgba(0, 0, 0, 0)`);
@@ -228,16 +260,30 @@
testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w 25% / alpha)`, `rgba(26, 107, 191, 0.4)`);
testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w b / .25)`, `rgba(26, 51, 77, 0.25)`);
- // Testing permutation (unclear if this is allowed per-spec, we disallow it).
- testComputed(`hwb(from rebeccapurple h b w)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rebeccapurple h alpha w / b)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rebeccapurple h w w / w)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rebeccapurple h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h b w)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)`, `rgba(0, 0, 0, 0)`);
- testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ // Testing valid permutation (types match).
+ testComputed(`hwb(from rebeccapurple h b w)`, `rgb(153, 102, 204)`);
+ testComputed(`hwb(from rebeccapurple h alpha w / b)`, `rgba(213, 213, 213, 0.4)`);
+ testComputed(`hwb(from rebeccapurple h w w / w)`, `rgba(128, 51, 204, 0.2)`);
+ testComputed(`hwb(from rebeccapurple h alpha alpha / alpha)`, `rgb(128, 128, 128)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h b w)`, `rgb(178, 203, 229)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)`, `rgba(102, 164, 229, 0.698)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)`, `rgba(26, 126, 229, 0.1)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(102, 127, 153, 0.4)`);
+ // Testing invalid permutation (types don't match).
+ testComputed(`hwb(from rebeccapurple w h b)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rebeccapurple b b b / b)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rebeccapurple h h h / h)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) w b h)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+
+ // Testing with calc().
+ testComputed(`hwb(from rebeccapurple calc(h) calc(w) calc(b))`, `rgb(102, 51, 153)`);
+ testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) calc(h) calc(w) calc(b) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`);
+
// Testing invalid values.
testComputed(`hwb(from rebeccapurple h 10% 10)`, `rgba(0, 0, 0, 0)`);
testComputed(`hwb(from rebeccapurple h 10 10%)`, `rgba(0, 0, 0, 0)`);
@@ -288,16 +334,22 @@
testComputed(`lab(from lab(25% 20 50 / 40%) l a 35 / alpha)`, `lab(25% 20 35 / 0.4)`);
testComputed(`lab(from lab(25% 20 50 / 40%) l a b / .35)`, `lab(25% 20 50 / 0.35)`);
- // Testing permutation (unclear if this is allowed per-spec, we disallow it).
- testComputed(`lab(from lab(25% 20 50) l b a)`, `rgba(0, 0, 0, 0)`);
+ // Testing valid permutation (types match).
+ testComputed(`lab(from lab(25% 20 50) l b a)`, `lab(25% 50 20)`);
+ testComputed(`lab(from lab(25% 20 50) l a a / a)`, `lab(25% 20 20)`);
+ testComputed(`lab(from lab(25% 20 50 / 40%) l b a)`, `lab(25% 50 20)`);
+ testComputed(`lab(from lab(25% 20 50 / 40%) l a a / a)`, `lab(25% 20 20)`);
+
+ // Testing invalid permutation (types don't match).
testComputed(`lab(from lab(25% 20 50) l alpha a / b)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lab(from lab(25% 20 50) l a a / a)`, `rgba(0, 0, 0, 0)`);
testComputed(`lab(from lab(25% 20 50) l alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lab(from lab(25% 20 50 / 40%) l b a)`, `rgba(0, 0, 0, 0)`);
testComputed(`lab(from lab(25% 20 50 / 40%) l alpha a / b)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lab(from lab(25% 20 50 / 40%) l a a / a)`, `rgba(0, 0, 0, 0)`);
testComputed(`lab(from lab(25% 20 50 / 40%) l alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ // Testing with calc().
+ testComputed(`lab(from lab(25% 20 50) calc(l) calc(a) calc(b))`, `lab(25% 20 50)`);
+ testComputed(`lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))`, `lab(25% 20 50 / 0.4)`);
+
// Testing invalid values.
testComputed(`lab(from lab(25% 20 50) l 10% 10)`, `rgba(0, 0, 0, 0)`);
testComputed(`lab(from lab(25% 20 50) l 10 10%)`, `rgba(0, 0, 0, 0)`);
@@ -355,12 +407,29 @@
testComputed(`lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)`, `lch(70% 45 25 / 0.4)`);
testComputed(`lch(from lch(70% 45 30 / 40%) l c h / .25)`, `lch(70% 45 30 / 0.25)`);
- // Testing permutation (unclear if this is allowed per-spec, we disallow it).
- testComputed(`lch(from lch(70% 45 30) alpha c h / l)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lch(from lch(70% 45 30) alpha c h / alpha)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / l)`, `rgba(0, 0, 0, 0)`);
- testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / alpha)`, `rgba(0, 0, 0, 0)`);
+ // Testing valid permutation (types match).
+ // NOTE: 'c' is a vaild hue, as hue is <angle>|<number>.
+ testComputed(`lch(from lch(70% 45 30) alpha c h / l)`, `lch(100% 45 30 / 0.7)`);
+ testComputed(`lch(from lch(70% 45 30) l c c / alpha)`, `lch(70% 45 45)`);
+ testComputed(`lch(from lch(70% 45 30) alpha c h / alpha)`, `lch(100% 45 30)`);
+ testComputed(`lch(from lch(70% 45 30) alpha c c / alpha)`, `lch(100% 45 45)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / l)`, `lch(40% 45 30 / 0.7)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) l c c / alpha)`, `lch(70% 45 45 / 0.4)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / alpha)`, `lch(40% 45 30 / 0.4)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) alpha c c / alpha)`, `lch(40% 45 45 / 0.4)`);
+ // Testing invalid permutation (types don't match).
+ testComputed(`lch(from lch(70% 45 30) h l c / alpha)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`lch(from lch(70% 45 30) c c c / c)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`lch(from lch(70% 45 30) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) h l c / alpha)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) c c c / c)`, `rgba(0, 0, 0, 0)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`);
+
+ // Testing with calc().
+ testComputed(`lch(from lch(70% 45 30) calc(l) calc(c) calc(h))`, `lch(70% 45 30)`);
+ testComputed(`lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))`, `lch(70% 45 30 / 0.4)`);
+
// Testing invalid values.
testComputed(`lch(from lch(70% 45 30) l 10% h)`, `rgba(0, 0, 0, 0)`);
testComputed(`lch(from lch(70% 45 30) l c 10%)`, `rgba(0, 0, 0, 0)`);
@@ -373,6 +442,44 @@
testComputed(`lch(from lch(70% 45 30) lightness c h)`, `rgba(0, 0, 0, 0)`);
testComputed(`lch(from lch(70% 45 30) x c h)`, `rgba(0, 0, 0, 0)`);
testComputed(`lch(from lch(70% 45 30) l g b)`, `rgba(0, 0, 0, 0)`);
+
+
+ // Spec examples:
+ // Example 11.
+ testComputed(`rgb(from var(--bg-color) r g b / 80%)`, `rgba(0, 0, 255, 0.8)`);
+
+ // Example 12.
+ testComputed(`lch(from var(--color) calc(l / 2) c h)`, `lch(23.138971% 67.989716 134.39125)`);
+
+ // Example 13.
+ testComputed(`rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))`, `rgb(76, 76, 76)`)
+ testComputed(`lch(from var(--color) l 0 h)`, `lch(46.277943% 0 134.39125)`)
+
+ // Example 14.
+ testComputed(`rgb(from indianred 255 g b)`, `rgb(255, 92, 92)`);
+
+ // Example 15.
+ testComputed(`hsl(from var(--accent) calc(h + 180deg) s l)`, `rgb(178, 32, 40)`);
+
+ // Example 16.
+ testComputed(`lab(from var(--mycolor) l a b / 100%)`, `lab(62.751923% 52.45802 -34.117283)`);
+ testComputed(`lab(from var(--mycolor) l a b / calc(alpha * 0.8))`, `lab(62.751923% 52.45802 -34.117283 / 0.8)`);
+ testComputed(`lab(from var(--mycolor) l a b / calc(alpha - 20%))`, `lab(62.751923% 52.45802 -34.117283 / 0.8)`);
+
+ // Example 17.
+ testComputed(`lab(from var(--mycolor) l 0 0)`, `lab(62.751923% 0 0)`);
+
+ // Example 18.
+ testComputed(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80138% 54.003296 63.680317)`);
+
+ // Example 19.
+ testComputed(`LCH(from var(--accent) l c calc(h + 180deg))`, `lch(65.49473% 39.446903 10.114471)`);
+
+ // Example 20.
+ testComputed(`lch(from var(--mycolor) l 0 h)`, `lch(62.751923% 0 326.96112)`);
+ testComputed(`var(--mygray)`, `lch(62.751923% 0 326.96112)`);
+ testComputed(`lch(from var(--mygray) l 30 h)`, `lch(62.751923% 30 326.96112)`);
+
</script>
<script src=""
Modified: trunk/Source/WebCore/ChangeLog (278260 => 278261)
--- trunk/Source/WebCore/ChangeLog 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/ChangeLog 2021-05-31 00:29:18 UTC (rev 278261)
@@ -1,3 +1,85 @@
+2021-05-30 Sam Weinig <wei...@apple.com>
+
+ Support calc() on components inside relative color syntax colors
+ https://bugs.webkit.org/show_bug.cgi?id=226272
+
+ Reviewed by Darin Adler.
+
+ Added new and updated test cases to fast/css/parsing-relative-color-syntax.html.
+
+ Updates support for the CSS Color 5 "Relative Color Syntax" to support
+ both calc() on components and component permutations within the syntax.
+
+ This allows for things like:
+
+ background: lch(from var(--primary-color) 60% calc(c * 0.8) h);
+
+ or
+
+ background: lch(from rebeccapurple g b r);
+
+ To make this work, the calc() infrastructure now supports passing a CSSCalcSymbolTable
+ which allows the logic in the parser to lookup unknown identifiers when parsing a value.
+ The relative color syntax parsers can then build an appropriate CSSCalcSymbolTable filled
+ with the components of the origin color.
+
+ Since these calc() values are not serialized, this can all happen in the parser, but if
+ we to be able serialize them in the future, CSSCalcPrimitiveValueNode could be updated
+ to store the symbol name in addition to storing the value and type (or we could we could
+ add a new node for it).
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * css/calc/CSSCalcSymbolTable.cpp: Added.
+ * css/calc/CSSCalcSymbolTable.h: Added.
+ Add CSSCalcSymbolTable which contains a mapping from CSSValueID to CSSUnitType/double pairs.
+
+ * css/calc/CSSCalcExpressionNodeParser.cpp:
+ (WebCore::CSSCalcExpressionNodeParser::parseValue):
+ When trying to construct a value node, if the token is a identifier, use the new
+ symbol table to look up a type/value to use instead. Use a switch to make things
+ a bit more clear that differentiation is being done based on token type.
+
+ * css/calc/CSSCalcExpressionNodeParser.h:
+ Add reference to a CSSCalcSymbolTable to the parser. The parser should only ever be used
+ on the stack, so this works well and allows us to avoid copying the table.
+
+ * css/calc/CSSCalcValue.cpp:
+ (WebCore::CSSCalcValue::create):
+ * css/calc/CSSCalcValue.h:
+ Pass the CSSCalcSymbolTable to the parser if one is provided. An overload was used
+ to avoid #including CSSCalcSymbolTable.h in the header just to add a default value.
+
+ * css/makevalues.pl:
+ Give a concrete base of uint16_t to allow it to be forward declared and add DefaultHash
+ and HashTraits to allow it to be used with HashTable. These match the definition of
+ CSSPropertyID.
+
+ * css/parser/CSSPropertyParserHelpers.cpp:
+ (WebCore::CSSPropertyParserHelpers::CalcParser::CalcParser):
+ (WebCore::CSSPropertyParserHelpers::consumeNumberRaw):
+ (WebCore::CSSPropertyParserHelpers::consumePercentWorkerSafe):
+ (WebCore::CSSPropertyParserHelpers::consumeAngleRaw):
+ (WebCore::CSSPropertyParserHelpers::consumeAngleWorkerSafe):
+ (WebCore::CSSPropertyParserHelpers::consumeAngleOrPercent):
+ (WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaOrIdent):
+ (WebCore::CSSPropertyParserHelpers::consumeHueOrIdent):
+ (WebCore::CSSPropertyParserHelpers::consumeNumberOrIdent):
+ (WebCore::CSSPropertyParserHelpers::consumePercentOrIdent):
+ (WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentOrIdentNormalizedForRelativeRGB):
+ (WebCore::CSSPropertyParserHelpers::parseRelativeRGBParameters):
+ (WebCore::CSSPropertyParserHelpers::parseRelativeHSLParameters):
+ (WebCore::CSSPropertyParserHelpers::parseRelativeHWBParameters):
+ (WebCore::CSSPropertyParserHelpers::parseRelativeLabParameters):
+ (WebCore::CSSPropertyParserHelpers::parseRelativeLCHParameters):
+ (WebCore::CSSPropertyParserHelpers::extractChannelValue): Deleted.
+ (WebCore::CSSPropertyParserHelpers::resolveRelativeColorChannel): Deleted.
+ Rework relative color syntax parsing to allow permutation of channel symbols
+ and use of the calc() symbol table support to allow passing in the channels.
+ This makes the relatative color syntax variants much closer to the normal
+ variants (with the exception of passing the symbol table) and a subsequent
+ change will attempt to merge them further.
+
2021-05-30 Dean Jackson <d...@apple.com>
[WebXR] Provide a way to bind and unbind IOSurfaces to ANGLE Pbuffers
Modified: trunk/Source/WebCore/Sources.txt (278260 => 278261)
--- trunk/Source/WebCore/Sources.txt 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/Sources.txt 2021-05-31 00:29:18 UTC (rev 278261)
@@ -831,6 +831,7 @@
css/calc/CSSCalcNegateNode.cpp
css/calc/CSSCalcOperationNode.cpp
css/calc/CSSCalcPrimitiveValueNode.cpp
+css/calc/CSSCalcSymbolTable.cpp
css/calc/CSSCalcValue.cpp
css/parser/CSSAtRuleID.cpp
css/parser/CSSDeferredParser.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (278260 => 278261)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-31 00:29:18 UTC (rev 278261)
@@ -4077,6 +4077,7 @@
BC6932740D7E293900AE44D1 /* JSDOMWindowBase.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6932720D7E293900AE44D1 /* JSDOMWindowBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC6D44ED0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D44EB0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h */; };
BC6D6E2609AF943500F59759 /* ScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D6E2509AF943500F59759 /* ScrollView.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */; };
BC772B3C0C4EA91E0083285F /* CSSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772B360C4EA91E0083285F /* CSSHelper.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC772C470C4EB2C60083285F /* XMLHttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772C450C4EB2C60083285F /* XMLHttpRequest.h */; };
BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772C4D0C4EB3040083285F /* MIMETypeRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -14304,6 +14305,8 @@
BC6D44EB0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLEmbedElement.h; sourceTree = "<group>"; };
BC6D6E2509AF943500F59759 /* ScrollView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScrollView.h; sourceTree = "<group>"; };
BC6EB84526266B61003225A7 /* ColorLuminance.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorLuminance.cpp; sourceTree = "<group>"; };
+ BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSCalcSymbolTable.h; sourceTree = "<group>"; };
+ BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCalcSymbolTable.cpp; sourceTree = "<group>"; };
BC772B360C4EA91E0083285F /* CSSHelper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSHelper.h; sourceTree = "<group>"; };
BC772C440C4EB2C60083285F /* XMLHttpRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = XMLHttpRequest.cpp; sourceTree = "<group>"; };
BC772C450C4EB2C60083285F /* XMLHttpRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = XMLHttpRequest.h; sourceTree = "<group>"; };
@@ -27956,6 +27959,8 @@
BCF1645F2662A28D0002F7EF /* CSSCalcOperationNode.h */,
BCF164542662A1220002F7EF /* CSSCalcPrimitiveValueNode.cpp */,
BCF164532662A1220002F7EF /* CSSCalcPrimitiveValueNode.h */,
+ BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */,
+ BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */,
49AE2D8C134EE50C0072920A /* CSSCalcValue.cpp */,
49AE2D8D134EE50C0072920A /* CSSCalcValue.h */,
);
@@ -34669,6 +34674,7 @@
26601EBF14B3B9AD0012C0FE /* PlatformEventFactoryIOS.h in Headers */,
BCAA487014A052530088FAC4 /* PlatformEventFactoryMac.h in Headers */,
A723F77B1484CA4C008C6DBE /* PlatformExportMacros.h in Headers */,
+ BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */,
515BE1951D54F5FB00DD7C68 /* PlatformGamepad.h in Headers */,
726D56E2253AE28D0002EF90 /* PlatformImage.h in Headers */,
2D7705C7255276CD001D0C94 /* PlatformImageBuffer.h in Headers */,
Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (278260 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp 2021-05-31 00:29:18 UTC (rev 278261)
@@ -31,9 +31,11 @@
#include "CSSCalcNegateNode.h"
#include "CSSCalcOperationNode.h"
#include "CSSCalcPrimitiveValueNode.h"
+#include "CSSCalcSymbolTable.h"
#include "CSSCalcValue.h"
#include "CSSParserToken.h"
#include "CSSParserTokenRange.h"
+#include "CSSValueKeywords.h"
#include "Logging.h"
namespace WebCore {
@@ -180,19 +182,35 @@
bool CSSCalcExpressionNodeParser::parseValue(CSSParserTokenRange& tokens, RefPtr<CSSCalcExpressionNode>& result)
{
- // FIXME: Add code here to parse CSSValidID for named constants.
+ auto makeCSSCalcPrimitiveValueNode = [&] (CSSUnitType type, double value) -> bool {
+ if (calcUnitCategory(type) == CalculationCategory::Other)
+ return false;
+
+ result = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(value, type));
+ return true;
+ };
- CSSParserToken token = tokens.consumeIncludingWhitespace();
- if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken))
+ auto token = tokens.consumeIncludingWhitespace();
+
+ switch (token.type()) {
+ case IdentToken: {
+ auto value = m_symbolTable.get(token.id());
+ if (!value)
+ return false;
+ return makeCSSCalcPrimitiveValueNode(value->type, value->value);
+ }
+
+ case NumberToken:
+ case PercentageToken:
+ case DimensionToken:
+ return makeCSSCalcPrimitiveValueNode(token.unitType(), token.numericValue());
+
+ default:
return false;
-
- auto type = token.unitType();
- if (calcUnitCategory(type) == CalculationCategory::Other)
- return false;
-
- result = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(token.numericValue(), type));
-
- return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
}
bool CSSCalcExpressionNodeParser::parseCalcValue(CSSParserTokenRange& tokens, int depth, RefPtr<CSSCalcExpressionNode>& result)
Modified: trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h (278260 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h 2021-05-31 00:29:18 UTC (rev 278261)
@@ -25,7 +25,6 @@
#pragma once
-#include "CSSValueKeywords.h"
#include "CalcOperator.h"
#include "CalculationCategory.h"
@@ -32,13 +31,17 @@
namespace WebCore {
class CSSCalcExpressionNode;
+class CSSCalcSymbolTable;
class CSSParserToken;
class CSSParserTokenRange;
+enum CSSValueID : uint16_t;
+
class CSSCalcExpressionNodeParser {
public:
- explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory)
+ explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory, const CSSCalcSymbolTable& symbolTable)
: m_destinationCategory(destinationCategory)
+ , m_symbolTable(symbolTable)
{
}
@@ -55,6 +58,7 @@
bool parseCalcValue(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&);
CalculationCategory m_destinationCategory;
+ const CSSCalcSymbolTable& m_symbolTable;
};
}
Copied: trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.cpp (from rev 278260, trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h) (0 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.cpp (rev 0)
+++ trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.cpp 2021-05-31 00:29:18 UTC (rev 278261)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CSSCalcSymbolTable.h"
+
+#include "CSSUnits.h"
+
+namespace WebCore {
+
+CSSCalcSymbolTable::CSSCalcSymbolTable(std::initializer_list<std::tuple<CSSValueID, CSSUnitType, double>> initializer)
+{
+ for (auto& [identifier, type, value] : initializer)
+ m_table.add(identifier, std::make_pair(type, value));
+}
+
+std::optional<CSSCalcSymbolTable::Value> CSSCalcSymbolTable::get(CSSValueID valueID) const
+{
+ auto it = m_table.find(valueID);
+ if (it == m_table.end())
+ return std::nullopt;
+
+ return {{ it->value.first, it->value.second }};
+}
+
+}
Copied: trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.h (from rev 278260, trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h) (0 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.h (rev 0)
+++ trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.h 2021-05-31 00:29:18 UTC (rev 278261)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CSSValueKeywords.h"
+#include <wtf/HashMap.h>
+#include <wtf/Optional.h>
+
+namespace WebCore {
+
+enum class CSSUnitType : uint8_t;
+
+class CSSCalcSymbolTable {
+public:
+ struct Value {
+ CSSUnitType type;
+ double value;
+ };
+
+ CSSCalcSymbolTable() = default;
+ CSSCalcSymbolTable(std::initializer_list<std::tuple<CSSValueID, CSSUnitType, double>>);
+
+ std::optional<Value> get(CSSValueID) const;
+
+private:
+ HashMap<CSSValueID, std::pair<CSSUnitType, double>> m_table;
+};
+
+};
Modified: trunk/Source/WebCore/css/calc/CSSCalcValue.cpp (278260 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcValue.cpp 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/calc/CSSCalcValue.cpp 2021-05-31 00:29:18 UTC (rev 278261)
@@ -40,6 +40,7 @@
#include "CSSParser.h"
#include "CSSParserTokenRange.h"
#include "CSSPrimitiveValueMappings.h"
+#include "CSSValueKeywords.h"
#include "CalcExpressionBlendLength.h"
#include "CalcExpressionLength.h"
#include "Logging.h"
@@ -299,9 +300,9 @@
ts << ")\n";
}
-RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range)
+RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range, const CSSCalcSymbolTable& symbolTable)
{
- CSSCalcExpressionNodeParser parser(destinationCategory);
+ CSSCalcExpressionNodeParser parser(destinationCategory, symbolTable);
auto _expression_ = parser.parseCalc(tokens, function);
if (!_expression_)
return nullptr;
@@ -309,7 +310,12 @@
LOG_WITH_STREAM(Calc, stream << "CSSCalcValue::create " << *result);
return result;
}
-
+
+RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range)
+{
+ return create(function, tokens, destinationCategory, range, { });
+}
+
RefPtr<CSSCalcValue> CSSCalcValue::create(const CalculationValue& value, const RenderStyle& style)
{
auto _expression_ = createCSS(value._expression_(), style);
Modified: trunk/Source/WebCore/css/calc/CSSCalcValue.h (278260 => 278261)
--- trunk/Source/WebCore/css/calc/CSSCalcValue.h 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/calc/CSSCalcValue.h 2021-05-31 00:29:18 UTC (rev 278261)
@@ -31,7 +31,6 @@
#pragma once
#include "CSSValue.h"
-#include "CSSValueKeywords.h"
#include "CalculationValue.h"
#include <wtf/Forward.h>
#include <wtf/Ref.h>
@@ -39,6 +38,7 @@
namespace WebCore {
class CSSCalcExpressionNode;
+class CSSCalcSymbolTable;
class CSSParserTokenRange;
class CSSToLengthConversionData;
class RenderStyle;
@@ -47,8 +47,11 @@
enum class CalculationCategory : uint8_t;
enum class ValueRange : uint8_t;
+enum CSSValueID : uint16_t;
+
class CSSCalcValue final : public CSSValue {
public:
+ static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange, const CSSCalcSymbolTable&);
static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange);
static RefPtr<CSSCalcValue> create(const CalculationValue&, const RenderStyle&);
~CSSCalcValue();
Modified: trunk/Source/WebCore/css/makevalues.pl (278260 => 278261)
--- trunk/Source/WebCore/css/makevalues.pl 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/makevalues.pl 2021-05-31 00:29:18 UTC (rev 278261)
@@ -164,10 +164,12 @@
#include <string.h>
#include <wtf/Forward.h>
+#include <wtf/HashFunctions.h>
+#include <wtf/HashTraits.h>
namespace WebCore {
-enum CSSValueID {
+enum CSSValueID : uint16_t {
CSSValueInvalid = 0,
EOF
@@ -204,6 +206,12 @@
}
} // namespace WebCore
+
+namespace WTF {
+template<> struct DefaultHash<WebCore::CSSValueID> : IntHash<unsigned> { };
+template<> struct HashTraits<WebCore::CSSValueID> : StrongEnumHashTraits<WebCore::CSSValueID> { };
+} // namespace WTF
+
EOF
close HEADER;
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (278260 => 278261)
--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2021-05-30 22:46:54 UTC (rev 278260)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2021-05-31 00:29:18 UTC (rev 278261)
@@ -30,6 +30,7 @@
#include "config.h"
#include "CSSPropertyParserHelpers.h"
+#include "CSSCalcSymbolTable.h"
#include "CSSCalcValue.h"
#include "CSSCanvasValue.h"
#include "CSSCrossfadeValue.h"
@@ -98,7 +99,7 @@
// FIXME: consider pulling in the parsing logic from CSSCalcExpressionNodeParser.
class CalcParser {
public:
- explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, CSSValuePool& cssValuePool = CSSValuePool::singleton())
+ explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, const CSSCalcSymbolTable& symbolTable = { }, CSSValuePool& cssValuePool = CSSValuePool::singleton())
: m_sourceRange(range)
, m_range(range)
, m_valuePool(cssValuePool)
@@ -106,7 +107,7 @@
const CSSParserToken& token = range.peek();
auto functionId = token.functionId();
if (CSSCalcValue::isCalcFunction(functionId))
- m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange);
+ m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange, symbolTable);
}
const CSSCalcValue* value() const { return m_calcValue.get(); }
@@ -119,6 +120,14 @@
return m_valuePool.createValue(WTFMove(m_calcValue));
}
+ RefPtr<CSSPrimitiveValue> consumeValueIfCategory(CalculationCategory category)
+ {
+ if (!m_calcValue || m_calcValue->category() != category)
+ return nullptr;
+ m_sourceRange = m_range;
+ return m_valuePool.createValue(WTFMove(m_calcValue));
+ }
+
RefPtr<CSSPrimitiveValue> consumeInteger(double minimumValue)
{
if (!m_calcValue)
@@ -217,11 +226,8 @@
return std::nullopt;
CalcParser calcParser(range, CalculationCategory::Number);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (calculation->category() != CalculationCategory::Number)
- return std::nullopt;
+ if (auto calculation = calcParser.value(); calculation && calculation->category() == CalculationCategory::Number)
return calcParser.consumeIntegerTypeRaw<IntType>(minimumValue);
- }
return std::nullopt;
}
@@ -272,11 +278,7 @@
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
CalcParser calcParser(range, CalculationCategory::Number, valueRange);
- if (const auto* calcValue = calcParser.value()) {
- if (calcValue->category() == CalculationCategory::Number)
- return calcParser.consumeValue();
- }
- return nullptr;
+ return calcParser.consumeValueIfCategory(CalculationCategory::Number);
}
if (auto number = consumeNumberRaw(range, valueRange))
@@ -398,8 +400,7 @@
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
CalcParser calcParser(range, CalculationCategory::Length, valueRange);
- if (calcParser.value() && calcParser.value()->category() == CalculationCategory::Length)
- return calcParser.consumeValue();
+ return calcParser.consumeValueIfCategory(CalculationCategory::Length);
}
if (auto result = consumeLengthRaw(range, cssParserMode, valueRange, unitless))
@@ -433,12 +434,8 @@
{
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
- CalcParser calcParser(range, CalculationCategory::Percent, valueRange, cssValuePool);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (calculation->category() == CalculationCategory::Percent)
- return calcParser.consumeValue();
- }
- return nullptr;
+ CalcParser calcParser(range, CalculationCategory::Percent, valueRange, { }, cssValuePool);
+ return calcParser.consumeValueIfCategory(CalculationCategory::Percent);
}
if (auto percent = consumePercentRaw(range, valueRange))
@@ -479,10 +476,8 @@
return std::nullopt;
CalcParser calcParser(range, CalculationCategory::Length, valueRange);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (canConsumeCalcValue(calculation->category(), cssParserMode))
- return calcParser.consumeLengthOrPercentRaw();
- }
+ if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode))
+ return calcParser.consumeLengthOrPercentRaw();
return std::nullopt;
}
@@ -491,10 +486,8 @@
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
CalcParser calcParser(range, CalculationCategory::Length, valueRange);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (canConsumeCalcValue(calculation->category(), cssParserMode))
- return calcParser.consumeValue();
- }
+ if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode))
+ return calcParser.consumeValue();
return nullptr;
}
@@ -543,12 +536,8 @@
{
const CSSParserToken& token = range.peek();
if (token.type() == FunctionToken) {
- CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, cssValuePool);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (calculation->category() == CalculationCategory::Angle)
- return calcParser.consumeValue();
- }
- return nullptr;
+ CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, { }, cssValuePool);
+ return calcParser.consumeValueIfCategory(CalculationCategory::Angle);
}
if (auto angle = consumeAngleRaw(range, cssParserMode, unitless, unitlessZero))
@@ -560,7 +549,8 @@
static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
{
const CSSParserToken& token = range.peek();
- if (token.type() == DimensionToken) {
+ switch (token.type()) {
+ case DimensionToken:
switch (token.unitType()) {
case CSSUnitType::CSS_DEG:
case CSSUnitType::CSS_RAD:
@@ -568,29 +558,38 @@
case CSSUnitType::CSS_TURN:
return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
default:
- return nullptr;
+ break;
}
- }
- if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
- return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG);
+ break;
+
+ case NumberToken:
+ if (shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
+ return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG);
+ break;
- if (token.type() == PercentageToken)
+ case PercentageToken:
return consumePercent(range, valueRange);
- if (token.type() != FunctionToken)
- return nullptr;
+ case FunctionToken: {
+ CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange);
+ if (const CSSCalcValue* calculation = angleCalcParser.value()) {
+ if (calculation->category() == CalculationCategory::Angle)
+ return angleCalcParser.consumeValue();
+ }
- CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange);
- if (const CSSCalcValue* calculation = angleCalcParser.value()) {
- if (calculation->category() == CalculationCategory::Angle)
- return angleCalcParser.consumeValue();
+ CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange);
+ if (const CSSCalcValue* calculation = percentCalcParser.value()) {
+ if (calculation->category() == CalculationCategory::Percent)
+ return percentCalcParser.consumeValue();
+ }
+
+ break;
}
+
+ default:
+ break;
+ }
- CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange);
- if (const CSSCalcValue* calculation = percentCalcParser.value()) {
- if (calculation->category() == CalculationCategory::Percent)
- return percentCalcParser.consumeValue();
- }
return nullptr;
}
@@ -613,11 +612,7 @@
return nullptr;
CalcParser calcParser(range, CalculationCategory::Time, valueRange);
- if (const CSSCalcValue* calculation = calcParser.value()) {
- if (calculation->category() == CalculationCategory::Time)
- return calcParser.consumeValue();
- }
- return nullptr;
+ return calcParser.consumeValueIfCategory(CalculationCategory::Time);
}
RefPtr<CSSPrimitiveValue> consumeResolution(CSSParserTokenRange& range, AllowXResolutionUnit allowX)
@@ -743,19 +738,67 @@
return 1.0;
if (auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(range))
- return clampTo(*alphaParameter, 0.0, 1.0);
+ return std::clamp(*alphaParameter, 0.0, 1.0);
return std::nullopt;
}
-template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range)
+static std::optional<double> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
{
- if (auto alpha = consumeOptionalAlpha(range))
- return { *alpha };
+ if (!consumeSlashIncludingWhitespace(range))
+ return 1.0;
- if (auto ident = consumeIdentRaw<allowedIdents...>(range))
- return { *ident };
+ auto normalizePercent = [](double percent) {
+ return std::clamp(percent / 100.0, 0.0, 1.0);
+ };
+ auto normalizeNumber = [](double alpha) {
+ return std::clamp(alpha, 0.0, 1.0);
+ };
+
+ const CSSParserToken& token = range.peek();
+
+ switch (token.type()) {
+ case FunctionToken: {
+ CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
+ if (auto percent = percentageCalcParser.consumePercentRaw())
+ return normalizePercent(*percent);
+
+ CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
+ if (auto number = numberCalcParser.consumeNumberRaw())
+ return normalizeNumber(*number);
+
+ return std::nullopt;
+ }
+
+ case PercentageToken:
+ if (std::isinf(token.numericValue()))
+ return std::nullopt;
+ return normalizePercent(range.consumeIncludingWhitespace().numericValue());
+
+ case NumberToken:
+ return normalizeNumber(range.consumeIncludingWhitespace().numericValue());
+
+ case IdentToken:
+ if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
+ switch (variable->type) {
+ case CSSUnitType::CSS_PERCENTAGE:
+ return normalizePercent(variable->value);
+
+ case CSSUnitType::CSS_NUMBER:
+ return normalizeNumber(variable->value);
+
+ default:
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
+
+ default:
+ return std::nullopt;
+ }
+
+ ASSERT_NOT_REACHED();
return std::nullopt;
}
@@ -767,14 +810,59 @@
return consumeNumberRaw(range);
}
-template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeHueOrIdent(CSSParserTokenRange& range, const CSSParserContext& context)
+static std::optional<double> consumeHueOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
{
- if (auto hue = consumeHue(range, context))
- return { *hue };
+ const CSSParserToken& token = range.peek();
- if (auto ident = consumeIdentRaw<allowedIdents...>(range))
- return { *ident };
+ switch (token.type()) {
+ case FunctionToken: {
+ CalcParser angleCalcParser(range, CalculationCategory::Angle, ValueRange::All, symbolTable);
+ if (auto angle = angleCalcParser.consumeAngleRaw())
+ return CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
+
+ CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
+ return numberCalcParser.consumeNumberRaw();
+ }
+
+ case DimensionToken: {
+ auto unitType = token.unitType();
+ switch (unitType) {
+ case CSSUnitType::CSS_DEG:
+ case CSSUnitType::CSS_RAD:
+ case CSSUnitType::CSS_GRAD:
+ case CSSUnitType::CSS_TURN:
+ return CSSPrimitiveValue::computeDegrees(unitType, range.consumeIncludingWhitespace().numericValue());
+ default:
+ return std::nullopt;
+ }
+ }
+
+ case NumberToken:
+ return range.consumeIncludingWhitespace().numericValue();
+ case IdentToken:
+ if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
+ switch (variable->type) {
+ case CSSUnitType::CSS_DEG:
+ case CSSUnitType::CSS_RAD:
+ case CSSUnitType::CSS_GRAD:
+ case CSSUnitType::CSS_TURN:
+ return CSSPrimitiveValue::computeDegrees(variable->type, variable->value);
+
+ case CSSUnitType::CSS_NUMBER:
+ return variable->value;
+
+ default:
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
+
+ default:
+ return std::nullopt;
+ }
+
+ ASSERT_NOT_REACHED();
return std::nullopt;
}
@@ -783,66 +871,132 @@
return std::fmod(std::fmod(hue, 360.0) + 360.0, 360.0);
}
-template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeNumberOrIdent(CSSParserTokenRange& range)
+static std::optional<double> consumeNumberOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
{
- if (auto number = consumeNumberRaw(range))
- return { *number };
+ const CSSParserToken& token = range.peek();
- if (auto ident = consumeIdentRaw<allowedIdents...>(range))
- return { *ident };
+ switch (token.type()) {
+ case FunctionToken: {
+ CalcParser calcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
+ return calcParser.consumeNumberRaw();
+ }
+ case NumberToken:
+ return range.consumeIncludingWhitespace().numericValue();
+
+ case IdentToken:
+ if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
+ switch (variable->type) {
+ case CSSUnitType::CSS_NUMBER:
+ return variable->value;
+
+ default:
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
+
+ default:
+ return std::nullopt;
+ }
+
+ ASSERT_NOT_REACHED();
return std::nullopt;
}
-template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumePercentOrIdent(CSSParserTokenRange& range)
+static std::optional<double> consumePercentOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
{
- if (auto percent = consumePercentRaw(range))
- return { *percent };
+ const CSSParserToken& token = range.peek();
- if (auto ident = consumeIdentRaw<allowedIdents...>(range))
- return { *ident };
+ switch (token.type()) {
+ case FunctionToken: {
+ CalcParser calcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
+ return calcParser.consumePercentRaw();
+ }
+ case PercentageToken:
+ if (std::isinf(token.numericValue()))
+ return std::nullopt;
+ return range.consumeIncludingWhitespace().numericValue();
+
+ case IdentToken:
+ if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
+ switch (variable->type) {
+ case CSSUnitType::CSS_PERCENTAGE:
+ return variable->value;
+
+ default:
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
+
+ default:
+ return std::nullopt;
+ }
+
+ ASSERT_NOT_REACHED();
return std::nullopt;
}
-template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static auto extractChannelValue(CSSValueID channel, const ColorType& originColor) -> typename ColorType::ComponentType
+enum class RGBComponentType { Number, Percentage };
+
+static std::optional<uint8_t> consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
{
- auto components = asColorComponents(originColor);
- switch (channel) {
- case C1:
- return components[0];
- case C2:
- return components[1];
- case C3:
- return components[2];
- case AlphaChannel:
- return components[3];
- default:
- ASSERT_NOT_REACHED();
+ auto normalizePercent = [](double percent) {
+ return convertPrescaledSRGBAFloatToSRGBAByte(percent / 100.0 * 255.0);
+ };
+
+ auto normalizeNumber = [](double number) {
+ return convertPrescaledSRGBAFloatToSRGBAByte(number);
+ };
+
+ const CSSParserToken& token = range.peek();
+
+ switch (token.type()) {
+ case FunctionToken: {
+ CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
+ if (auto percent = percentageCalcParser.consumePercentRaw())
+ return normalizePercent(*percent);
+
+ CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
+ if (auto number = numberCalcParser.consumeNumberRaw())
+ return normalizeNumber(*number);
+
+ return std::nullopt;
}
- return 0;
-}
+ case PercentageToken:
+ if (std::isinf(token.numericValue()))
+ return std::nullopt;
+ return normalizePercent(range.consumeIncludingWhitespace().numericValue());
-template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType, typename ValueTransformer> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor, ValueTransformer&& valueTransformer)
-{
- return switchOn(parsedChannel,
- [&] (double value) {
- return valueTransformer(value);
- },
- [&] (CSSValueID channel) {
- return extractChannelValue<C1, C2, C3, AlphaChannel>(channel, originColor);
+ case NumberToken:
+ return normalizeNumber(range.consumeIncludingWhitespace().numericValue());
+
+ case IdentToken:
+ if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
+ switch (variable->type) {
+ case CSSUnitType::CSS_PERCENTAGE:
+ return normalizePercent(variable->value);
+
+ case CSSUnitType::CSS_NUMBER:
+ return normalizeNumber(variable->value);
+
+ default:
+ return std::nullopt;
+ }
}
- );
-}
+ return std::nullopt;
-template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor)
-{
- return resolveRelativeColorChannel<C1, C2, C3, AlphaChannel>(parsedChannel, originColor, [](auto value) { return value; });
+ default:
+ return std::nullopt;
+ }
+
+ ASSERT_NOT_REACHED();
+ return std::nullopt;
}
-enum class RGBComponentType { Number, Percentage };
-
static uint8_t clampRGBComponent(double value, RGBComponentType componentType)
{
if (componentType == RGBComponentType::Percentage)
@@ -921,26 +1075,28 @@
if (!originColor.isValid())
return { };
- std::optional<RGBComponentType> componentType;
- auto redResult = consumeRelativeRGBComponent<CSSValueR>(args, componentType);
- if (!redResult)
+ auto originColorAsSRGB = originColor.toColorTypeLossy<SRGBA<float>>();
+
+ CSSCalcSymbolTable symbolTable {
+ { CSSValueR, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.red * 100.0 },
+ { CSSValueG, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.green * 100.0 },
+ { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.blue * 100.0 },
+ { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.alpha * 100.0 }
+ };
+
+ auto red = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
+ if (!red)
return { };
- auto red = redResult->value;
- componentType = redResult->type;
- auto greenResult = consumeRelativeRGBComponent<CSSValueG>(args, componentType);
- if (!greenResult)
+ auto green = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
+ if (!green)
return { };
- auto green = greenResult->value;
- componentType = greenResult->type;
- auto blueResult = consumeRelativeRGBComponent<CSSValueB>(args, componentType);
- if (!blueResult)
+ auto blue = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
+ if (!blue)
return { };
- auto blue = blueResult->value;
- componentType = blueResult->type;
- auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args);
+ auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
if (!alpha)
return { };
@@ -947,26 +1103,9 @@
if (!args.atEnd())
return { };
- // After parsing, convert identifiers to values from the origin color.
+ auto normalizedAlpha = convertFloatAlphaTo<uint8_t>(*alpha);
- // FIXME: Do we want to being doing this in uint8_t values? Or should we use
- // higher precision and clamp at the end? It won't make a difference until we
- // support calculations on the origin's components.
- auto originColorAsSRGB = originColor.toSRGBALossy<uint8_t>();
-
- auto resolvedComponentType = componentType.value_or(RGBComponentType::Percentage);
- auto channelResolver = [resolvedComponentType](auto value) {
- return clampRGBComponent(value, resolvedComponentType);
- };
-
- auto resolvedRed = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(red, originColorAsSRGB, channelResolver);
- auto resolvedGreen = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(green, originColorAsSRGB, channelResolver);
- auto resolvedBlue = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(blue, originColorAsSRGB, channelResolver);
- auto resolvedAlpha = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(*alpha, originColorAsSRGB, [](auto value) {
- return convertFloatAlphaTo<uint8_t>(value);
- });
-
- return SRGBA<uint8_t> { resolvedRed, resolvedGreen, resolvedBlue, resolvedAlpha };
+ return SRGBA<uint8_t> { *red, *green, *blue, normalizedAlpha };
}
enum class RGBFunctionMode { RGB, RGBA };
@@ -1048,19 +1187,28 @@
if (!originColor.isValid())
return { };
- auto hue = consumeHueOrIdent<CSSValueH>(args, context);
+ auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>();
+
+ CSSCalcSymbolTable symbolTable {
+ { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHSL.hue },
+ { CSSValueS, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.saturation },
+ { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.lightness },
+ { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.alpha * 100.0 }
+ };
+
+ auto hue = consumeHueOrIdent(args, symbolTable);
if (!hue)
return { };
- auto saturation = consumePercentOrIdent<CSSValueS>(args);
+ auto saturation = consumePercentOrIdent(args, symbolTable);
if (!saturation)
return { };
- auto lightness = consumePercentOrIdent<CSSValueL>(args);
+ auto lightness = consumePercentOrIdent(args, symbolTable);
if (!lightness)
return { };
- auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args);
+ auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
if (!alpha)
return { };
@@ -1067,22 +1215,12 @@
if (!args.atEnd())
return { };
- // After parsing, convert identifiers to values from the origin color.
+ auto normalizedHue = normalizeHue(*hue);
+ auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0);
+ auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0);
+ auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0);
- auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>();
-
- auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*hue, originColorAsHSL, [](auto hue) {
- return normalizeHue(hue);
- });
- auto resolvedSaturation = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*saturation, originColorAsHSL, [](auto saturation) {
- return clampTo(saturation, 0.0, 100.0);
- });
- auto resolvedLightness = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*lightness, originColorAsHSL, [](auto lightness) {
- return clampTo(lightness, 0.0, 100.0);
- });
- auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*alpha, originColorAsHSL);
-
- return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(resolvedHue), static_cast<float>(resolvedSaturation), static_cast<float>(resolvedLightness), static_cast<float>(resolvedAlpha) });
+ return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) });
}
enum class HSLFunctionMode { HSL, HSLA };
@@ -1122,15 +1260,14 @@
return { };
auto normalizedHue = normalizeHue(*hue);
- auto normalizedSaturation = clampTo(*saturation, 0.0, 100.0);
- auto normalizedLightness = clampTo(*lightness, 0.0, 100.0);
- auto normalizedAlpha = clampTo(*alpha, 0.0, 1.0);
+ auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0);
+ auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0);
+ auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0);
return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) });
}
-template<typename ComponentType>
-struct WhitenessBlackness {
+template<typename ComponentType> struct WhitenessBlackness {
ComponentType whiteness;
ComponentType blackness;
};
@@ -1164,19 +1301,28 @@
if (!originColor.isValid())
return { };
- auto hue = consumeHueOrIdent<CSSValueH>(args, context);
+ auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>();
+
+ CSSCalcSymbolTable symbolTable {
+ { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHWB.hue },
+ { CSSValueW, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.whiteness },
+ { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.blackness },
+ { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.alpha * 100.0 }
+ };
+
+ auto hue = consumeHueOrIdent(args, symbolTable);
if (!hue)
return { };
- auto whiteness = consumePercentOrIdent<CSSValueW>(args);
+ auto whiteness = consumePercentOrIdent(args, symbolTable);
if (!whiteness)
return { };
- auto blackness = consumePercentOrIdent<CSSValueB>(args);
+ auto blackness = consumePercentOrIdent(args, symbolTable);
if (!blackness)
return { };
- auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args);
+ auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
if (!alpha)
return { };
@@ -1183,20 +1329,10 @@
if (!args.atEnd())
return { };
- // After parsing, convert identifiers to values from the origin color.
+ auto normalizedHue = normalizeHue(*hue);
+ auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(*whiteness, *blackness);
- auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>();
-
- auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*hue, originColorAsHWB, [](auto hue) {
- return normalizeHue(hue);
- });
- auto resolvedWhiteness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*whiteness, originColorAsHWB);
- auto resolvedBlackness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*blackness, originColorAsHWB);
- auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*alpha, originColorAsHWB);
-
- auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(resolvedWhiteness, resolvedBlackness);
-
- return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(resolvedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(resolvedAlpha) });
+ return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(*alpha) });
}
static Color parseHWBParameters(CSSParserTokenRange& range, const CSSParserContext& context)
@@ -1245,19 +1381,28 @@
if (!originColor.isValid())
return { };
- auto lightness = consumePercentOrIdent<CSSValueL>(args);
+ auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>();
+
+ CSSCalcSymbolTable symbolTable {
+ { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.lightness },
+ { CSSValueA, CSSUnitType::CSS_NUMBER, originColorAsLab.a },
+ { CSSValueB, CSSUnitType::CSS_NUMBER, originColorAsLab.b },
+ { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.alpha * 100.0 }
+ };
+
+ auto lightness = consumePercentOrIdent(args, symbolTable);
if (!lightness)
return { };
- auto aValue = consumeNumberOrIdent<CSSValueA>(args);
+ auto aValue = consumeNumberOrIdent(args, symbolTable);
if (!aValue)
return { };
- auto bValue = consumeNumberOrIdent<CSSValueB>(args);
+ auto bValue = consumeNumberOrIdent(args, symbolTable);
if (!bValue)
return { };
- auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args);
+ auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
if (!alpha)
return { };
@@ -1264,18 +1409,9 @@
if (!args.atEnd())
return { };
- // After parsing, convert identifiers to values from the origin color.
+ auto normalizedLightness = std::max(0.0, *lightness);
- auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>();
-
- auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*lightness, originColorAsLab, [](auto lightness) {
- return std::max(0.0, lightness);
- });
- auto resolvedAValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*aValue, originColorAsLab);
- auto resolvedBValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*bValue, originColorAsLab);
- auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*alpha, originColorAsLab);
-
- return Lab<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedAValue), static_cast<float>(resolvedBValue), static_cast<float>(resolvedAlpha) };
+ return Lab<float> { static_cast<float>(normalizedLightness), static_cast<float>(*aValue), static_cast<float>(*bValue), static_cast<float>(*alpha) };
}
static Color parseLabParameters(CSSParserTokenRange& range, const CSSParserContext& context)
@@ -1323,19 +1459,28 @@
if (!originColor.isValid())
return { };
- auto lightness = consumePercentOrIdent<CSSValueL>(args);
+ auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>();
+
+ CSSCalcSymbolTable symbolTable {
+ { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.lightness },
+ { CSSValueC, CSSUnitType::CSS_NUMBER, originColorAsLCH.chroma },
+ { CSSValueH, CSSUnitType::CSS_DEG, originColorAsLCH.hue },
+ { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.alpha * 100.0 }
+ };
+
+ auto lightness = consumePercentOrIdent(args, symbolTable);
if (!lightness)
return { };
- auto chroma = consumeNumberOrIdent<CSSValueC>(args);
+ auto chroma = consumeNumberOrIdent(args, symbolTable);
if (!chroma)
return { };
- auto hue = consumeHueOrIdent<CSSValueH>(args, context);
+ auto hue = consumeHueOrIdent(args, symbolTable);
if (!hue)
return { };
- auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args);
+ auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
if (!alpha)
return { };
@@ -1342,20 +1487,11 @@
if (!args.atEnd())
return { };
- auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>();
+ auto normalizedLightness = std::max(0.0, *lightness);
+ auto normalizedChroma = std::max(0.0, *chroma);
+ auto normalizedHue = normalizeHue(*hue);
- auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*lightness, originColorAsLCH, [](auto lightness) {
- return std::max(0.0, lightness);
- });
- auto resolvedChroma = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*chroma, originColorAsLCH, [](auto chroma) {
- return std::max(0.0, chroma);
- });
- auto resolvedHue = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*hue, originColorAsLCH, [](auto hue) {
- return normalizeHue(hue);
- });
- auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*alpha, originColorAsLCH);
-
- return LCHA<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedChroma), static_cast<float>(resolvedHue), static_cast<float>(resolvedAlpha) };
+ return LCHA<float> { static_cast<float>(normalizedLightness), static_cast<float>(normalizedChroma), static_cast<float>(normalizedHue), static_cast<float>(*alpha) };
}
static Color parseLCHParameters(CSSParserTokenRange& range, const CSSParserContext& context)