diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 863d9438a3e..9d49387322e 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3564,12 +3564,12 @@ fn static_assert() { <%def name="impl_shape_source(ident, gecko_ffi_name)"> pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { use gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource}; - use gecko_bindings::structs::StyleGeometryBox; use gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType}; - use gecko_bindings::structs::{StyleFillRule, StyleShapeSource}; + use gecko_bindings::structs::{StyleFillRule, StyleGeometryBox, StyleShapeSource}; use gecko::conversions::basic_shape::set_corners_from_radius; use gecko::values::GeckoStyleCoordConvertible; - use values::computed::basic_shape::*; + use values::computed::basic_shape::BasicShape; + use values::generics::basic_shape::{ShapeSource, FillRule}; let ref mut ${ident} = self.gecko.${gecko_ffi_name}; // clean up existing struct unsafe { Gecko_DestroyShapeSource(${ident}) }; @@ -3579,7 +3579,7 @@ fn static_assert() { match v { ShapeSource::Url(ref url) => { unsafe { - bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.for_ffi()); + bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.for_ffi()) } } ShapeSource::None => {} // don't change the type diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 1a520af8344..5d13f91e282 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -248,7 +248,7 @@ use properties::style_structs; use std::sync::Arc; use values::computed::{Context, ToComputedValue}; - use values::{computed, specified}; + use values::{computed, generics, specified}; use Atom; ${caller.body()} #[allow(unused_variables)] diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 57a798e5a51..71d101b9c6e 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -2462,29 +2462,8 @@ ${helpers.single_keyword("-moz-orient", } -<%helpers:longhand name="shape-outside" products="gecko" animation_value_type="none" boxed="True" - spec="https://drafts.csswg.org/css-shapes/#shape-outside-property"> - use std::fmt; - use style_traits::ToCss; - use values::specified::basic_shape::{ShapeBox, ShapeSource}; - use values::HasViewportPercentage; - - no_viewport_percentage!(SpecifiedValue); - - pub mod computed_value { - use values::computed::basic_shape::{ShapeBox, ShapeSource}; - - pub type T = ShapeSource; - } - - pub type SpecifiedValue = ShapeSource; - - #[inline] - pub fn get_initial_value() -> computed_value::T { - Default::default() - } - - pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { - ShapeSource::parse(context, input) - } - +${helpers.predefined_type("shape-outside", "basic_shape::ShapeWithShapeBox", + "generics::basic_shape::ShapeSource::None", + products="gecko", boxed="True", + animation_value_type="none", + spec="https://drafts.csswg.org/css-shapes/#shape-outside-property")} diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs index eb9f9156a42..7a764fbe9f5 100644 --- a/components/style/properties/longhand/svg.mako.rs +++ b/components/style/properties/longhand/svg.mako.rs @@ -58,34 +58,11 @@ ${helpers.single_keyword("mask-type", "luminance alpha", products="gecko", animation_value_type="none", spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")} -<%helpers:longhand name="clip-path" animation_value_type="none" products="gecko" boxed="True" - flags="CREATES_STACKING_CONTEXT" - spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path"> - use std::fmt; - use style_traits::ToCss; - use values::HasViewportPercentage; - use values::specified::basic_shape::{ShapeSource, GeometryBox}; - - pub mod computed_value { - use app_units::Au; - use values::computed::basic_shape::{ShapeSource, GeometryBox}; - - pub type T = ShapeSource; - } - - pub type SpecifiedValue = ShapeSource; - - #[inline] - pub fn get_initial_value() -> computed_value::T { - Default::default() - } - - pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { - ShapeSource::parse(context, input) - } - - no_viewport_percentage!(SpecifiedValue); - +${helpers.predefined_type("clip-path", "basic_shape::ShapeWithGeometryBox", + "generics::basic_shape::ShapeSource::None", + products="gecko", boxed="True", + animation_value_type="none", flags="CREATES_STACKING_CONTEXT", + spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path")} ${helpers.single_keyword("mask-mode", "match-source alpha luminance", diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 784293b95d3..eb5d67a98db 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -12,45 +12,16 @@ use style_traits::ToCss; use values::computed::LengthOrPercentage; use values::computed::position::Position; use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, ShapeRadius as GenericShapeRadius}; -use values::generics::basic_shape::{InsetRect as GenericInsetRect, Polygon as GenericPolygon}; -use values::specified::url::SpecifiedUrl; +use values::generics::basic_shape::{InsetRect as GenericInsetRect, Polygon as GenericPolygon, ShapeSource}; pub use values::generics::basic_shape::FillRule; pub use values::specified::basic_shape::{self, GeometryBox, ShapeBox}; -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub enum ShapeSource { - Url(SpecifiedUrl), - Shape(BasicShape, Option), - Box(T), - None, -} - -impl Default for ShapeSource { - fn default() -> Self { - ShapeSource::None - } -} - -impl ToCss for ShapeSource { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - ShapeSource::Url(ref url) => url.to_css(dest), - ShapeSource::Shape(ref shape, Some(ref reference)) => { - try!(shape.to_css(dest)); - try!(dest.write_str(" ")); - reference.to_css(dest) - } - ShapeSource::Shape(ref shape, None) => shape.to_css(dest), - ShapeSource::Box(ref reference) => reference.to_css(dest), - ShapeSource::None => dest.write_str("none"), - - } - } -} +/// The computed value used by `clip-path` +pub type ShapeWithGeometryBox = ShapeSource; +/// The computed value used by `shape-outside` +pub type ShapeWithShapeBox = ShapeSource; #[derive(Clone, PartialEq, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 9bfa973f85a..d961141dbc9 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -12,8 +12,10 @@ use properties::shorthands::serialize_four_sides; use std::ascii::AsciiExt; use std::fmt; use style_traits::ToCss; +use values::HasViewportPercentage; use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::generics::BorderRadiusSize; +use values::specified::url::SpecifiedUrl; /// A generic type used for `border-radius`, `outline-radius` and `inset()` values. /// @@ -292,3 +294,104 @@ impl ToComputedValue for InsetRect { } } } + +/// A shape source, for some reference box +/// +/// `clip-path` uses ShapeSource, +/// `shape-outside` uses ShapeSource +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub enum ShapeSource { + Url(SpecifiedUrl), + Shape(B, Option), + Box(T), + None, +} + +impl HasViewportPercentage for ShapeSource { + #[inline] + fn has_viewport_percentage(&self) -> bool { false } +} + +impl ToCss for ShapeSource { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + ShapeSource::Url(ref url) => url.to_css(dest), + ShapeSource::Shape(ref shape, Some(ref ref_box)) => { + shape.to_css(dest)?; + dest.write_str(" ")?; + ref_box.to_css(dest) + }, + ShapeSource::Shape(ref shape, None) => shape.to_css(dest), + ShapeSource::Box(ref val) => val.to_css(dest), + ShapeSource::None => dest.write_str("none"), + } + } +} + +impl Parse for ShapeSource { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(ShapeSource::None) + } + + if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { + return Ok(ShapeSource::Url(url)) + } + + fn parse_component(context: &ParserContext, input: &mut Parser, + component: &mut Option) -> bool { + if component.is_some() { + return false // already parsed this component + } + + *component = input.try(|i| U::parse(context, i)).ok(); + component.is_some() + } + + let mut shape = None; + let mut ref_box = None; + + while parse_component(context, input, &mut shape) || + parse_component(context, input, &mut ref_box) { + // + } + + if let Some(shp) = shape { + return Ok(ShapeSource::Shape(shp, ref_box)) + } + + ref_box.map(|v| ShapeSource::Box(v)).ok_or(()) + } +} + +impl ToComputedValue for ShapeSource { + type ComputedValue = ShapeSource; + + #[inline] + fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { + match *self { + ShapeSource::Url(ref url) => ShapeSource::Url(url.to_computed_value(cx)), + ShapeSource::Shape(ref shape, ref ref_box) => { + ShapeSource::Shape(shape.to_computed_value(cx), + ref_box.as_ref().map(|ref val| val.to_computed_value(cx))) + }, + ShapeSource::Box(ref ref_box) => ShapeSource::Box(ref_box.to_computed_value(cx)), + ShapeSource::None => ShapeSource::None, + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + ShapeSource::Url(ref url) => ShapeSource::Url(SpecifiedUrl::from_computed_value(url)), + ShapeSource::Shape(ref shape, ref ref_box) => { + ShapeSource::Shape(ToComputedValue::from_computed_value(shape), + ref_box.as_ref().map(|val| ToComputedValue::from_computed_value(val))) + }, + ShapeSource::Box(ref ref_box) => ShapeSource::Box(ToComputedValue::from_computed_value(ref_box)), + ShapeSource::None => ShapeSource::None, + } + } +} diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 4941655d5d1..9d1176dad70 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -18,121 +18,15 @@ use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::computed::basic_shape as computed_basic_shape; use values::generics::BorderRadiusSize; use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, ShapeRadius as GenericShapeRadius}; -use values::generics::basic_shape::{InsetRect as GenericInsetRect, Polygon as GenericPolygon}; +use values::generics::basic_shape::{InsetRect as GenericInsetRect, Polygon as GenericPolygon, ShapeSource}; use values::specified::{LengthOrPercentage, Percentage}; use values::specified::position::{Keyword, Position}; -use values::specified::url::SpecifiedUrl; -/// A shape source, for some reference box -/// -/// clip-path uses ShapeSource, -/// shape-outside uses ShapeSource -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub enum ShapeSource { - Url(SpecifiedUrl), - Shape(BasicShape, Option), - Box(T), - None, -} +/// The specified value used by `clip-path` +pub type ShapeWithGeometryBox = ShapeSource; -impl Default for ShapeSource { - fn default() -> Self { - ShapeSource::None - } -} - -impl ToCss for ShapeSource { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - ShapeSource::Url(ref url) => url.to_css(dest), - ShapeSource::Shape(ref shape, Some(ref reference)) => { - try!(shape.to_css(dest)); - try!(dest.write_str(" ")); - reference.to_css(dest) - } - ShapeSource::Shape(ref shape, None) => shape.to_css(dest), - ShapeSource::Box(ref reference) => reference.to_css(dest), - ShapeSource::None => dest.write_str("none"), - - } - } -} - -impl Parse for ShapeSource { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - if input.try(|input| input.expect_ident_matching("none")).is_ok() { - return Ok(ShapeSource::None) - } - - if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) { - return Ok(ShapeSource::Url(url)) - } - - fn parse_component(context: &ParserContext, input: &mut Parser, - component: &mut Option) -> bool { - if component.is_some() { - return false // already parsed this component - } - - *component = input.try(|i| U::parse(context, i)).ok(); - component.is_some() - } - - let mut shape = None; - let mut reference = None; - - while parse_component(context, input, &mut shape) || - parse_component(context, input, &mut reference) { - // - } - - if let Some(shp) = shape { - return Ok(ShapeSource::Shape(shp, reference)) - } - - match reference { - Some(r) => Ok(ShapeSource::Box(r)), - None => Err(()) - } - } -} - -impl ToComputedValue for ShapeSource { - type ComputedValue = computed_basic_shape::ShapeSource; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - match *self { - ShapeSource::Url(ref url) => computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx)), - ShapeSource::Shape(ref shape, ref reference) => { - computed_basic_shape::ShapeSource::Shape( - shape.to_computed_value(cx), - reference.as_ref().map(|ref r| r.to_computed_value(cx))) - }, - ShapeSource::Box(ref reference) => - computed_basic_shape::ShapeSource::Box(reference.to_computed_value(cx)), - ShapeSource::None => computed_basic_shape::ShapeSource::None, - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - computed_basic_shape::ShapeSource::Url(ref url) => - ShapeSource::Url(SpecifiedUrl::from_computed_value(url)), - computed_basic_shape::ShapeSource::Shape(ref shape, ref reference) => { - ShapeSource::Shape( - ToComputedValue::from_computed_value(shape), - reference.as_ref().map(|r| ToComputedValue::from_computed_value(r))) - } - computed_basic_shape::ShapeSource::Box(ref reference) => - ShapeSource::Box(ToComputedValue::from_computed_value(reference)), - computed_basic_shape::ShapeSource::None => ShapeSource::None, - } - } -} +/// The specified value used by `shape-outside` +pub type ShapeWithShapeBox = ShapeSource; #[derive(Clone, PartialEq, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]