style/values/computed/
border.rs1use crate::properties::{LogicalGroupId, LonghandId};
8use crate::values::animated::{Context as AnimatedContext, ToAnimatedValue};
9use crate::values::computed::length::{
10 CSSPixelLength, NonNegativeLength, NonNegativeLengthPercentage,
11};
12use crate::values::computed::{NonNegativeNumber, NonNegativeNumberOrPercentage};
13use crate::values::generics::border::{
14 GenericBorderCornerRadius, GenericBorderImageSideWidth, GenericBorderImageSlice,
15 GenericBorderRadius, GenericBorderSpacing,
16};
17use crate::values::generics::rect::Rect;
18use crate::values::generics::size::Size2D;
19use crate::values::generics::NonNegative;
20use crate::values::resolved::{Context as ResolvedContext, ToResolvedValue};
21use crate::Zero;
22use app_units::Au;
23
24pub use crate::values::specified::border::BorderImageRepeat;
25
26pub type LineWidth = Au;
28
29#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToTyped, From)]
31#[repr(transparent)]
32pub struct BorderSideWidth(pub Au);
33
34impl BorderSideWidth {
35 pub fn medium() -> Self {
37 Self(Au::from_px(3))
38 }
39}
40
41impl ToAnimatedValue for BorderSideWidth {
42 type AnimatedValue = CSSPixelLength;
43
44 #[inline]
45 fn to_animated_value(self, context: &AnimatedContext) -> Self::AnimatedValue {
46 self.0.to_animated_value(context)
47 }
48
49 #[inline]
50 fn from_animated_value(animated: Self::AnimatedValue) -> Self {
51 Self(Au::from_animated_value(animated))
52 }
53}
54
55impl ToResolvedValue for BorderSideWidth {
56 type ResolvedValue = CSSPixelLength;
57
58 fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue {
59 let resolved_length = CSSPixelLength::from(self.0).to_resolved_value(context);
60 if !context
61 .current_longhand
62 .is_some_and(|l| l.logical_group() == Some(LogicalGroupId::BorderWidth))
63 {
64 return resolved_length;
65 }
66 let style = match context.current_longhand.unwrap() {
68 LonghandId::BorderTopWidth => context.style.clone_border_top_style(),
69 LonghandId::BorderRightWidth => context.style.clone_border_right_style(),
70 LonghandId::BorderBottomWidth => context.style.clone_border_bottom_style(),
71 LonghandId::BorderLeftWidth => context.style.clone_border_left_style(),
72 _ => {
73 debug_assert!(false, "Expected a physical longhand");
74 return resolved_length;
75 },
76 };
77 if style.none_or_hidden() {
78 return CSSPixelLength::new(0.0);
79 }
80 resolved_length
81 }
82
83 #[inline]
84 fn from_resolved_value(value: Self::ResolvedValue) -> Self {
85 Self(Au::from_f32_px(value.px()))
86 }
87}
88
89pub type BorderSideOffset = Au;
91
92pub type BorderImageWidth = Rect<BorderImageSideWidth>;
94
95pub type BorderImageSideWidth =
97 GenericBorderImageSideWidth<NonNegativeLengthPercentage, NonNegativeNumber>;
98
99pub type BorderImageSlice = GenericBorderImageSlice<NonNegativeNumberOrPercentage>;
101
102pub type BorderRadius = GenericBorderRadius<NonNegativeLengthPercentage>;
104
105pub type BorderCornerRadius = GenericBorderCornerRadius<NonNegativeLengthPercentage>;
107
108pub type BorderSpacing = GenericBorderSpacing<NonNegativeLength>;
110
111impl BorderImageSideWidth {
112 #[inline]
114 pub fn one() -> Self {
115 GenericBorderImageSideWidth::Number(NonNegative(1.))
116 }
117}
118
119impl BorderImageSlice {
120 #[inline]
122 pub fn hundred_percent() -> Self {
123 GenericBorderImageSlice {
124 offsets: Rect::all(NonNegativeNumberOrPercentage::hundred_percent()),
125 fill: false,
126 }
127 }
128}
129
130impl BorderSpacing {
131 pub fn zero() -> Self {
133 GenericBorderSpacing(Size2D::new(
134 NonNegativeLength::zero(),
135 NonNegativeLength::zero(),
136 ))
137 }
138
139 pub fn horizontal(&self) -> Au {
141 Au::from(*self.0.width())
142 }
143
144 pub fn vertical(&self) -> Au {
146 Au::from(*self.0.height())
147 }
148}