1use super::prelude::*;
2use crate::{AngleOrNumber, NoneOr, NumberOrPercentage};
3
4#[derive(Parse, Peek, IntoCursor, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
6#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
7pub enum ColorSpace {
8 #[atom(CssAtomSet::Srgb)]
9 Srgb(T![Ident]),
10 #[atom(CssAtomSet::SrgbLinear)]
11 SrgbLinear(T![Ident]),
12 #[atom(CssAtomSet::DisplayP3)]
13 DisplayP3(T![Ident]),
14 #[atom(CssAtomSet::A98Rgb)]
15 A98Rgb(T![Ident]),
16 #[atom(CssAtomSet::ProphotoRgb)]
17 ProphotoRgb(T![Ident]),
18 #[atom(CssAtomSet::Rec2020)]
19 Rec2020(T![Ident]),
20 #[atom(CssAtomSet::Xyz)]
21 Xyz(T![Ident]),
22 #[atom(CssAtomSet::XyzD50)]
23 XyzD50(T![Ident]),
24 #[atom(CssAtomSet::XyzD65)]
25 XyzD65(T![Ident]),
26}
27
28#[derive(IntoCursor, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
30#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
31pub struct CommaOrSlash(Cursor);
32
33impl<'a> Peek<'a> for CommaOrSlash {
34 fn peek<I>(_: &Parser<'a, I>, c: Cursor) -> bool
35 where
36 I: Iterator<Item = Cursor> + Clone,
37 {
38 c == ',' || c == '/'
39 }
40}
41
42impl<'a> Parse<'a> for CommaOrSlash {
43 fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
44 where
45 I: Iterator<Item = Cursor> + Clone,
46 {
47 if !p.peek::<Self>() {
48 Err(Diagnostic::new(p.next(), Diagnostic::unexpected))?
49 }
50 Ok(Self(p.next()))
51 }
52}
53
54#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
56#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
57#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
58pub enum ColorFunction {
59 Color(ColorFunctionColor),
60 Rgb(RgbFunction),
61 Rgba(RgbaFunction),
62 Hsl(HslFunction),
63 Hsla(HslaFunction),
64 Hwb(HwbFunction),
65 Lab(LabFunction),
66 Lch(LchFunction),
67 Oklab(OklabFunction),
68 Oklch(OklchFunction),
69}
70
71#[cfg(feature = "chromashift")]
72impl crate::ToChromashift for ColorFunction {
73 fn to_chromashift(&self) -> Option<chromashift::Color> {
74 match self {
75 Self::Color(c) => c.to_chromashift(),
76 Self::Rgb(c) => c.to_chromashift(),
77 Self::Rgba(c) => c.to_chromashift(),
78 Self::Hsl(c) => c.to_chromashift(),
79 Self::Hsla(c) => c.to_chromashift(),
80 Self::Hwb(c) => c.to_chromashift(),
81 Self::Lab(c) => c.to_chromashift(),
82 Self::Lch(c) => c.to_chromashift(),
83 Self::Oklab(c) => c.to_chromashift(),
84 Self::Oklch(c) => c.to_chromashift(),
85 }
86 }
87}
88
89#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
100#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
101#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
102pub struct ColorFunctionColor {
103 #[atom(CssAtomSet::Color)]
104 pub name: T![Function],
105 pub params: ColorFunctionColorParams,
106 pub close: T![')'],
107}
108
109#[cfg(feature = "chromashift")]
110impl crate::ToChromashift for ColorFunctionColor {
111 fn to_chromashift(&self) -> Option<chromashift::Color> {
112 todo!();
113 }
114}
115
116#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
118#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
119pub struct ColorFunctionColorParams(
120 pub ColorSpace,
121 pub NoneOr<NumberOrPercentage>,
122 pub NoneOr<NumberOrPercentage>,
123 pub NoneOr<NumberOrPercentage>,
124 pub Option<T![/]>,
125 pub Option<NoneOr<NumberOrPercentage>>,
126);
127
128#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
146#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
147pub struct RgbFunction {
148 #[atom(CssAtomSet::Rgb)]
149 pub name: T![Function],
150 pub params: RgbFunctionParams,
151 pub close: T![')'],
152}
153
154#[cfg(feature = "chromashift")]
155impl crate::ToChromashift for RgbFunction {
156 fn to_chromashift(&self) -> Option<chromashift::Color> {
157 self.params.to_chromashift()
158 }
159}
160
161#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
162#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
163#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
164pub struct RgbaFunction {
165 #[atom(CssAtomSet::Rgba)]
166 pub name: T![Function],
167 pub params: RgbFunctionParams,
168 pub close: T![')'],
169}
170
171#[cfg(feature = "chromashift")]
172impl crate::ToChromashift for RgbaFunction {
173 fn to_chromashift(&self) -> Option<chromashift::Color> {
174 self.params.to_chromashift()
175 }
176}
177
178#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
180#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
181pub struct RgbFunctionParams(
182 pub NoneOr<NumberOrPercentage>,
183 pub Option<T![,]>,
184 pub NoneOr<NumberOrPercentage>,
185 pub Option<T![,]>,
186 pub NoneOr<NumberOrPercentage>,
187 pub Option<CommaOrSlash>,
188 pub Option<NoneOr<NumberOrPercentage>>,
189);
190
191#[cfg(feature = "chromashift")]
192impl crate::ToChromashift for RgbFunctionParams {
193 fn to_chromashift(&self) -> Option<chromashift::Color> {
194 use chromashift::Srgb;
195 let Self(red, _, green, _, blue, _, alpha) = &self;
196 let alpha = match alpha {
197 Some(NoneOr::None(_)) => 0.0,
198 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
199 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
200 None => 100.0,
201 };
202 let red = match red {
203 NoneOr::None(_) => {
204 return None;
205 }
206 NoneOr::Some(NumberOrPercentage::Number(red)) => red.value(),
207 NoneOr::Some(NumberOrPercentage::Percentage(red)) => red.value() / 100.0 * 255.0,
208 } as u8;
209 let green = match green {
210 NoneOr::None(_) => {
211 return None;
212 }
213 NoneOr::Some(NumberOrPercentage::Number(green)) => green.value(),
214 NoneOr::Some(NumberOrPercentage::Percentage(green)) => green.value() / 100.0 * 255.0,
215 } as u8;
216 let blue = match blue {
217 NoneOr::None(_) => {
218 return None;
219 }
220 NoneOr::Some(NumberOrPercentage::Number(blue)) => blue.value(),
221 NoneOr::Some(NumberOrPercentage::Percentage(blue)) => blue.value() / 100.0 * 255.0,
222 } as u8;
223 Some(chromashift::Color::Srgb(Srgb::new(red, green, blue, alpha)))
224 }
225}
226
227#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
246#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
247#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
248pub struct HslFunction {
249 #[atom(CssAtomSet::Hsl)]
250 pub name: T![Function],
251 pub params: HslFunctionParams,
252 pub close: T![')'],
253}
254
255#[cfg(feature = "chromashift")]
256impl crate::ToChromashift for HslFunction {
257 fn to_chromashift(&self) -> Option<chromashift::Color> {
258 self.params.to_chromashift()
259 }
260}
261
262#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
263#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
264#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
265pub struct HslaFunction {
266 #[atom(CssAtomSet::Hsla)]
267 pub name: T![Function],
268 pub params: HslFunctionParams,
269 pub close: T![')'],
270}
271
272#[cfg(feature = "chromashift")]
273impl crate::ToChromashift for HslaFunction {
274 fn to_chromashift(&self) -> Option<chromashift::Color> {
275 self.params.to_chromashift()
276 }
277}
278
279#[derive(Parse, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
280#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
281#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
282pub struct HslFunctionParams(
283 pub NoneOr<AngleOrNumber>,
284 pub Option<T![,]>,
285 pub NoneOr<NumberOrPercentage>,
286 pub Option<T![,]>,
287 pub NoneOr<NumberOrPercentage>,
288 pub Option<CommaOrSlash>,
289 pub Option<NoneOr<NumberOrPercentage>>,
290);
291
292#[cfg(feature = "chromashift")]
293impl crate::ToChromashift for HslFunctionParams {
294 fn to_chromashift(&self) -> Option<chromashift::Color> {
295 use chromashift::Hsl;
296 let Self(hue, _, saturation, _, lightness, _, alpha) = &self;
297 let hue = match hue {
298 NoneOr::None(_) => {
299 return None;
300 }
301 NoneOr::Some(AngleOrNumber::Number(hue)) => hue.value(),
302 NoneOr::Some(AngleOrNumber::Angle(d)) => d.as_degrees(),
303 };
304 let saturation = match saturation {
305 NoneOr::None(_) => {
306 return None;
307 }
308 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
309 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
310 };
311 let lightness = match lightness {
312 NoneOr::None(_) => {
313 return None;
314 }
315 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
316 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
317 };
318 let alpha = match alpha {
319 Some(NoneOr::None(_)) => 0.0,
320 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
321 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
322 None => 100.0,
323 };
324 Some(chromashift::Color::Hsl(Hsl::new(hue, saturation, lightness, alpha)))
325 }
326}
327
328#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
335#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
336#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
337pub struct HwbFunction {
338 #[atom(CssAtomSet::Hwb)]
339 pub name: T![Function],
340 pub params: HwbFunctionParams,
341 pub close: T![')'],
342}
343
344#[cfg(feature = "chromashift")]
345impl crate::ToChromashift for HwbFunction {
346 fn to_chromashift(&self) -> Option<chromashift::Color> {
347 use chromashift::Hwb;
348 let HwbFunctionParams(hue, whiteness, blackness, _, alpha) = &self.params;
349 let hue = match hue {
350 NoneOr::None(_) => {
351 return None;
352 }
353 NoneOr::Some(AngleOrNumber::Number(hue)) => hue.value(),
354 NoneOr::Some(AngleOrNumber::Angle(d)) => d.as_degrees(),
355 };
356 let whiteness = match whiteness {
357 NoneOr::None(_) => {
358 return None;
359 }
360 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
361 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
362 };
363 let blackness = match blackness {
364 NoneOr::None(_) => {
365 return None;
366 }
367 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
368 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
369 };
370 let alpha = match alpha {
371 Some(NoneOr::None(_)) => 0.0,
372 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
373 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
374 None => 100.0,
375 };
376 Some(chromashift::Color::Hwb(Hwb::new(hue, whiteness, blackness, alpha)))
377 }
378}
379
380#[derive(Parse, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
381#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
382#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
383pub struct HwbFunctionParams(
384 pub NoneOr<AngleOrNumber>,
385 pub NoneOr<NumberOrPercentage>,
386 pub NoneOr<NumberOrPercentage>,
387 pub Option<T![/]>,
388 pub Option<NoneOr<NumberOrPercentage>>,
389);
390
391#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
400#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
401#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
402pub struct LabFunction {
403 #[atom(CssAtomSet::Lab)]
404 pub name: T![Function],
405 pub params: LabFunctionParams,
406 pub close: T![')'],
407}
408
409#[cfg(feature = "chromashift")]
410impl crate::ToChromashift for LabFunction {
411 fn to_chromashift(&self) -> Option<chromashift::Color> {
412 use chromashift::Lab;
413 let LabFunctionParams(l, a, b, _, alpha) = &self.params;
414 let l = match l {
415 NoneOr::None(_) => {
416 return None;
417 }
418 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
419 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
420 } as f64;
421 let a = match a {
422 NoneOr::None(_) => {
423 return None;
424 }
425 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
426 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 125.0,
427 } as f64;
428 let b = match b {
429 NoneOr::None(_) => {
430 return None;
431 }
432 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
433 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 125.0,
434 } as f64;
435 let alpha = match alpha {
436 Some(NoneOr::None(_)) => 0.0,
437 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
438 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
439 None => 100.0,
440 };
441 Some(chromashift::Color::Lab(Lab::new(l, a, b, alpha)))
442 }
443}
444
445#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
446#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
447#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
448pub struct LabFunctionParams(
449 pub NoneOr<NumberOrPercentage>,
450 pub NoneOr<NumberOrPercentage>,
451 pub NoneOr<NumberOrPercentage>,
452 pub Option<T![/]>,
453 pub Option<NoneOr<NumberOrPercentage>>,
454);
455
456#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
465#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
466#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
467pub struct LchFunction {
468 #[atom(CssAtomSet::Lch)]
469 pub name: T![Function],
470 pub params: LchFunctionParams,
471 pub close: T![')'],
472}
473
474#[cfg(feature = "chromashift")]
475impl crate::ToChromashift for LchFunction {
476 fn to_chromashift(&self) -> Option<chromashift::Color> {
477 use chromashift::Lch;
478 let LchFunctionParams(lightness, chroma, hue, _, alpha) = &self.params;
479 let lightness = match lightness {
480 NoneOr::None(_) => {
481 return None;
482 }
483 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
484 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
485 } as f64;
486 let chroma = match chroma {
487 NoneOr::None(_) => {
488 return None;
489 }
490 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
491 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 150.0,
492 } as f64;
493 let hue = match hue {
494 NoneOr::None(_) => {
495 return None;
496 }
497 NoneOr::Some(AngleOrNumber::Number(hue)) => hue.value(),
498 NoneOr::Some(AngleOrNumber::Angle(d)) => d.as_degrees(),
499 } as f64;
500 let alpha = match alpha {
501 Some(NoneOr::None(_)) => 0.0,
502 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
503 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
504 None => 100.0,
505 };
506 Some(chromashift::Color::Lch(Lch::new(lightness, chroma, hue, alpha)))
507 }
508}
509
510#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
511#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
512#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
513pub struct LchFunctionParams(
514 pub NoneOr<NumberOrPercentage>,
515 pub NoneOr<NumberOrPercentage>,
516 pub NoneOr<AngleOrNumber>,
517 pub Option<T![/]>,
518 pub Option<NoneOr<NumberOrPercentage>>,
519);
520
521#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
530#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
531#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
532pub struct OklabFunction {
533 #[atom(CssAtomSet::Oklab)]
534 pub name: T![Function],
535 pub params: LabFunctionParams,
536 pub close: T![')'],
537}
538
539#[cfg(feature = "chromashift")]
540impl crate::ToChromashift for OklabFunction {
541 fn to_chromashift(&self) -> Option<chromashift::Color> {
542 use chromashift::Oklab;
543 let LabFunctionParams(l, a, b, _, alpha) = &self.params;
544 let alpha = match alpha {
545 Some(NoneOr::None(_)) => 0.0,
546 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
547 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
548 None => 100.0,
549 };
550 let l = match l {
551 NoneOr::None(_) => {
552 return None;
553 }
554 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
555 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0,
556 } as f64;
557 let a = match a {
558 NoneOr::None(_) => {
559 return None;
560 }
561 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
562 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 0.4,
563 } as f64;
564 let b = match b {
565 NoneOr::None(_) => {
566 return None;
567 }
568 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
569 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 0.4,
570 } as f64;
571 Some(chromashift::Color::Oklab(Oklab::new(l, a, b, alpha)))
572 }
573}
574
575#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
584#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
585#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
586pub struct OklchFunction {
587 #[atom(CssAtomSet::Oklch)]
588 pub name: T![Function],
589 pub params: LchFunctionParams,
590 pub close: T![')'],
591}
592
593#[cfg(feature = "chromashift")]
594impl crate::ToChromashift for OklchFunction {
595 fn to_chromashift(&self) -> Option<chromashift::Color> {
596 use chromashift::Oklch;
597 let LchFunctionParams(lightness, chroma, hue, _, alpha) = &self.params;
598 let lightness = match lightness {
599 NoneOr::None(_) => {
600 return None;
601 }
602 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
603 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value(),
604 } as f64;
605 let chroma = match chroma {
606 NoneOr::None(_) => {
607 return None;
608 }
609 NoneOr::Some(NumberOrPercentage::Number(n)) => n.value(),
610 NoneOr::Some(NumberOrPercentage::Percentage(p)) => p.value() / 100.0 * 150.0,
611 } as f64;
612 let hue = match hue {
613 NoneOr::None(_) => {
614 return None;
615 }
616 NoneOr::Some(AngleOrNumber::Number(hue)) => hue.value(),
617 NoneOr::Some(AngleOrNumber::Angle(d)) => d.as_degrees(),
618 } as f64;
619 let alpha = match alpha {
620 Some(NoneOr::None(_)) => 0.0,
621 Some(NoneOr::Some(NumberOrPercentage::Number(t))) => t.value() * 100.0,
622 Some(NoneOr::Some(NumberOrPercentage::Percentage(t))) => t.value(),
623 None => 100.0,
624 };
625 Some(chromashift::Color::Oklch(Oklch::new(lightness, chroma, hue, alpha)))
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use super::*;
632
633 #[test]
634 fn size_test() {
635 assert_eq!(std::mem::size_of::<ColorFunction>(), 140);
636 assert_eq!(std::mem::size_of::<ColorFunctionColor>(), 120);
637 assert_eq!(std::mem::size_of::<RgbFunction>(), 136);
638 assert_eq!(std::mem::size_of::<RgbaFunction>(), 136);
639 assert_eq!(std::mem::size_of::<HslFunction>(), 136);
640 assert_eq!(std::mem::size_of::<HslaFunction>(), 136);
641 assert_eq!(std::mem::size_of::<HwbFunction>(), 104);
642 assert_eq!(std::mem::size_of::<LabFunction>(), 104);
643 assert_eq!(std::mem::size_of::<LchFunction>(), 104);
644 assert_eq!(std::mem::size_of::<OklabFunction>(), 104);
645 assert_eq!(std::mem::size_of::<OklchFunction>(), 104);
646 }
647}