style: Split clip-path and shape-outside values.

We don't actually share _that_ much code across them. This makes callers clearer
and code less confusing, IMHO.

This also has the benefit of not autocompleting path from devtools for
shape-outside.

Differential Revision: https://phabricator.services.mozilla.com/D62373
This commit is contained in:
Emilio Cobos Álvarez 2020-02-11 23:34:53 +00:00
parent ab03688994
commit 239302b1ed
6 changed files with 135 additions and 109 deletions

View file

@ -9,7 +9,7 @@
use crate::parser::{Parse, ParserContext};
use crate::values::generics::basic_shape as generic;
use crate::values::generics::basic_shape::{Path, PolygonCoord, ShapeSource};
use crate::values::generics::basic_shape::{Path, PolygonCoord};
use crate::values::generics::rect::Rect;
use crate::values::specified::border::BorderRadius;
use crate::values::specified::image::Image;
@ -24,11 +24,11 @@ use style_traits::{ParseError, StyleParseErrorKind};
/// A specified alias for FillRule.
pub use crate::values::generics::basic_shape::FillRule;
/// A specified clipping shape.
pub type ClippingShape = generic::GenericClippingShape<BasicShape, SpecifiedUrl>;
/// A specified `clip-path` value.
pub type ClipPath = generic::GenericClipPath<BasicShape, SpecifiedUrl>;
/// A specified float area shape.
pub type FloatAreaShape = generic::GenericFloatAreaShape<BasicShape, Image>;
/// A specified `shape-outside` value.
pub type ShapeOutside = generic::GenericShapeOutside<BasicShape, Image>;
/// A specified basic shape.
pub type BasicShape = generic::GenericBasicShape<
@ -64,31 +64,78 @@ fn is_clip_path_path_enabled(_: &ParserContext) -> bool {
false
}
impl Parse for ClippingShape {
/// A helper for both clip-path and shape-outside parsing of shapes.
fn parse_shape_or_box<'i, 't, R, ReferenceBox>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
to_shape: impl FnOnce(Box<BasicShape>, ReferenceBox) -> R,
to_reference_box: impl FnOnce(ReferenceBox) -> R,
) -> Result<R, ParseError<'i>>
where
ReferenceBox: Default + Parse,
{
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(to_shape(Box::new(shp), ref_box.unwrap_or_default()));
}
match ref_box {
Some(r) => Ok(to_reference_box(r)),
None => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
}
}
impl Parse for ClipPath {
#[inline]
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() {
return Ok(ShapeSource::None);
return Ok(ClipPath::None);
}
if is_clip_path_path_enabled(context) {
if let Ok(p) = input.try(|i| Path::parse(context, i)) {
return Ok(ShapeSource::Path(p));
return Ok(ClipPath::Path(p));
}
}
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
return Ok(ShapeSource::ImageOrUrl(url));
return Ok(ClipPath::Url(url));
}
Self::parse_common(context, input)
parse_shape_or_box(
context,
input,
ClipPath::Shape,
ClipPath::Box,
)
}
}
impl Parse for FloatAreaShape {
impl Parse for ShapeOutside {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
@ -97,56 +144,20 @@ impl Parse for FloatAreaShape {
// Need to parse this here so that `Image::parse_with_cors_anonymous`
// doesn't parse it.
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(ShapeSource::None);
return Ok(ShapeOutside::None);
}
if let Ok(image) = input.try(|i| Image::parse_with_cors_anonymous(context, i)) {
debug_assert_ne!(image, Image::None);
return Ok(ShapeSource::ImageOrUrl(image));
return Ok(ShapeOutside::Image(image));
}
Self::parse_common(context, input)
}
}
impl<ReferenceBox, ImageOrUrl> ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>
where
ReferenceBox: Parse + Default + PartialEq,
{
/// The internal parser for ShapeSource.
fn parse_common<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
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(Box::new(shp), ref_box.unwrap_or_default()));
}
ref_box
.map(ShapeSource::Box)
.ok_or(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
parse_shape_or_box(
context,
input,
ShapeOutside::Shape,
ShapeOutside::Box,
)
}
}