tor-browser

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

svg.mako.rs (12538B)


      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 <%namespace name="helpers" file="/helpers.mako.rs" />
      6 
      7 <%helpers:shorthand name="mask" engines="gecko" extra_prefixes="webkit"
      8                    sub_properties="mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x
      9                                    mask-position-y mask-size mask-image"
     10                    spec="https://drafts.fxtf.org/css-masking/#propdef-mask">
     11    use crate::properties::longhands::{mask_mode, mask_repeat, mask_clip, mask_origin, mask_composite, mask_position_x,
     12                                mask_position_y};
     13    use crate::properties::longhands::{mask_size, mask_image};
     14    use crate::values::specified::{Position, PositionComponent};
     15    use crate::parser::Parse;
     16 
     17    // FIXME(emilio): These two mask types should be the same!
     18    impl From<mask_origin::single_value::SpecifiedValue> for mask_clip::single_value::SpecifiedValue {
     19        fn from(origin: mask_origin::single_value::SpecifiedValue) -> mask_clip::single_value::SpecifiedValue {
     20            match origin {
     21                mask_origin::single_value::SpecifiedValue::ContentBox =>
     22                    mask_clip::single_value::SpecifiedValue::ContentBox,
     23                mask_origin::single_value::SpecifiedValue::PaddingBox =>
     24                    mask_clip::single_value::SpecifiedValue::PaddingBox ,
     25                mask_origin::single_value::SpecifiedValue::BorderBox =>
     26                    mask_clip::single_value::SpecifiedValue::BorderBox,
     27                % if engine == "gecko":
     28                mask_origin::single_value::SpecifiedValue::FillBox =>
     29                    mask_clip::single_value::SpecifiedValue::FillBox ,
     30                mask_origin::single_value::SpecifiedValue::StrokeBox =>
     31                    mask_clip::single_value::SpecifiedValue::StrokeBox,
     32                mask_origin::single_value::SpecifiedValue::ViewBox=>
     33                    mask_clip::single_value::SpecifiedValue::ViewBox,
     34                % endif
     35            }
     36        }
     37    }
     38 
     39    pub fn parse_value<'i, 't>(
     40        context: &ParserContext,
     41        input: &mut Parser<'i, 't>,
     42    ) -> Result<Longhands, ParseError<'i>> {
     43        % for name in "image mode position_x position_y size repeat origin clip composite".split():
     44        // Vec grows from 0 to 4 by default on first push().  So allocate with
     45        // capacity 1, so in the common case of only one item we don't way
     46        // overallocate, then shrink.  Note that we always push at least one
     47        // item if parsing succeeds.
     48        let mut mask_${name} = Vec::with_capacity(1);
     49        % endfor
     50 
     51        input.parse_comma_separated(|input| {
     52            % for name in "image mode position size repeat origin clip composite".split():
     53                let mut ${name} = None;
     54            % endfor
     55            loop {
     56                if image.is_none() {
     57                    if let Ok(value) = input.try_parse(|input| mask_image::single_value
     58                                                                   ::parse(context, input)) {
     59                        image = Some(value);
     60                        continue
     61                    }
     62                }
     63                if position.is_none() {
     64                    if let Ok(value) = input.try_parse(|input| Position::parse(context, input)) {
     65                        position = Some(value);
     66 
     67                        // Parse mask size, if applicable.
     68                        size = input.try_parse(|input| {
     69                            input.expect_delim('/')?;
     70                            mask_size::single_value::parse(context, input)
     71                        }).ok();
     72 
     73                        continue
     74                    }
     75                }
     76                % for name in "repeat origin clip composite mode".split():
     77                    if ${name}.is_none() {
     78                        if let Ok(value) = input.try_parse(|input| mask_${name}::single_value
     79                                                                               ::parse(context, input)) {
     80                            ${name} = Some(value);
     81                            continue
     82                        }
     83                    }
     84                % endfor
     85                break
     86            }
     87            if clip.is_none() {
     88                if let Some(origin) = origin {
     89                    clip = Some(mask_clip::single_value::SpecifiedValue::from(origin));
     90                }
     91            }
     92            let mut any = false;
     93            % for name in "image mode position size repeat origin clip composite".split():
     94                any = any || ${name}.is_some();
     95            % endfor
     96            if any {
     97                if let Some(position) = position {
     98                    mask_position_x.push(position.horizontal);
     99                    mask_position_y.push(position.vertical);
    100                } else {
    101                    mask_position_x.push(PositionComponent::zero());
    102                    mask_position_y.push(PositionComponent::zero());
    103                }
    104                % for name in "image mode size repeat origin clip composite".split():
    105                    if let Some(m_${name}) = ${name} {
    106                        mask_${name}.push(m_${name});
    107                    } else {
    108                        mask_${name}.push(mask_${name}::single_value
    109                                                        ::get_initial_specified_value());
    110                    }
    111                % endfor
    112                Ok(())
    113            } else {
    114                Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
    115            }
    116        })?;
    117 
    118        Ok(expanded! {
    119            % for name in "image mode position_x position_y size repeat origin clip composite".split():
    120                mask_${name}: mask_${name}::SpecifiedValue(mask_${name}.into()),
    121            % endfor
    122         })
    123    }
    124 
    125    impl<'a> ToCss for LonghandsToSerialize<'a>  {
    126        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
    127            use crate::properties::longhands::mask_origin::single_value::computed_value::T as Origin;
    128            use crate::properties::longhands::mask_clip::single_value::computed_value::T as Clip;
    129            use style_traits::values::SequenceWriter;
    130 
    131            let len = self.mask_image.0.len();
    132            if len == 0 {
    133                return Ok(());
    134            }
    135            % for name in "mode position_x position_y size repeat origin clip composite".split():
    136                if self.mask_${name}.0.len() != len {
    137                    return Ok(());
    138                }
    139            % endfor
    140 
    141            // For each <mask-layer>, we serialize it according to the following order:
    142            // <mask-layer> =
    143            //   <mask-reference> ||
    144            //   <position> [ / <bg-size> ]? ||
    145            //   <repeat-style> ||
    146            //   <coord-box> ||
    147            //   [ <coord-box> | no-clip ] ||
    148            //   <compositing-operator> ||
    149            //   <masking-mode>
    150            // https://drafts.fxtf.org/css-masking-1/#the-mask
    151            for i in 0..len {
    152                if i > 0 {
    153                    dest.write_str(", ")?;
    154                }
    155 
    156                % for name in "image mode position_x position_y size repeat origin clip composite".split():
    157                    let ${name} = &self.mask_${name}.0[i];
    158                % endfor
    159 
    160                let mut has_other = false;
    161                % for name in "image mode size repeat composite".split():
    162                    let has_${name} =
    163                        *${name} != mask_${name}::single_value::get_initial_specified_value();
    164                    has_other |= has_${name};
    165                % endfor
    166                let has_position = *position_x != PositionComponent::zero()
    167                    || *position_y != PositionComponent::zero();
    168                let has_origin = *origin != Origin::BorderBox;
    169                let has_clip = *clip != Clip::BorderBox;
    170 
    171                // If all are initial values, we serialize mask-image.
    172                if !has_other && !has_position && !has_origin && !has_clip {
    173                    return image.to_css(dest);
    174                }
    175 
    176                let mut writer = SequenceWriter::new(dest, " ");
    177                // <mask-reference>
    178                if has_image {
    179                    writer.item(image)?;
    180                }
    181 
    182                // <position> [ / <bg-size> ]?
    183                if has_position || has_size {
    184                    writer.item(&Position {
    185                        horizontal: position_x.clone(),
    186                        vertical: position_y.clone()
    187                    })?;
    188 
    189                    if has_size {
    190                        writer.raw_item("/")?;
    191                        writer.item(size)?;
    192                    }
    193                }
    194 
    195                // <repeat-style>
    196                if has_repeat {
    197                    writer.item(repeat)?;
    198                }
    199 
    200                // <coord-box>
    201                // Note:
    202                // Even if 'mask-origin' is at its initial value 'border-box',
    203                // we still have to serialize it to avoid ambiguity iF the
    204                // 'mask-clip' longhand has some other <coord-box> value
    205                // (i.e. neither 'border-box' nor 'no-clip'). (If we naively
    206                // declined to serialize the 'mask-origin' value in this
    207                // situation, then whatever value we serialize for 'mask-clip'
    208                // would implicitly also represent 'mask-origin' and would be
    209                // providing the wrong value for that longhand.)
    210                if has_origin || (has_clip && *clip != Clip::NoClip) {
    211                    writer.item(origin)?;
    212                }
    213 
    214                // [ <coord-box> | no-clip ]
    215                if has_clip && *clip != From::from(*origin) {
    216                    writer.item(clip)?;
    217                }
    218 
    219                // <compositing-operator>
    220                if has_composite {
    221                    writer.item(composite)?;
    222                }
    223 
    224                // <masking-mode>
    225                if has_mode {
    226                    writer.item(mode)?;
    227                }
    228            }
    229 
    230            Ok(())
    231        }
    232    }
    233 </%helpers:shorthand>
    234 
    235 <%helpers:shorthand name="mask-position" engines="gecko" extra_prefixes="webkit"
    236                    sub_properties="mask-position-x mask-position-y"
    237                    spec="https://drafts.csswg.org/css-masks-4/#the-mask-position">
    238    use crate::properties::longhands::{mask_position_x,mask_position_y};
    239    use crate::values::specified::position::Position;
    240    use crate::parser::Parse;
    241 
    242    pub fn parse_value<'i, 't>(
    243        context: &ParserContext,
    244        input: &mut Parser<'i, 't>,
    245    ) -> Result<Longhands, ParseError<'i>> {
    246        // Vec grows from 0 to 4 by default on first push().  So allocate with
    247        // capacity 1, so in the common case of only one item we don't way
    248        // overallocate, then shrink.  Note that we always push at least one
    249        // item if parsing succeeds.
    250        let mut position_x = Vec::with_capacity(1);
    251        let mut position_y = Vec::with_capacity(1);
    252        let mut any = false;
    253 
    254        input.parse_comma_separated(|input| {
    255            let value = Position::parse(context, input)?;
    256            position_x.push(value.horizontal);
    257            position_y.push(value.vertical);
    258            any = true;
    259            Ok(())
    260        })?;
    261 
    262        if !any {
    263            return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
    264        }
    265 
    266 
    267        Ok(expanded! {
    268            mask_position_x: mask_position_x::SpecifiedValue(position_x.into()),
    269            mask_position_y: mask_position_y::SpecifiedValue(position_y.into()),
    270        })
    271    }
    272 
    273    impl<'a> ToCss for LonghandsToSerialize<'a>  {
    274        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
    275            let len = self.mask_position_x.0.len();
    276            if len == 0 || self.mask_position_y.0.len() != len {
    277                return Ok(());
    278            }
    279 
    280            for i in 0..len {
    281                Position {
    282                    horizontal: self.mask_position_x.0[i].clone(),
    283                    vertical: self.mask_position_y.0[i].clone()
    284                }.to_css(dest)?;
    285 
    286                if i < len - 1 {
    287                    dest.write_str(", ")?;
    288                }
    289            }
    290 
    291            Ok(())
    292        }
    293    }
    294 </%helpers:shorthand>