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(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
36 if let Ok(arg) = input.try_parse(|i| -> Result<SuperellipseArg, ParseError> {
37 match i.next()? {
38 Token::Ident(ident) if ident.eq_ignore_ascii_case("infinity") => {
39 Ok(SuperellipseArg::Infinity)
40 },
41 Token::Ident(ident) if ident.eq_ignore_ascii_case("-infinity") => {
42 Ok(SuperellipseArg::NegativeInfinity)
43 },
44 _ => Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError)),
45 }
46 }) {
47 return Ok(arg);
48 }
49 Number::parse(context, input).map(SuperellipseArg::Number)
50 }
51
52 pub fn to_k(&self, context: &Context) -> f32 {
54 match self {
55 SuperellipseArg::Infinity => f32::INFINITY,
56 SuperellipseArg::NegativeInfinity => f32::NEG_INFINITY,
57 SuperellipseArg::Number(n) => n.to_computed_value(context),
58 }
59 }
60}
61
62#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped)]
66#[typed(todo_derive_fields)]
67pub enum CornerShape {
68 Round,
70 Scoop,
72 Bevel,
74 Notch,
76 Square,
78 Squircle,
80 #[css(function)]
82 Superellipse(SuperellipseArg),
83}
84
85impl CornerShape {
86 #[inline]
88 pub fn round() -> Self {
89 CornerShape::Round
90 }
91}
92
93impl Parse for CornerShape {
94 fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
95 if let Ok(arg) = input.try_parse(|i| {
97 i.expect_function_matching("superellipse")?;
98 i.parse_nested_block(|i| SuperellipseArg::parse(context, i))
99 }) {
100 return Ok(CornerShape::Superellipse(arg));
101 }
102 Ok(try_match_ident_ignore_ascii_case! { input,
103 "round" => CornerShape::Round,
104 "scoop" => CornerShape::Scoop,
105 "bevel" => CornerShape::Bevel,
106 "notch" => CornerShape::Notch,
107 "square" => CornerShape::Square,
108 "squircle" => CornerShape::Squircle,
109 })
110 }
111}
112
113impl ToComputedValue for CornerShape {
114 type ComputedValue = computed::CornerShape;
115
116 fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
117 computed::CornerShape {
120 k: match self {
121 CornerShape::Round => 1.0,
122 CornerShape::Scoop => -1.0,
123 CornerShape::Bevel => 0.0,
124 CornerShape::Notch => f32::NEG_INFINITY,
125 CornerShape::Square => f32::INFINITY,
126 CornerShape::Squircle => 2.0,
127 CornerShape::Superellipse(arg) => arg.to_k(context),
128 },
129 }
130 }
131
132 fn from_computed_value(c: &Self::ComputedValue) -> Self {
133 let arg = if c.k == f32::INFINITY {
134 SuperellipseArg::Infinity
135 } else if c.k == f32::NEG_INFINITY {
136 SuperellipseArg::NegativeInfinity
137 } else {
138 SuperellipseArg::Number(Number::new(c.k))
139 };
140 CornerShape::Superellipse(arg)
141 }
142}
143
144pub type CornerShapeRect = crate::values::generics::border::GenericCornerShapeRect<CornerShape>;
146
147impl CornerShapeRect {
148 pub fn round() -> Self {
150 Self::all(CornerShape::Round)
151 }
152}