Changeset 278261 in webkit
- Timestamp:
- May 30, 2021 5:29:18 PM (14 months ago)
- Location:
- trunk
- Files:
-
- 12 edited
- 2 copied
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt (modified) (6 diffs)
-
LayoutTests/fast/css/parsing-relative-color-syntax.html (modified) (7 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/Sources.txt (modified) (1 diff)
-
Source/WebCore/WebCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp (modified) (2 diffs)
-
Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h (modified) (3 diffs)
-
Source/WebCore/css/calc/CSSCalcSymbolTable.cpp (copied) (copied from trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h) (1 diff)
-
Source/WebCore/css/calc/CSSCalcSymbolTable.h (copied) (copied from trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h) (1 diff)
-
Source/WebCore/css/calc/CSSCalcValue.cpp (modified) (3 diffs)
-
Source/WebCore/css/calc/CSSCalcValue.h (modified) (3 diffs)
-
Source/WebCore/css/makevalues.pl (modified) (2 diffs)
-
Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r278245 r278261 1 2021-05-30 Sam Weinig <weinig@apple.com> 2 3 Support calc() on components inside relative color syntax colors 4 https://bugs.webkit.org/show_bug.cgi?id=226272 5 6 Reviewed by Darin Adler. 7 8 Updated test and results for update support including calc() 9 and compoment permutation. 10 11 * fast/css/parsing-relative-color-syntax-expected.txt: 12 * fast/css/parsing-relative-color-syntax.html: 13 1 14 2021-05-29 Cameron McCormack <heycam@apple.com> 2 15 -
trunk/LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt
r273127 r278261 43 43 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 25 b / 25%)") is "rgba(26, 25, 77, 0.25)" 44 44 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r g 25 / 25%)") is "rgba(26, 51, 25, 0.25)" 45 PASS computedStyle("background-color", "rgb(from rebeccapurple g b r)") is "rgba(0, 0, 0, 0)" 46 PASS computedStyle("background-color", "rgb(from rebeccapurple b alpha r / g)") is "rgba(0, 0, 0, 0)" 47 PASS computedStyle("background-color", "rgb(from rebeccapurple r r r / r)") is "rgba(0, 0, 0, 0)" 48 PASS computedStyle("background-color", "rgb(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 49 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) g b r)") is "rgba(0, 0, 0, 0)" 50 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)") is "rgba(0, 0, 0, 0)" 51 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)") is "rgba(0, 0, 0, 0)" 52 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 53 PASS computedStyle("background-color", "rgb(from rebeccapurple r 10% 10)") is "rgba(0, 0, 0, 0)" 54 PASS computedStyle("background-color", "rgb(from rebeccapurple r 10 10%)") is "rgba(0, 0, 0, 0)" 55 PASS computedStyle("background-color", "rgb(from rebeccapurple 0% 10 10)") is "rgba(0, 0, 0, 0)" 56 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)") is "rgba(0, 0, 0, 0)" 57 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)") is "rgba(0, 0, 0, 0)" 58 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)") is "rgba(0, 0, 0, 0)" 45 PASS computedStyle("background-color", "rgb(from rebeccapurple g b r)") is "rgb(51, 153, 102)" 46 PASS computedStyle("background-color", "rgb(from rebeccapurple b alpha r / g)") is "rgba(153, 255, 102, 0.2)" 47 PASS computedStyle("background-color", "rgb(from rebeccapurple r r r / r)") is "rgba(102, 102, 102, 0.4)" 48 PASS computedStyle("background-color", "rgb(from rebeccapurple alpha alpha alpha / alpha)") is "rgb(255, 255, 255)" 49 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) g b r)") is "rgb(51, 77, 26)" 50 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)") is "rgba(77, 102, 26, 0.2)" 51 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)") is "rgba(26, 26, 26, 0.1)" 52 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(102, 102, 102, 0.4)" 53 PASS computedStyle("background-color", "rgb(from rebeccapurple r 10% 10)") is "rgb(102, 26, 10)" 54 PASS computedStyle("background-color", "rgb(from rebeccapurple r 10 10%)") is "rgb(102, 10, 26)" 55 PASS computedStyle("background-color", "rgb(from rebeccapurple 0% 10 10)") is "rgb(0, 10, 10)" 56 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)") is "rgb(26, 26, 10)" 57 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)") is "rgb(26, 10, 26)" 58 PASS computedStyle("background-color", "rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)") is "rgb(0, 10, 10)" 59 PASS computedStyle("background-color", "rgb(from rebeccapurple calc(r) calc(g) calc(b))") is "rgb(102, 51, 153)" 60 PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(g * .5) 10)") is "rgb(102, 26, 10)" 61 PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5) 10)") is "rgb(102, 77, 10)" 62 PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 + g * .5) 10)") is "rgb(102, 102, 10)" 63 PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)") is "rgb(102, 51, 10)" 64 PASS computedStyle("background-color", "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)") is "rgb(102, 51, 10)" 65 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)" 59 66 PASS computedStyle("background-color", "rgb(from rebeccapurple red g b)") is "rgba(0, 0, 0, 0)" 60 67 PASS computedStyle("background-color", "rgb(from rebeccapurple l g b)") is "rgba(0, 0, 0, 0)" … … 92 99 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h s 25% / alpha)") is "rgba(32, 63, 95, 0.4)" 93 100 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h s l / .25)") is "rgba(26, 51, 77, 0.25)" 94 PASS computedStyle("background-color", "hsl(from rebeccapurple h l s)") is "rgba(0, 0, 0, 0)" 95 PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha l / s)") is "rgba(0, 0, 0, 0)" 96 PASS computedStyle("background-color", "hsl(from rebeccapurple h l l / l)") is "rgba(0, 0, 0, 0)" 97 PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 98 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l s)") is "rgba(0, 0, 0, 0)" 99 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)") is "rgba(0, 0, 0, 0)" 100 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)") is "rgba(0, 0, 0, 0)" 101 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 101 PASS computedStyle("background-color", "hsl(from rebeccapurple h l s)") is "rgb(128, 77, 179)" 102 PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha l / s)") is "rgba(102, 0, 204, 0.5)" 103 PASS computedStyle("background-color", "hsl(from rebeccapurple h l l / l)") is "rgba(102, 61, 143, 0.4)" 104 PASS computedStyle("background-color", "hsl(from rebeccapurple h alpha alpha / alpha)") is "rgb(255, 255, 255)" 105 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l s)") is "rgb(101, 126, 152)" 106 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)") is "rgba(31, 51, 72, 0.494)" 107 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)") is "rgba(41, 51, 62, 0.204)" 108 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(61, 101, 143, 0.4)" 109 PASS computedStyle("background-color", "hsl(from rebeccapurple s h l)") is "rgba(0, 0, 0, 0)" 110 PASS computedStyle("background-color", "hsl(from rebeccapurple s s s / s)") is "rgba(0, 0, 0, 0)" 111 PASS computedStyle("background-color", "hsl(from rebeccapurple h h h / h)") is "rgba(0, 0, 0, 0)" 112 PASS computedStyle("background-color", "hsl(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 113 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) s h l)") is "rgba(0, 0, 0, 0)" 114 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)") is "rgba(0, 0, 0, 0)" 115 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)") is "rgba(0, 0, 0, 0)" 116 PASS computedStyle("background-color", "hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 117 PASS computedStyle("background-color", "hsl(from rebeccapurple calc(h) calc(s) calc(l))") is "rgb(102, 51, 153)" 118 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)" 102 119 PASS computedStyle("background-color", "hsl(from rebeccapurple h 10% 10)") is "rgba(0, 0, 0, 0)" 103 120 PASS computedStyle("background-color", "hsl(from rebeccapurple h 10 10%)") is "rgba(0, 0, 0, 0)" … … 141 158 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w 25% / alpha)") is "rgba(26, 107, 191, 0.4)" 142 159 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w b / .25)") is "rgba(26, 51, 77, 0.25)" 143 PASS computedStyle("background-color", "hwb(from rebeccapurple h b w)") is "rgba(0, 0, 0, 0)" 144 PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha w / b)") is "rgba(0, 0, 0, 0)" 145 PASS computedStyle("background-color", "hwb(from rebeccapurple h w w / w)") is "rgba(0, 0, 0, 0)" 146 PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 147 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h b w)") is "rgba(0, 0, 0, 0)" 148 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)") is "rgba(0, 0, 0, 0)" 149 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)") is "rgba(0, 0, 0, 0)" 150 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 160 PASS computedStyle("background-color", "hwb(from rebeccapurple h b w)") is "rgb(153, 102, 204)" 161 PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha w / b)") is "rgba(213, 213, 213, 0.4)" 162 PASS computedStyle("background-color", "hwb(from rebeccapurple h w w / w)") is "rgba(128, 51, 204, 0.2)" 163 PASS computedStyle("background-color", "hwb(from rebeccapurple h alpha alpha / alpha)") is "rgb(128, 128, 128)" 164 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h b w)") is "rgb(178, 203, 229)" 165 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)") is "rgba(102, 164, 229, 0.698)" 166 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)") is "rgba(26, 126, 229, 0.1)" 167 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)") is "rgba(102, 127, 153, 0.4)" 168 PASS computedStyle("background-color", "hwb(from rebeccapurple w h b)") is "rgba(0, 0, 0, 0)" 169 PASS computedStyle("background-color", "hwb(from rebeccapurple b b b / b)") is "rgba(0, 0, 0, 0)" 170 PASS computedStyle("background-color", "hwb(from rebeccapurple h h h / h)") is "rgba(0, 0, 0, 0)" 171 PASS computedStyle("background-color", "hwb(from rebeccapurple alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 172 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) w b h)") is "rgba(0, 0, 0, 0)" 173 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)") is "rgba(0, 0, 0, 0)" 174 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)") is "rgba(0, 0, 0, 0)" 175 PASS computedStyle("background-color", "hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 176 PASS computedStyle("background-color", "hwb(from rebeccapurple calc(h) calc(w) calc(b))") is "rgb(102, 51, 153)" 177 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)" 151 178 PASS computedStyle("background-color", "hwb(from rebeccapurple h 10% 10)") is "rgba(0, 0, 0, 0)" 152 179 PASS computedStyle("background-color", "hwb(from rebeccapurple h 10 10%)") is "rgba(0, 0, 0, 0)" … … 183 210 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a 35 / alpha)") is "lab(25% 20 35 / 0.4)" 184 211 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a b / .35)") is "lab(25% 20 50 / 0.35)" 185 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l b a)") is "rgba(0, 0, 0, 0)" 212 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l b a)") is "lab(25% 50 20)" 213 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l a a / a)") is "lab(25% 20 20)" 214 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l b a)") is "lab(25% 50 20)" 215 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a a / a)") is "lab(25% 20 20)" 186 216 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l alpha a / b)") is "rgba(0, 0, 0, 0)" 187 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l a a / a)") is "rgba(0, 0, 0, 0)"188 217 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 189 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l b a)") is "rgba(0, 0, 0, 0)"190 218 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l alpha a / b)") is "rgba(0, 0, 0, 0)" 191 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l a a / a)") is "rgba(0, 0, 0, 0)"192 219 PASS computedStyle("background-color", "lab(from lab(25% 20 50 / 40%) l alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 220 PASS computedStyle("background-color", "lab(from lab(25% 20 50) calc(l) calc(a) calc(b))") is "lab(25% 20 50)" 221 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)" 193 222 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l 10% 10)") is "rgba(0, 0, 0, 0)" 194 223 PASS computedStyle("background-color", "lab(from lab(25% 20 50) l 10 10%)") is "rgba(0, 0, 0, 0)" … … 232 261 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)") is "lch(70% 45 25 / 0.4)" 233 262 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c h / .25)") is "lch(70% 45 30 / 0.25)" 234 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / l)") is "rgba(0, 0, 0, 0)" 235 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / alpha)") is "rgba(0, 0, 0, 0)" 236 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / l)") is "rgba(0, 0, 0, 0)" 237 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)") is "rgba(0, 0, 0, 0)" 263 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / l)") is "lch(100% 45 30 / 0.7)" 264 PASS computedStyle("background-color", "lch(from lch(70% 45 30) l c c / alpha)") is "lch(70% 45 45)" 265 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c h / alpha)") is "lch(100% 45 30)" 266 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha c c / alpha)") is "lch(100% 45 45)" 267 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / l)") is "lch(40% 45 30 / 0.7)" 268 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) l c c / alpha)") is "lch(70% 45 45 / 0.4)" 269 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)") is "lch(40% 45 30 / 0.4)" 270 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha c c / alpha)") is "lch(40% 45 45 / 0.4)" 271 PASS computedStyle("background-color", "lch(from lch(70% 45 30) h l c / alpha)") is "rgba(0, 0, 0, 0)" 272 PASS computedStyle("background-color", "lch(from lch(70% 45 30) c c c / c)") is "rgba(0, 0, 0, 0)" 273 PASS computedStyle("background-color", "lch(from lch(70% 45 30) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 274 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) h l c / alpha)") is "rgba(0, 0, 0, 0)" 275 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) c c c / c)") is "rgba(0, 0, 0, 0)" 276 PASS computedStyle("background-color", "lch(from lch(70% 45 30 / 40%) alpha alpha alpha / alpha)") is "rgba(0, 0, 0, 0)" 277 PASS computedStyle("background-color", "lch(from lch(70% 45 30) calc(l) calc(c) calc(h))") is "lch(70% 45 30)" 278 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)" 238 279 PASS computedStyle("background-color", "lch(from lch(70% 45 30) l 10% h)") is "rgba(0, 0, 0, 0)" 239 280 PASS computedStyle("background-color", "lch(from lch(70% 45 30) l c 10%)") is "rgba(0, 0, 0, 0)" … … 245 286 PASS computedStyle("background-color", "lch(from lch(70% 45 30) x c h)") is "rgba(0, 0, 0, 0)" 246 287 PASS computedStyle("background-color", "lch(from lch(70% 45 30) l g b)") is "rgba(0, 0, 0, 0)" 288 PASS computedStyle("background-color", "rgb(from var(--bg-color) r g b / 80%)") is "rgba(0, 0, 255, 0.8)" 289 PASS computedStyle("background-color", "lch(from var(--color) calc(l / 2) c h)") is "lch(23.138971% 67.989716 134.39125)" 290 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)" 291 PASS computedStyle("background-color", "lch(from var(--color) l 0 h)") is "lch(46.277943% 0 134.39125)" 292 PASS computedStyle("background-color", "rgb(from indianred 255 g b)") is "rgb(255, 92, 92)" 293 PASS computedStyle("background-color", "hsl(from var(--accent) calc(h + 180deg) s l)") is "rgb(178, 32, 40)" 294 PASS computedStyle("background-color", "lab(from var(--mycolor) l a b / 100%)") is "lab(62.751923% 52.45802 -34.117283)" 295 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)" 296 PASS computedStyle("background-color", "lab(from var(--mycolor) l a b / calc(alpha - 20%))") is "lab(62.751923% 52.45802 -34.117283 / 0.8)" 297 PASS computedStyle("background-color", "lab(from var(--mycolor) l 0 0)") is "lab(62.751923% 0 0)" 298 PASS computedStyle("background-color", "lch(from peru calc(l * 0.8) c h)") is "lch(49.80138% 54.003296 63.680317)" 299 PASS computedStyle("background-color", "LCH(from var(--accent) l c calc(h + 180deg))") is "lch(65.49473% 39.446903 10.114471)" 300 PASS computedStyle("background-color", "lch(from var(--mycolor) l 0 h)") is "lch(62.751923% 0 326.96112)" 301 PASS computedStyle("background-color", "var(--mygray)") is "lch(62.751923% 0 326.96112)" 302 PASS computedStyle("background-color", "lch(from var(--mygray) l 30 h)") is "lch(62.751923% 30 326.96112)" 247 303 PASS successfullyParsed is true 248 304 -
trunk/LayoutTests/fast/css/parsing-relative-color-syntax.html
r273127 r278261 2 2 <html> 3 3 <script src="../../resources/js-test-pre.js"></script> 4 <style> 5 html { 6 --bg-color: blue; 7 --color: green; 8 --accent: lightseagreen; 9 --mycolor: orchid; 10 --mygray: lch(from var(--mycolor) l 0 h); 11 } 12 </style> 4 13 </head> 5 14 <body> … … 96 105 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r g 25 / 25%)`, `rgba(26, 51, 25, 0.25)`); 97 106 98 // Testing permutation (unclear if this is allowed per-spec, we disallow it). 99 testComputed(`rgb(from rebeccapurple g b r)`, `rgba(0, 0, 0, 0)`); 100 testComputed(`rgb(from rebeccapurple b alpha r / g)`, `rgba(0, 0, 0, 0)`); 101 testComputed(`rgb(from rebeccapurple r r r / r)`, `rgba(0, 0, 0, 0)`); 102 testComputed(`rgb(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 103 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) g b r)`, `rgba(0, 0, 0, 0)`); 104 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)`, `rgba(0, 0, 0, 0)`); 105 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)`, `rgba(0, 0, 0, 0)`); 106 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 107 108 // Testing invalid mixes of number and percentage 109 testComputed(`rgb(from rebeccapurple r 10% 10)`, `rgba(0, 0, 0, 0)`); 110 testComputed(`rgb(from rebeccapurple r 10 10%)`, `rgba(0, 0, 0, 0)`); 111 testComputed(`rgb(from rebeccapurple 0% 10 10)`, `rgba(0, 0, 0, 0)`); 112 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)`, `rgba(0, 0, 0, 0)`); 113 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)`, `rgba(0, 0, 0, 0)`); 114 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)`, `rgba(0, 0, 0, 0)`); 107 // Testing permutation. 108 testComputed(`rgb(from rebeccapurple g b r)`, `rgb(51, 153, 102)`); 109 testComputed(`rgb(from rebeccapurple b alpha r / g)`, `rgba(153, 255, 102, 0.2)`); 110 testComputed(`rgb(from rebeccapurple r r r / r)`, `rgba(102, 102, 102, 0.4)`); 111 testComputed(`rgb(from rebeccapurple alpha alpha alpha / alpha)`, `rgb(255, 255, 255)`); 112 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) g b r)`, `rgb(51, 77, 26)`); 113 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) b alpha r / g)`, `rgba(77, 102, 26, 0.2)`); 114 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r r r / r)`, `rgba(26, 26, 26, 0.1)`); 115 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(102, 102, 102, 0.4)`); 116 117 // Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax). 118 testComputed(`rgb(from rebeccapurple r 10% 10)`, `rgb(102, 26, 10)`); 119 testComputed(`rgb(from rebeccapurple r 10 10%)`, `rgb(102, 10, 26)`); 120 testComputed(`rgb(from rebeccapurple 0% 10 10)`, `rgb(0, 10, 10)`); 121 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10% 10)`, `rgb(26, 26, 10)`); 122 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) r 10 10%)`, `rgb(26, 10, 26)`); 123 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) 0% 10 10)`, `rgb(0, 10, 10)`); 124 125 // Testing with calc(). 126 testComputed(`rgb(from rebeccapurple calc(r) calc(g) calc(b))`, `rgb(102, 51, 153)`); 127 testComputed(`rgb(from rebeccapurple r calc(g * .5) 10)`, `rgb(102, 26, 10)`); 128 testComputed(`rgb(from rebeccapurple r calc(b * .5) 10)`, `rgb(102, 77, 10)`); 129 testComputed(`rgb(from rebeccapurple r calc(b * .5 + g * .5) 10)`, `rgb(102, 102, 10)`); 130 testComputed(`rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`); 131 testComputed(`rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`); 132 testComputed(`rgb(from rgb(10%, 20%, 30%, 40%) calc(r) calc(g) calc(b) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`); 115 133 116 134 // Testing invalid component names … … 162 180 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h s l / .25)`, `rgba(26, 51, 77, 0.25)`); 163 181 164 // Testing permutation (unclear if this is allowed per-spec, we disallow it). 165 testComputed(`hsl(from rebeccapurple h l s)`, `rgba(0, 0, 0, 0)`); 166 testComputed(`hsl(from rebeccapurple h alpha l / s)`, `rgba(0, 0, 0, 0)`); 167 testComputed(`hsl(from rebeccapurple h l l / l)`, `rgba(0, 0, 0, 0)`); 168 testComputed(`hsl(from rebeccapurple h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 169 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l s)`, `rgba(0, 0, 0, 0)`); 170 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)`, `rgba(0, 0, 0, 0)`); 171 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)`, `rgba(0, 0, 0, 0)`); 172 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 182 // Testing valid permutation (types match). 183 testComputed(`hsl(from rebeccapurple h l s)`, `rgb(128, 77, 179)`); 184 testComputed(`hsl(from rebeccapurple h alpha l / s)`, `rgba(102, 0, 204, 0.5)`); 185 testComputed(`hsl(from rebeccapurple h l l / l)`, `rgba(102, 61, 143, 0.4)`); 186 testComputed(`hsl(from rebeccapurple h alpha alpha / alpha)`, `rgb(255, 255, 255)`); 187 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l s)`, `rgb(101, 126, 152)`); 188 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha l / s)`, `rgba(31, 51, 72, 0.494)`); 189 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h l l / l)`, `rgba(41, 51, 62, 0.204)`); 190 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(61, 101, 143, 0.4)`); 191 192 // Testing invalid permutation (types don't match). 193 testComputed(`hsl(from rebeccapurple s h l)`, `rgba(0, 0, 0, 0)`); 194 testComputed(`hsl(from rebeccapurple s s s / s)`, `rgba(0, 0, 0, 0)`); 195 testComputed(`hsl(from rebeccapurple h h h / h)`, `rgba(0, 0, 0, 0)`); 196 testComputed(`hsl(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 197 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) s h l)`, `rgba(0, 0, 0, 0)`); 198 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)`, `rgba(0, 0, 0, 0)`); 199 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)`, `rgba(0, 0, 0, 0)`); 200 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 201 202 // Testing with calc(). 203 testComputed(`hsl(from rebeccapurple calc(h) calc(s) calc(l))`, `rgb(102, 51, 153)`); 204 testComputed(`hsl(from rgb(10%, 20%, 30%, 40%) calc(h) calc(s) calc(l) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`); 173 205 174 206 // Testing invalid values. … … 229 261 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w b / .25)`, `rgba(26, 51, 77, 0.25)`); 230 262 231 // Testing permutation (unclear if this is allowed per-spec, we disallow it). 232 testComputed(`hwb(from rebeccapurple h b w)`, `rgba(0, 0, 0, 0)`); 233 testComputed(`hwb(from rebeccapurple h alpha w / b)`, `rgba(0, 0, 0, 0)`); 234 testComputed(`hwb(from rebeccapurple h w w / w)`, `rgba(0, 0, 0, 0)`); 235 testComputed(`hwb(from rebeccapurple h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 236 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h b w)`, `rgba(0, 0, 0, 0)`); 237 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)`, `rgba(0, 0, 0, 0)`); 238 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)`, `rgba(0, 0, 0, 0)`); 239 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 263 // Testing valid permutation (types match). 264 testComputed(`hwb(from rebeccapurple h b w)`, `rgb(153, 102, 204)`); 265 testComputed(`hwb(from rebeccapurple h alpha w / b)`, `rgba(213, 213, 213, 0.4)`); 266 testComputed(`hwb(from rebeccapurple h w w / w)`, `rgba(128, 51, 204, 0.2)`); 267 testComputed(`hwb(from rebeccapurple h alpha alpha / alpha)`, `rgb(128, 128, 128)`); 268 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h b w)`, `rgb(178, 203, 229)`); 269 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha w / b)`, `rgba(102, 164, 229, 0.698)`); 270 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h w w / w)`, `rgba(26, 126, 229, 0.1)`); 271 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h alpha alpha / alpha)`, `rgba(102, 127, 153, 0.4)`); 272 273 // Testing invalid permutation (types don't match). 274 testComputed(`hwb(from rebeccapurple w h b)`, `rgba(0, 0, 0, 0)`); 275 testComputed(`hwb(from rebeccapurple b b b / b)`, `rgba(0, 0, 0, 0)`); 276 testComputed(`hwb(from rebeccapurple h h h / h)`, `rgba(0, 0, 0, 0)`); 277 testComputed(`hwb(from rebeccapurple alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 278 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) w b h)`, `rgba(0, 0, 0, 0)`); 279 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)`, `rgba(0, 0, 0, 0)`); 280 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)`, `rgba(0, 0, 0, 0)`); 281 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 282 283 // Testing with calc(). 284 testComputed(`hwb(from rebeccapurple calc(h) calc(w) calc(b))`, `rgb(102, 51, 153)`); 285 testComputed(`hwb(from rgb(10%, 20%, 30%, 40%) calc(h) calc(w) calc(b) / calc(alpha))`, `rgba(26, 51, 77, 0.4)`); 240 286 241 287 // Testing invalid values. … … 289 335 testComputed(`lab(from lab(25% 20 50 / 40%) l a b / .35)`, `lab(25% 20 50 / 0.35)`); 290 336 291 // Testing permutation (unclear if this is allowed per-spec, we disallow it). 292 testComputed(`lab(from lab(25% 20 50) l b a)`, `rgba(0, 0, 0, 0)`); 337 // Testing valid permutation (types match). 338 testComputed(`lab(from lab(25% 20 50) l b a)`, `lab(25% 50 20)`); 339 testComputed(`lab(from lab(25% 20 50) l a a / a)`, `lab(25% 20 20)`); 340 testComputed(`lab(from lab(25% 20 50 / 40%) l b a)`, `lab(25% 50 20)`); 341 testComputed(`lab(from lab(25% 20 50 / 40%) l a a / a)`, `lab(25% 20 20)`); 342 343 // Testing invalid permutation (types don't match). 293 344 testComputed(`lab(from lab(25% 20 50) l alpha a / b)`, `rgba(0, 0, 0, 0)`); 294 testComputed(`lab(from lab(25% 20 50) l a a / a)`, `rgba(0, 0, 0, 0)`);295 345 testComputed(`lab(from lab(25% 20 50) l alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 296 testComputed(`lab(from lab(25% 20 50 / 40%) l b a)`, `rgba(0, 0, 0, 0)`);297 346 testComputed(`lab(from lab(25% 20 50 / 40%) l alpha a / b)`, `rgba(0, 0, 0, 0)`); 298 testComputed(`lab(from lab(25% 20 50 / 40%) l a a / a)`, `rgba(0, 0, 0, 0)`);299 347 testComputed(`lab(from lab(25% 20 50 / 40%) l alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 348 349 // Testing with calc(). 350 testComputed(`lab(from lab(25% 20 50) calc(l) calc(a) calc(b))`, `lab(25% 20 50)`); 351 testComputed(`lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))`, `lab(25% 20 50 / 0.4)`); 300 352 301 353 // Testing invalid values. … … 356 408 testComputed(`lch(from lch(70% 45 30 / 40%) l c h / .25)`, `lch(70% 45 30 / 0.25)`); 357 409 358 // Testing permutation (unclear if this is allowed per-spec, we disallow it). 359 testComputed(`lch(from lch(70% 45 30) alpha c h / l)`, `rgba(0, 0, 0, 0)`); 360 testComputed(`lch(from lch(70% 45 30) alpha c h / alpha)`, `rgba(0, 0, 0, 0)`); 361 testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / l)`, `rgba(0, 0, 0, 0)`); 362 testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / alpha)`, `rgba(0, 0, 0, 0)`); 410 // Testing valid permutation (types match). 411 // NOTE: 'c' is a vaild hue, as hue is <angle>|<number>. 412 testComputed(`lch(from lch(70% 45 30) alpha c h / l)`, `lch(100% 45 30 / 0.7)`); 413 testComputed(`lch(from lch(70% 45 30) l c c / alpha)`, `lch(70% 45 45)`); 414 testComputed(`lch(from lch(70% 45 30) alpha c h / alpha)`, `lch(100% 45 30)`); 415 testComputed(`lch(from lch(70% 45 30) alpha c c / alpha)`, `lch(100% 45 45)`); 416 testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / l)`, `lch(40% 45 30 / 0.7)`); 417 testComputed(`lch(from lch(70% 45 30 / 40%) l c c / alpha)`, `lch(70% 45 45 / 0.4)`); 418 testComputed(`lch(from lch(70% 45 30 / 40%) alpha c h / alpha)`, `lch(40% 45 30 / 0.4)`); 419 testComputed(`lch(from lch(70% 45 30 / 40%) alpha c c / alpha)`, `lch(40% 45 45 / 0.4)`); 420 421 // Testing invalid permutation (types don't match). 422 testComputed(`lch(from lch(70% 45 30) h l c / alpha)`, `rgba(0, 0, 0, 0)`); 423 testComputed(`lch(from lch(70% 45 30) c c c / c)`, `rgba(0, 0, 0, 0)`); 424 testComputed(`lch(from lch(70% 45 30) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 425 testComputed(`lch(from lch(70% 45 30 / 40%) h l c / alpha)`, `rgba(0, 0, 0, 0)`); 426 testComputed(`lch(from lch(70% 45 30 / 40%) c c c / c)`, `rgba(0, 0, 0, 0)`); 427 testComputed(`lch(from lch(70% 45 30 / 40%) alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); 428 429 // Testing with calc(). 430 testComputed(`lch(from lch(70% 45 30) calc(l) calc(c) calc(h))`, `lch(70% 45 30)`); 431 testComputed(`lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))`, `lch(70% 45 30 / 0.4)`); 363 432 364 433 // Testing invalid values. … … 374 443 testComputed(`lch(from lch(70% 45 30) x c h)`, `rgba(0, 0, 0, 0)`); 375 444 testComputed(`lch(from lch(70% 45 30) l g b)`, `rgba(0, 0, 0, 0)`); 445 446 447 // Spec examples: 448 // Example 11. 449 testComputed(`rgb(from var(--bg-color) r g b / 80%)`, `rgba(0, 0, 255, 0.8)`); 450 451 // Example 12. 452 testComputed(`lch(from var(--color) calc(l / 2) c h)`, `lch(23.138971% 67.989716 134.39125)`); 453 454 // Example 13. 455 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)`) 456 testComputed(`lch(from var(--color) l 0 h)`, `lch(46.277943% 0 134.39125)`) 457 458 // Example 14. 459 testComputed(`rgb(from indianred 255 g b)`, `rgb(255, 92, 92)`); 460 461 // Example 15. 462 testComputed(`hsl(from var(--accent) calc(h + 180deg) s l)`, `rgb(178, 32, 40)`); 463 464 // Example 16. 465 testComputed(`lab(from var(--mycolor) l a b / 100%)`, `lab(62.751923% 52.45802 -34.117283)`); 466 testComputed(`lab(from var(--mycolor) l a b / calc(alpha * 0.8))`, `lab(62.751923% 52.45802 -34.117283 / 0.8)`); 467 testComputed(`lab(from var(--mycolor) l a b / calc(alpha - 20%))`, `lab(62.751923% 52.45802 -34.117283 / 0.8)`); 468 469 // Example 17. 470 testComputed(`lab(from var(--mycolor) l 0 0)`, `lab(62.751923% 0 0)`); 471 472 // Example 18. 473 testComputed(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80138% 54.003296 63.680317)`); 474 475 // Example 19. 476 testComputed(`LCH(from var(--accent) l c calc(h + 180deg))`, `lch(65.49473% 39.446903 10.114471)`); 477 478 // Example 20. 479 testComputed(`lch(from var(--mycolor) l 0 h)`, `lch(62.751923% 0 326.96112)`); 480 testComputed(`var(--mygray)`, `lch(62.751923% 0 326.96112)`); 481 testComputed(`lch(from var(--mygray) l 30 h)`, `lch(62.751923% 30 326.96112)`); 482 376 483 </script> 377 484 -
trunk/Source/WebCore/ChangeLog
r278260 r278261 1 2021-05-30 Sam Weinig <weinig@apple.com> 2 3 Support calc() on components inside relative color syntax colors 4 https://bugs.webkit.org/show_bug.cgi?id=226272 5 6 Reviewed by Darin Adler. 7 8 Added new and updated test cases to fast/css/parsing-relative-color-syntax.html. 9 10 Updates support for the CSS Color 5 "Relative Color Syntax" to support 11 both calc() on components and component permutations within the syntax. 12 13 This allows for things like: 14 15 background: lch(from var(--primary-color) 60% calc(c * 0.8) h); 16 17 or 18 19 background: lch(from rebeccapurple g b r); 20 21 To make this work, the calc() infrastructure now supports passing a CSSCalcSymbolTable 22 which allows the logic in the parser to lookup unknown identifiers when parsing a value. 23 The relative color syntax parsers can then build an appropriate CSSCalcSymbolTable filled 24 with the components of the origin color. 25 26 Since these calc() values are not serialized, this can all happen in the parser, but if 27 we to be able serialize them in the future, CSSCalcPrimitiveValueNode could be updated 28 to store the symbol name in addition to storing the value and type (or we could we could 29 add a new node for it). 30 31 * Sources.txt: 32 * WebCore.xcodeproj/project.pbxproj: 33 * css/calc/CSSCalcSymbolTable.cpp: Added. 34 * css/calc/CSSCalcSymbolTable.h: Added. 35 Add CSSCalcSymbolTable which contains a mapping from CSSValueID to CSSUnitType/double pairs. 36 37 * css/calc/CSSCalcExpressionNodeParser.cpp: 38 (WebCore::CSSCalcExpressionNodeParser::parseValue): 39 When trying to construct a value node, if the token is a identifier, use the new 40 symbol table to look up a type/value to use instead. Use a switch to make things 41 a bit more clear that differentiation is being done based on token type. 42 43 * css/calc/CSSCalcExpressionNodeParser.h: 44 Add reference to a CSSCalcSymbolTable to the parser. The parser should only ever be used 45 on the stack, so this works well and allows us to avoid copying the table. 46 47 * css/calc/CSSCalcValue.cpp: 48 (WebCore::CSSCalcValue::create): 49 * css/calc/CSSCalcValue.h: 50 Pass the CSSCalcSymbolTable to the parser if one is provided. An overload was used 51 to avoid #including CSSCalcSymbolTable.h in the header just to add a default value. 52 53 * css/makevalues.pl: 54 Give a concrete base of uint16_t to allow it to be forward declared and add DefaultHash 55 and HashTraits to allow it to be used with HashTable. These match the definition of 56 CSSPropertyID. 57 58 * css/parser/CSSPropertyParserHelpers.cpp: 59 (WebCore::CSSPropertyParserHelpers::CalcParser::CalcParser): 60 (WebCore::CSSPropertyParserHelpers::consumeNumberRaw): 61 (WebCore::CSSPropertyParserHelpers::consumePercentWorkerSafe): 62 (WebCore::CSSPropertyParserHelpers::consumeAngleRaw): 63 (WebCore::CSSPropertyParserHelpers::consumeAngleWorkerSafe): 64 (WebCore::CSSPropertyParserHelpers::consumeAngleOrPercent): 65 (WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaOrIdent): 66 (WebCore::CSSPropertyParserHelpers::consumeHueOrIdent): 67 (WebCore::CSSPropertyParserHelpers::consumeNumberOrIdent): 68 (WebCore::CSSPropertyParserHelpers::consumePercentOrIdent): 69 (WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentOrIdentNormalizedForRelativeRGB): 70 (WebCore::CSSPropertyParserHelpers::parseRelativeRGBParameters): 71 (WebCore::CSSPropertyParserHelpers::parseRelativeHSLParameters): 72 (WebCore::CSSPropertyParserHelpers::parseRelativeHWBParameters): 73 (WebCore::CSSPropertyParserHelpers::parseRelativeLabParameters): 74 (WebCore::CSSPropertyParserHelpers::parseRelativeLCHParameters): 75 (WebCore::CSSPropertyParserHelpers::extractChannelValue): Deleted. 76 (WebCore::CSSPropertyParserHelpers::resolveRelativeColorChannel): Deleted. 77 Rework relative color syntax parsing to allow permutation of channel symbols 78 and use of the calc() symbol table support to allow passing in the channels. 79 This makes the relatative color syntax variants much closer to the normal 80 variants (with the exception of passing the symbol table) and a subsequent 81 change will attempt to merge them further. 82 1 83 2021-05-30 Dean Jackson <dino@apple.com> 2 84 -
trunk/Source/WebCore/Sources.txt
r278246 r278261 832 832 css/calc/CSSCalcOperationNode.cpp 833 833 css/calc/CSSCalcPrimitiveValueNode.cpp 834 css/calc/CSSCalcSymbolTable.cpp 834 835 css/calc/CSSCalcValue.cpp 835 836 css/parser/CSSAtRuleID.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r278246 r278261 4078 4078 BC6D44ED0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D44EB0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h */; }; 4079 4079 BC6D6E2609AF943500F59759 /* ScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D6E2509AF943500F59759 /* ScrollView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4080 BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */; }; 4080 4081 BC772B3C0C4EA91E0083285F /* CSSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772B360C4EA91E0083285F /* CSSHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4081 4082 BC772C470C4EB2C60083285F /* XMLHttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772C450C4EB2C60083285F /* XMLHttpRequest.h */; }; … … 14305 14306 BC6D6E2509AF943500F59759 /* ScrollView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScrollView.h; sourceTree = "<group>"; }; 14306 14307 BC6EB84526266B61003225A7 /* ColorLuminance.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorLuminance.cpp; sourceTree = "<group>"; }; 14308 BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSCalcSymbolTable.h; sourceTree = "<group>"; }; 14309 BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCalcSymbolTable.cpp; sourceTree = "<group>"; }; 14307 14310 BC772B360C4EA91E0083285F /* CSSHelper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSHelper.h; sourceTree = "<group>"; }; 14308 14311 BC772C440C4EB2C60083285F /* XMLHttpRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = XMLHttpRequest.cpp; sourceTree = "<group>"; }; … … 27957 27960 BCF164542662A1220002F7EF /* CSSCalcPrimitiveValueNode.cpp */, 27958 27961 BCF164532662A1220002F7EF /* CSSCalcPrimitiveValueNode.h */, 27962 BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */, 27963 BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */, 27959 27964 49AE2D8C134EE50C0072920A /* CSSCalcValue.cpp */, 27960 27965 49AE2D8D134EE50C0072920A /* CSSCalcValue.h */, … … 34670 34675 BCAA487014A052530088FAC4 /* PlatformEventFactoryMac.h in Headers */, 34671 34676 A723F77B1484CA4C008C6DBE /* PlatformExportMacros.h in Headers */, 34677 BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */, 34672 34678 515BE1951D54F5FB00DD7C68 /* PlatformGamepad.h in Headers */, 34673 34679 726D56E2253AE28D0002EF90 /* PlatformImage.h in Headers */, -
trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp
r278253 r278261 32 32 #include "CSSCalcOperationNode.h" 33 33 #include "CSSCalcPrimitiveValueNode.h" 34 #include "CSSCalcSymbolTable.h" 34 35 #include "CSSCalcValue.h" 35 36 #include "CSSParserToken.h" 36 37 #include "CSSParserTokenRange.h" 38 #include "CSSValueKeywords.h" 37 39 #include "Logging.h" 38 40 … … 181 183 bool CSSCalcExpressionNodeParser::parseValue(CSSParserTokenRange& tokens, RefPtr<CSSCalcExpressionNode>& result) 182 184 { 183 // FIXME: Add code here to parse CSSValidID for named constants. 184 185 CSSParserToken token = tokens.consumeIncludingWhitespace(); 186 if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken)) 187 return false; 188 189 auto type = token.unitType(); 190 if (calcUnitCategory(type) == CalculationCategory::Other) 191 return false; 192 193 result = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(token.numericValue(), type)); 194 195 return true; 185 auto makeCSSCalcPrimitiveValueNode = [&] (CSSUnitType type, double value) -> bool { 186 if (calcUnitCategory(type) == CalculationCategory::Other) 187 return false; 188 189 result = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(value, type)); 190 return true; 191 }; 192 193 auto token = tokens.consumeIncludingWhitespace(); 194 195 switch (token.type()) { 196 case IdentToken: { 197 auto value = m_symbolTable.get(token.id()); 198 if (!value) 199 return false; 200 return makeCSSCalcPrimitiveValueNode(value->type, value->value); 201 } 202 203 case NumberToken: 204 case PercentageToken: 205 case DimensionToken: 206 return makeCSSCalcPrimitiveValueNode(token.unitType(), token.numericValue()); 207 208 default: 209 return false; 210 } 211 212 ASSERT_NOT_REACHED(); 213 return false; 196 214 } 197 215 -
trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h
r278246 r278261 26 26 #pragma once 27 27 28 #include "CSSValueKeywords.h"29 28 #include "CalcOperator.h" 30 29 #include "CalculationCategory.h" … … 33 32 34 33 class CSSCalcExpressionNode; 34 class CSSCalcSymbolTable; 35 35 class CSSParserToken; 36 36 class CSSParserTokenRange; 37 37 38 enum CSSValueID : uint16_t; 39 38 40 class CSSCalcExpressionNodeParser { 39 41 public: 40 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory )42 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory, const CSSCalcSymbolTable& symbolTable) 41 43 : m_destinationCategory(destinationCategory) 44 , m_symbolTable(symbolTable) 42 45 { 43 46 } … … 56 59 57 60 CalculationCategory m_destinationCategory; 61 const CSSCalcSymbolTable& m_symbolTable; 58 62 }; 59 63 -
trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.cpp
r278260 r278261 24 24 */ 25 25 26 #pragma once 26 #include "config.h" 27 #include "CSSCalcSymbolTable.h" 27 28 28 #include "CSSValueKeywords.h" 29 #include "CalcOperator.h" 30 #include "CalculationCategory.h" 29 #include "CSSUnits.h" 31 30 32 31 namespace WebCore { 33 32 34 class CSSCalcExpressionNode; 35 class CSSParserToken; 36 class CSSParserTokenRange; 33 CSSCalcSymbolTable::CSSCalcSymbolTable(std::initializer_list<std::tuple<CSSValueID, CSSUnitType, double>> initializer) 34 { 35 for (auto& [identifier, type, value] : initializer) 36 m_table.add(identifier, std::make_pair(type, value)); 37 } 37 38 38 class CSSCalcExpressionNodeParser { 39 public: 40 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory) 41 : m_destinationCategory(destinationCategory) 42 { 43 } 39 std::optional<CSSCalcSymbolTable::Value> CSSCalcSymbolTable::get(CSSValueID valueID) const 40 { 41 auto it = m_table.find(valueID); 42 if (it == m_table.end()) 43 return std::nullopt; 44 44 45 RefPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange, CSSValueID function); 46 47 private: 48 char operatorValue(const CSSParserToken&); 49 50 bool parseValue(CSSParserTokenRange&, RefPtr<CSSCalcExpressionNode>&); 51 bool parseValueTerm(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 52 bool parseCalcFunction(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&); 53 bool parseCalcSum(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 54 bool parseCalcProduct(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 55 bool parseCalcValue(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 56 57 CalculationCategory m_destinationCategory; 58 }; 45 return {{ it->value.first, it->value.second }}; 46 } 59 47 60 48 } -
trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.h
r278260 r278261 27 27 28 28 #include "CSSValueKeywords.h" 29 #include "CalcOperator.h"30 #include "CalculationCategory.h"29 #include <wtf/HashMap.h> 30 #include <wtf/Optional.h> 31 31 32 32 namespace WebCore { 33 33 34 class CSSCalcExpressionNode; 35 class CSSParserToken; 36 class CSSParserTokenRange; 34 enum class CSSUnitType : uint8_t; 37 35 38 class CSSCalc ExpressionNodeParser{36 class CSSCalcSymbolTable { 39 37 public: 40 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory)41 : m_destinationCategory(destinationCategory)42 {43 } 38 struct Value { 39 CSSUnitType type; 40 double value; 41 }; 44 42 45 RefPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange, CSSValueID function); 46 43 CSSCalcSymbolTable() = default; 44 CSSCalcSymbolTable(std::initializer_list<std::tuple<CSSValueID, CSSUnitType, double>>); 45 46 std::optional<Value> get(CSSValueID) const; 47 47 48 private: 48 char operatorValue(const CSSParserToken&); 49 50 bool parseValue(CSSParserTokenRange&, RefPtr<CSSCalcExpressionNode>&); 51 bool parseValueTerm(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 52 bool parseCalcFunction(CSSParserTokenRange&, CSSValueID, int depth, RefPtr<CSSCalcExpressionNode>&); 53 bool parseCalcSum(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 54 bool parseCalcProduct(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 55 bool parseCalcValue(CSSParserTokenRange&, int depth, RefPtr<CSSCalcExpressionNode>&); 56 57 CalculationCategory m_destinationCategory; 49 HashMap<CSSValueID, std::pair<CSSUnitType, double>> m_table; 58 50 }; 59 51 60 } 52 }; -
trunk/Source/WebCore/css/calc/CSSCalcValue.cpp
r278246 r278261 41 41 #include "CSSParserTokenRange.h" 42 42 #include "CSSPrimitiveValueMappings.h" 43 #include "CSSValueKeywords.h" 43 44 #include "CalcExpressionBlendLength.h" 44 45 #include "CalcExpressionLength.h" … … 300 301 } 301 302 302 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range )303 { 304 CSSCalcExpressionNodeParser parser(destinationCategory );303 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range, const CSSCalcSymbolTable& symbolTable) 304 { 305 CSSCalcExpressionNodeParser parser(destinationCategory, symbolTable); 305 306 auto expression = parser.parseCalc(tokens, function); 306 307 if (!expression) … … 310 311 return result; 311 312 } 312 313 314 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range) 315 { 316 return create(function, tokens, destinationCategory, range, { }); 317 } 318 313 319 RefPtr<CSSCalcValue> CSSCalcValue::create(const CalculationValue& value, const RenderStyle& style) 314 320 { -
trunk/Source/WebCore/css/calc/CSSCalcValue.h
r278246 r278261 32 32 33 33 #include "CSSValue.h" 34 #include "CSSValueKeywords.h"35 34 #include "CalculationValue.h" 36 35 #include <wtf/Forward.h> … … 40 39 41 40 class CSSCalcExpressionNode; 41 class CSSCalcSymbolTable; 42 42 class CSSParserTokenRange; 43 43 class CSSToLengthConversionData; … … 48 48 enum class ValueRange : uint8_t; 49 49 50 enum CSSValueID : uint16_t; 51 50 52 class CSSCalcValue final : public CSSValue { 51 53 public: 54 static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange, const CSSCalcSymbolTable&); 52 55 static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange); 53 56 static RefPtr<CSSCalcValue> create(const CalculationValue&, const RenderStyle&); -
trunk/Source/WebCore/css/makevalues.pl
r246636 r278261 165 165 #include <string.h> 166 166 #include <wtf/Forward.h> 167 #include <wtf/HashFunctions.h> 168 #include <wtf/HashTraits.h> 167 169 168 170 namespace WebCore { 169 171 170 enum CSSValueID {172 enum CSSValueID : uint16_t { 171 173 CSSValueInvalid = 0, 172 174 EOF … … 205 207 206 208 } // namespace WebCore 209 210 namespace WTF { 211 template<> struct DefaultHash<WebCore::CSSValueID> : IntHash<unsigned> { }; 212 template<> struct HashTraits<WebCore::CSSValueID> : StrongEnumHashTraits<WebCore::CSSValueID> { }; 213 } // namespace WTF 214 207 215 EOF 208 216 close HEADER; -
trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
r278253 r278261 31 31 #include "CSSPropertyParserHelpers.h" 32 32 33 #include "CSSCalcSymbolTable.h" 33 34 #include "CSSCalcValue.h" 34 35 #include "CSSCanvasValue.h" … … 99 100 class CalcParser { 100 101 public: 101 explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, CSSValuePool& cssValuePool = CSSValuePool::singleton())102 explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, const CSSCalcSymbolTable& symbolTable = { }, CSSValuePool& cssValuePool = CSSValuePool::singleton()) 102 103 : m_sourceRange(range) 103 104 , m_range(range) … … 107 108 auto functionId = token.functionId(); 108 109 if (CSSCalcValue::isCalcFunction(functionId)) 109 m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange );110 m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange, symbolTable); 110 111 } 111 112 … … 115 116 { 116 117 if (!m_calcValue) 118 return nullptr; 119 m_sourceRange = m_range; 120 return m_valuePool.createValue(WTFMove(m_calcValue)); 121 } 122 123 RefPtr<CSSPrimitiveValue> consumeValueIfCategory(CalculationCategory category) 124 { 125 if (!m_calcValue || m_calcValue->category() != category) 117 126 return nullptr; 118 127 m_sourceRange = m_range; … … 218 227 219 228 CalcParser calcParser(range, CalculationCategory::Number); 220 if (const CSSCalcValue* calculation = calcParser.value()) { 221 if (calculation->category() != CalculationCategory::Number) 222 return std::nullopt; 229 if (auto calculation = calcParser.value(); calculation && calculation->category() == CalculationCategory::Number) 223 230 return calcParser.consumeIntegerTypeRaw<IntType>(minimumValue); 224 }225 231 226 232 return std::nullopt; … … 273 279 if (token.type() == FunctionToken) { 274 280 CalcParser calcParser(range, CalculationCategory::Number, valueRange); 275 if (const auto* calcValue = calcParser.value()) { 276 if (calcValue->category() == CalculationCategory::Number) 277 return calcParser.consumeValue(); 278 } 279 return nullptr; 281 return calcParser.consumeValueIfCategory(CalculationCategory::Number); 280 282 } 281 283 … … 399 401 if (token.type() == FunctionToken) { 400 402 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 401 if (calcParser.value() && calcParser.value()->category() == CalculationCategory::Length) 402 return calcParser.consumeValue(); 403 return calcParser.consumeValueIfCategory(CalculationCategory::Length); 403 404 } 404 405 … … 434 435 const CSSParserToken& token = range.peek(); 435 436 if (token.type() == FunctionToken) { 436 CalcParser calcParser(range, CalculationCategory::Percent, valueRange, cssValuePool); 437 if (const CSSCalcValue* calculation = calcParser.value()) { 438 if (calculation->category() == CalculationCategory::Percent) 439 return calcParser.consumeValue(); 440 } 441 return nullptr; 437 CalcParser calcParser(range, CalculationCategory::Percent, valueRange, { }, cssValuePool); 438 return calcParser.consumeValueIfCategory(CalculationCategory::Percent); 442 439 } 443 440 … … 480 477 481 478 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 482 if (const CSSCalcValue* calculation = calcParser.value()) { 483 if (canConsumeCalcValue(calculation->category(), cssParserMode)) 484 return calcParser.consumeLengthOrPercentRaw(); 485 } 479 if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode)) 480 return calcParser.consumeLengthOrPercentRaw(); 486 481 return std::nullopt; 487 482 } … … 492 487 if (token.type() == FunctionToken) { 493 488 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 494 if (const CSSCalcValue* calculation = calcParser.value()) { 495 if (canConsumeCalcValue(calculation->category(), cssParserMode)) 496 return calcParser.consumeValue(); 497 } 489 if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode)) 490 return calcParser.consumeValue(); 498 491 return nullptr; 499 492 } … … 544 537 const CSSParserToken& token = range.peek(); 545 538 if (token.type() == FunctionToken) { 546 CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, cssValuePool); 547 if (const CSSCalcValue* calculation = calcParser.value()) { 548 if (calculation->category() == CalculationCategory::Angle) 549 return calcParser.consumeValue(); 550 } 551 return nullptr; 539 CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, { }, cssValuePool); 540 return calcParser.consumeValueIfCategory(CalculationCategory::Angle); 552 541 } 553 542 … … 561 550 { 562 551 const CSSParserToken& token = range.peek(); 563 if (token.type() == DimensionToken) { 552 switch (token.type()) { 553 case DimensionToken: 564 554 switch (token.unitType()) { 565 555 case CSSUnitType::CSS_DEG: … … 569 559 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType()); 570 560 default: 571 return nullptr; 572 } 573 } 574 if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero)) 575 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG); 576 577 if (token.type() == PercentageToken) 561 break; 562 } 563 break; 564 565 case NumberToken: 566 if (shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero)) 567 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG); 568 break; 569 570 case PercentageToken: 578 571 return consumePercent(range, valueRange); 579 572 580 if (token.type() != FunctionToken) 581 return nullptr; 582 583 CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange); 584 if (const CSSCalcValue* calculation = angleCalcParser.value()) { 585 if (calculation->category() == CalculationCategory::Angle) 586 return angleCalcParser.consumeValue(); 587 } 588 589 CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange); 590 if (const CSSCalcValue* calculation = percentCalcParser.value()) { 591 if (calculation->category() == CalculationCategory::Percent) 592 return percentCalcParser.consumeValue(); 593 } 573 case FunctionToken: { 574 CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange); 575 if (const CSSCalcValue* calculation = angleCalcParser.value()) { 576 if (calculation->category() == CalculationCategory::Angle) 577 return angleCalcParser.consumeValue(); 578 } 579 580 CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange); 581 if (const CSSCalcValue* calculation = percentCalcParser.value()) { 582 if (calculation->category() == CalculationCategory::Percent) 583 return percentCalcParser.consumeValue(); 584 } 585 586 break; 587 } 588 589 default: 590 break; 591 } 592 594 593 return nullptr; 595 594 } … … 614 613 615 614 CalcParser calcParser(range, CalculationCategory::Time, valueRange); 616 if (const CSSCalcValue* calculation = calcParser.value()) { 617 if (calculation->category() == CalculationCategory::Time) 618 return calcParser.consumeValue(); 619 } 620 return nullptr; 615 return calcParser.consumeValueIfCategory(CalculationCategory::Time); 621 616 } 622 617 … … 744 739 745 740 if (auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(range)) 746 return clampTo(*alphaParameter, 0.0, 1.0);741 return std::clamp(*alphaParameter, 0.0, 1.0); 747 742 748 743 return std::nullopt; 749 744 } 750 745 751 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range) 752 { 753 if (auto alpha = consumeOptionalAlpha(range)) 754 return { *alpha }; 755 756 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 757 return { *ident }; 758 746 static std::optional<double> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 747 { 748 if (!consumeSlashIncludingWhitespace(range)) 749 return 1.0; 750 751 auto normalizePercent = [](double percent) { 752 return std::clamp(percent / 100.0, 0.0, 1.0); 753 }; 754 755 auto normalizeNumber = [](double alpha) { 756 return std::clamp(alpha, 0.0, 1.0); 757 }; 758 759 const CSSParserToken& token = range.peek(); 760 761 switch (token.type()) { 762 case FunctionToken: { 763 CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 764 if (auto percent = percentageCalcParser.consumePercentRaw()) 765 return normalizePercent(*percent); 766 767 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 768 if (auto number = numberCalcParser.consumeNumberRaw()) 769 return normalizeNumber(*number); 770 771 return std::nullopt; 772 } 773 774 case PercentageToken: 775 if (std::isinf(token.numericValue())) 776 return std::nullopt; 777 return normalizePercent(range.consumeIncludingWhitespace().numericValue()); 778 779 case NumberToken: 780 return normalizeNumber(range.consumeIncludingWhitespace().numericValue()); 781 782 case IdentToken: 783 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 784 switch (variable->type) { 785 case CSSUnitType::CSS_PERCENTAGE: 786 return normalizePercent(variable->value); 787 788 case CSSUnitType::CSS_NUMBER: 789 return normalizeNumber(variable->value); 790 791 default: 792 return std::nullopt; 793 } 794 } 795 return std::nullopt; 796 797 default: 798 return std::nullopt; 799 } 800 801 ASSERT_NOT_REACHED(); 759 802 return std::nullopt; 760 803 } … … 768 811 } 769 812 770 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeHueOrIdent(CSSParserTokenRange& range, const CSSParserContext& context) 771 { 772 if (auto hue = consumeHue(range, context)) 773 return { *hue }; 774 775 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 776 return { *ident }; 777 813 static std::optional<double> consumeHueOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 814 { 815 const CSSParserToken& token = range.peek(); 816 817 switch (token.type()) { 818 case FunctionToken: { 819 CalcParser angleCalcParser(range, CalculationCategory::Angle, ValueRange::All, symbolTable); 820 if (auto angle = angleCalcParser.consumeAngleRaw()) 821 return CSSPrimitiveValue::computeDegrees(angle->type, angle->value); 822 823 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 824 return numberCalcParser.consumeNumberRaw(); 825 } 826 827 case DimensionToken: { 828 auto unitType = token.unitType(); 829 switch (unitType) { 830 case CSSUnitType::CSS_DEG: 831 case CSSUnitType::CSS_RAD: 832 case CSSUnitType::CSS_GRAD: 833 case CSSUnitType::CSS_TURN: 834 return CSSPrimitiveValue::computeDegrees(unitType, range.consumeIncludingWhitespace().numericValue()); 835 default: 836 return std::nullopt; 837 } 838 } 839 840 case NumberToken: 841 return range.consumeIncludingWhitespace().numericValue(); 842 843 case IdentToken: 844 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 845 switch (variable->type) { 846 case CSSUnitType::CSS_DEG: 847 case CSSUnitType::CSS_RAD: 848 case CSSUnitType::CSS_GRAD: 849 case CSSUnitType::CSS_TURN: 850 return CSSPrimitiveValue::computeDegrees(variable->type, variable->value); 851 852 case CSSUnitType::CSS_NUMBER: 853 return variable->value; 854 855 default: 856 return std::nullopt; 857 } 858 } 859 return std::nullopt; 860 861 default: 862 return std::nullopt; 863 } 864 865 ASSERT_NOT_REACHED(); 778 866 return std::nullopt; 779 867 } … … 784 872 } 785 873 786 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeNumberOrIdent(CSSParserTokenRange& range) 787 { 788 if (auto number = consumeNumberRaw(range)) 789 return { *number }; 790 791 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 792 return { *ident }; 793 874 static std::optional<double> consumeNumberOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 875 { 876 const CSSParserToken& token = range.peek(); 877 878 switch (token.type()) { 879 case FunctionToken: { 880 CalcParser calcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 881 return calcParser.consumeNumberRaw(); 882 } 883 884 case NumberToken: 885 return range.consumeIncludingWhitespace().numericValue(); 886 887 case IdentToken: 888 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 889 switch (variable->type) { 890 case CSSUnitType::CSS_NUMBER: 891 return variable->value; 892 893 default: 894 return std::nullopt; 895 } 896 } 897 return std::nullopt; 898 899 default: 900 return std::nullopt; 901 } 902 903 ASSERT_NOT_REACHED(); 794 904 return std::nullopt; 795 905 } 796 906 797 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumePercentOrIdent(CSSParserTokenRange& range) 798 { 799 if (auto percent = consumePercentRaw(range)) 800 return { *percent }; 801 802 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 803 return { *ident }; 804 907 static std::optional<double> consumePercentOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 908 { 909 const CSSParserToken& token = range.peek(); 910 911 switch (token.type()) { 912 case FunctionToken: { 913 CalcParser calcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 914 return calcParser.consumePercentRaw(); 915 } 916 917 case PercentageToken: 918 if (std::isinf(token.numericValue())) 919 return std::nullopt; 920 return range.consumeIncludingWhitespace().numericValue(); 921 922 case IdentToken: 923 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 924 switch (variable->type) { 925 case CSSUnitType::CSS_PERCENTAGE: 926 return variable->value; 927 928 default: 929 return std::nullopt; 930 } 931 } 932 return std::nullopt; 933 934 default: 935 return std::nullopt; 936 } 937 938 ASSERT_NOT_REACHED(); 805 939 return std::nullopt; 806 940 } 807 941 808 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static auto extractChannelValue(CSSValueID channel, const ColorType& originColor) -> typename ColorType::ComponentType 809 { 810 auto components = asColorComponents(originColor); 811 switch (channel) { 812 case C1: 813 return components[0]; 814 case C2: 815 return components[1]; 816 case C3: 817 return components[2]; 818 case AlphaChannel: 819 return components[3]; 942 enum class RGBComponentType { Number, Percentage }; 943 944 static std::optional<uint8_t> consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 945 { 946 auto normalizePercent = [](double percent) { 947 return convertPrescaledSRGBAFloatToSRGBAByte(percent / 100.0 * 255.0); 948 }; 949 950 auto normalizeNumber = [](double number) { 951 return convertPrescaledSRGBAFloatToSRGBAByte(number); 952 }; 953 954 const CSSParserToken& token = range.peek(); 955 956 switch (token.type()) { 957 case FunctionToken: { 958 CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 959 if (auto percent = percentageCalcParser.consumePercentRaw()) 960 return normalizePercent(*percent); 961 962 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 963 if (auto number = numberCalcParser.consumeNumberRaw()) 964 return normalizeNumber(*number); 965 966 return std::nullopt; 967 } 968 969 case PercentageToken: 970 if (std::isinf(token.numericValue())) 971 return std::nullopt; 972 return normalizePercent(range.consumeIncludingWhitespace().numericValue()); 973 974 case NumberToken: 975 return normalizeNumber(range.consumeIncludingWhitespace().numericValue()); 976 977 case IdentToken: 978 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 979 switch (variable->type) { 980 case CSSUnitType::CSS_PERCENTAGE: 981 return normalizePercent(variable->value); 982 983 case CSSUnitType::CSS_NUMBER: 984 return normalizeNumber(variable->value); 985 986 default: 987 return std::nullopt; 988 } 989 } 990 return std::nullopt; 991 820 992 default: 821 ASSERT_NOT_REACHED(); 822 } 823 824 return 0; 825 } 826 827 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) 828 { 829 return switchOn(parsedChannel, 830 [&] (double value) { 831 return valueTransformer(value); 832 }, 833 [&] (CSSValueID channel) { 834 return extractChannelValue<C1, C2, C3, AlphaChannel>(channel, originColor); 835 } 836 ); 837 } 838 839 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor) 840 { 841 return resolveRelativeColorChannel<C1, C2, C3, AlphaChannel>(parsedChannel, originColor, [](auto value) { return value; }); 842 } 843 844 enum class RGBComponentType { Number, Percentage }; 993 return std::nullopt; 994 } 995 996 ASSERT_NOT_REACHED(); 997 return std::nullopt; 998 } 845 999 846 1000 static uint8_t clampRGBComponent(double value, RGBComponentType componentType) … … 922 1076 return { }; 923 1077 924 std::optional<RGBComponentType> componentType; 925 auto redResult = consumeRelativeRGBComponent<CSSValueR>(args, componentType); 926 if (!redResult) 927 return { }; 928 auto red = redResult->value; 929 componentType = redResult->type; 930 931 auto greenResult = consumeRelativeRGBComponent<CSSValueG>(args, componentType); 932 if (!greenResult) 933 return { }; 934 auto green = greenResult->value; 935 componentType = greenResult->type; 936 937 auto blueResult = consumeRelativeRGBComponent<CSSValueB>(args, componentType); 938 if (!blueResult) 939 return { }; 940 auto blue = blueResult->value; 941 componentType = blueResult->type; 942 943 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1078 auto originColorAsSRGB = originColor.toColorTypeLossy<SRGBA<float>>(); 1079 1080 CSSCalcSymbolTable symbolTable { 1081 { CSSValueR, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.red * 100.0 }, 1082 { CSSValueG, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.green * 100.0 }, 1083 { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.blue * 100.0 }, 1084 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.alpha * 100.0 } 1085 }; 1086 1087 auto red = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1088 if (!red) 1089 return { }; 1090 1091 auto green = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1092 if (!green) 1093 return { }; 1094 1095 auto blue = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1096 if (!blue) 1097 return { }; 1098 1099 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 944 1100 if (!alpha) 945 1101 return { }; … … 948 1104 return { }; 949 1105 950 // After parsing, convert identifiers to values from the origin color. 951 952 // FIXME: Do we want to being doing this in uint8_t values? Or should we use 953 // higher precision and clamp at the end? It won't make a difference until we 954 // support calculations on the origin's components. 955 auto originColorAsSRGB = originColor.toSRGBALossy<uint8_t>(); 956 957 auto resolvedComponentType = componentType.value_or(RGBComponentType::Percentage); 958 auto channelResolver = [resolvedComponentType](auto value) { 959 return clampRGBComponent(value, resolvedComponentType); 960 }; 961 962 auto resolvedRed = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(red, originColorAsSRGB, channelResolver); 963 auto resolvedGreen = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(green, originColorAsSRGB, channelResolver); 964 auto resolvedBlue = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(blue, originColorAsSRGB, channelResolver); 965 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(*alpha, originColorAsSRGB, [](auto value) { 966 return convertFloatAlphaTo<uint8_t>(value); 967 }); 968 969 return SRGBA<uint8_t> { resolvedRed, resolvedGreen, resolvedBlue, resolvedAlpha }; 1106 auto normalizedAlpha = convertFloatAlphaTo<uint8_t>(*alpha); 1107 1108 return SRGBA<uint8_t> { *red, *green, *blue, normalizedAlpha }; 970 1109 } 971 1110 … … 1049 1188 return { }; 1050 1189 1051 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1190 auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>(); 1191 1192 CSSCalcSymbolTable symbolTable { 1193 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHSL.hue }, 1194 { CSSValueS, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.saturation }, 1195 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.lightness }, 1196 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.alpha * 100.0 } 1197 }; 1198 1199 auto hue = consumeHueOrIdent(args, symbolTable); 1052 1200 if (!hue) 1053 1201 return { }; 1054 1202 1055 auto saturation = consumePercentOrIdent <CSSValueS>(args);1203 auto saturation = consumePercentOrIdent(args, symbolTable); 1056 1204 if (!saturation) 1057 1205 return { }; 1058 1206 1059 auto lightness = consumePercentOrIdent <CSSValueL>(args);1207 auto lightness = consumePercentOrIdent(args, symbolTable); 1060 1208 if (!lightness) 1061 1209 return { }; 1062 1210 1063 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1211 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1064 1212 if (!alpha) 1065 1213 return { }; … … 1068 1216 return { }; 1069 1217 1070 // After parsing, convert identifiers to values from the origin color. 1071 1072 auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>(); 1073 1074 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*hue, originColorAsHSL, [](auto hue) { 1075 return normalizeHue(hue); 1076 }); 1077 auto resolvedSaturation = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*saturation, originColorAsHSL, [](auto saturation) { 1078 return clampTo(saturation, 0.0, 100.0); 1079 }); 1080 auto resolvedLightness = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*lightness, originColorAsHSL, [](auto lightness) { 1081 return clampTo(lightness, 0.0, 100.0); 1082 }); 1083 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*alpha, originColorAsHSL); 1084 1085 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(resolvedHue), static_cast<float>(resolvedSaturation), static_cast<float>(resolvedLightness), static_cast<float>(resolvedAlpha) }); 1218 auto normalizedHue = normalizeHue(*hue); 1219 auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0); 1220 auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0); 1221 auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0); 1222 1223 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) }); 1086 1224 } 1087 1225 … … 1123 1261 1124 1262 auto normalizedHue = normalizeHue(*hue); 1125 auto normalizedSaturation = clampTo(*saturation, 0.0, 100.0);1126 auto normalizedLightness = clampTo(*lightness, 0.0, 100.0);1127 auto normalizedAlpha = clampTo(*alpha, 0.0, 1.0);1263 auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0); 1264 auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0); 1265 auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0); 1128 1266 1129 1267 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) }); 1130 1268 } 1131 1269 1132 template<typename ComponentType> 1133 struct WhitenessBlackness { 1270 template<typename ComponentType> struct WhitenessBlackness { 1134 1271 ComponentType whiteness; 1135 1272 ComponentType blackness; … … 1165 1302 return { }; 1166 1303 1167 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1304 auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>(); 1305 1306 CSSCalcSymbolTable symbolTable { 1307 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHWB.hue }, 1308 { CSSValueW, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.whiteness }, 1309 { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.blackness }, 1310 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.alpha * 100.0 } 1311 }; 1312 1313 auto hue = consumeHueOrIdent(args, symbolTable); 1168 1314 if (!hue) 1169 1315 return { }; 1170 1316 1171 auto whiteness = consumePercentOrIdent <CSSValueW>(args);1317 auto whiteness = consumePercentOrIdent(args, symbolTable); 1172 1318 if (!whiteness) 1173 1319 return { }; 1174 1320 1175 auto blackness = consumePercentOrIdent <CSSValueB>(args);1321 auto blackness = consumePercentOrIdent(args, symbolTable); 1176 1322 if (!blackness) 1177 1323 return { }; 1178 1324 1179 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1325 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1180 1326 if (!alpha) 1181 1327 return { }; … … 1184 1330 return { }; 1185 1331 1186 // After parsing, convert identifiers to values from the origin color. 1187 1188 auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>(); 1189 1190 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*hue, originColorAsHWB, [](auto hue) { 1191 return normalizeHue(hue); 1192 }); 1193 auto resolvedWhiteness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*whiteness, originColorAsHWB); 1194 auto resolvedBlackness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*blackness, originColorAsHWB); 1195 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*alpha, originColorAsHWB); 1196 1197 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(resolvedWhiteness, resolvedBlackness); 1198 1199 return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(resolvedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(resolvedAlpha) }); 1332 auto normalizedHue = normalizeHue(*hue); 1333 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(*whiteness, *blackness); 1334 1335 return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(*alpha) }); 1200 1336 } 1201 1337 … … 1246 1382 return { }; 1247 1383 1248 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1384 auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>(); 1385 1386 CSSCalcSymbolTable symbolTable { 1387 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.lightness }, 1388 { CSSValueA, CSSUnitType::CSS_NUMBER, originColorAsLab.a }, 1389 { CSSValueB, CSSUnitType::CSS_NUMBER, originColorAsLab.b }, 1390 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.alpha * 100.0 } 1391 }; 1392 1393 auto lightness = consumePercentOrIdent(args, symbolTable); 1249 1394 if (!lightness) 1250 1395 return { }; 1251 1396 1252 auto aValue = consumeNumberOrIdent <CSSValueA>(args);1397 auto aValue = consumeNumberOrIdent(args, symbolTable); 1253 1398 if (!aValue) 1254 1399 return { }; 1255 1400 1256 auto bValue = consumeNumberOrIdent <CSSValueB>(args);1401 auto bValue = consumeNumberOrIdent(args, symbolTable); 1257 1402 if (!bValue) 1258 1403 return { }; 1259 1404 1260 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1405 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1261 1406 if (!alpha) 1262 1407 return { }; … … 1265 1410 return { }; 1266 1411 1267 // After parsing, convert identifiers to values from the origin color. 1268 1269 auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>(); 1270 1271 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*lightness, originColorAsLab, [](auto lightness) { 1272 return std::max(0.0, lightness); 1273 }); 1274 auto resolvedAValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*aValue, originColorAsLab); 1275 auto resolvedBValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*bValue, originColorAsLab); 1276 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*alpha, originColorAsLab); 1277 1278 return Lab<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedAValue), static_cast<float>(resolvedBValue), static_cast<float>(resolvedAlpha) }; 1412 auto normalizedLightness = std::max(0.0, *lightness); 1413 1414 return Lab<float> { static_cast<float>(normalizedLightness), static_cast<float>(*aValue), static_cast<float>(*bValue), static_cast<float>(*alpha) }; 1279 1415 } 1280 1416 … … 1324 1460 return { }; 1325 1461 1326 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1462 auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>(); 1463 1464 CSSCalcSymbolTable symbolTable { 1465 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.lightness }, 1466 { CSSValueC, CSSUnitType::CSS_NUMBER, originColorAsLCH.chroma }, 1467 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsLCH.hue }, 1468 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.alpha * 100.0 } 1469 }; 1470 1471 auto lightness = consumePercentOrIdent(args, symbolTable); 1327 1472 if (!lightness) 1328 1473 return { }; 1329 1474 1330 auto chroma = consumeNumberOrIdent <CSSValueC>(args);1475 auto chroma = consumeNumberOrIdent(args, symbolTable); 1331 1476 if (!chroma) 1332 1477 return { }; 1333 1478 1334 auto hue = consumeHueOrIdent <CSSValueH>(args, context);1479 auto hue = consumeHueOrIdent(args, symbolTable); 1335 1480 if (!hue) 1336 1481 return { }; 1337 1482 1338 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1483 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1339 1484 if (!alpha) 1340 1485 return { }; … … 1343 1488 return { }; 1344 1489 1345 auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>(); 1346 1347 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*lightness, originColorAsLCH, [](auto lightness) { 1348 return std::max(0.0, lightness); 1349 }); 1350 auto resolvedChroma = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*chroma, originColorAsLCH, [](auto chroma) { 1351 return std::max(0.0, chroma); 1352 }); 1353 auto resolvedHue = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*hue, originColorAsLCH, [](auto hue) { 1354 return normalizeHue(hue); 1355 }); 1356 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*alpha, originColorAsLCH); 1357 1358 return LCHA<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedChroma), static_cast<float>(resolvedHue), static_cast<float>(resolvedAlpha) }; 1490 auto normalizedLightness = std::max(0.0, *lightness); 1491 auto normalizedChroma = std::max(0.0, *chroma); 1492 auto normalizedHue = normalizeHue(*hue); 1493 1494 return LCHA<float> { static_cast<float>(normalizedLightness), static_cast<float>(normalizedChroma), static_cast<float>(normalizedHue), static_cast<float>(*alpha) }; 1359 1495 } 1360 1496
Note: See TracChangeset
for help on using the changeset viewer.