mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Add background-repeat
This commit is contained in:
parent
6e78cdf0ed
commit
7c1f2335d4
2 changed files with 71 additions and 25 deletions
|
@ -319,6 +319,8 @@ impl<'a> BuilderForBoxFragment<'a> {
|
||||||
use style::computed_values::background_clip::single_value::T as Clip;
|
use style::computed_values::background_clip::single_value::T as Clip;
|
||||||
use style::computed_values::background_origin::single_value::T as Origin;
|
use style::computed_values::background_origin::single_value::T as Origin;
|
||||||
use style::values::computed::background::BackgroundSize as Size;
|
use style::values::computed::background::BackgroundSize as Size;
|
||||||
|
use style::values::specified::background::BackgroundRepeat as RepeatXY;
|
||||||
|
use style::values::specified::background::BackgroundRepeatKeyword as Repeat;
|
||||||
|
|
||||||
fn get_cyclic<T>(values: &[T], index: usize) -> &T {
|
fn get_cyclic<T>(values: &[T], index: usize) -> &T {
|
||||||
&values[index % values.len()]
|
&values[index % values.len()]
|
||||||
|
@ -361,7 +363,7 @@ impl<'a> BuilderForBoxFragment<'a> {
|
||||||
}
|
}
|
||||||
tile_size
|
tile_size
|
||||||
};
|
};
|
||||||
let tile_size = match get_cyclic(&b.background_size.0, index) {
|
let mut tile_size = match get_cyclic(&b.background_size.0, index) {
|
||||||
Size::Contain => size_contain_or_cover(ContainOrCover::Contain),
|
Size::Contain => size_contain_or_cover(ContainOrCover::Contain),
|
||||||
Size::Cover => size_contain_or_cover(ContainOrCover::Cover),
|
Size::Cover => size_contain_or_cover(ContainOrCover::Cover),
|
||||||
Size::ExplicitSize { width, height } => {
|
Size::ExplicitSize { width, height } => {
|
||||||
|
@ -413,30 +415,74 @@ impl<'a> BuilderForBoxFragment<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: background-repeat
|
/// Abstract over the horizontal or vertical dimension
|
||||||
let tile_spacing = units::LayoutSize::zero();
|
/// Returns `(bounds_origin, bounds_size)`
|
||||||
let tile_stride = tile_size + tile_spacing;
|
/// Coordinates (0, 0) for the purpose of this function are the positioning area’s origin.
|
||||||
|
fn layout_1d(
|
||||||
|
tile_size: &mut f32,
|
||||||
|
tile_spacing: &mut f32,
|
||||||
|
mut repeat: Repeat,
|
||||||
|
position: &LengthPercentage,
|
||||||
|
clipping_area_origin: f32,
|
||||||
|
clipping_area_size: f32,
|
||||||
|
positioning_area_size: f32,
|
||||||
|
) -> (f32, f32) {
|
||||||
|
// https://drafts.csswg.org/css-backgrounds/#background-repeat
|
||||||
|
if let Repeat::Round = repeat {
|
||||||
|
*tile_size = positioning_area_size / (positioning_area_size / *tile_size).round();
|
||||||
|
}
|
||||||
|
// https://drafts.csswg.org/css-backgrounds/#background-position
|
||||||
|
let mut position = position
|
||||||
|
.percentage_relative_to(Length::new(positioning_area_size - *tile_size))
|
||||||
|
.px();
|
||||||
|
// https://drafts.csswg.org/css-backgrounds/#background-repeat
|
||||||
|
if let Repeat::Space = repeat {
|
||||||
|
let tile_count = (positioning_area_size / *tile_size).floor();
|
||||||
|
if tile_count >= 2.0 {
|
||||||
|
position = 0.0;
|
||||||
|
let total_space = positioning_area_size - *tile_size * tile_count;
|
||||||
|
let spaces_count = tile_count - 1.0;
|
||||||
|
*tile_spacing = total_space / spaces_count;
|
||||||
|
} else {
|
||||||
|
repeat = Repeat::NoRepeat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match repeat {
|
||||||
|
Repeat::NoRepeat => (position, *tile_size),
|
||||||
|
Repeat::Repeat | Repeat::Round | Repeat::Space => {
|
||||||
|
let tile_stride = *tile_size + *tile_spacing;
|
||||||
|
let offset = position - clipping_area_origin;
|
||||||
|
let bounds_origin = position - tile_stride * (offset / tile_stride).ceil();
|
||||||
|
let bounds_size = clipping_area_size - bounds_origin - clipping_area_origin;
|
||||||
|
(bounds_origin, bounds_size)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-backgrounds/#background-position
|
let mut tile_spacing = units::LayoutSize::zero();
|
||||||
let position_percentages = positioning_area.size - tile_size;
|
let RepeatXY(repeat_x, repeat_y) = *get_cyclic(&b.background_repeat.0, index);
|
||||||
let positioned_tile_origin = positioning_area.origin +
|
let (bounds_origin_x, bounds_width) = layout_1d(
|
||||||
units::LayoutSize::new(
|
&mut tile_size.width,
|
||||||
get_cyclic(&b.background_position_x.0, index)
|
&mut tile_spacing.width,
|
||||||
.percentage_relative_to(Length::new(position_percentages.width))
|
repeat_x,
|
||||||
.px(),
|
get_cyclic(&b.background_position_x.0, index),
|
||||||
get_cyclic(&b.background_position_y.0, index)
|
clipping_area.origin.x - positioning_area.origin.x,
|
||||||
.percentage_relative_to(Length::new(position_percentages.height))
|
clipping_area.size.width,
|
||||||
.px(),
|
positioning_area.size.width,
|
||||||
);
|
);
|
||||||
|
let (bounds_origin_y, bounds_height) = layout_1d(
|
||||||
let offset = positioned_tile_origin - clipping_area.origin;
|
&mut tile_size.height,
|
||||||
let first_tile_origin = positioned_tile_origin -
|
&mut tile_spacing.height,
|
||||||
Vector2D::new(
|
repeat_y,
|
||||||
tile_stride.width * (offset.x / tile_stride.width).ceil(),
|
get_cyclic(&b.background_position_y.0, index),
|
||||||
tile_stride.height * (offset.y / tile_stride.height).ceil(),
|
clipping_area.origin.y - positioning_area.origin.y,
|
||||||
);
|
clipping_area.size.height,
|
||||||
|
positioning_area.size.height,
|
||||||
let bounds = units::LayoutRect::from_points(&[first_tile_origin, clipping_area.max()]);
|
);
|
||||||
|
let bounds = units::LayoutRect::new(
|
||||||
|
positioning_area.origin + Vector2D::new(bounds_origin_x, bounds_origin_y),
|
||||||
|
Size2D::new(bounds_width, bounds_height),
|
||||||
|
);
|
||||||
|
|
||||||
// The 'backgound-clip' property maps directly to `clip_rect` in `CommonItemProperties`:
|
// The 'backgound-clip' property maps directly to `clip_rect` in `CommonItemProperties`:
|
||||||
let mut common = builder.common_properties(*clipping_area);
|
let mut common = builder.common_properties(*clipping_area);
|
||||||
|
|
|
@ -49,7 +49,7 @@ ${helpers.predefined_type(
|
||||||
"background-repeat",
|
"background-repeat",
|
||||||
"BackgroundRepeat",
|
"BackgroundRepeat",
|
||||||
"computed::BackgroundRepeat::repeat()",
|
"computed::BackgroundRepeat::repeat()",
|
||||||
engines="gecko servo-2013",
|
engines="gecko servo-2013 servo-2020",
|
||||||
initial_specified_value="specified::BackgroundRepeat::repeat()",
|
initial_specified_value="specified::BackgroundRepeat::repeat()",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
vector=True,
|
vector=True,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue