tor-browser

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

resolution.rs (4089B)


      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 //! Resolution values:
      6 //!
      7 //! https://drafts.csswg.org/css-values/#resolution
      8 
      9 use crate::derives::*;
     10 use crate::parser::{Parse, ParserContext};
     11 use crate::values::specified::CalcNode;
     12 use crate::values::CSSFloat;
     13 use cssparser::{match_ignore_ascii_case, Parser, Token};
     14 use std::fmt::{self, Write};
     15 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
     16 
     17 /// A specified resolution.
     18 #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
     19 pub struct Resolution {
     20    value: CSSFloat,
     21    unit: ResolutionUnit,
     22    was_calc: bool,
     23 }
     24 
     25 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
     26 enum ResolutionUnit {
     27    /// Dots per inch.
     28    Dpi,
     29    /// An alias unit for dots per pixel.
     30    X,
     31    /// Dots per pixel.
     32    Dppx,
     33    /// Dots per centimeter.
     34    Dpcm,
     35 }
     36 
     37 impl ResolutionUnit {
     38    fn as_str(self) -> &'static str {
     39        match self {
     40            Self::Dpi => "dpi",
     41            Self::X => "x",
     42            Self::Dppx => "dppx",
     43            Self::Dpcm => "dpcm",
     44        }
     45    }
     46 }
     47 
     48 impl Resolution {
     49    /// Returns a resolution value from dppx units.
     50    pub fn from_dppx(value: CSSFloat) -> Self {
     51        Self {
     52            value,
     53            unit: ResolutionUnit::Dppx,
     54            was_calc: false,
     55        }
     56    }
     57 
     58    /// Returns a resolution value from dppx units.
     59    pub fn from_x(value: CSSFloat) -> Self {
     60        Self {
     61            value,
     62            unit: ResolutionUnit::X,
     63            was_calc: false,
     64        }
     65    }
     66 
     67    /// Returns a resolution value from dppx units.
     68    pub fn from_dppx_calc(value: CSSFloat) -> Self {
     69        Self {
     70            value,
     71            unit: ResolutionUnit::Dppx,
     72            was_calc: true,
     73        }
     74    }
     75 
     76    /// Convert this resolution value to dppx units.
     77    pub fn dppx(&self) -> CSSFloat {
     78        match self.unit {
     79            ResolutionUnit::X | ResolutionUnit::Dppx => self.value,
     80            _ => self.dpi() / 96.0,
     81        }
     82    }
     83 
     84    /// Convert this resolution value to dpi units.
     85    pub fn dpi(&self) -> CSSFloat {
     86        match self.unit {
     87            ResolutionUnit::Dpi => self.value,
     88            ResolutionUnit::X | ResolutionUnit::Dppx => self.value * 96.0,
     89            ResolutionUnit::Dpcm => self.value * 2.54,
     90        }
     91    }
     92 
     93    /// Parse a resolution given a value and unit.
     94    pub fn parse_dimension<'i, 't>(value: CSSFloat, unit: &str) -> Result<Self, ()> {
     95        let unit = match_ignore_ascii_case! { &unit,
     96            "dpi" => ResolutionUnit::Dpi,
     97            "dppx" => ResolutionUnit::Dppx,
     98            "dpcm" => ResolutionUnit::Dpcm,
     99            "x" => ResolutionUnit::X,
    100            _ => return Err(())
    101        };
    102        Ok(Self {
    103            value,
    104            unit,
    105            was_calc: false,
    106        })
    107    }
    108 }
    109 
    110 impl ToCss for Resolution {
    111    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    112    where
    113        W: Write,
    114    {
    115        crate::values::serialize_specified_dimension(
    116            self.value,
    117            self.unit.as_str(),
    118            self.was_calc,
    119            dest,
    120        )
    121    }
    122 }
    123 
    124 impl Parse for Resolution {
    125    fn parse<'i, 't>(
    126        context: &ParserContext,
    127        input: &mut Parser<'i, 't>,
    128    ) -> Result<Self, ParseError<'i>> {
    129        let location = input.current_source_location();
    130        match *input.next()? {
    131            Token::Dimension {
    132                value, ref unit, ..
    133            } if value >= 0. => Self::parse_dimension(value, unit)
    134                .map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
    135            Token::Function(ref name) => {
    136                let function = CalcNode::math_function(context, name, location)?;
    137                CalcNode::parse_resolution(context, input, function)
    138            },
    139            ref t => return Err(location.new_unexpected_token_error(t.clone())),
    140        }
    141    }
    142 }