tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }