Skip to content

Commit 134125d

Browse files
committed
Update relative color parsing to latest spec
1 parent ec6767e commit 134125d

File tree

9 files changed

+282
-181
lines changed

9 files changed

+282
-181
lines changed

src/lib.rs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14312,7 +14312,7 @@ mod tests {
1431214312
}
1431314313

1431414314
test("lab(from indianred calc(l * .8) a b)", "lab(43.1402% 45.7516 23.1557)");
14315-
test("lch(from indianred calc(l + 10%) c h)", "lch(63.9252% 51.2776 26.8448)");
14315+
test("lch(from indianred calc(l + 10) c h)", "lch(63.9252% 51.2776 26.8448)");
1431614316
test("lch(from indianred l calc(c - 50) h)", "lch(53.9252% 1.27763 26.8448)");
1431714317
test(
1431814318
"lch(from indianred l c calc(h + 180deg))",
@@ -14328,12 +14328,23 @@ mod tests {
1432814328
"rgba(205, 92, 92, .7)",
1432914329
);
1433014330
test(
14331-
"rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + 20%))",
14331+
"rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
1433214332
"rgba(205, 92, 92, .7)",
1433314333
);
1433414334
test("lch(from indianred l sin(c) h)", "lch(53.9252% .84797 26.8448)");
1433514335
test("lch(from indianred l sqrt(c) h)", "lch(53.9252% 7.16084 26.8448)");
14336-
test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .990043)");
14336+
test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .451575)");
14337+
test("lch(from indianred calc(10% + 20%) c h)", "lch(30% 51.2776 26.8448)");
14338+
test("lch(from indianred calc(10 + 20) c h)", "lch(30% 51.2776 26.8448)");
14339+
test("lch(from indianred l c calc(10 + 20))", "lch(53.9252% 51.2776 30)");
14340+
test(
14341+
"lch(from indianred l c calc(10deg + 20deg))",
14342+
"lch(53.9252% 51.2776 30)",
14343+
);
14344+
test(
14345+
"lch(from indianred l c calc(10deg + 0.35rad))",
14346+
"lch(53.9252% 51.2776 30.0535)",
14347+
);
1433714348

1433814349
// The following tests were converted from WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-valid.html
1433914350
// Find: test_valid_value\(`color`, `(.*?)`,\s*`(.*?)`\)
@@ -14443,21 +14454,15 @@ mod tests {
1444314454

1444414455
// Testing permutation.
1444514456
test("rgb(from rebeccapurple g b r)", "rgb(51, 153, 102)");
14446-
test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 255, 102, 0.2)");
14447-
test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 0.4)");
14448-
test(
14449-
"rgb(from rebeccapurple alpha alpha alpha / alpha)",
14450-
"rgb(255, 255, 255)",
14451-
);
14457+
test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 1, 102, 1)");
14458+
test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 1)");
14459+
test("rgb(from rebeccapurple alpha alpha alpha / alpha)", "rgb(1, 1, 1)");
1445214460
test("rgb(from rgb(20%, 40%, 60%, 80%) g b r)", "rgb(102, 153, 51)");
14453-
test(
14454-
"rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)",
14455-
"rgba(153, 204, 51, 0.4)",
14456-
);
14457-
test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 0.2)");
14461+
test("rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)", "rgba(153, 1, 51, 1)");
14462+
test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 1)");
1445814463
test(
1445914464
"rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)",
14460-
"rgba(204, 204, 204, 0.8)",
14465+
"rgba(1, 1, 1, 0.8)",
1446114466
);
1446214467

