tor-browser

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

margin_rule.rs (7195B)


      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 //! A [`@margin`][margin] rule.
      6 //!
      7 //! [margin]: https://drafts.csswg.org/css-page-3/#margin-boxes
      8 
      9 use crate::derives::*;
     10 use crate::properties::PropertyDeclarationBlock;
     11 use crate::shared_lock::{DeepCloneWithLock, Locked};
     12 use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
     13 use cssparser::{match_ignore_ascii_case, SourceLocation};
     14 #[cfg(feature = "gecko")]
     15 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
     16 use servo_arc::Arc;
     17 use std::fmt::{self, Write};
     18 use style_traits::CssStringWriter;
     19 
     20 macro_rules! margin_rule_types {
     21    ($($(#[$($meta:tt)+])* $id:ident => $val:literal,)+) => {
     22        /// [`@margin`][margin] rule names.
     23        ///
     24        /// https://drafts.csswg.org/css-page-3/#margin-at-rules
     25        #[derive(Clone, Copy, Eq, MallocSizeOf, PartialEq, ToShmem)]
     26        #[repr(u8)]
     27        pub enum MarginRuleType {
     28            $($(#[$($meta)+])* $id,)+
     29        }
     30 
     31        /// All [`@margin`][margin] rule names, with a preceding '@'.
     32        ///
     33        /// This array lets us have just one single memory region used for
     34        /// to_str, name, and the Debug implementation.
     35        const MARGIN_RULE_AT_NAMES:&[&'static str] = &[
     36            $( concat!('@', $val), )+
     37        ];
     38 
     39        impl MarginRuleType {
     40            /// Matches the rule type for this name. This does not expect a
     41            /// leading '@'.
     42            pub fn match_name(name: &str) -> Option<Self> {
     43                Some(match_ignore_ascii_case! { name,
     44                    $( $val => MarginRuleType::$id, )+
     45                    _ => return None,
     46                })
     47            }
     48        }
     49    }
     50 }
     51 
     52 margin_rule_types! {
     53    /// [`@top-left-corner`][top-left-corner] margin rule
     54    ///
     55    /// [top-left-corner] https://drafts.csswg.org/css-page-3/#top-left-corner-box-def
     56    TopLeftCorner => "top-left-corner",
     57    /// [`@top-left`][top-left] margin rule
     58    ///
     59    /// [top-left] https://drafts.csswg.org/css-page-3/#top-left-box-def
     60    TopLeft => "top-left",
     61    /// [`@top-center`][top-center] margin rule
     62    ///
     63    /// [top-center] https://drafts.csswg.org/css-page-3/#top-center-box-def
     64    TopCenter => "top-center",
     65    /// [`@top-right`][top-right] margin rule
     66    ///
     67    /// [top-right] https://drafts.csswg.org/css-page-3/#top-right-box-def
     68    TopRight => "top-right",
     69    /// [`@top-right-corner`][top-right-corner] margin rule
     70    ///
     71    /// [top-right-corner] https://drafts.csswg.org/css-page-3/#top-right-corner-box-def
     72    TopRightCorner => "top-right-corner",
     73    /// [`@bottom-left-corner`][bottom-left-corner] margin rule
     74    ///
     75    /// [bottom-left-corner] https://drafts.csswg.org/css-page-3/#bottom-left-corner-box-def
     76    BottomLeftCorner => "bottom-left-corner",
     77    /// [`@bottom-left`][bottom-left] margin rule
     78    ///
     79    /// [bottom-left] https://drafts.csswg.org/css-page-3/#bottom-left-box-def
     80    BottomLeft => "bottom-left",
     81    /// [`@bottom-center`][bottom-center] margin rule
     82    ///
     83    /// [bottom-center] https://drafts.csswg.org/css-page-3/#bottom-center-box-def
     84    BottomCenter => "bottom-center",
     85    /// [`@bottom-right`][bottom-right] margin rule
     86    ///
     87    /// [bottom-right] https://drafts.csswg.org/css-page-3/#bottom-right-box-def
     88    BottomRight => "bottom-right",
     89    /// [`@bottom-right-corner`][bottom-right-corner] margin rule
     90    ///
     91    /// [bottom-right-corner] https://drafts.csswg.org/css-page-3/#bottom-right-corner-box-def
     92    BottomRightCorner => "bottom-right-corner",
     93    /// [`@left-top`][left-top] margin rule
     94    ///
     95    /// [left-top] https://drafts.csswg.org/css-page-3/#left-top-box-def
     96    LeftTop => "left-top",
     97    /// [`@left-middle`][left-middle] margin rule
     98    ///
     99    /// [left-middle] https://drafts.csswg.org/css-page-3/#left-middle-box-def
    100    LeftMiddle => "left-middle",
    101    /// [`@left-bottom`][left-bottom] margin rule
    102    ///
    103    /// [left-bottom] https://drafts.csswg.org/css-page-3/#left-bottom-box-def
    104    LeftBottom => "left-bottom",
    105    /// [`@right-top`][right-top] margin rule
    106    ///
    107    /// [right-top] https://drafts.csswg.org/css-page-3/#right-top-box-def
    108    RightTop => "right-top",
    109    /// [`@right-middle`][right-middle] margin rule
    110    ///
    111    /// [right-middle] https://drafts.csswg.org/css-page-3/#right-middle-box-def
    112    RightMiddle => "right-middle",
    113    /// [`@right-bottom`][right-bottom] margin rule
    114    ///
    115    /// [right-bottom] https://drafts.csswg.org/css-page-3/#right-bottom-box-def
    116    RightBottom => "right-bottom",
    117 }
    118 
    119 impl MarginRuleType {
    120    #[inline]
    121    fn to_str(&self) -> &'static str {
    122        &MARGIN_RULE_AT_NAMES[*self as usize]
    123    }
    124    #[inline]
    125    fn name(&self) -> &'static str {
    126        // Use the at-name array, skipping the first character to get
    127        // the name without the @ sign.
    128        &MARGIN_RULE_AT_NAMES[*self as usize][1..]
    129    }
    130 }
    131 
    132 // Implement Debug manually so that it will share the same string memory as
    133 // MarginRuleType::name and MarginRuleType::to_str.
    134 impl fmt::Debug for MarginRuleType {
    135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
    136        f.write_str(self.name())
    137    }
    138 }
    139 
    140 /// A [`@margin`][margin] rule.
    141 ///
    142 /// [margin]: https://drafts.csswg.org/css-page-3/#margin-at-rules
    143 #[derive(Clone, Debug, ToShmem)]
    144 pub struct MarginRule {
    145    /// Type of this margin rule.
    146    pub rule_type: MarginRuleType,
    147    /// The declaration block this margin rule contains.
    148    pub block: Arc<Locked<PropertyDeclarationBlock>>,
    149    /// The source position this rule was found at.
    150    pub source_location: SourceLocation,
    151 }
    152 
    153 impl MarginRule {
    154    /// Measure heap usage.
    155    #[cfg(feature = "gecko")]
    156    pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
    157        // Measurement of other fields may be added later.
    158        self.block.unconditional_shallow_size_of(ops) + self.block.read_with(guard).size_of(ops)
    159    }
    160    /// Gets the name for this margin rule.
    161    #[inline]
    162    pub fn name(&self) -> &'static str {
    163        self.rule_type.name()
    164    }
    165 }
    166 
    167 impl ToCssWithGuard for MarginRule {
    168    /// Serialization of a margin-rule is not specced, this is adapted from how
    169    /// page-rules and style-rules are serialized.
    170    fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
    171        dest.write_str(self.rule_type.to_str())?;
    172        dest.write_str(" { ")?;
    173        let declaration_block = self.block.read_with(guard);
    174        declaration_block.to_css(dest)?;
    175        if !declaration_block.declarations().is_empty() {
    176            dest.write_char(' ')?;
    177        }
    178        dest.write_char('}')
    179    }
    180 }
    181 
    182 impl DeepCloneWithLock for MarginRule {
    183    fn deep_clone_with_lock(&self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard) -> Self {
    184        MarginRule {
    185            rule_type: self.rule_type,
    186            block: Arc::new(lock.wrap(self.block.read_with(&guard).clone())),
    187            source_location: self.source_location.clone(),
    188        }
    189    }
    190 }