Add PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES to force to parse negative values.

As per SVG spec [1], we should also parse negative color components values for
SMIL, but currently Gecko does not support it either.

[1] https://www.w3.org/TR/SVG/implnote.html#RangeClamping
This commit is contained in:
Hiroyuki Ikezoe 2017-05-13 18:34:15 +09:00
parent b6b3187efa
commit 59dd93f849
3 changed files with 43 additions and 6 deletions

View file

@ -20,6 +20,9 @@ bitflags! {
/// to be in user units (px). /// to be in user units (px).
/// https://www.w3.org/TR/SVG/coords.html#Units /// https://www.w3.org/TR/SVG/coords.html#Units
const PARSING_MODE_ALLOW_UNITLESS_LENGTH = 0x01, const PARSING_MODE_ALLOW_UNITLESS_LENGTH = 0x01,
/// In SVG, out-of-range values are not treated as an error in parsing.
/// https://www.w3.org/TR/SVG/implnote.html#RangeClamping
const PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES = 0x02,
} }
} }
@ -28,6 +31,11 @@ impl ParsingMode {
pub fn allows_unitless_lengths(&self) -> bool { pub fn allows_unitless_lengths(&self) -> bool {
self.intersects(PARSING_MODE_ALLOW_UNITLESS_LENGTH) self.intersects(PARSING_MODE_ALLOW_UNITLESS_LENGTH)
} }
/// Whether the parsing mode allows all numeric values.
pub fn allows_all_numeric_values(&self) -> bool {
self.intersects(PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES)
}
} }
/// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko. /// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko.
@ -39,12 +47,12 @@ pub fn assert_parsing_mode_match() {
macro_rules! check_parsing_modes { macro_rules! check_parsing_modes {
( $( $a:ident => $b:ident ),*, ) => { ( $( $a:ident => $b:ident ),*, ) => {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let mut hints = ParsingMode::all(); let mut modes = ParsingMode::all();
$( $(
assert_eq!(structs::$a as usize, $b.bits() as usize, stringify!($b)); assert_eq!(structs::$a as usize, $b.bits() as usize, stringify!($b));
hints.remove($b); modes.remove($b);
)* )*
assert_eq!(hints, ParsingMode::empty(), "all ParsingMode bits should have an assertion"); assert_eq!(modes, ParsingMode::empty(), "all ParsingMode bits should have an assertion");
} }
} }
} }
@ -52,6 +60,7 @@ pub fn assert_parsing_mode_match() {
check_parsing_modes! { check_parsing_modes! {
ParsingMode_Default => PARSING_MODE_DEFAULT, ParsingMode_Default => PARSING_MODE_DEFAULT,
ParsingMode_AllowUnitlessLength => PARSING_MODE_ALLOW_UNITLESS_LENGTH, ParsingMode_AllowUnitlessLength => PARSING_MODE_ALLOW_UNITLESS_LENGTH,
ParsingMode_AllowAllNumericValues => PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES,
} }
} }

View file

@ -632,13 +632,21 @@ impl Number {
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> { pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
if context.parsing_mode.allows_all_numeric_values() {
parse_number(context, input)
} else {
parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative) parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
} }
}
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> { pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
if context.parsing_mode.allows_all_numeric_values() {
parse_number(context, input)
} else {
parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne) parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne)
} }
}
} }
impl ToComputedValue for Number { impl ToComputedValue for Number {

View file

@ -3,8 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au; use app_units::Au;
use cssparser::Parser;
use media_queries::CSSErrorReporterTest;
use style::context::QuirksMode;
use style::parser::{PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES, ParserContext};
use style::stylesheets::{CssRuleType, Origin};
use style::values::HasViewportPercentage; use style::values::HasViewportPercentage;
use style::values::specified::{AbsoluteLength, NoCalcLength, ViewportPercentageLength}; use style::values::specified::{AbsoluteLength, NoCalcLength, Number, ViewportPercentageLength};
#[test] #[test]
fn length_has_viewport_percentage() { fn length_has_viewport_percentage() {
@ -13,3 +18,18 @@ fn length_has_viewport_percentage() {
let l = NoCalcLength::Absolute(AbsoluteLength::Px(Au(100).to_f32_px())); let l = NoCalcLength::Absolute(AbsoluteLength::Px(Au(100).to_f32_px()));
assert!(!l.has_viewport_percentage()); assert!(!l.has_viewport_percentage());
} }
#[test]
fn test_parsing_allo_all_numeric_values() {
// In SVG length mode, non-zero lengths are assumed to be px.
let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap();
let reporter = CSSErrorReporterTest;
let context = ParserContext::new(Origin::Author, &url, &reporter,
Some(CssRuleType::Style), PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES,
QuirksMode::NoQuirks);
let mut parser = Parser::new("-1");
let result = Number::parse_non_negative(&context, &mut parser);
assert!(result.is_ok());
assert_eq!(result.unwrap(), Number::new(-1.));
}