mirror of
https://github.com/servo/servo.git
synced 2025-06-06 00:25:37 +00:00
Add ShapeSource to basic-shape values
This commit is contained in:
parent
fc7053e030
commit
254900bd1a
3 changed files with 219 additions and 3 deletions
|
@ -81,3 +81,11 @@ impl<'a> ParserContext<'a> {
|
|||
pub fn log_css_error(input: &mut Parser, position: SourcePosition, message: &str, parsercontext: &ParserContext) {
|
||||
parsercontext.error_reporter.report_error(input, position, message);
|
||||
}
|
||||
|
||||
// XXXManishearth Replace all specified value parse impls with impls of this
|
||||
// trait. This will make it easy to write more generic values in the future.
|
||||
// There may need to be two traits -- one for parsing with context, and one
|
||||
// for parsing without
|
||||
pub trait Parse {
|
||||
fn parse(input: &mut Parser) -> Result<Self, ()> where Self: Sized;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,46 @@
|
|||
use cssparser::ToCss;
|
||||
use properties::shorthands::serialize_four_sides;
|
||||
use std::fmt;
|
||||
use url::Url;
|
||||
use values::computed::position::Position;
|
||||
use values::computed::{BorderRadiusSize, LengthOrPercentage};
|
||||
use values::computed::UrlExtraData;
|
||||
|
||||
pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum ShapeSource<T> {
|
||||
Url(Url, UrlExtraData),
|
||||
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 {
|
||||
use values::LocalToCss;
|
||||
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"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use values::specified::basic_shape::FillRule;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
|
|
@ -8,12 +8,110 @@
|
|||
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
|
||||
|
||||
use cssparser::{Parser, ToCss};
|
||||
use parser::{ParserContext, Parse};
|
||||
use properties::shorthands::{parse_four_sides, serialize_four_sides};
|
||||
use std::fmt;
|
||||
use url::Url;
|
||||
use values::computed::basic_shape as computed_basic_shape;
|
||||
use values::computed::{Context, ToComputedValue, ComputedValueAsSpecified};
|
||||
use values::specified::position::Position;
|
||||
use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage};
|
||||
use values::specified::UrlExtraData;
|
||||
|
||||
/// A shape source, for some reference box
|
||||
///
|
||||
/// clip-path uses ShapeSource<GeometryBox>,
|
||||
/// shape-outside uses ShapeSource<ShapeBox>
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum ShapeSource<T> {
|
||||
Url(Url, UrlExtraData),
|
||||
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 {
|
||||
use values::LocalToCss;
|
||||
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<T: Parse + PartialEq + Copy> ShapeSource<T> {
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
|
||||
Ok(ShapeSource::None)
|
||||
} else if let Ok(url) = input.try(|input| input.expect_url()) {
|
||||
match UrlExtraData::make_from(context) {
|
||||
Some(extra_data) => {
|
||||
Ok(ShapeSource::Url(context.parse_url(&url), extra_data))
|
||||
},
|
||||
None => Err(()),
|
||||
}
|
||||
} else {
|
||||
fn parse_component<U: Parse>(input: &mut Parser, component: &mut Option<U>) -> bool {
|
||||
if component.is_some() {
|
||||
return false; // already parsed this component
|
||||
}
|
||||
*component = input.try(U::parse).ok();
|
||||
component.is_some()
|
||||
}
|
||||
|
||||
let mut shape = None;
|
||||
let mut reference = None;
|
||||
loop {
|
||||
if !parse_component(input, &mut shape) &&
|
||||
!parse_component(input, &mut reference) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
match (shape, reference) {
|
||||
(Some(shape), _) => Ok(ShapeSource::Shape(shape, reference)),
|
||||
(None, Some(reference)) => Ok(ShapeSource::Box(reference)),
|
||||
(None, None) => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
|
||||
type ComputedValue = computed_basic_shape::ShapeSource<T::ComputedValue>;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
ShapeSource::Url(ref url, ref data) => {
|
||||
computed_basic_shape::ShapeSource::Url(url.clone(), data.clone())
|
||||
}
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -24,8 +122,8 @@ pub enum BasicShape {
|
|||
Polygon(Polygon),
|
||||
}
|
||||
|
||||
impl BasicShape {
|
||||
pub fn parse(input: &mut Parser) -> Result<BasicShape, ()> {
|
||||
impl Parse for BasicShape {
|
||||
fn parse(input: &mut Parser) -> Result<BasicShape, ()> {
|
||||
match_ignore_ascii_case! { try!(input.expect_function()),
|
||||
"inset" => {
|
||||
Ok(BasicShape::Inset(
|
||||
|
@ -528,3 +626,77 @@ impl ToCss for FillRule {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum GeometryBox {
|
||||
Fill,
|
||||
Stroke,
|
||||
View,
|
||||
ShapeBox(ShapeBox),
|
||||
}
|
||||
|
||||
impl Parse for GeometryBox {
|
||||
fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(shape_box) = input.try(ShapeBox::parse) {
|
||||
Ok(GeometryBox::ShapeBox(shape_box))
|
||||
} else {
|
||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||
"fill-box" => Ok(GeometryBox::Fill),
|
||||
"stroke-box" => Ok(GeometryBox::Stroke),
|
||||
"view-box" => Ok(GeometryBox::View),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for GeometryBox {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
GeometryBox::Fill => dest.write_str("fill-box"),
|
||||
GeometryBox::Stroke => dest.write_str("stroke-box"),
|
||||
GeometryBox::View => dest.write_str("view-box"),
|
||||
GeometryBox::ShapeBox(s) => s.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for GeometryBox {}
|
||||
|
||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum ShapeBox {
|
||||
Margin,
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#box
|
||||
Border,
|
||||
Padding,
|
||||
Content,
|
||||
}
|
||||
|
||||
impl Parse for ShapeBox {
|
||||
fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||
"margin-box" => Ok(ShapeBox::Margin),
|
||||
"border-box" => Ok(ShapeBox::Border),
|
||||
"padding-box" => Ok(ShapeBox::Padding),
|
||||
"content-box" => Ok(ShapeBox::Content),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for ShapeBox {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
ShapeBox::Margin => dest.write_str("margin-box"),
|
||||
ShapeBox::Border => dest.write_str("border-box"),
|
||||
ShapeBox::Padding => dest.write_str("padding-box"),
|
||||
ShapeBox::Content => dest.write_str("content-box"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for ShapeBox {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue