From f3dbaad222976ec9191690242cedee99802ddb92 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Fri, 17 Nov 2017 17:59:11 +0800 Subject: [PATCH] style: Support shape-image: MozReview-Commit-ID: GSCZIMEpCS2 --- components/style/gecko/conversions.rs | 68 ++++++++++++++----- components/style/properties/gecko.mako.rs | 18 ++++- .../style/values/computed/basic_shape.rs | 4 +- .../style/values/generics/basic_shape.rs | 6 +- .../style/values/specified/basic_shape.rs | 13 ++-- 5 files changed, 82 insertions(+), 27 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index c23f760fa04f..6d082549dfce 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -596,7 +596,7 @@ pub mod basic_shape { use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue}; use std::borrow::Borrow; use values::computed::ComputedUrl; - use values::computed::basic_shape::{BasicShape, ShapeRadius}; + use values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape, ShapeRadius}; use values::computed::border::{BorderCornerRadius, BorderRadius}; use values::computed::length::LengthOrPercentage; use values::computed::position; @@ -606,32 +606,68 @@ pub mod basic_shape { use values::generics::border::BorderRadius as GenericBorderRadius; use values::generics::rect::Rect; - impl<'a, ReferenceBox> From<&'a StyleShapeSource> for ShapeSource - where - ReferenceBox: From, + impl StyleShapeSource { + /// Convert StyleShapeSource to ShapeSource except URL and Image + /// types. + fn into_shape_source( + &self + ) -> Option> + where + ReferenceBox: From + { + match self.mType { + StyleShapeSourceType::None => Some(ShapeSource::None), + StyleShapeSourceType::Box => Some(ShapeSource::Box(self.mReferenceBox.into())), + StyleShapeSourceType::Shape => { + let other_shape = unsafe { &*self.mBasicShape.mPtr }; + let shape = other_shape.into(); + let reference_box = if self.mReferenceBox == StyleGeometryBox::NoBox { + None + } else { + Some(self.mReferenceBox.into()) + }; + Some(ShapeSource::Shape(shape, reference_box)) + }, + StyleShapeSourceType::URL | StyleShapeSourceType::Image => None, + } + } + } + + impl<'a> From<&'a StyleShapeSource> for ClippingShape { fn from(other: &'a StyleShapeSource) -> Self { match other.mType { - StyleShapeSourceType::None => ShapeSource::None, - StyleShapeSourceType::Box => ShapeSource::Box(other.mReferenceBox.into()), StyleShapeSourceType::URL => { unsafe { let shape_image = &*other.mShapeImage.mPtr; let other_url = &(**shape_image.__bindgen_anon_1.mURLValue.as_ref()); let url = ComputedUrl::from_url_value_data(&other_url._base).unwrap(); - ShapeSource::Url(url) + ShapeSource::ImageOrUrl(url) } }, - StyleShapeSourceType::Shape => { - let other_shape = unsafe { &*other.mBasicShape.mPtr }; - let shape = other_shape.into(); - let reference_box = if other.mReferenceBox == StyleGeometryBox::NoBox { - None - } else { - Some(other.mReferenceBox.into()) - }; - ShapeSource::Shape(shape, reference_box) + StyleShapeSourceType::Image => { + unreachable!("ClippingShape doesn't support Image!"); + } + _ => other.into_shape_source().expect("Couldn't convert to StyleSource!") + } + } + } + + impl<'a> From<&'a StyleShapeSource> for FloatAreaShape + { + fn from(other: &'a StyleShapeSource) -> Self { + match other.mType { + StyleShapeSourceType::URL => { + unreachable!("FloatAreaShape doesn't support URL!"); + }, + StyleShapeSourceType::Image => { + unsafe { + let shape_image = &*other.mShapeImage.mPtr; + let image = shape_image.into_image().expect("Cannot convert to Image"); + ShapeSource::ImageOrUrl(image) + } } + _ => other.into_shape_source().expect("Couldn't convert to StyleSource!") } } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 2030a27f503e..8db4433ab171 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -5008,18 +5008,32 @@ fn static_assert() { use gecko::conversions::basic_shape::set_corners_from_radius; use gecko::values::GeckoStyleCoordConvertible; use values::generics::basic_shape::{BasicShape, FillRule, ShapeSource}; + let ref mut ${ident} = self.gecko.${gecko_ffi_name}; + // clean up existing struct unsafe { Gecko_DestroyShapeSource(${ident}) }; - ${ident}.mType = StyleShapeSourceType::None; match v { - ShapeSource::Url(ref url) => { + % if ident == "clip_path": + ShapeSource::ImageOrUrl(ref url) => { unsafe { bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.for_ffi()) } } + % elif ident == "shape_outside": + ShapeSource::ImageOrUrl(image) => { + unsafe { + bindings::Gecko_NewShapeImage(${ident}); + let style_image = &mut *${ident}.mShapeImage.mPtr; + style_image.set(image); + } + } + % else: + <% raise Exception("Unknown property: %s" % ident) %> + } + % endif ShapeSource::None => {} // don't change the type ShapeSource::Box(reference) => { ${ident}.mReferenceBox = reference.into(); diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 2b4feecfba88..20dcffec9c6d 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -9,7 +9,7 @@ use std::fmt; use style_traits::ToCss; -use values::computed::{LengthOrPercentage, ComputedUrl}; +use values::computed::{LengthOrPercentage, ComputedUrl, Image}; use values::generics::basic_shape::{BasicShape as GenericBasicShape}; use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape}; use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape}; @@ -19,7 +19,7 @@ use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius a pub type ClippingShape = GenericClippingShape; /// A computed float area shape. -pub type FloatAreaShape = GenericFloatAreaShape; +pub type FloatAreaShape = GenericFloatAreaShape; /// A computed basic shape. pub type BasicShape = GenericBasicShape; diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 12c7411dbf93..a2f0eb089719 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -27,7 +27,7 @@ pub enum GeometryBox { } /// A float area shape, for `shape-outside`. -pub type FloatAreaShape = ShapeSource; +pub type FloatAreaShape = ShapeSource; // https://drafts.csswg.org/css-shapes-1/#typedef-shape-box define_css_keyword_enum!(ShapeBox: @@ -41,9 +41,9 @@ add_impls_for_keyword_enum!(ShapeBox); /// A shape source, for some reference box. #[allow(missing_docs)] #[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] -pub enum ShapeSource { +pub enum ShapeSource { #[animation(error)] - Url(Url), + ImageOrUrl(ImageOrUrl), Shape( BasicShape, #[animation(constant)] diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index dbc63adee068..e6d612c7ee7a 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -22,6 +22,7 @@ use values::generics::basic_shape::{Polygon as GenericPolygon, ShapeRadius as Ge use values::generics::rect::Rect; use values::specified::LengthOrPercentage; use values::specified::border::BorderRadius; +use values::specified::image::Image; use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition}; use values::specified::url::SpecifiedUrl; @@ -29,7 +30,7 @@ use values::specified::url::SpecifiedUrl; pub type ClippingShape = GenericClippingShape; /// A specified float area shape. -pub type FloatAreaShape = GenericFloatAreaShape; +pub type FloatAreaShape = GenericFloatAreaShape; /// A specified basic shape. pub type BasicShape = GenericBasicShape; @@ -49,14 +50,18 @@ pub type ShapeRadius = GenericShapeRadius; /// The specified value of `Polygon` pub type Polygon = GenericPolygon; -impl Parse for ShapeSource { +impl Parse for ShapeSource +where + ReferenceBox: Parse, + ImageOrUrl: Parse, +{ fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> 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)) + if let Ok(image_or_url) = input.try(|i| ImageOrUrl::parse(context, i)) { + return Ok(ShapeSource::ImageOrUrl(image_or_url)) } fn parse_component(context: &ParserContext, input: &mut Parser,