From 4dadcf71a5c315953dc78806c7c3f40141884fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 11 Feb 2020 20:56:13 +0000 Subject: [PATCH] style: Some preparation to start using cbindgen for shape-outside and clip-path. Tweak the ShapeSourceRepresentation so that it doesn't store Option<>s. Some renames so that GeometryBox doesn't conflict with the Gecko type, and some other usual bits / re-exports to deal with cbindgen and generics. Also, drive-by derive parsing of GeometryBox as it's trivial. Doing this unfortunately is not possible without removing nsStyleImage first, so let's do that before. This makes us serialize in the shortest form for shape-outside, but that's what we should do anyway. (aside: the shapes code is a bit too generic, maybe we should unify ClippingShape and FloatAreaShape...) Differential Revision: https://phabricator.services.mozilla.com/D62163 --- components/style/gecko/conversions.rs | 45 +++++++------- components/style/properties/gecko.mako.rs | 6 +- .../style/values/computed/basic_shape.rs | 4 +- .../style/values/generics/basic_shape.rs | 59 +++++++++++++++---- .../style/values/specified/basic_shape.rs | 30 ++-------- 5 files changed, 76 insertions(+), 68 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 5390d904d02..52007c55622 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -99,7 +99,7 @@ pub mod basic_shape { }; use crate::values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape}; use crate::values::computed::motion::OffsetPath; - use crate::values::generics::basic_shape::{GeometryBox, Path, ShapeBox, ShapeSource}; + use crate::values::generics::basic_shape::{ShapeGeometryBox, Path, ShapeBox, ShapeSource}; use crate::values::specified::SVGPathData; impl StyleShapeSource { @@ -109,7 +109,7 @@ pub mod basic_shape { &self, ) -> Option> where - ReferenceBox: From, + ReferenceBox: From + Default + PartialEq, { match self.mType { StyleShapeSourceType::None => Some(ShapeSource::None), @@ -117,11 +117,7 @@ pub mod basic_shape { StyleShapeSourceType::Shape => { let other_shape = unsafe { &*self.__bindgen_anon_1.mBasicShape.as_ref().mPtr }; let shape = Box::new(other_shape.clone()); - let reference_box = if self.mReferenceBox == StyleGeometryBox::NoBox { - None - } else { - Some(self.mReferenceBox.into()) - }; + let reference_box = self.mReferenceBox.into(); Some(ShapeSource::Shape(shape, reference_box)) }, StyleShapeSourceType::Image => None, @@ -207,33 +203,32 @@ pub mod basic_shape { } } - impl From for StyleGeometryBox { - fn from(reference: GeometryBox) -> Self { + impl From for StyleGeometryBox { + fn from(reference: ShapeGeometryBox) -> Self { use crate::gecko_bindings::structs::StyleGeometryBox::*; match reference { - GeometryBox::ShapeBox(shape_box) => From::from(shape_box), - GeometryBox::FillBox => FillBox, - GeometryBox::StrokeBox => StrokeBox, - GeometryBox::ViewBox => ViewBox, + ShapeGeometryBox::ShapeBox(shape_box) => From::from(shape_box), + ShapeGeometryBox::FillBox => FillBox, + ShapeGeometryBox::StrokeBox => StrokeBox, + ShapeGeometryBox::ViewBox => ViewBox, + ShapeGeometryBox::ElementDependent => NoBox, } } } - // Will panic on NoBox - // Ideally these would be implemented on Option, - // but coherence doesn't like that and TryFrom isn't stable - impl From for GeometryBox { + impl From for ShapeGeometryBox { fn from(reference: StyleGeometryBox) -> Self { use crate::gecko_bindings::structs::StyleGeometryBox::*; match reference { - ContentBox => GeometryBox::ShapeBox(ShapeBox::ContentBox), - PaddingBox => GeometryBox::ShapeBox(ShapeBox::PaddingBox), - BorderBox => GeometryBox::ShapeBox(ShapeBox::BorderBox), - MarginBox => GeometryBox::ShapeBox(ShapeBox::MarginBox), - FillBox => GeometryBox::FillBox, - StrokeBox => GeometryBox::StrokeBox, - ViewBox => GeometryBox::ViewBox, - _ => panic!("Unexpected StyleGeometryBox while converting to GeometryBox"), + ContentBox => ShapeGeometryBox::ShapeBox(ShapeBox::ContentBox), + PaddingBox => ShapeGeometryBox::ShapeBox(ShapeBox::PaddingBox), + BorderBox => ShapeGeometryBox::ShapeBox(ShapeBox::BorderBox), + MarginBox => ShapeGeometryBox::ShapeBox(ShapeBox::MarginBox), + FillBox => ShapeGeometryBox::FillBox, + StrokeBox => ShapeGeometryBox::StrokeBox, + ViewBox => ShapeGeometryBox::ViewBox, + NoBox => ShapeGeometryBox::ElementDependent, + NoClip | Text | MozAlmostPadding => unreachable!(), } } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index e6cd75e2ee0..1a9eba8eff8 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2247,7 +2247,6 @@ fn set_style_svg_path( pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { use crate::values::generics::basic_shape::ShapeSource; use crate::gecko_bindings::structs::StyleShapeSourceType; - use crate::gecko_bindings::structs::StyleGeometryBox; let ref mut ${ident} = self.gecko.${gecko_ffi_name}; @@ -2275,13 +2274,12 @@ fn set_style_svg_path( ${ident}.mType = StyleShapeSourceType::Box; } ShapeSource::Path(p) => set_style_svg_path(${ident}, p.path, p.fill), - ShapeSource::Shape(servo_shape, maybe_box) => { + ShapeSource::Shape(servo_shape, reference_box) => { unsafe { ${ident}.__bindgen_anon_1.mBasicShape.as_mut().mPtr = Box::into_raw(servo_shape); } - ${ident}.mReferenceBox = - maybe_box.map(Into::into).unwrap_or(StyleGeometryBox::NoBox); + ${ident}.mReferenceBox = reference_box.into(); ${ident}.mType = StyleShapeSourceType::Shape; } } diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 27a091a1115..2b36809fd7e 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -15,10 +15,10 @@ use crate::values::generics::basic_shape as generic; pub use crate::values::generics::basic_shape::FillRule; /// A computed clipping shape. -pub type ClippingShape = generic::ClippingShape; +pub type ClippingShape = generic::GenericClippingShape; /// A computed float area shape. -pub type FloatAreaShape = generic::FloatAreaShape; +pub type FloatAreaShape = generic::GenericFloatAreaShape; /// A computed basic shape. pub type BasicShape = generic::GenericBasicShape< diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index d91fa58eb0d..92a0a6d7839 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -16,7 +16,7 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; /// A clipping shape, for `clip-path`. -pub type ClippingShape = ShapeSource; +pub type GenericClippingShape = GenericShapeSource; /// #[allow(missing_docs)] @@ -27,6 +27,7 @@ pub type ClippingShape = ShapeSource = ShapeSource Self { + Self::ElementDependent + } +} + /// A float area shape, for `shape-outside`. -pub type FloatAreaShape = ShapeSource; +pub type GenericFloatAreaShape = GenericShapeSource; /// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box #[allow(missing_docs)] @@ -63,6 +79,7 @@ pub type FloatAreaShape = ShapeSource Self { + ShapeBox::MarginBox + } +} + /// A shape source, for some reference box. #[allow(missing_docs)] -#[animation(no_bound(ImageOrUrl))] +#[animation(no_bound(I))] #[derive( Animate, Clone, @@ -86,10 +109,14 @@ pub enum ShapeBox { ToResolvedValue, ToShmem, )] -pub enum ShapeSource { +#[repr(u8)] +pub enum GenericShapeSource +where + ReferenceBox: Default + PartialEq, +{ #[animation(error)] - ImageOrUrl(ImageOrUrl), - Shape(Box, Option), + ImageOrUrl(I), + Shape(Box, #[css(skip_if = "is_default")] ReferenceBox), #[animation(error)] Box(ReferenceBox), #[css(function)] @@ -98,6 +125,8 @@ pub enum ShapeSource { None, } +pub use self::GenericShapeSource as ShapeSource; + #[allow(missing_docs)] #[derive( Animate, @@ -252,7 +281,7 @@ pub use self::GenericShapeRadius as ShapeRadius; #[repr(C)] pub struct GenericPolygon { /// The filling rule for a polygon. - #[css(skip_if = "fill_is_default")] + #[css(skip_if = "is_default")] pub fill: FillRule, /// A collection of (x, y) coordinates to draw the polygon. #[css(iterable)] @@ -321,9 +350,10 @@ pub enum FillRule { ToResolvedValue, ToShmem, )] +#[repr(C)] pub struct Path { /// The filling rule for the svg path. - #[css(skip_if = "fill_is_default")] + #[css(skip_if = "is_default")] #[animation(constant)] pub fill: FillRule, /// The svg path data. @@ -335,7 +365,7 @@ pub struct Path { impl ComputeSquaredDistance for ShapeSource where B: ComputeSquaredDistance, - T: PartialEq, + T: Default + PartialEq, { fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { @@ -353,7 +383,10 @@ where } } -impl ToAnimatedZero for ShapeSource { +impl ToAnimatedZero for ShapeSource +where + T: Default + PartialEq, +{ fn to_animated_zero(&self) -> Result { Err(()) } @@ -488,6 +521,6 @@ impl Default for FillRule { } #[inline] -fn fill_is_default(fill: &FillRule) -> bool { - *fill == FillRule::default() +fn is_default(fill: &T) -> bool { + *fill == Default::default() } diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 68938b4e6dd..188ec19279f 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -9,8 +9,7 @@ use crate::parser::{Parse, ParserContext}; use crate::values::generics::basic_shape as generic; -use crate::values::generics::basic_shape::{GeometryBox, Path, PolygonCoord}; -use crate::values::generics::basic_shape::{ShapeBox, ShapeSource}; +use crate::values::generics::basic_shape::{Path, PolygonCoord, ShapeSource}; use crate::values::generics::rect::Rect; use crate::values::specified::border::BorderRadius; use crate::values::specified::image::Image; @@ -26,13 +25,13 @@ use style_traits::{ParseError, StyleParseErrorKind}; pub use crate::values::generics::basic_shape::FillRule; /// A specified clipping shape. -pub type ClippingShape = generic::ClippingShape; +pub type ClippingShape = generic::GenericClippingShape; /// A specified float area shape. -pub type FloatAreaShape = generic::FloatAreaShape; +pub type FloatAreaShape = generic::GenericFloatAreaShape; /// A specified basic shape. -pub type BasicShape = generic::BasicShape< +pub type BasicShape = generic::GenericBasicShape< HorizontalPosition, VerticalPosition, LengthPercentage, @@ -112,7 +111,7 @@ impl Parse for FloatAreaShape { impl ShapeSource where - ReferenceBox: Parse, + ReferenceBox: Parse + Default + PartialEq, { /// The internal parser for ShapeSource. fn parse_common<'i, 't>( @@ -142,7 +141,7 @@ where } if let Some(shp) = shape { - return Ok(ShapeSource::Shape(Box::new(shp), ref_box)); + return Ok(ShapeSource::Shape(Box::new(shp), ref_box.unwrap_or_default())); } ref_box @@ -151,23 +150,6 @@ where } } -impl Parse for GeometryBox { - fn parse<'i, 't>( - _context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - if let Ok(shape_box) = input.try(ShapeBox::parse) { - return Ok(GeometryBox::ShapeBox(shape_box)); - } - - try_match_ident_ignore_ascii_case! { input, - "fill-box" => Ok(GeometryBox::FillBox), - "stroke-box" => Ok(GeometryBox::StrokeBox), - "view-box" => Ok(GeometryBox::ViewBox), - } - } -} - impl Parse for BasicShape { fn parse<'i, 't>( context: &ParserContext,