style/values/specified/
corner_shape.rs1use crate::derives::*;
10use crate::parser::{Parse, ParserContext};
11use crate::values::computed::corner_shape as computed;
12use crate::values::computed::{Context, ToComputedValue};
13use crate::values::specified::Number;
14use cssparser::{Parser, Token};
15use style_traits::{ParseError, StyleParseErrorKind};
16
17#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped)]
23#[typed(todo_derive_fields)]
24pub enum SuperellipseArg {
25 Number(Number),
27 Infinity,
29 #[css(keyword = "-infinity")]
31 NegativeInfinity,
32}
33
34impl SuperellipseArg {
35 fn parse<'i, 't>(
36 context: &ParserContext,
37 input: &mut Parser<'i, 't>,
38 ) -> Result<Self, ParseError<'i>> {
39 if let Ok(arg) = input.try_parse(|i| -> Result<SuperellipseArg, ParseError<'i>> {
40 let location = i.current_source_location();
41 match i.next()? {
42 Token::Ident(ref ident) if ident.eq_ignore_ascii_case("infinity") => {
43 Ok(SuperellipseArg::Infinity)
44 },
45 Token::Ident(ref ident) if ident.eq_ignore_ascii_case("-infinity") => {
46 Ok(SuperellipseArg::NegativeInfinity)
47 },
48 _ => Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
49 }
50 }) {
51 return Ok(arg);
52 }
53 Number::parse(context, input).map(SuperellipseArg::Number)
54 }
55
56 pub fn to_k(&self, context: &Context) -> f32 {
58 match self {
59 SuperellipseArg::Infinity => f32::INFINITY,
60 SuperellipseArg::NegativeInfinity => f32::NEG_INFINITY,
61 SuperellipseArg::Number(n) => n.to_computed_value(context),
62 }
63 }
64}
65
66#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped)]
70#[typed(todo_derive_fields)]
71pub enum CornerShape {
72 Round,
74 Scoop,
76 Bevel,
78 Notch,
80 Square,
82 Squircle,
84 #[css(function)]
86 Superellipse(SuperellipseArg),
87}
88
89impl CornerShape {
90 #[inline]
92 pub fn round() -> Self {
93 CornerShape::Round
94 }
95}
96
97impl Parse for CornerShape {
98 fn parse<'i, 't>(
99 context: &ParserContext,
100 input: &mut Parser<'i, 't>,
101 ) -> Result<Self, ParseError<'i>> {
102 if let Ok(arg) = input.try_parse(|i| {
104 i.expect_function_matching("superellipse")?;
105 i.parse_nested_block(|i| SuperellipseArg::parse(context, i))
106 }) {
107 return Ok(CornerShape::Superellipse(arg));
108 }
109 Ok(try_match_ident_ignore_ascii_case! { input,
110 "round" => CornerShape::Round,
111 "scoop" => CornerShape::Scoop,
112 "bevel" => CornerShape::Bevel,
113 "notch" => CornerShape::Notch,
114 "square" => CornerShape::Square,
115 "squircle" => CornerShape::Squircle,
116 })
117 }
118}
119
120impl ToComputedValue for CornerShape {
121 type ComputedValue = computed::CornerShape;
122
123 fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
124 computed::CornerShape {
127 k: match self {
128 CornerShape::Round => 1.0,
129 CornerShape::Scoop => -1.0,
130 CornerShape::Bevel => 0.0,
131 CornerShape::Notch => f32::NEG_INFINITY,
132 CornerShape::Square => f32::INFINITY,
133 CornerShape::Squircle => 2.0,
134 CornerShape::Superellipse(arg) => arg.to_k(context),
135 },
136 }
137 }
138
139 fn from_computed_value(c: &Self::ComputedValue) -> Self {
140 let arg = if c.k == f32::INFINITY {
141 SuperellipseArg::Infinity
142 } else if c.k == f32::NEG_INFINITY {
143 SuperellipseArg::NegativeInfinity
144 } else {
145 SuperellipseArg::Number(Number::new(c.k))
146 };
147 CornerShape::Superellipse(arg)
148 }
149}
150
151pub type CornerShapeRect = crate::values::generics::border::GenericCornerShapeRect<CornerShape>;
153
154impl CornerShapeRect {
155 pub fn round() -> Self {
157 Self::all(CornerShape::Round)
158 }
159}