box.rs (7782B)
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 //! Computed types for box properties. 6 7 use crate::derives::*; 8 use crate::values::animated::{Animate, Procedure, ToAnimatedValue}; 9 use crate::values::computed::length::{LengthPercentage, NonNegativeLength}; 10 use crate::values::computed::{Context, Integer, Number, ToComputedValue}; 11 use crate::values::generics::box_::{ 12 GenericContainIntrinsicSize, GenericLineClamp, GenericOverflowClipMargin, GenericPerspective, 13 GenericVerticalAlign, 14 }; 15 use crate::values::specified::box_ as specified; 16 use std::fmt; 17 use style_traits::{CssWriter, ToCss}; 18 19 pub use crate::values::specified::box_::{ 20 Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain, ContainerName, 21 ContainerType, ContentVisibility, Display, Float, Overflow, OverflowAnchor, OverscrollBehavior, 22 PositionProperty, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, 23 ScrollSnapType, ScrollbarGutter, TouchAction, WillChange, WritingModeProperty, 24 }; 25 26 /// A computed value for the `vertical-align` property. 27 pub type VerticalAlign = GenericVerticalAlign<LengthPercentage>; 28 29 /// A computed value for the `overflow-clip-margin` property. 30 pub type OverflowClipMargin = GenericOverflowClipMargin<NonNegativeLength>; 31 32 /// A computed value for the `contain-intrinsic-size` property. 33 pub type ContainIntrinsicSize = GenericContainIntrinsicSize<NonNegativeLength>; 34 35 impl ContainIntrinsicSize { 36 /// Converts contain-intrinsic-size to auto style. 37 pub fn add_auto_if_needed(&self) -> Option<Self> { 38 Some(match *self { 39 Self::None => Self::AutoNone, 40 Self::Length(ref l) => Self::AutoLength(*l), 41 Self::AutoNone | Self::AutoLength(..) => return None, 42 }) 43 } 44 } 45 46 /// A computed value for the `line-clamp` property. 47 pub type LineClamp = GenericLineClamp<Integer>; 48 49 impl Animate for LineClamp { 50 #[inline] 51 fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { 52 if self.is_none() != other.is_none() { 53 return Err(()); 54 } 55 if self.is_none() { 56 return Ok(Self::none()); 57 } 58 Ok(Self(self.0.animate(&other.0, procedure)?.max(1))) 59 } 60 } 61 62 /// A computed value for the `perspective` property. 63 pub type Perspective = GenericPerspective<NonNegativeLength>; 64 65 /// A computed value for the `resize` property. 66 #[allow(missing_docs)] 67 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] 68 #[derive( 69 Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss, ToResolvedValue, ToTyped, 70 )] 71 #[repr(u8)] 72 pub enum Resize { 73 None, 74 Both, 75 Horizontal, 76 Vertical, 77 } 78 79 impl ToComputedValue for specified::Resize { 80 type ComputedValue = Resize; 81 82 #[inline] 83 fn to_computed_value(&self, context: &Context) -> Resize { 84 let is_vertical = context.style().writing_mode.is_vertical(); 85 match self { 86 specified::Resize::Inline => { 87 context 88 .rule_cache_conditions 89 .borrow_mut() 90 .set_writing_mode_dependency(context.builder.writing_mode); 91 if is_vertical { 92 Resize::Vertical 93 } else { 94 Resize::Horizontal 95 } 96 }, 97 specified::Resize::Block => { 98 context 99 .rule_cache_conditions 100 .borrow_mut() 101 .set_writing_mode_dependency(context.builder.writing_mode); 102 if is_vertical { 103 Resize::Horizontal 104 } else { 105 Resize::Vertical 106 } 107 }, 108 specified::Resize::None => Resize::None, 109 specified::Resize::Both => Resize::Both, 110 specified::Resize::Horizontal => Resize::Horizontal, 111 specified::Resize::Vertical => Resize::Vertical, 112 } 113 } 114 115 #[inline] 116 fn from_computed_value(computed: &Resize) -> specified::Resize { 117 match computed { 118 Resize::None => specified::Resize::None, 119 Resize::Both => specified::Resize::Both, 120 Resize::Horizontal => specified::Resize::Horizontal, 121 Resize::Vertical => specified::Resize::Vertical, 122 } 123 } 124 } 125 126 /// The computed `zoom` property value. 127 #[derive( 128 Clone, 129 ComputeSquaredDistance, 130 Copy, 131 Debug, 132 MallocSizeOf, 133 PartialEq, 134 PartialOrd, 135 ToResolvedValue, 136 ToTyped, 137 )] 138 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] 139 #[repr(C)] 140 pub struct Zoom(f32); 141 142 impl ToComputedValue for specified::Zoom { 143 type ComputedValue = Zoom; 144 145 #[inline] 146 fn to_computed_value(&self, _: &Context) -> Self::ComputedValue { 147 let n = match *self { 148 Self::Normal => return Zoom::ONE, 149 Self::Document => return Zoom::DOCUMENT, 150 Self::Value(ref n) => n.0.to_number().get(), 151 }; 152 if n == 0.0 { 153 // For legacy reasons, zoom: 0 (and 0%) computes to 1. ¯\_(ツ)_/¯ 154 return Zoom::ONE; 155 } 156 Zoom(n) 157 } 158 159 #[inline] 160 fn from_computed_value(computed: &Self::ComputedValue) -> Self { 161 Self::new_number(computed.value()) 162 } 163 } 164 165 impl ToCss for Zoom { 166 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 167 where 168 W: fmt::Write, 169 { 170 use std::fmt::Write; 171 if *self == Self::DOCUMENT { 172 return dest.write_str("document"); 173 } 174 self.value().to_css(dest) 175 } 176 } 177 178 impl ToAnimatedValue for Zoom { 179 type AnimatedValue = Number; 180 181 #[inline] 182 fn to_animated_value(self, _: &crate::values::animated::Context) -> Self::AnimatedValue { 183 self.value() 184 } 185 186 #[inline] 187 fn from_animated_value(animated: Self::AnimatedValue) -> Self { 188 Zoom(animated.max(0.0)) 189 } 190 } 191 192 impl Zoom { 193 /// The value 1. This is by far the most common value. 194 pub const ONE: Zoom = Zoom(1.0); 195 196 /// The `document` value. This can appear in the computed zoom property value, but not in the 197 /// `effective_zoom` field. 198 pub const DOCUMENT: Zoom = Zoom(0.0); 199 200 /// Returns whether we're the number 1. 201 #[inline] 202 pub fn is_one(self) -> bool { 203 self == Self::ONE 204 } 205 206 /// Returns whether we're the `document` keyword. 207 #[inline] 208 pub fn is_document(self) -> bool { 209 self == Self::DOCUMENT 210 } 211 212 /// Returns the inverse of our value. 213 #[inline] 214 pub fn inverted(&self) -> Option<Self> { 215 if self.0 == 0.0 { 216 return None; 217 } 218 Some(Self(1. / self.0)) 219 } 220 221 /// Returns the value as a float. 222 #[inline] 223 pub fn value(&self) -> f32 { 224 self.0 225 } 226 227 /// Computes the effective zoom for a given new zoom value in rhs. 228 pub fn compute_effective(self, specified: Self) -> Self { 229 if specified == Self::DOCUMENT { 230 return Self::ONE; 231 } 232 if self == Self::ONE { 233 return specified; 234 } 235 if specified == Self::ONE { 236 return self; 237 } 238 Zoom(self.0 * specified.0) 239 } 240 241 /// Returns the zoomed value. 242 #[inline] 243 pub fn zoom(self, value: f32) -> f32 { 244 if self == Self::ONE { 245 return value; 246 } 247 value * self.value() 248 } 249 250 /// Returns the un-zoomed value. 251 #[inline] 252 pub fn unzoom(self, value: f32) -> f32 { 253 // Avoid division by zero if our effective zoom computation ends up being zero. 254 if self == Self::ONE || self.0 == 0.0 { 255 return value; 256 } 257 value / self.value() 258 } 259 }