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