mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Use inline-start/inline-end instead of left/right terminology for floats (#34608)
It was a bit confusing that e.g. a float with `FloatSide::InlineStart` would set `FloatBand::left`, or that `PlacementAmongFloats` would compute `max_inline_start` from the various `FloatBand::left`. So now all the float logic will consistently use logical terminoligy. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
0e9746fbbe
commit
681d7dca9b
2 changed files with 82 additions and 79 deletions
|
@ -176,11 +176,11 @@ impl<'a> PlacementAmongFloats<'a> {
|
||||||
let mut max_inline_start = self.min_inline_start;
|
let mut max_inline_start = self.min_inline_start;
|
||||||
let mut min_inline_end = self.max_inline_end;
|
let mut min_inline_end = self.max_inline_end;
|
||||||
for band in self.current_bands.iter() {
|
for band in self.current_bands.iter() {
|
||||||
if let Some(left) = band.left {
|
if let Some(inline_start) = band.inline_start {
|
||||||
max_inline_start.max_assign(left);
|
max_inline_start.max_assign(inline_start);
|
||||||
}
|
}
|
||||||
if let Some(right) = band.right {
|
if let Some(inline_end) = band.inline_end {
|
||||||
min_inline_end.min_assign(right);
|
min_inline_end.min_assign(inline_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(max_inline_start, min_inline_end)
|
(max_inline_start, min_inline_end)
|
||||||
|
@ -352,13 +352,13 @@ impl FloatContext {
|
||||||
let mut bands = FloatBandTree::new();
|
let mut bands = FloatBandTree::new();
|
||||||
bands = bands.insert(FloatBand {
|
bands = bands.insert(FloatBand {
|
||||||
top: MIN_AU,
|
top: MIN_AU,
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
bands = bands.insert(FloatBand {
|
bands = bands.insert(FloatBand {
|
||||||
top: MAX_AU,
|
top: MAX_AU,
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
FloatContext {
|
FloatContext {
|
||||||
bands,
|
bands,
|
||||||
|
@ -414,22 +414,22 @@ impl FloatContext {
|
||||||
// The object fits perfectly here. Place it.
|
// The object fits perfectly here. Place it.
|
||||||
match object.side {
|
match object.side {
|
||||||
FloatSide::InlineStart => {
|
FloatSide::InlineStart => {
|
||||||
let left_object_edge = match first_band.left {
|
let inline_start_object_edge = match first_band.inline_start {
|
||||||
Some(band_left) => band_left.max(self.containing_block_info.inline_start),
|
Some(inline_start) => inline_start.max(self.containing_block_info.inline_start),
|
||||||
None => self.containing_block_info.inline_start,
|
None => self.containing_block_info.inline_start,
|
||||||
};
|
};
|
||||||
LogicalVec2 {
|
LogicalVec2 {
|
||||||
inline: left_object_edge,
|
inline: inline_start_object_edge,
|
||||||
block: first_band.top.max(ceiling),
|
block: first_band.top.max(ceiling),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FloatSide::InlineEnd => {
|
FloatSide::InlineEnd => {
|
||||||
let right_object_edge = match first_band.right {
|
let inline_end_object_edge = match first_band.inline_end {
|
||||||
Some(band_right) => band_right.min(self.containing_block_info.inline_end),
|
Some(inline_end) => inline_end.min(self.containing_block_info.inline_end),
|
||||||
None => self.containing_block_info.inline_end,
|
None => self.containing_block_info.inline_end,
|
||||||
};
|
};
|
||||||
LogicalVec2 {
|
LogicalVec2 {
|
||||||
inline: right_object_edge - object.size.inline,
|
inline: inline_end_object_edge - object.size.inline,
|
||||||
block: first_band.top.max(ceiling),
|
block: first_band.top.max(ceiling),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -524,18 +524,18 @@ impl Clear {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information needed to place an object so that it doesn't collide with existing floats.
|
/// Information needed to place a float so that it doesn't collide with existing floats.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PlacementInfo {
|
pub struct PlacementInfo {
|
||||||
/// The *margin* box size of the object.
|
/// The *margin* box size of the float.
|
||||||
pub size: LogicalVec2<Au>,
|
pub size: LogicalVec2<Au>,
|
||||||
/// Whether the object is (logically) aligned to the left or right.
|
/// Which side of the containing block the float is aligned to.
|
||||||
pub side: FloatSide,
|
pub side: FloatSide,
|
||||||
/// Which side or sides to clear floats on.
|
/// Which side or sides to clear existing floats on.
|
||||||
pub clear: Clear,
|
pub clear: Clear,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the float is left or right.
|
/// Whether the float is aligned to the inline-start or inline-end side of its containing block.
|
||||||
///
|
///
|
||||||
/// See CSS 2.1 § 9.5.1: <https://www.w3.org/TR/CSS2/visuren.html#float-position>
|
/// See CSS 2.1 § 9.5.1: <https://www.w3.org/TR/CSS2/visuren.html#float-position>
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -544,22 +544,22 @@ pub enum FloatSide {
|
||||||
InlineEnd,
|
InlineEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal data structure that describes a nonoverlapping vertical region in which floats may be
|
/// Internal data structure that describes a nonoverlapping vertical region in which floats may be placed.
|
||||||
/// placed. Floats must go between "left edge + `left`" and "right edge - `right`".
|
/// Floats must go between "inline-start edge + `inline_start`" and "inline-end edge - `inline_end`".
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct FloatBand {
|
pub struct FloatBand {
|
||||||
/// The logical vertical position of the top of this band.
|
/// The logical vertical position of the top of this band.
|
||||||
pub top: Au,
|
pub top: Au,
|
||||||
/// The distance from the left edge of the block formatting context to the first legal
|
/// The distance from the inline-start edge of the block formatting context to the first legal
|
||||||
/// (logically) horizontal position where floats may be placed. If `None`, there are no floats
|
/// (logically) horizontal position where floats may be placed. If `None`, there are no floats
|
||||||
/// to the left; distinguishing between the cases of "a zero-width float is present" and "no
|
/// to the inline-start; distinguishing between the cases of "a zero-width float is present" and
|
||||||
/// floats at all are present" is necessary to, for example, clear past zero-width floats.
|
/// "no floats at all are present" is necessary to, for example, clear past zero-width floats.
|
||||||
pub left: Option<Au>,
|
pub inline_start: Option<Au>,
|
||||||
/// The distance from the *left* edge of the block formatting context to the first legal
|
/// The distance from the *inline-start* edge of the block formatting context to the last legal
|
||||||
/// (logically) horizontal position where floats may be placed. If `None`, there are no floats
|
/// (logically) horizontal position where floats may be placed. If `None`, there are no floats
|
||||||
/// to the right; distinguishing between the cases of "a zero-width float is present" and "no
|
/// to the inline-end; distinguishing between the cases of "a zero-width float is present" and
|
||||||
/// floats at all are present" is necessary to, for example, clear past zero-width floats.
|
/// "no floats at all are present" is necessary to, for example, clear past zero-width floats.
|
||||||
pub right: Option<Au>,
|
pub inline_end: Option<Au>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatSide {
|
impl FloatSide {
|
||||||
|
@ -584,45 +584,48 @@ impl FloatBand {
|
||||||
fn object_fits(&self, object: &PlacementInfo, walls: &ContainingBlockPositionInfo) -> bool {
|
fn object_fits(&self, object: &PlacementInfo, walls: &ContainingBlockPositionInfo) -> bool {
|
||||||
match object.side {
|
match object.side {
|
||||||
FloatSide::InlineStart => {
|
FloatSide::InlineStart => {
|
||||||
// Compute a candidate left position for the object.
|
// Compute a candidate inline-start position for the object.
|
||||||
let candidate_left = match self.left {
|
let candidate_inline_start = match self.inline_start {
|
||||||
None => walls.inline_start,
|
None => walls.inline_start,
|
||||||
Some(left) => left.max(walls.inline_start),
|
Some(inline_start) => inline_start.max(walls.inline_start),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If this band has an existing left float in it, then make sure that the object
|
// If this band has an existing inline-start float in it, then make sure that the object
|
||||||
// doesn't stick out past the right edge (rule 7).
|
// doesn't stick out past the inline-end edge (rule 7).
|
||||||
if self.left.is_some() && candidate_left + object.size.inline > walls.inline_end {
|
if self.inline_start.is_some() &&
|
||||||
return false;
|
candidate_inline_start + object.size.inline > walls.inline_end
|
||||||
}
|
|
||||||
|
|
||||||
// If this band has an existing right float in it, make sure we don't collide with
|
|
||||||
// it (rule 3).
|
|
||||||
match self.right {
|
|
||||||
None => true,
|
|
||||||
Some(right) => object.size.inline <= right - candidate_left,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
FloatSide::InlineEnd => {
|
|
||||||
// Compute a candidate right position for the object.
|
|
||||||
let candidate_right = match self.right {
|
|
||||||
None => walls.inline_end,
|
|
||||||
Some(right) => right.min(walls.inline_end),
|
|
||||||
};
|
|
||||||
|
|
||||||
// If this band has an existing right float in it, then make sure that the new
|
|
||||||
// object doesn't stick out past the left edge (rule 7).
|
|
||||||
if self.right.is_some() && candidate_right - object.size.inline < walls.inline_start
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this band has an existing left float in it, make sure we don't collide with
|
// If this band has an existing inline-end float in it, make sure we don't collide with
|
||||||
// it (rule 3).
|
// it (rule 3).
|
||||||
match self.left {
|
match self.inline_end {
|
||||||
None => true,
|
None => true,
|
||||||
Some(left) => object.size.inline <= candidate_right - left,
|
Some(inline_end) => object.size.inline <= inline_end - candidate_inline_start,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
FloatSide::InlineEnd => {
|
||||||
|
// Compute a candidate inline-end position for the object.
|
||||||
|
let candidate_inline_end = match self.inline_end {
|
||||||
|
None => walls.inline_end,
|
||||||
|
Some(inline_end) => inline_end.min(walls.inline_end),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this band has an existing inline-end float in it, then make sure that the new
|
||||||
|
// object doesn't stick out past the inline-start edge (rule 7).
|
||||||
|
if self.inline_end.is_some() &&
|
||||||
|
candidate_inline_end - object.size.inline < walls.inline_start
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this band has an existing inline-start float in it, make sure we don't collide with
|
||||||
|
// it (rule 3).
|
||||||
|
match self.inline_start {
|
||||||
|
None => true,
|
||||||
|
Some(inline_start) => object.size.inline <= candidate_inline_end - inline_start,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -729,13 +732,13 @@ impl FloatBandNode {
|
||||||
if self.band.top >= range.start && self.band.top < range.end {
|
if self.band.top >= range.start && self.band.top < range.end {
|
||||||
match side {
|
match side {
|
||||||
FloatSide::InlineStart => {
|
FloatSide::InlineStart => {
|
||||||
new_band.left = match new_band.left {
|
new_band.inline_start = match new_band.inline_start {
|
||||||
Some(old_value) => Some(std::cmp::max(old_value, new_value)),
|
Some(old_value) => Some(std::cmp::max(old_value, new_value)),
|
||||||
None => Some(new_value),
|
None => Some(new_value),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
FloatSide::InlineEnd => {
|
FloatSide::InlineEnd => {
|
||||||
new_band.right = match new_band.right {
|
new_band.inline_end = match new_band.inline_end {
|
||||||
Some(old_value) => Some(std::cmp::min(old_value, new_value)),
|
Some(old_value) => Some(std::cmp::min(old_value, new_value)),
|
||||||
None => Some(new_value),
|
None => Some(new_value),
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,13 +56,13 @@ struct FloatBandWrapper(FloatBand);
|
||||||
impl Arbitrary for FloatBandWrapper {
|
impl Arbitrary for FloatBandWrapper {
|
||||||
fn arbitrary(generator: &mut Gen) -> FloatBandWrapper {
|
fn arbitrary(generator: &mut Gen) -> FloatBandWrapper {
|
||||||
let top: u32 = u32::arbitrary(generator);
|
let top: u32 = u32::arbitrary(generator);
|
||||||
let left: Option<u32> = Some(u32::arbitrary(generator));
|
let inline_start: Option<u32> = Some(u32::arbitrary(generator));
|
||||||
let right: Option<u32> = Some(u32::arbitrary(generator));
|
let inline_end: Option<u32> = Some(u32::arbitrary(generator));
|
||||||
|
|
||||||
FloatBandWrapper(FloatBand {
|
FloatBandWrapper(FloatBand {
|
||||||
top: Au::from_f32_px(top as f32),
|
top: Au::from_f32_px(top as f32),
|
||||||
left: left.map(|value| Au::from_f32_px(value as f32)),
|
inline_start: inline_start.map(|value| Au::from_f32_px(value as f32)),
|
||||||
right: right.map(|value| Au::from_f32_px(value as f32)),
|
inline_end: inline_end.map(|value| Au::from_f32_px(value as f32)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,8 +158,8 @@ fn check_tree_find(tree: &FloatBandTree, block_position: Au, sorted_bands: &[Flo
|
||||||
1;
|
1;
|
||||||
let reference_band = &sorted_bands[reference_band_index];
|
let reference_band = &sorted_bands[reference_band_index];
|
||||||
assert_eq!(found_band.top, reference_band.top);
|
assert_eq!(found_band.top, reference_band.top);
|
||||||
assert_eq!(found_band.left, reference_band.left);
|
assert_eq!(found_band.inline_start, reference_band.inline_start);
|
||||||
assert_eq!(found_band.right, reference_band.right);
|
assert_eq!(found_band.inline_end, reference_band.inline_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_tree_find_next(tree: &FloatBandTree, block_position: Au, sorted_bands: &[FloatBand]) {
|
fn check_tree_find_next(tree: &FloatBandTree, block_position: Au, sorted_bands: &[FloatBand]) {
|
||||||
|
@ -172,8 +172,8 @@ fn check_tree_find_next(tree: &FloatBandTree, block_position: Au, sorted_bands:
|
||||||
.expect("Couldn't find the reference band!");
|
.expect("Couldn't find the reference band!");
|
||||||
let reference_band = &sorted_bands[reference_band_index];
|
let reference_band = &sorted_bands[reference_band_index];
|
||||||
assert_eq!(found_band.top, reference_band.top);
|
assert_eq!(found_band.top, reference_band.top);
|
||||||
assert_eq!(found_band.left, reference_band.left);
|
assert_eq!(found_band.inline_start, reference_band.inline_start);
|
||||||
assert_eq!(found_band.right, reference_band.right);
|
assert_eq!(found_band.inline_end, reference_band.inline_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_node_range_setting(
|
fn check_node_range_setting(
|
||||||
|
@ -184,8 +184,8 @@ fn check_node_range_setting(
|
||||||
) {
|
) {
|
||||||
if node.band.top >= block_range.start && node.band.top < block_range.end {
|
if node.band.top >= block_range.start && node.band.top < block_range.end {
|
||||||
match side {
|
match side {
|
||||||
FloatSide::InlineStart => assert!(node.band.left.unwrap() >= value),
|
FloatSide::InlineStart => assert!(node.band.inline_start.unwrap() >= value),
|
||||||
FloatSide::InlineEnd => assert!(node.band.right.unwrap() <= value),
|
FloatSide::InlineEnd => assert!(node.band.inline_end.unwrap() <= value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,13 +247,13 @@ fn test_tree_find() {
|
||||||
let mut bands: Vec<FloatBand> = bands.into_iter().map(|band| band.0).collect();
|
let mut bands: Vec<FloatBand> = bands.into_iter().map(|band| band.0).collect();
|
||||||
bands.push(FloatBand {
|
bands.push(FloatBand {
|
||||||
top: Au::zero(),
|
top: Au::zero(),
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
bands.push(FloatBand {
|
bands.push(FloatBand {
|
||||||
top: Au::from_f32_px(INFINITY),
|
top: Au::from_f32_px(INFINITY),
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
let mut tree = FloatBandTree::new();
|
let mut tree = FloatBandTree::new();
|
||||||
for band in &bands {
|
for band in &bands {
|
||||||
|
@ -275,13 +275,13 @@ fn test_tree_find_next() {
|
||||||
let mut bands: Vec<FloatBand> = bands.into_iter().map(|band| band.0).collect();
|
let mut bands: Vec<FloatBand> = bands.into_iter().map(|band| band.0).collect();
|
||||||
bands.push(FloatBand {
|
bands.push(FloatBand {
|
||||||
top: Au::zero(),
|
top: Au::zero(),
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
bands.push(FloatBand {
|
bands.push(FloatBand {
|
||||||
top: Au::from_f32_px(INFINITY),
|
top: Au::from_f32_px(INFINITY),
|
||||||
left: None,
|
inline_start: None,
|
||||||
right: None,
|
inline_end: None,
|
||||||
});
|
});
|
||||||
bands.sort_by(|a, b| a.top.partial_cmp(&b.top).unwrap());
|
bands.sort_by(|a, b| a.top.partial_cmp(&b.top).unwrap());
|
||||||
bands.dedup_by(|a, b| a.top == b.top);
|
bands.dedup_by(|a, b| a.top == b.top);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue