Auto merge of #12458 - Manishearth:style-gecko-only, r=emilio

Cleanups in autoarray helper

Addresses @emilio's comments from #11851

- Replace gecko_autoarray_longhand with vector_longhand, make it configurable
- Allow for empty vectors, use empty vector longhand in box-shadow

<!-- 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/12458)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-07-15 22:31:37 -07:00 committed by GitHub
commit a8a6d83d07
4 changed files with 68 additions and 94 deletions

View file

@ -37,12 +37,18 @@
// and handle the empty case correctly
<%doc>
To be used in cases where we have a grammar like
"<thing> [ , <thing> ]*", but only support a single value
in servo
"<thing> [ , <thing> ]*". `gecko_only` should be set
to True for cases where Servo takes a single value
and Stylo supports vector values.
Setting allow_empty to False allows for cases where the vector
is empty. The grammar for these is usually "none | <thing> [ , <thing> ]*".
We assume that the default/initial value is an empty vector for these.
`initial_value` need not be defined for these.
</%doc>
<%def name="gecko_autoarray_longhand(name, **kwargs)">
<%def name="vector_longhand(name, gecko_only=False, allow_empty=False, **kwargs)">
<%call expr="longhand(name, **kwargs)">
% if product == "gecko":
% if product == "gecko" or not gecko_only:
use cssparser::ToCss;
use std::fmt;
@ -63,10 +69,17 @@
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if !self.0.is_empty() {
try!(self.0[0].to_css(dest));
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
try!(val.to_css(dest));
} else {
% if allow_empty:
try!(dest.write_str("none"));
% else:
error!("Found empty value for property ${name}");
% endif
}
for i in self.0.iter().skip(1) {
for i in iter {
try!(dest.write_str(", "));
try!(i.to_css(dest));
}
@ -80,10 +93,17 @@
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if !self.0.is_empty() {
try!(self.0[0].to_css(dest))
let mut iter = self.0.iter();
if let Some(val) = iter.next() {
try!(val.to_css(dest));
} else {
% if allow_empty:
try!(dest.write_str("none"));
% else:
error!("Found empty value for property ${name}");
% endif
}
for i in self.0.iter().skip(1) {
for i in iter {
try!(dest.write_str(", "));
try!(i.to_css(dest));
}
@ -91,12 +111,26 @@
}
}
pub fn get_initial_value() -> computed_value::T {
computed_value::T(vec![single_value::get_initial_value()])
% if allow_empty:
computed_value::T(vec![])
% else:
computed_value::T(vec![single_value::get_initial_value()])
% endif
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.parse_comma_separated(|parser| {
single_value::parse(context, parser)
}).map(|ok| SpecifiedValue(ok))
% if allow_empty:
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
Ok(SpecifiedValue(Vec::new()))
} else {
input.parse_comma_separated(|parser| {
single_value::parse(context, parser)
}).map(SpecifiedValue)
}
% else:
input.parse_comma_separated(|parser| {
single_value::parse(context, parser)
}).map(SpecifiedValue)
% endif
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;

View file

@ -16,7 +16,7 @@ use properties::longhands::line_height::computed_value::T as LineHeight;
use properties::longhands::text_shadow::computed_value::T as TextShadowList;
use properties::longhands::text_shadow::computed_value::TextShadow;
use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
use properties::longhands::box_shadow::computed_value::BoxShadow;
use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
use properties::longhands::transform::computed_value::ComputedMatrix;
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use properties::longhands::transform::computed_value::T as TransformList;

View file

@ -10,7 +10,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
"::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */",
animatable=True)}
<%helpers:gecko_autoarray_longhand name="background-image" animatable="False">
<%helpers:vector_longhand gecko_only="True" name="background-image" animatable="False">
use cssparser::ToCss;
use std::fmt;
use values::specified::Image;
@ -70,7 +70,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
}
}
}
</%helpers:gecko_autoarray_longhand>
</%helpers:vector_longhand>
<%helpers:longhand name="background-position" animatable="True">
use cssparser::ToCss;

View file

@ -12,18 +12,14 @@ ${helpers.predefined_type("opacity",
"1.0",
animatable=True)}
<%helpers:longhand name="box-shadow" animatable="True">
<%helpers:vector_longhand name="box-shadow" allow_empty="True" animatable="True">
use cssparser::{self, ToCss};
use std::fmt;
use values::LocalToCss;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(Vec<SpecifiedBoxShadow>);
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedBoxShadow {
pub struct SpecifiedValue {
pub offset_x: specified::Length,
pub offset_y: specified::Length,
pub blur_radius: specified::Length,
@ -33,23 +29,6 @@ ${helpers.predefined_type("opacity",
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.0.iter();
if let Some(shadow) = iter.next() {
try!(shadow.to_css(dest));
} else {
try!(dest.write_str("none"));
return Ok(())
}
for shadow in iter {
try!(dest.write_str(", "));
try!(shadow.to_css(dest));
}
Ok(())
}
}
impl ToCss for SpecifiedBoxShadow {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.inset {
try!(dest.write_str("inset "));
@ -75,13 +54,9 @@ ${helpers.predefined_type("opacity",
use std::fmt;
use values::computed;
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Vec<BoxShadow>);
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct BoxShadow {
pub struct T {
pub offset_x: Au,
pub offset_y: Au,
pub blur_radius: Au,
@ -92,23 +67,6 @@ ${helpers.predefined_type("opacity",
}
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.0.iter();
if let Some(shadow) = iter.next() {
try!(shadow.to_css(dest));
} else {
try!(dest.write_str("none"));
return Ok(())
}
for shadow in iter {
try!(dest.write_str(", "));
try!(shadow.to_css(dest));
}
Ok(())
}
}
impl ToCss for computed_value::BoxShadow {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.inset {
try!(dest.write_str("inset "));
@ -126,44 +84,26 @@ ${helpers.predefined_type("opacity",
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(Vec::new())
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
Ok(SpecifiedValue(Vec::new()))
} else {
input.parse_comma_separated(parse_one_box_shadow).map(SpecifiedValue)
}
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T {
computed_value::T(self.0.iter().map(|value| compute_one_box_shadow(value, context)).collect())
computed_value::T {
offset_x: self.offset_x.to_computed_value(context),
offset_y: self.offset_y.to_computed_value(context),
blur_radius: self.blur_radius.to_computed_value(context),
spread_radius: self.spread_radius.to_computed_value(context),
color: self.color
.as_ref()
.map(|color| color.parsed)
.unwrap_or(cssparser::Color::CurrentColor),
inset: self.inset,
}
}
}
pub fn compute_one_box_shadow<Cx: TContext>(value: &SpecifiedBoxShadow, context: &Cx)
-> computed_value::BoxShadow {
computed_value::BoxShadow {
offset_x: value.offset_x.to_computed_value(context),
offset_y: value.offset_y.to_computed_value(context),
blur_radius: value.blur_radius.to_computed_value(context),
spread_radius: value.spread_radius.to_computed_value(context),
color: value.color
.as_ref()
.map(|color| color.parsed)
.unwrap_or(cssparser::Color::CurrentColor),
inset: value.inset,
}
}
pub fn parse_one_box_shadow(input: &mut Parser) -> Result<SpecifiedBoxShadow, ()> {
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
use app_units::Au;
let mut lengths = [specified::Length::Absolute(Au(0)); 4];
let mut lengths_parsed = false;
@ -213,7 +153,7 @@ ${helpers.predefined_type("opacity",
return Err(())
}
Ok(SpecifiedBoxShadow {
Ok(SpecifiedValue {
offset_x: lengths[0],
offset_y: lengths[1],
blur_radius: lengths[2],
@ -222,7 +162,7 @@ ${helpers.predefined_type("opacity",
inset: inset,
})
}
</%helpers:longhand>
</%helpers:vector_longhand>
// FIXME: This prop should be animatable
<%helpers:longhand name="clip" animatable="False">