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