mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Rustfmt layout crate
This commit is contained in:
parent
577830de90
commit
349047b096
37 changed files with 7177 additions and 4832 deletions
|
@ -45,25 +45,25 @@ enum AxisSize {
|
|||
impl AxisSize {
|
||||
/// Generate a new available cross or main axis size from the specified size of the container,
|
||||
/// containing block size, min constraint, and max constraint
|
||||
pub fn new(size: LengthOrPercentageOrAuto, content_size: Option<Au>, min: LengthOrPercentage,
|
||||
max: LengthOrPercentageOrNone) -> AxisSize {
|
||||
pub fn new(
|
||||
size: LengthOrPercentageOrAuto,
|
||||
content_size: Option<Au>,
|
||||
min: LengthOrPercentage,
|
||||
max: LengthOrPercentageOrNone,
|
||||
) -> AxisSize {
|
||||
match size {
|
||||
LengthOrPercentageOrAuto::Length(length) => AxisSize::Definite(Au::from(length)),
|
||||
LengthOrPercentageOrAuto::Percentage(percent) => {
|
||||
match content_size {
|
||||
Some(size) => AxisSize::Definite(size.scale_by(percent.0)),
|
||||
None => AxisSize::Infinite
|
||||
}
|
||||
}
|
||||
LengthOrPercentageOrAuto::Calc(calc) => {
|
||||
match calc.to_used_value(content_size) {
|
||||
Some(length) => AxisSize::Definite(length),
|
||||
None => AxisSize::Infinite,
|
||||
}
|
||||
}
|
||||
LengthOrPercentageOrAuto::Percentage(percent) => match content_size {
|
||||
Some(size) => AxisSize::Definite(size.scale_by(percent.0)),
|
||||
None => AxisSize::Infinite,
|
||||
},
|
||||
LengthOrPercentageOrAuto::Calc(calc) => match calc.to_used_value(content_size) {
|
||||
Some(length) => AxisSize::Definite(length),
|
||||
None => AxisSize::Infinite,
|
||||
},
|
||||
LengthOrPercentageOrAuto::Auto => {
|
||||
AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ struct FlexItem {
|
|||
/// Whether the main size has met its constraint.
|
||||
pub is_frozen: bool,
|
||||
/// True if this flow has property 'visibility::collapse'.
|
||||
pub is_strut: bool
|
||||
pub is_strut: bool,
|
||||
}
|
||||
|
||||
impl FlexItem {
|
||||
|
@ -133,7 +133,7 @@ impl FlexItem {
|
|||
flex_shrink: flex_shrink.into(),
|
||||
order: order,
|
||||
is_frozen: false,
|
||||
is_strut: false
|
||||
is_strut: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,41 +147,61 @@ impl FlexItem {
|
|||
// should change to LengthOrPercentageOrAuto for automatic implied minimal size.
|
||||
// https://drafts.csswg.org/css-flexbox-1/#min-size-auto
|
||||
Direction::Inline => {
|
||||
let basis = from_flex_basis(block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_inline_size(),
|
||||
containing_length);
|
||||
let basis = from_flex_basis(
|
||||
block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_inline_size(),
|
||||
containing_length,
|
||||
);
|
||||
|
||||
// These methods compute auto margins to zero length, which is exactly what we want.
|
||||
block.fragment.compute_border_and_padding(containing_length);
|
||||
block.fragment.compute_inline_direction_margins(containing_length);
|
||||
block.fragment.compute_block_direction_margins(containing_length);
|
||||
block
|
||||
.fragment
|
||||
.compute_inline_direction_margins(containing_length);
|
||||
block
|
||||
.fragment
|
||||
.compute_block_direction_margins(containing_length);
|
||||
|
||||
let (border_padding, margin) = block.fragment.surrounding_intrinsic_inline_size();
|
||||
let content_size = block.base.intrinsic_inline_sizes.preferred_inline_size
|
||||
- border_padding
|
||||
- margin
|
||||
+ block.fragment.box_sizing_boundary(direction);
|
||||
let content_size = block.base.intrinsic_inline_sizes.preferred_inline_size -
|
||||
border_padding -
|
||||
margin +
|
||||
block.fragment.box_sizing_boundary(direction);
|
||||
self.base_size = basis.specified_or_default(content_size);
|
||||
self.max_size =
|
||||
block.fragment.style.max_inline_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block.fragment.style.min_inline_size().to_used_value(containing_length);
|
||||
}
|
||||
self.max_size = block
|
||||
.fragment
|
||||
.style
|
||||
.max_inline_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block
|
||||
.fragment
|
||||
.style
|
||||
.min_inline_size()
|
||||
.to_used_value(containing_length);
|
||||
},
|
||||
Direction::Block => {
|
||||
let basis = from_flex_basis(block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_block_size(),
|
||||
containing_length);
|
||||
let content_size = block.fragment.border_box.size.block
|
||||
- block.fragment.border_padding.block_start_end()
|
||||
+ block.fragment.box_sizing_boundary(direction);
|
||||
let basis = from_flex_basis(
|
||||
block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_block_size(),
|
||||
containing_length,
|
||||
);
|
||||
let content_size = block.fragment.border_box.size.block -
|
||||
block.fragment.border_padding.block_start_end() +
|
||||
block.fragment.box_sizing_boundary(direction);
|
||||
self.base_size = basis.specified_or_default(content_size);
|
||||
self.max_size =
|
||||
block.fragment.style.max_block_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block.fragment.style.min_block_size().to_used_value(containing_length);
|
||||
}
|
||||
self.max_size = block
|
||||
.fragment
|
||||
.style
|
||||
.max_block_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block
|
||||
.fragment
|
||||
.style
|
||||
.min_block_size()
|
||||
.to_used_value(containing_length);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,13 +212,14 @@ impl FlexItem {
|
|||
let outer_width = match direction {
|
||||
Direction::Inline => {
|
||||
fragment.border_padding.inline_start_end() + fragment.margin.inline_start_end()
|
||||
}
|
||||
},
|
||||
Direction::Block => {
|
||||
fragment.border_padding.block_start_end() + fragment.margin.block_start_end()
|
||||
}
|
||||
},
|
||||
};
|
||||
max(self.min_size, min(self.base_size, self.max_size))
|
||||
- fragment.box_sizing_boundary(direction) + outer_width
|
||||
max(self.min_size, min(self.base_size, self.max_size)) -
|
||||
fragment.box_sizing_boundary(direction) +
|
||||
outer_width
|
||||
}
|
||||
|
||||
/// Returns the number of auto margins in given direction.
|
||||
|
@ -213,7 +234,7 @@ impl FlexItem {
|
|||
if margin.inline_end == LengthOrPercentageOrAuto::Auto {
|
||||
margin_count += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
Direction::Block => {
|
||||
if margin.block_start == LengthOrPercentageOrAuto::Auto {
|
||||
margin_count += 1;
|
||||
|
@ -221,7 +242,7 @@ impl FlexItem {
|
|||
if margin.block_end == LengthOrPercentageOrAuto::Auto {
|
||||
margin_count += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
margin_count
|
||||
}
|
||||
|
@ -247,7 +268,7 @@ impl FlexLine {
|
|||
range: range,
|
||||
auto_margin_count: auto_margin_count,
|
||||
free_space: free_space,
|
||||
cross_size: Au(0)
|
||||
cross_size: Au(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,17 +286,20 @@ impl FlexLine {
|
|||
// https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths
|
||||
for item in items.iter_mut().filter(|i| !(i.is_strut && collapse)) {
|
||||
item.main_size = max(item.min_size, min(item.base_size, item.max_size));
|
||||
if (self.free_space > Au(0) && (item.flex_grow == 0.0 || item.base_size >= item.max_size)) ||
|
||||
(self.free_space < Au(0) && (item.flex_shrink == 0.0 || item.base_size <= item.min_size)) {
|
||||
item.is_frozen = true;
|
||||
} else {
|
||||
item.is_frozen = false;
|
||||
total_grow += item.flex_grow;
|
||||
total_shrink += item.flex_shrink;
|
||||
// The scaled factor is used to calculate flex shrink
|
||||
total_scaled += item.flex_shrink * item.base_size.0 as f32;
|
||||
active_count += 1;
|
||||
}
|
||||
if (self.free_space > Au(0) &&
|
||||
(item.flex_grow == 0.0 || item.base_size >= item.max_size)) ||
|
||||
(self.free_space < Au(0) &&
|
||||
(item.flex_shrink == 0.0 || item.base_size <= item.min_size))
|
||||
{
|
||||
item.is_frozen = true;
|
||||
} else {
|
||||
item.is_frozen = false;
|
||||
total_grow += item.flex_grow;
|
||||
total_shrink += item.flex_shrink;
|
||||
// The scaled factor is used to calculate flex shrink
|
||||
total_scaled += item.flex_shrink * item.base_size.0 as f32;
|
||||
active_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let initial_free_space = self.free_space;
|
||||
|
@ -291,12 +315,19 @@ impl FlexLine {
|
|||
};
|
||||
|
||||
total_variation = Au(0);
|
||||
for item in items.iter_mut().filter(|i| !i.is_frozen).filter(|i| !(i.is_strut && collapse)) {
|
||||
for item in items
|
||||
.iter_mut()
|
||||
.filter(|i| !i.is_frozen)
|
||||
.filter(|i| !(i.is_strut && collapse))
|
||||
{
|
||||
// Use this and the 'abs()' below to make the code work in both grow and shrink scenarios.
|
||||
let (factor, end_size) = if self.free_space > Au(0) {
|
||||
(item.flex_grow / total_grow, item.max_size)
|
||||
} else {
|
||||
(item.flex_shrink * item.base_size.0 as f32 / total_scaled, item.min_size)
|
||||
(
|
||||
item.flex_shrink * item.base_size.0 as f32 / total_scaled,
|
||||
item.min_size,
|
||||
)
|
||||
};
|
||||
let variation = self.free_space.scale_by(factor);
|
||||
if variation.0.abs() >= (end_size - item.main_size).0.abs() {
|
||||
|
@ -343,13 +374,11 @@ pub struct FlexFlow {
|
|||
/// True if this flex container can be multiline.
|
||||
is_wrappable: bool,
|
||||
/// True if the cross direction is reversed.
|
||||
cross_reverse: bool
|
||||
cross_reverse: bool,
|
||||
}
|
||||
|
||||
impl FlexFlow {
|
||||
pub fn from_fragment(fragment: Fragment,
|
||||
flotation: Option<FloatKind>)
|
||||
-> FlexFlow {
|
||||
pub fn from_fragment(fragment: Fragment, flotation: Option<FloatKind>) -> FlexFlow {
|
||||
let main_mode;
|
||||
let main_reverse;
|
||||
let is_wrappable;
|
||||
|
@ -363,8 +392,7 @@ impl FlexFlow {
|
|||
FlexDirection::ColumnReverse => (Direction::Block, true),
|
||||
};
|
||||
main_mode = mode;
|
||||
main_reverse =
|
||||
reverse == style.writing_mode.is_bidi_ltr();
|
||||
main_reverse = reverse == style.writing_mode.is_bidi_ltr();
|
||||
let (wrappable, reverse) = match fragment.style.get_position().flex_wrap {
|
||||
FlexWrap::Nowrap => (false, false),
|
||||
FlexWrap::Wrap => (true, false),
|
||||
|
@ -384,7 +412,7 @@ impl FlexFlow {
|
|||
items: Vec::new(),
|
||||
main_reverse: main_reverse,
|
||||
is_wrappable: is_wrappable,
|
||||
cross_reverse: cross_reverse
|
||||
cross_reverse: cross_reverse,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,7 +442,10 @@ impl FlexFlow {
|
|||
let kid = children.get(item.index);
|
||||
item.init_sizes(kid, container_size, self.main_mode);
|
||||
let outer_main_size = item.outer_main_size(kid, self.main_mode);
|
||||
if total_line_size + outer_main_size > container_size && end != start && self.is_wrappable {
|
||||
if total_line_size + outer_main_size > container_size &&
|
||||
end != start &&
|
||||
self.is_wrappable
|
||||
{
|
||||
break;
|
||||
}
|
||||
margin_count += item.auto_margin_count(kid, self.main_mode);
|
||||
|
@ -439,7 +470,8 @@ impl FlexFlow {
|
|||
if !fixed_width {
|
||||
for kid in self.block_flow.base.children.iter_mut() {
|
||||
let base = kid.mut_base();
|
||||
let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
|
||||
let is_absolutely_positioned =
|
||||
base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
|
||||
if !is_absolutely_positioned {
|
||||
let flex_item_inline_sizes = IntrinsicISizes {
|
||||
minimum_inline_size: base.intrinsic_inline_sizes.minimum_inline_size,
|
||||
|
@ -465,15 +497,18 @@ impl FlexFlow {
|
|||
if !fixed_width {
|
||||
for kid in self.block_flow.base.children.iter_mut() {
|
||||
let base = kid.mut_base();
|
||||
let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
|
||||
let is_absolutely_positioned =
|
||||
base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
|
||||
if !is_absolutely_positioned {
|
||||
computation.content_intrinsic_sizes.minimum_inline_size =
|
||||
max(computation.content_intrinsic_sizes.minimum_inline_size,
|
||||
base.intrinsic_inline_sizes.minimum_inline_size);
|
||||
computation.content_intrinsic_sizes.minimum_inline_size = max(
|
||||
computation.content_intrinsic_sizes.minimum_inline_size,
|
||||
base.intrinsic_inline_sizes.minimum_inline_size,
|
||||
);
|
||||
|
||||
computation.content_intrinsic_sizes.preferred_inline_size =
|
||||
max(computation.content_intrinsic_sizes.preferred_inline_size,
|
||||
base.intrinsic_inline_sizes.preferred_inline_size);
|
||||
computation.content_intrinsic_sizes.preferred_inline_size = max(
|
||||
computation.content_intrinsic_sizes.preferred_inline_size,
|
||||
base.intrinsic_inline_sizes.preferred_inline_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -483,11 +518,13 @@ impl FlexFlow {
|
|||
// TODO(zentner): This function needs to be radically different for multi-line flexbox.
|
||||
// Currently, this is the core of BlockFlow::propagate_assigned_inline_size_to_children() with
|
||||
// all float and table logic stripped out.
|
||||
fn block_mode_assign_inline_sizes(&mut self,
|
||||
_layout_context: &LayoutContext,
|
||||
inline_start_content_edge: Au,
|
||||
inline_end_content_edge: Au,
|
||||
content_inline_size: Au) {
|
||||
fn block_mode_assign_inline_sizes(
|
||||
&mut self,
|
||||
_layout_context: &LayoutContext,
|
||||
inline_start_content_edge: Au,
|
||||
inline_end_content_edge: Au,
|
||||
content_inline_size: Au,
|
||||
) {
|
||||
let _scope = layout_debug_scope!("flex::block_mode_assign_inline_sizes");
|
||||
debug!("flex::block_mode_assign_inline_sizes");
|
||||
|
||||
|
@ -496,19 +533,22 @@ impl FlexFlow {
|
|||
|
||||
let container_block_size = match self.available_main_size {
|
||||
AxisSize::Definite(length) => Some(length),
|
||||
_ => None
|
||||
_ => None,
|
||||
};
|
||||
let container_inline_size = match self.available_cross_size {
|
||||
AxisSize::Definite(length) => length,
|
||||
AxisSize::MinMax(ref constraint) => constraint.clamp(content_inline_size),
|
||||
AxisSize::Infinite => content_inline_size
|
||||
AxisSize::Infinite => content_inline_size,
|
||||
};
|
||||
|
||||
let mut children = self.block_flow.base.children.random_access_mut();
|
||||
for kid in &mut self.items {
|
||||
let kid_base = children.get(kid.index).mut_base();
|
||||
kid_base.block_container_explicit_block_size = container_block_size;
|
||||
if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) {
|
||||
if kid_base
|
||||
.flags
|
||||
.contains(FlowFlags::INLINE_POSITION_IS_STATIC)
|
||||
{
|
||||
// The inline-start margin edge of the child flow is at our inline-start content
|
||||
// edge, and its inline-size is our content inline-size.
|
||||
kid_base.position.start.i =
|
||||
|
@ -525,11 +565,13 @@ impl FlexFlow {
|
|||
}
|
||||
}
|
||||
|
||||
fn inline_mode_assign_inline_sizes(&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
inline_start_content_edge: Au,
|
||||
_inline_end_content_edge: Au,
|
||||
content_inline_size: Au) {
|
||||
fn inline_mode_assign_inline_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
inline_start_content_edge: Au,
|
||||
_inline_end_content_edge: Au,
|
||||
content_inline_size: Au,
|
||||
) {
|
||||
let _scope = layout_debug_scope!("flex::inline_mode_assign_inline_sizes");
|
||||
debug!("inline_mode_assign_inline_sizes");
|
||||
|
||||
|
@ -551,17 +593,25 @@ impl FlexFlow {
|
|||
self.block_flow.base.position.size.inline = inline_size;
|
||||
|
||||
// Calculate non-auto block size to pass to children.
|
||||
let box_border = self.block_flow.fragment.box_sizing_boundary(Direction::Block);
|
||||
let box_border = self
|
||||
.block_flow
|
||||
.fragment
|
||||
.box_sizing_boundary(Direction::Block);
|
||||
|
||||
let parent_container_size =
|
||||
self.block_flow.explicit_block_containing_size(layout_context.shared_context());
|
||||
let parent_container_size = self
|
||||
.block_flow
|
||||
.explicit_block_containing_size(layout_context.shared_context());
|
||||
// https://drafts.csswg.org/css-ui-3/#box-sizing
|
||||
let explicit_content_size = self
|
||||
.block_flow
|
||||
.explicit_block_size(parent_container_size)
|
||||
.map(|x| max(x - box_border, Au(0)));
|
||||
let containing_block_text_align =
|
||||
self.block_flow.fragment.style().get_inherited_text().text_align;
|
||||
.block_flow
|
||||
.explicit_block_size(parent_container_size)
|
||||
.map(|x| max(x - box_border, Au(0)));
|
||||
let containing_block_text_align = self
|
||||
.block_flow
|
||||
.fragment
|
||||
.style()
|
||||
.get_inherited_text()
|
||||
.text_align;
|
||||
|
||||
while let Some(mut line) = self.get_flex_line(inline_size) {
|
||||
let items = &mut self.items[line.range.clone()];
|
||||
|
@ -572,32 +622,42 @@ impl FlexFlow {
|
|||
let item_count = items.len() as i32;
|
||||
let mut cur_i = inline_start_content_edge;
|
||||
let item_interval = if line.free_space >= Au(0) && line.auto_margin_count == 0 {
|
||||
match self.block_flow.fragment.style().get_position().justify_content {
|
||||
match self
|
||||
.block_flow
|
||||
.fragment
|
||||
.style()
|
||||
.get_position()
|
||||
.justify_content
|
||||
{
|
||||
JustifyContent::SpaceBetween => {
|
||||
if item_count == 1 {
|
||||
Au(0)
|
||||
} else {
|
||||
line.free_space / (item_count - 1)
|
||||
}
|
||||
}
|
||||
JustifyContent::SpaceAround => {
|
||||
line.free_space / item_count
|
||||
}
|
||||
},
|
||||
JustifyContent::SpaceAround => line.free_space / item_count,
|
||||
_ => Au(0),
|
||||
}
|
||||
} else {
|
||||
Au(0)
|
||||
};
|
||||
|
||||
match self.block_flow.fragment.style().get_position().justify_content {
|
||||
match self
|
||||
.block_flow
|
||||
.fragment
|
||||
.style()
|
||||
.get_position()
|
||||
.justify_content
|
||||
{
|
||||
// Overflow equally in both ends of line.
|
||||
JustifyContent::Center | JustifyContent::SpaceAround => {
|
||||
cur_i += (line.free_space - item_interval * (item_count - 1)) / 2;
|
||||
}
|
||||
},
|
||||
JustifyContent::FlexEnd => {
|
||||
cur_i += line.free_space;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let mut children = self.block_flow.base.children.random_access_mut();
|
||||
|
@ -613,19 +673,18 @@ impl FlexFlow {
|
|||
block.base.flags.set_text_align(containing_block_text_align);
|
||||
|
||||
let margin = block.fragment.style().logical_margin();
|
||||
let auto_len =
|
||||
if line.auto_margin_count == 0 || line.free_space <= Au(0) {
|
||||
Au(0)
|
||||
} else {
|
||||
line.free_space / line.auto_margin_count
|
||||
};
|
||||
let auto_len = if line.auto_margin_count == 0 || line.free_space <= Au(0) {
|
||||
Au(0)
|
||||
} else {
|
||||
line.free_space / line.auto_margin_count
|
||||
};
|
||||
let margin_inline_start = MaybeAuto::from_style(margin.inline_start, inline_size)
|
||||
.specified_or_default(auto_len);
|
||||
let margin_inline_end = MaybeAuto::from_style(margin.inline_end, inline_size)
|
||||
.specified_or_default(auto_len);
|
||||
let item_inline_size = item.main_size
|
||||
- block.fragment.box_sizing_boundary(self.main_mode)
|
||||
+ block.fragment.border_padding.inline_start_end();
|
||||
let item_inline_size = item.main_size -
|
||||
block.fragment.box_sizing_boundary(self.main_mode) +
|
||||
block.fragment.border_padding.inline_start_end();
|
||||
let item_outer_size = item_inline_size + block.fragment.margin.inline_start_end();
|
||||
|
||||
block.fragment.margin.inline_start = margin_inline_start;
|
||||
|
@ -635,7 +694,7 @@ impl FlexFlow {
|
|||
block.base.position.start.i = if !self.main_reverse {
|
||||
cur_i
|
||||
} else {
|
||||
inline_start_content_edge * 2 + content_inline_size - cur_i - item_outer_size
|
||||
inline_start_content_edge * 2 + content_inline_size - cur_i - item_outer_size
|
||||
};
|
||||
block.base.position.size.inline = item_outer_size;
|
||||
cur_i += item_outer_size + item_interval;
|
||||
|
@ -669,7 +728,12 @@ impl FlexFlow {
|
|||
let _scope = layout_debug_scope!("flex::inline_mode_assign_block_size");
|
||||
|
||||
let line_count = self.lines.len() as i32;
|
||||
let line_align = self.block_flow.fragment.style().get_position().align_content;
|
||||
let line_align = self
|
||||
.block_flow
|
||||
.fragment
|
||||
.style()
|
||||
.get_position()
|
||||
.align_content;
|
||||
let mut cur_b = self.block_flow.fragment.border_padding.block_start;
|
||||
let mut total_cross_size = Au(0);
|
||||
let mut line_interval = Au(0);
|
||||
|
@ -679,22 +743,27 @@ impl FlexFlow {
|
|||
for line in self.lines.iter_mut() {
|
||||
for item in &self.items[line.range.clone()] {
|
||||
let fragment = &children.get(item.index).as_block().fragment;
|
||||
line.cross_size = max(line.cross_size,
|
||||
fragment.border_box.size.block +
|
||||
fragment.margin.block_start_end());
|
||||
line.cross_size = max(
|
||||
line.cross_size,
|
||||
fragment.border_box.size.block + fragment.margin.block_start_end(),
|
||||
);
|
||||
}
|
||||
total_cross_size += line.cross_size;
|
||||
}
|
||||
}
|
||||
|
||||
let box_border = self.block_flow.fragment.box_sizing_boundary(Direction::Block);
|
||||
let parent_container_size =
|
||||
self.block_flow.explicit_block_containing_size(layout_context.shared_context());
|
||||
let box_border = self
|
||||
.block_flow
|
||||
.fragment
|
||||
.box_sizing_boundary(Direction::Block);
|
||||
let parent_container_size = self
|
||||
.block_flow
|
||||
.explicit_block_containing_size(layout_context.shared_context());
|
||||
// https://drafts.csswg.org/css-ui-3/#box-sizing
|
||||
let explicit_content_size = self
|
||||
.block_flow
|
||||
.explicit_block_size(parent_container_size)
|
||||
.map(|x| max(x - box_border, Au(0)));
|
||||
.block_flow
|
||||
.explicit_block_size(parent_container_size)
|
||||
.map(|x| max(x - box_border, Au(0)));
|
||||
|
||||
if let Some(container_block_size) = explicit_content_size {
|
||||
let free_space = container_block_size - total_cross_size;
|
||||
|
@ -713,25 +782,25 @@ impl FlexFlow {
|
|||
} else {
|
||||
free_space / (line_count - 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
AlignContent::SpaceAround => {
|
||||
if line_count == 0 {
|
||||
Au(0)
|
||||
} else {
|
||||
free_space / line_count
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => Au(0),
|
||||
};
|
||||
|
||||
match line_align {
|
||||
AlignContent::Center | AlignContent::SpaceAround => {
|
||||
cur_b += (free_space - line_interval * (line_count - 1)) / 2;
|
||||
}
|
||||
},
|
||||
AlignContent::FlexEnd => {
|
||||
cur_b += free_space;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,8 +813,9 @@ impl FlexFlow {
|
|||
|
||||
let mut margin_block_start = block.fragment.margin.block_start;
|
||||
let mut margin_block_end = block.fragment.margin.block_end;
|
||||
let mut free_space = line.cross_size - block.base.position.size.block
|
||||
- block.fragment.margin.block_start_end();
|
||||
let mut free_space = line.cross_size -
|
||||
block.base.position.size.block -
|
||||
block.fragment.margin.block_start_end();
|
||||
|
||||
// The spec is a little vague here, but if I understand it correctly, the outer
|
||||
// cross size of item should equal to the line size if any auto margin exists.
|
||||
|
@ -758,29 +828,31 @@ impl FlexFlow {
|
|||
free_space / auto_margin_count
|
||||
};
|
||||
}
|
||||
margin_block_end = line.cross_size - margin_block_start - block.base.position.size.block;
|
||||
margin_block_end =
|
||||
line.cross_size - margin_block_start - block.base.position.size.block;
|
||||
free_space = Au(0);
|
||||
}
|
||||
|
||||
let self_align = block.fragment.style().get_position().align_self;
|
||||
if self_align == AlignSelf::Stretch &&
|
||||
block.fragment.style().content_block_size() == LengthOrPercentageOrAuto::Auto {
|
||||
free_space = Au(0);
|
||||
block.base.block_container_explicit_block_size = Some(line.cross_size);
|
||||
block.base.position.size.block =
|
||||
line.cross_size - margin_block_start - margin_block_end;
|
||||
block.fragment.border_box.size.block = block.base.position.size.block;
|
||||
// FIXME(stshine): item with 'align-self: stretch' and auto cross size should act
|
||||
// as if it has a fixed cross size, all child blocks should resolve against it.
|
||||
// block.assign_block_size(layout_context);
|
||||
}
|
||||
block.base.position.start.b = margin_block_start +
|
||||
if !self.cross_reverse {
|
||||
cur_b
|
||||
} else {
|
||||
self.block_flow.fragment.border_padding.block_start * 2
|
||||
+ total_cross_size - cur_b - line.cross_size
|
||||
};
|
||||
block.fragment.style().content_block_size() == LengthOrPercentageOrAuto::Auto
|
||||
{
|
||||
free_space = Au(0);
|
||||
block.base.block_container_explicit_block_size = Some(line.cross_size);
|
||||
block.base.position.size.block =
|
||||
line.cross_size - margin_block_start - margin_block_end;
|
||||
block.fragment.border_box.size.block = block.base.position.size.block;
|
||||
// FIXME(stshine): item with 'align-self: stretch' and auto cross size should act
|
||||
// as if it has a fixed cross size, all child blocks should resolve against it.
|
||||
// block.assign_block_size(layout_context);
|
||||
}
|
||||
block.base.position.start.b = margin_block_start + if !self.cross_reverse {
|
||||
cur_b
|
||||
} else {
|
||||
self.block_flow.fragment.border_padding.block_start * 2 + total_cross_size -
|
||||
cur_b -
|
||||
line.cross_size
|
||||
};
|
||||
// TODO(stshine): support baseline alignment.
|
||||
if free_space != Au(0) {
|
||||
let flex_cross = match self_align {
|
||||
|
@ -788,17 +860,17 @@ impl FlexFlow {
|
|||
AlignSelf::Center => free_space / 2,
|
||||
_ => Au(0),
|
||||
};
|
||||
block.base.position.start.b +=
|
||||
if !self.cross_reverse {
|
||||
flex_cross
|
||||
} else {
|
||||
free_space - flex_cross
|
||||
};
|
||||
block.base.position.start.b += if !self.cross_reverse {
|
||||
flex_cross
|
||||
} else {
|
||||
free_space - flex_cross
|
||||
};
|
||||
}
|
||||
}
|
||||
cur_b += line_interval + line.cross_size;
|
||||
}
|
||||
let total_block_size = total_cross_size + self.block_flow.fragment.border_padding.block_start_end();
|
||||
let total_block_size =
|
||||
total_cross_size + self.block_flow.fragment.border_padding.block_start_end();
|
||||
self.block_flow.fragment.border_box.size.block = total_block_size;
|
||||
self.block_flow.base.position.size.block = total_block_size;
|
||||
}
|
||||
|
@ -830,72 +902,96 @@ impl Flow for FlexFlow {
|
|||
}
|
||||
|
||||
fn bubble_inline_sizes(&mut self) {
|
||||
let _scope = layout_debug_scope!("flex::bubble_inline_sizes {:x}",
|
||||
self.block_flow.base.debug_id());
|
||||
let _scope = layout_debug_scope!(
|
||||
"flex::bubble_inline_sizes {:x}",
|
||||
self.block_flow.base.debug_id()
|
||||
);
|
||||
|
||||
// Flexbox Section 9.0: Generate anonymous flex items:
|
||||
// This part was handled in the flow constructor.
|
||||
|
||||
// Flexbox Section 9.1: Re-order flex items according to their order.
|
||||
// FIXME(stshine): This should be done during flow construction.
|
||||
let mut items: Vec<FlexItem> =
|
||||
self.block_flow
|
||||
.base
|
||||
.children
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, flow)| {
|
||||
!flow.as_block().base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)
|
||||
})
|
||||
.map(|(index, flow)| FlexItem::new(index, flow))
|
||||
.collect();
|
||||
let mut items: Vec<FlexItem> = self
|
||||
.block_flow
|
||||
.base
|
||||
.children
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, flow)| {
|
||||
!flow
|
||||
.as_block()
|
||||
.base
|
||||
.flags
|
||||
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)
|
||||
}).map(|(index, flow)| FlexItem::new(index, flow))
|
||||
.collect();
|
||||
|
||||
items.sort_by_key(|item| item.order);
|
||||
self.items = items;
|
||||
|
||||
match self.main_mode {
|
||||
Direction::Inline => self.inline_mode_bubble_inline_sizes(),
|
||||
Direction::Block => self.block_mode_bubble_inline_sizes()
|
||||
Direction::Block => self.block_mode_bubble_inline_sizes(),
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) {
|
||||
let _scope = layout_debug_scope!("flex::assign_inline_sizes {:x}", self.block_flow.base.debug_id());
|
||||
let _scope = layout_debug_scope!(
|
||||
"flex::assign_inline_sizes {:x}",
|
||||
self.block_flow.base.debug_id()
|
||||
);
|
||||
debug!("assign_inline_sizes");
|
||||
|
||||
if !self.block_flow.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW |
|
||||
ServoRestyleDamage::REFLOW) {
|
||||
return
|
||||
if !self
|
||||
.block_flow
|
||||
.base
|
||||
.restyle_damage
|
||||
.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.block_flow.initialize_container_size_for_root(layout_context.shared_context());
|
||||
self.block_flow
|
||||
.initialize_container_size_for_root(layout_context.shared_context());
|
||||
|
||||
// Our inline-size was set to the inline-size of the containing block by the flow's parent.
|
||||
// Now compute the real value.
|
||||
let containing_block_inline_size = self.block_flow.base.block_container_inline_size;
|
||||
self.block_flow.compute_used_inline_size(layout_context.shared_context(),
|
||||
containing_block_inline_size);
|
||||
self.block_flow.compute_used_inline_size(
|
||||
layout_context.shared_context(),
|
||||
containing_block_inline_size,
|
||||
);
|
||||
if self.block_flow.base.flags.is_float() {
|
||||
self.block_flow.float.as_mut().unwrap().containing_inline_size = containing_block_inline_size
|
||||
self.block_flow
|
||||
.float
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.containing_inline_size = containing_block_inline_size
|
||||
}
|
||||
|
||||
let (available_block_size, available_inline_size) = {
|
||||
let style = &self.block_flow.fragment.style;
|
||||
let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical() {
|
||||
let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical()
|
||||
{
|
||||
(style.get_position().width, style.get_position().height)
|
||||
} else {
|
||||
(style.get_position().height, style.get_position().width)
|
||||
};
|
||||
|
||||
let available_inline_size = AxisSize::new(specified_inline_size,
|
||||
Some(self.block_flow.base.block_container_inline_size),
|
||||
style.min_inline_size(),
|
||||
style.max_inline_size());
|
||||
let available_inline_size = AxisSize::new(
|
||||
specified_inline_size,
|
||||
Some(self.block_flow.base.block_container_inline_size),
|
||||
style.min_inline_size(),
|
||||
style.max_inline_size(),
|
||||
);
|
||||
|
||||
let available_block_size = AxisSize::new(specified_block_size,
|
||||
self.block_flow.base.block_container_explicit_block_size,
|
||||
style.min_block_size(),
|
||||
style.max_block_size());
|
||||
let available_block_size = AxisSize::new(
|
||||
specified_block_size,
|
||||
self.block_flow.base.block_container_explicit_block_size,
|
||||
style.min_block_size(),
|
||||
style.max_block_size(),
|
||||
);
|
||||
(available_block_size, available_inline_size)
|
||||
};
|
||||
|
||||
|
@ -903,37 +999,46 @@ impl Flow for FlexFlow {
|
|||
let inline_start_content_edge = self.block_flow.fragment.border_box.start.i +
|
||||
self.block_flow.fragment.border_padding.inline_start;
|
||||
|
||||
debug!("inline_start_content_edge = {:?}", inline_start_content_edge);
|
||||
debug!(
|
||||
"inline_start_content_edge = {:?}",
|
||||
inline_start_content_edge
|
||||
);
|
||||
|
||||
let padding_and_borders = self.block_flow.fragment.border_padding.inline_start_end();
|
||||
|
||||
// Distance from the inline-end margin edge to the inline-end content edge.
|
||||
let inline_end_content_edge =
|
||||
self.block_flow.fragment.margin.inline_end +
|
||||
let inline_end_content_edge = self.block_flow.fragment.margin.inline_end +
|
||||
self.block_flow.fragment.border_padding.inline_end;
|
||||
|
||||
debug!("padding_and_borders = {:?}", padding_and_borders);
|
||||
debug!("self.block_flow.fragment.border_box.size.inline = {:?}",
|
||||
self.block_flow.fragment.border_box.size.inline);
|
||||
let content_inline_size = self.block_flow.fragment.border_box.size.inline - padding_and_borders;
|
||||
debug!(
|
||||
"self.block_flow.fragment.border_box.size.inline = {:?}",
|
||||
self.block_flow.fragment.border_box.size.inline
|
||||
);
|
||||
let content_inline_size =
|
||||
self.block_flow.fragment.border_box.size.inline - padding_and_borders;
|
||||
|
||||
match self.main_mode {
|
||||
Direction::Inline => {
|
||||
self.available_main_size = available_inline_size;
|
||||
self.available_cross_size = available_block_size;
|
||||
self.inline_mode_assign_inline_sizes(layout_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
content_inline_size)
|
||||
}
|
||||
Direction::Block => {
|
||||
self.inline_mode_assign_inline_sizes(
|
||||
layout_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
content_inline_size,
|
||||
)
|
||||
},
|
||||
Direction::Block => {
|
||||
self.available_main_size = available_block_size;
|
||||
self.available_cross_size = available_inline_size;
|
||||
self.block_mode_assign_inline_sizes(layout_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
content_inline_size)
|
||||
}
|
||||
self.block_mode_assign_inline_sizes(
|
||||
layout_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
content_inline_size,
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -941,31 +1046,37 @@ impl Flow for FlexFlow {
|
|||
match self.main_mode {
|
||||
Direction::Inline => {
|
||||
self.inline_mode_assign_block_size(layout_context);
|
||||
let block_start = AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_start);
|
||||
let block_end = AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_end);
|
||||
self.block_flow.base.collapsible_margins = CollapsibleMargins::Collapse(block_start, block_end);
|
||||
let block_start =
|
||||
AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_start);
|
||||
let block_end =
|
||||
AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_end);
|
||||
self.block_flow.base.collapsible_margins =
|
||||
CollapsibleMargins::Collapse(block_start, block_end);
|
||||
|
||||
// TODO(stshine): assign proper static position for absolute descendants.
|
||||
if (&*self as &Flow).contains_roots_of_absolute_flow_tree() {
|
||||
// Assign block-sizes for all flows in this absolute flow tree.
|
||||
// This is preorder because the block-size of an absolute flow may depend on
|
||||
// the block-size of its containing block, which may also be an absolute flow.
|
||||
let assign_abs_b_sizes = AbsoluteAssignBSizesTraversal(layout_context.shared_context());
|
||||
let assign_abs_b_sizes =
|
||||
AbsoluteAssignBSizesTraversal(layout_context.shared_context());
|
||||
assign_abs_b_sizes.traverse_absolute_flows(&mut *self);
|
||||
}
|
||||
}
|
||||
Direction::Block =>{
|
||||
self.block_flow
|
||||
.assign_block_size_block_base(layout_context,
|
||||
None,
|
||||
MarginsMayCollapseFlag::MarginsMayNotCollapse);
|
||||
},
|
||||
Direction::Block => {
|
||||
self.block_flow.assign_block_size_block_base(
|
||||
layout_context,
|
||||
None,
|
||||
MarginsMayCollapseFlag::MarginsMayNotCollapse,
|
||||
);
|
||||
self.block_mode_assign_block_size();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) {
|
||||
self.block_flow.compute_stacking_relative_position(layout_context)
|
||||
self.block_flow
|
||||
.compute_stacking_relative_position(layout_context)
|
||||
}
|
||||
|
||||
fn place_float_if_applicable<'a>(&mut self) {
|
||||
|
@ -973,11 +1084,13 @@ impl Flow for FlexFlow {
|
|||
}
|
||||
|
||||
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
|
||||
self.block_flow.update_late_computed_inline_position_if_necessary(inline_position)
|
||||
self.block_flow
|
||||
.update_late_computed_inline_position_if_necessary(inline_position)
|
||||
}
|
||||
|
||||
fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
|
||||
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
|
||||
self.block_flow
|
||||
.update_late_computed_block_position_if_necessary(block_position)
|
||||
}
|
||||
|
||||
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
|
||||
|
@ -1008,11 +1121,17 @@ impl Flow for FlexFlow {
|
|||
self.block_flow.generated_containing_block_size(flow)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
level: i32,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position);
|
||||
fn iterate_through_fragment_border_boxes(
|
||||
&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
level: i32,
|
||||
stacking_context_position: &Point2D<Au>,
|
||||
) {
|
||||
self.block_flow.iterate_through_fragment_border_boxes(
|
||||
iterator,
|
||||
level,
|
||||
stacking_context_position,
|
||||
);
|
||||
}
|
||||
|
||||
fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue