mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
layout: Allow layouts to customize their used style (#35012)
Some layouts like table need some style overrides. We were handling this in `ComputedValuesExt`, but it was messy, unreliable and too limited. For example, we were assuming that a style with `display: table` would belong to a table wrapper box or table grid box. However, certain HTML elements can ignore their `display` value and generate a different kind of box. I think we aren't doing that yet, but we will need this. Also, resolving the used border of a table needs layout information, which we don't have in `ComputedValuesExt`. This patch will allow to improve border collapsing in a follow-up. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
7e7792dfbd
commit
60dc3b26fb
11 changed files with 368 additions and 238 deletions
|
@ -42,7 +42,8 @@ use crate::sizing::{
|
||||||
ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult, IntrinsicSizingMode,
|
ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult, IntrinsicSizingMode,
|
||||||
};
|
};
|
||||||
use crate::style_ext::{
|
use crate::style_ext::{
|
||||||
AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin,
|
AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, LayoutStyle,
|
||||||
|
PaddingBorderMargin,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock,
|
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock,
|
||||||
|
@ -1052,7 +1053,7 @@ impl FlexContainer {
|
||||||
containing_block_for_container: &ContainingBlock,
|
containing_block_for_container: &ContainingBlock,
|
||||||
) -> (FlexRelativeVec2<Au>, FlexRelativeVec2<Option<Au>>, bool) {
|
) -> (FlexRelativeVec2<Au>, FlexRelativeVec2<Option<Au>>, bool) {
|
||||||
let sizes: ContentBoxSizesAndPBMDeprecated = self
|
let sizes: ContentBoxSizesAndPBMDeprecated = self
|
||||||
.style
|
.layout_style()
|
||||||
.content_box_sizes_and_padding_border_margin(&containing_block_for_container.into())
|
.content_box_sizes_and_padding_border_margin(&containing_block_for_container.into())
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
|
@ -1071,6 +1072,11 @@ impl FlexContainer {
|
||||||
sizes.depends_on_block_constraints,
|
sizes.depends_on_block_constraints,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Align all flex lines per `align-content` according to
|
/// Align all flex lines per `align-content` according to
|
||||||
|
@ -1141,7 +1147,8 @@ impl<'a> FlexItem<'a> {
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
} = box_
|
} = box_
|
||||||
.style()
|
.independent_formatting_context
|
||||||
|
.layout_style()
|
||||||
.content_box_sizes_and_padding_border_margin(&containing_block.into())
|
.content_box_sizes_and_padding_border_margin(&containing_block.into())
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
|
@ -2281,7 +2288,9 @@ impl FlexItemBox {
|
||||||
content_max_box_size,
|
content_max_box_size,
|
||||||
pbm,
|
pbm,
|
||||||
..
|
..
|
||||||
} = style
|
} = self
|
||||||
|
.independent_formatting_context
|
||||||
|
.layout_style()
|
||||||
.content_box_sizes_and_padding_border_margin(containing_block)
|
.content_box_sizes_and_padding_border_margin(containing_block)
|
||||||
.into();
|
.into();
|
||||||
let preferred_aspect_ratio = self
|
let preferred_aspect_ratio = self
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::dom_traversal::NodeAndStyleInfo;
|
use crate::dom_traversal::NodeAndStyleInfo;
|
||||||
use crate::fragment_tree::BaseFragmentInfo;
|
use crate::fragment_tree::BaseFragmentInfo;
|
||||||
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{LayoutStyle, PaddingBorderMargin};
|
||||||
use crate::ContainingBlock;
|
use crate::ContainingBlock;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -52,6 +52,11 @@ impl InlineBox {
|
||||||
..*self
|
..*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -214,7 +219,9 @@ impl InlineBoxContainerState {
|
||||||
font_metrics: Option<&FontMetrics>,
|
font_metrics: Option<&FontMetrics>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let style = inline_box.style.clone();
|
let style = inline_box.style.clone();
|
||||||
let pbm = style.padding_border_margin(containing_block);
|
let pbm = inline_box
|
||||||
|
.layout_style()
|
||||||
|
.padding_border_margin(containing_block);
|
||||||
|
|
||||||
let mut flags = InlineContainerStateFlags::empty();
|
let mut flags = InlineContainerStateFlags::empty();
|
||||||
if inline_container_needs_strut(&style, layout_context, Some(&pbm)) {
|
if inline_container_needs_strut(&style, layout_context, Some(&pbm)) {
|
||||||
|
|
|
@ -2244,11 +2244,11 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
let inline_box = inline_box.borrow();
|
let inline_box = inline_box.borrow();
|
||||||
let zero = Au::zero();
|
let zero = Au::zero();
|
||||||
let writing_mode = self.constraint_space.writing_mode;
|
let writing_mode = self.constraint_space.writing_mode;
|
||||||
let padding = inline_box
|
let layout_style = inline_box.layout_style();
|
||||||
.style
|
let padding = layout_style
|
||||||
.padding(writing_mode)
|
.padding(writing_mode)
|
||||||
.percentages_relative_to(zero);
|
.percentages_relative_to(zero);
|
||||||
let border = inline_box.style.border_width(writing_mode);
|
let border = layout_style.border_width(writing_mode);
|
||||||
let margin = inline_box
|
let margin = inline_box
|
||||||
.style
|
.style
|
||||||
.margin(writing_mode)
|
.margin(writing_mode)
|
||||||
|
|
|
@ -38,7 +38,7 @@ use crate::layout_box_base::LayoutBoxBase;
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
use crate::replaced::ReplacedContents;
|
use crate::replaced::ReplacedContents;
|
||||||
use crate::sizing::{self, ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{self, ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{ComputedValuesExt, ContentBoxSizesAndPBM, PaddingBorderMargin};
|
use crate::style_ext::{ContentBoxSizesAndPBM, LayoutStyle, PaddingBorderMargin};
|
||||||
use crate::{
|
use crate::{
|
||||||
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock,
|
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock,
|
||||||
SizeConstraint,
|
SizeConstraint,
|
||||||
|
@ -105,19 +105,22 @@ impl BlockLevelBox {
|
||||||
collected_margin: &mut CollapsedMargin,
|
collected_margin: &mut CollapsedMargin,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let style = match self {
|
let layout_style = match self {
|
||||||
BlockLevelBox::SameFormattingContextBlock { base, .. } => &base.style,
|
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => {
|
||||||
|
contents.layout_style(base)
|
||||||
|
},
|
||||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) |
|
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) |
|
||||||
BlockLevelBox::OutOfFlowFloatBox(_) => return true,
|
BlockLevelBox::OutOfFlowFloatBox(_) => return true,
|
||||||
BlockLevelBox::OutsideMarker(_) => return false,
|
BlockLevelBox::OutsideMarker(_) => return false,
|
||||||
BlockLevelBox::Independent(ref context) => {
|
BlockLevelBox::Independent(ref context) => {
|
||||||
// FIXME: If the element doesn't fit next to floats, it will get clearance.
|
// FIXME: If the element doesn't fit next to floats, it will get clearance.
|
||||||
// In that case this should be returning false.
|
// In that case this should be returning false.
|
||||||
context.style()
|
context.layout_style()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: This should only return false when 'clear' causes clearance.
|
// FIXME: This should only return false when 'clear' causes clearance.
|
||||||
|
let style = layout_style.style();
|
||||||
if style.get_box().clear != StyleClear::None {
|
if style.get_box().clear != StyleClear::None {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +129,7 @@ impl BlockLevelBox {
|
||||||
content_box_sizes,
|
content_box_sizes,
|
||||||
pbm,
|
pbm,
|
||||||
..
|
..
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = layout_style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
let margin = pbm.margin.auto_is(Au::zero);
|
let margin = pbm.margin.auto_is(Au::zero);
|
||||||
collected_margin.adjoin_assign(&CollapsedMargin::new(margin.block_start));
|
collected_margin.adjoin_assign(&CollapsedMargin::new(margin.block_start));
|
||||||
|
|
||||||
|
@ -310,9 +313,11 @@ impl OutsideMarker {
|
||||||
// TODO: This is the wrong containing block, as it should be the containing block of the
|
// TODO: This is the wrong containing block, as it should be the containing block of the
|
||||||
// parent of this list item. What this means in practice is that the writing mode could be
|
// parent of this list item. What this means in practice is that the writing mode could be
|
||||||
// wrong and padding defined as a percentage will be resolved incorrectly.
|
// wrong and padding defined as a percentage will be resolved incorrectly.
|
||||||
let pbm_of_list_item = self
|
//
|
||||||
.list_item_style()
|
// TODO: This should use the LayoutStyle of the list item, not the default one. Currently
|
||||||
.padding_border_margin(containing_block);
|
// they are the same, but this could change in the future.
|
||||||
|
let pbm_of_list_item =
|
||||||
|
LayoutStyle::Default(self.list_item_style()).padding_border_margin(containing_block);
|
||||||
let content_rect = LogicalRect {
|
let content_rect = LogicalRect {
|
||||||
start_corner: LogicalVec2 {
|
start_corner: LogicalVec2 {
|
||||||
inline: -max_inline_size -
|
inline: -max_inline_size -
|
||||||
|
@ -387,6 +392,11 @@ impl BlockFormattingContext {
|
||||||
detailed_layout_info: None,
|
detailed_layout_info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style<'a>(&self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> {
|
||||||
|
LayoutStyle::Default(&base.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the min/max-content inline size of the block-level children of a block container.
|
/// Finds the min/max-content inline size of the block-level children of a block container.
|
||||||
|
@ -425,7 +435,7 @@ fn compute_inline_content_sizes_for_block_level_boxes(
|
||||||
},
|
},
|
||||||
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => {
|
BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => {
|
||||||
let inline_content_sizes_result = sizing::outer_inline(
|
let inline_content_sizes_result = sizing::outer_inline(
|
||||||
&base.style,
|
&contents.layout_style(base),
|
||||||
containing_block,
|
containing_block,
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
|
@ -568,6 +578,11 @@ impl BlockContainer {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style<'a>(&self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> {
|
||||||
|
LayoutStyle::Default(&base.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputeInlineContentSizes for BlockContainer {
|
impl ComputeInlineContentSizes for BlockContainer {
|
||||||
|
@ -824,6 +839,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
|
||||||
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
|
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
|
||||||
) -> BoxFragment {
|
) -> BoxFragment {
|
||||||
let style = &base.style;
|
let style = &base.style;
|
||||||
|
let layout_style = contents.layout_style(base);
|
||||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||||
let get_inline_content_sizes = |constraint_space: &ConstraintSpace| {
|
let get_inline_content_sizes = |constraint_space: &ConstraintSpace| {
|
||||||
base.inline_content_sizes(layout_context, constraint_space, contents)
|
base.inline_content_sizes(layout_context, constraint_space, contents)
|
||||||
|
@ -837,7 +853,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
|
||||||
available_block_size,
|
available_block_size,
|
||||||
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
||||||
containing_block,
|
containing_block,
|
||||||
style,
|
&layout_style,
|
||||||
get_inline_content_sizes,
|
get_inline_content_sizes,
|
||||||
false, /* is_table */
|
false, /* is_table */
|
||||||
);
|
);
|
||||||
|
@ -1071,6 +1087,7 @@ impl IndependentNonReplacedContents {
|
||||||
base.inline_content_sizes(layout_context, constraint_space, self)
|
base.inline_content_sizes(layout_context, constraint_space, self)
|
||||||
.sizes
|
.sizes
|
||||||
};
|
};
|
||||||
|
let layout_style = self.layout_style(base);
|
||||||
let ContainingBlockPaddingAndBorder {
|
let ContainingBlockPaddingAndBorder {
|
||||||
containing_block: containing_block_for_children,
|
containing_block: containing_block_for_children,
|
||||||
pbm,
|
pbm,
|
||||||
|
@ -1079,7 +1096,7 @@ impl IndependentNonReplacedContents {
|
||||||
available_block_size,
|
available_block_size,
|
||||||
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
||||||
containing_block,
|
containing_block,
|
||||||
&base.style,
|
&layout_style,
|
||||||
get_inline_content_sizes,
|
get_inline_content_sizes,
|
||||||
self.is_table(),
|
self.is_table(),
|
||||||
);
|
);
|
||||||
|
@ -1163,7 +1180,9 @@ impl IndependentNonReplacedContents {
|
||||||
content_box_sizes,
|
content_box_sizes,
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = self
|
||||||
|
.layout_style(base)
|
||||||
|
.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
|
|
||||||
let (margin_block_start, margin_block_end) =
|
let (margin_block_start, margin_block_end) =
|
||||||
solve_block_margins_for_in_flow_block_level(&pbm);
|
solve_block_margins_for_in_flow_block_level(&pbm);
|
||||||
|
@ -1468,8 +1487,8 @@ impl ReplacedContents {
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
mut sequential_layout_state: Option<&mut SequentialLayoutState>,
|
mut sequential_layout_state: Option<&mut SequentialLayoutState>,
|
||||||
) -> BoxFragment {
|
) -> BoxFragment {
|
||||||
let content_box_sizes_and_pbm = base
|
let content_box_sizes_and_pbm = self
|
||||||
.style
|
.layout_style(base)
|
||||||
.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
let pbm = &content_box_sizes_and_pbm.pbm;
|
let pbm = &content_box_sizes_and_pbm.pbm;
|
||||||
let content_size = self.used_size_as_if_inline_element(
|
let content_size = self.used_size_as_if_inline_element(
|
||||||
|
@ -1618,10 +1637,11 @@ struct ResolvedMargins {
|
||||||
/// inline size could then be incorrect.
|
/// inline size could then be incorrect.
|
||||||
fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
containing_block: &ContainingBlock<'_>,
|
containing_block: &ContainingBlock<'_>,
|
||||||
style: &'a Arc<ComputedValues>,
|
layout_style: &'a LayoutStyle,
|
||||||
get_inline_content_sizes: impl FnOnce(&ConstraintSpace) -> ContentSizes,
|
get_inline_content_sizes: impl FnOnce(&ConstraintSpace) -> ContentSizes,
|
||||||
is_table: bool,
|
is_table: bool,
|
||||||
) -> ContainingBlockPaddingAndBorder<'a> {
|
) -> ContainingBlockPaddingAndBorder<'a> {
|
||||||
|
let style = layout_style.style();
|
||||||
if matches!(style.pseudo(), Some(PseudoElement::ServoAnonymousBox)) {
|
if matches!(style.pseudo(), Some(PseudoElement::ServoAnonymousBox)) {
|
||||||
// <https://drafts.csswg.org/css2/#anonymous-block-level>
|
// <https://drafts.csswg.org/css2/#anonymous-block-level>
|
||||||
// > Anonymous block boxes are ignored when resolving percentage values that would
|
// > Anonymous block boxes are ignored when resolving percentage values that would
|
||||||
|
@ -1650,7 +1670,7 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
content_box_sizes,
|
content_box_sizes,
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = layout_style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
|
|
||||||
let margin = pbm.margin.auto_is(Au::zero);
|
let margin = pbm.margin.auto_is(Au::zero);
|
||||||
let pbm_sums = pbm.padding + pbm.border + margin;
|
let pbm_sums = pbm.padding + pbm.border + margin;
|
||||||
|
@ -2140,8 +2160,9 @@ impl IndependentFormattingContext {
|
||||||
) -> IndependentLayoutResult {
|
) -> IndependentLayoutResult {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let container_writing_mode = containing_block.style.writing_mode;
|
let container_writing_mode = containing_block.style.writing_mode;
|
||||||
let content_box_sizes_and_pbm =
|
let content_box_sizes_and_pbm = self
|
||||||
style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
.layout_style()
|
||||||
|
.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
let pbm = &content_box_sizes_and_pbm.pbm;
|
let pbm = &content_box_sizes_and_pbm.pbm;
|
||||||
let margin = pbm.margin.auto_is(Au::zero);
|
let margin = pbm.margin.auto_is(Au::zero);
|
||||||
let pbm_sums = pbm.padding + pbm.border + margin;
|
let pbm_sums = pbm.padding + pbm.border + margin;
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::layout_box_base::LayoutBoxBase;
|
||||||
use crate::positioned::PositioningContext;
|
use crate::positioned::PositioningContext;
|
||||||
use crate::replaced::ReplacedContents;
|
use crate::replaced::ReplacedContents;
|
||||||
use crate::sizing::{self, ComputeInlineContentSizes, InlineContentSizesResult};
|
use crate::sizing::{self, ComputeInlineContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{AspectRatio, DisplayInside};
|
use crate::style_ext::{AspectRatio, DisplayInside, LayoutStyle};
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
use crate::taffy::TaffyContainer;
|
use crate::taffy::TaffyContainer;
|
||||||
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
|
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
|
||||||
|
@ -217,7 +217,7 @@ impl IndependentFormattingContext {
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
) -> InlineContentSizesResult {
|
) -> InlineContentSizesResult {
|
||||||
sizing::outer_inline(
|
sizing::outer_inline(
|
||||||
self.style(),
|
&self.layout_style(),
|
||||||
containing_block,
|
containing_block,
|
||||||
auto_minimum,
|
auto_minimum,
|
||||||
auto_block_size_stretches_to_containing_block,
|
auto_block_size_stretches_to_containing_block,
|
||||||
|
@ -242,6 +242,18 @@ impl IndependentFormattingContext {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
match &self.contents {
|
||||||
|
IndependentFormattingContextContents::NonReplaced(content) => {
|
||||||
|
content.layout_style(&self.base)
|
||||||
|
},
|
||||||
|
IndependentFormattingContextContents::Replaced(content) => {
|
||||||
|
content.layout_style(&self.base)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndependentNonReplacedContents {
|
impl IndependentNonReplacedContents {
|
||||||
|
@ -279,6 +291,16 @@ impl IndependentNonReplacedContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style<'a>(&'a self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> {
|
||||||
|
match self {
|
||||||
|
IndependentNonReplacedContents::Flow(fc) => fc.layout_style(base),
|
||||||
|
IndependentNonReplacedContents::Flex(fc) => fc.layout_style(),
|
||||||
|
IndependentNonReplacedContents::Grid(fc) => fc.layout_style(),
|
||||||
|
IndependentNonReplacedContents::Table(fc) => fc.layout_style(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn preferred_aspect_ratio(&self) -> Option<AspectRatio> {
|
pub(crate) fn preferred_aspect_ratio(&self) -> Option<AspectRatio> {
|
||||||
// TODO: support preferred aspect ratios on non-replaced boxes.
|
// TODO: support preferred aspect ratios on non-replaced boxes.
|
||||||
|
|
|
@ -467,7 +467,9 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
content_box_sizes,
|
content_box_sizes,
|
||||||
pbm,
|
pbm,
|
||||||
..
|
..
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = context
|
||||||
|
.layout_style()
|
||||||
|
.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
let containing_block = &containing_block.into();
|
let containing_block = &containing_block.into();
|
||||||
let is_table = context.is_table();
|
let is_table = context.is_table();
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,9 @@ use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes};
|
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes};
|
||||||
|
use crate::layout_box_base::LayoutBoxBase;
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM, LayoutStyle};
|
||||||
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -567,6 +568,11 @@ impl ReplacedContents {
|
||||||
block: block_size,
|
block: block_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style<'a>(&self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> {
|
||||||
|
LayoutStyle::Default(&base.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputeInlineContentSizes for ReplacedContents {
|
impl ComputeInlineContentSizes for ReplacedContents {
|
||||||
|
|
|
@ -8,13 +8,12 @@ use std::cell::LazyCell;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use style::properties::ComputedValues;
|
|
||||||
use style::values::computed::LengthPercentage;
|
use style::values::computed::LengthPercentage;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::geom::Size;
|
use crate::geom::Size;
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM, LayoutStyle};
|
||||||
use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2};
|
use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -111,7 +110,7 @@ impl From<Au> for ContentSizes {
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn outer_inline(
|
pub(crate) fn outer_inline(
|
||||||
style: &ComputedValues,
|
layout_style: &LayoutStyle,
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
|
@ -125,12 +124,13 @@ pub(crate) fn outer_inline(
|
||||||
content_box_sizes,
|
content_box_sizes,
|
||||||
pbm,
|
pbm,
|
||||||
mut depends_on_block_constraints,
|
mut depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(containing_block);
|
} = layout_style.content_box_sizes_and_padding_border_margin(containing_block);
|
||||||
let margin = pbm.margin.map(|v| v.auto_is(Au::zero));
|
let margin = pbm.margin.map(|v| v.auto_is(Au::zero));
|
||||||
let pbm_sums = LogicalVec2 {
|
let pbm_sums = LogicalVec2 {
|
||||||
block: pbm.padding_border_sums.block + margin.block_sum(),
|
block: pbm.padding_border_sums.block + margin.block_sum(),
|
||||||
inline: pbm.padding_border_sums.inline + margin.inline_sum(),
|
inline: pbm.padding_border_sums.inline + margin.inline_sum(),
|
||||||
};
|
};
|
||||||
|
let style = layout_style.style();
|
||||||
let content_size = LazyCell::new(|| {
|
let content_size = LazyCell::new(|| {
|
||||||
let constraint_space = if establishes_containing_block {
|
let constraint_space = if establishes_containing_block {
|
||||||
let available_block_size = containing_block
|
let available_block_size = containing_block
|
||||||
|
|
|
@ -278,23 +278,10 @@ pub(crate) trait ComputedValuesExt {
|
||||||
box_size: LogicalVec2<Size<Au>>,
|
box_size: LogicalVec2<Size<Au>>,
|
||||||
pbm: &PaddingBorderMargin,
|
pbm: &PaddingBorderMargin,
|
||||||
) -> LogicalVec2<Size<Au>>;
|
) -> LogicalVec2<Size<Au>>;
|
||||||
fn content_box_sizes_and_padding_border_margin(
|
|
||||||
&self,
|
|
||||||
containing_block: &IndefiniteContainingBlock,
|
|
||||||
) -> ContentBoxSizesAndPBM;
|
|
||||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
|
|
||||||
fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
|
||||||
&self,
|
|
||||||
writing_mode: WritingMode,
|
|
||||||
containing_block_inline_size: Au,
|
|
||||||
) -> PaddingBorderMargin;
|
|
||||||
fn padding(&self, containing_block_writing_mode: WritingMode)
|
|
||||||
-> LogicalSides<LengthPercentage>;
|
|
||||||
fn border_style_color(
|
fn border_style_color(
|
||||||
&self,
|
&self,
|
||||||
containing_block_writing_mode: WritingMode,
|
containing_block_writing_mode: WritingMode,
|
||||||
) -> LogicalSides<BorderStyleColor>;
|
) -> LogicalSides<BorderStyleColor>;
|
||||||
fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au>;
|
|
||||||
fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>;
|
fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>>;
|
||||||
fn margin(
|
fn margin(
|
||||||
&self,
|
&self,
|
||||||
|
@ -445,129 +432,6 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_box_sizes_and_padding_border_margin(
|
|
||||||
&self,
|
|
||||||
containing_block: &IndefiniteContainingBlock,
|
|
||||||
) -> ContentBoxSizesAndPBM {
|
|
||||||
// <https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution>
|
|
||||||
// If max size properties or preferred size properties are set to a value containing
|
|
||||||
// indefinite percentages, we treat the entire value as the initial value of the property.
|
|
||||||
// However, for min size properties, as well as for margins and paddings,
|
|
||||||
// we instead resolve indefinite percentages against zero.
|
|
||||||
let containing_block_size = containing_block.size.map(|value| value.non_auto());
|
|
||||||
let containing_block_size_auto_is_zero =
|
|
||||||
containing_block_size.map(|value| value.unwrap_or_else(Au::zero));
|
|
||||||
let writing_mode = containing_block.writing_mode;
|
|
||||||
let pbm = self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
|
||||||
writing_mode,
|
|
||||||
containing_block.size.inline.auto_is(Au::zero),
|
|
||||||
);
|
|
||||||
let box_size = self.box_size(writing_mode);
|
|
||||||
let min_size = self.min_box_size(writing_mode);
|
|
||||||
let max_size = self.max_box_size(writing_mode);
|
|
||||||
let depends_on_block_constraints = |size: &Size<LengthPercentage>| {
|
|
||||||
match size {
|
|
||||||
// fit-content is like clamp(min-content, stretch, max-content), but currently
|
|
||||||
// min-content and max-content have the same behavior in the block axis,
|
|
||||||
// so there is no dependency on block constraints.
|
|
||||||
// TODO: for flex and grid layout, min-content and max-content should be different.
|
|
||||||
// TODO: We are assuming that Size::Initial doesn't stretch. However, it may actually
|
|
||||||
// stretch flex and grid items depending on the CSS Align properties, in that case
|
|
||||||
// the caller needs to take care of it.
|
|
||||||
Size::Stretch => true,
|
|
||||||
Size::Numeric(length_percentage) => length_percentage.has_percentage(),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let depends_on_block_constraints = depends_on_block_constraints(&box_size.block) ||
|
|
||||||
depends_on_block_constraints(&min_size.block) ||
|
|
||||||
depends_on_block_constraints(&max_size.block) ||
|
|
||||||
self.depends_on_block_constraints_due_to_relative_positioning(writing_mode);
|
|
||||||
|
|
||||||
let box_size = box_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
|
||||||
let content_box_size = self
|
|
||||||
.content_box_size_for_box_size(box_size, &pbm)
|
|
||||||
.map(|v| v.map(Au::from));
|
|
||||||
let min_size = min_size.percentages_relative_to_basis(&containing_block_size_auto_is_zero);
|
|
||||||
let content_min_box_size = self
|
|
||||||
.content_min_box_size_for_min_size(min_size, &pbm)
|
|
||||||
.map(|v| v.map(Au::from));
|
|
||||||
let max_size = max_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
|
||||||
let content_max_box_size = self
|
|
||||||
.content_max_box_size_for_max_size(max_size, &pbm)
|
|
||||||
.map(|v| v.map(Au::from));
|
|
||||||
ContentBoxSizesAndPBM {
|
|
||||||
content_box_sizes: LogicalVec2 {
|
|
||||||
block: Sizes::new(
|
|
||||||
content_box_size.block,
|
|
||||||
content_min_box_size.block,
|
|
||||||
content_max_box_size.block,
|
|
||||||
),
|
|
||||||
inline: Sizes::new(
|
|
||||||
content_box_size.inline,
|
|
||||||
content_min_box_size.inline,
|
|
||||||
content_max_box_size.inline,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
pbm,
|
|
||||||
depends_on_block_constraints,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin {
|
|
||||||
self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
|
||||||
containing_block.style.writing_mode,
|
|
||||||
containing_block.size.inline,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
|
||||||
&self,
|
|
||||||
writing_mode: WritingMode,
|
|
||||||
containing_block_inline_size: Au,
|
|
||||||
) -> PaddingBorderMargin {
|
|
||||||
let padding = self
|
|
||||||
.padding(writing_mode)
|
|
||||||
.percentages_relative_to(containing_block_inline_size);
|
|
||||||
let border = self.border_width(writing_mode);
|
|
||||||
let margin = self
|
|
||||||
.margin(writing_mode)
|
|
||||||
.percentages_relative_to(containing_block_inline_size);
|
|
||||||
PaddingBorderMargin {
|
|
||||||
padding_border_sums: LogicalVec2 {
|
|
||||||
inline: padding.inline_sum() + border.inline_sum(),
|
|
||||||
block: padding.block_sum() + border.block_sum(),
|
|
||||||
},
|
|
||||||
padding,
|
|
||||||
border,
|
|
||||||
margin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn padding(
|
|
||||||
&self,
|
|
||||||
containing_block_writing_mode: WritingMode,
|
|
||||||
) -> LogicalSides<LengthPercentage> {
|
|
||||||
if self.get_box().display.inside() == stylo::DisplayInside::Table &&
|
|
||||||
self.get_inherited_table().border_collapse == BorderCollapse::Collapse
|
|
||||||
{
|
|
||||||
// https://drafts.csswg.org/css-tables/#collapsed-style-overrides
|
|
||||||
// > The padding of the table-root is ignored (as if it was set to 0px).
|
|
||||||
return LogicalSides::zero();
|
|
||||||
}
|
|
||||||
let padding = self.get_padding().clone();
|
|
||||||
LogicalSides::from_physical(
|
|
||||||
&PhysicalSides::new(
|
|
||||||
padding.padding_top.0,
|
|
||||||
padding.padding_right.0,
|
|
||||||
padding.padding_bottom.0,
|
|
||||||
padding.padding_left.0,
|
|
||||||
),
|
|
||||||
containing_block_writing_mode,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn border_style_color(
|
fn border_style_color(
|
||||||
&self,
|
&self,
|
||||||
containing_block_writing_mode: WritingMode,
|
containing_block_writing_mode: WritingMode,
|
||||||
|
@ -578,36 +442,6 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn border_width(&self, containing_block_writing_mode: WritingMode) -> LogicalSides<Au> {
|
|
||||||
let border = self.get_border();
|
|
||||||
if self.get_box().display.inside() == stylo::DisplayInside::Table &&
|
|
||||||
!matches!(self.pseudo(), Some(PseudoElement::ServoTableGrid)) &&
|
|
||||||
self.get_inherited_table().border_collapse == BorderCollapse::Collapse
|
|
||||||
{
|
|
||||||
// For tables in collapsed-borders mode we halve the border widths, because
|
|
||||||
// > in this model, the width of the table includes half the table border.
|
|
||||||
// https://www.w3.org/TR/CSS22/tables.html#collapsing-borders
|
|
||||||
return LogicalSides::from_physical(
|
|
||||||
&PhysicalSides::new(
|
|
||||||
border.border_top_width / 2,
|
|
||||||
border.border_right_width / 2,
|
|
||||||
border.border_bottom_width / 2,
|
|
||||||
border.border_left_width / 2,
|
|
||||||
),
|
|
||||||
containing_block_writing_mode,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
LogicalSides::from_physical(
|
|
||||||
&PhysicalSides::new(
|
|
||||||
border.border_top_width,
|
|
||||||
border.border_right_width,
|
|
||||||
border.border_bottom_width,
|
|
||||||
border.border_left_width,
|
|
||||||
),
|
|
||||||
containing_block_writing_mode,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>> {
|
fn physical_margin(&self) -> PhysicalSides<LengthPercentageOrAuto<'_>> {
|
||||||
fn convert(inset: &Margin) -> LengthPercentageOrAuto<'_> {
|
fn convert(inset: &Margin) -> LengthPercentageOrAuto<'_> {
|
||||||
match inset {
|
match inset {
|
||||||
|
@ -969,6 +803,183 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) enum LayoutStyle<'a> {
|
||||||
|
Default(&'a ComputedValues),
|
||||||
|
Table(&'a ComputedValues),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutStyle<'_> {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn style(&self) -> &ComputedValues {
|
||||||
|
match self {
|
||||||
|
Self::Default(style) => style,
|
||||||
|
Self::Table(style) => style,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn content_box_sizes_and_padding_border_margin(
|
||||||
|
&self,
|
||||||
|
containing_block: &IndefiniteContainingBlock,
|
||||||
|
) -> ContentBoxSizesAndPBM {
|
||||||
|
// <https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution>
|
||||||
|
// If max size properties or preferred size properties are set to a value containing
|
||||||
|
// indefinite percentages, we treat the entire value as the initial value of the property.
|
||||||
|
// However, for min size properties, as well as for margins and paddings,
|
||||||
|
// we instead resolve indefinite percentages against zero.
|
||||||
|
let containing_block_size = containing_block.size.map(|value| value.non_auto());
|
||||||
|
let containing_block_size_auto_is_zero =
|
||||||
|
containing_block_size.map(|value| value.unwrap_or_else(Au::zero));
|
||||||
|
let writing_mode = containing_block.writing_mode;
|
||||||
|
let pbm = self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||||
|
writing_mode,
|
||||||
|
containing_block.size.inline.auto_is(Au::zero),
|
||||||
|
);
|
||||||
|
let style = self.style();
|
||||||
|
let box_size = style.box_size(writing_mode);
|
||||||
|
let min_size = style.min_box_size(writing_mode);
|
||||||
|
let max_size = style.max_box_size(writing_mode);
|
||||||
|
let depends_on_block_constraints = |size: &Size<LengthPercentage>| {
|
||||||
|
match size {
|
||||||
|
// fit-content is like clamp(min-content, stretch, max-content), but currently
|
||||||
|
// min-content and max-content have the same behavior in the block axis,
|
||||||
|
// so there is no dependency on block constraints.
|
||||||
|
// TODO: for flex and grid layout, min-content and max-content should be different.
|
||||||
|
// TODO: We are assuming that Size::Initial doesn't stretch. However, it may actually
|
||||||
|
// stretch flex and grid items depending on the CSS Align properties, in that case
|
||||||
|
// the caller needs to take care of it.
|
||||||
|
Size::Stretch => true,
|
||||||
|
Size::Numeric(length_percentage) => length_percentage.has_percentage(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let depends_on_block_constraints = depends_on_block_constraints(&box_size.block) ||
|
||||||
|
depends_on_block_constraints(&min_size.block) ||
|
||||||
|
depends_on_block_constraints(&max_size.block) ||
|
||||||
|
style.depends_on_block_constraints_due_to_relative_positioning(writing_mode);
|
||||||
|
|
||||||
|
let box_size = box_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
||||||
|
let content_box_size = style
|
||||||
|
.content_box_size_for_box_size(box_size, &pbm)
|
||||||
|
.map(|v| v.map(Au::from));
|
||||||
|
let min_size = min_size.percentages_relative_to_basis(&containing_block_size_auto_is_zero);
|
||||||
|
let content_min_box_size = style
|
||||||
|
.content_min_box_size_for_min_size(min_size, &pbm)
|
||||||
|
.map(|v| v.map(Au::from));
|
||||||
|
let max_size = max_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
||||||
|
let content_max_box_size = style
|
||||||
|
.content_max_box_size_for_max_size(max_size, &pbm)
|
||||||
|
.map(|v| v.map(Au::from));
|
||||||
|
ContentBoxSizesAndPBM {
|
||||||
|
content_box_sizes: LogicalVec2 {
|
||||||
|
block: Sizes::new(
|
||||||
|
content_box_size.block,
|
||||||
|
content_min_box_size.block,
|
||||||
|
content_max_box_size.block,
|
||||||
|
),
|
||||||
|
inline: Sizes::new(
|
||||||
|
content_box_size.inline,
|
||||||
|
content_min_box_size.inline,
|
||||||
|
content_max_box_size.inline,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
pbm,
|
||||||
|
depends_on_block_constraints,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn padding_border_margin(
|
||||||
|
&self,
|
||||||
|
containing_block: &ContainingBlock,
|
||||||
|
) -> PaddingBorderMargin {
|
||||||
|
self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||||
|
containing_block.style.writing_mode,
|
||||||
|
containing_block.size.inline,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||||
|
&self,
|
||||||
|
writing_mode: WritingMode,
|
||||||
|
containing_block_inline_size: Au,
|
||||||
|
) -> PaddingBorderMargin {
|
||||||
|
let padding = self
|
||||||
|
.padding(writing_mode)
|
||||||
|
.percentages_relative_to(containing_block_inline_size);
|
||||||
|
let style = self.style();
|
||||||
|
let border = self.border_width(writing_mode);
|
||||||
|
let margin = style
|
||||||
|
.margin(writing_mode)
|
||||||
|
.percentages_relative_to(containing_block_inline_size);
|
||||||
|
PaddingBorderMargin {
|
||||||
|
padding_border_sums: LogicalVec2 {
|
||||||
|
inline: padding.inline_sum() + border.inline_sum(),
|
||||||
|
block: padding.block_sum() + border.block_sum(),
|
||||||
|
},
|
||||||
|
padding,
|
||||||
|
border,
|
||||||
|
margin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn padding(
|
||||||
|
&self,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> LogicalSides<LengthPercentage> {
|
||||||
|
let style = self.style();
|
||||||
|
if matches!(self, Self::Table(_)) &&
|
||||||
|
style.get_inherited_table().border_collapse == BorderCollapse::Collapse
|
||||||
|
{
|
||||||
|
// https://drafts.csswg.org/css-tables/#collapsed-style-overrides
|
||||||
|
// > The padding of the table-root is ignored (as if it was set to 0px).
|
||||||
|
return LogicalSides::zero();
|
||||||
|
}
|
||||||
|
let padding = self.style().get_padding().clone();
|
||||||
|
LogicalSides::from_physical(
|
||||||
|
&PhysicalSides::new(
|
||||||
|
padding.padding_top.0,
|
||||||
|
padding.padding_right.0,
|
||||||
|
padding.padding_bottom.0,
|
||||||
|
padding.padding_left.0,
|
||||||
|
),
|
||||||
|
containing_block_writing_mode,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn border_width(
|
||||||
|
&self,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> LogicalSides<Au> {
|
||||||
|
let style = self.style();
|
||||||
|
let border = style.get_border();
|
||||||
|
if matches!(self, Self::Table(_)) &&
|
||||||
|
style.get_inherited_table().border_collapse == BorderCollapse::Collapse
|
||||||
|
{
|
||||||
|
// For tables in collapsed-borders mode we halve the border widths, because
|
||||||
|
// > in this model, the width of the table includes half the table border.
|
||||||
|
// https://www.w3.org/TR/CSS22/tables.html#collapsing-borders
|
||||||
|
return LogicalSides::from_physical(
|
||||||
|
&PhysicalSides::new(
|
||||||
|
border.border_top_width / 2,
|
||||||
|
border.border_right_width / 2,
|
||||||
|
border.border_bottom_width / 2,
|
||||||
|
border.border_left_width / 2,
|
||||||
|
),
|
||||||
|
containing_block_writing_mode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
LogicalSides::from_physical(
|
||||||
|
&PhysicalSides::new(
|
||||||
|
border.border_top_width,
|
||||||
|
border.border_right_width,
|
||||||
|
border.border_bottom_width,
|
||||||
|
border.border_left_width,
|
||||||
|
),
|
||||||
|
containing_block_writing_mode,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<stylo::Display> for Display {
|
impl From<stylo::Display> for Display {
|
||||||
fn from(packed: stylo::Display) -> Self {
|
fn from(packed: stylo::Display) -> Self {
|
||||||
let outside = packed.outside();
|
let outside = packed.outside();
|
||||||
|
|
|
@ -38,7 +38,9 @@ use crate::geom::{
|
||||||
};
|
};
|
||||||
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
|
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{BorderStyleColor, Clamp, ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{
|
||||||
|
BorderStyleColor, Clamp, ComputedValuesExt, LayoutStyle, PaddingBorderMargin,
|
||||||
|
};
|
||||||
use crate::table::{SpecificTableOrTableCellInfo, TableSlotCoordinates};
|
use crate::table::{SpecificTableOrTableCellInfo, TableSlotCoordinates};
|
||||||
use crate::{
|
use crate::{
|
||||||
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, WritingMode,
|
ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, WritingMode,
|
||||||
|
@ -121,9 +123,12 @@ impl CollapsedBorder {
|
||||||
Self { style_color, width }
|
Self { style_color, width }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_style(style: &ComputedValues, writing_mode: WritingMode) -> LogicalSides<Self> {
|
fn from_layout_style(
|
||||||
let border_style_color = style.border_style_color(writing_mode);
|
layout_style: &LayoutStyle,
|
||||||
let border_width = style.border_width(writing_mode);
|
writing_mode: WritingMode,
|
||||||
|
) -> LogicalSides<Self> {
|
||||||
|
let border_style_color = layout_style.style().border_style_color(writing_mode);
|
||||||
|
let border_width = layout_style.border_width(writing_mode);
|
||||||
LogicalSides {
|
LogicalSides {
|
||||||
inline_start: Self::new(border_style_color.inline_start, border_width.inline_start),
|
inline_start: Self::new(border_style_color.inline_start, border_width.inline_start),
|
||||||
inline_end: Self::new(border_style_color.inline_end, border_width.inline_end),
|
inline_end: Self::new(border_style_color.inline_end, border_width.inline_end),
|
||||||
|
@ -285,12 +290,10 @@ impl<'a> TableLayout<'a> {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = cell
|
let layout_style = cell.layout_style();
|
||||||
.base
|
let padding = layout_style
|
||||||
.style
|
|
||||||
.padding(writing_mode)
|
.padding(writing_mode)
|
||||||
.percentages_relative_to(Au::zero());
|
.percentages_relative_to(Au::zero());
|
||||||
|
|
||||||
let border = self
|
let border = self
|
||||||
.get_collapsed_border_widths_for_area(LogicalSides {
|
.get_collapsed_border_widths_for_area(LogicalSides {
|
||||||
inline_start: column_index,
|
inline_start: column_index,
|
||||||
|
@ -298,7 +301,7 @@ impl<'a> TableLayout<'a> {
|
||||||
block_start: row_index,
|
block_start: row_index,
|
||||||
block_end: row_index + cell.rowspan,
|
block_end: row_index + cell.rowspan,
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| cell.base.style.border_width(writing_mode));
|
.unwrap_or_else(|| layout_style.border_width(writing_mode));
|
||||||
|
|
||||||
let padding_border_sums = LogicalVec2 {
|
let padding_border_sums = LogicalVec2 {
|
||||||
inline: padding.inline_sum() + border.inline_sum(),
|
inline: padding.inline_sum() + border.inline_sum(),
|
||||||
|
@ -1217,16 +1220,14 @@ impl<'a> TableLayout<'a> {
|
||||||
self.get_collapsed_border_style_colors_for_area(area),
|
self.get_collapsed_border_style_colors_for_area(area),
|
||||||
self.table.style.writing_mode,
|
self.table.style.writing_mode,
|
||||||
);
|
);
|
||||||
|
let layout_style = cell.layout_style();
|
||||||
let border = self
|
let border = self
|
||||||
.get_collapsed_border_widths_for_area(area)
|
.get_collapsed_border_widths_for_area(area)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
cell.base
|
layout_style
|
||||||
.style
|
|
||||||
.border_width(containing_block_for_table.style.writing_mode)
|
.border_width(containing_block_for_table.style.writing_mode)
|
||||||
});
|
});
|
||||||
let padding: LogicalSides<Au> = cell
|
let padding: LogicalSides<Au> = layout_style
|
||||||
.base
|
|
||||||
.style
|
|
||||||
.padding(containing_block_for_table.style.writing_mode)
|
.padding(containing_block_for_table.style.writing_mode)
|
||||||
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
||||||
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
|
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
|
||||||
|
@ -1651,9 +1652,8 @@ impl<'a> TableLayout<'a> {
|
||||||
containing_block_for_table: &ContainingBlock,
|
containing_block_for_table: &ContainingBlock,
|
||||||
) -> IndependentLayout {
|
) -> IndependentLayout {
|
||||||
let table_writing_mode = containing_block_for_children.style.writing_mode;
|
let table_writing_mode = containing_block_for_children.style.writing_mode;
|
||||||
self.pbm = self
|
let layout_style = self.table.layout_style();
|
||||||
.table
|
self.pbm = layout_style
|
||||||
.style
|
|
||||||
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||||
table_writing_mode,
|
table_writing_mode,
|
||||||
containing_block_for_table.size.inline,
|
containing_block_for_table.size.inline,
|
||||||
|
@ -1690,9 +1690,7 @@ impl<'a> TableLayout<'a> {
|
||||||
let offset_from_wrapper = -self.pbm.padding - self.pbm.border;
|
let offset_from_wrapper = -self.pbm.padding - self.pbm.border;
|
||||||
let mut current_block_offset = offset_from_wrapper.block_start;
|
let mut current_block_offset = offset_from_wrapper.block_start;
|
||||||
|
|
||||||
let depends_on_block_constraints = self
|
let depends_on_block_constraints = layout_style
|
||||||
.table
|
|
||||||
.style
|
|
||||||
.content_box_sizes_and_padding_border_margin(&containing_block_for_table.into())
|
.content_box_sizes_and_padding_border_margin(&containing_block_for_table.into())
|
||||||
.depends_on_block_constraints;
|
.depends_on_block_constraints;
|
||||||
|
|
||||||
|
@ -2234,8 +2232,8 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut apply_border =
|
let mut apply_border =
|
||||||
|style: &ComputedValues, block: &Range<usize>, inline: &Range<usize>| {
|
|layout_style: &LayoutStyle, block: &Range<usize>, inline: &Range<usize>| {
|
||||||
let border = CollapsedBorder::from_style(style, writing_mode);
|
let border = CollapsedBorder::from_layout_style(layout_style, writing_mode);
|
||||||
collapsed_borders.block[block.start].max_assign(&border.block_start, inline);
|
collapsed_borders.block[block.start].max_assign(&border.block_start, inline);
|
||||||
collapsed_borders.block[block.end].max_assign(&border.block_end, inline);
|
collapsed_borders.block[block.end].max_assign(&border.block_end, inline);
|
||||||
collapsed_borders.inline[inline.start].max_assign(&border.inline_start, block);
|
collapsed_borders.inline[inline.start].max_assign(&border.inline_start, block);
|
||||||
|
@ -2243,18 +2241,34 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
let all_rows = 0..self.table.size.height;
|
let all_rows = 0..self.table.size.height;
|
||||||
let all_columns = 0..self.table.size.width;
|
let all_columns = 0..self.table.size.width;
|
||||||
apply_border(&self.table.grid_style, &all_rows, &all_columns);
|
apply_border(&self.table.layout_style_for_grid(), &all_rows, &all_columns);
|
||||||
for column_group in &self.table.column_groups {
|
for column_group in &self.table.column_groups {
|
||||||
apply_border(&column_group.style, &all_rows, &column_group.track_range);
|
apply_border(
|
||||||
|
&column_group.layout_style(),
|
||||||
|
&all_rows,
|
||||||
|
&column_group.track_range,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (column_index, column) in self.table.columns.iter().enumerate() {
|
for (column_index, column) in self.table.columns.iter().enumerate() {
|
||||||
apply_border(&column.style, &all_rows, &(column_index..column_index + 1));
|
apply_border(
|
||||||
|
&column.layout_style(),
|
||||||
|
&all_rows,
|
||||||
|
&(column_index..column_index + 1),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for row_group in &self.table.row_groups {
|
for row_group in &self.table.row_groups {
|
||||||
apply_border(&row_group.style, &row_group.track_range, &all_columns);
|
apply_border(
|
||||||
|
&row_group.layout_style(),
|
||||||
|
&row_group.track_range,
|
||||||
|
&all_columns,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (row_index, row) in self.table.rows.iter().enumerate() {
|
for (row_index, row) in self.table.rows.iter().enumerate() {
|
||||||
apply_border(&row.style, &(row_index..row_index + 1), &all_columns);
|
apply_border(
|
||||||
|
&row.layout_style(),
|
||||||
|
&(row_index..row_index + 1),
|
||||||
|
&all_columns,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for row_index in 0..self.table.size.height {
|
for row_index in 0..self.table.size.height {
|
||||||
for column_index in 0..self.table.size.width {
|
for column_index in 0..self.table.size.width {
|
||||||
|
@ -2264,7 +2278,7 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
apply_border(
|
apply_border(
|
||||||
&cell.base.style,
|
&cell.layout_style(),
|
||||||
&(row_index..row_index + cell.rowspan),
|
&(row_index..row_index + cell.rowspan),
|
||||||
&(column_index..column_index + cell.colspan),
|
&(column_index..column_index + cell.colspan),
|
||||||
);
|
);
|
||||||
|
@ -2752,9 +2766,9 @@ impl ComputeInlineContentSizes for Table {
|
||||||
constraint_space: &ConstraintSpace,
|
constraint_space: &ConstraintSpace,
|
||||||
) -> InlineContentSizesResult {
|
) -> InlineContentSizesResult {
|
||||||
let writing_mode = constraint_space.writing_mode;
|
let writing_mode = constraint_space.writing_mode;
|
||||||
|
let layout_style = self.layout_style();
|
||||||
let mut layout = TableLayout::new(self);
|
let mut layout = TableLayout::new(self);
|
||||||
layout.pbm = self
|
layout.pbm = layout_style
|
||||||
.style
|
|
||||||
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||||
writing_mode,
|
writing_mode,
|
||||||
Au::zero(),
|
Au::zero(),
|
||||||
|
@ -2769,11 +2783,10 @@ impl ComputeInlineContentSizes for Table {
|
||||||
// Padding and border should apply to the table grid, but they will be taken into
|
// Padding and border should apply to the table grid, but they will be taken into
|
||||||
// account when computing the inline content sizes of the table wrapper (our parent), so
|
// account when computing the inline content sizes of the table wrapper (our parent), so
|
||||||
// this code removes their contribution from the inline content size of the caption.
|
// this code removes their contribution from the inline content size of the caption.
|
||||||
let padding = self
|
let padding = layout_style
|
||||||
.style
|
|
||||||
.padding(writing_mode)
|
.padding(writing_mode)
|
||||||
.percentages_relative_to(Au::zero());
|
.percentages_relative_to(Au::zero());
|
||||||
let border = self.style.border_width(writing_mode);
|
let border = layout_style.border_width(writing_mode);
|
||||||
caption_minimum_inline_size -= padding.inline_sum() + border.inline_sum();
|
caption_minimum_inline_size -= padding.inline_sum() + border.inline_sum();
|
||||||
table_content_sizes
|
table_content_sizes
|
||||||
.min_content
|
.min_content
|
||||||
|
@ -2790,7 +2803,38 @@ impl ComputeInlineContentSizes for Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Table(&self.style)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style_for_grid(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.grid_style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableTrack {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableTrackGroup {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TableSlotCell {
|
impl TableSlotCell {
|
||||||
|
#[inline]
|
||||||
|
fn layout_style(&self) -> LayoutStyle {
|
||||||
|
self.contents.layout_style(&self.base)
|
||||||
|
}
|
||||||
|
|
||||||
fn effective_vertical_align(&self) -> VerticalAlignKeyword {
|
fn effective_vertical_align(&self) -> VerticalAlignKeyword {
|
||||||
match self.base.style.clone_vertical_align() {
|
match self.base.style.clone_vertical_align() {
|
||||||
VerticalAlign::Keyword(VerticalAlignKeyword::Top) => VerticalAlignKeyword::Top,
|
VerticalAlign::Keyword(VerticalAlignKeyword::Top) => VerticalAlignKeyword::Top,
|
||||||
|
|
|
@ -27,7 +27,7 @@ use crate::geom::{
|
||||||
};
|
};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::ComputedValuesExt;
|
use crate::style_ext::LayoutStyle;
|
||||||
use crate::{ConstraintSpace, ContainingBlock, ContainingBlockSize};
|
use crate::{ConstraintSpace, ContainingBlock, ContainingBlockSize};
|
||||||
|
|
||||||
const DUMMY_NODE_ID: taffy::NodeId = taffy::NodeId::new(u64::MAX);
|
const DUMMY_NODE_ID: taffy::NodeId = taffy::NodeId::new(u64::MAX);
|
||||||
|
@ -136,7 +136,9 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
|
||||||
let style = independent_context.style();
|
let style = independent_context.style();
|
||||||
|
|
||||||
// Adjust known_dimensions from border box to content box
|
// Adjust known_dimensions from border box to content box
|
||||||
let pbm = style.padding_border_margin(containing_block);
|
let pbm = independent_context
|
||||||
|
.layout_style()
|
||||||
|
.padding_border_margin(containing_block);
|
||||||
let pb_sum = pbm.padding_border_sums.map(|v| v.to_f32_px());
|
let pb_sum = pbm.padding_border_sums.map(|v| v.to_f32_px());
|
||||||
let margin_sum = pbm.margin.auto_is(Au::zero).sum().map(|v| v.to_f32_px());
|
let margin_sum = pbm.margin.auto_is(Au::zero).sum().map(|v| v.to_f32_px());
|
||||||
let content_box_inset = pb_sum + margin_sum;
|
let content_box_inset = pb_sum + margin_sum;
|
||||||
|
@ -387,7 +389,8 @@ impl ComputeInlineContentSizes for TaffyContainer {
|
||||||
_ => panic!("Servo is only configured to use Taffy for CSS Grid layout"),
|
_ => panic!("Servo is only configured to use Taffy for CSS Grid layout"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pb_sums = style
|
let pb_sums = self
|
||||||
|
.layout_style()
|
||||||
.padding_border_margin(containing_block)
|
.padding_border_margin(containing_block)
|
||||||
.padding_border_sums;
|
.padding_border_sums;
|
||||||
|
|
||||||
|
@ -428,7 +431,7 @@ impl TaffyContainer {
|
||||||
let container_style = &content_box_size_override.style;
|
let container_style = &content_box_size_override.style;
|
||||||
let align_items = container_style.clone_align_items();
|
let align_items = container_style.clone_align_items();
|
||||||
let justify_items = container_style.clone_justify_items();
|
let justify_items = container_style.clone_justify_items();
|
||||||
let pbm = container_style.padding_border_margin(containing_block);
|
let pbm = self.layout_style().padding_border_margin(containing_block);
|
||||||
|
|
||||||
let known_dimensions = taffy::Size {
|
let known_dimensions = taffy::Size {
|
||||||
width: Some(
|
width: Some(
|
||||||
|
@ -625,4 +628,9 @@ impl TaffyContainer {
|
||||||
detailed_layout_info: container_ctx.detailed_layout_info,
|
detailed_layout_info: container_ctx.detailed_layout_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn layout_style(&self) -> LayoutStyle {
|
||||||
|
LayoutStyle::Default(&self.style)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue