mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Support multiple backgrounds in servo layout
This commit is contained in:
parent
66cdf9ae4f
commit
69ada0d7a3
5 changed files with 125 additions and 95 deletions
|
@ -60,6 +60,10 @@ use table_cell::CollapsedBordersForCell;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::opts;
|
use util::opts;
|
||||||
|
|
||||||
|
fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
|
||||||
|
&arr[index % arr.len()]
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DisplayListBuildState<'a> {
|
pub struct DisplayListBuildState<'a> {
|
||||||
pub layout_context: &'a LayoutContext<'a>,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
pub items: Vec<DisplayItem>,
|
pub items: Vec<DisplayItem>,
|
||||||
|
@ -146,7 +150,7 @@ pub trait FragmentDisplayListBuilding {
|
||||||
fn compute_background_image_size(&self,
|
fn compute_background_image_size(&self,
|
||||||
style: &ServoComputedValues,
|
style: &ServoComputedValues,
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
image: &WebRenderImageInfo)
|
image: &WebRenderImageInfo, index: usize)
|
||||||
-> Size2D<Au>;
|
-> Size2D<Au>;
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background image of this fragment to the
|
/// Adds the display items necessary to paint the background image of this fragment to the
|
||||||
|
@ -157,7 +161,8 @@ pub trait FragmentDisplayListBuilding {
|
||||||
display_list_section: DisplayListSection,
|
display_list_section: DisplayListSection,
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &ClippingRegion,
|
clip: &ClippingRegion,
|
||||||
image_url: &Url);
|
image_url: &Url,
|
||||||
|
background_index: usize);
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
||||||
/// to the appropriate section of the display list.
|
/// to the appropriate section of the display list.
|
||||||
|
@ -344,27 +349,32 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
if !border_radii.is_square() {
|
if !border_radii.is_square() {
|
||||||
clip.intersect_with_rounded_rect(absolute_bounds, &border_radii)
|
clip.intersect_with_rounded_rect(absolute_bounds, &border_radii)
|
||||||
}
|
}
|
||||||
|
let background = style.get_background();
|
||||||
|
|
||||||
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
// needed. We could use display list optimization to clean this up, but it still seems
|
// needed. We could use display list optimization to clean this up, but it still seems
|
||||||
// inefficient. What we really want is something like "nearest ancestor element that
|
// inefficient. What we really want is something like "nearest ancestor element that
|
||||||
// doesn't have a fragment".
|
// doesn't have a fragment".
|
||||||
let background_color = style.resolve_color(style.get_background().background_color);
|
let background_color = style.resolve_color(background.background_color);
|
||||||
|
|
||||||
// 'background-clip' determines the area within which the background is painted.
|
// 'background-clip' determines the area within which the background is painted.
|
||||||
// http://dev.w3.org/csswg/css-backgrounds-3/#the-background-clip
|
// http://dev.w3.org/csswg/css-backgrounds-3/#the-background-clip
|
||||||
let mut bounds = *absolute_bounds;
|
let mut bounds = *absolute_bounds;
|
||||||
|
|
||||||
match style.get_background().background_clip {
|
// This is the clip for the color (which is the last element in the bg array)
|
||||||
background_clip::T::border_box => {}
|
let color_clip = get_cyclic(&background.background_clip.0,
|
||||||
background_clip::T::padding_box => {
|
background.background_image.0.len() - 1);
|
||||||
|
|
||||||
|
match *color_clip {
|
||||||
|
background_clip::single_value::T::border_box => {}
|
||||||
|
background_clip::single_value::T::padding_box => {
|
||||||
let border = style.logical_border_width().to_physical(style.writing_mode);
|
let border = style.logical_border_width().to_physical(style.writing_mode);
|
||||||
bounds.origin.x = bounds.origin.x + border.left;
|
bounds.origin.x = bounds.origin.x + border.left;
|
||||||
bounds.origin.y = bounds.origin.y + border.top;
|
bounds.origin.y = bounds.origin.y + border.top;
|
||||||
bounds.size.width = bounds.size.width - border.horizontal();
|
bounds.size.width = bounds.size.width - border.horizontal();
|
||||||
bounds.size.height = bounds.size.height - border.vertical();
|
bounds.size.height = bounds.size.height - border.vertical();
|
||||||
}
|
}
|
||||||
background_clip::T::content_box => {
|
background_clip::single_value::T::content_box => {
|
||||||
let border_padding = self.border_padding.to_physical(style.writing_mode);
|
let border_padding = self.border_padding.to_physical(style.writing_mode);
|
||||||
bounds.origin.x = bounds.origin.x + border_padding.left;
|
bounds.origin.x = bounds.origin.x + border_padding.left;
|
||||||
bounds.origin.y = bounds.origin.y + border_padding.top;
|
bounds.origin.y = bounds.origin.y + border_padding.top;
|
||||||
|
@ -388,23 +398,26 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
// Implements background image, per spec:
|
// Implements background image, per spec:
|
||||||
// http://www.w3.org/TR/CSS21/colors.html#background
|
// http://www.w3.org/TR/CSS21/colors.html#background
|
||||||
let background = style.get_background();
|
let background = style.get_background();
|
||||||
match background.background_image.0 {
|
for (i, background_image) in background.background_image.0.iter().enumerate().rev() {
|
||||||
None => {}
|
match background_image.0 {
|
||||||
Some(computed::Image::LinearGradient(ref gradient)) => {
|
None => {}
|
||||||
self.build_display_list_for_background_linear_gradient(state,
|
Some(computed::Image::LinearGradient(ref gradient)) => {
|
||||||
display_list_section,
|
self.build_display_list_for_background_linear_gradient(state,
|
||||||
&bounds,
|
display_list_section,
|
||||||
&clip,
|
&bounds,
|
||||||
gradient,
|
&clip,
|
||||||
style);
|
gradient,
|
||||||
}
|
style);
|
||||||
Some(computed::Image::Url(ref image_url, ref _extra_data)) => {
|
}
|
||||||
self.build_display_list_for_background_image(state,
|
Some(computed::Image::Url(ref image_url, ref _extra_data)) => {
|
||||||
style,
|
self.build_display_list_for_background_image(state,
|
||||||
display_list_section,
|
style,
|
||||||
&bounds,
|
display_list_section,
|
||||||
&clip,
|
&bounds,
|
||||||
image_url);
|
&clip,
|
||||||
|
image_url,
|
||||||
|
i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +425,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
fn compute_background_image_size(&self,
|
fn compute_background_image_size(&self,
|
||||||
style: &ServoComputedValues,
|
style: &ServoComputedValues,
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
image: &WebRenderImageInfo)
|
image: &WebRenderImageInfo,
|
||||||
|
index: usize)
|
||||||
-> Size2D<Au> {
|
-> Size2D<Au> {
|
||||||
// If `image_aspect_ratio` < `bounds_aspect_ratio`, the image is tall; otherwise, it is
|
// If `image_aspect_ratio` < `bounds_aspect_ratio`, the image is tall; otherwise, it is
|
||||||
// wide.
|
// wide.
|
||||||
|
@ -420,19 +434,22 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let bounds_aspect_ratio = bounds.size.width.to_f64_px() / bounds.size.height.to_f64_px();
|
let bounds_aspect_ratio = bounds.size.width.to_f64_px() / bounds.size.height.to_f64_px();
|
||||||
let intrinsic_size = Size2D::new(Au::from_px(image.width as i32),
|
let intrinsic_size = Size2D::new(Au::from_px(image.width as i32),
|
||||||
Au::from_px(image.height as i32));
|
Au::from_px(image.height as i32));
|
||||||
match (style.get_background().background_size.clone(),
|
let background_size = get_cyclic(&style.get_background().background_size.0, index).clone();
|
||||||
image_aspect_ratio < bounds_aspect_ratio) {
|
match (background_size, image_aspect_ratio < bounds_aspect_ratio) {
|
||||||
(background_size::T::Contain, false) | (background_size::T::Cover, true) => {
|
(background_size::single_value::T::Contain, false) |
|
||||||
|
(background_size::single_value::T::Cover, true) => {
|
||||||
Size2D::new(bounds.size.width,
|
Size2D::new(bounds.size.width,
|
||||||
Au::from_f64_px(bounds.size.width.to_f64_px() / image_aspect_ratio))
|
Au::from_f64_px(bounds.size.width.to_f64_px() / image_aspect_ratio))
|
||||||
}
|
}
|
||||||
|
|
||||||
(background_size::T::Contain, true) | (background_size::T::Cover, false) => {
|
(background_size::single_value::T::Contain, true) |
|
||||||
|
(background_size::single_value::T::Cover, false) => {
|
||||||
Size2D::new(Au::from_f64_px(bounds.size.height.to_f64_px() * image_aspect_ratio),
|
Size2D::new(Au::from_f64_px(bounds.size.height.to_f64_px() * image_aspect_ratio),
|
||||||
bounds.size.height)
|
bounds.size.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
(background_size::T::Explicit(background_size::ExplicitSize {
|
(background_size::single_value::T::Explicit(background_size::single_value
|
||||||
|
::ExplicitSize {
|
||||||
width,
|
width,
|
||||||
height: LengthOrPercentageOrAuto::Auto,
|
height: LengthOrPercentageOrAuto::Auto,
|
||||||
}), _) => {
|
}), _) => {
|
||||||
|
@ -441,7 +458,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
Size2D::new(width, Au::from_f64_px(width.to_f64_px() / image_aspect_ratio))
|
Size2D::new(width, Au::from_f64_px(width.to_f64_px() / image_aspect_ratio))
|
||||||
}
|
}
|
||||||
|
|
||||||
(background_size::T::Explicit(background_size::ExplicitSize {
|
(background_size::single_value::T::Explicit(background_size::single_value
|
||||||
|
::ExplicitSize {
|
||||||
width: LengthOrPercentageOrAuto::Auto,
|
width: LengthOrPercentageOrAuto::Auto,
|
||||||
height
|
height
|
||||||
}), _) => {
|
}), _) => {
|
||||||
|
@ -450,7 +468,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
Size2D::new(Au::from_f64_px(height.to_f64_px() * image_aspect_ratio), height)
|
Size2D::new(Au::from_f64_px(height.to_f64_px() * image_aspect_ratio), height)
|
||||||
}
|
}
|
||||||
|
|
||||||
(background_size::T::Explicit(background_size::ExplicitSize {
|
(background_size::single_value::T::Explicit(background_size::single_value
|
||||||
|
::ExplicitSize {
|
||||||
width,
|
width,
|
||||||
height
|
height
|
||||||
}), _) => {
|
}), _) => {
|
||||||
|
@ -468,19 +487,22 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
display_list_section: DisplayListSection,
|
display_list_section: DisplayListSection,
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &ClippingRegion,
|
clip: &ClippingRegion,
|
||||||
image_url: &Url) {
|
image_url: &Url,
|
||||||
|
index: usize) {
|
||||||
let background = style.get_background();
|
let background = style.get_background();
|
||||||
let fetch_image_data_as_well = !opts::get().use_webrender;
|
let fetch_image_data_as_well = !opts::get().use_webrender;
|
||||||
let webrender_image =
|
let webrender_image =
|
||||||
state.layout_context.get_webrender_image_for_url(image_url,
|
state.layout_context.get_webrender_image_for_url(image_url,
|
||||||
UsePlaceholder::No,
|
UsePlaceholder::No,
|
||||||
fetch_image_data_as_well);
|
fetch_image_data_as_well);
|
||||||
|
|
||||||
if let Some((webrender_image, image_data)) = webrender_image {
|
if let Some((webrender_image, image_data)) = webrender_image {
|
||||||
debug!("(building display list) building background image");
|
debug!("(building display list) building background image");
|
||||||
|
|
||||||
// Use `background-size` to get the size.
|
// Use `background-size` to get the size.
|
||||||
let mut bounds = *absolute_bounds;
|
let mut bounds = *absolute_bounds;
|
||||||
let image_size = self.compute_background_image_size(style, &bounds, &webrender_image);
|
let image_size = self.compute_background_image_size(style, &bounds,
|
||||||
|
&webrender_image, index);
|
||||||
|
|
||||||
// Clip.
|
// Clip.
|
||||||
//
|
//
|
||||||
|
@ -492,51 +514,54 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let border = style.logical_border_width().to_physical(style.writing_mode);
|
let border = style.logical_border_width().to_physical(style.writing_mode);
|
||||||
|
|
||||||
// Use 'background-origin' to get the origin value.
|
// Use 'background-origin' to get the origin value.
|
||||||
let (mut origin_x, mut origin_y) = match background.background_origin {
|
let origin = get_cyclic(&background.background_origin.0, index);
|
||||||
background_origin::T::padding_box => {
|
let (mut origin_x, mut origin_y) = match *origin {
|
||||||
(Au(0), Au(0))
|
background_origin::single_value::T::padding_box => {
|
||||||
}
|
(Au(0), Au(0))
|
||||||
background_origin::T::border_box => {
|
}
|
||||||
(-border.left, -border.top)
|
background_origin::single_value::T::border_box => {
|
||||||
}
|
(-border.left, -border.top)
|
||||||
background_origin::T::content_box => {
|
}
|
||||||
let border_padding = self.border_padding.to_physical(self.style.writing_mode);
|
background_origin::single_value::T::content_box => {
|
||||||
(border_padding.left - border.left, border_padding.top - border.top)
|
let border_padding = self.border_padding.to_physical(self.style.writing_mode);
|
||||||
}
|
(border_padding.left - border.left, border_padding.top - border.top)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use `background-attachment` to get the initial virtual origin
|
// Use `background-attachment` to get the initial virtual origin
|
||||||
let (virtual_origin_x, virtual_origin_y) = match background.background_attachment {
|
let attachment = get_cyclic(&background.background_attachment.0, index);
|
||||||
background_attachment::T::scroll => {
|
let (virtual_origin_x, virtual_origin_y) = match *attachment {
|
||||||
(absolute_bounds.origin.x, absolute_bounds.origin.y)
|
background_attachment::single_value::T::scroll => {
|
||||||
}
|
(absolute_bounds.origin.x, absolute_bounds.origin.y)
|
||||||
background_attachment::T::fixed => {
|
}
|
||||||
// If the ‘background-attachment’ value for this image is ‘fixed’, then
|
background_attachment::single_value::T::fixed => {
|
||||||
// 'background-origin' has no effect.
|
// If the ‘background-attachment’ value for this image is ‘fixed’, then
|
||||||
origin_x = Au(0);
|
// 'background-origin' has no effect.
|
||||||
origin_y = Au(0);
|
origin_x = Au(0);
|
||||||
(Au(0), Au(0))
|
origin_y = Au(0);
|
||||||
}
|
(Au(0), Au(0))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let position = *get_cyclic(&background.background_position.0, index);
|
||||||
// Use `background-position` to get the offset.
|
// Use `background-position` to get the offset.
|
||||||
let horizontal_position = model::specified(background.background_position.horizontal,
|
let horizontal_position = model::specified(position.horizontal,
|
||||||
bounds.size.width - image_size.width);
|
bounds.size.width - image_size.width);
|
||||||
let vertical_position = model::specified(background.background_position.vertical,
|
let vertical_position = model::specified(position.vertical,
|
||||||
bounds.size.height - image_size.height);
|
bounds.size.height - image_size.height);
|
||||||
|
|
||||||
let abs_x = border.left + virtual_origin_x + horizontal_position + origin_x;
|
let abs_x = border.left + virtual_origin_x + horizontal_position + origin_x;
|
||||||
let abs_y = border.top + virtual_origin_y + vertical_position + origin_y;
|
let abs_y = border.top + virtual_origin_y + vertical_position + origin_y;
|
||||||
|
|
||||||
// Adjust origin and size based on background-repeat
|
// Adjust origin and size based on background-repeat
|
||||||
match background.background_repeat {
|
match *get_cyclic(&background.background_repeat.0, index) {
|
||||||
background_repeat::T::no_repeat => {
|
background_repeat::single_value::T::no_repeat => {
|
||||||
bounds.origin.x = abs_x;
|
bounds.origin.x = abs_x;
|
||||||
bounds.origin.y = abs_y;
|
bounds.origin.y = abs_y;
|
||||||
bounds.size.width = image_size.width;
|
bounds.size.width = image_size.width;
|
||||||
bounds.size.height = image_size.height;
|
bounds.size.height = image_size.height;
|
||||||
}
|
}
|
||||||
background_repeat::T::repeat_x => {
|
background_repeat::single_value::T::repeat_x => {
|
||||||
bounds.origin.y = abs_y;
|
bounds.origin.y = abs_y;
|
||||||
bounds.size.height = image_size.height;
|
bounds.size.height = image_size.height;
|
||||||
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
|
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
|
||||||
|
@ -544,7 +569,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
abs_x,
|
abs_x,
|
||||||
image_size.width.to_nearest_px() as u32);
|
image_size.width.to_nearest_px() as u32);
|
||||||
}
|
}
|
||||||
background_repeat::T::repeat_y => {
|
background_repeat::single_value::T::repeat_y => {
|
||||||
bounds.origin.x = abs_x;
|
bounds.origin.x = abs_x;
|
||||||
bounds.size.width = image_size.width;
|
bounds.size.width = image_size.width;
|
||||||
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
|
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
|
||||||
|
@ -552,31 +577,32 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
abs_y,
|
abs_y,
|
||||||
image_size.height.to_nearest_px() as u32);
|
image_size.height.to_nearest_px() as u32);
|
||||||
}
|
}
|
||||||
background_repeat::T::repeat => {
|
background_repeat::single_value::T::repeat => {
|
||||||
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
|
ImageFragmentInfo::tile_image(&mut bounds.origin.x,
|
||||||
&mut bounds.size.width,
|
&mut bounds.size.width,
|
||||||
abs_x,
|
abs_x,
|
||||||
image_size.width.to_nearest_px() as u32);
|
image_size.width.to_nearest_px() as u32);
|
||||||
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
|
ImageFragmentInfo::tile_image(&mut bounds.origin.y,
|
||||||
&mut bounds.size.height,
|
&mut bounds.size.height,
|
||||||
abs_y,
|
abs_y,
|
||||||
image_size.height.to_nearest_px() as u32);
|
image_size.height.to_nearest_px() as u32);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the image display item.
|
// Create the image display item.
|
||||||
let base = state.create_base_display_item(&bounds,
|
let base = state.create_base_display_item(&bounds,
|
||||||
&clip,
|
&clip,
|
||||||
self.node,
|
self.node,
|
||||||
style.get_cursor(Cursor::Default),
|
style.get_cursor(Cursor::Default),
|
||||||
display_list_section);
|
display_list_section);
|
||||||
state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem {
|
state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
webrender_image: webrender_image,
|
webrender_image: webrender_image,
|
||||||
image_data: image_data.map(Arc::new),
|
image_data: image_data.map(Arc::new),
|
||||||
stretch_size: Size2D::new(image_size.width, image_size.height),
|
stretch_size: Size2D::new(image_size.width, image_size.height),
|
||||||
image_rendering: style.get_inheritedbox().image_rendering.clone(),
|
image_rendering: style.get_inheritedbox().image_rendering.clone(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,8 +362,11 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
if let Some(url) = background {
|
if let Some(url) = background {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
PropertyDeclaration::BackgroundImage(DeclaredValue::Value(
|
PropertyDeclaration::BackgroundImage(DeclaredValue::Value(
|
||||||
background_image::SpecifiedValue(Some(
|
background_image::SpecifiedValue(vec![
|
||||||
specified::Image::Url(url, specified::UrlExtraData { })))))));
|
background_image::single_value::SpecifiedValue(Some(
|
||||||
|
specified::Image::Url(url, specified::UrlExtraData { })
|
||||||
|
))
|
||||||
|
])))));
|
||||||
}
|
}
|
||||||
|
|
||||||
let color = if let Some(this) = self.downcast::<HTMLFontElement>() {
|
let color = if let Some(this) = self.downcast::<HTMLFontElement>() {
|
||||||
|
|
|
@ -69,10 +69,10 @@
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
}
|
}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use super::single_value;
|
pub use super::single_value::computed_value as single_value;
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct T(pub Vec<single_value::computed_value::T>);
|
pub struct T(pub Vec<single_value::T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for computed_value::T {
|
impl ToCss for computed_value::T {
|
||||||
|
|
|
@ -10,7 +10,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
|
||||||
"::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */",
|
"::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */",
|
||||||
animatable=True)}
|
animatable=True)}
|
||||||
|
|
||||||
<%helpers:vector_longhand gecko_only="True" name="background-image" animatable="False">
|
<%helpers:vector_longhand name="background-image" animatable="False">
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use values::specified::Image;
|
use values::specified::Image;
|
||||||
|
@ -79,7 +79,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
|
||||||
}
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
|
||||||
<%helpers:vector_longhand name="background-position" gecko_only="True" animatable="True">
|
<%helpers:vector_longhand name="background-position" animatable="True">
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use values::LocalToCss;
|
use values::LocalToCss;
|
||||||
|
@ -121,25 +121,21 @@ ${helpers.predefined_type("background-color", "CSSColor",
|
||||||
${helpers.single_keyword("background-repeat",
|
${helpers.single_keyword("background-repeat",
|
||||||
"repeat repeat-x repeat-y no-repeat",
|
"repeat repeat-x repeat-y no-repeat",
|
||||||
vector=True,
|
vector=True,
|
||||||
gecko_only=True,
|
|
||||||
animatable=False)}
|
animatable=False)}
|
||||||
|
|
||||||
${helpers.single_keyword("background-attachment",
|
${helpers.single_keyword("background-attachment",
|
||||||
"scroll fixed" + (" local" if product == "gecko" else ""),
|
"scroll fixed" + (" local" if product == "gecko" else ""),
|
||||||
vector=True,
|
vector=True,
|
||||||
gecko_only=True,
|
|
||||||
animatable=False)}
|
animatable=False)}
|
||||||
|
|
||||||
${helpers.single_keyword("background-clip",
|
${helpers.single_keyword("background-clip",
|
||||||
"border-box padding-box content-box",
|
"border-box padding-box content-box",
|
||||||
vector=True,
|
vector=True,
|
||||||
gecko_only=True,
|
|
||||||
animatable=False)}
|
animatable=False)}
|
||||||
|
|
||||||
${helpers.single_keyword("background-origin",
|
${helpers.single_keyword("background-origin",
|
||||||
"padding-box border-box content-box",
|
"padding-box border-box content-box",
|
||||||
vector=True,
|
vector=True,
|
||||||
gecko_only=True,
|
|
||||||
animatable=False)}
|
animatable=False)}
|
||||||
|
|
||||||
<%helpers:vector_longhand name="background-size" animatable="True">
|
<%helpers:vector_longhand name="background-size" animatable="True">
|
||||||
|
|
|
@ -23,14 +23,14 @@
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if background_color.is_none() {
|
if let Ok(value) = input.try(|input| background_color::parse(context, input)) {
|
||||||
if let Ok(value) = input.try(|input| background_color::parse(context, input)) {
|
if background_color.is_none() {
|
||||||
background_color = Some(value);
|
background_color = Some(value);
|
||||||
continue
|
continue
|
||||||
|
} else {
|
||||||
|
// color can only be the last element
|
||||||
|
return Err(())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// color can only be the last element
|
|
||||||
return Err(())
|
|
||||||
}
|
}
|
||||||
if position.is_none() {
|
if position.is_none() {
|
||||||
if let Ok(value) = input.try(|input| background_position::single_value::parse(context, input)) {
|
if let Ok(value) = input.try(|input| background_position::single_value::parse(context, input)) {
|
||||||
|
@ -118,6 +118,11 @@
|
||||||
.unwrap_or(0));
|
.unwrap_or(0));
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
|
// There should be at least one declared value
|
||||||
|
if len == 0 {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
|
||||||
let iter = repeat(None).take(len - 1).chain(once(Some(self.background_color)))
|
let iter = repeat(None).take(len - 1).chain(once(Some(self.background_color)))
|
||||||
% for name in "image position repeat size attachment origin clip".split():
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
.zip(extract_value(self.background_${name}).into_iter()
|
.zip(extract_value(self.background_${name}).into_iter()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue