1use crate::derives::*;
8use crate::values::animated::{Animate, Procedure, ToAnimatedValue};
9use crate::values::computed::length::{LengthPercentage, NonNegativeLength};
10use crate::values::computed::{Context, Integer, Number, ToComputedValue};
11use crate::values::generics::box_::{
12 GenericBaselineShift, GenericContainIntrinsicSize, GenericLineClamp, GenericOverflowClipMargin,
13 GenericPerspective,
14};
15use crate::values::specified::box_ as specified;
16use std::fmt;
17use style_traits::{CssWriter, ToCss};
18
19pub use crate::values::specified::box_::{
20 AlignmentBaseline, Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain,
21 ContainerName, ContainerType, ContentVisibility, Display, Float, Overflow, OverflowAnchor,
22 OverscrollBehavior, PositionProperty, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop,
23 ScrollSnapStrictness, ScrollSnapType, ScrollbarGutter, TouchAction, WillChange,
24 WritingModeProperty,
25};
26
27pub type BaselineShift = GenericBaselineShift<LengthPercentage>;
29
30pub type OverflowClipMargin = GenericOverflowClipMargin<NonNegativeLength>;
32
33pub type ContainIntrinsicSize = GenericContainIntrinsicSize<NonNegativeLength>;
35
36impl ContainIntrinsicSize {
37 pub fn add_auto_if_needed(&self) -> Option<Self> {
39 Some(match *self {
40 Self::None => Self::AutoNone,
41 Self::Length(ref l) => Self::AutoLength(*l),
42 Self::AutoNone | Self::AutoLength(..) => return None,
43 })
44 }
45}
46
47pub type LineClamp = GenericLineClamp<Integer>;
49
50impl Animate for LineClamp {
51 #[inline]
52 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
53 if self.is_none() != other.is_none() {
54 return Err(());
55 }
56 if self.is_none() {
57 return Ok(Self::none());
58 }
59 Ok(Self(self.0.animate(&other.0, procedure)?.max(1)))
60 }
61}
62
63pub type Perspective = GenericPerspective<NonNegativeLength>;
65
66#[allow(missing_docs)]
68#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
69#[derive(
70 Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss, ToResolvedValue, ToTyped,
71)]
72#[repr(u8)]
73pub enum Resize {
74 None,
75 Both,
76 Horizontal,
77 Vertical,
78}
79
80impl ToComputedValue for specified::Resize {
81 type ComputedValue = Resize;
82
83 #[inline]
84 fn to_computed_value(&self, context: &Context) -> Resize {
85 let is_vertical = context.style().writing_mode.is_vertical();
86 match self {
87 specified::Resize::Inline => {
88 context
89 .rule_cache_conditions
90 .borrow_mut()
91 .set_writing_mode_dependency(context.builder.writing_mode);
92 if is_vertical {
93 Resize::Vertical
94 } else {
95 Resize::Horizontal
96 }
97 },
98 specified::Resize::Block => {
99 context
100 .rule_cache_conditions
101 .borrow_mut()
102 .set_writing_mode_dependency(context.builder.writing_mode);
103 if is_vertical {
104 Resize::Horizontal
105 } else {
106 Resize::Vertical
107 }
108 },
109 specified::Resize::None => Resize::None,
110 specified::Resize::Both => Resize::Both,
111 specified::Resize::Horizontal => Resize::Horizontal,
112 specified::Resize::Vertical => Resize::Vertical,
113 }
114 }
115
116 #[inline]
117 fn from_computed_value(computed: &Resize) -> specified::Resize {
118 match computed {
119 Resize::None => specified::Resize::None,
120 Resize::Both => specified::Resize::Both,
121 Resize::Horizontal => specified::Resize::Horizontal,
122 Resize::Vertical => specified::Resize::Vertical,
123 }
124 }
125}
126
127#[derive(
129 Clone,
130 ComputeSquaredDistance,
131 Copy,
132 Debug,
133 MallocSizeOf,
134 PartialEq,
135 PartialOrd,
136 ToResolvedValue,
137 ToTyped,
138)]
139#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
140#[repr(C)]
141pub struct Zoom(f32);
142
143impl ToComputedValue for specified::Zoom {
144 type ComputedValue = Zoom;
145
146 #[inline]
147 fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
148 let n = match *self {
149 Self::Normal => return Zoom::ONE,
150 Self::Document => return Zoom::DOCUMENT,
151 Self::Value(ref n) => n.0.to_number().get(),
152 };
153 if n == 0.0 {
154 return Zoom::ONE;
156 }
157 Zoom(n)
158 }
159
160 #[inline]
161 fn from_computed_value(computed: &Self::ComputedValue) -> Self {
162 Self::new_number(computed.value())
163 }
164}
165
166impl ToCss for Zoom {
167 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
168 where
169 W: fmt::Write,
170 {
171 use std::fmt::Write;
172 if *self == Self::DOCUMENT {
173 return dest.write_str("document");
174 }
175 self.value().to_css(dest)
176 }
177}
178
179impl ToAnimatedValue for Zoom {
180 type AnimatedValue = Number;
181
182 #[inline]
183 fn to_animated_value(self, _: &crate::values::animated::Context) -> Self::AnimatedValue {
184 self.value()
185 }
186
187 #[inline]
188 fn from_animated_value(animated: Self::AnimatedValue) -> Self {
189 Zoom(animated.max(0.0))
190 }
191}
192
193impl Zoom {
194 pub const ONE: Zoom = Zoom(1.0);
196
197 pub const DOCUMENT: Zoom = Zoom(0.0);
200
201 #[inline]
203 pub fn is_one(self) -> bool {
204 self == Self::ONE
205 }
206
207 #[inline]
209 pub fn is_document(self) -> bool {
210 self == Self::DOCUMENT
211 }
212
213 #[inline]
215 pub fn inverted(&self) -> Option<Self> {
216 if self.0 == 0.0 {
217 return None;
218 }
219 Some(Self(1. / self.0))
220 }
221
222 #[inline]
224 pub fn value(&self) -> f32 {
225 self.0
226 }
227
228 pub fn compute_effective(self, specified: Self) -> Self {
230 if specified == Self::DOCUMENT {
231 return Self::ONE;
232 }
233 if self == Self::ONE {
234 return specified;
235 }
236 if specified == Self::ONE {
237 return self;
238 }
239 Zoom(self.0 * specified.0)
240 }
241
242 #[inline]
244 pub fn zoom(self, value: f32) -> f32 {
245 if self == Self::ONE {
246 return value;
247 }
248 value * self.value()
249 }
250
251 #[inline]
253 pub fn unzoom(self, value: f32) -> f32 {
254 if self == Self::ONE || self.0 == 0.0 {
256 return value;
257 }
258 value / self.value()
259 }
260}