style/values/resolved/
mod.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Resolved values. These are almost always computed values, but in some cases
6//! there are used values.
7
8use app_units::Au;
9#[cfg(feature = "gecko")]
10use crate::media_queries::Device;
11use crate::properties::ComputedValues;
12use crate::ArcSlice;
13use servo_arc::Arc;
14use smallvec::SmallVec;
15
16mod animation;
17mod color;
18mod counters;
19
20use crate::values::computed::{self, Length};
21
22/// Element-specific information needed to resolve property values.
23#[cfg(feature = "gecko")]
24pub struct ResolvedElementInfo<'a> {
25    /// Element we're resolving line-height against.
26    pub element: crate::gecko::wrapper::GeckoElement<'a>,
27}
28
29/// Information needed to resolve a given value.
30pub struct Context<'a> {
31    /// The style we're resolving for. This is useful to resolve currentColor.
32    pub style: &'a ComputedValues,
33    /// The device / document we're resolving style for. Useful to do font metrics stuff needed for
34    /// line-height.
35    #[cfg(feature = "gecko")]
36    pub device: &'a Device,
37    /// The element-specific information to resolve the value.
38    #[cfg(feature = "gecko")]
39    pub element_info: ResolvedElementInfo<'a>,
40}
41
42/// A trait to represent the conversion between resolved and resolved values.
43///
44/// This trait is derivable with `#[derive(ToResolvedValue)]`.
45///
46/// The deriving code assumes that if the type isn't generic, then the trait can
47/// be implemented as simple move. This means that a manual implementation with
48/// `ResolvedValue = Self` is bogus if it returns anything else than a clone.
49pub trait ToResolvedValue {
50    /// The resolved value type we're going to be converted to.
51    type ResolvedValue;
52
53    /// Convert a resolved value to a resolved value.
54    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue;
55
56    /// Convert a resolved value to resolved value form.
57    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self;
58}
59
60macro_rules! trivial_to_resolved_value {
61    ($ty:ty) => {
62        impl $crate::values::resolved::ToResolvedValue for $ty {
63            type ResolvedValue = Self;
64
65            #[inline]
66            fn to_resolved_value(self, _: &Context) -> Self {
67                self
68            }
69
70            #[inline]
71            fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
72                resolved
73            }
74        }
75    };
76}
77
78trivial_to_resolved_value!(());
79trivial_to_resolved_value!(bool);
80trivial_to_resolved_value!(f32);
81trivial_to_resolved_value!(u8);
82trivial_to_resolved_value!(i8);
83trivial_to_resolved_value!(u16);
84trivial_to_resolved_value!(i16);
85trivial_to_resolved_value!(u32);
86trivial_to_resolved_value!(i32);
87trivial_to_resolved_value!(usize);
88trivial_to_resolved_value!(String);
89trivial_to_resolved_value!(Box<str>);
90trivial_to_resolved_value!(crate::OwnedStr);
91trivial_to_resolved_value!(crate::color::AbsoluteColor);
92trivial_to_resolved_value!(crate::values::generics::color::ColorMixFlags);
93trivial_to_resolved_value!(crate::Atom);
94trivial_to_resolved_value!(crate::values::AtomIdent);
95trivial_to_resolved_value!(crate::custom_properties::VariableValue);
96trivial_to_resolved_value!(crate::stylesheets::UrlExtraData);
97trivial_to_resolved_value!(computed::url::ComputedUrl);
98#[cfg(feature = "servo")]
99trivial_to_resolved_value!(crate::Namespace);
100#[cfg(feature = "servo")]
101trivial_to_resolved_value!(crate::Prefix);
102trivial_to_resolved_value!(style_traits::values::specified::AllowedNumericType);
103trivial_to_resolved_value!(computed::TimingFunction);
104
105impl ToResolvedValue for Au {
106    type ResolvedValue = Length;
107
108    #[inline]
109    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
110        Length::new(self.to_f32_px()).to_resolved_value(context)
111    }
112
113    #[inline]
114    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
115        Au::from_f32_px(Length::from_resolved_value(resolved).px())
116    }
117}
118
119impl<A, B> ToResolvedValue for (A, B)
120where
121    A: ToResolvedValue,
122    B: ToResolvedValue,
123{
124    type ResolvedValue = (
125        <A as ToResolvedValue>::ResolvedValue,
126        <B as ToResolvedValue>::ResolvedValue,
127    );
128
129    #[inline]
130    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
131        (
132            self.0.to_resolved_value(context),
133            self.1.to_resolved_value(context),
134        )
135    }
136
137    #[inline]
138    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
139        (
140            A::from_resolved_value(resolved.0),
141            B::from_resolved_value(resolved.1),
142        )
143    }
144}
145
146impl<T> ToResolvedValue for Option<T>
147where
148    T: ToResolvedValue,
149{
150    type ResolvedValue = Option<<T as ToResolvedValue>::ResolvedValue>;
151
152    #[inline]
153    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
154        self.map(|item| item.to_resolved_value(context))
155    }
156
157    #[inline]
158    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
159        resolved.map(T::from_resolved_value)
160    }
161}
162
163impl<T> ToResolvedValue for SmallVec<[T; 1]>
164where
165    T: ToResolvedValue,
166{
167    type ResolvedValue = SmallVec<[<T as ToResolvedValue>::ResolvedValue; 1]>;
168
169    #[inline]
170    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
171        self.into_iter()
172            .map(|item| item.to_resolved_value(context))
173            .collect()
174    }
175
176    #[inline]
177    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
178        resolved.into_iter().map(T::from_resolved_value).collect()
179    }
180}
181
182impl<T> ToResolvedValue for Vec<T>
183where
184    T: ToResolvedValue,
185{
186    type ResolvedValue = Vec<<T as ToResolvedValue>::ResolvedValue>;
187
188    #[inline]
189    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
190        self.into_iter()
191            .map(|item| item.to_resolved_value(context))
192            .collect()
193    }
194
195    #[inline]
196    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
197        resolved.into_iter().map(T::from_resolved_value).collect()
198    }
199}
200
201impl<T> ToResolvedValue for thin_vec::ThinVec<T>
202where
203    T: ToResolvedValue,
204{
205    type ResolvedValue = thin_vec::ThinVec<<T as ToResolvedValue>::ResolvedValue>;
206
207    #[inline]
208    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
209        self.into_iter()
210            .map(|item| item.to_resolved_value(context))
211            .collect()
212    }
213
214    #[inline]
215    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
216        resolved.into_iter().map(T::from_resolved_value).collect()
217    }
218}
219
220impl<T> ToResolvedValue for Box<T>
221where
222    T: ToResolvedValue,
223{
224    type ResolvedValue = Box<<T as ToResolvedValue>::ResolvedValue>;
225
226    #[inline]
227    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
228        Box::new(T::to_resolved_value(*self, context))
229    }
230
231    #[inline]
232    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
233        Box::new(T::from_resolved_value(*resolved))
234    }
235}
236
237impl<T> ToResolvedValue for Box<[T]>
238where
239    T: ToResolvedValue,
240{
241    type ResolvedValue = Box<[<T as ToResolvedValue>::ResolvedValue]>;
242
243    #[inline]
244    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
245        Vec::from(self)
246            .to_resolved_value(context)
247            .into_boxed_slice()
248    }
249
250    #[inline]
251    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
252        Vec::from_resolved_value(Vec::from(resolved)).into_boxed_slice()
253    }
254}
255
256impl<T> ToResolvedValue for crate::OwnedSlice<T>
257where
258    T: ToResolvedValue,
259{
260    type ResolvedValue = crate::OwnedSlice<<T as ToResolvedValue>::ResolvedValue>;
261
262    #[inline]
263    fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
264        self.into_box().to_resolved_value(context).into()
265    }
266
267    #[inline]
268    fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
269        Self::from(Box::from_resolved_value(resolved.into_box()))
270    }
271}
272
273// NOTE(emilio): This is implementable more generically, but it's unlikely what
274// you want there, as it forces you to have an extra allocation.
275//
276// We could do that if needed, ideally with specialization for the case where
277// ResolvedValue = T. But we don't need it for now.
278impl<T> ToResolvedValue for Arc<T>
279where
280    T: ToResolvedValue<ResolvedValue = T>,
281{
282    type ResolvedValue = Self;
283
284    #[inline]
285    fn to_resolved_value(self, _: &Context) -> Self {
286        self
287    }
288
289    #[inline]
290    fn from_resolved_value(resolved: Self) -> Self {
291        resolved
292    }
293}
294
295// Same caveat as above applies.
296impl<T> ToResolvedValue for ArcSlice<T>
297where
298    T: ToResolvedValue<ResolvedValue = T>,
299{
300    type ResolvedValue = Self;
301
302    #[inline]
303    fn to_resolved_value(self, _: &Context) -> Self {
304        self
305    }
306
307    #[inline]
308    fn from_resolved_value(resolved: Self) -> Self {
309        resolved
310    }
311}