1446314468
// Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
@@ -15182,23 +15187,31 @@ mod tests {
1518215187
// NOTE: 'c' is a vaild hue, as hue is <angle>|<number>.
1518315188
test(
1518415189
&format!("{}(from {}(70% 45 30) alpha c h / l)", color_space, color_space),
15185-
&format!("{}(100% 45 30 / 0.7)", color_space),
15190+
&format!(
15191+
"{}(1 45 30 / {})",
15192+
color_space,
15193+
if *color_space == "lch" { "1" } else { ".7" }
15194+
),
1518615195
);
1518715196
test(
1518815197
&format!("{}(from {}(70% 45 30) l c c / alpha)", color_space, color_space),
1518915198
&format!("{}(70% 45 45)", color_space),
1519015199
);
1519115200
test(
1519215201
&format!("{}(from {}(70% 45 30) alpha c h / alpha)", color_space, color_space),
15193-
&format!("{}(100% 45 30)", color_space),
15202+
&format!("{}(1 45 30)", color_space),
1519415203
);
1519515204
test(
1519615205
&format!("{}(from {}(70% 45 30) alpha c c / alpha)", color_space, color_space),
15197-
&format!("{}(100% 45 45)", color_space),
15206+
&format!("{}(1 45 45)", color_space),
1519815207
);
1519915208
test(
1520015209
&format!("{}(from {}(70% 45 30 / 40%) alpha c h / l)", color_space, color_space),
15201-
&format!("{}(40% 45 30 / 0.7)", color_space),
15210+
&format!(
15211+
"{}(.4 45 30 / {})",
15212+
color_space,
15213+
if *color_space == "lch" { "1" } else { ".7" }
15214+
),
1520215215
);
1520315216
test(
1520415217
&format!("{}(from {}(70% 45 30 / 40%) l c c / alpha)", color_space, color_space),
@@ -15209,14 +15222,14 @@ mod tests {
1520915222
"{}(from {}(70% 45 30 / 40%) alpha c h / alpha)",
1521015223
color_space, color_space
1521115224
),
15212-
&format!("{}(40% 45 30 / 0.4)", color_space),
15225+
&format!("{}(.4 45 30 / 0.4)", color_space),
1521315226
);
1521415227
test(
1521515228
&format!(
1521615229
"{}(from {}(70% 45 30 / 40%) alpha c c / alpha)",
1521715230
color_space, color_space
1521815231
),
15219-
&format!("{}(40% 45 45 / 0.4)", color_space),
15232+
&format!("{}(.4 45 45 / 0.4)", color_space),
1522015233
);
1522115234

1522215235
// Testing with calc().
@@ -16084,7 +16097,7 @@ mod tests {
1608416097
);
1608516098
minify_test(
1608616099
".foo{color:hsl(from rebeccapurple alpha alpha alpha / alpha)}",
16087-
".foo{color:hsl(from rebeccapurple alpha alpha alpha/alpha)}",
16100+
".foo{color:#fff}",
1608816101
);
1608916102
}
1609016103
}

