mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Auto merge of #19415 - aethanyc:shape-image, r=heycam
style: Support shape-image: <image> This was reviewed in nhttps://bugzilla.mozilla.org/show_bug.cgi?id=1418224 Reland #19376 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19415) <!-- Reviewable:end -->
This commit is contained in:
commit
1f30196a37
7 changed files with 105 additions and 48 deletions
|
@ -596,7 +596,7 @@ pub mod basic_shape {
|
||||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
|
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use values::computed::ComputedUrl;
|
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::border::{BorderCornerRadius, BorderRadius};
|
||||||
use values::computed::length::LengthOrPercentage;
|
use values::computed::length::LengthOrPercentage;
|
||||||
use values::computed::position;
|
use values::computed::position;
|
||||||
|
@ -606,32 +606,68 @@ pub mod basic_shape {
|
||||||
use values::generics::border::BorderRadius as GenericBorderRadius;
|
use values::generics::border::BorderRadius as GenericBorderRadius;
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
|
|
||||||
impl<'a, ReferenceBox> From<&'a StyleShapeSource> for ShapeSource<BasicShape, ReferenceBox, ComputedUrl>
|
impl StyleShapeSource {
|
||||||
where
|
/// Convert StyleShapeSource to ShapeSource except URL and Image
|
||||||
ReferenceBox: From<StyleGeometryBox>,
|
/// types.
|
||||||
|
fn into_shape_source<ReferenceBox, ImageOrUrl>(
|
||||||
|
&self
|
||||||
|
) -> Option<ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>>
|
||||||
|
where
|
||||||
|
ReferenceBox: From<StyleGeometryBox>
|
||||||
|
{
|
||||||
|
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 {
|
fn from(other: &'a StyleShapeSource) -> Self {
|
||||||
match other.mType {
|
match other.mType {
|
||||||
StyleShapeSourceType::None => ShapeSource::None,
|
|
||||||
StyleShapeSourceType::Box => ShapeSource::Box(other.mReferenceBox.into()),
|
|
||||||
StyleShapeSourceType::URL => {
|
StyleShapeSourceType::URL => {
|
||||||
unsafe {
|
unsafe {
|
||||||
let shape_image = &*other.mShapeImage.mPtr;
|
let shape_image = &*other.mShapeImage.mPtr;
|
||||||
let other_url = &(**shape_image.__bindgen_anon_1.mURLValue.as_ref());
|
let other_url = &(**shape_image.__bindgen_anon_1.mURLValue.as_ref());
|
||||||
let url = ComputedUrl::from_url_value_data(&other_url._base).unwrap();
|
let url = ComputedUrl::from_url_value_data(&other_url._base).unwrap();
|
||||||
ShapeSource::Url(url)
|
ShapeSource::ImageOrUrl(url)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StyleShapeSourceType::Shape => {
|
StyleShapeSourceType::Image => {
|
||||||
let other_shape = unsafe { &*other.mBasicShape.mPtr };
|
unreachable!("ClippingShape doesn't support Image!");
|
||||||
let shape = other_shape.into();
|
|
||||||
let reference_box = if other.mReferenceBox == StyleGeometryBox::NoBox {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(other.mReferenceBox.into())
|
|
||||||
};
|
|
||||||
ShapeSource::Shape(shape, reference_box)
|
|
||||||
}
|
}
|
||||||
|
_ => 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!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -817,6 +817,8 @@ extern "C" {
|
||||||
pub fn Gecko_DestroyShapeSource ( shape : * mut StyleShapeSource , ) ;
|
pub fn Gecko_DestroyShapeSource ( shape : * mut StyleShapeSource , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_NewBasicShape ( shape : * mut StyleShapeSource , type_ : StyleBasicShapeType , ) ;
|
pub fn Gecko_NewBasicShape ( shape : * mut StyleShapeSource , type_ : StyleBasicShapeType , ) ;
|
||||||
|
} extern "C" {
|
||||||
|
pub fn Gecko_NewShapeImage ( shape : * mut StyleShapeSource , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_StyleShapeSource_SetURLValue ( shape : * mut StyleShapeSource , uri : ServoBundledURI , ) ;
|
pub fn Gecko_StyleShapeSource_SetURLValue ( shape : * mut StyleShapeSource , uri : ServoBundledURI , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
@ -1578,7 +1580,7 @@ extern "C" {
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Servo_ParseIntersectionObserverRootMargin ( value : * const nsAString , result : * mut nsCSSRect , ) -> bool ;
|
pub fn Servo_ParseIntersectionObserverRootMargin ( value : * const nsAString , result : * mut nsCSSRect , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Servo_ParseTransformIntoMatrix ( value : * const nsAString , contains_3d_transform : * mut bool , result : * mut RawGeckoGfxMatrix4x4 , ) -> bool ;
|
pub fn Servo_ParseTransformIntoMatrix ( value : * const nsAString , contains_3d_transform : * mut bool , result : * mut RawGeckoGfxMatrix4x4 , ) -> bool ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_CreateCSSErrorReporter ( sheet : * mut ServoStyleSheet , loader : * mut Loader , uri : * mut nsIURI , ) -> * mut ErrorReporter ;
|
pub fn Gecko_CreateCSSErrorReporter ( sheet : * mut ServoStyleSheet , loader : * mut Loader , uri : * mut nsIURI , ) -> * mut ErrorReporter ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
|
@ -1589,4 +1591,4 @@ extern "C" {
|
||||||
pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ;
|
pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ;
|
||||||
} extern "C" {
|
} extern "C" {
|
||||||
pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ;
|
pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ;
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
|
@ -5008,18 +5008,32 @@ fn static_assert() {
|
||||||
use gecko::conversions::basic_shape::set_corners_from_radius;
|
use gecko::conversions::basic_shape::set_corners_from_radius;
|
||||||
use gecko::values::GeckoStyleCoordConvertible;
|
use gecko::values::GeckoStyleCoordConvertible;
|
||||||
use values::generics::basic_shape::{BasicShape, FillRule, ShapeSource};
|
use values::generics::basic_shape::{BasicShape, FillRule, ShapeSource};
|
||||||
|
|
||||||
let ref mut ${ident} = self.gecko.${gecko_ffi_name};
|
let ref mut ${ident} = self.gecko.${gecko_ffi_name};
|
||||||
|
|
||||||
// clean up existing struct
|
// clean up existing struct
|
||||||
unsafe { Gecko_DestroyShapeSource(${ident}) };
|
unsafe { Gecko_DestroyShapeSource(${ident}) };
|
||||||
|
|
||||||
${ident}.mType = StyleShapeSourceType::None;
|
${ident}.mType = StyleShapeSourceType::None;
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
ShapeSource::Url(ref url) => {
|
% if ident == "clip_path":
|
||||||
|
ShapeSource::ImageOrUrl(ref url) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.for_ffi())
|
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::None => {} // don't change the type
|
||||||
ShapeSource::Box(reference) => {
|
ShapeSource::Box(reference) => {
|
||||||
${ident}.mReferenceBox = reference.into();
|
${ident}.mReferenceBox = reference.into();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
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::{BasicShape as GenericBasicShape};
|
||||||
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
|
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
|
||||||
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
|
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<BasicShape, ComputedUrl>;
|
pub type ClippingShape = GenericClippingShape<BasicShape, ComputedUrl>;
|
||||||
|
|
||||||
/// A computed float area shape.
|
/// A computed float area shape.
|
||||||
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, ComputedUrl>;
|
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, Image>;
|
||||||
|
|
||||||
/// A computed basic shape.
|
/// A computed basic shape.
|
||||||
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
|
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub enum GeometryBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A float area shape, for `shape-outside`.
|
/// A float area shape, for `shape-outside`.
|
||||||
pub type FloatAreaShape<BasicShape, Url> = ShapeSource<BasicShape, ShapeBox, Url>;
|
pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, Image>;
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||||
define_css_keyword_enum!(ShapeBox:
|
define_css_keyword_enum!(ShapeBox:
|
||||||
|
@ -41,9 +41,9 @@ add_impls_for_keyword_enum!(ShapeBox);
|
||||||
/// A shape source, for some reference box.
|
/// A shape source, for some reference box.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub enum ShapeSource<BasicShape, ReferenceBox, Url> {
|
pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
|
||||||
#[animation(error)]
|
#[animation(error)]
|
||||||
Url(Url),
|
ImageOrUrl(ImageOrUrl),
|
||||||
Shape(
|
Shape(
|
||||||
BasicShape,
|
BasicShape,
|
||||||
#[animation(constant)]
|
#[animation(constant)]
|
||||||
|
|
|
@ -22,6 +22,7 @@ use values::generics::basic_shape::{Polygon as GenericPolygon, ShapeRadius as Ge
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified::LengthOrPercentage;
|
use values::specified::LengthOrPercentage;
|
||||||
use values::specified::border::BorderRadius;
|
use values::specified::border::BorderRadius;
|
||||||
|
use values::specified::image::Image;
|
||||||
use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition};
|
use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition};
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ use values::specified::url::SpecifiedUrl;
|
||||||
pub type ClippingShape = GenericClippingShape<BasicShape, SpecifiedUrl>;
|
pub type ClippingShape = GenericClippingShape<BasicShape, SpecifiedUrl>;
|
||||||
|
|
||||||
/// A specified float area shape.
|
/// A specified float area shape.
|
||||||
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, SpecifiedUrl>;
|
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape, Image>;
|
||||||
|
|
||||||
/// A specified basic shape.
|
/// A specified basic shape.
|
||||||
pub type BasicShape = GenericBasicShape<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
|
pub type BasicShape = GenericBasicShape<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
|
||||||
|
@ -49,14 +50,18 @@ pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;
|
||||||
/// The specified value of `Polygon`
|
/// The specified value of `Polygon`
|
||||||
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
||||||
|
|
||||||
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox, SpecifiedUrl> {
|
impl<ReferenceBox, ImageOrUrl> Parse for ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>
|
||||||
|
where
|
||||||
|
ReferenceBox: Parse,
|
||||||
|
ImageOrUrl: Parse,
|
||||||
|
{
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(ShapeSource::None)
|
return Ok(ShapeSource::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
|
if let Ok(image_or_url) = input.try(|i| ImageOrUrl::parse(context, i)) {
|
||||||
return Ok(ShapeSource::Url(url))
|
return Ok(ShapeSource::ImageOrUrl(image_or_url))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_component<U: Parse>(context: &ParserContext, input: &mut Parser,
|
fn parse_component<U: Parse>(context: &ParserContext, input: &mut Parser,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue