1use super::prelude::*;
2
3#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
10#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.types.angle"))]
11#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
12#[derive(csskit_derives::NodeWithMetadata)]
13#[metadata(node_kinds = Dimension)]
14pub enum Angle {
15 #[atom(CssAtomSet::Grad)]
16 Grad(T![Dimension]),
17 #[atom(CssAtomSet::Rad)]
18 Rad(T![Dimension]),
19 #[atom(CssAtomSet::Turn)]
20 Turn(T![Dimension]),
21 #[atom(CssAtomSet::Deg)]
22 Deg(T![Dimension]),
23}
24
25impl From<Angle> for f32 {
26 fn from(val: Angle) -> Self {
27 match val {
28 Angle::Grad(f) => f.into(),
29 Angle::Rad(f) => f.into(),
30 Angle::Turn(f) => f.into(),
31 Angle::Deg(f) => f.into(),
32 }
33 }
34}
35
36impl ToNumberValue for Angle {
37 fn to_number_value(&self) -> Option<f32> {
38 Some((*self).into())
39 }
40}
41
42impl Angle {
43 const DEG_GRAD: f32 = 0.9;
44 const DEG_RAD: f32 = 57.295_78;
45 const DEG_TURN: f32 = 360.0;
46
47 pub fn as_degrees(&self) -> f32 {
48 match self {
49 Self::Grad(d) => Into::<f32>::into(*d) * Self::DEG_GRAD,
50 Self::Rad(d) => Into::<f32>::into(*d) * Self::DEG_RAD,
51 Self::Turn(d) => Into::<f32>::into(*d) * Self::DEG_TURN,
52 Self::Deg(d) => (*d).into(),
53 }
54 }
55}
56
57#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
59#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(children))]
60#[derive(csskit_derives::NodeWithMetadata)]
61pub enum AngleOrZero {
62 Angle(Angle),
63 #[cfg_attr(feature = "visitable", visit(skip))]
64 Zero(Exact<T![Number], 0>),
65}
66
67#[derive(IntoCursor, Parse, Peek, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
69#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(children))]
70#[derive(csskit_derives::NodeWithMetadata)]
71pub enum AngleOrNumber {
72 Angle(Angle),
73 #[cfg_attr(feature = "visitable", visit(skip))]
74 Number(T![Number]),
75}
76
77impl From<AngleOrZero> for f32 {
78 fn from(val: AngleOrZero) -> Self {
79 match val {
80 AngleOrZero::Angle(f) => f.into(),
81 AngleOrZero::Zero(f) => f.0.into(),
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::CssAtomSet;
90 use css_parse::assert_parse;
91
92 #[test]
93 fn size_test() {
94 assert_eq!(std::mem::size_of::<Angle>(), 16);
95 }
96
97 #[test]
98 fn test_writes() {
99 assert_parse!(CssAtomSet::ATOMS, Angle, "0grad");
100 assert_parse!(CssAtomSet::ATOMS, Angle, "0deg");
101 assert_parse!(CssAtomSet::ATOMS, AngleOrZero, "0", AngleOrZero::Zero(_));
102 }
103}