src/properties/custom.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,21 +1479,16 @@ impl<'i> UnresolvedColor<'i> {
14791479
where
14801480
W: std::fmt::Write,
14811481
{
1482-
#[inline]
1483-
fn c(c: &f32) -> i32 {
1484-
(c * 255.0).round().clamp(0.0, 255.0) as i32
1485-
}
1486-
14871482
match self {
14881483
UnresolvedColor::RGB { r, g, b, alpha } => {
14891484
if let Some(targets) = dest.targets {
14901485
if !compat::Feature::SpaceSeparatedColorFunction.is_compatible(targets) {
14911486
dest.write_str("rgba(")?;
1492-
c(r).to_css(dest)?;
1487+
r.to_css(dest)?;
14931488
dest.delim(',', false)?;
1494-
c(g).to_css(dest)?;
1489+
g.to_css(dest)?;
14951490
dest.delim(',', false)?;
1496-
c(b).to_css(dest)?;
1491+
b.to_css(dest)?;
14971492
dest.delim(',', false)?;
14981493
alpha.to_css(dest, is_custom_property)?;
14991494
dest.write_char(')')?;
@@ -1502,11 +1497,11 @@ impl<'i> UnresolvedColor<'i> {
15021497
}
15031498

15041499
dest.write_str("rgb(")?;
1505-
c(r).to_css(dest)?;
1500+
r.to_css(dest)?;
15061501
dest.write_char(' ')?;
1507-
c(g).to_css(dest)?;
1502+
g.to_css(dest)?;
15081503
dest.write_char(' ')?;
1509-
c(b).to_css(dest)?;
1504+
b.to_css(dest)?;
15101505
dest.delim('/', true)?;
15111506
alpha.to_css(dest, is_custom_property)?;
15121507
dest.write_char(')')

src/values/angle.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,13 @@ impl Into<Calc<Angle>> for Angle {
182182
}
183183
}
184184

185-
impl From<Calc<Angle>> for Angle {
186-
fn from(calc: Calc<Angle>) -> Angle {
185+
impl TryFrom<Calc<Angle>> for Angle {
186+
type Error = ();
187+
188+
fn try_from(calc: Calc<Angle>) -> Result<Angle, ()> {
187189
match calc {
188-
Calc::Value(v) => *v,
189-
_ => unreachable!(),
190+
Calc::Value(v) => Ok(*v),
191+
_ => Err(()),
190192
}
191193
}
192194
}
@@ -284,6 +286,13 @@ macro_rules! impl_try_from_angle {
284286
Err(())
285287
}
286288
}
289+
290+
impl TryInto<crate::values::angle::Angle> for $t {
291+
type Error = ();
292+
fn try_into(self) -> Result<crate::values::angle::Angle, Self::Error> {
293+
Err(())
294+
}
295+
}
287296
};
288297
}
289298

src/values/calc.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,9 @@ impl<
267267
+ TrySign
268268
+ std::cmp::PartialOrd<V>
269269
+ Into<Calc<V>>
270-
+ From<Calc<V>>
270+
+ TryFrom<Calc<V>>
271271
+ TryFrom<Angle>
272+
+ TryInto<Angle>
272273
+ Clone
273274
+ std::fmt::Debug,
274275
> Parse<'i> for Calc<V>
@@ -288,8 +289,9 @@ impl<
288289
+ TrySign
289290
+ std::cmp::PartialOrd<V>
290291
+ Into<Calc<V>>
291-
+ From<Calc<V>>
292+
+ TryFrom<Calc<V>>
292293
+ TryFrom<Angle>
294+
+ TryInto<Angle>
293295
+ Clone
294296
+ std::fmt::Debug,
295297
> Calc<V>
@@ -501,12 +503,12 @@ impl<
501503
match *input.next()? {
502504
Token::Delim('+') => {
503505
let next = Calc::parse_product(input, parse_ident)?;
504-
cur = cur.add(next);
506+
cur = cur.add(next).map_err(|_| input.new_custom_error(ParserError::InvalidValue))?;
505507
}
506508
Token::Delim('-') => {
507509
let mut rhs = Calc::parse_product(input, parse_ident)?;
508510
rhs = rhs * -1.0;
509-
cur = cur.add(rhs);
511+
cur = cur.add(rhs).map_err(|_| input.new_custom_error(ParserError::InvalidValue))?;
510512
}
511513
ref t => {
512514
let t = t.clone();
@@ -695,9 +697,12 @@ impl<
695697
) -> Result<Self, ParseError<'i, ParserError<'i>>> {
696698
input.parse_nested_block(|input| {
697699
let v: Calc<Angle> = Calc::parse_sum(input, |v| {
698-
parse_ident(v).and_then(|v| match v {
699-
Calc::Number(v) => Some(Calc::Number(v)),
700-
_ => None,
700+
parse_ident(v).and_then(|v| -> Option<Calc<Angle>> {
701+
match v {
702+
Calc::Number(v) => Some(Calc::Number(v)),
703+
Calc::Value(v) => (*v).try_into().ok().map(|v| Calc::Value(Box::new(v))),
704+
_ => None,
705+
}
701706
})
702707
})?;
703708
let rad = match v {
@@ -854,19 +859,17 @@ impl<V: std::ops::Mul<f32, Output = V>> std::ops::Mul<f32> for Calc<V> {
854859
}
855860
}
856861

857-
impl<V: AddInternal + std::convert::Into<Calc<V>> + std::convert::From<Calc<V>> + std::fmt::Debug> AddInternal
858-
for Calc<V>
859-
{
860-
fn add(self, other: Calc<V>) -> Calc<V> {
861-
match (self, other) {
862+
impl<V: AddInternal + std::convert::Into<Calc<V>> + std::convert::TryFrom<Calc<V>> + std::fmt::Debug> Calc<V> {
863+
pub(crate) fn add(self, other: Calc<V>) -> Result<Calc<V>, <V as TryFrom<Calc<V>>>::Error> {
864+
Ok(match (self, other) {
862865
(Calc::Value(a), Calc::Value(b)) => (a.add(*b)).into(),
863866
(Calc::Number(a), Calc::Number(b)) => Calc::Number(a + b),
864-
(Calc::Value(a), b) => (a.add(V::from(b))).into(),
865-
(a, Calc::Value(b)) => (V::from(a).add(*b)).into(),
867+
(Calc::Value(a), b) => (a.add(V::try_from(b)?)).into(),
868+
(a, Calc::Value(b)) => (V::try_from(a)?.add(*b)).into(),
866869
(Calc::Function(a), b) => Calc::Sum(Box::new(Calc::Function(a)), Box::new(b)),
867870
(a, Calc::Function(b)) => Calc::Sum(Box::new(a), Box::new(Calc::Function(b))),
868-
(a, b) => V::from(a).add(V::from(b)).into(),
869-
}
871+
(a, b) => V::try_from(a)?.add(V::try_from(b)?).into(),
872+
})
870873
}
871874
}
872875

0 commit comments

Comments
 (0)