summaryrefslogtreecommitdiffstats
path: root/servo/components/style/values/specified
diff options
context:
space:
mode:
Diffstat (limited to 'servo/components/style/values/specified')
-rw-r--r--servo/components/style/values/specified/animation.rs40
-rw-r--r--servo/components/style/values/specified/basic_shape.rs206
-rw-r--r--servo/components/style/values/specified/box.rs50
-rw-r--r--servo/components/style/values/specified/color.rs159
-rw-r--r--servo/components/style/values/specified/counters.rs11
-rw-r--r--servo/components/style/values/specified/easing.rs11
-rw-r--r--servo/components/style/values/specified/effects.rs2
-rw-r--r--servo/components/style/values/specified/image.rs2
-rw-r--r--servo/components/style/values/specified/length.rs57
-rw-r--r--servo/components/style/values/specified/motion.rs23
-rw-r--r--servo/components/style/values/specified/svg_path.rs562
-rw-r--r--servo/components/style/values/specified/text.rs7
12 files changed, 472 insertions, 658 deletions
diff --git a/servo/components/style/values/specified/animation.rs b/servo/components/style/values/specified/animation.rs
index 5a1f5003f3..552521711c 100644
--- a/servo/components/style/values/specified/animation.rs
+++ b/servo/components/style/values/specified/animation.rs
@@ -165,6 +165,12 @@ impl AnimationIterationCount {
pub fn one() -> Self {
Self::Number(NonNegativeNumber::new(1.0))
}
+
+ /// Returns true if it's `1.0`.
+ #[inline]
+ pub fn is_one(&self) -> bool {
+ *self == Self::one()
+ }
}
/// A value for the `animation-name` property.
@@ -230,6 +236,17 @@ pub enum AnimationDirection {
AlternateReverse,
}
+impl AnimationDirection {
+ /// Returns true if the name matches any animation-direction keyword.
+ #[inline]
+ pub fn match_keywords(name: &AnimationName) -> bool {
+ if let Some(name) = name.as_atom() {
+ return name.with_str(|n| Self::from_ident(n).is_ok());
+ }
+ false
+ }
+}
+
/// https://drafts.csswg.org/css-animations/#animation-play-state
#[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
#[repr(u8)]
@@ -239,6 +256,17 @@ pub enum AnimationPlayState {
Paused,
}
+impl AnimationPlayState {
+ /// Returns true if the name matches any animation-play-state keyword.
+ #[inline]
+ pub fn match_keywords(name: &AnimationName) -> bool {
+ if let Some(name) = name.as_atom() {
+ return name.with_str(|n| Self::from_ident(n).is_ok());
+ }
+ false
+ }
+}
+
/// https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode
#[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
#[repr(u8)]
@@ -250,6 +278,18 @@ pub enum AnimationFillMode {
Both,
}
+impl AnimationFillMode {
+ /// Returns true if the name matches any animation-fill-mode keyword.
+ /// Note: animation-name:none is its initial value, so we don't have to match none here.
+ #[inline]
+ pub fn match_keywords(name: &AnimationName) -> bool {
+ if let Some(atom) = name.as_atom() {
+ return !name.is_none() && atom.with_str(|n| Self::from_ident(n).is_ok());
+ }
+ false
+ }
+}
+
/// https://drafts.csswg.org/css-animations-2/#animation-composition
#[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
#[repr(u8)]
diff --git a/servo/components/style/values/specified/basic_shape.rs b/servo/components/style/values/specified/basic_shape.rs
index 526296b735..8ed32c40c5 100644
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -14,6 +14,7 @@ use crate::values::generics::basic_shape as generic;
use crate::values::generics::basic_shape::{Path, PolygonCoord};
use crate::values::generics::position::{GenericPosition, GenericPositionOrAuto};
use crate::values::generics::rect::Rect;
+use crate::values::specified::angle::Angle;
use crate::values::specified::border::BorderRadius;
use crate::values::specified::image::Image;
use crate::values::specified::length::LengthPercentageOrAuto;
@@ -40,6 +41,7 @@ pub type ShapePosition = GenericPosition<LengthPercentage, LengthPercentage>;
/// A specified basic shape.
pub type BasicShape = generic::GenericBasicShape<
+ Angle,
ShapePosition,
LengthPercentage,
NonNegativeLengthPercentage,
@@ -61,6 +63,12 @@ pub type ShapeRadius = generic::ShapeRadius<NonNegativeLengthPercentage>;
/// The specified value of `Polygon`.
pub type Polygon = generic::GenericPolygon<LengthPercentage>;
+/// The specified value of `PathOrShapeFunction`.
+pub type PathOrShapeFunction = generic::GenericPathOrShapeFunction<Angle, LengthPercentage>;
+
+/// The specified value of `ShapeCommand`.
+pub type ShapeCommand = generic::GenericShapeCommand<Angle, LengthPercentage>;
+
/// The specified value of `xywh()`.
/// Defines a rectangle via offsets from the top and left edge of the reference box, and a
/// specified width and height.
@@ -168,8 +176,8 @@ bitflags! {
const POLYGON = 1 << 5;
/// path().
const PATH = 1 << 6;
- // TODO: Bug 1823463. Add shape().
- // const SHAPE = 1 << 7;
+ /// shape().
+ const SHAPE = 1 << 7;
/// All flags.
const ALL =
@@ -179,7 +187,8 @@ bitflags! {
Self::CIRCLE.bits() |
Self::ELLIPSE.bits() |
Self::POLYGON.bits() |
- Self::PATH.bits();
+ Self::PATH.bits() |
+ Self::SHAPE.bits();
/// For shape-outside.
const SHAPE_OUTSIDE =
@@ -329,7 +338,17 @@ impl BasicShape {
.map(BasicShape::Polygon)
},
"path" if flags.contains(AllowedBasicShapes::PATH) => {
- Path::parse_function_arguments(i, shape_type).map(BasicShape::Path)
+ Path::parse_function_arguments(i, shape_type)
+ .map(PathOrShapeFunction::Path)
+ .map(BasicShape::PathOrShape)
+ },
+ "shape"
+ if flags.contains(AllowedBasicShapes::SHAPE)
+ && static_prefs::pref!("layout.css.basic-shape-shape.enabled") =>
+ {
+ generic::Shape::parse_function_arguments(context, i, shape_type)
+ .map(PathOrShapeFunction::Shape)
+ .map(BasicShape::PathOrShape)
},
_ => Err(location
.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone()))),
@@ -490,7 +509,11 @@ impl Ellipse {
}
}
-fn parse_fill_rule<'i, 't>(input: &mut Parser<'i, 't>, shape_type: ShapeType) -> FillRule {
+fn parse_fill_rule<'i, 't>(
+ input: &mut Parser<'i, 't>,
+ shape_type: ShapeType,
+ expect_comma: bool,
+) -> FillRule {
match shape_type {
// Per [1] and [2], we ignore `<fill-rule>` for outline shapes, so always use a default
// value.
@@ -508,7 +531,9 @@ fn parse_fill_rule<'i, 't>(input: &mut Parser<'i, 't>, shape_type: ShapeType) ->
ShapeType::Filled => input
.try_parse(|i| -> Result<_, ParseError> {
let fill = FillRule::parse(i)?;
- i.expect_comma()?;
+ if expect_comma {
+ i.expect_comma()?;
+ }
Ok(fill)
})
.unwrap_or_default(),
@@ -532,7 +557,7 @@ impl Polygon {
input: &mut Parser<'i, 't>,
shape_type: ShapeType,
) -> Result<Self, ParseError<'i>> {
- let fill = parse_fill_rule(input, shape_type);
+ let fill = parse_fill_rule(input, shape_type, true /* has comma */);
let coordinates = input
.parse_comma_separated(|i| {
Ok(PolygonCoord(
@@ -554,7 +579,7 @@ impl Path {
) -> Result<Self, ParseError<'i>> {
use crate::values::specified::svg_path::AllowEmpty;
- let fill = parse_fill_rule(input, shape_type);
+ let fill = parse_fill_rule(input, shape_type, true /* has comma */);
let path = SVGPathData::parse(input, AllowEmpty::No)?;
Ok(Path { fill, path })
}
@@ -717,3 +742,168 @@ impl ToComputedValue for BasicShapeRect {
Self::Inset(ToComputedValue::from_computed_value(computed))
}
}
+
+impl generic::Shape<Angle, LengthPercentage> {
+ /// Parse the inner arguments of a `shape` function.
+ /// shape() = shape(<fill-rule>? from <coordinate-pair>, <shape-command>#)
+ fn parse_function_arguments<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ shape_type: ShapeType,
+ ) -> Result<Self, ParseError<'i>> {
+ let fill = parse_fill_rule(input, shape_type, false /* no following comma */);
+
+ let mut first = true;
+ let commands = input.parse_comma_separated(|i| {
+ if first {
+ first = false;
+
+ // The starting point for the first shape-command. It adds an initial absolute
+ // moveto to the list of path data commands, with the <coordinate-pair> measured
+ // from the top-left corner of the reference
+ i.expect_ident_matching("from")?;
+ Ok(ShapeCommand::Move {
+ by_to: generic::ByTo::To,
+ point: generic::CoordinatePair::parse(context, i)?,
+ })
+ } else {
+ // The further path data commands.
+ ShapeCommand::parse(context, i)
+ }
+ })?;
+
+ // We must have one starting point and at least one following <shape-command>.
+ if commands.len() < 2 {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
+
+ Ok(Self {
+ fill,
+ commands: commands.into(),
+ })
+ }
+}
+
+impl Parse for ShapeCommand {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ use crate::values::generics::basic_shape::{ArcSize, ArcSweep, ByTo, CoordinatePair};
+
+ // <shape-command> = <move-command> | <line-command> | <hv-line-command> |
+ // <curve-command> | <smooth-command> | <arc-command> | close
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "close" => Self::Close,
+ "move" => {
+ let by_to = ByTo::parse(input)?;
+ let point = CoordinatePair::parse(context, input)?;
+ Self::Move { by_to, point }
+ },
+ "line" => {
+ let by_to = ByTo::parse(input)?;
+ let point = CoordinatePair::parse(context, input)?;
+ Self::Line { by_to, point }
+ },
+ "hline" => {
+ let by_to = ByTo::parse(input)?;
+ let x = LengthPercentage::parse(context, input)?;
+ Self::HLine { by_to, x }
+ },
+ "vline" => {
+ let by_to = ByTo::parse(input)?;
+ let y = LengthPercentage::parse(context, input)?;
+ Self::VLine { by_to, y }
+ },
+ "curve" => {
+ let by_to = ByTo::parse(input)?;
+ let point = CoordinatePair::parse(context, input)?;
+ input.expect_ident_matching("via")?;
+ let control1 = CoordinatePair::parse(context, input)?;
+ match input.try_parse(|i| CoordinatePair::parse(context, i)) {
+ Ok(control2) => Self::CubicCurve {
+ by_to,
+ point,
+ control1,
+ control2,
+ },
+ Err(_) => Self::QuadCurve {
+ by_to,
+ point,
+ control1,
+ },
+ }
+ },
+ "smooth" => {
+ let by_to = ByTo::parse(input)?;
+ let point = CoordinatePair::parse(context, input)?;
+ if input.try_parse(|i| i.expect_ident_matching("via")).is_ok() {
+ let control2 = CoordinatePair::parse(context, input)?;
+ Self::SmoothCubic {
+ by_to,
+ point,
+ control2,
+ }
+ } else {
+ Self::SmoothQuad { by_to, point }
+ }
+ },
+ "arc" => {
+ let by_to = ByTo::parse(input)?;
+ let point = CoordinatePair::parse(context, input)?;
+ input.expect_ident_matching("of")?;
+ let rx = LengthPercentage::parse(context, input)?;
+ let ry = input
+ .try_parse(|i| LengthPercentage::parse(context, i))
+ .unwrap_or(rx.clone());
+ let radii = CoordinatePair::new(rx, ry);
+
+ // [<arc-sweep> || <arc-size> || rotate <angle>]?
+ let mut arc_sweep = None;
+ let mut arc_size = None;
+ let mut rotate = None;
+ loop {
+ if arc_sweep.is_none() {
+ arc_sweep = input.try_parse(ArcSweep::parse).ok();
+ }
+
+ if arc_size.is_none() {
+ arc_size = input.try_parse(ArcSize::parse).ok();
+ if arc_size.is_some() {
+ continue;
+ }
+ }
+
+ if rotate.is_none()
+ && input
+ .try_parse(|i| i.expect_ident_matching("rotate"))
+ .is_ok()
+ {
+ rotate = Some(Angle::parse(context, input)?);
+ continue;
+ }
+ break;
+ }
+ Self::Arc {
+ by_to,
+ point,
+ radii,
+ arc_sweep: arc_sweep.unwrap_or(ArcSweep::Ccw),
+ arc_size: arc_size.unwrap_or(ArcSize::Small),
+ rotate: rotate.unwrap_or(Angle::zero()),
+ }
+ },
+ })
+ }
+}
+
+impl Parse for generic::CoordinatePair<LengthPercentage> {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let x = LengthPercentage::parse(context, input)?;
+ let y = LengthPercentage::parse(context, input)?;
+ Ok(Self::new(x, y))
+ }
+}
diff --git a/servo/components/style/values/specified/box.rs b/servo/components/style/values/specified/box.rs
index 8414591c2b..ee50227504 100644
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -19,12 +19,12 @@ use std::fmt::{self, Write};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
-#[cfg(not(feature = "servo-layout-2020"))]
+#[cfg(not(feature = "servo"))]
fn flexbox_enabled() -> bool {
true
}
-#[cfg(feature = "servo-layout-2020")]
+#[cfg(feature = "servo")]
fn flexbox_enabled() -> bool {
servo_config::prefs::pref_map()
.get("layout.flexbox.enabled")
@@ -42,9 +42,7 @@ pub enum DisplayOutside {
None = 0,
Inline,
Block,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableCaption,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
InternalTable,
#[cfg(feature = "gecko")]
InternalRuby,
@@ -55,28 +53,19 @@ pub enum DisplayOutside {
#[repr(u8)]
pub enum DisplayInside {
None = 0,
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
Contents,
Flow,
FlowRoot,
Flex,
#[cfg(feature = "gecko")]
Grid,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
Table,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableRowGroup,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableColumn,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableColumnGroup,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableHeaderGroup,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableFooterGroup,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableRow,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
TableCell,
#[cfg(feature = "gecko")]
Ruby,
@@ -145,7 +134,6 @@ impl Display {
/// ::new() inlined so cbindgen can use it
pub const None: Self =
Self(((DisplayOutside::None as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::None as u16);
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
pub const Contents: Self = Self(
((DisplayOutside::None as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::Contents as u16,
);
@@ -170,14 +158,11 @@ impl Display {
#[cfg(feature = "gecko")]
pub const InlineGrid: Self =
Self(((DisplayOutside::Inline as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::Grid as u16);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const Table: Self =
Self(((DisplayOutside::Block as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::Table as u16);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const InlineTable: Self = Self(
((DisplayOutside::Inline as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::Table as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableCaption: Self = Self(
((DisplayOutside::TableCaption as u16) << Self::OUTSIDE_SHIFT) | DisplayInside::Flow as u16,
);
@@ -195,37 +180,30 @@ impl Display {
// Internal table boxes.
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableRowGroup: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableRowGroup as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableHeaderGroup: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableHeaderGroup as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableFooterGroup: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableFooterGroup as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableColumn: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableColumn as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableColumnGroup: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableColumnGroup as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableRow: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableRow as u16,
);
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
pub const TableCell: Self = Self(
((DisplayOutside::InternalTable as u16) << Self::OUTSIDE_SHIFT) |
DisplayInside::TableCell as u16,
@@ -336,7 +314,6 @@ impl Display {
pub fn is_atomic_inline_level(&self) -> bool {
match *self {
Display::InlineBlock | Display::InlineFlex => true,
- #[cfg(any(feature = "servo-layout-2013"))]
Display::InlineTable => true,
_ => false,
}
@@ -373,7 +350,6 @@ impl Display {
///
/// Also used for :root style adjustments.
pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self {
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
{
// Special handling for `contents` and `list-item`s on the root element.
if _is_root_element && (self.is_contents() || self.is_list_item()) {
@@ -392,7 +368,6 @@ impl Display {
Display::from3(DisplayOutside::Block, inside, self.is_list_item())
},
DisplayOutside::Block | DisplayOutside::None => *self,
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
_ => Display::Block,
}
}
@@ -419,7 +394,6 @@ impl Display {
#[inline]
pub fn is_contents(&self) -> bool {
match *self {
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
Display::Contents => true,
_ => false,
}
@@ -444,30 +418,20 @@ impl DisplayKeyword {
use self::DisplayKeyword::*;
Ok(try_match_ident_ignore_ascii_case! { input,
"none" => Full(Display::None),
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
"contents" => Full(Display::Contents),
"inline-block" => Full(Display::InlineBlock),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"inline-table" => Full(Display::InlineTable),
"-webkit-flex" if flexbox_enabled() => Full(Display::Flex),
"inline-flex" | "-webkit-inline-flex" if flexbox_enabled() => Full(Display::InlineFlex),
#[cfg(feature = "gecko")]
"inline-grid" => Full(Display::InlineGrid),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-caption" => Full(Display::TableCaption),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-row-group" => Full(Display::TableRowGroup),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-header-group" => Full(Display::TableHeaderGroup),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-footer-group" => Full(Display::TableFooterGroup),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-column" => Full(Display::TableColumn),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-column-group" => Full(Display::TableColumnGroup),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-row" => Full(Display::TableRow),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table-cell" => Full(Display::TableCell),
#[cfg(feature = "gecko")]
"ruby-base" => Full(Display::RubyBase),
@@ -493,9 +457,7 @@ impl DisplayKeyword {
/// https://drafts.csswg.org/css-display/#typedef-display-inside
"flow" => Inside(DisplayInside::Flow),
"flex" if flexbox_enabled() => Inside(DisplayInside::Flex),
- #[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
"flow-root" => Inside(DisplayInside::FlowRoot),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
"table" => Inside(DisplayInside::Table),
#[cfg(feature = "gecko")]
"grid" => Inside(DisplayInside::Grid),
@@ -517,13 +479,11 @@ impl ToCss for Display {
Display::InlineBlock => dest.write_str("inline-block"),
#[cfg(feature = "gecko")]
Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
Display::TableCaption => dest.write_str("table-caption"),
_ => match (outside, inside) {
#[cfg(feature = "gecko")]
(DisplayOutside::Inline, DisplayInside::Grid) => dest.write_str("inline-grid"),
(DisplayOutside::Inline, DisplayInside::Flex) => dest.write_str("inline-flex"),
- #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
(DisplayOutside::Inline, DisplayInside::Table) => dest.write_str("inline-table"),
#[cfg(feature = "gecko")]
(DisplayOutside::Block, DisplayInside::Ruby) => dest.write_str("block ruby"),
@@ -1607,18 +1567,12 @@ pub enum Appearance {
TabScrollArrowBack,
#[parse(condition = "ParserContext::chrome_rules_enabled")]
TabScrollArrowForward,
- /// A toolbar in an application window.
- #[parse(condition = "ParserContext::chrome_rules_enabled")]
- Toolbar,
/// A single toolbar button (with no associated dropdown).
#[parse(condition = "ParserContext::chrome_rules_enabled")]
Toolbarbutton,
/// The dropdown portion of a toolbar button
#[parse(condition = "ParserContext::chrome_rules_enabled")]
ToolbarbuttonDropdown,
- /// The toolbox that contains the toolbars.
- #[parse(condition = "ParserContext::chrome_rules_enabled")]
- Toolbox,
/// A tooltip.
#[parse(condition = "ParserContext::chrome_rules_enabled")]
Tooltip,
diff --git a/servo/components/style/values/specified/color.rs b/servo/components/style/values/specified/color.rs
index 3694b4e9bc..f823ba7d30 100644
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -7,21 +7,20 @@
use super::AllowQuirks;
use crate::color::component::ColorComponent;
use crate::color::convert::normalize_hue;
-use crate::color::parsing::{self, FromParsedColor, NumberOrAngle, NumberOrPercentage};
+use crate::color::parsing::{
+ self, ColorParser, FromParsedColor, NumberOrAngle, NumberOrPercentage,
+};
use crate::color::{mix::ColorInterpolationMethod, AbsoluteColor, ColorSpace};
use crate::media_queries::Device;
use crate::parser::{Parse, ParserContext};
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
-use crate::values::generics::calc::CalcUnits;
use crate::values::generics::color::{
ColorMixFlags, GenericCaretColor, GenericColorMix, GenericColorOrAuto,
};
-use crate::values::specified::calc::{CalcNode, Leaf};
use crate::values::specified::Percentage;
use crate::values::{normalize, CustomIdent};
use cssparser::color::OPAQUE;
use cssparser::{color::PredefinedColorSpace, BasicParseErrorKind, ParseErrorKind, Parser, Token};
-use itoa;
use std::fmt::{self, Write};
use std::io::Write as IoWrite;
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParseErrorKind};
@@ -623,156 +622,6 @@ impl FromParsedColor for Color {
}
}
-struct ColorParser<'a, 'b: 'a>(&'a ParserContext<'b>);
-
-impl<'a, 'b: 'a, 'i: 'a> parsing::ColorParser<'i> for ColorParser<'a, 'b> {
- type Output = Color;
-
- fn parse_number_or_angle<'t>(
- &self,
- input: &mut Parser<'i, 't>,
- allow_none: bool,
- ) -> Result<ColorComponent<NumberOrAngle>, ParseError<'i>> {
- use crate::values::specified::Angle;
-
- let location = input.current_source_location();
- let token = input.next()?.clone();
- Ok(match token {
- Token::Ident(ref value) if allow_none && value.eq_ignore_ascii_case("none") => {
- ColorComponent::None
- },
- Token::Dimension {
- value, ref unit, ..
- } => {
- let angle = Angle::parse_dimension(value, unit, /* from_calc = */ false);
-
- let degrees = match angle {
- Ok(angle) => angle.degrees(),
- Err(()) => return Err(location.new_unexpected_token_error(token.clone())),
- };
-
- ColorComponent::Value(NumberOrAngle::Angle { degrees })
- },
- Token::Number { value, .. } => ColorComponent::Value(NumberOrAngle::Number { value }),
- Token::Function(ref name) => {
- let function = CalcNode::math_function(self.0, name, location)?;
- let node = CalcNode::parse(self.0, input, function, CalcUnits::ANGLE)?;
-
- // If we can resolve the calc node, then use the value.
- match node.resolve() {
- Ok(Leaf::Number(value)) => {
- ColorComponent::Value(NumberOrAngle::Number { value })
- },
- Ok(Leaf::Angle(angle)) => ColorComponent::Value(NumberOrAngle::Angle {
- degrees: angle.degrees(),
- }),
- _ => {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
- },
- }
- },
- t => return Err(location.new_unexpected_token_error(t)),
- })
- }
-
- fn parse_percentage<'t>(
- &self,
- input: &mut Parser<'i, 't>,
- allow_none: bool,
- ) -> Result<ColorComponent<f32>, ParseError<'i>> {
- let location = input.current_source_location();
-
- Ok(match *input.next()? {
- Token::Ident(ref value) if allow_none && value.eq_ignore_ascii_case("none") => {
- ColorComponent::None
- },
- Token::Percentage { unit_value, .. } => ColorComponent::Value(unit_value),
- Token::Function(ref name) => {
- let function = CalcNode::math_function(self.0, name, location)?;
- let node = CalcNode::parse(self.0, input, function, CalcUnits::PERCENTAGE)?;
-
- // If we can resolve the calc node, then use the value.
- let Ok(resolved_leaf) = node.resolve() else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- };
- if let Leaf::Percentage(value) = resolved_leaf {
- ColorComponent::Value(value)
- } else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- }
- },
- ref t => return Err(location.new_unexpected_token_error(t.clone())),
- })
- }
-
- fn parse_number<'t>(
- &self,
- input: &mut Parser<'i, 't>,
- allow_none: bool,
- ) -> Result<ColorComponent<f32>, ParseError<'i>> {
- let location = input.current_source_location();
-
- Ok(match *input.next()? {
- Token::Ident(ref value) if allow_none && value.eq_ignore_ascii_case("none") => {
- ColorComponent::None
- },
- Token::Number { value, .. } => ColorComponent::Value(value),
- Token::Function(ref name) => {
- let function = CalcNode::math_function(self.0, name, location)?;
- let node = CalcNode::parse(self.0, input, function, CalcUnits::empty())?;
-
- // If we can resolve the calc node, then use the value.
- let Ok(resolved_leaf) = node.resolve() else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- };
- if let Leaf::Number(value) = resolved_leaf {
- ColorComponent::Value(value)
- } else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- }
- },
- ref t => return Err(location.new_unexpected_token_error(t.clone())),
- })
- }
-
- fn parse_number_or_percentage<'t>(
- &self,
- input: &mut Parser<'i, 't>,
- allow_none: bool,
- ) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
- let location = input.current_source_location();
-
- Ok(match *input.next()? {
- Token::Ident(ref value) if allow_none && value.eq_ignore_ascii_case("none") => {
- ColorComponent::None
- },
- Token::Number { value, .. } => {
- ColorComponent::Value(NumberOrPercentage::Number { value })
- },
- Token::Percentage { unit_value, .. } => {
- ColorComponent::Value(NumberOrPercentage::Percentage { unit_value })
- },
- Token::Function(ref name) => {
- let function = CalcNode::math_function(self.0, name, location)?;
- let node = CalcNode::parse(self.0, input, function, CalcUnits::PERCENTAGE)?;
-
- // If we can resolve the calc node, then use the value.
- let Ok(resolved_leaf) = node.resolve() else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- };
- if let Leaf::Percentage(unit_value) = resolved_leaf {
- ColorComponent::Value(NumberOrPercentage::Percentage { unit_value })
- } else if let Leaf::Number(value) = resolved_leaf {
- ColorComponent::Value(NumberOrPercentage::Number { value })
- } else {
- return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- }
- },
- ref t => return Err(location.new_unexpected_token_error(t.clone())),
- })
- }
-}
-
/// Whether to preserve authored colors during parsing. That's useful only if we
/// plan to serialize the color back.
#[derive(Copy, Clone)]
@@ -809,7 +658,7 @@ impl Color {
},
};
- let color_parser = ColorParser(&*context);
+ let color_parser = ColorParser { context: &context };
match input.try_parse(|i| parsing::parse_color_with(&color_parser, i)) {
Ok(mut color) => {
if let Color::Absolute(ref mut absolute) = color {
diff --git a/servo/components/style/values/specified/counters.rs b/servo/components/style/values/specified/counters.rs
index 9d8261ce6c..7760be91d7 100644
--- a/servo/components/style/values/specified/counters.rs
+++ b/servo/components/style/values/specified/counters.rs
@@ -4,7 +4,7 @@
//! Specified types for counter properties.
-#[cfg(feature = "servo-layout-2013")]
+#[cfg(feature = "servo")]
use crate::computed_values::list_style_type::T as ListStyleType;
use crate::parser::{Parse, ParserContext};
use crate::values::generics::counters as generics;
@@ -12,12 +12,10 @@ use crate::values::generics::counters::CounterPair;
#[cfg(feature = "gecko")]
use crate::values::generics::CounterStyle;
use crate::values::specified::image::Image;
-#[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
use crate::values::specified::Attr;
use crate::values::specified::Integer;
use crate::values::CustomIdent;
use cssparser::{Parser, Token};
-#[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
use selectors::parser::SelectorParseErrorKind;
use style_traits::{ParseError, StyleParseErrorKind};
@@ -151,7 +149,7 @@ pub type Content = generics::GenericContent<Image>;
pub type ContentItem = generics::GenericContentItem<Image>;
impl Content {
- #[cfg(feature = "servo-layout-2013")]
+ #[cfg(feature = "servo")]
fn parse_counter_style(_: &ParserContext, input: &mut Parser) -> ListStyleType {
input
.try_parse(|input| {
@@ -197,7 +195,6 @@ impl Parse for Content {
let mut content = vec![];
let mut has_alt_content = false;
loop {
- #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
{
if let Ok(image) = input.try_parse(|i| Image::parse_forbid_none(context, i)) {
content.push(generics::ContentItem::Image(image));
@@ -212,13 +209,11 @@ impl Parse for Content {
},
Ok(&Token::Function(ref name)) => {
let result = match_ignore_ascii_case! { &name,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
"counter" => input.parse_nested_block(|input| {
let name = CustomIdent::parse(input, &[])?;
let style = Content::parse_counter_style(context, input);
Ok(generics::ContentItem::Counter(name, style))
}),
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
"counters" => input.parse_nested_block(|input| {
let name = CustomIdent::parse(input, &[])?;
input.expect_comma()?;
@@ -226,7 +221,6 @@ impl Parse for Content {
let style = Content::parse_counter_style(context, input);
Ok(generics::ContentItem::Counters(name, separator, style))
}),
- #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
"attr" => input.parse_nested_block(|input| {
Ok(generics::ContentItem::Attr(Attr::parse_function(context, input)?))
}),
@@ -240,7 +234,6 @@ impl Parse for Content {
}?;
content.push(result);
},
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
Ok(&Token::Ident(ref ident)) => {
content.push(match_ignore_ascii_case! { &ident,
"open-quote" => generics::ContentItem::OpenQuote,
diff --git a/servo/components/style/values/specified/easing.rs b/servo/components/style/values/specified/easing.rs
index 5e4d8ae1ea..7697e6a5d7 100644
--- a/servo/components/style/values/specified/easing.rs
+++ b/servo/components/style/values/specified/easing.rs
@@ -9,7 +9,7 @@ use crate::values::computed::easing::TimingFunction as ComputedTimingFunction;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::generics::easing::TimingFunction as GenericTimingFunction;
use crate::values::generics::easing::{StepPosition, TimingKeyword};
-use crate::values::specified::{Integer, Number, Percentage};
+use crate::values::specified::{AnimationName, Integer, Number, Percentage};
use cssparser::{Delimiter, Parser, Token};
use selectors::parser::SelectorParseErrorKind;
use style_traits::{ParseError, StyleParseErrorKind};
@@ -140,6 +140,15 @@ impl TimingFunction {
Ok(GenericTimingFunction::LinearFunction(builder.build()))
}
+
+ /// Returns true if the name matches any keyword.
+ #[inline]
+ pub fn match_keywords(name: &AnimationName) -> bool {
+ if let Some(name) = name.as_atom() {
+ return name.with_str(|n| TimingKeyword::from_ident(n).is_ok());
+ }
+ false
+ }
}
// We need this for converting the specified TimingFunction into computed TimingFunction without
diff --git a/servo/components/style/values/specified/effects.rs b/servo/components/style/values/specified/effects.rs
index 0453582768..a32390e148 100644
--- a/servo/components/style/values/specified/effects.rs
+++ b/servo/components/style/values/specified/effects.rs
@@ -28,7 +28,7 @@ use crate::values::specified::{Angle, Number, NumberOrPercentage};
#[cfg(feature = "servo")]
use crate::values::Impossible;
use crate::Zero;
-use cssparser::{self, BasicParseErrorKind, Parser, Token};
+use cssparser::{BasicParseErrorKind, Parser, Token};
use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind};
/// A specified value for a single shadow of the `box-shadow` property.
diff --git a/servo/components/style/values/specified/image.rs b/servo/components/style/values/specified/image.rs
index 76bbbf85df..bedced1a27 100644
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -241,7 +241,7 @@ impl Image {
let function = input.expect_function()?.clone();
input.parse_nested_block(|input| {
Ok(match_ignore_ascii_case! { &function,
- #[cfg(feature = "servo-layout-2013")]
+ #[cfg(feature = "servo")]
"paint" => Self::PaintWorklet(PaintWorklet::parse_args(context, input)?),
"cross-fade" if cross_fade_enabled() => Self::CrossFade(Box::new(CrossFade::parse_args(context, input, cors_mode, flags)?)),
#[cfg(feature = "gecko")]
diff --git a/servo/components/style/values/specified/length.rs b/servo/components/style/values/specified/length.rs
index d2e1d7d346..17ff43cd6f 100644
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -97,9 +97,15 @@ pub enum LineHeightBase {
impl FontBaseSize {
/// Calculate the actual size for a given context
pub fn resolve(&self, context: &Context) -> computed::FontSize {
+ let style = context.style();
match *self {
- Self::CurrentStyle => context.style().get_font().clone_font_size(),
- Self::InheritedStyle => context.style().get_parent_font().clone_font_size(),
+ Self::CurrentStyle => style.get_font().clone_font_size(),
+ Self::InheritedStyle => {
+ // If we're using the size from our inherited style, we still need to apply our
+ // own zoom.
+ let zoom = style.get_box().clone_zoom();
+ style.get_parent_font().clone_font_size().zoom(zoom)
+ },
}
}
}
@@ -351,7 +357,7 @@ impl FontRelativeLength {
let reference_size = if context.builder.is_root_element || context.in_media_query {
reference_font_size.computed_size()
} else {
- context.device().root_font_size()
+ context.device().root_font_size().zoom(context.builder.effective_zoom)
};
(reference_size, length)
},
@@ -394,19 +400,19 @@ impl FontRelativeLength {
// When specified on the root element, the rlh units refer
// to the initial values of font and line-height properties.
//
- let reference_size: CSSPixelLength =
- if context.builder.is_root_element || context.in_media_query {
- context
- .device()
- .calc_line_height(
- &context.default_style().get_font(),
- context.style().writing_mode,
- None,
- )
- .0
- } else {
- context.device().root_line_height()
- };
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
+ context
+ .device()
+ .calc_line_height(
+ &context.default_style().get_font(),
+ context.style().writing_mode,
+ None,
+ )
+ .0
+ } else {
+ context.device().root_line_height()
+ };
+ let reference_size = reference_size.zoom(context.builder.effective_zoom);
(reference_size, length)
},
}
@@ -668,7 +674,7 @@ impl ViewportPercentageLength {
pub fn to_computed_value(&self, context: &Context) -> CSSPixelLength {
let (variant, unit, factor) = self.unpack();
let size = context.viewport_size_for_viewport_unit_resolution(variant);
- let length = match unit {
+ let length: app_units::Au = match unit {
ViewportUnit::Vw => size.width,
ViewportUnit::Vh => size.height,
ViewportUnit::Vmin => cmp::min(size.width, size.height),
@@ -686,13 +692,15 @@ impl ViewportPercentageLength {
},
};
+ // NOTE: This is in app units!
+ let length = context.builder.effective_zoom.zoom(length.0 as f32);
+
// FIXME: Bug 1396535, we need to fix the extremely small viewport length for transform.
- // See bug 989802. We truncate so that adding multiple viewport units
- // that add up to 100 does not overflow due to rounding differences.
- // We convert appUnits to CSS px manually here to avoid premature clamping by
- // going through the Au type.
+ // See bug 989802. We truncate so that adding multiple viewport units that add up to 100
+ // does not overflow due to rounding differences. We convert appUnits to CSS px manually
+ // here to avoid premature clamping by going through the Au type.
let trunc_scaled =
- ((length.0 as f64 * factor as f64 / 100.).trunc() / AU_PER_PX as f64) as f32;
+ ((length as f64 * factor as f64 / 100.).trunc() / AU_PER_PX as f64) as f32;
CSSPixelLength::new(crate::values::normalize(trunc_scaled))
}
}
@@ -797,7 +805,7 @@ impl ToComputedValue for AbsoluteLength {
type ComputedValue = CSSPixelLength;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- CSSPixelLength::new(context.builder.effective_zoom().zoom(self.to_px())).finite()
+ CSSPixelLength::new(self.to_px()).zoom(context.builder.effective_zoom).finite()
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
@@ -910,6 +918,9 @@ impl ContainerRelativeLength {
.builder
.add_flags(ComputedValueFlags::USES_CONTAINER_UNITS);
+ // TODO(emilio, bug 1894104): Need to handle zoom here, probably something like
+ // container_zoom - effective_zoom or so. See
+ // https://github.com/w3c/csswg-drafts/issues/10268
let size = context.get_container_size_query();
let (factor, container_length) = match *self {
Self::Cqw(v) => (v, size.get_container_width(context)),
diff --git a/servo/components/style/values/specified/motion.rs b/servo/components/style/values/specified/motion.rs
index 98858c712c..15c76bc640 100644
--- a/servo/components/style/values/specified/motion.rs
+++ b/servo/components/style/values/specified/motion.rs
@@ -76,10 +76,6 @@ impl Parse for RayFunction {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- if !static_prefs::pref!("layout.css.motion-path-ray.enabled") {
- return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- }
-
input.expect_function_matching("ray")?;
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
}
@@ -154,11 +150,8 @@ impl Parse for OffsetPathFunction {
// <offset-path> = <ray()> | <url> | <basic-shape>
// https://drafts.fxtf.org/motion-1/#typedef-offset-path
-
- if static_prefs::pref!("layout.css.motion-path-ray.enabled") {
- if let Ok(ray) = input.try_parse(|i| RayFunction::parse(context, i)) {
- return Ok(OffsetPathFunction::Ray(ray));
- }
+ if let Ok(ray) = input.try_parse(|i| RayFunction::parse(context, i)) {
+ return Ok(OffsetPathFunction::Ray(ray));
}
if static_prefs::pref!("layout.css.motion-path-url.enabled") {
@@ -167,13 +160,7 @@ impl Parse for OffsetPathFunction {
}
}
- let allowed_shapes = if static_prefs::pref!("layout.css.motion-path-basic-shapes.enabled") {
- AllowedBasicShapes::ALL
- } else {
- AllowedBasicShapes::PATH
- };
-
- BasicShape::parse(context, input, allowed_shapes, ShapeType::Outline)
+ BasicShape::parse(context, input, AllowedBasicShapes::ALL, ShapeType::Outline)
.map(OffsetPathFunction::Shape)
}
}
@@ -197,9 +184,7 @@ impl Parse for OffsetPath {
.ok();
}
- if static_prefs::pref!("layout.css.motion-path-coord-box.enabled") &&
- coord_box.is_none()
- {
+ if coord_box.is_none() {
coord_box = input.try_parse(CoordBox::parse).ok();
if coord_box.is_some() {
continue;
diff --git a/servo/components/style/values/specified/svg_path.rs b/servo/components/style/values/specified/svg_path.rs
index 1eb9866dd1..56342b48bb 100644
--- a/servo/components/style/values/specified/svg_path.rs
+++ b/servo/components/style/values/specified/svg_path.rs
@@ -5,10 +5,13 @@
//! Specified types for SVG Path.
use crate::parser::{Parse, ParserContext};
-use crate::values::animated::{lists, Animate, Procedure, ToAnimatedZero};
+use crate::values::animated::{lists, Animate, Procedure};
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
+use crate::values::generics::basic_shape::GenericShapeCommand;
+use crate::values::generics::basic_shape::{ArcSize, ArcSweep, ByTo, CoordinatePair};
use crate::values::CSSFloat;
use cssparser::Parser;
+use num_traits::FromPrimitive;
use std::fmt::{self, Write};
use std::iter::{Cloned, Peekable};
use std::slice;
@@ -70,6 +73,7 @@ impl SVGPathData {
#[cfg(feature = "gecko")]
pub fn decode_from_f32_array(path: &[f32]) -> Result<Self, ()> {
use crate::gecko_bindings::structs::dom::SVGPathSeg_Binding::*;
+ use crate::values::generics::basic_shape::GenericShapeCommand::*;
let mut result: Vec<PathCommand> = Vec::new();
let mut i: usize = 0;
@@ -80,85 +84,84 @@ impl SVGPathData {
let seg_type = path[i].to_bits() as u16;
i = i + 1;
match seg_type {
- PATHSEG_CLOSEPATH => result.push(PathCommand::ClosePath),
+ PATHSEG_CLOSEPATH => result.push(Close),
PATHSEG_MOVETO_ABS | PATHSEG_MOVETO_REL => {
debug_assert!(i + 1 < path.len());
- result.push(PathCommand::MoveTo {
+ result.push(Move {
point: CoordPair::new(path[i], path[i + 1]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_MOVETO_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_MOVETO_ABS),
});
i = i + 2;
},
PATHSEG_LINETO_ABS | PATHSEG_LINETO_REL => {
debug_assert!(i + 1 < path.len());
- result.push(PathCommand::LineTo {
+ result.push(Line {
point: CoordPair::new(path[i], path[i + 1]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_LINETO_ABS),
});
i = i + 2;
},
PATHSEG_CURVETO_CUBIC_ABS | PATHSEG_CURVETO_CUBIC_REL => {
debug_assert!(i + 5 < path.len());
- result.push(PathCommand::CurveTo {
+ result.push(CubicCurve {
control1: CoordPair::new(path[i], path[i + 1]),
control2: CoordPair::new(path[i + 2], path[i + 3]),
point: CoordPair::new(path[i + 4], path[i + 5]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_CUBIC_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_CURVETO_CUBIC_ABS),
});
i = i + 6;
},
PATHSEG_CURVETO_QUADRATIC_ABS | PATHSEG_CURVETO_QUADRATIC_REL => {
debug_assert!(i + 3 < path.len());
- result.push(PathCommand::QuadBezierCurveTo {
+ result.push(QuadCurve {
control1: CoordPair::new(path[i], path[i + 1]),
point: CoordPair::new(path[i + 2], path[i + 3]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_QUADRATIC_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_CURVETO_QUADRATIC_ABS),
});
i = i + 4;
},
PATHSEG_ARC_ABS | PATHSEG_ARC_REL => {
debug_assert!(i + 6 < path.len());
- result.push(PathCommand::EllipticalArc {
- rx: path[i],
- ry: path[i + 1],
- angle: path[i + 2],
- large_arc_flag: ArcFlag(path[i + 3] != 0.0f32),
- sweep_flag: ArcFlag(path[i + 4] != 0.0f32),
+ result.push(Arc {
+ radii: CoordPair::new(path[i], path[i + 1]),
+ rotate: path[i + 2],
+ arc_size: ArcSize::from_u8((path[i + 3] != 0.0f32) as u8).unwrap(),
+ arc_sweep: ArcSweep::from_u8((path[i + 4] != 0.0f32) as u8).unwrap(),
point: CoordPair::new(path[i + 5], path[i + 6]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_ARC_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_ARC_ABS),
});
i = i + 7;
},
PATHSEG_LINETO_HORIZONTAL_ABS | PATHSEG_LINETO_HORIZONTAL_REL => {
debug_assert!(i < path.len());
- result.push(PathCommand::HorizontalLineTo {
+ result.push(HLine {
x: path[i],
- absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_HORIZONTAL_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_LINETO_HORIZONTAL_ABS),
});
i = i + 1;
},
PATHSEG_LINETO_VERTICAL_ABS | PATHSEG_LINETO_VERTICAL_REL => {
debug_assert!(i < path.len());
- result.push(PathCommand::VerticalLineTo {
+ result.push(VLine {
y: path[i],
- absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_VERTICAL_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_LINETO_VERTICAL_ABS),
});
i = i + 1;
},
PATHSEG_CURVETO_CUBIC_SMOOTH_ABS | PATHSEG_CURVETO_CUBIC_SMOOTH_REL => {
debug_assert!(i + 3 < path.len());
- result.push(PathCommand::SmoothCurveTo {
+ result.push(SmoothCubic {
control2: CoordPair::new(path[i], path[i + 1]),
point: CoordPair::new(path[i + 2], path[i + 3]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS),
});
i = i + 4;
},
PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS | PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL => {
debug_assert!(i + 1 < path.len());
- result.push(PathCommand::SmoothQuadBezierCurveTo {
+ result.push(SmoothQuad {
point: CoordPair::new(path[i], path[i + 1]),
- absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS),
+ by_to: ByTo::new(seg_type == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS),
});
i = i + 2;
},
@@ -215,7 +218,7 @@ impl ToCss for SVGPathData {
{
let mut writer = SequenceWriter::new(dest, " ");
for command in self.commands() {
- writer.item(command)?;
+ writer.write_item(|inner| command.to_css_for_svg(inner))?;
}
}
dest.write_char('"')
@@ -268,79 +271,7 @@ impl ComputeSquaredDistance for SVGPathData {
/// points of the Bézier curve in the spec.
///
/// https://www.w3.org/TR/SVG11/paths.html#PathData
-#[derive(
- Animate,
- Clone,
- ComputeSquaredDistance,
- Copy,
- Debug,
- Deserialize,
- MallocSizeOf,
- PartialEq,
- Serialize,
- SpecifiedValueInfo,
- ToAnimatedZero,
- ToComputedValue,
- ToResolvedValue,
- ToShmem,
-)]
-#[allow(missing_docs)]
-#[repr(C, u8)]
-pub enum PathCommand {
- /// The unknown type.
- /// https://www.w3.org/TR/SVG/paths.html#__svg__SVGPathSeg__PATHSEG_UNKNOWN
- Unknown,
- /// The "moveto" command.
- MoveTo {
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The "lineto" command.
- LineTo {
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The horizontal "lineto" command.
- HorizontalLineTo { x: CSSFloat, absolute: IsAbsolute },
- /// The vertical "lineto" command.
- VerticalLineTo { y: CSSFloat, absolute: IsAbsolute },
- /// The cubic Bézier curve command.
- CurveTo {
- control1: CoordPair,
- control2: CoordPair,
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The smooth curve command.
- SmoothCurveTo {
- control2: CoordPair,
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The quadratic Bézier curve command.
- QuadBezierCurveTo {
- control1: CoordPair,
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The smooth quadratic Bézier curve command.
- SmoothQuadBezierCurveTo {
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The elliptical arc curve command.
- EllipticalArc {
- rx: CSSFloat,
- ry: CSSFloat,
- angle: CSSFloat,
- large_arc_flag: ArcFlag,
- sweep_flag: ArcFlag,
- point: CoordPair,
- absolute: IsAbsolute,
- },
- /// The "closepath" command.
- ClosePath,
-}
+pub type PathCommand = GenericShapeCommand<CSSFloat, CSSFloat>;
/// For internal SVGPath normalization.
#[allow(missing_docs)]
@@ -355,177 +286,157 @@ impl PathCommand {
///
/// See discussion: https://github.com/w3c/svgwg/issues/321
fn normalize(&self, state: &mut PathTraversalState) -> Self {
- use self::PathCommand::*;
+ use crate::values::generics::basic_shape::GenericShapeCommand::*;
match *self {
- Unknown => Unknown,
- ClosePath => {
+ Close => {
state.pos = state.subpath_start;
- ClosePath
+ Close
},
- MoveTo {
- mut point,
- absolute,
- } => {
- if !absolute.is_yes() {
+ Move { by_to, mut point } => {
+ if !by_to.is_abs() {
point += state.pos;
}
state.pos = point;
state.subpath_start = point;
- MoveTo {
+ Move {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
}
},
- LineTo {
- mut point,
- absolute,
- } => {
- if !absolute.is_yes() {
+ Line { by_to, mut point } => {
+ if !by_to.is_abs() {
point += state.pos;
}
state.pos = point;
- LineTo {
+ Line {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
}
},
- HorizontalLineTo { mut x, absolute } => {
- if !absolute.is_yes() {
+ HLine { by_to, mut x } => {
+ if !by_to.is_abs() {
x += state.pos.x;
}
state.pos.x = x;
- HorizontalLineTo {
- x,
- absolute: IsAbsolute::Yes,
- }
+ HLine { by_to: ByTo::To, x }
},
- VerticalLineTo { mut y, absolute } => {
- if !absolute.is_yes() {
+ VLine { by_to, mut y } => {
+ if !by_to.is_abs() {
y += state.pos.y;
}
state.pos.y = y;
- VerticalLineTo {
- y,
- absolute: IsAbsolute::Yes,
- }
+ VLine { by_to: ByTo::To, y }
},
- CurveTo {
+ CubicCurve {
+ by_to,
+ mut point,
mut control1,
mut control2,
- mut point,
- absolute,
} => {
- if !absolute.is_yes() {
+ if !by_to.is_abs() {
+ point += state.pos;
control1 += state.pos;
control2 += state.pos;
- point += state.pos;
}
state.pos = point;
- CurveTo {
+ CubicCurve {
+ by_to: ByTo::To,
+ point,
control1,
control2,
- point,
- absolute: IsAbsolute::Yes,
}
},
- SmoothCurveTo {
- mut control2,
+ QuadCurve {
+ by_to,
mut point,
- absolute,
+ mut control1,
} => {
- if !absolute.is_yes() {
- control2 += state.pos;
+ if !by_to.is_abs() {
point += state.pos;
+ control1 += state.pos;
}
state.pos = point;
- SmoothCurveTo {
- control2,
+ QuadCurve {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
+ control1,
}
},
- QuadBezierCurveTo {
- mut control1,
+ SmoothCubic {
+ by_to,
mut point,
- absolute,
+ mut control2,
} => {
- if !absolute.is_yes() {
- control1 += state.pos;
+ if !by_to.is_abs() {
point += state.pos;
+ control2 += state.pos;
}
state.pos = point;
- QuadBezierCurveTo {
- control1,
+ SmoothCubic {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
+ control2,
}
},
- SmoothQuadBezierCurveTo {
- mut point,
- absolute,
- } => {
- if !absolute.is_yes() {
+ SmoothQuad { by_to, mut point } => {
+ if !by_to.is_abs() {
point += state.pos;
}
state.pos = point;
- SmoothQuadBezierCurveTo {
+ SmoothQuad {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
}
},
- EllipticalArc {
- rx,
- ry,
- angle,
- large_arc_flag,
- sweep_flag,
+ Arc {
+ by_to,
mut point,
- absolute,
+ radii,
+ arc_sweep,
+ arc_size,
+ rotate,
} => {
- if !absolute.is_yes() {
+ if !by_to.is_abs() {
point += state.pos;
}
state.pos = point;
- EllipticalArc {
- rx,
- ry,
- angle,
- large_arc_flag,
- sweep_flag,
+ Arc {
+ by_to: ByTo::To,
point,
- absolute: IsAbsolute::Yes,
+ radii,
+ arc_sweep,
+ arc_size,
+ rotate,
}
},
}
}
-}
-impl ToCss for PathCommand {
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ /// The serialization of the svg path.
+ fn to_css_for_svg<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
- use self::PathCommand::*;
+ use crate::values::generics::basic_shape::GenericShapeCommand::*;
match *self {
- Unknown => dest.write_char('X'),
- ClosePath => dest.write_char('Z'),
- MoveTo { point, absolute } => {
- dest.write_char(if absolute.is_yes() { 'M' } else { 'm' })?;
+ Close => dest.write_char('Z'),
+ Move { by_to, point } => {
+ dest.write_char(if by_to.is_abs() { 'M' } else { 'm' })?;
dest.write_char(' ')?;
point.to_css(dest)
},
- LineTo { point, absolute } => {
- dest.write_char(if absolute.is_yes() { 'L' } else { 'l' })?;
+ Line { by_to, point } => {
+ dest.write_char(if by_to.is_abs() { 'L' } else { 'l' })?;
dest.write_char(' ')?;
point.to_css(dest)
},
- CurveTo {
+ CubicCurve {
+ by_to,
+ point,
control1,
control2,
- point,
- absolute,
} => {
- dest.write_char(if absolute.is_yes() { 'C' } else { 'c' })?;
+ dest.write_char(if by_to.is_abs() { 'C' } else { 'c' })?;
dest.write_char(' ')?;
control1.to_css(dest)?;
dest.write_char(' ')?;
@@ -533,63 +444,60 @@ impl ToCss for PathCommand {
dest.write_char(' ')?;
point.to_css(dest)
},
- QuadBezierCurveTo {
- control1,
+ QuadCurve {
+ by_to,
point,
- absolute,
+ control1,
} => {
- dest.write_char(if absolute.is_yes() { 'Q' } else { 'q' })?;
+ dest.write_char(if by_to.is_abs() { 'Q' } else { 'q' })?;
dest.write_char(' ')?;
control1.to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
- EllipticalArc {
- rx,
- ry,
- angle,
- large_arc_flag,
- sweep_flag,
+ Arc {
+ by_to,
point,
- absolute,
+ radii,
+ arc_sweep,
+ arc_size,
+ rotate,
} => {
- dest.write_char(if absolute.is_yes() { 'A' } else { 'a' })?;
- dest.write_char(' ')?;
- rx.to_css(dest)?;
+ dest.write_char(if by_to.is_abs() { 'A' } else { 'a' })?;
dest.write_char(' ')?;
- ry.to_css(dest)?;
+ radii.to_css(dest)?;
dest.write_char(' ')?;
- angle.to_css(dest)?;
+ rotate.to_css(dest)?;
dest.write_char(' ')?;
- large_arc_flag.to_css(dest)?;
+ (arc_size as i32).to_css(dest)?;
dest.write_char(' ')?;
- sweep_flag.to_css(dest)?;
+ (arc_sweep as i32).to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
- HorizontalLineTo { x, absolute } => {
- dest.write_char(if absolute.is_yes() { 'H' } else { 'h' })?;
+ HLine { by_to, x } => {
+ dest.write_char(if by_to.is_abs() { 'H' } else { 'h' })?;
dest.write_char(' ')?;
x.to_css(dest)
},
- VerticalLineTo { y, absolute } => {
- dest.write_char(if absolute.is_yes() { 'V' } else { 'v' })?;
+ VLine { by_to, y } => {
+ dest.write_char(if by_to.is_abs() { 'V' } else { 'v' })?;
dest.write_char(' ')?;
y.to_css(dest)
},
- SmoothCurveTo {
- control2,
+ SmoothCubic {
+ by_to,
point,
- absolute,
+ control2,
} => {
- dest.write_char(if absolute.is_yes() { 'S' } else { 's' })?;
+ dest.write_char(if by_to.is_abs() { 'S' } else { 's' })?;
dest.write_char(' ')?;
control2.to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
- SmoothQuadBezierCurveTo { point, absolute } => {
- dest.write_char(if absolute.is_yes() { 'T' } else { 't' })?;
+ SmoothQuad { by_to, point } => {
+ dest.write_char(if by_to.is_abs() { 'T' } else { 't' })?;
dest.write_char(' ')?;
point.to_css(dest)
},
@@ -597,135 +505,8 @@ impl ToCss for PathCommand {
}
}
-/// The path command absolute type.
-#[allow(missing_docs)]
-#[derive(
- Animate,
- Clone,
- ComputeSquaredDistance,
- Copy,
- Debug,
- Deserialize,
- MallocSizeOf,
- PartialEq,
- Serialize,
- SpecifiedValueInfo,
- ToAnimatedZero,
- ToComputedValue,
- ToResolvedValue,
- ToShmem,
-)]
-#[repr(u8)]
-pub enum IsAbsolute {
- Yes,
- No,
-}
-
-impl IsAbsolute {
- /// Return true if this is IsAbsolute::Yes.
- #[inline]
- pub fn is_yes(&self) -> bool {
- *self == IsAbsolute::Yes
- }
-
- /// Return Yes if value is true. Otherwise, return No.
- #[inline]
- fn new(value: bool) -> Self {
- if value {
- IsAbsolute::Yes
- } else {
- IsAbsolute::No
- }
- }
-}
-
/// The path coord type.
-#[allow(missing_docs)]
-#[derive(
- AddAssign,
- Animate,
- Clone,
- ComputeSquaredDistance,
- Copy,
- Debug,
- Deserialize,
- MallocSizeOf,
- PartialEq,
- Serialize,
- SpecifiedValueInfo,
- ToAnimatedZero,
- ToComputedValue,
- ToCss,
- ToResolvedValue,
- ToShmem,
-)]
-#[repr(C)]
-pub struct CoordPair {
- x: CSSFloat,
- y: CSSFloat,
-}
-
-impl CoordPair {
- /// Create a CoordPair.
- #[inline]
- pub fn new(x: CSSFloat, y: CSSFloat) -> Self {
- CoordPair { x, y }
- }
-}
-
-/// The EllipticalArc flag type.
-#[derive(
- Clone,
- Copy,
- Debug,
- Deserialize,
- MallocSizeOf,
- PartialEq,
- Serialize,
- SpecifiedValueInfo,
- ToComputedValue,
- ToResolvedValue,
- ToShmem,
-)]
-#[repr(C)]
-pub struct ArcFlag(bool);
-
-impl ToCss for ArcFlag {
- #[inline]
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: fmt::Write,
- {
- (self.0 as i32).to_css(dest)
- }
-}
-
-impl Animate for ArcFlag {
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- (self.0 as i32)
- .animate(&(other.0 as i32), procedure)
- .map(|v| ArcFlag(v > 0))
- }
-}
-
-impl ComputeSquaredDistance for ArcFlag {
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
- (self.0 as i32).compute_squared_distance(&(other.0 as i32))
- }
-}
-
-impl ToAnimatedZero for ArcFlag {
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> {
- // The 2 ArcFlags in EllipticalArc determine which one of the 4 different arcs will be
- // used. (i.e. From 4 combinations). In other words, if we change the flag, we get a
- // different arc. Therefore, we return *self.
- // https://svgwg.org/svg2-draft/paths.html#PathDataEllipticalArcCommands
- Ok(*self)
- }
-}
+pub type CoordPair = CoordinatePair<CSSFloat>;
/// SVG Path parser.
struct PathParser<'a> {
@@ -736,7 +517,7 @@ struct PathParser<'a> {
macro_rules! parse_arguments {
(
$parser:ident,
- $abs:ident,
+ $by_to:ident,
$enum:ident,
[ $para:ident => $func:ident $(, $other_para:ident => $other_func:ident)* ]
) => {
@@ -747,7 +528,9 @@ macro_rules! parse_arguments {
skip_comma_wsp(&mut $parser.chars);
let $other_para = $other_func(&mut $parser.chars)?;
)*
- $parser.path.push(PathCommand::$enum { $para $(, $other_para)*, $abs });
+ $parser.path.push(
+ PathCommand::$enum { $by_to, $para $(, $other_para)* }
+ );
// End of string or the next character is a possible new command.
if !skip_wsp(&mut $parser.chars) ||
@@ -785,23 +568,23 @@ impl<'a> PathParser<'a> {
}
let command = self.chars.next().unwrap();
- let abs = if command.is_ascii_uppercase() {
- IsAbsolute::Yes
+ let by_to = if command.is_ascii_uppercase() {
+ ByTo::To
} else {
- IsAbsolute::No
+ ByTo::By
};
skip_wsp(&mut self.chars);
match command {
b'Z' | b'z' => self.parse_closepath(),
- b'L' | b'l' => self.parse_lineto(abs),
- b'H' | b'h' => self.parse_h_lineto(abs),
- b'V' | b'v' => self.parse_v_lineto(abs),
- b'C' | b'c' => self.parse_curveto(abs),
- b'S' | b's' => self.parse_smooth_curveto(abs),
- b'Q' | b'q' => self.parse_quadratic_bezier_curveto(abs),
- b'T' | b't' => self.parse_smooth_quadratic_bezier_curveto(abs),
- b'A' | b'a' => self.parse_elliptical_arc(abs),
+ b'L' | b'l' => self.parse_lineto(by_to),
+ b'H' | b'h' => self.parse_h_lineto(by_to),
+ b'V' | b'v' => self.parse_v_lineto(by_to),
+ b'C' | b'c' => self.parse_curveto(by_to),
+ b'S' | b's' => self.parse_smooth_curveto(by_to),
+ b'Q' | b'q' => self.parse_quadratic_bezier_curveto(by_to),
+ b'T' | b't' => self.parse_smooth_quadratic_bezier_curveto(by_to),
+ b'A' | b'a' => self.parse_elliptical_arc(by_to),
_ => return Err(()),
}?;
}
@@ -817,12 +600,8 @@ impl<'a> PathParser<'a> {
skip_wsp(&mut self.chars);
let point = parse_coord(&mut self.chars)?;
- let absolute = if command == b'M' {
- IsAbsolute::Yes
- } else {
- IsAbsolute::No
- };
- self.path.push(PathCommand::MoveTo { point, absolute });
+ let by_to = if command == b'M' { ByTo::To } else { ByTo::By };
+ self.path.push(PathCommand::Move { by_to, point });
// End of string or the next character is a possible new command.
if !skip_wsp(&mut self.chars) || self.chars.peek().map_or(true, |c| c.is_ascii_alphabetic())
@@ -833,69 +612,74 @@ impl<'a> PathParser<'a> {
// If a moveto is followed by multiple pairs of coordinates, the subsequent
// pairs are treated as implicit lineto commands.
- self.parse_lineto(absolute)
+ self.parse_lineto(by_to)
}
/// Parse "closepath" command.
fn parse_closepath(&mut self) -> Result<(), ()> {
- self.path.push(PathCommand::ClosePath);
+ self.path.push(PathCommand::Close);
Ok(())
}
/// Parse "lineto" command.
- fn parse_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, LineTo, [ point => parse_coord ])
+ fn parse_lineto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, Line, [ point => parse_coord ])
}
/// Parse horizontal "lineto" command.
- fn parse_h_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, HorizontalLineTo, [ x => parse_number ])
+ fn parse_h_lineto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, HLine, [ x => parse_number ])
}
/// Parse vertical "lineto" command.
- fn parse_v_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, VerticalLineTo, [ y => parse_number ])
+ fn parse_v_lineto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, VLine, [ y => parse_number ])
}
/// Parse cubic Bézier curve command.
- fn parse_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, CurveTo, [
+ fn parse_curveto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, CubicCurve, [
control1 => parse_coord, control2 => parse_coord, point => parse_coord
])
}
/// Parse smooth "curveto" command.
- fn parse_smooth_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, SmoothCurveTo, [
+ fn parse_smooth_curveto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, SmoothCubic, [
control2 => parse_coord, point => parse_coord
])
}
/// Parse quadratic Bézier curve command.
- fn parse_quadratic_bezier_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, QuadBezierCurveTo, [
+ fn parse_quadratic_bezier_curveto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, QuadCurve, [
control1 => parse_coord, point => parse_coord
])
}
/// Parse smooth quadratic Bézier curveto command.
- fn parse_smooth_quadratic_bezier_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
- parse_arguments!(self, absolute, SmoothQuadBezierCurveTo, [ point => parse_coord ])
+ fn parse_smooth_quadratic_bezier_curveto(&mut self, by_to: ByTo) -> Result<(), ()> {
+ parse_arguments!(self, by_to, SmoothQuad, [ point => parse_coord ])
}
/// Parse elliptical arc curve command.
- fn parse_elliptical_arc(&mut self, absolute: IsAbsolute) -> Result<(), ()> {
+ fn parse_elliptical_arc(&mut self, by_to: ByTo) -> Result<(), ()> {
// Parse a flag whose value is '0' or '1'; otherwise, return Err(()).
- let parse_flag = |iter: &mut Peekable<Cloned<slice::Iter<u8>>>| match iter.next() {
- Some(c) if c == b'0' || c == b'1' => Ok(ArcFlag(c == b'1')),
+ let parse_arc_size = |iter: &mut Peekable<Cloned<slice::Iter<u8>>>| match iter.next() {
+ Some(c) if c == b'1' => Ok(ArcSize::Large),
+ Some(c) if c == b'0' => Ok(ArcSize::Small),
+ _ => Err(()),
+ };
+ let parse_arc_sweep = |iter: &mut Peekable<Cloned<slice::Iter<u8>>>| match iter.next() {
+ Some(c) if c == b'1' => Ok(ArcSweep::Cw),
+ Some(c) if c == b'0' => Ok(ArcSweep::Ccw),
_ => Err(()),
};
- parse_arguments!(self, absolute, EllipticalArc, [
- rx => parse_number,
- ry => parse_number,
- angle => parse_number,
- large_arc_flag => parse_flag,
- sweep_flag => parse_flag,
+ parse_arguments!(self, by_to, Arc, [
+ radii => parse_coord,
+ rotate => parse_number,
+ arc_size => parse_arc_size,
+ arc_sweep => parse_arc_sweep,
point => parse_coord
])
}
diff --git a/servo/components/style/values/specified/text.rs b/servo/components/style/values/specified/text.rs
index 0e70bd26ac..e26a17ba27 100644
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -454,7 +454,6 @@ pub enum TextAlignKeyword {
Left,
Right,
Center,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
Justify,
#[css(skip)]
#[cfg(feature = "gecko")]
@@ -466,11 +465,11 @@ pub enum TextAlignKeyword {
MozLeft,
#[cfg(feature = "gecko")]
MozRight,
- #[cfg(feature = "servo-layout-2013")]
+ #[cfg(feature = "servo")]
ServoCenter,
- #[cfg(feature = "servo-layout-2013")]
+ #[cfg(feature = "servo")]
ServoLeft,
- #[cfg(feature = "servo-layout-2013")]
+ #[cfg(feature = "servo")]
ServoRight,
}