mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Auto merge of #19457 - emilio:color-calc, r=SimonSapin
style: support calc() in color functions. Depends on #19456 and https://github.com/servo/rust-cssparser/pull/207. Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=984021 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19457) <!-- Reviewable:end -->
This commit is contained in:
commit
3cef09ae21
20 changed files with 248 additions and 90 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -281,7 +281,7 @@ dependencies = [
|
|||
"azure 0.23.0 (git+https://github.com/servo/rust-azure)",
|
||||
"canvas_traits 0.0.1",
|
||||
"compositing 0.0.1",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -298,7 +298,7 @@ dependencies = [
|
|||
name = "canvas_traits"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -561,7 +561,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cssparser"
|
||||
version = "0.22.0"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1038,7 +1038,7 @@ name = "geckoservo"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1109,7 +1109,7 @@ dependencies = [
|
|||
name = "gfx_tests"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx 0.0.1",
|
||||
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
|
@ -1696,7 +1696,7 @@ name = "malloc_size_of"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
"mozjs 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2560,7 +2560,7 @@ dependencies = [
|
|||
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deny_public_fields 0.0.1",
|
||||
"devtools_traits 0.0.1",
|
||||
"dom_struct 0.0.1",
|
||||
|
@ -2636,7 +2636,7 @@ dependencies = [
|
|||
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"canvas_traits 0.0.1",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2717,7 +2717,7 @@ name = "selectors"
|
|||
version = "0.19.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
|
@ -3133,7 +3133,7 @@ dependencies = [
|
|||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fallible 0.0.1",
|
||||
|
@ -3192,7 +3192,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3214,7 +3214,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"malloc_size_of_derive 0.0.1",
|
||||
|
@ -3230,7 +3230,7 @@ name = "stylo_tests"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"geckoservo 0.0.1",
|
||||
|
@ -3811,7 +3811,7 @@ dependencies = [
|
|||
"checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
|
||||
"checksum core-graphics 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc0a78ab2ac23b6ea7b3fe5fe93b227900dc0956979735b8f68032417976dd4"
|
||||
"checksum core-text 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcad23756dd1dc4b47bf6a914ace27aadb8fa68889db5837af2308d018d0467c"
|
||||
"checksum cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44313341610282488e1156ad1fedebca51c54766c87a041d0287b10499c04ba1"
|
||||
"checksum cssparser 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83b169a4a5c49826a93ab1778008771b3b05bca95deea76e6c723c667dbc74b8"
|
||||
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
|
||||
"checksum cubeb-ffi 0.0.2 (git+https://github.com/djg/cubeb-pulse-rs?branch=dev)" = "<none>"
|
||||
"checksum cubeb-pulse 0.0.2 (git+https://github.com/djg/cubeb-pulse-rs?branch=dev)" = "<none>"
|
||||
|
|
|
@ -13,7 +13,7 @@ path = "lib.rs"
|
|||
azure = {git = "https://github.com/servo/rust-azure"}
|
||||
canvas_traits = {path = "../canvas_traits"}
|
||||
compositing = {path = "../compositing"}
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
euclid = "0.15"
|
||||
fnv = "1.0"
|
||||
gleam = "0.4"
|
||||
|
|
|
@ -10,7 +10,7 @@ name = "canvas_traits"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
euclid = "0.15"
|
||||
ipc-channel = "0.9"
|
||||
lazy_static = "0.2"
|
||||
|
|
|
@ -13,7 +13,7 @@ servo = ["mozjs", "string_cache", "url", "webrender_api", "xml5ever"]
|
|||
|
||||
[dependencies]
|
||||
app_units = "0.5.5"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
euclid = "0.15"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
mozjs = { version = "0.1.8", features = ["promises"], optional = true }
|
||||
|
|
|
@ -39,7 +39,7 @@ byteorder = "1.0"
|
|||
canvas_traits = {path = "../canvas_traits"}
|
||||
caseless = "0.1.0"
|
||||
cookie = "0.10"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
deny_public_fields = {path = "../deny_public_fields"}
|
||||
devtools_traits = {path = "../devtools_traits"}
|
||||
dom_struct = {path = "../dom_struct"}
|
||||
|
|
|
@ -13,7 +13,7 @@ path = "lib.rs"
|
|||
app_units = "0.5"
|
||||
atomic_refcell = "0.1"
|
||||
canvas_traits = {path = "../canvas_traits"}
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
euclid = "0.15"
|
||||
gfx_traits = {path = "../gfx_traits"}
|
||||
html5ever = "0.21.0"
|
||||
|
|
|
@ -25,7 +25,7 @@ bench = []
|
|||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
matches = "0.1"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
log = "0.3"
|
||||
fnv = "1.0"
|
||||
malloc_size_of = { path = "../malloc_size_of" }
|
||||
|
|
|
@ -35,7 +35,7 @@ atomic_refcell = "0.1"
|
|||
bitflags = "1.0"
|
||||
byteorder = "1.0"
|
||||
cfg-if = "0.1.0"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
encoding_rs = {version = "0.7", optional = true}
|
||||
euclid = "0.15"
|
||||
fallible = { path = "../fallible" }
|
||||
|
|
|
@ -76,7 +76,6 @@ impl<'a> fmt::Display for ContextualParseError<'a> {
|
|||
Token::PrefixMatch => write!(f, "prefix match (^=)"),
|
||||
Token::SuffixMatch => write!(f, "suffix match ($=)"),
|
||||
Token::SubstringMatch => write!(f, "substring match (*=)"),
|
||||
Token::Column => write!(f, "column (||)"),
|
||||
Token::CDO => write!(f, "CDO (<!--)"),
|
||||
Token::CDC => write!(f, "CDC (-->)"),
|
||||
Token::Function(ref name) => write!(f, "function {}", name),
|
||||
|
|
|
@ -81,6 +81,13 @@ impl Angle {
|
|||
self.value.radians()
|
||||
}
|
||||
|
||||
/// Returns the amount of degrees this angle represents.
|
||||
#[inline]
|
||||
pub fn degrees(self) -> f32 {
|
||||
use std::f32::consts::PI;
|
||||
self.radians() * 360. / (2. * PI)
|
||||
}
|
||||
|
||||
/// Returns `0deg`.
|
||||
pub fn zero() -> Self {
|
||||
Self::from_degrees(0.0, false)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//!
|
||||
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use cssparser::{Parser, Token, NumberOrPercentage, AngleOrNumber};
|
||||
use parser::ParserContext;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
|
@ -202,9 +202,8 @@ impl CalcNode {
|
|||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
expected_unit: CalcUnit)
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
expected_unit: CalcUnit,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let mut root = Self::parse_product(context, input, expected_unit)?;
|
||||
|
||||
loop {
|
||||
|
@ -613,4 +612,39 @@ impl CalcNode {
|
|||
.to_time()
|
||||
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<number>` or `<percentage>`.
|
||||
pub fn parse_number_or_percentage<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<NumberOrPercentage, ParseError<'i>> {
|
||||
let node = Self::parse(context, input, CalcUnit::Percentage)?;
|
||||
|
||||
if let Ok(value) = node.to_number() {
|
||||
return Ok(NumberOrPercentage::Number { value })
|
||||
}
|
||||
|
||||
match node.to_percentage() {
|
||||
Ok(unit_value) => Ok(NumberOrPercentage::Percentage { unit_value }),
|
||||
Err(()) => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<number>` or `<angle>`.
|
||||
pub fn parse_angle_or_number<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<AngleOrNumber, ParseError<'i>> {
|
||||
let node = Self::parse(context, input, CalcUnit::Angle)?;
|
||||
|
||||
if let Ok(angle) = node.to_angle() {
|
||||
let degrees = angle.degrees();
|
||||
return Ok(AngleOrNumber::Angle { degrees })
|
||||
}
|
||||
|
||||
match node.to_number() {
|
||||
Ok(value) => Ok(AngleOrNumber::Number { value }),
|
||||
Err(()) => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
//! Specified color values.
|
||||
|
||||
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token, BasicParseError, BasicParseErrorKind};
|
||||
use cssparser::{AngleOrNumber, Color as CSSParserColor, Parser, RGBA, Token};
|
||||
use cssparser::{BasicParseErrorKind, NumberOrPercentage, ParseErrorKind};
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::nscolor;
|
||||
use itoa;
|
||||
|
@ -16,6 +17,7 @@ use std::io::Write;
|
|||
use style_traits::{ToCss, ParseError, StyleParseErrorKind, ValueParseErrorKind};
|
||||
use super::AllowQuirks;
|
||||
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||
use values::specified::calc::CalcNode;
|
||||
|
||||
/// Specified color value
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
|
@ -43,7 +45,6 @@ pub enum Color {
|
|||
InheritFromBodyQuirk,
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
mod gecko {
|
||||
define_css_keyword_enum! { SpecialColorKeyword:
|
||||
|
@ -61,9 +62,127 @@ impl From<RGBA> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
struct ColorComponentParser<'a, 'b: 'a>(&'a ParserContext<'b>);
|
||||
impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponentParser<'a, 'b> {
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
||||
fn parse_angle_or_number<'t>(
|
||||
&self,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<AngleOrNumber, ParseError<'i>> {
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use values::specified::Angle;
|
||||
|
||||
let location = input.current_source_location();
|
||||
let token = input.next()?.clone();
|
||||
match token {
|
||||
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())),
|
||||
};
|
||||
|
||||
Ok(AngleOrNumber::Angle { degrees })
|
||||
}
|
||||
Token::Number { value, .. } => {
|
||||
Ok(AngleOrNumber::Number { value })
|
||||
}
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
input.parse_nested_block(|i| CalcNode::parse_angle_or_number(self.0, i))
|
||||
}
|
||||
t => return Err(location.new_unexpected_token_error(t)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_percentage<'t>(
|
||||
&self,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<f32, ParseError<'i>> {
|
||||
use values::specified::Percentage;
|
||||
|
||||
Ok(Percentage::parse(self.0, input)?.get())
|
||||
}
|
||||
|
||||
fn parse_number<'t>(
|
||||
&self,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<f32, ParseError<'i>> {
|
||||
use values::specified::Number;
|
||||
|
||||
Ok(Number::parse(self.0, input)?.get())
|
||||
}
|
||||
|
||||
fn parse_number_or_percentage<'t>(
|
||||
&self,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<NumberOrPercentage, ParseError<'i>> {
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
|
||||
let location = input.current_source_location();
|
||||
|
||||
match input.next()?.clone() {
|
||||
Token::Number { value, .. } => Ok(NumberOrPercentage::Number { value }),
|
||||
Token::Percentage { unit_value, .. } => {
|
||||
Ok(NumberOrPercentage::Percentage { unit_value })
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
input.parse_nested_block(|i| CalcNode::parse_number_or_percentage(self.0, i))
|
||||
}
|
||||
t => return Err(location.new_unexpected_token_error(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Color {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Color::parse_color(input)
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
|
||||
// Currently we only store authored value for color keywords,
|
||||
// because all browsers serialize those values as keywords for
|
||||
// specified value.
|
||||
let start = input.state();
|
||||
let authored = input.expect_ident_cloned().ok();
|
||||
input.reset(&start);
|
||||
|
||||
let compontent_parser = ColorComponentParser(&*context);
|
||||
match input.try(|i| CSSParserColor::parse_with(&compontent_parser, i)) {
|
||||
Ok(value) => {
|
||||
Ok(match value {
|
||||
CSSParserColor::CurrentColor => Color::CurrentColor,
|
||||
CSSParserColor::RGBA(rgba) => Color::Numeric {
|
||||
parsed: rgba,
|
||||
authored: authored.map(|s| s.to_ascii_lowercase().into_boxed_str()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
if let Ok(system) = input.try(SystemColor::parse) {
|
||||
return Ok(Color::System(system));
|
||||
}
|
||||
|
||||
if let Ok(c) = gecko::SpecialColorKeyword::parse(input) {
|
||||
return Ok(Color::Special(c));
|
||||
}
|
||||
}
|
||||
|
||||
match e.kind {
|
||||
ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(t)) => {
|
||||
Err(e.location.new_custom_error(
|
||||
StyleParseErrorKind::ValueError(ValueParseErrorKind::InvalidColor(t))
|
||||
))
|
||||
}
|
||||
_ => Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,9 +205,9 @@ impl ToCss for Color {
|
|||
|
||||
/// A wrapper of cssparser::Color::parse_hash.
|
||||
///
|
||||
/// That function should never return CurrentColor, so it makes no sense
|
||||
/// to handle a cssparser::Color here. This should really be done in
|
||||
/// cssparser directly rather than here.
|
||||
/// That function should never return CurrentColor, so it makes no sense to
|
||||
/// handle a cssparser::Color here. This should really be done in cssparser
|
||||
/// directly rather than here.
|
||||
fn parse_hash_color(value: &[u8]) -> Result<RGBA, ()> {
|
||||
CSSParserColor::parse_hash(value).map(|color| {
|
||||
match color {
|
||||
|
@ -125,16 +244,17 @@ impl Color {
|
|||
/// Parse a color, with quirks.
|
||||
///
|
||||
/// <https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk>
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
pub fn parse_quirky<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
input.try(|i| Self::parse(context, i)).or_else(|e| {
|
||||
if !allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(e);
|
||||
}
|
||||
Color::parse_quirky_color(input)
|
||||
.map(|rgba| Color::rgba(rgba))
|
||||
.map(Color::rgba)
|
||||
.map_err(|_| e)
|
||||
})
|
||||
}
|
||||
|
@ -205,52 +325,6 @@ impl Color {
|
|||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a <color> value.
|
||||
pub fn parse_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// Currently we only store authored value for color keywords,
|
||||
// because all browsers serialize those values as keywords for
|
||||
// specified value.
|
||||
let start = input.state();
|
||||
let authored = match input.next() {
|
||||
Ok(&Token::Ident(ref s)) => Some(s.clone()),
|
||||
_ => None,
|
||||
};
|
||||
input.reset(&start);
|
||||
match input.try(CSSParserColor::parse) {
|
||||
Ok(value) =>
|
||||
Ok(match value {
|
||||
CSSParserColor::CurrentColor => Color::CurrentColor,
|
||||
CSSParserColor::RGBA(rgba) => {
|
||||
Color::Numeric {
|
||||
parsed: rgba,
|
||||
authored: authored.map(|s| s.to_lowercase().into_boxed_str()),
|
||||
}
|
||||
}
|
||||
}),
|
||||
Err(e) => {
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
if let Ok(system) = input.try(SystemColor::parse) {
|
||||
return Ok(Color::System(system));
|
||||
}
|
||||
|
||||
if let Ok(c) = gecko::SpecialColorKeyword::parse(input) {
|
||||
return Ok(Color::Special(c));
|
||||
}
|
||||
}
|
||||
|
||||
match e {
|
||||
BasicParseError { kind: BasicParseErrorKind::UnexpectedToken(t), location } => {
|
||||
Err(location.new_custom_error(
|
||||
StyleParseErrorKind::ValueError(ValueParseErrorKind::InvalidColor(t))
|
||||
))
|
||||
}
|
||||
e => Err(e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -15,7 +15,7 @@ gecko = []
|
|||
|
||||
[dependencies]
|
||||
app_units = "0.5"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
bitflags = "1.0"
|
||||
euclid = "0.15"
|
||||
malloc_size_of = { path = "../malloc_size_of" }
|
||||
|
|
|
@ -15,7 +15,7 @@ gecko_debug = ["style/gecko_debug"]
|
|||
|
||||
[dependencies]
|
||||
atomic_refcell = "0.1"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
|
||||
libc = "0.2"
|
||||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
|
|
|
@ -4563,8 +4563,17 @@ fn parse_color(
|
|||
) -> Result<specified::Color, ()> {
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let url_data = unsafe { dummy_url_data() };
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
url_data,
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
);
|
||||
|
||||
let start_position = parser.position();
|
||||
parser.parse_entirely(specified::Color::parse_color).map_err(|err| {
|
||||
parser.parse_entirely(|i| specified::Color::parse(&context, i)).map_err(|err| {
|
||||
if let Some(error_reporter) = error_reporter {
|
||||
match err.kind {
|
||||
ParseErrorKind::Custom(StyleParseErrorKind::ValueError(..)) => {
|
||||
|
|
|
@ -10,7 +10,7 @@ path = "lib.rs"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
gfx = {path = "../../../components/gfx"}
|
||||
ipc-channel = "0.9"
|
||||
style = {path = "../../../components/style"}
|
||||
|
|
|
@ -12,7 +12,7 @@ doctest = false
|
|||
[dependencies]
|
||||
byteorder = "1.0"
|
||||
app_units = "0.5"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
euclid = "0.15"
|
||||
html5ever = "0.21"
|
||||
parking_lot = "0.4"
|
||||
|
|
|
@ -13,7 +13,7 @@ doctest = false
|
|||
|
||||
[dependencies]
|
||||
atomic_refcell = "0.1"
|
||||
cssparser = "0.22.0"
|
||||
cssparser = "0.23.0"
|
||||
env_logger = "0.4"
|
||||
euclid = "0.15"
|
||||
geckoservo = {path = "../../../ports/geckolib"}
|
||||
|
|
|
@ -303223,6 +303223,12 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-values/calc-in-color-001.html": [
|
||||
[
|
||||
"/css/css-values/calc-in-color-001.html",
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-values/calc-serialization.html": [
|
||||
[
|
||||
"/css/css-values/calc-serialization.html",
|
||||
|
@ -503720,6 +503726,10 @@
|
|||
"be08a1510714e8b4fbc4d35582db5708924d06b2",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-values/calc-in-color-001.html": [
|
||||
"32a0face898f08b854ac392c75368282d718be32",
|
||||
"testharness"
|
||||
],
|
||||
"css/css-values/calc-in-media-queries-001.html": [
|
||||
"f8fdd8373eaca7a03d6a089b4faf71825c8bfaf2",
|
||||
"reftest"
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: calc() function in <color></title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values/#funcdef-calc">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="testNode"></div>
|
||||
<script>
|
||||
const div = document.querySelector("#testNode");
|
||||
const TESTS = {
|
||||
// specified -> expected
|
||||
"rgb(calc(0), calc(255 + 0), calc(140 - 139 - 1))": "rgb(0, 255, 0)",
|
||||
"rgba(calc(0%) calc(100%) calc(0%) / calc(10% * 10))": "rgb(0, 255, 0)",
|
||||
"hsl(calc(5deg * (360 / 5)), calc(10% * 10), calc(10% * 10))": "rgb(255, 255, 255)"
|
||||
}
|
||||
|
||||
test(function() {
|
||||
for (let test in TESTS) {
|
||||
div.style.backgroundColor = "";
|
||||
div.style.backgroundColor = test;
|
||||
assert_equals(getComputedStyle(div).backgroundColor, TESTS[test], test);
|
||||
}
|
||||
}, "calc() in color functions");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue