SVG length parsing mode

SVG allows non-zero lengths to be accepted and assumes they are in px.  This
adds this length parsing mode to Servo.

MozReview-Commit-ID: Kxd3x64r9Ye
This commit is contained in:
J. Ryan Stinnett 2017-04-12 17:40:48 +08:00
parent 0936dd24d0
commit 6069e44f02
18 changed files with 130 additions and 53 deletions

View file

@ -11,6 +11,24 @@ use error_reporting::ParseErrorReporter;
use style_traits::OneOrMoreCommaSeparated;
use stylesheets::{CssRuleType, Origin, UrlExtraData};
/// The mode to use when parsing lengths.
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum LengthParsingMode {
/// In CSS, lengths must have units, except for zero values, where the unit can be omitted.
/// https://www.w3.org/TR/css3-values/#lengths
Default,
/// In SVG, a coordinate or length value without a unit identifier (e.g., "25") is assumed to be in user units (px).
/// https://www.w3.org/TR/SVG/coords.html#Units
SVG,
}
impl LengthParsingMode {
/// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px.
pub fn allows_unitless_lengths(&self) -> bool {
*self == LengthParsingMode::SVG
}
}
/// The data that the parser needs from outside in order to parse a stylesheet.
pub struct ParserContext<'a> {
/// The `Origin` of the stylesheet, whether it's a user, author or
@ -22,8 +40,10 @@ pub struct ParserContext<'a> {
pub error_reporter: &'a ParseErrorReporter,
/// The current rule type, if any.
pub rule_type: Option<CssRuleType>,
/// line number offsets for inline stylesheets
/// Line number offsets for inline stylesheets
pub line_number_offset: u64,
/// The mode to use when parsing lengths.
pub length_parsing_mode: LengthParsingMode,
}
impl<'a> ParserContext<'a> {
@ -31,7 +51,8 @@ impl<'a> ParserContext<'a> {
pub fn new(stylesheet_origin: Origin,
url_data: &'a UrlExtraData,
error_reporter: &'a ParseErrorReporter,
rule_type: Option<CssRuleType>)
rule_type: Option<CssRuleType>,
length_parsing_mode: LengthParsingMode)
-> ParserContext<'a> {
ParserContext {
stylesheet_origin: stylesheet_origin,
@ -39,15 +60,17 @@ impl<'a> ParserContext<'a> {
error_reporter: error_reporter,
rule_type: rule_type,
line_number_offset: 0u64,
length_parsing_mode: length_parsing_mode,
}
}
/// Create a parser context for on-the-fly parsing in CSSOM
pub fn new_for_cssom(url_data: &'a UrlExtraData,
error_reporter: &'a ParseErrorReporter,
rule_type: Option<CssRuleType>)
rule_type: Option<CssRuleType>,
length_parsing_mode: LengthParsingMode)
-> ParserContext<'a> {
Self::new(Origin::Author, url_data, error_reporter, rule_type)
Self::new(Origin::Author, url_data, error_reporter, rule_type, length_parsing_mode)
}
/// Create a parser context based on a previous context, but with a modified rule type.
@ -60,19 +83,16 @@ impl<'a> ParserContext<'a> {
error_reporter: context.error_reporter,
rule_type: rule_type,
line_number_offset: context.line_number_offset,
length_parsing_mode: context.length_parsing_mode,
}
}
/// Get the rule type, which assumes that one is available.
pub fn rule_type(&self) -> CssRuleType {
self.rule_type.expect("Rule type expected, but none was found.")
}
/// Create a parser context for inline CSS which accepts additional line offset argument.
pub fn new_with_line_number_offset(stylesheet_origin: Origin,
url_data: &'a UrlExtraData,
error_reporter: &'a ParseErrorReporter,
line_number_offset: u64)
line_number_offset: u64,
length_parsing_mode: LengthParsingMode)
-> ParserContext<'a> {
ParserContext {
stylesheet_origin: stylesheet_origin,
@ -80,8 +100,14 @@ impl<'a> ParserContext<'a> {
error_reporter: error_reporter,
rule_type: None,
line_number_offset: line_number_offset,
length_parsing_mode: length_parsing_mode,
}
}
/// Get the rule type, which assumes that one is available.
pub fn rule_type(&self) -> CssRuleType {
self.rule_type.expect("Rule type expected, but none was found.")
}
}
/// Defaults to a no-op.