mirror of
https://github.com/servo/servo.git
synced 2025-08-12 08:55:32 +01:00
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:
parent
0936dd24d0
commit
6069e44f02
18 changed files with 130 additions and 53 deletions
|
@ -8,7 +8,7 @@
|
|||
|
||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
||||
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule};
|
||||
use parser::{ParserContext, log_css_error};
|
||||
use parser::{LengthParsingMode, ParserContext, log_css_error};
|
||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
||||
use properties::{PropertyDeclarationId, LonghandId, ParsedDeclaration};
|
||||
use properties::LonghandIdSet;
|
||||
|
@ -129,7 +129,8 @@ impl Keyframe {
|
|||
let context = ParserContext::new(parent_stylesheet.origin,
|
||||
&parent_stylesheet.url_data,
|
||||
&error_reporter,
|
||||
Some(CssRuleType::Keyframe));
|
||||
Some(CssRuleType::Keyframe),
|
||||
LengthParsingMode::Default);
|
||||
let mut input = Parser::new(css);
|
||||
|
||||
let mut rule_parser = KeyframeListParser {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
use cssparser::{DeclarationListParser, parse_important};
|
||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use parser::{ParserContext, log_css_error};
|
||||
use parser::{LengthParsingMode, ParserContext, log_css_error};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||
|
@ -617,7 +617,11 @@ pub fn parse_style_attribute(input: &str,
|
|||
url_data: &UrlExtraData,
|
||||
error_reporter: &ParseErrorReporter)
|
||||
-> PropertyDeclarationBlock {
|
||||
let context = ParserContext::new(Origin::Author, url_data, error_reporter, Some(CssRuleType::Style));
|
||||
let context = ParserContext::new(Origin::Author,
|
||||
url_data,
|
||||
error_reporter,
|
||||
Some(CssRuleType::Style),
|
||||
LengthParsingMode::Default);
|
||||
parse_property_declaration_list(&context, &mut Parser::new(input))
|
||||
}
|
||||
|
||||
|
@ -631,7 +635,11 @@ pub fn parse_one_declaration(id: PropertyId,
|
|||
url_data: &UrlExtraData,
|
||||
error_reporter: &ParseErrorReporter)
|
||||
-> Result<ParsedDeclaration, ()> {
|
||||
let context = ParserContext::new(Origin::Author, url_data, error_reporter, Some(CssRuleType::Style));
|
||||
let context = ParserContext::new(Origin::Author,
|
||||
url_data,
|
||||
error_reporter,
|
||||
Some(CssRuleType::Style),
|
||||
LengthParsingMode::Default);
|
||||
Parser::new(input).parse_entirely(|parser| {
|
||||
ParsedDeclaration::parse(id, &context, parser)
|
||||
.map_err(|_| ())
|
||||
|
|
|
@ -27,7 +27,7 @@ use font_metrics::FontMetricsProvider;
|
|||
#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
|
||||
use logical_geometry::WritingMode;
|
||||
use media_queries::Device;
|
||||
use parser::{Parse, ParserContext};
|
||||
use parser::{LengthParsingMode, Parse, ParserContext};
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
||||
use shared_lock::StylesheetGuards;
|
||||
|
@ -369,7 +369,11 @@ impl PropertyDeclarationIdSet {
|
|||
//
|
||||
// FIXME(pcwalton): Cloning the error reporter is slow! But so are custom
|
||||
// properties, so whatever...
|
||||
let context = ParserContext::new(Origin::Author, url_data, error_reporter, None);
|
||||
let context = ParserContext::new(Origin::Author,
|
||||
url_data,
|
||||
error_reporter,
|
||||
None,
|
||||
LengthParsingMode::Default);
|
||||
Parser::new(&css).parse_entirely(|input| {
|
||||
match from_shorthand {
|
||||
None => {
|
||||
|
|
|
@ -23,7 +23,7 @@ use gecko_bindings::sugar::refptr::RefPtr;
|
|||
use keyframes::{Keyframe, parse_keyframe_list};
|
||||
use media_queries::{Device, MediaList, parse_media_query_list};
|
||||
use parking_lot::RwLock;
|
||||
use parser::{Parse, ParserContext, log_css_error};
|
||||
use parser::{LengthParsingMode, Parse, ParserContext, log_css_error};
|
||||
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
|
||||
use selector_parser::{SelectorImpl, SelectorParser};
|
||||
use selectors::parser::SelectorList;
|
||||
|
@ -422,7 +422,8 @@ impl CssRule {
|
|||
let context = ParserContext::new(parent_stylesheet.origin,
|
||||
&parent_stylesheet.url_data,
|
||||
&error_reporter,
|
||||
None);
|
||||
None,
|
||||
LengthParsingMode::Default);
|
||||
let mut input = Parser::new(css);
|
||||
|
||||
// nested rules are in the body state
|
||||
|
@ -695,7 +696,7 @@ impl Stylesheet {
|
|||
shared_lock: shared_lock,
|
||||
loader: stylesheet_loader,
|
||||
context: ParserContext::new_with_line_number_offset(origin, url_data, error_reporter,
|
||||
line_number_offset),
|
||||
line_number_offset, LengthParsingMode::Default),
|
||||
state: Cell::new(State::Start),
|
||||
};
|
||||
|
||||
|
|
|
@ -551,7 +551,12 @@ impl Length {
|
|||
match try!(input.next()) {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
Length::parse_dimension(context, value.value, unit),
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Length::zero()),
|
||||
Token::Number(ref value) => {
|
||||
if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() {
|
||||
return Err(())
|
||||
}
|
||||
Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
||||
input.parse_nested_block(|input| {
|
||||
CalcLengthOrPercentage::parse_length(context, input, num_context)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue