mirror of
https://github.com/servo/servo.git
synced 2025-06-24 17:14:33 +01:00
Support serializing vector backgrounds in shorthand form
This commit is contained in:
parent
979a2798d5
commit
66cdf9ae4f
3 changed files with 176 additions and 136 deletions
|
@ -316,6 +316,10 @@
|
||||||
computed_value::T::${to_rust_ident(values.split()[0])}
|
computed_value::T::${to_rust_ident(values.split()[0])}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
|
get_initial_value()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ()> {
|
||||||
computed_value::T::parse(input)
|
computed_value::T::parse(input)
|
||||||
|
|
|
@ -12,172 +12,208 @@
|
||||||
use properties::longhands::{background_image, background_size, background_origin, background_clip};
|
use properties::longhands::{background_image, background_size, background_origin, background_clip};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||||
let mut color = None;
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
let mut image = None;
|
let mut any_${name} = false;
|
||||||
let mut position = None;
|
% endfor
|
||||||
let mut repeat = None;
|
|
||||||
let mut size = None;
|
|
||||||
let mut attachment = None;
|
|
||||||
let mut any = false;
|
|
||||||
let mut origin = None;
|
|
||||||
let mut clip = None;
|
|
||||||
|
|
||||||
loop {
|
let mut background_color = None;
|
||||||
if position.is_none() {
|
let vec = try!(input.parse_comma_separated(|input| {
|
||||||
if let Ok(value) = input.try(|input| background_position::parse(context, input)) {
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
position = Some(value);
|
let mut ${name} = None;
|
||||||
any = true;
|
% endfor
|
||||||
|
|
||||||
// Parse background size, if applicable.
|
loop {
|
||||||
size = input.try(|input| {
|
if background_color.is_none() {
|
||||||
try!(input.expect_delim('/'));
|
if let Ok(value) = input.try(|input| background_color::parse(context, input)) {
|
||||||
background_size::parse(context, input)
|
background_color = Some(value);
|
||||||
}).ok();
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// color can only be the last element
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
if position.is_none() {
|
||||||
|
if let Ok(value) = input.try(|input| background_position::single_value::parse(context, input)) {
|
||||||
|
position = Some(value);
|
||||||
|
any_position = true;
|
||||||
|
|
||||||
continue
|
// Parse background size, if applicable.
|
||||||
|
size = input.try(|input| {
|
||||||
|
try!(input.expect_delim('/'));
|
||||||
|
background_size::single_value::parse(context, input)
|
||||||
|
}).ok();
|
||||||
|
if let Some(_) = size {
|
||||||
|
any_size = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
% for name in "image repeat attachment origin clip".split():
|
||||||
|
if ${name}.is_none() {
|
||||||
|
if let Ok(value) = input.try(|input| background_${name}::single_value::parse(context, input)) {
|
||||||
|
${name} = Some(value);
|
||||||
|
any_${name} = true;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if color.is_none() {
|
Ok((image, position, repeat, size, attachment, origin, clip))
|
||||||
if let Ok(value) = input.try(|input| background_color::parse(context, input)) {
|
}));
|
||||||
color = Some(value);
|
|
||||||
any = true;
|
if !(any_image || any_position || any_repeat || any_size ||
|
||||||
continue
|
any_attachment || any_origin || any_clip ||
|
||||||
}
|
background_color.is_some()) {
|
||||||
}
|
return Err(())
|
||||||
if image.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| background_image::parse(context, input)) {
|
|
||||||
image = Some(value);
|
|
||||||
any = true;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if repeat.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| background_repeat::parse(context, input)) {
|
|
||||||
repeat = Some(value);
|
|
||||||
any = true;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if attachment.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| background_attachment::parse(context, input)) {
|
|
||||||
attachment = Some(value);
|
|
||||||
any = true;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if origin.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| background_origin::parse(context, input)) {
|
|
||||||
origin = Some(value);
|
|
||||||
any = true;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if clip.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| background_clip::parse(context, input)) {
|
|
||||||
clip = Some(value);
|
|
||||||
any = true;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if any {
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
Ok(Longhands {
|
let mut background_${name} = if any_${name} {
|
||||||
background_color: color,
|
Some(background_${name}::SpecifiedValue(Vec::new()))
|
||||||
background_image: image,
|
} else {
|
||||||
background_position: position,
|
None
|
||||||
background_repeat: repeat,
|
};
|
||||||
background_attachment: attachment,
|
% endfor
|
||||||
background_size: size,
|
|
||||||
background_origin: origin,
|
for i in vec {
|
||||||
background_clip: clip,
|
% for i,name in enumerate("image position repeat size attachment origin clip".split()):
|
||||||
})
|
if let Some(ref mut buf) = background_${name} {
|
||||||
} else {
|
if let Some(bg_${name}) = i.${i} {
|
||||||
Err(())
|
buf.0.push(bg_${name})
|
||||||
|
} else {
|
||||||
|
buf.0.push(background_${name}::single_value::get_initial_specified_value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(Longhands {
|
||||||
|
background_color: background_color,
|
||||||
|
background_image: background_image,
|
||||||
|
background_position: background_position,
|
||||||
|
background_repeat: background_repeat,
|
||||||
|
background_attachment: background_attachment,
|
||||||
|
background_size: background_size,
|
||||||
|
background_origin: background_origin,
|
||||||
|
background_clip: background_clip,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
match *self.background_color {
|
// mako doesn't like ampersands following `<`
|
||||||
DeclaredValue::Value(ref color) => {
|
fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
|
||||||
try!(color.to_css(dest));
|
match *x {
|
||||||
},
|
DeclaredValue::Value(ref val) => Some(val),
|
||||||
_ => {
|
_ => None,
|
||||||
try!(write!(dest, "transparent"));
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
use std::cmp;
|
||||||
|
use std::iter::{once, repeat};
|
||||||
|
let mut len = 0;
|
||||||
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
|
len = cmp::max(len, extract_value(self.background_${name}).map(|i| i.0.len())
|
||||||
|
.unwrap_or(0));
|
||||||
|
% endfor
|
||||||
|
|
||||||
try!(write!(dest, " "));
|
let iter = repeat(None).take(len - 1).chain(once(Some(self.background_color)))
|
||||||
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
|
.zip(extract_value(self.background_${name}).into_iter()
|
||||||
|
.flat_map(|x| x.0.iter())
|
||||||
|
.map(Some).chain(repeat(None)))
|
||||||
|
% endfor
|
||||||
|
;
|
||||||
|
let mut first = true;
|
||||||
|
for (((((((color, image), position), repeat), size), attachment), origin), clip) in iter {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
try!(write!(dest, ", "));
|
||||||
|
}
|
||||||
|
match color {
|
||||||
|
Some(&DeclaredValue::Value(ref color)) => {
|
||||||
|
try!(color.to_css(dest));
|
||||||
|
try!(write!(dest, " "));
|
||||||
|
},
|
||||||
|
Some(_) => {
|
||||||
|
try!(write!(dest, "transparent "));
|
||||||
|
try!(write!(dest, " "));
|
||||||
|
}
|
||||||
|
// Not yet the last one
|
||||||
|
None => ()
|
||||||
|
};
|
||||||
|
|
||||||
match *self.background_image {
|
|
||||||
DeclaredValue::Value(ref image) => {
|
if let Some(image) = image {
|
||||||
try!(image.to_css(dest));
|
try!(image.to_css(dest));
|
||||||
},
|
} else {
|
||||||
_ => {
|
|
||||||
try!(write!(dest, "none"));
|
try!(write!(dest, "none"));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
|
|
||||||
try!(self.background_repeat.to_css(dest));
|
if let Some(repeat) = repeat {
|
||||||
|
try!(repeat.to_css(dest));
|
||||||
|
} else {
|
||||||
|
try!(write!(dest, "repeat"));
|
||||||
|
}
|
||||||
|
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
|
|
||||||
match *self.background_attachment {
|
if let Some(attachment) = attachment {
|
||||||
DeclaredValue::Value(ref attachment) => {
|
|
||||||
try!(attachment.to_css(dest));
|
try!(attachment.to_css(dest));
|
||||||
},
|
} else {
|
||||||
_ => {
|
|
||||||
try!(write!(dest, "scroll"));
|
try!(write!(dest, "scroll"));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
|
|
||||||
try!(self.background_position.to_css(dest));
|
try!(position.unwrap_or(&background_position::single_value
|
||||||
|
::get_initial_specified_value())
|
||||||
|
.to_css(dest));
|
||||||
|
|
||||||
if let DeclaredValue::Value(ref size) = *self.background_size {
|
if let Some(size) = size {
|
||||||
try!(write!(dest, " / "));
|
try!(write!(dest, " / "));
|
||||||
try!(size.to_css(dest));
|
try!(size.to_css(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
match (self.background_origin, self.background_clip) {
|
match (origin, clip) {
|
||||||
(&DeclaredValue::Value(ref origin), &DeclaredValue::Value(ref clip)) => {
|
(Some(origin), Some(clip)) => {
|
||||||
use properties::longhands::background_origin::computed_value::T as Origin;
|
use properties::longhands::background_origin::single_value::computed_value::T as Origin;
|
||||||
use properties::longhands::background_clip::computed_value::T as Clip;
|
use properties::longhands::background_clip::single_value::computed_value::T as Clip;
|
||||||
|
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
|
|
||||||
match (origin, clip) {
|
match (origin, clip) {
|
||||||
(&Origin::padding_box, &Clip::padding_box) => {
|
(&Origin::padding_box, &Clip::padding_box) => {
|
||||||
try!(origin.to_css(dest));
|
try!(origin.to_css(dest));
|
||||||
},
|
},
|
||||||
(&Origin::border_box, &Clip::border_box) => {
|
(&Origin::border_box, &Clip::border_box) => {
|
||||||
try!(origin.to_css(dest));
|
try!(origin.to_css(dest));
|
||||||
},
|
},
|
||||||
(&Origin::content_box, &Clip::content_box) => {
|
(&Origin::content_box, &Clip::content_box) => {
|
||||||
try!(origin.to_css(dest));
|
try!(origin.to_css(dest));
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
try!(origin.to_css(dest));
|
try!(origin.to_css(dest));
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
try!(clip.to_css(dest));
|
try!(clip.to_css(dest));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
(Some(origin), _) => {
|
||||||
(&DeclaredValue::Value(ref origin), _) => {
|
try!(write!(dest, " "));
|
||||||
try!(write!(dest, " "));
|
try!(origin.to_css(dest));
|
||||||
try!(origin.to_css(dest));
|
},
|
||||||
},
|
(_, Some(clip)) => {
|
||||||
(_, &DeclaredValue::Value(ref clip)) => {
|
try!(write!(dest, " "));
|
||||||
try!(write!(dest, " "));
|
try!(clip.to_css(dest));
|
||||||
try!(clip.to_css(dest));
|
},
|
||||||
},
|
_ => {}
|
||||||
_ => {}
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -89,8 +89,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Border radius for the radius shorthand is not implemented correctly yet
|
// TODO: Border radius for the radius shorthand is not implemented correctly yet
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
try!(self._moz_outline_radius_topleft.to_css(dest));
|
try!(self._moz_outline_radius_topleft.to_css(dest));
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue