Changeset 278304 in webkit
- Timestamp:
- Jun 1, 2021 6:50:16 AM (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) (2 diffs)
-
Source/WebCore/css/calc/CSSCalcValue.h (modified) (2 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
r278297 r278304 1 2021-06-01 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-31 Diego Pino Garcia <dpino@igalia.com> 2 15 -
trunk/LayoutTests/fast/css/parsing-relative-color-syntax-expected.txt
r278290 r278304 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
r278290 r278304 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
r278303 r278304 1 2021-06-01 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-06-01 Alan Bujtas <zalan@apple.com> 2 84 -
trunk/Source/WebCore/Sources.txt
r278290 r278304 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
r278292 r278304 4080 4080 BC6D44ED0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D44EB0C07F2ED0072D2C9 /* JSHTMLEmbedElement.h */; }; 4081 4081 BC6D6E2609AF943500F59759 /* ScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6D6E2509AF943500F59759 /* ScrollView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4082 BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */; }; 4082 4083 BC772B3C0C4EA91E0083285F /* CSSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772B360C4EA91E0083285F /* CSSHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4083 4084 BC772C470C4EB2C60083285F /* XMLHttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = BC772C450C4EB2C60083285F /* XMLHttpRequest.h */; }; … … 14309 14310 BC6D6E2509AF943500F59759 /* ScrollView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScrollView.h; sourceTree = "<group>"; }; 14310 14311 BC6EB84526266B61003225A7 /* ColorLuminance.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorLuminance.cpp; sourceTree = "<group>"; }; 14312 BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSCalcSymbolTable.h; sourceTree = "<group>"; }; 14313 BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCalcSymbolTable.cpp; sourceTree = "<group>"; }; 14311 14314 BC772B360C4EA91E0083285F /* CSSHelper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSHelper.h; sourceTree = "<group>"; }; 14312 14315 BC772C440C4EB2C60083285F /* XMLHttpRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = XMLHttpRequest.cpp; sourceTree = "<group>"; }; … … 27963 27966 BCF164542662A1220002F7EF /* CSSCalcPrimitiveValueNode.cpp */, 27964 27967 BCF164532662A1220002F7EF /* CSSCalcPrimitiveValueNode.h */, 27968 BC709DDF266323CE00B9A21C /* CSSCalcSymbolTable.cpp */, 27969 BC709DDE266323CE00B9A21C /* CSSCalcSymbolTable.h */, 27965 27970 49AE2D8C134EE50C0072920A /* CSSCalcValue.cpp */, 27966 27971 49AE2D8D134EE50C0072920A /* CSSCalcValue.h */, … … 34677 34682 BCAA487014A052530088FAC4 /* PlatformEventFactoryMac.h in Headers */, 34678 34683 A723F77B1484CA4C008C6DBE /* PlatformExportMacros.h in Headers */, 34684 BC709DE0266323CF00B9A21C /* CSSCalcSymbolTable.h in Headers */, 34679 34685 515BE1951D54F5FB00DD7C68 /* PlatformGamepad.h in Headers */, 34680 34686 726D56E2253AE28D0002EF90 /* PlatformImage.h in Headers */, -
trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp
r278290 r278304 32 32 #include "CSSCalcOperationNode.h" 33 33 #include "CSSCalcPrimitiveValueNode.h" 34 #include "CSSCalcSymbolTable.h" 34 35 #include "CSSCalcValue.h" 35 36 #include "CSSParserToken.h" … … 181 182 bool CSSCalcExpressionNodeParser::parseValue(CSSParserTokenRange& tokens, RefPtr<CSSCalcExpressionNode>& result) 182 183 { 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; 184 auto makeCSSCalcPrimitiveValueNode = [&] (CSSUnitType type, double value) -> bool { 185 if (calcUnitCategory(type) == CalculationCategory::Other) 186 return false; 187 188 result = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(value, type)); 189 return true; 190 }; 191 192 auto token = tokens.consumeIncludingWhitespace(); 193 194 switch (token.type()) { 195 case IdentToken: { 196 auto value = m_symbolTable.get(token.id()); 197 if (!value) 198 return false; 199 return makeCSSCalcPrimitiveValueNode(value->type, value->value); 200 } 201 202 case NumberToken: 203 case PercentageToken: 204 case DimensionToken: 205 return makeCSSCalcPrimitiveValueNode(token.unitType(), token.numericValue()); 206 207 default: 208 return false; 209 } 210 211 ASSERT_NOT_REACHED(); 212 return false; 196 213 } 197 214 -
trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.h
r278290 r278304 33 33 34 34 class CSSCalcExpressionNode; 35 class CSSCalcSymbolTable; 35 36 class CSSParserToken; 36 37 class CSSParserTokenRange; … … 38 39 class CSSCalcExpressionNodeParser { 39 40 public: 40 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory )41 explicit CSSCalcExpressionNodeParser(CalculationCategory destinationCategory, const CSSCalcSymbolTable& symbolTable) 41 42 : m_destinationCategory(destinationCategory) 43 , m_symbolTable(symbolTable) 42 44 { 43 45 } … … 56 58 57 59 CalculationCategory m_destinationCategory; 60 const CSSCalcSymbolTable& m_symbolTable; 58 61 }; 59 62 -
trunk/Source/WebCore/css/calc/CSSCalcSymbolTable.cpp
r278303 r278304 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
r278303 r278304 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
r278291 r278304 304 304 } 305 305 306 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range )307 { 308 CSSCalcExpressionNodeParser parser(destinationCategory );306 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range, const CSSCalcSymbolTable& symbolTable) 307 { 308 CSSCalcExpressionNodeParser parser(destinationCategory, symbolTable); 309 309 auto expression = parser.parseCalc(tokens, function); 310 310 if (!expression) … … 314 314 return result; 315 315 } 316 316 317 RefPtr<CSSCalcValue> CSSCalcValue::create(CSSValueID function, const CSSParserTokenRange& tokens, CalculationCategory destinationCategory, ValueRange range) 318 { 319 return create(function, tokens, destinationCategory, range, { }); 320 } 321 317 322 RefPtr<CSSCalcValue> CSSCalcValue::create(const CalculationValue& value, const RenderStyle& style) 318 323 { -
trunk/Source/WebCore/css/calc/CSSCalcValue.h
r278290 r278304 40 40 41 41 class CSSCalcExpressionNode; 42 class CSSCalcSymbolTable; 42 43 class CSSParserTokenRange; 43 44 class CSSToLengthConversionData; … … 50 51 class CSSCalcValue final : public CSSValue { 51 52 public: 53 static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange, const CSSCalcSymbolTable&); 52 54 static RefPtr<CSSCalcValue> create(CSSValueID function, const CSSParserTokenRange&, CalculationCategory destinationCategory, ValueRange); 53 55 static RefPtr<CSSCalcValue> create(const CalculationValue&, const RenderStyle&); -
trunk/Source/WebCore/css/makevalues.pl
r278290 r278304 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 { … … 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
r278290 r278304 31 31 #include "CSSPropertyParserHelpers.h" 32 32 33 #include "CSSCalcSymbolTable.h" 33 34 #include "CSSCalcValue.h" 34 35 #include "CSSCanvasValue.h" … … 100 101 class CalcParser { 101 102 public: 102 explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, CSSValuePool& cssValuePool = CSSValuePool::singleton())103 explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, const CSSCalcSymbolTable& symbolTable = { }, CSSValuePool& cssValuePool = CSSValuePool::singleton()) 103 104 : m_sourceRange(range) 104 105 , m_range(range) … … 108 109 auto functionId = token.functionId(); 109 110 if (CSSCalcValue::isCalcFunction(functionId)) 110 m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange );111 m_calcValue = CSSCalcValue::create(functionId, consumeFunction(m_range), destinationCategory, valueRange, symbolTable); 111 112 } 112 113 … … 116 117 { 117 118 if (!m_calcValue) 119 return nullptr; 120 m_sourceRange = m_range; 121 return m_valuePool.createValue(WTFMove(m_calcValue)); 122 } 123 124 RefPtr<CSSPrimitiveValue> consumeValueIfCategory(CalculationCategory category) 125 { 126 if (!m_calcValue || m_calcValue->category() != category) 118 127 return nullptr; 119 128 m_sourceRange = m_range; … … 219 228 220 229 CalcParser calcParser(range, CalculationCategory::Number); 221 if (const CSSCalcValue* calculation = calcParser.value()) { 222 if (calculation->category() != CalculationCategory::Number) 223 return std::nullopt; 230 if (auto calculation = calcParser.value(); calculation && calculation->category() == CalculationCategory::Number) 224 231 return calcParser.consumeIntegerTypeRaw<IntType>(minimumValue); 225 }226 232 227 233 return std::nullopt; … … 274 280 if (token.type() == FunctionToken) { 275 281 CalcParser calcParser(range, CalculationCategory::Number, valueRange); 276 if (const auto* calcValue = calcParser.value()) { 277 if (calcValue->category() == CalculationCategory::Number) 278 return calcParser.consumeValue(); 279 } 280 return nullptr; 282 return calcParser.consumeValueIfCategory(CalculationCategory::Number); 281 283 } 282 284 … … 400 402 if (token.type() == FunctionToken) { 401 403 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 402 if (calcParser.value() && calcParser.value()->category() == CalculationCategory::Length) 403 return calcParser.consumeValue(); 404 return calcParser.consumeValueIfCategory(CalculationCategory::Length); 404 405 } 405 406 … … 435 436 const CSSParserToken& token = range.peek(); 436 437 if (token.type() == FunctionToken) { 437 CalcParser calcParser(range, CalculationCategory::Percent, valueRange, cssValuePool); 438 if (const CSSCalcValue* calculation = calcParser.value()) { 439 if (calculation->category() == CalculationCategory::Percent) 440 return calcParser.consumeValue(); 441 } 442 return nullptr; 438 CalcParser calcParser(range, CalculationCategory::Percent, valueRange, { }, cssValuePool); 439 return calcParser.consumeValueIfCategory(CalculationCategory::Percent); 443 440 } 444 441 … … 481 478 482 479 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 483 if (const CSSCalcValue* calculation = calcParser.value()) { 484 if (canConsumeCalcValue(calculation->category(), cssParserMode)) 485 return calcParser.consumeLengthOrPercentRaw(); 486 } 480 if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode)) 481 return calcParser.consumeLengthOrPercentRaw(); 487 482 return std::nullopt; 488 483 } … … 493 488 if (token.type() == FunctionToken) { 494 489 CalcParser calcParser(range, CalculationCategory::Length, valueRange); 495 if (const CSSCalcValue* calculation = calcParser.value()) { 496 if (canConsumeCalcValue(calculation->category(), cssParserMode)) 497 return calcParser.consumeValue(); 498 } 490 if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode)) 491 return calcParser.consumeValue(); 499 492 return nullptr; 500 493 } … … 545 538 const CSSParserToken& token = range.peek(); 546 539 if (token.type() == FunctionToken) { 547 CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, cssValuePool); 548 if (const CSSCalcValue* calculation = calcParser.value()) { 549 if (calculation->category() == CalculationCategory::Angle) 550 return calcParser.consumeValue(); 551 } 552 return nullptr; 540 CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, { }, cssValuePool); 541 return calcParser.consumeValueIfCategory(CalculationCategory::Angle); 553 542 } 554 543 … … 562 551 { 563 552 const CSSParserToken& token = range.peek(); 564 if (token.type() == DimensionToken) { 553 switch (token.type()) { 554 case DimensionToken: 565 555 switch (token.unitType()) { 566 556 case CSSUnitType::CSS_DEG: … … 570 560 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType()); 571 561 default: 572 return nullptr; 573 } 574 } 575 if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero)) 576 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG); 577 578 if (token.type() == PercentageToken) 562 break; 563 } 564 break; 565 566 case NumberToken: 567 if (shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero)) 568 return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG); 569 break; 570 571 case PercentageToken: 579 572 return consumePercent(range, valueRange); 580 573 581 if (token.type() != FunctionToken) 582 return nullptr; 583 584 CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange); 585 if (const CSSCalcValue* calculation = angleCalcParser.value()) { 586 if (calculation->category() == CalculationCategory::Angle) 587 return angleCalcParser.consumeValue(); 588 } 589 590 CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange); 591 if (const CSSCalcValue* calculation = percentCalcParser.value()) { 592 if (calculation->category() == CalculationCategory::Percent) 593 return percentCalcParser.consumeValue(); 594 } 574 case FunctionToken: { 575 CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange); 576 if (const CSSCalcValue* calculation = angleCalcParser.value()) { 577 if (calculation->category() == CalculationCategory::Angle) 578 return angleCalcParser.consumeValue(); 579 } 580 581 CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange); 582 if (const CSSCalcValue* calculation = percentCalcParser.value()) { 583 if (calculation->category() == CalculationCategory::Percent) 584 return percentCalcParser.consumeValue(); 585 } 586 587 break; 588 } 589 590 default: 591 break; 592 } 593 595 594 return nullptr; 596 595 } … … 615 614 616 615 CalcParser calcParser(range, CalculationCategory::Time, valueRange); 617 if (const CSSCalcValue* calculation = calcParser.value()) { 618 if (calculation->category() == CalculationCategory::Time) 619 return calcParser.consumeValue(); 620 } 621 return nullptr; 616 return calcParser.consumeValueIfCategory(CalculationCategory::Time); 622 617 } 623 618 … … 745 740 746 741 if (auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(range)) 747 return clampTo(*alphaParameter, 0.0, 1.0);742 return std::clamp(*alphaParameter, 0.0, 1.0); 748 743 749 744 return std::nullopt; 750 745 } 751 746 752 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range) 753 { 754 if (auto alpha = consumeOptionalAlpha(range)) 755 return { *alpha }; 756 757 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 758 return { *ident }; 759 747 static std::optional<double> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 748 { 749 if (!consumeSlashIncludingWhitespace(range)) 750 return 1.0; 751 752 auto normalizePercent = [](double percent) { 753 return std::clamp(percent / 100.0, 0.0, 1.0); 754 }; 755 756 auto normalizeNumber = [](double alpha) { 757 return std::clamp(alpha, 0.0, 1.0); 758 }; 759 760 const CSSParserToken& token = range.peek(); 761 762 switch (token.type()) { 763 case FunctionToken: { 764 CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 765 if (auto percent = percentageCalcParser.consumePercentRaw()) 766 return normalizePercent(*percent); 767 768 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 769 if (auto number = numberCalcParser.consumeNumberRaw()) 770 return normalizeNumber(*number); 771 772 return std::nullopt; 773 } 774 775 case PercentageToken: 776 if (std::isinf(token.numericValue())) 777 return std::nullopt; 778 return normalizePercent(range.consumeIncludingWhitespace().numericValue()); 779 780 case NumberToken: 781 return normalizeNumber(range.consumeIncludingWhitespace().numericValue()); 782 783 case IdentToken: 784 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 785 switch (variable->type) { 786 case CSSUnitType::CSS_PERCENTAGE: 787 return normalizePercent(variable->value); 788 789 case CSSUnitType::CSS_NUMBER: 790 return normalizeNumber(variable->value); 791 792 default: 793 return std::nullopt; 794 } 795 } 796 return std::nullopt; 797 798 default: 799 return std::nullopt; 800 } 801 802 ASSERT_NOT_REACHED(); 760 803 return std::nullopt; 761 804 } … … 769 812 } 770 813 771 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeHueOrIdent(CSSParserTokenRange& range, const CSSParserContext& context) 772 { 773 if (auto hue = consumeHue(range, context)) 774 return { *hue }; 775 776 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 777 return { *ident }; 778 814 static std::optional<double> consumeHueOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 815 { 816 const CSSParserToken& token = range.peek(); 817 818 switch (token.type()) { 819 case FunctionToken: { 820 CalcParser angleCalcParser(range, CalculationCategory::Angle, ValueRange::All, symbolTable); 821 if (auto angle = angleCalcParser.consumeAngleRaw()) 822 return CSSPrimitiveValue::computeDegrees(angle->type, angle->value); 823 824 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 825 return numberCalcParser.consumeNumberRaw(); 826 } 827 828 case DimensionToken: { 829 auto unitType = token.unitType(); 830 switch (unitType) { 831 case CSSUnitType::CSS_DEG: 832 case CSSUnitType::CSS_RAD: 833 case CSSUnitType::CSS_GRAD: 834 case CSSUnitType::CSS_TURN: 835 return CSSPrimitiveValue::computeDegrees(unitType, range.consumeIncludingWhitespace().numericValue()); 836 default: 837 return std::nullopt; 838 } 839 } 840 841 case NumberToken: 842 return range.consumeIncludingWhitespace().numericValue(); 843 844 case IdentToken: 845 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 846 switch (variable->type) { 847 case CSSUnitType::CSS_DEG: 848 case CSSUnitType::CSS_RAD: 849 case CSSUnitType::CSS_GRAD: 850 case CSSUnitType::CSS_TURN: 851 return CSSPrimitiveValue::computeDegrees(variable->type, variable->value); 852 853 case CSSUnitType::CSS_NUMBER: 854 return variable->value; 855 856 default: 857 return std::nullopt; 858 } 859 } 860 return std::nullopt; 861 862 default: 863 return std::nullopt; 864 } 865 866 ASSERT_NOT_REACHED(); 779 867 return std::nullopt; 780 868 } … … 785 873 } 786 874 787 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumeNumberOrIdent(CSSParserTokenRange& range) 788 { 789 if (auto number = consumeNumberRaw(range)) 790 return { *number }; 791 792 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 793 return { *ident }; 794 875 static std::optional<double> consumeNumberOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 876 { 877 const CSSParserToken& token = range.peek(); 878 879 switch (token.type()) { 880 case FunctionToken: { 881 CalcParser calcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 882 return calcParser.consumeNumberRaw(); 883 } 884 885 case NumberToken: 886 return range.consumeIncludingWhitespace().numericValue(); 887 888 case IdentToken: 889 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 890 switch (variable->type) { 891 case CSSUnitType::CSS_NUMBER: 892 return variable->value; 893 894 default: 895 return std::nullopt; 896 } 897 } 898 return std::nullopt; 899 900 default: 901 return std::nullopt; 902 } 903 904 ASSERT_NOT_REACHED(); 795 905 return std::nullopt; 796 906 } 797 907 798 template<CSSValueID... allowedIdents> static std::optional<Variant<double, CSSValueID>> consumePercentOrIdent(CSSParserTokenRange& range) 799 { 800 if (auto percent = consumePercentRaw(range)) 801 return { *percent }; 802 803 if (auto ident = consumeIdentRaw<allowedIdents...>(range)) 804 return { *ident }; 805 908 static std::optional<double> consumePercentOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 909 { 910 const CSSParserToken& token = range.peek(); 911 912 switch (token.type()) { 913 case FunctionToken: { 914 CalcParser calcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 915 return calcParser.consumePercentRaw(); 916 } 917 918 case PercentageToken: 919 if (std::isinf(token.numericValue())) 920 return std::nullopt; 921 return range.consumeIncludingWhitespace().numericValue(); 922 923 case IdentToken: 924 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 925 switch (variable->type) { 926 case CSSUnitType::CSS_PERCENTAGE: 927 return variable->value; 928 929 default: 930 return std::nullopt; 931 } 932 } 933 return std::nullopt; 934 935 default: 936 return std::nullopt; 937 } 938 939 ASSERT_NOT_REACHED(); 806 940 return std::nullopt; 807 941 } 808 942 809 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static auto extractChannelValue(CSSValueID channel, const ColorType& originColor) -> typename ColorType::ComponentType 810 { 811 auto components = asColorComponents(originColor); 812 switch (channel) { 813 case C1: 814 return components[0]; 815 case C2: 816 return components[1]; 817 case C3: 818 return components[2]; 819 case AlphaChannel: 820 return components[3]; 943 enum class RGBComponentType { Number, Percentage }; 944 945 static std::optional<uint8_t> consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 946 { 947 auto normalizePercent = [](double percent) { 948 return convertPrescaledSRGBAFloatToSRGBAByte(percent / 100.0 * 255.0); 949 }; 950 951 auto normalizeNumber = [](double number) { 952 return convertPrescaledSRGBAFloatToSRGBAByte(number); 953 }; 954 955 const CSSParserToken& token = range.peek(); 956 957 switch (token.type()) { 958 case FunctionToken: { 959 CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable); 960 if (auto percent = percentageCalcParser.consumePercentRaw()) 961 return normalizePercent(*percent); 962 963 CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable); 964 if (auto number = numberCalcParser.consumeNumberRaw()) 965 return normalizeNumber(*number); 966 967 return std::nullopt; 968 } 969 970 case PercentageToken: 971 if (std::isinf(token.numericValue())) 972 return std::nullopt; 973 return normalizePercent(range.consumeIncludingWhitespace().numericValue()); 974 975 case NumberToken: 976 return normalizeNumber(range.consumeIncludingWhitespace().numericValue()); 977 978 case IdentToken: 979 if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) { 980 switch (variable->type) { 981 case CSSUnitType::CSS_PERCENTAGE: 982 return normalizePercent(variable->value); 983 984 case CSSUnitType::CSS_NUMBER: 985 return normalizeNumber(variable->value); 986 987 default: 988 return std::nullopt; 989 } 990 } 991 return std::nullopt; 992 821 993 default: 822 ASSERT_NOT_REACHED(); 823 } 824 825 return 0; 826 } 827 828 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) 829 { 830 return switchOn(parsedChannel, 831 [&] (double value) { 832 return valueTransformer(value); 833 }, 834 [&] (CSSValueID channel) { 835 return extractChannelValue<C1, C2, C3, AlphaChannel>(channel, originColor); 836 } 837 ); 838 } 839 840 template<CSSValueID C1, CSSValueID C2, CSSValueID C3, CSSValueID AlphaChannel, typename ColorType> static decltype(auto) resolveRelativeColorChannel(const Variant<double, CSSValueID>& parsedChannel, const ColorType& originColor) 841 { 842 return resolveRelativeColorChannel<C1, C2, C3, AlphaChannel>(parsedChannel, originColor, [](auto value) { return value; }); 843 } 844 845 enum class RGBComponentType { Number, Percentage }; 994 return std::nullopt; 995 } 996 997 ASSERT_NOT_REACHED(); 998 return std::nullopt; 999 } 846 1000 847 1001 static uint8_t clampRGBComponent(double value, RGBComponentType componentType) … … 923 1077 return { }; 924 1078 925 std::optional<RGBComponentType> componentType; 926 auto redResult = consumeRelativeRGBComponent<CSSValueR>(args, componentType); 927 if (!redResult) 928 return { }; 929 auto red = redResult->value; 930 componentType = redResult->type; 931 932 auto greenResult = consumeRelativeRGBComponent<CSSValueG>(args, componentType); 933 if (!greenResult) 934 return { }; 935 auto green = greenResult->value; 936 componentType = greenResult->type; 937 938 auto blueResult = consumeRelativeRGBComponent<CSSValueB>(args, componentType); 939 if (!blueResult) 940 return { }; 941 auto blue = blueResult->value; 942 componentType = blueResult->type; 943 944 auto alpha = consumeOptionalAlphaOrIdent<CSSValueAlpha>(args); 1079 auto originColorAsSRGB = originColor.toColorTypeLossy<SRGBA<float>>(); 1080 1081 CSSCalcSymbolTable symbolTable { 1082 { CSSValueR, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.red * 100.0 }, 1083 { CSSValueG, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.green * 100.0 }, 1084 { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.blue * 100.0 }, 1085 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsSRGB.alpha * 100.0 } 1086 }; 1087 1088 auto red = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1089 if (!red) 1090 return { }; 1091 1092 auto green = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1093 if (!green) 1094 return { }; 1095 1096 auto blue = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable); 1097 if (!blue) 1098 return { }; 1099 1100 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 945 1101 if (!alpha) 946 1102 return { }; … … 949 1105 return { }; 950 1106 951 // After parsing, convert identifiers to values from the origin color. 952 953 // FIXME: Do we want to being doing this in uint8_t values? Or should we use 954 // higher precision and clamp at the end? It won't make a difference until we 955 // support calculations on the origin's components. 956 auto originColorAsSRGB = originColor.toSRGBALossy<uint8_t>(); 957 958 auto resolvedComponentType = componentType.value_or(RGBComponentType::Percentage); 959 auto channelResolver = [resolvedComponentType](auto value) { 960 return clampRGBComponent(value, resolvedComponentType); 961 }; 962 963 auto resolvedRed = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(red, originColorAsSRGB, channelResolver); 964 auto resolvedGreen = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(green, originColorAsSRGB, channelResolver); 965 auto resolvedBlue = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(blue, originColorAsSRGB, channelResolver); 966 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueR, CSSValueG, CSSValueB, CSSValueAlpha>(*alpha, originColorAsSRGB, [](auto value) { 967 return convertFloatAlphaTo<uint8_t>(value); 968 }); 969 970 return SRGBA<uint8_t> { resolvedRed, resolvedGreen, resolvedBlue, resolvedAlpha }; 1107 auto normalizedAlpha = convertFloatAlphaTo<uint8_t>(*alpha); 1108 1109 return SRGBA<uint8_t> { *red, *green, *blue, normalizedAlpha }; 971 1110 } 972 1111 … … 1050 1189 return { }; 1051 1190 1052 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1191 auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>(); 1192 1193 CSSCalcSymbolTable symbolTable { 1194 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHSL.hue }, 1195 { CSSValueS, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.saturation }, 1196 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.lightness }, 1197 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHSL.alpha * 100.0 } 1198 }; 1199 1200 auto hue = consumeHueOrIdent(args, symbolTable); 1053 1201 if (!hue) 1054 1202 return { }; 1055 1203 1056 auto saturation = consumePercentOrIdent <CSSValueS>(args);1204 auto saturation = consumePercentOrIdent(args, symbolTable); 1057 1205 if (!saturation) 1058 1206 return { }; 1059 1207 1060 auto lightness = consumePercentOrIdent <CSSValueL>(args);1208 auto lightness = consumePercentOrIdent(args, symbolTable); 1061 1209 if (!lightness) 1062 1210 return { }; 1063 1211 1064 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1212 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1065 1213 if (!alpha) 1066 1214 return { }; … … 1069 1217 return { }; 1070 1218 1071 // After parsing, convert identifiers to values from the origin color. 1072 1073 auto originColorAsHSL = originColor.toColorTypeLossy<HSLA<float>>(); 1074 1075 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*hue, originColorAsHSL, [](auto hue) { 1076 return normalizeHue(hue); 1077 }); 1078 auto resolvedSaturation = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*saturation, originColorAsHSL, [](auto saturation) { 1079 return clampTo(saturation, 0.0, 100.0); 1080 }); 1081 auto resolvedLightness = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*lightness, originColorAsHSL, [](auto lightness) { 1082 return clampTo(lightness, 0.0, 100.0); 1083 }); 1084 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueS, CSSValueL, CSSValueAlpha>(*alpha, originColorAsHSL); 1085 1086 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(resolvedHue), static_cast<float>(resolvedSaturation), static_cast<float>(resolvedLightness), static_cast<float>(resolvedAlpha) }); 1219 auto normalizedHue = normalizeHue(*hue); 1220 auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0); 1221 auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0); 1222 auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0); 1223 1224 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) }); 1087 1225 } 1088 1226 … … 1124 1262 1125 1263 auto normalizedHue = normalizeHue(*hue); 1126 auto normalizedSaturation = clampTo(*saturation, 0.0, 100.0);1127 auto normalizedLightness = clampTo(*lightness, 0.0, 100.0);1128 auto normalizedAlpha = clampTo(*alpha, 0.0, 1.0);1264 auto normalizedSaturation = std::clamp(*saturation, 0.0, 100.0); 1265 auto normalizedLightness = std::clamp(*lightness, 0.0, 100.0); 1266 auto normalizedAlpha = std::clamp(*alpha, 0.0, 1.0); 1129 1267 1130 1268 return convertColor<SRGBA<uint8_t>>(HSLA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedSaturation), static_cast<float>(normalizedLightness), static_cast<float>(normalizedAlpha) }); 1131 1269 } 1132 1270 1133 template<typename ComponentType> 1134 struct WhitenessBlackness { 1271 template<typename ComponentType> struct WhitenessBlackness { 1135 1272 ComponentType whiteness; 1136 1273 ComponentType blackness; … … 1166 1303 return { }; 1167 1304 1168 auto hue = consumeHueOrIdent<CSSValueH>(args, context); 1305 auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>(); 1306 1307 CSSCalcSymbolTable symbolTable { 1308 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsHWB.hue }, 1309 { CSSValueW, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.whiteness }, 1310 { CSSValueB, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.blackness }, 1311 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsHWB.alpha * 100.0 } 1312 }; 1313 1314 auto hue = consumeHueOrIdent(args, symbolTable); 1169 1315 if (!hue) 1170 1316 return { }; 1171 1317 1172 auto whiteness = consumePercentOrIdent <CSSValueW>(args);1318 auto whiteness = consumePercentOrIdent(args, symbolTable); 1173 1319 if (!whiteness) 1174 1320 return { }; 1175 1321 1176 auto blackness = consumePercentOrIdent <CSSValueB>(args);1322 auto blackness = consumePercentOrIdent(args, symbolTable); 1177 1323 if (!blackness) 1178 1324 return { }; 1179 1325 1180 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1326 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1181 1327 if (!alpha) 1182 1328 return { }; … … 1185 1331 return { }; 1186 1332 1187 // After parsing, convert identifiers to values from the origin color. 1188 1189 auto originColorAsHWB = originColor.toColorTypeLossy<HWBA<float>>(); 1190 1191 auto resolvedHue = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*hue, originColorAsHWB, [](auto hue) { 1192 return normalizeHue(hue); 1193 }); 1194 auto resolvedWhiteness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*whiteness, originColorAsHWB); 1195 auto resolvedBlackness = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*blackness, originColorAsHWB); 1196 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueH, CSSValueW, CSSValueB, CSSValueAlpha>(*alpha, originColorAsHWB); 1197 1198 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(resolvedWhiteness, resolvedBlackness); 1199 1200 return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(resolvedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(resolvedAlpha) }); 1333 auto normalizedHue = normalizeHue(*hue); 1334 auto [normalizedWhitness, normalizedBlackness] = normalizeWhitenessBlackness(*whiteness, *blackness); 1335 1336 return convertColor<SRGBA<uint8_t>>(HWBA<float> { static_cast<float>(normalizedHue), static_cast<float>(normalizedWhitness), static_cast<float>(normalizedBlackness), static_cast<float>(*alpha) }); 1201 1337 } 1202 1338 … … 1247 1383 return { }; 1248 1384 1249 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1385 auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>(); 1386 1387 CSSCalcSymbolTable symbolTable { 1388 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.lightness }, 1389 { CSSValueA, CSSUnitType::CSS_NUMBER, originColorAsLab.a }, 1390 { CSSValueB, CSSUnitType::CSS_NUMBER, originColorAsLab.b }, 1391 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLab.alpha * 100.0 } 1392 }; 1393 1394 auto lightness = consumePercentOrIdent(args, symbolTable); 1250 1395 if (!lightness) 1251 1396 return { }; 1252 1397 1253 auto aValue = consumeNumberOrIdent <CSSValueA>(args);1398 auto aValue = consumeNumberOrIdent(args, symbolTable); 1254 1399 if (!aValue) 1255 1400 return { }; 1256 1401 1257 auto bValue = consumeNumberOrIdent <CSSValueB>(args);1402 auto bValue = consumeNumberOrIdent(args, symbolTable); 1258 1403 if (!bValue) 1259 1404 return { }; 1260 1405 1261 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1406 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1262 1407 if (!alpha) 1263 1408 return { }; … … 1266 1411 return { }; 1267 1412 1268 // After parsing, convert identifiers to values from the origin color. 1269 1270 auto originColorAsLab = originColor.toColorTypeLossy<Lab<float>>(); 1271 1272 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*lightness, originColorAsLab, [](auto lightness) { 1273 return std::max(0.0, lightness); 1274 }); 1275 auto resolvedAValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*aValue, originColorAsLab); 1276 auto resolvedBValue = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*bValue, originColorAsLab); 1277 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueA, CSSValueB, CSSValueAlpha>(*alpha, originColorAsLab); 1278 1279 return Lab<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedAValue), static_cast<float>(resolvedBValue), static_cast<float>(resolvedAlpha) }; 1413 auto normalizedLightness = std::max(0.0, *lightness); 1414 1415 return Lab<float> { static_cast<float>(normalizedLightness), static_cast<float>(*aValue), static_cast<float>(*bValue), static_cast<float>(*alpha) }; 1280 1416 } 1281 1417 … … 1325 1461 return { }; 1326 1462 1327 auto lightness = consumePercentOrIdent<CSSValueL>(args); 1463 auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>(); 1464 1465 CSSCalcSymbolTable symbolTable { 1466 { CSSValueL, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.lightness }, 1467 { CSSValueC, CSSUnitType::CSS_NUMBER, originColorAsLCH.chroma }, 1468 { CSSValueH, CSSUnitType::CSS_DEG, originColorAsLCH.hue }, 1469 { CSSValueAlpha, CSSUnitType::CSS_PERCENTAGE, originColorAsLCH.alpha * 100.0 } 1470 }; 1471 1472 auto lightness = consumePercentOrIdent(args, symbolTable); 1328 1473 if (!lightness) 1329 1474 return { }; 1330 1475 1331 auto chroma = consumeNumberOrIdent <CSSValueC>(args);1476 auto chroma = consumeNumberOrIdent(args, symbolTable); 1332 1477 if (!chroma) 1333 1478 return { }; 1334 1479 1335 auto hue = consumeHueOrIdent <CSSValueH>(args, context);1480 auto hue = consumeHueOrIdent(args, symbolTable); 1336 1481 if (!hue) 1337 1482 return { }; 1338 1483 1339 auto alpha = consumeOptionalAlphaOrIdent <CSSValueAlpha>(args);1484 auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable); 1340 1485 if (!alpha) 1341 1486 return { }; … … 1344 1489 return { }; 1345 1490 1346 auto originColorAsLCH = originColor.toColorTypeLossy<LCHA<float>>(); 1347 1348 auto resolvedLightness = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*lightness, originColorAsLCH, [](auto lightness) { 1349 return std::max(0.0, lightness); 1350 }); 1351 auto resolvedChroma = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*chroma, originColorAsLCH, [](auto chroma) { 1352 return std::max(0.0, chroma); 1353 }); 1354 auto resolvedHue = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*hue, originColorAsLCH, [](auto hue) { 1355 return normalizeHue(hue); 1356 }); 1357 auto resolvedAlpha = resolveRelativeColorChannel<CSSValueL, CSSValueC, CSSValueH, CSSValueAlpha>(*alpha, originColorAsLCH); 1358 1359 return LCHA<float> { static_cast<float>(resolvedLightness), static_cast<float>(resolvedChroma), static_cast<float>(resolvedHue), static_cast<float>(resolvedAlpha) }; 1491 auto normalizedLightness = std::max(0.0, *lightness); 1492 auto normalizedChroma = std::max(0.0, *chroma); 1493 auto normalizedHue = normalizeHue(*hue); 1494 1495 return LCHA<float> { static_cast<float>(normalizedLightness), static_cast<float>(normalizedChroma), static_cast<float>(normalizedHue), static_cast<float>(*alpha) }; 1360 1496 } 1361 1497
Note: See TracChangeset
for help on using the changeset viewer.