Convert layout to use Gecko's alignment style representation (#32790)

Signed-off-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: Nico Burns <nico@nicoburns.com>
This commit is contained in:
Martin Robinson 2024-07-17 16:18:55 +02:00 committed by GitHub
parent a0d2b36ad8
commit 882a855b8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 177 additions and 6482 deletions

View file

@ -18,6 +18,7 @@ use style::properties::ComputedValues;
use style::values::computed::length::Size;
use style::values::computed::Length;
use style::values::generics::flex::GenericFlexBasis as FlexBasis;
use style::values::specified::align::AlignFlags;
use style::Zero;
use super::geom::{
@ -136,14 +137,12 @@ impl FlexContext<'_> {
}
fn align_for(&self, align_self: &AlignSelf) -> AlignItems {
match align_self {
AlignSelf::Auto => self.align_items,
AlignSelf::Stretch => AlignItems::Stretch,
AlignSelf::FlexStart => AlignItems::FlexStart,
AlignSelf::FlexEnd => AlignItems::FlexEnd,
AlignSelf::Center => AlignItems::Center,
AlignSelf::Baseline => AlignItems::Baseline,
}
let value = align_self.0 .0.value();
let mapped_value = match value {
AlignFlags::AUTO | AlignFlags::NORMAL => self.align_items.0,
_ => value,
};
AlignItems(mapped_value)
}
}
@ -225,8 +224,12 @@ impl FlexContainer {
FlexWrap::Nowrap | FlexWrap::Wrap => false,
FlexWrap::WrapReverse => true,
};
let align_content = container_style.clone_align_content();
let align_items = container_style.clone_align_items();
let align_items = AlignItems(match container_style.clone_align_items().0 {
AlignFlags::AUTO | AlignFlags::NORMAL => AlignFlags::STRETCH,
align => align,
});
let justify_content = container_style.clone_justify_content();
let mut flex_context = FlexContext {
@ -310,10 +313,12 @@ impl FlexContainer {
//
// In addition to the spec at https://www.w3.org/TR/css-align-3/ this implementation follows
// the resolution of https://github.com/w3c/csswg-drafts/issues/10154
let resolved_align_content: AlignContent = {
let resolved_align_content: AlignFlags = {
let align_content_style = flex_context.align_content.0.primary();
// Inital values from the style system
let mut resolved_align_content = flex_context.align_content;
let mut is_safe = false; // FIXME: retrieve from style system
let mut resolved_align_content = align_content_style.value();
let mut is_safe = align_content_style.flags() == AlignFlags::SAFE;
// Fallback occurs in two cases:
@ -321,17 +326,17 @@ impl FlexContainer {
// https://www.w3.org/TR/css-align-3/#distribution-values
if line_count <= 1 || free_space <= Au::zero() {
(resolved_align_content, is_safe) = match resolved_align_content {
AlignContent::Stretch => (AlignContent::FlexStart, true),
AlignContent::SpaceBetween => (AlignContent::FlexStart, true),
AlignContent::SpaceAround => (AlignContent::Center, true),
AlignContent::SpaceEvenly => (AlignContent::Center, true),
AlignFlags::STRETCH => (AlignFlags::FLEX_START, true),
AlignFlags::SPACE_BETWEEN => (AlignFlags::FLEX_START, true),
AlignFlags::SPACE_AROUND => (AlignFlags::CENTER, true),
AlignFlags::SPACE_EVENLY => (AlignFlags::CENTER, true),
_ => (resolved_align_content, is_safe),
}
};
// 2. If free space is negative the "safe" alignment variants all fallback to Start alignment
if free_space <= Au::zero() && is_safe {
resolved_align_content = AlignContent::Start;
resolved_align_content = AlignFlags::START;
}
resolved_align_content
@ -339,40 +344,46 @@ impl FlexContainer {
// Implement "unsafe" alignment. "safe" alignment is handled by the fallback process above.
cross_start_position_cursor = match resolved_align_content {
AlignContent::Start => Au::zero(),
AlignContent::FlexStart => {
AlignFlags::START => Au::zero(),
AlignFlags::FLEX_START => {
if layout_is_flex_reversed {
free_space
} else {
Au::zero()
}
},
AlignContent::End => free_space,
AlignContent::FlexEnd => {
AlignFlags::END => free_space,
AlignFlags::FLEX_END => {
if layout_is_flex_reversed {
Au::zero()
} else {
free_space
}
},
AlignContent::Center => free_space / 2,
AlignContent::Stretch => Au::zero(),
AlignContent::SpaceBetween => Au::zero(),
AlignContent::SpaceAround => free_space / line_count as i32 / 2,
AlignContent::SpaceEvenly => free_space / (line_count + 1) as i32,
AlignFlags::CENTER => free_space / 2,
AlignFlags::STRETCH => Au::zero(),
AlignFlags::SPACE_BETWEEN => Au::zero(),
AlignFlags::SPACE_AROUND => free_space / line_count as i32 / 2,
AlignFlags::SPACE_EVENLY => free_space / (line_count + 1) as i32,
// TODO: Implement all alignments. Note: not all alignment values are valid for content distribution
_ => Au::zero(),
};
// TODO: Implement gap property
line_interval = /*gap + */ match resolved_align_content {
AlignContent::Start => Au::zero(),
AlignContent::FlexStart => Au::zero(),
AlignContent::End => Au::zero(),
AlignContent::FlexEnd => Au::zero(),
AlignContent::Center => Au::zero(),
AlignContent::Stretch => Au::zero(),
AlignContent::SpaceBetween => free_space / (line_count - 1) as i32,
AlignContent::SpaceAround => free_space / line_count as i32,
AlignContent::SpaceEvenly => free_space / (line_count + 1) as i32,
AlignFlags::START => Au::zero(),
AlignFlags::FLEX_START => Au::zero(),
AlignFlags::END => Au::zero(),
AlignFlags::FLEX_END => Au::zero(),
AlignFlags::CENTER => Au::zero(),
AlignFlags::STRETCH => Au::zero(),
AlignFlags::SPACE_BETWEEN => free_space / (line_count - 1) as i32,
AlignFlags::SPACE_AROUND => free_space / line_count as i32,
AlignFlags::SPACE_EVENLY => free_space / (line_count + 1) as i32,
// TODO: Implement all alignments. Note: not all alignment values are valid for content distribution
_ => Au::zero(),
};
};
@ -819,7 +830,7 @@ impl FlexLine<'_> {
.zip(item_layout_results)
.zip(&item_used_main_sizes)
.map(|((item, mut item_result), &used_main_size)| {
let has_stretch = item.align_self == AlignItems::Stretch;
let has_stretch = item.align_self.0.value() == AlignFlags::STRETCH;
let cross_size = if has_stretch &&
item.content_box_size.cross.is_auto() &&
!(item.margin.cross_start.is_auto() || item.margin.cross_end.is_auto())
@ -857,10 +868,12 @@ impl FlexLine<'_> {
//
// In addition to the spec at https://www.w3.org/TR/css-align-3/ this implementation follows
// the resolution of https://github.com/w3c/csswg-drafts/issues/10154
let resolved_justify_content: JustifyContent = {
let resolved_justify_content: AlignFlags = {
let justify_content_style = flex_context.justify_content.0.primary();
// Inital values from the style system
let mut resolved_justify_content = flex_context.justify_content;
let mut is_safe = false; // FIXME: retrieve from style system
let mut resolved_justify_content = justify_content_style.value();
let mut is_safe = justify_content_style.flags() == AlignFlags::SAFE;
// Fallback occurs in two cases:
@ -868,17 +881,17 @@ impl FlexLine<'_> {
// https://www.w3.org/TR/css-align-3/#distribution-values
if item_count <= 1 || free_space <= Au::zero() {
(resolved_justify_content, is_safe) = match resolved_justify_content {
JustifyContent::Stretch => (JustifyContent::FlexStart, true),
JustifyContent::SpaceBetween => (JustifyContent::FlexStart, true),
JustifyContent::SpaceAround => (JustifyContent::Center, true),
JustifyContent::SpaceEvenly => (JustifyContent::Center, true),
AlignFlags::STRETCH => (AlignFlags::FLEX_START, true),
AlignFlags::SPACE_BETWEEN => (AlignFlags::FLEX_START, true),
AlignFlags::SPACE_AROUND => (AlignFlags::CENTER, true),
AlignFlags::SPACE_EVENLY => (AlignFlags::CENTER, true),
_ => (resolved_justify_content, is_safe),
}
};
// 2. If free space is negative the "safe" alignment variants all fallback to Start alignment
if free_space <= Au::zero() && is_safe {
resolved_justify_content = JustifyContent::Start;
resolved_justify_content = AlignFlags::START;
}
resolved_justify_content
@ -886,40 +899,46 @@ impl FlexLine<'_> {
// Implement "unsafe" alignment. "safe" alignment is handled by the fallback process above.
let main_start_position = match resolved_justify_content {
JustifyContent::Start => Au::zero(),
JustifyContent::FlexStart => {
AlignFlags::START => Au::zero(),
AlignFlags::FLEX_START => {
if layout_is_flex_reversed {
free_space
} else {
Au::zero()
}
},
JustifyContent::End => free_space,
JustifyContent::FlexEnd => {
AlignFlags::END => free_space,
AlignFlags::FLEX_END => {
if layout_is_flex_reversed {
Au::zero()
} else {
free_space
}
},
JustifyContent::Center => free_space / 2,
JustifyContent::Stretch => Au::zero(),
JustifyContent::SpaceBetween => Au::zero(),
JustifyContent::SpaceAround => (free_space / item_count as i32) / 2,
JustifyContent::SpaceEvenly => free_space / (item_count + 1) as i32,
AlignFlags::CENTER => free_space / 2,
AlignFlags::STRETCH => Au::zero(),
AlignFlags::SPACE_BETWEEN => Au::zero(),
AlignFlags::SPACE_AROUND => (free_space / item_count as i32) / 2,
AlignFlags::SPACE_EVENLY => free_space / (item_count + 1) as i32,
// TODO: Implement all alignments. Note: not all alignment values are valid for content distribution
_ => Au::zero(),
};
// TODO: Implement gap property
let item_main_interval = /*gap + */ match resolved_justify_content {
JustifyContent::Start => Au::zero(),
JustifyContent::FlexStart => Au::zero(),
JustifyContent::End => Au::zero(),
JustifyContent::FlexEnd => Au::zero(),
JustifyContent::Center => Au::zero(),
JustifyContent::Stretch => Au::zero(),
JustifyContent::SpaceBetween => free_space / (item_count - 1) as i32,
JustifyContent::SpaceAround => free_space / item_count as i32,
JustifyContent::SpaceEvenly => free_space / (item_count + 1) as i32,
AlignFlags::START => Au::zero(),
AlignFlags::FLEX_START => Au::zero(),
AlignFlags::END => Au::zero(),
AlignFlags::FLEX_END => Au::zero(),
AlignFlags::CENTER => Au::zero(),
AlignFlags::STRETCH => Au::zero(),
AlignFlags::SPACE_BETWEEN => free_space / (item_count - 1) as i32,
AlignFlags::SPACE_AROUND => free_space / item_count as i32,
AlignFlags::SPACE_EVENLY => free_space / (item_count + 1) as i32,
// TODO: Implement all alignments. Note: not all alignment values are valid for content distribution
_ => Au::zero(),
};
// https://drafts.csswg.org/css-flexbox/#algo-cross-margins
@ -1440,18 +1459,18 @@ impl FlexItem<'_> {
if self.margin.cross_start.is_auto() || self.margin.cross_end.is_auto() {
Au::zero()
} else {
match self.align_self {
AlignItems::Stretch | AlignItems::FlexStart => Au::zero(),
AlignItems::FlexEnd => {
match self.align_self.0.value() {
AlignFlags::STRETCH | AlignFlags::FLEX_START => Au::zero(),
AlignFlags::FLEX_END => {
let margin_box_cross = *content_size + self.pbm_auto_is_zero.cross;
line_cross_size - margin_box_cross
},
AlignItems::Center => {
AlignFlags::CENTER => {
let margin_box_cross = *content_size + self.pbm_auto_is_zero.cross;
(line_cross_size - margin_box_cross) / 2
},
// FIXME: handle baseline alignment
AlignItems::Baseline => Au::zero(),
// FIXME: handle other alignments (note: not all AlignFlags values are valid for self alignment)
_ => Au::zero(),
}
};
outer_cross_start + margin.cross_start + self.border.cross_start + self.padding.cross_start