mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
layout: Add an indefinite containing block for intrinsic sizing (#33204)
When computing the min-content or max-content size of an element we need to ignore `inline-size`, `min-inline-size` and `max-inline-size`. However, we should take the block-axis sizing properties into account. That's because the contents could have percentages depending on them, which can then affect their inline size via an aspect ratio. Therefore, this patch adds `IndefiniteContainingBlock`, which is similar to `ContainingBlock`, but it allows an indefinite inline-size. This struct is then passed arround during intrinsic sizing. More refinement will be needed in follow-up patches in order to fully address the problem. Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
46dbe4ce32
commit
93abdf7cb5
29 changed files with 600 additions and 332 deletions
|
@ -9,7 +9,6 @@ use app_units::Au;
|
|||
use atomic_refcell::AtomicRefMut;
|
||||
use itertools::izip;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::longhands::align_items::computed_value::T as AlignItems;
|
||||
use style::properties::longhands::align_self::computed_value::T as AlignSelf;
|
||||
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
|
||||
|
@ -35,7 +34,7 @@ use crate::positioned::{
|
|||
};
|
||||
use crate::sizing::{ContentSizes, IntrinsicSizingMode};
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
// FIMXE: “Flex items […] `z-index` values other than `auto` create a stacking context
|
||||
// even if `position` is `static` (behaving exactly as if `position` were `relative`).”
|
||||
|
@ -305,19 +304,27 @@ impl FlexContainer {
|
|||
pub fn inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
match self.config.flex_axis {
|
||||
FlexAxis::Row => self.main_content_sizes(layout_context, writing_mode, || {
|
||||
FlexAxis::Row => {
|
||||
self.main_content_sizes(layout_context, containing_block_for_children, || {
|
||||
unreachable!(
|
||||
"Unexpected FlexContext query during row flex intrinsic size calculation."
|
||||
)
|
||||
}),
|
||||
FlexAxis::Column => self.cross_content_sizes(layout_context),
|
||||
})
|
||||
},
|
||||
FlexAxis::Column => {
|
||||
self.cross_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn cross_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes {
|
||||
fn cross_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
// <https://drafts.csswg.org/css-flexbox/#intrinsic-cross-sizes>
|
||||
assert_eq!(
|
||||
self.config.flex_axis,
|
||||
|
@ -331,10 +338,15 @@ impl FlexContainer {
|
|||
FlexLevelBox::FlexItem(item) => {
|
||||
// TODO: For the max-content size we should distribute items into
|
||||
// columns, and sum the column sizes and gaps.
|
||||
content_sizes.max_assign(
|
||||
item.independent_formatting_context
|
||||
.inline_content_sizes(layout_context),
|
||||
);
|
||||
// TODO: Use the proper automatic minimum size.
|
||||
let ifc = &mut item.independent_formatting_context;
|
||||
content_sizes.max_assign(ifc.inline_content_sizes(
|
||||
layout_context,
|
||||
&containing_block_for_children.new_for_intrinsic_inline_size_of_child(
|
||||
&ifc.style().clone(),
|
||||
&LogicalVec2::zero(),
|
||||
),
|
||||
));
|
||||
},
|
||||
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(_) => {},
|
||||
}
|
||||
|
@ -345,7 +357,7 @@ impl FlexContainer {
|
|||
fn main_content_sizes<'a>(
|
||||
&self,
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
flex_context_getter: impl Fn() -> &'a FlexContext<'a>,
|
||||
) -> ContentSizes {
|
||||
// - TODO: calculate intrinsic cross sizes when container is a column
|
||||
|
@ -372,7 +384,7 @@ impl FlexContainer {
|
|||
|
||||
let info = item.main_content_size_info(
|
||||
layout_context,
|
||||
writing_mode,
|
||||
containing_block_for_children,
|
||||
container_is_horizontal,
|
||||
self.config.flex_axis,
|
||||
self.config.main_start_cross_start_sides_are,
|
||||
|
@ -514,7 +526,7 @@ impl FlexContainer {
|
|||
let container_main_size = match self.config.flex_axis {
|
||||
FlexAxis::Row => containing_block.inline_size,
|
||||
FlexAxis::Column => containing_block.block_size.auto_is(|| {
|
||||
self.main_content_sizes(layout_context, self.style.writing_mode, || &flex_context)
|
||||
self.main_content_sizes(layout_context, &containing_block.into(), || &flex_context)
|
||||
.max_content
|
||||
}),
|
||||
};
|
||||
|
@ -905,16 +917,17 @@ fn allocate_free_cross_space_for_flex_line(
|
|||
impl<'a> FlexItem<'a> {
|
||||
fn new(flex_context: &FlexContext, box_: &'a mut FlexItemBox) -> Self {
|
||||
let containing_block = flex_context.containing_block;
|
||||
let parent_writing_mode = containing_block.effective_writing_mode();
|
||||
let item_writing_mode = box_.style().effective_writing_mode();
|
||||
|
||||
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
|
||||
assert_eq!(
|
||||
containing_block.effective_writing_mode(),
|
||||
box_.style().effective_writing_mode(),
|
||||
parent_writing_mode, item_writing_mode,
|
||||
"Mixed writing modes are not supported yet"
|
||||
);
|
||||
|
||||
let container_is_horizontal = containing_block.effective_writing_mode().is_horizontal();
|
||||
let item_is_horizontal = box_.style().effective_writing_mode().is_horizontal();
|
||||
let container_is_horizontal = parent_writing_mode.is_horizontal();
|
||||
let item_is_horizontal = item_writing_mode.is_horizontal();
|
||||
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
|
||||
container_is_horizontal,
|
||||
item_is_horizontal,
|
||||
|
@ -979,6 +992,8 @@ impl<'a> FlexItem<'a> {
|
|||
flex_context.container_definite_inner_size,
|
||||
cross_axis_is_item_block_axis,
|
||||
flex_relative_content_box_size,
|
||||
flex_relative_content_min_size,
|
||||
flex_relative_content_max_size,
|
||||
padding_border,
|
||||
|item| {
|
||||
let min_size = flex_context
|
||||
|
@ -1585,6 +1600,7 @@ impl FlexItem<'_> {
|
|||
);
|
||||
// … and also the item’s inline axis.
|
||||
|
||||
let flex_axis = flex_context.config.flex_axis;
|
||||
match &mut self.box_.independent_formatting_context {
|
||||
IndependentFormattingContext::Replaced(replaced) => {
|
||||
let pbm = replaced.style.padding_border_margin(containing_block);
|
||||
|
@ -1602,11 +1618,7 @@ impl FlexItem<'_> {
|
|||
box_size,
|
||||
&pbm,
|
||||
);
|
||||
let cross_size = flex_context
|
||||
.config
|
||||
.flex_axis
|
||||
.vec2_to_flex_relative(size)
|
||||
.cross;
|
||||
let cross_size = flex_axis.vec2_to_flex_relative(size).cross;
|
||||
let fragments = replaced.contents.make_fragments(
|
||||
&replaced.style,
|
||||
size.to_physical_size(container_writing_mode),
|
||||
|
@ -1642,23 +1654,34 @@ impl FlexItem<'_> {
|
|||
.effective_writing_mode()
|
||||
.is_horizontal(),
|
||||
item_is_horizontal,
|
||||
flex_context.config.flex_axis,
|
||||
flex_axis,
|
||||
);
|
||||
|
||||
let (inline_size, block_size) = if cross_axis_is_item_block_axis {
|
||||
(used_main_size, cross_size)
|
||||
} else {
|
||||
(
|
||||
cross_size.auto_is(|| {
|
||||
let content_contributions = non_replaced.outer_inline_content_sizes(
|
||||
flex_context.layout_context,
|
||||
container_writing_mode,
|
||||
Au::zero,
|
||||
let style = non_replaced.style.clone();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(
|
||||
&style,
|
||||
AuOrAuto::LengthPercentage(used_main_size),
|
||||
);
|
||||
containing_block
|
||||
.inline_size
|
||||
let content_contributions = non_replaced
|
||||
.inline_content_sizes(
|
||||
flex_context.layout_context,
|
||||
&containing_block_for_children,
|
||||
)
|
||||
.map(|size| {
|
||||
size.clamp_between_extremums(
|
||||
self.content_min_size.cross,
|
||||
self.content_max_size.cross,
|
||||
)
|
||||
});
|
||||
(containing_block.inline_size - self.pbm_auto_is_zero.cross)
|
||||
.min(content_contributions.max_content)
|
||||
.max(content_contributions.min_content) -
|
||||
self.pbm_auto_is_zero.cross
|
||||
.max(content_contributions.min_content)
|
||||
}),
|
||||
// The main size of a flex item is considered to be definite if its flex basis is definite
|
||||
// or the flex container has a definite main size.
|
||||
|
@ -1874,7 +1897,7 @@ impl FlexItemBox {
|
|||
fn main_content_size_info<'a>(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
container_writing_mode: WritingMode,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
container_is_horizontal: bool,
|
||||
flex_axis: FlexAxis,
|
||||
main_start_cross_start: MainStartCrossStart,
|
||||
|
@ -1886,25 +1909,8 @@ impl FlexItemBox {
|
|||
let cross_axis_is_item_block_axis =
|
||||
cross_axis_is_item_block_axis(container_is_horizontal, item_is_horizontal, flex_axis);
|
||||
|
||||
let pbm = style.padding_border_margin_for_intrinsic_size(item_writing_mode);
|
||||
let box_size = style
|
||||
.box_size(item_writing_mode)
|
||||
.map(|v| v.percentage_relative_to(Length::zero()));
|
||||
let content_box_size = style
|
||||
.content_box_size_for_box_size(box_size, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let min_size = style
|
||||
.min_box_size(item_writing_mode)
|
||||
.map(|v| v.percentage_relative_to(Length::zero()));
|
||||
let content_min_size = style
|
||||
.content_min_box_size_for_min_size(min_size, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let max_size = style
|
||||
.max_box_size(item_writing_mode)
|
||||
.map(|v| v.map(|v| v.percentage_relative_to(Length::zero())));
|
||||
let content_max_size = style
|
||||
.content_max_box_size_for_max_size(max_size, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let (content_box_size, content_min_size, content_max_size, pbm) =
|
||||
style.content_box_sizes_and_padding_border_margin(containing_block);
|
||||
let automatic_min_size = self.automatic_min_size(
|
||||
layout_context,
|
||||
cross_axis_is_item_block_axis,
|
||||
|
@ -1942,9 +1948,11 @@ impl FlexItemBox {
|
|||
let content_contribution_sizes = match flex_axis {
|
||||
FlexAxis::Row => self
|
||||
.independent_formatting_context
|
||||
.outer_inline_content_sizes(layout_context, container_writing_mode, || {
|
||||
automatic_min_size
|
||||
}),
|
||||
.outer_inline_content_sizes(
|
||||
layout_context,
|
||||
containing_block,
|
||||
&content_min_size_no_auto,
|
||||
),
|
||||
FlexAxis::Column => self
|
||||
.layout_for_block_content_size(
|
||||
flex_context_getter(),
|
||||
|
@ -1982,6 +1990,8 @@ impl FlexItemBox {
|
|||
},
|
||||
cross_axis_is_item_block_axis,
|
||||
content_box_size,
|
||||
content_min_size_no_auto,
|
||||
content_max_size,
|
||||
padding_border,
|
||||
block_content_size_callback,
|
||||
);
|
||||
|
@ -2142,8 +2152,14 @@ impl FlexItemBox {
|
|||
// > preferred aspect ratio, by any definite minimum and maximum cross sizes converted through the
|
||||
// > aspect ratio.
|
||||
let main_content_size = if cross_axis_is_item_block_axis {
|
||||
let block_size = content_box_size.cross.map(|v| {
|
||||
v.clamp_between_extremums(min_size.cross.auto_is(Au::zero), max_size.cross)
|
||||
});
|
||||
let style = self.independent_formatting_context.style().clone();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(&style, block_size);
|
||||
self.independent_formatting_context
|
||||
.inline_content_sizes(layout_context)
|
||||
.inline_content_sizes(layout_context, &containing_block_for_children)
|
||||
.min_content
|
||||
} else {
|
||||
block_content_size_callback(self)
|
||||
|
@ -2178,16 +2194,19 @@ impl FlexItemBox {
|
|||
container_definite_inner_size: FlexRelativeVec2<Option<Au>>,
|
||||
cross_axis_is_item_block_axis: bool,
|
||||
content_box_size: FlexRelativeVec2<AuOrAuto>,
|
||||
min_size: FlexRelativeVec2<Au>,
|
||||
max_size: FlexRelativeVec2<Option<Au>>,
|
||||
padding_border_sums: FlexRelativeVec2<Au>,
|
||||
block_content_size_callback: impl FnOnce(&mut FlexItemBox) -> Au,
|
||||
) -> (Au, bool) {
|
||||
let flex_item = &mut self.independent_formatting_context;
|
||||
let style = flex_item.style();
|
||||
|
||||
let used_flex_basis = match &flex_item.style().get_position().flex_basis {
|
||||
let used_flex_basis = match &style.get_position().flex_basis {
|
||||
FlexBasis::Content => FlexBasis::Content,
|
||||
FlexBasis::Size(Size::LengthPercentage(length_percentage)) => {
|
||||
let apply_box_sizing = |length: Au| {
|
||||
match flex_item.style().get_position().box_sizing {
|
||||
match style.get_position().box_sizing {
|
||||
BoxSizing::ContentBox => length,
|
||||
BoxSizing::BorderBox => {
|
||||
// This may make `length` negative,
|
||||
|
@ -2250,7 +2269,15 @@ impl FlexItemBox {
|
|||
let flex_basis = if cross_axis_is_item_block_axis {
|
||||
// The main axis is the inline axis, so we can get the content size from the normal
|
||||
// preferred widths calculation.
|
||||
flex_item.inline_content_sizes(layout_context).max_content
|
||||
let style = style.clone();
|
||||
let block_size = content_box_size
|
||||
.cross
|
||||
.map(|v| v.clamp_between_extremums(min_size.cross, max_size.cross));
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(&style, block_size);
|
||||
flex_item
|
||||
.inline_content_sizes(layout_context, &containing_block_for_children)
|
||||
.max_content
|
||||
} else {
|
||||
block_content_size_callback(self)
|
||||
};
|
||||
|
@ -2305,8 +2332,14 @@ impl FlexItemBox {
|
|||
if will_stretch {
|
||||
containing_block_inline_size_minus_pbm
|
||||
} else {
|
||||
let inline_content_sizes =
|
||||
non_replaced.inline_content_sizes(flex_context.layout_context);
|
||||
let style = non_replaced.style.clone();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style(&style);
|
||||
let inline_content_sizes = non_replaced.inline_content_sizes(
|
||||
flex_context.layout_context,
|
||||
&containing_block_for_children,
|
||||
);
|
||||
|
||||
containing_block_inline_size_minus_pbm
|
||||
.min(inline_content_sizes.max_content)
|
||||
.max(inline_content_sizes.min_content)
|
||||
|
|
|
@ -18,7 +18,7 @@ use servo_arc::Arc;
|
|||
use style::computed_values::float::T as FloatProperty;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Clear, Length};
|
||||
use style::values::computed::Clear;
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
|
||||
use crate::context::LayoutContext;
|
||||
|
@ -28,8 +28,8 @@ use crate::formatting_contexts::IndependentFormattingContext;
|
|||
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, CollapsedMargin};
|
||||
use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
|
||||
use crate::positioned::PositioningContext;
|
||||
use crate::style_ext::{ComputedValuesExt, DisplayInside, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, DisplayInside, PaddingBorderMargin};
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
/// A floating box.
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -905,35 +905,44 @@ impl FloatBox {
|
|||
IndependentFormattingContext::NonReplaced(ref mut non_replaced) => {
|
||||
// Calculate inline size.
|
||||
// https://drafts.csswg.org/css2/#float-width
|
||||
let box_size = non_replaced.style.content_box_size(containing_block, &pbm);
|
||||
let max_box_size = non_replaced
|
||||
.style
|
||||
.content_max_box_size(containing_block, &pbm);
|
||||
let min_box_size = non_replaced
|
||||
.style
|
||||
let style = non_replaced.style.clone();
|
||||
let box_size = style
|
||||
.content_box_size(containing_block, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let max_box_size = style
|
||||
.content_max_box_size(containing_block, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let min_box_size = style
|
||||
.content_min_box_size(containing_block, &pbm)
|
||||
.auto_is(Length::zero);
|
||||
.map(|v| v.map(Au::from))
|
||||
.auto_is(Au::zero);
|
||||
|
||||
let tentative_inline_size = box_size.inline.auto_is(|| {
|
||||
let available_size =
|
||||
containing_block.inline_size - pbm_sums.inline_sum();
|
||||
non_replaced
|
||||
.inline_content_sizes(layout_context)
|
||||
.shrink_to_fit(available_size)
|
||||
.into()
|
||||
});
|
||||
let inline_size = tentative_inline_size
|
||||
.clamp_between_extremums(min_box_size.inline, max_box_size.inline);
|
||||
let block_size = box_size.block.map(|size| {
|
||||
size.clamp_between_extremums(min_box_size.block, max_box_size.block)
|
||||
});
|
||||
let tentative_inline_size = box_size.inline.auto_is(|| {
|
||||
let available_size =
|
||||
containing_block.inline_size - pbm_sums.inline_sum();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(
|
||||
&style, block_size,
|
||||
);
|
||||
non_replaced
|
||||
.inline_content_sizes(
|
||||
layout_context,
|
||||
&containing_block_for_children,
|
||||
)
|
||||
.shrink_to_fit(available_size)
|
||||
});
|
||||
let inline_size = tentative_inline_size
|
||||
.clamp_between_extremums(min_box_size.inline, max_box_size.inline);
|
||||
|
||||
// Calculate block size.
|
||||
// https://drafts.csswg.org/css2/#block-root-margin
|
||||
// FIXME(pcwalton): Is a tree rank of zero correct here?
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
inline_size: inline_size.into(),
|
||||
block_size: block_size.map(|t| t.into()),
|
||||
inline_size,
|
||||
block_size,
|
||||
style: &non_replaced.style,
|
||||
};
|
||||
let independent_layout = non_replaced.layout(
|
||||
|
@ -944,13 +953,13 @@ impl FloatBox {
|
|||
);
|
||||
let (block_size, inline_size) =
|
||||
match independent_layout.content_inline_size_for_table {
|
||||
Some(inline_size) => (
|
||||
independent_layout.content_block_size.into(),
|
||||
inline_size.into(),
|
||||
),
|
||||
Some(inline_size) => {
|
||||
(independent_layout.content_block_size, inline_size)
|
||||
},
|
||||
None => (
|
||||
block_size.auto_is(|| {
|
||||
Length::from(independent_layout.content_block_size)
|
||||
independent_layout
|
||||
.content_block_size
|
||||
.clamp_between_extremums(
|
||||
min_box_size.block,
|
||||
max_box_size.block,
|
||||
|
@ -960,8 +969,8 @@ impl FloatBox {
|
|||
),
|
||||
};
|
||||
content_size = LogicalVec2 {
|
||||
inline: inline_size.into(),
|
||||
block: block_size.into(),
|
||||
inline: inline_size,
|
||||
block: block_size,
|
||||
};
|
||||
children = independent_layout.fragments;
|
||||
},
|
||||
|
|
|
@ -94,7 +94,6 @@ use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
|||
use style::computed_values::vertical_align::T as VerticalAlign;
|
||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||
use style::context::QuirksMode;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::style_structs::InheritedText;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Clear, Length};
|
||||
|
@ -128,7 +127,7 @@ use crate::geom::{LogicalRect, LogicalVec2, PhysicalRect, ToLogical};
|
|||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||
use crate::sizing::ContentSizes;
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
// From gfxFontConstants.h in Firefox.
|
||||
static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;
|
||||
|
@ -1557,9 +1556,9 @@ impl InlineFormattingContext {
|
|||
pub(super) fn inline_content_sizes(
|
||||
&self,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
ContentSizesComputation::compute(self, layout_context, containing_block_writing_mode)
|
||||
ContentSizesComputation::compute(self, layout_context, containing_block_for_children)
|
||||
}
|
||||
|
||||
pub(super) fn layout(
|
||||
|
@ -1954,13 +1953,19 @@ impl IndependentFormattingContext {
|
|||
.content_min_box_size(layout.containing_block, &pbm)
|
||||
.map(|v| v.map(Au::from))
|
||||
.auto_is(Au::zero);
|
||||
let block_size = box_size
|
||||
.block
|
||||
.map(|v| v.clamp_between_extremums(min_box_size.block, max_box_size.block));
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
||||
let tentative_inline_size = box_size.inline.auto_is(|| {
|
||||
let style = non_replaced.style.clone();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(&style, block_size);
|
||||
let available_size =
|
||||
layout.containing_block.inline_size - pbm_sums.inline_sum();
|
||||
non_replaced
|
||||
.inline_content_sizes(layout.layout_context)
|
||||
.inline_content_sizes(layout.layout_context, &containing_block_for_children)
|
||||
.shrink_to_fit(available_size)
|
||||
});
|
||||
|
||||
|
@ -1969,9 +1974,6 @@ impl IndependentFormattingContext {
|
|||
// always results in that size.
|
||||
let inline_size = tentative_inline_size
|
||||
.clamp_between_extremums(min_box_size.inline, max_box_size.inline);
|
||||
let block_size = box_size
|
||||
.block
|
||||
.map(|v| v.clamp_between_extremums(min_box_size.block, max_box_size.block));
|
||||
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
inline_size,
|
||||
|
@ -2259,7 +2261,7 @@ fn inline_container_needs_strut(
|
|||
/// A struct which takes care of computing [`ContentSizes`] for an [`InlineFormattingContext`].
|
||||
struct ContentSizesComputation<'layout_data> {
|
||||
layout_context: &'layout_data LayoutContext<'layout_data>,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
containing_block: &'layout_data IndefiniteContainingBlock<'layout_data>,
|
||||
paragraph: ContentSizes,
|
||||
current_line: ContentSizes,
|
||||
/// Size for whitepsace pending to be added to this line.
|
||||
|
@ -2297,14 +2299,14 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
|||
let zero = Length::zero();
|
||||
let padding = inline_box
|
||||
.style
|
||||
.padding(self.containing_block_writing_mode)
|
||||
.padding(self.containing_block.style.writing_mode)
|
||||
.percentages_relative_to(zero);
|
||||
let border = inline_box
|
||||
.style
|
||||
.border_width(self.containing_block_writing_mode);
|
||||
.border_width(self.containing_block.style.writing_mode);
|
||||
let margin = inline_box
|
||||
.style
|
||||
.margin(self.containing_block_writing_mode)
|
||||
.margin(self.containing_block.style.writing_mode)
|
||||
.percentages_relative_to(zero)
|
||||
.auto_is(Length::zero);
|
||||
|
||||
|
@ -2379,8 +2381,8 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
|||
|
||||
let outer = atomic.outer_inline_content_sizes(
|
||||
self.layout_context,
|
||||
self.containing_block_writing_mode,
|
||||
Au::zero,
|
||||
self.containing_block,
|
||||
&LogicalVec2::zero(),
|
||||
);
|
||||
|
||||
if !inline_formatting_context
|
||||
|
@ -2428,11 +2430,11 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
|||
fn compute(
|
||||
inline_formatting_context: &InlineFormattingContext,
|
||||
layout_context: &'layout_data LayoutContext,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
containing_block: &'layout_data IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
Self {
|
||||
layout_context,
|
||||
containing_block_writing_mode,
|
||||
containing_block,
|
||||
paragraph: ContentSizes::zero(),
|
||||
current_line: ContentSizes::zero(),
|
||||
pending_whitespace: Au::zero(),
|
||||
|
|
|
@ -36,7 +36,7 @@ use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, Positioning
|
|||
use crate::replaced::ReplacedContent;
|
||||
use crate::sizing::{self, ContentSizes};
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
mod construct;
|
||||
pub mod float;
|
||||
|
@ -227,10 +227,10 @@ impl OutsideMarker {
|
|||
sequential_layout_state: Option<&mut SequentialLayoutState>,
|
||||
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
|
||||
) -> Fragment {
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let content_sizes = self
|
||||
.block_container
|
||||
.inline_content_sizes(layout_context, containing_block_writing_mode);
|
||||
let content_sizes = self.block_container.inline_content_sizes(
|
||||
layout_context,
|
||||
&IndefiniteContainingBlock::new_for_style(&self.marker_style),
|
||||
);
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
inline_size: content_sizes.max_content,
|
||||
block_size: AuOrAuto::auto(),
|
||||
|
@ -244,6 +244,8 @@ impl OutsideMarker {
|
|||
sequential_layout_state,
|
||||
collapsible_with_parent_start_margin.unwrap_or(CollapsibleWithParentStartMargin(false)),
|
||||
);
|
||||
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let max_inline_size =
|
||||
flow_layout
|
||||
.fragments
|
||||
|
@ -357,7 +359,7 @@ impl BlockFormattingContext {
|
|||
fn calculate_inline_content_size_for_block_level_boxes(
|
||||
boxes: &[ArcRefCell<BlockLevelBox>],
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
let get_box_info = |box_: &ArcRefCell<BlockLevelBox>| {
|
||||
match &mut *box_.borrow_mut() {
|
||||
|
@ -366,7 +368,11 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
|||
BlockLevelBox::OutOfFlowFloatBox(ref mut float_box) => {
|
||||
let size = float_box
|
||||
.contents
|
||||
.outer_inline_content_sizes(layout_context, writing_mode, Au::zero)
|
||||
.outer_inline_content_sizes(
|
||||
layout_context,
|
||||
containing_block,
|
||||
&LogicalVec2::zero(),
|
||||
)
|
||||
.max(ContentSizes::zero());
|
||||
let style_box = &float_box.contents.style().get_box();
|
||||
Some((size, style_box.float, style_box.clear))
|
||||
|
@ -376,12 +382,11 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
|||
} => {
|
||||
let size = sizing::outer_inline(
|
||||
style,
|
||||
writing_mode,
|
||||
|| {
|
||||
contents
|
||||
.inline_content_sizes(layout_context, style.effective_writing_mode())
|
||||
&containing_block,
|
||||
&LogicalVec2::zero(),
|
||||
|containing_block_for_children| {
|
||||
contents.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
Au::zero,
|
||||
)
|
||||
.max(ContentSizes::zero());
|
||||
// A block in the same BFC can overlap floats, it's not moved next to them,
|
||||
|
@ -391,7 +396,11 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
|||
},
|
||||
BlockLevelBox::Independent(ref mut independent) => {
|
||||
let size = independent
|
||||
.outer_inline_content_sizes(layout_context, writing_mode, Au::zero)
|
||||
.outer_inline_content_sizes(
|
||||
layout_context,
|
||||
containing_block,
|
||||
&LogicalVec2::zero(),
|
||||
)
|
||||
.max(ContentSizes::zero());
|
||||
Some((size, Float::None, independent.style().get_box().clear))
|
||||
},
|
||||
|
@ -498,16 +507,16 @@ impl BlockContainer {
|
|||
pub(super) fn inline_content_sizes(
|
||||
&self,
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
match &self {
|
||||
Self::BlockLevelBoxes(boxes) => calculate_inline_content_size_for_block_level_boxes(
|
||||
boxes,
|
||||
layout_context,
|
||||
writing_mode,
|
||||
containing_block_for_children,
|
||||
),
|
||||
Self::InlineFormattingContext(context) => {
|
||||
context.inline_content_sizes(layout_context, writing_mode)
|
||||
context.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use app_units::Au;
|
||||
use serde::Serialize;
|
||||
use servo_arc::Arc;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::logical_geometry::Direction;
|
||||
use style::properties::ComputedValues;
|
||||
use style::selector_parser::PseudoElement;
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
|
@ -19,9 +19,9 @@ use crate::fragment_tree::{BaseFragmentInfo, Fragment, FragmentFlags};
|
|||
use crate::positioned::PositioningContext;
|
||||
use crate::replaced::ReplacedContent;
|
||||
use crate::sizing::{self, ContentSizes};
|
||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||
use crate::style_ext::{AspectRatio, DisplayInside};
|
||||
use crate::table::Table;
|
||||
use crate::ContainingBlock;
|
||||
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
|
||||
|
||||
/// <https://drafts.csswg.org/css-display/#independent-formatting-context>
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -36,7 +36,7 @@ pub(crate) struct NonReplacedFormattingContext {
|
|||
#[serde(skip_serializing)]
|
||||
pub style: Arc<ComputedValues>,
|
||||
/// If it was requested during construction
|
||||
pub content_sizes: Option<ContentSizes>,
|
||||
pub content_sizes: Option<(AuOrAuto, ContentSizes)>,
|
||||
pub contents: NonReplacedFormattingContextContents,
|
||||
}
|
||||
|
||||
|
@ -176,30 +176,56 @@ impl IndependentFormattingContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes {
|
||||
pub(crate) fn inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
match self {
|
||||
Self::NonReplaced(inner) => inner.inline_content_sizes(layout_context),
|
||||
Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style),
|
||||
Self::NonReplaced(inner) => {
|
||||
inner.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
Self::Replaced(inner) => inner
|
||||
.contents
|
||||
.inline_content_sizes(layout_context, containing_block_for_children),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outer_inline_content_sizes(
|
||||
pub(crate) fn outer_inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
get_auto_minimum: impl FnOnce() -> Au,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
auto_minimum: &LogicalVec2<Au>,
|
||||
) -> ContentSizes {
|
||||
match self {
|
||||
Self::NonReplaced(non_replaced) => non_replaced.outer_inline_content_sizes(
|
||||
layout_context,
|
||||
containing_block_writing_mode,
|
||||
get_auto_minimum,
|
||||
Self::NonReplaced(non_replaced) => sizing::outer_inline(
|
||||
&non_replaced.style.clone(),
|
||||
containing_block,
|
||||
auto_minimum,
|
||||
|containing_block_for_children| {
|
||||
non_replaced.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
),
|
||||
Self::Replaced(replaced) => sizing::outer_inline(
|
||||
&replaced.style,
|
||||
containing_block_writing_mode,
|
||||
|| replaced.contents.inline_content_sizes(&replaced.style),
|
||||
get_auto_minimum,
|
||||
containing_block,
|
||||
auto_minimum,
|
||||
|containing_block_for_children| {
|
||||
match (
|
||||
containing_block_for_children.size.block,
|
||||
replaced.preferred_aspect_ratio(containing_block),
|
||||
) {
|
||||
(AuOrAuto::LengthPercentage(block_size), Some(ratio)) => {
|
||||
return ratio
|
||||
.compute_dependent_size(Direction::Inline, block_size)
|
||||
.into();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
replaced
|
||||
.contents
|
||||
.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -234,46 +260,59 @@ impl NonReplacedFormattingContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes {
|
||||
let writing_mode = self.style.effective_writing_mode();
|
||||
let contents = &mut self.contents;
|
||||
*self
|
||||
.content_sizes
|
||||
.get_or_insert_with(|| contents.inline_content_sizes(layout_context, writing_mode))
|
||||
}
|
||||
|
||||
pub fn outer_inline_content_sizes(
|
||||
pub(crate) fn inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
get_auto_minimum: impl FnOnce() -> Au,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
sizing::outer_inline(
|
||||
&self.style,
|
||||
containing_block_writing_mode,
|
||||
|| {
|
||||
*self.content_sizes.get_or_insert_with(|| {
|
||||
assert_eq!(
|
||||
containing_block_for_children.size.inline,
|
||||
AuOrAuto::Auto,
|
||||
"inline_content_sizes() got non-auto containing block inline-size",
|
||||
);
|
||||
if let Some((previous_cb_block_size, result)) = self.content_sizes {
|
||||
if previous_cb_block_size == containing_block_for_children.size.block {
|
||||
return result;
|
||||
}
|
||||
// TODO: Should we keep multiple caches for various block sizes?
|
||||
}
|
||||
|
||||
self.content_sizes
|
||||
.insert((
|
||||
containing_block_for_children.size.block,
|
||||
self.contents
|
||||
.inline_content_sizes(layout_context, self.style.effective_writing_mode())
|
||||
})
|
||||
},
|
||||
get_auto_minimum,
|
||||
)
|
||||
.inline_content_sizes(layout_context, &containing_block_for_children),
|
||||
))
|
||||
.1
|
||||
}
|
||||
}
|
||||
|
||||
impl NonReplacedFormattingContextContents {
|
||||
pub fn inline_content_sizes(
|
||||
pub(crate) fn inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
match self {
|
||||
Self::Flow(inner) => inner
|
||||
.contents
|
||||
.inline_content_sizes(layout_context, writing_mode),
|
||||
Self::Flex(inner) => inner.inline_content_sizes(layout_context, writing_mode),
|
||||
Self::Table(table) => table.inline_content_sizes(layout_context, writing_mode),
|
||||
.inline_content_sizes(layout_context, containing_block_for_children),
|
||||
Self::Flex(inner) => {
|
||||
inner.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
Self::Table(table) => {
|
||||
table.inline_content_sizes(layout_context, containing_block_for_children)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ReplacedFormattingContext {
|
||||
pub(crate) fn preferred_aspect_ratio(
|
||||
&self,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
) -> Option<AspectRatio> {
|
||||
self.contents
|
||||
.preferred_aspect_ratio(containing_block, &self.style)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ pub type AuOrAuto = AutoOr<Au>;
|
|||
pub type LengthOrAuto = AutoOr<Length>;
|
||||
pub type LengthPercentageOrAuto<'a> = AutoOr<&'a LengthPercentage>;
|
||||
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
#[derive(Clone, Copy, PartialEq, Serialize)]
|
||||
pub struct LogicalVec2<T> {
|
||||
pub inline: T,
|
||||
pub block: T,
|
||||
|
@ -150,7 +150,7 @@ impl<T: Clone> LogicalVec2<AutoOr<T>> {
|
|||
}
|
||||
|
||||
impl LogicalVec2<LengthPercentageOrAuto<'_>> {
|
||||
pub fn percentages_relative_to(
|
||||
pub(crate) fn percentages_relative_to(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
) -> LogicalVec2<LengthOrAuto> {
|
||||
|
@ -165,8 +165,32 @@ impl LogicalVec2<LengthPercentageOrAuto<'_>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl LogicalVec2<LengthPercentageOrAuto<'_>> {
|
||||
pub(crate) fn percentages_relative_to_basis(
|
||||
&self,
|
||||
basis: &LogicalVec2<Length>,
|
||||
) -> LogicalVec2<LengthOrAuto> {
|
||||
LogicalVec2 {
|
||||
inline: self.inline.percentage_relative_to(basis.inline),
|
||||
block: self.block.percentage_relative_to(basis.block),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogicalVec2<LengthPercentageOrAuto<'_>> {
|
||||
pub(crate) fn maybe_percentages_relative_to_basis(
|
||||
&self,
|
||||
basis: &LogicalVec2<Option<Length>>,
|
||||
) -> LogicalVec2<LengthOrAuto> {
|
||||
LogicalVec2 {
|
||||
inline: self.inline.maybe_percentage_relative_to(basis.inline),
|
||||
block: self.block.maybe_percentage_relative_to(basis.block),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogicalVec2<Option<&'_ LengthPercentage>> {
|
||||
pub fn percentages_relative_to(
|
||||
pub(crate) fn percentages_relative_to(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
) -> LogicalVec2<Option<Length>> {
|
||||
|
@ -183,6 +207,22 @@ impl LogicalVec2<Option<&'_ LengthPercentage>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl LogicalVec2<Option<&'_ LengthPercentage>> {
|
||||
pub(crate) fn maybe_percentages_relative_to_basis(
|
||||
&self,
|
||||
basis: &LogicalVec2<Option<Length>>,
|
||||
) -> LogicalVec2<Option<Length>> {
|
||||
LogicalVec2 {
|
||||
inline: self
|
||||
.inline
|
||||
.and_then(|v| v.maybe_percentage_relative_to(basis.inline)),
|
||||
block: self
|
||||
.block
|
||||
.and_then(|v| v.maybe_percentage_relative_to(basis.block)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero> LogicalRect<T> {
|
||||
pub fn zero() -> Self {
|
||||
Self {
|
||||
|
|
|
@ -31,10 +31,76 @@ pub use fragment_tree::FragmentTree;
|
|||
use geom::AuOrAuto;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style_ext::ComputedValuesExt;
|
||||
use style_ext::{Clamp, ComputedValuesExt};
|
||||
|
||||
use crate::geom::LogicalVec2;
|
||||
|
||||
/// A containing block useful for calculating inline content sizes, which may
|
||||
/// have inline sizes that depend on block sizes due to aspect ratio.
|
||||
pub(crate) struct IndefiniteContainingBlock<'a> {
|
||||
pub size: LogicalVec2<AuOrAuto>,
|
||||
pub style: &'a ComputedValues,
|
||||
}
|
||||
|
||||
impl<'a> IndefiniteContainingBlock<'a> {
|
||||
fn new_for_style(style: &'a ComputedValues) -> Self {
|
||||
Self::new_for_style_and_block_size(style, AuOrAuto::Auto)
|
||||
}
|
||||
|
||||
/// Creates an [`IndefiniteContainingBlock`] with the provided style and block size,
|
||||
/// and the inline size is set to auto.
|
||||
/// This is useful when finding the min-content or max-content size of an element,
|
||||
/// since then we ignore its 'inline-size', 'min-inline-size' and 'max-inline-size'.
|
||||
fn new_for_style_and_block_size(style: &'a ComputedValues, block_size: AuOrAuto) -> Self {
|
||||
Self {
|
||||
size: LogicalVec2 {
|
||||
inline: AuOrAuto::Auto,
|
||||
block: block_size,
|
||||
},
|
||||
style,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_for_intrinsic_inline_size_of_child(
|
||||
&self,
|
||||
style: &'a ComputedValues,
|
||||
auto_minimum: &LogicalVec2<Au>,
|
||||
) -> Self {
|
||||
let (content_box_size, content_min_size, content_max_size, _) =
|
||||
style.content_box_sizes_and_padding_border_margin(&self);
|
||||
let block_size = content_box_size.block.map(|v| {
|
||||
v.clamp_between_extremums(
|
||||
content_min_size.block.auto_is(|| auto_minimum.block),
|
||||
content_max_size.block,
|
||||
)
|
||||
});
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'_ ContainingBlock<'a>> for IndefiniteContainingBlock<'a> {
|
||||
fn from(containing_block: &ContainingBlock<'a>) -> Self {
|
||||
Self {
|
||||
size: LogicalVec2 {
|
||||
inline: AuOrAuto::LengthPercentage(containing_block.inline_size),
|
||||
block: containing_block.block_size,
|
||||
},
|
||||
style: containing_block.style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'_ DefiniteContainingBlock<'a>> for IndefiniteContainingBlock<'a> {
|
||||
fn from(containing_block: &DefiniteContainingBlock<'a>) -> Self {
|
||||
Self {
|
||||
size: containing_block
|
||||
.size
|
||||
.map(|v| AuOrAuto::LengthPercentage(*v)),
|
||||
style: containing_block.style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContainingBlock<'a> {
|
||||
inline_size: Au,
|
||||
block_size: AuOrAuto,
|
||||
|
@ -47,6 +113,23 @@ impl<'a> ContainingBlock<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'_ IndefiniteContainingBlock<'a>> for ContainingBlock<'a> {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(
|
||||
indefinite_containing_block: &IndefiniteContainingBlock<'a>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match indefinite_containing_block.size.inline {
|
||||
AuOrAuto::Auto => Err("ContainingBlock doesn't accept auto inline sizes"),
|
||||
AuOrAuto::LengthPercentage(inline_size) => Ok(ContainingBlock {
|
||||
inline_size,
|
||||
block_size: indefinite_containing_block.size.block,
|
||||
style: indefinite_containing_block.style,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DefiniteContainingBlock<'a> {
|
||||
size: LogicalVec2<Au>,
|
||||
style: &'a ComputedValues,
|
||||
|
|
|
@ -27,7 +27,7 @@ use crate::geom::{
|
|||
PhysicalPoint, PhysicalRect, ToLogical,
|
||||
};
|
||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||
use crate::{ContainingBlock, DefiniteContainingBlock};
|
||||
use crate::{ContainingBlock, DefiniteContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(crate) struct AbsolutelyPositionedBox {
|
||||
|
@ -578,8 +578,16 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
let margin_sum = inline_axis.margin_start + inline_axis.margin_end;
|
||||
let available_size =
|
||||
cbis - anchor - pbm.padding_border_sums.inline - margin_sum;
|
||||
|
||||
let style = non_replaced.style.clone();
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::from(containing_block)
|
||||
.new_for_intrinsic_inline_size_of_child(
|
||||
&style,
|
||||
&LogicalVec2::zero(),
|
||||
);
|
||||
non_replaced
|
||||
.inline_content_sizes(layout_context)
|
||||
.inline_content_sizes(layout_context, &containing_block_for_children)
|
||||
.shrink_to_fit(available_size)
|
||||
});
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ use crate::dom::NodeExt;
|
|||
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
||||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
|
||||
use crate::sizing::ContentSizes;
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::{AuOrAuto, ContainingBlock};
|
||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(crate) struct ReplacedContent {
|
||||
|
@ -238,7 +238,7 @@ impl ReplacedContent {
|
|||
LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode())
|
||||
}
|
||||
|
||||
pub fn inline_size_over_block_size_intrinsic_ratio(
|
||||
pub(crate) fn inline_size_over_block_size_intrinsic_ratio(
|
||||
&self,
|
||||
style: &ComputedValues,
|
||||
) -> Option<CSSFloat> {
|
||||
|
@ -251,11 +251,16 @@ impl ReplacedContent {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn inline_content_sizes(&self, style: &ComputedValues) -> ContentSizes {
|
||||
pub fn inline_content_sizes(
|
||||
&self,
|
||||
_: &LayoutContext,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
// FIXME: min/max-content of replaced elements is not defined in
|
||||
// https://dbaron.org/css/intrinsic/
|
||||
// This seems sensible?
|
||||
self.flow_relative_intrinsic_size(style)
|
||||
|
||||
self.flow_relative_intrinsic_size(containing_block_for_children.style)
|
||||
.inline
|
||||
.unwrap_or(Au::zero())
|
||||
.into()
|
||||
|
@ -331,6 +336,18 @@ impl ReplacedContent {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn preferred_aspect_ratio(
|
||||
&self,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
style: &ComputedValues,
|
||||
) -> Option<AspectRatio> {
|
||||
style.preferred_aspect_ratio(
|
||||
self.inline_size_over_block_size_intrinsic_ratio(style),
|
||||
containing_block.try_into().ok().as_ref(),
|
||||
containing_block.style.effective_writing_mode(),
|
||||
)
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width>
|
||||
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height>
|
||||
///
|
||||
|
@ -345,10 +362,7 @@ impl ReplacedContent {
|
|||
) -> LogicalVec2<Au> {
|
||||
let mode = style.effective_writing_mode();
|
||||
let intrinsic_size = self.flow_relative_intrinsic_size(style);
|
||||
let intrinsic_ratio = style.preferred_aspect_ratio(
|
||||
self.inline_size_over_block_size_intrinsic_ratio(style),
|
||||
containing_block,
|
||||
);
|
||||
let intrinsic_ratio = self.preferred_aspect_ratio(&containing_block.into(), style);
|
||||
|
||||
let box_size = box_size.unwrap_or(
|
||||
style
|
||||
|
|
|
@ -8,13 +8,11 @@ use std::ops::{Add, AddAssign};
|
|||
|
||||
use app_units::Au;
|
||||
use serde::Serialize;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::Length;
|
||||
use style::Zero;
|
||||
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt};
|
||||
use crate::{AuOrAuto, IndefiniteContainingBlock, LogicalVec2};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub(crate) enum IntrinsicSizingMode {
|
||||
|
@ -111,70 +109,31 @@ impl From<Au> for ContentSizes {
|
|||
|
||||
pub(crate) fn outer_inline(
|
||||
style: &ComputedValues,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
get_content_size: impl FnOnce() -> ContentSizes,
|
||||
get_auto_minimum: impl FnOnce() -> Au,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
auto_minimum: &LogicalVec2<Au>,
|
||||
get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> ContentSizes,
|
||||
) -> ContentSizes {
|
||||
let padding = style.padding(containing_block_writing_mode);
|
||||
let border = style.border_width(containing_block_writing_mode);
|
||||
let margin = style.margin(containing_block_writing_mode);
|
||||
|
||||
// For margins and paddings, a cyclic percentage is resolved against zero
|
||||
// for determining intrinsic size contributions.
|
||||
// https://drafts.csswg.org/css-sizing-3/#min-percentage-contribution
|
||||
let zero = Length::zero();
|
||||
let pb_lengths = Au::from(
|
||||
border.inline_sum() +
|
||||
padding.inline_start.percentage_relative_to(zero) +
|
||||
padding.inline_end.percentage_relative_to(zero),
|
||||
);
|
||||
let mut m_lengths = zero;
|
||||
if let Some(m) = margin.inline_start.non_auto() {
|
||||
m_lengths += m.percentage_relative_to(zero)
|
||||
}
|
||||
if let Some(m) = margin.inline_end.non_auto() {
|
||||
m_lengths += m.percentage_relative_to(zero)
|
||||
}
|
||||
|
||||
let box_sizing = style.get_position().box_sizing;
|
||||
let inline_size = style
|
||||
.box_size(containing_block_writing_mode)
|
||||
.inline
|
||||
.non_auto()
|
||||
// Percentages for 'width' are treated as 'auto'
|
||||
.and_then(|lp| lp.to_length());
|
||||
let min_inline_size = style
|
||||
.min_box_size(containing_block_writing_mode)
|
||||
.inline
|
||||
// Percentages for 'min-width' are treated as zero
|
||||
.percentage_relative_to(zero)
|
||||
.map(Au::from)
|
||||
.auto_is(get_auto_minimum);
|
||||
let max_inline_size = style
|
||||
.max_box_size(containing_block_writing_mode)
|
||||
.inline
|
||||
// Percentages for 'max-width' are treated as 'none'
|
||||
.and_then(|lp| lp.to_length())
|
||||
.map(Au::from);
|
||||
let clamp = |l: Au| l.clamp_between_extremums(min_inline_size, max_inline_size);
|
||||
|
||||
let border_box_sizes = match inline_size {
|
||||
Some(non_auto) => {
|
||||
let clamped = clamp(non_auto.into());
|
||||
let border_box_size = match box_sizing {
|
||||
BoxSizing::ContentBox => clamped + pb_lengths,
|
||||
BoxSizing::BorderBox => clamped,
|
||||
let (content_box_size, content_min_size, content_max_size, pbm) =
|
||||
style.content_box_sizes_and_padding_border_margin(containing_block);
|
||||
let content_min_size = LogicalVec2 {
|
||||
inline: content_min_size.inline.auto_is(|| auto_minimum.inline),
|
||||
block: content_min_size.block.auto_is(|| auto_minimum.block),
|
||||
};
|
||||
border_box_size.into()
|
||||
let pbm_inline_sum = pbm.padding_border_sums.inline +
|
||||
pbm.margin.inline_start.auto_is(Au::zero) +
|
||||
pbm.margin.inline_end.auto_is(Au::zero);
|
||||
let adjust = |v: Au| {
|
||||
v.clamp_between_extremums(content_min_size.inline, content_max_size.inline) + pbm_inline_sum
|
||||
};
|
||||
match content_box_size.inline {
|
||||
AuOrAuto::LengthPercentage(inline_size) => adjust(inline_size).into(),
|
||||
AuOrAuto::Auto => {
|
||||
let block_size = content_box_size
|
||||
.block
|
||||
.map(|v| v.clamp_between_extremums(content_min_size.block, content_max_size.block));
|
||||
let containing_block_for_children =
|
||||
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size);
|
||||
get_content_size(&containing_block_for_children).map(adjust)
|
||||
},
|
||||
None => get_content_size().map(|content_box_size| {
|
||||
match box_sizing {
|
||||
// Clamp to 'min-width' and 'max-width', which are sizing the…
|
||||
BoxSizing::ContentBox => clamp(content_box_size) + pb_lengths,
|
||||
BoxSizing::BorderBox => clamp(content_box_size + pb_lengths),
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
border_box_sizes.map(|s| s + m_lengths.into())
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ use crate::geom::{
|
|||
AuOrAuto, LengthOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides,
|
||||
PhysicalSize,
|
||||
};
|
||||
use crate::ContainingBlock;
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub(crate) enum Display {
|
||||
|
@ -233,11 +233,25 @@ pub(crate) trait ComputedValuesExt {
|
|||
box_size: LogicalVec2<Option<Length>>,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> LogicalVec2<Option<Length>>;
|
||||
fn content_box_sizes_and_padding_border_margin(
|
||||
&self,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
) -> (
|
||||
LogicalVec2<AuOrAuto>,
|
||||
LogicalVec2<AuOrAuto>,
|
||||
LogicalVec2<Option<Au>>,
|
||||
PaddingBorderMargin,
|
||||
);
|
||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
|
||||
fn padding_border_margin_for_intrinsic_size(
|
||||
&self,
|
||||
writing_mode: WritingMode,
|
||||
) -> 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,
|
||||
|
@ -263,7 +277,8 @@ pub(crate) trait ComputedValuesExt {
|
|||
fn preferred_aspect_ratio(
|
||||
&self,
|
||||
natural_aspect_ratio: Option<CSSFloat>,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block: Option<&ContainingBlock>,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
) -> Option<AspectRatio>;
|
||||
fn background_is_transparent(&self) -> bool;
|
||||
fn get_webrender_primitive_flags(&self) -> wr::PrimitiveFlags;
|
||||
|
@ -431,6 +446,49 @@ impl ComputedValuesExt for ComputedValues {
|
|||
}
|
||||
}
|
||||
|
||||
fn content_box_sizes_and_padding_border_margin(
|
||||
&self,
|
||||
containing_block: &IndefiniteContainingBlock,
|
||||
) -> (
|
||||
LogicalVec2<AuOrAuto>,
|
||||
LogicalVec2<AuOrAuto>,
|
||||
LogicalVec2<Option<Au>>,
|
||||
PaddingBorderMargin,
|
||||
) {
|
||||
// <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(|v| v.non_auto().map(Into::into));
|
||||
let containing_block_size_auto_is_zero =
|
||||
containing_block_size.map(|v| v.unwrap_or_else(Length::zero));
|
||||
let writing_mode = self.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)
|
||||
.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 = self
|
||||
.min_box_size(writing_mode)
|
||||
.percentages_relative_to_basis(&containing_block_size_auto_is_zero);
|
||||
let content_min_size = self
|
||||
.content_min_box_size_for_min_size(min_size, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
let max_size = self
|
||||
.max_box_size(writing_mode)
|
||||
.maybe_percentages_relative_to_basis(&containing_block_size);
|
||||
let content_max_size = self
|
||||
.content_max_box_size_for_max_size(max_size, &pbm)
|
||||
.map(|v| v.map(Au::from));
|
||||
(content_box_size, content_min_size, content_max_size, pbm)
|
||||
}
|
||||
|
||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin {
|
||||
let cbis = containing_block.inline_size;
|
||||
let padding = self
|
||||
|
@ -473,6 +531,30 @@ impl ComputedValuesExt for ComputedValues {
|
|||
}
|
||||
}
|
||||
|
||||
fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||
&self,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_inline_size: Au,
|
||||
) -> PaddingBorderMargin {
|
||||
let containing_block_inline_size = containing_block_inline_size.into();
|
||||
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()).into(),
|
||||
block: (padding.block_sum() + border.block_sum()).into(),
|
||||
},
|
||||
padding: padding.into(),
|
||||
border: border.into(),
|
||||
margin: margin.map(|margin_side| margin_side.map(Into::into)),
|
||||
}
|
||||
}
|
||||
|
||||
fn padding(
|
||||
&self,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
|
@ -677,7 +759,8 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn preferred_aspect_ratio(
|
||||
&self,
|
||||
natural_aspect_ratio: Option<CSSFloat>,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block: Option<&ContainingBlock>,
|
||||
containing_block_writing_mode: WritingMode,
|
||||
) -> Option<AspectRatio> {
|
||||
let GenericAspectRatio {
|
||||
auto,
|
||||
|
@ -728,7 +811,12 @@ impl ComputedValuesExt for ComputedValues {
|
|||
let box_sizing_adjustment = match self.clone_box_sizing() {
|
||||
BoxSizing::ContentBox => LogicalVec2::zero(),
|
||||
BoxSizing::BorderBox => {
|
||||
self.padding_border_margin(containing_block)
|
||||
match containing_block {
|
||||
Some(containing_block) => self.padding_border_margin(containing_block),
|
||||
None => self.padding_border_margin_for_intrinsic_size(
|
||||
containing_block_writing_mode,
|
||||
),
|
||||
}
|
||||
.padding_border_sums
|
||||
},
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ use crate::positioned::{relative_adjustement, PositioningContext, PositioningCon
|
|||
use crate::sizing::ContentSizes;
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::table::TableSlotCoordinates;
|
||||
use crate::ContainingBlock;
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
/// A result of a final or speculative layout of a single cell in
|
||||
/// the table. Note that this is only done for slots that are not
|
||||
|
@ -201,10 +201,10 @@ impl<'a> TableLayout<'a> {
|
|||
|
||||
let (size, min_size, max_size) =
|
||||
get_outer_sizes_from_style(&cell.style, writing_mode, &padding_border_sums);
|
||||
let mut inline_content_sizes = cell
|
||||
.contents
|
||||
.contents
|
||||
.inline_content_sizes(layout_context, writing_mode);
|
||||
let mut inline_content_sizes = cell.contents.contents.inline_content_sizes(
|
||||
layout_context,
|
||||
&IndefiniteContainingBlock::new_for_style(&cell.style),
|
||||
);
|
||||
inline_content_sizes.min_content += padding_border_sums.inline;
|
||||
inline_content_sizes.max_content += padding_border_sums.inline;
|
||||
|
||||
|
@ -677,13 +677,7 @@ impl<'a> TableLayout<'a> {
|
|||
.captions
|
||||
.iter()
|
||||
.map(|caption| {
|
||||
let size;
|
||||
let min_size;
|
||||
let max_size;
|
||||
let padding_border_sums;
|
||||
let size_is_auto;
|
||||
{
|
||||
let context = caption.context.borrow();
|
||||
let mut context = caption.context.borrow_mut();
|
||||
let padding = context
|
||||
.style
|
||||
.padding(writing_mode)
|
||||
|
@ -695,34 +689,30 @@ impl<'a> TableLayout<'a> {
|
|||
.percentages_relative_to(Length::zero())
|
||||
.auto_is(Length::zero);
|
||||
|
||||
padding_border_sums = LogicalVec2 {
|
||||
let padding_border_sums = LogicalVec2 {
|
||||
inline: (padding.inline_sum() + border.inline_sum() + margin.inline_sum())
|
||||
.into(),
|
||||
block: (padding.block_sum() + border.block_sum() + margin.block_sum())
|
||||
.into(),
|
||||
block: (padding.block_sum() + border.block_sum() + margin.block_sum()).into(),
|
||||
};
|
||||
|
||||
(size, min_size, max_size) = get_outer_sizes_from_style(
|
||||
&context.style,
|
||||
writing_mode,
|
||||
&padding_border_sums,
|
||||
);
|
||||
size_is_auto = context.style.box_size(writing_mode).inline.is_auto();
|
||||
}
|
||||
let (size, min_size, max_size) =
|
||||
get_outer_sizes_from_style(&context.style, writing_mode, &padding_border_sums);
|
||||
let size_is_auto = context.style.box_size(writing_mode).inline.is_auto();
|
||||
|
||||
// If an inline size is defined it should serve as the upper limit and lower limit
|
||||
// of the caption inline size.
|
||||
let inline_size = if !size_is_auto {
|
||||
if !size_is_auto {
|
||||
size.inline
|
||||
} else {
|
||||
let inline_content_sizes = caption
|
||||
.context
|
||||
.borrow_mut()
|
||||
.inline_content_sizes(layout_context);
|
||||
let style = context.style.clone();
|
||||
let inline_content_sizes = context.inline_content_sizes(
|
||||
layout_context,
|
||||
&IndefiniteContainingBlock::new_for_style(&style),
|
||||
);
|
||||
inline_content_sizes.min_content + padding_border_sums.inline
|
||||
};
|
||||
|
||||
inline_size.min(max_size.inline).max(min_size.inline)
|
||||
}
|
||||
.min(max_size.inline)
|
||||
.max(min_size.inline)
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_default()
|
||||
|
@ -2432,8 +2422,9 @@ impl Table {
|
|||
pub(crate) fn inline_content_sizes(
|
||||
&mut self,
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
let writing_mode = containing_block_for_children.style.effective_writing_mode();
|
||||
let mut layout = TableLayout::new(self);
|
||||
let mut table_content_sizes = layout.compute_grid_min_max(layout_context, writing_mode);
|
||||
|
||||
|
|
13
tests/wpt/meta/MANIFEST.json
vendored
13
tests/wpt/meta/MANIFEST.json
vendored
|
@ -176439,6 +176439,19 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"percentage-padding-005.html": [
|
||||
"928286a590407bd5607fe4797b19be3b4ecb14d8",
|
||||
[
|
||||
null,
|
||||
[
|
||||
[
|
||||
"/css/reference/ref-filled-green-100px-square-only.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"percentage-size-subitems-001.html": [
|
||||
"70f3953052a3a770c6cd15ee169607a00fc452b0",
|
||||
[
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[flex-basis-011.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flex-minimum-height-flex-items-015.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-flex-direction-column-percentage-ignored.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[item-with-max-height-and-scrollbar.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[nested-flex-image-loading-invalidates-intrinsic-sizes.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[percentage-heights-014.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[position-fixed-001.html]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[aspect-ratio-affects-container-width-when-height-changes.html]
|
||||
[#container 1]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-001.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-dynamic-002.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-dynamic-003.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-dynamic-004.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-dynamic-006.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[intrinsic-percent-replaced-dynamic-009.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[calc-rounding-002.html]
|
||||
expected: FAIL
|
11
tests/wpt/tests/css/css-flexbox/percentage-padding-005.html
vendored
Normal file
11
tests/wpt/tests/css/css-flexbox/percentage-padding-005.html
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#item-margins">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#intrinsic-main-sizes">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
|
||||
<meta name="assert" content="The flex container becomes 100px tall because the padding percentage of the item resolves against its width.">
|
||||
|
||||
<p>Test passes if there is a filled green square.</p>
|
||||
<div style="display: flex; background: green; flex-direction: column; width: 100px;">
|
||||
<div style="width: 100px; padding-bottom: 100%"></div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue