style: Add percentage for opacity (i.e. <alpha-value>).

The following properties accept <alpha-value> [1], which is
"<number> | <percentage>", so we update the parser, spec links, and
their web-platform-tests.
1. opacity
2. flood-opacity
3. fill-opacity
4. stroke-opacity
5. stop-opacity
6. -moz-window-opacity

Besides, shape-image-threshold [2] still only accepts <number>, so we need
to support a different version of `Opacity::parse()`.

[1] https://drafts.csswg.org/css-color/#typedef-alpha-value
[2] https://drafts.csswg.org/css-shapes/#shape-image-threshold-property

Differential Revision: https://phabricator.services.mozilla.com/D37493
This commit is contained in:
Boris Chiou 2019-07-12 19:49:32 +00:00 committed by Emilio Cobos Álvarez
parent 65bf72f131
commit 87231e676d
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
5 changed files with 43 additions and 14 deletions

View file

@ -601,8 +601,10 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-will-change/#will-change", spec="https://drafts.csswg.org/css-will-change/#will-change",
)} )}
// The spec issue for the parse_method: https://github.com/w3c/csswg-drafts/issues/4102.
${helpers.predefined_type( ${helpers.predefined_type(
"shape-image-threshold", "Opacity", "0.0", "shape-image-threshold", "Opacity", "0.0",
parse_method="parse_number",
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property", spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property",

View file

@ -13,7 +13,7 @@ ${helpers.predefined_type(
"1.0", "1.0",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR", flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-color/#opacity", spec="https://drafts.csswg.org/css-color/#transparency",
servo_restyle_damage = "reflow_out_of_flow", servo_restyle_damage = "reflow_out_of_flow",
)} )}

View file

@ -52,7 +52,7 @@ ${helpers.predefined_type(
"Default::default()", "Default::default()",
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty", spec="https://svgwg.org/svg2-draft/painting.html#FillOpacity",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(
@ -123,7 +123,7 @@ ${helpers.predefined_type(
"Default::default()", "Default::default()",
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty", spec="https://svgwg.org/svg2-draft/painting.html#StrokeOpacity",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(

View file

@ -40,7 +40,7 @@ ${helpers.predefined_type(
"1.0", "1.0",
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity", spec="https://svgwg.org/svg2-draft/pservers.html#StopOpacityProperty",
)} )}
// Section 15 - Filter Effects // Section 15 - Filter Effects
@ -60,7 +60,7 @@ ${helpers.predefined_type(
"1.0", "1.0",
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty", spec="https://drafts.fxtf.org/filter-effects/#FloodOpacityProperty",
)} )}
${helpers.predefined_type( ${helpers.predefined_type(

View file

@ -142,8 +142,8 @@ fn parse_number_with_clamping_mode<'i, 't>(
value: value.min(f32::MAX).max(f32::MIN), value: value.min(f32::MAX).max(f32::MIN),
calc_clamping_mode: None, calc_clamping_mode: None,
}); });
}, }
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
ref t => return Err(location.new_unexpected_token_error(t.clone())), ref t => return Err(location.new_unexpected_token_error(t.clone())),
} }
@ -402,14 +402,18 @@ impl Parse for NonNegativeNumberOrPercentage {
} }
} }
#[allow(missing_docs)] /// The value of Opacity is <alpha-value>, which is "<number> | <percentage>".
/// However, we serialize the specified value as number, so it's ok to store
/// the Opacity as Number.
#[derive( #[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss, ToShmem, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss, ToShmem,
)] )]
pub struct Opacity(Number); pub struct Opacity(Number);
impl Parse for Opacity { impl Opacity {
fn parse<'i, 't>( /// Parse number value only.
#[inline]
pub fn parse_number<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
@ -417,6 +421,29 @@ impl Parse for Opacity {
} }
} }
impl Parse for Opacity {
/// Opacity accepts <number> | <percentage>, so we parse it as NumberOrPercentage,
/// and then convert into an Number if it's a Percentage.
/// https://drafts.csswg.org/cssom/#serializing-css-values
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let number = match NumberOrPercentage::parse(context, input)? {
NumberOrPercentage::Percentage(p) => Number {
value: p.get(),
calc_clamping_mode: if p.is_calc() {
Some(AllowedNumericType::All)
} else {
None
},
},
NumberOrPercentage::Number(n) => n,
};
Ok(Opacity(number))
}
}
impl ToComputedValue for Opacity { impl ToComputedValue for Opacity {
type ComputedValue = CSSFloat; type ComputedValue = CSSFloat;
@ -510,7 +537,7 @@ impl Parse for Integer {
Token::Number { Token::Number {
int_value: Some(v), .. int_value: Some(v), ..
} => return Ok(Integer::new(v)), } => return Ok(Integer::new(v)),
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {}
ref t => return Err(location.new_unexpected_token_error(t.clone())), ref t => return Err(location.new_unexpected_token_error(t.clone())),
} }
@ -786,7 +813,7 @@ impl Attr {
None => { None => {
return Err(location return Err(location
.new_custom_error(StyleParseErrorKind::UnspecifiedError)); .new_custom_error(StyleParseErrorKind::UnspecifiedError));
}, }
}; };
Some((prefix, ns)) Some((prefix, ns))
} else { } else {
@ -796,10 +823,10 @@ impl Attr {
namespace: prefix_and_ns, namespace: prefix_and_ns,
attribute: Atom::from(second_token.as_ref()), attribute: Atom::from(second_token.as_ref()),
}); });
}, }
// In the case of attr(foobar ) we don't want to error out // In the case of attr(foobar ) we don't want to error out
// because of the trailing whitespace // because of the trailing whitespace
Token::WhiteSpace(..) => {}, Token::WhiteSpace(..) => {}
ref t => return Err(input.new_unexpected_token_error(t.clone())), ref t => return Err(input.new_unexpected_token_error(t.clone())),
} }
} }