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