Skip to content
Permalink
Browse files

Make ShapeSource generic

  • Loading branch information
wafflespeanut committed Apr 25, 2017
1 parent 24226af commit d56aec41098c8ec2bade43f0aff273ee6326d8d5
@@ -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
@@ -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)]
@@ -2462,29 +2462,8 @@ ${helpers.single_keyword("-moz-orient",
}
</%helpers:longhand>

<%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<ShapeBox>;
}

pub type SpecifiedValue = ShapeSource<ShapeBox>;

#[inline]
pub fn get_initial_value() -> computed_value::T {
Default::default()
}

pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
ShapeSource::parse(context, input)
}
</%helpers:longhand>
${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")}
@@ -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<GeometryBox>;
}

pub type SpecifiedValue = ShapeSource<GeometryBox>;

#[inline]
pub fn get_initial_value() -> computed_value::T {
Default::default()
}

pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
ShapeSource::parse(context, input)
}

no_viewport_percentage!(SpecifiedValue);
</%helpers:longhand>
${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",
@@ -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<T> {
Url(SpecifiedUrl),
Shape(BasicShape, Option<T>),
Box(T),
None,
}

impl<T> Default for ShapeSource<T> {
fn default() -> Self {
ShapeSource::None
}
}

impl<T: ToCss> ToCss for ShapeSource<T> {
fn to_css<W>(&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<BasicShape, GeometryBox>;

/// The computed value used by `shape-outside`
pub type ShapeWithShapeBox = ShapeSource<BasicShape, ShapeBox>;

#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -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<L: ToComputedValue> ToComputedValue for InsetRect<L> {
}
}
}

/// A shape source, for some reference box
///
/// `clip-path` uses ShapeSource<BasicShape, GeometryBox>,
/// `shape-outside` uses ShapeSource<BasicShape, ShapeBox>
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum ShapeSource<B, T> {
Url(SpecifiedUrl),
Shape(B, Option<T>),
Box(T),
None,
}

impl<B, T> HasViewportPercentage for ShapeSource<B, T> {
#[inline]
fn has_viewport_percentage(&self) -> bool { false }
}

impl<B: ToCss, T: ToCss> ToCss for ShapeSource<B, T> {
fn to_css<W>(&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<B: Parse, T: Parse> Parse for ShapeSource<B, T> {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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<U: Parse>(context: &ParserContext, input: &mut Parser,
component: &mut Option<U>) -> 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<B: ToComputedValue, T: ToComputedValue> ToComputedValue for ShapeSource<B, T> {
type ComputedValue = ShapeSource<B::ComputedValue, T::ComputedValue>;

#[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,
}
}
}

0 comments on commit d56aec4

Please sign in to comment.
You can’t perform that action at this time.