diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /servo/components/style/properties/shorthands/border.mako.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servo/components/style/properties/shorthands/border.mako.rs')
-rw-r--r-- | servo/components/style/properties/shorthands/border.mako.rs | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/servo/components/style/properties/shorthands/border.mako.rs b/servo/components/style/properties/shorthands/border.mako.rs new file mode 100644 index 0000000000..2532901251 --- /dev/null +++ b/servo/components/style/properties/shorthands/border.mako.rs @@ -0,0 +1,479 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +<%namespace name="helpers" file="/helpers.mako.rs" /> +<% from data import to_rust_ident, ALL_SIDES, PHYSICAL_SIDES, maybe_moz_logical_alias %> + +${helpers.four_sides_shorthand( + "border-color", + "border-%s-color", + "specified::Color::parse", + engines="gecko servo-2013 servo-2020", + spec="https://drafts.csswg.org/css-backgrounds/#border-color", + allow_quirks="Yes", +)} + +${helpers.four_sides_shorthand( + "border-style", + "border-%s-style", + engines="gecko servo-2013 servo-2020", + spec="https://drafts.csswg.org/css-backgrounds/#border-style", +)} + +<%helpers:shorthand + name="border-width" + engines="gecko servo-2013 servo-2020" + sub_properties="${ + ' '.join('border-%s-width' % side + for side in PHYSICAL_SIDES)}" + spec="https://drafts.csswg.org/css-backgrounds/#border-width"> + use crate::values::generics::rect::Rect; + use crate::values::specified::{AllowQuirks, BorderSideWidth}; + + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + let rect = Rect::parse_with(context, input, |_, i| { + BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes) + })?; + Ok(expanded! { + border_top_width: rect.0, + border_right_width: rect.1, + border_bottom_width: rect.2, + border_left_width: rect.3, + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + % for side in PHYSICAL_SIDES: + let ${side} = &self.border_${side}_width; + % endfor + Rect::new(top, right, bottom, left).to_css(dest) + } + } +</%helpers:shorthand> + + +pub fn parse_border<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, +) -> Result<(specified::Color, specified::BorderStyle, specified::BorderSideWidth), ParseError<'i>> { + use crate::values::specified::{Color, BorderStyle, BorderSideWidth}; + let _unused = context; + let mut color = None; + let mut style = None; + let mut width = None; + let mut any = false; + loop { + if width.is_none() { + if let Ok(value) = input.try_parse(|i| BorderSideWidth::parse(context, i)) { + width = Some(value); + any = true; + } + } + if style.is_none() { + if let Ok(value) = input.try_parse(BorderStyle::parse) { + style = Some(value); + any = true; + continue + } + } + if color.is_none() { + if let Ok(value) = input.try_parse(|i| Color::parse(context, i)) { + color = Some(value); + any = true; + continue + } + } + break + } + if any { + Ok((color.unwrap_or_else(|| Color::currentcolor()), + style.unwrap_or(BorderStyle::None), + width.unwrap_or(BorderSideWidth::medium()))) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } +} + +% for side, logical in ALL_SIDES: + <% + spec = "https://drafts.csswg.org/css-backgrounds/#border-%s" % side + if logical: + spec = "https://drafts.csswg.org/css-logical-props/#propdef-border-%s" % side + %> + <%helpers:shorthand + name="border-${side}" + engines="gecko servo-2013 servo-2020" + sub_properties="${' '.join( + 'border-%s-%s' % (side, prop) + for prop in ['color', 'style', 'width'] + )}" + aliases="${maybe_moz_logical_alias(engine, (side, logical), '-moz-border-%s')}" + spec="${spec}"> + + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + let (color, style, width) = super::parse_border(context, input)?; + Ok(expanded! { + border_${to_rust_ident(side)}_color: color, + border_${to_rust_ident(side)}_style: style, + border_${to_rust_ident(side)}_width: width + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + super::serialize_directional_border( + dest, + self.border_${to_rust_ident(side)}_width, + self.border_${to_rust_ident(side)}_style, + self.border_${to_rust_ident(side)}_color + ) + } + } + + </%helpers:shorthand> +% endfor + +<%helpers:shorthand name="border" + engines="gecko servo-2013 servo-2020" + sub_properties="${' '.join('border-%s-%s' % (side, prop) + for side in PHYSICAL_SIDES + for prop in ['color', 'style', 'width'])} + ${' '.join('border-image-%s' % name + for name in ['outset', 'repeat', 'slice', 'source', 'width'])}" + derive_value_info="False" + spec="https://drafts.csswg.org/css-backgrounds/#border"> + + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + use crate::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice}; + use crate::properties::longhands::{border_image_source, border_image_width}; + + let (color, style, width) = super::parse_border(context, input)?; + Ok(expanded! { + % for side in PHYSICAL_SIDES: + border_${side}_color: color.clone(), + border_${side}_style: style, + border_${side}_width: width.clone(), + % endfor + + // The ‘border’ shorthand resets ‘border-image’ to its initial value. + // See https://drafts.csswg.org/css-backgrounds-3/#the-border-shorthands + % for name in "outset repeat slice source width".split(): + border_image_${name}: border_image_${name}::get_initial_specified_value(), + % endfor + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + use crate::properties::longhands; + + // If any of the border-image longhands differ from their initial specified values we should not + // invoke serialize_directional_border(), so there is no point in continuing on to compute all_equal. + % for name in "outset repeat slice source width".split(): + if *self.border_image_${name} != longhands::border_image_${name}::get_initial_specified_value() { + return Ok(()); + } + % endfor + + let all_equal = { + % for side in PHYSICAL_SIDES: + let border_${side}_width = self.border_${side}_width; + let border_${side}_style = self.border_${side}_style; + let border_${side}_color = self.border_${side}_color; + % endfor + + border_top_width == border_right_width && + border_right_width == border_bottom_width && + border_bottom_width == border_left_width && + + border_top_style == border_right_style && + border_right_style == border_bottom_style && + border_bottom_style == border_left_style && + + border_top_color == border_right_color && + border_right_color == border_bottom_color && + border_bottom_color == border_left_color + }; + + // If all longhands are all present, then all sides should be the same, + // so we can just one set of color/style/width + if all_equal { + super::serialize_directional_border( + dest, + self.border_${side}_width, + self.border_${side}_style, + self.border_${side}_color + ) + } else { + Ok(()) + } + } + } + + // Just use the same as border-left. The border shorthand can't accept + // any value that the sub-shorthand couldn't. + <% + border_left = "<crate::properties::shorthands::border_left::Longhands as SpecifiedValueInfo>" + %> + impl SpecifiedValueInfo for Longhands { + const SUPPORTED_TYPES: u8 = ${border_left}::SUPPORTED_TYPES; + fn collect_completion_keywords(f: KeywordsCollectFn) { + ${border_left}::collect_completion_keywords(f); + } + } +</%helpers:shorthand> + +<%helpers:shorthand + name="border-radius" + engines="gecko servo-2013 servo-2020" + sub_properties="${' '.join( + 'border-%s-radius' % (corner) + for corner in ['top-left', 'top-right', 'bottom-right', 'bottom-left'] + )}" + extra_prefixes="webkit" + spec="https://drafts.csswg.org/css-backgrounds/#border-radius" +> + use crate::values::generics::rect::Rect; + use crate::values::generics::border::BorderCornerRadius; + use crate::values::specified::border::BorderRadius; + use crate::parser::Parse; + + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + let radii = BorderRadius::parse(context, input)?; + Ok(expanded! { + border_top_left_radius: radii.top_left, + border_top_right_radius: radii.top_right, + border_bottom_right_radius: radii.bottom_right, + border_bottom_left_radius: radii.bottom_left, + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + let LonghandsToSerialize { + border_top_left_radius: &BorderCornerRadius(ref tl), + border_top_right_radius: &BorderCornerRadius(ref tr), + border_bottom_right_radius: &BorderCornerRadius(ref br), + border_bottom_left_radius: &BorderCornerRadius(ref bl), + } = *self; + + + let widths = Rect::new(tl.width(), tr.width(), br.width(), bl.width()); + let heights = Rect::new(tl.height(), tr.height(), br.height(), bl.height()); + + BorderRadius::serialize_rects(widths, heights, dest) + } + } +</%helpers:shorthand> + +<%helpers:shorthand + name="border-image" + engines="gecko servo-2013" + sub_properties="border-image-outset + border-image-repeat border-image-slice border-image-source border-image-width" + extra_prefixes="moz:layout.css.prefixes.border-image webkit" + spec="https://drafts.csswg.org/css-backgrounds-3/#border-image" +> + use crate::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice}; + use crate::properties::longhands::{border_image_source, border_image_width}; + + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + % for name in "outset repeat slice source width".split(): + let mut border_image_${name} = border_image_${name}::get_initial_specified_value(); + % endfor + + let result: Result<_, ParseError> = input.try_parse(|input| { + % for name in "outset repeat slice source width".split(): + let mut ${name} = None; + % endfor + loop { + if slice.is_none() { + if let Ok(value) = input.try_parse(|input| border_image_slice::parse(context, input)) { + slice = Some(value); + // Parse border image width and outset, if applicable. + let maybe_width_outset: Result<_, ParseError> = input.try_parse(|input| { + input.expect_delim('/')?; + + // Parse border image width, if applicable. + let w = input.try_parse(|input| + border_image_width::parse(context, input)).ok(); + + // Parse border image outset if applicable. + let o = input.try_parse(|input| { + input.expect_delim('/')?; + border_image_outset::parse(context, input) + }).ok(); + if w.is_none() && o.is_none() { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + else { + Ok((w, o)) + } + }); + if let Ok((w, o)) = maybe_width_outset { + width = w; + outset = o; + } + + continue + } + } + % for name in "source repeat".split(): + if ${name}.is_none() { + if let Ok(value) = input.try_parse(|input| border_image_${name}::parse(context, input)) { + ${name} = Some(value); + continue + } + } + % endfor + break + } + let mut any = false; + % for name in "outset repeat slice source width".split(): + any = any || ${name}.is_some(); + % endfor + if any { + % for name in "outset repeat slice source width".split(): + if let Some(b_${name}) = ${name} { + border_image_${name} = b_${name}; + } + % endfor + Ok(()) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + }); + result?; + + Ok(expanded! { + % for name in "outset repeat slice source width".split(): + border_image_${name}: border_image_${name}, + % endfor + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + self.border_image_source.to_css(dest)?; + dest.write_char(' ')?; + self.border_image_slice.to_css(dest)?; + dest.write_str(" / ")?; + self.border_image_width.to_css(dest)?; + dest.write_str(" / ")?; + self.border_image_outset.to_css(dest)?; + dest.write_char(' ')?; + self.border_image_repeat.to_css(dest) + } + } +</%helpers:shorthand> + +% for axis in ["block", "inline"]: + % for prop in ["width", "style", "color"]: + <% + spec = "https://drafts.csswg.org/css-logical/#propdef-border-%s-%s" % (axis, prop) + %> + <%helpers:shorthand + engines="gecko servo-2013 servo-2020" + name="border-${axis}-${prop}" + sub_properties="${' '.join( + 'border-%s-%s-%s' % (axis, side, prop) + for side in ['start', 'end'] + )}" + spec="${spec}"> + + use crate::properties::longhands::border_${axis}_start_${prop}; + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + let start_value = border_${axis}_start_${prop}::parse(context, input)?; + let end_value = + input.try_parse(|input| border_${axis}_start_${prop}::parse(context, input)) + .unwrap_or_else(|_| start_value.clone()); + + Ok(expanded! { + border_${axis}_start_${prop}: start_value, + border_${axis}_end_${prop}: end_value, + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + self.border_${axis}_start_${prop}.to_css(dest)?; + + if self.border_${axis}_end_${prop} != self.border_${axis}_start_${prop} { + dest.write_char(' ')?; + self.border_${axis}_end_${prop}.to_css(dest)?; + } + + Ok(()) + } + } + </%helpers:shorthand> + % endfor +% endfor + +% for axis in ["block", "inline"]: + <% + spec = "https://drafts.csswg.org/css-logical/#propdef-border-%s" % (axis) + %> + <%helpers:shorthand + name="border-${axis}" + engines="gecko servo-2013 servo-2020" + sub_properties="${' '.join( + 'border-%s-%s-width' % (axis, side) + for side in ['start', 'end'] + )} ${' '.join( + 'border-%s-%s-style' % (axis, side) + for side in ['start', 'end'] + )} ${' '.join( + 'border-%s-%s-color' % (axis, side) + for side in ['start', 'end'] + )}" + spec="${spec}"> + + use crate::properties::shorthands::border_${axis}_start; + pub fn parse_value<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Longhands, ParseError<'i>> { + let start_value = border_${axis}_start::parse_value(context, input)?; + Ok(expanded! { + border_${axis}_start_width: start_value.border_${axis}_start_width.clone(), + border_${axis}_end_width: start_value.border_${axis}_start_width, + border_${axis}_start_style: start_value.border_${axis}_start_style.clone(), + border_${axis}_end_style: start_value.border_${axis}_start_style, + border_${axis}_start_color: start_value.border_${axis}_start_color.clone(), + border_${axis}_end_color: start_value.border_${axis}_start_color, + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + super::serialize_directional_border( + dest, + self.border_${axis}_start_width, + self.border_${axis}_start_style, + self.border_${axis}_start_color + ) + } + } + </%helpers:shorthand> +% endfor |