Implement shrink-to-fit for abspos

This commit is contained in:
Simon Sapin 2019-12-03 13:12:40 +01:00
parent efa1885e1b
commit 46f0f7d7e2
5 changed files with 48 additions and 15 deletions

View file

@ -7,6 +7,7 @@ use crate::dom_traversal::{Contents, NodeExt};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::sizing::shrink_to_fit;
use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, WritingMode}; use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, WritingMode};
use crate::{ContainingBlock, DefiniteContainingBlock}; use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
@ -51,8 +52,15 @@ impl AbsolutelyPositionedBox {
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents<impl NodeExt<'dom>>, contents: Contents<impl NodeExt<'dom>>,
) -> Self { ) -> Self {
let request_content_sizes = // "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
style.inline_size_is_auto() && !style.inline_box_offsets_are_both_auto(); let request_content_sizes = {
// If inline-size is non-auto, that value is used without shrink-to-fit
style.inline_size_is_auto() &&
// If it is, then the only case where shrink-to-fit is *not* used is
// if both offsets are non-auto, leaving inline-size as the only variable
// in the constraint equation.
!style.inline_box_offsets_are_both_non_auto()
};
Self { Self {
contents: IndependentFormattingContext::construct( contents: IndependentFormattingContext::construct(
context, context,
@ -278,8 +286,20 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
Anchor::End(end) => cbis - end - pb.inline_sum() - margin.inline_sum(), Anchor::End(end) => cbis - end - pb.inline_sum() - margin.inline_sum(),
}; };
// FIXME(nox): shrink-to-fit. if self
available_size .absolutely_positioned_box
.contents
.as_replaced()
.is_ok()
{
// FIXME: implement https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
available_size
} else {
shrink_to_fit(
&self.absolutely_positioned_box.contents.inline_content_sizes,
available_size,
)
}
}); });
let containing_block_for_children = ContainingBlock { let containing_block_for_children = ContainingBlock {

View file

@ -65,10 +65,7 @@ pub(crate) fn outer_inline_content_sizes_and_percentages(
let specified = specified.map(|lp| lp.as_length()); let specified = specified.map(|lp| lp.as_length());
// The (inner) min/max-content are only used for 'auto' // The (inner) min/max-content are only used for 'auto'
let mut outer = match specified.non_auto().flatten() { let mut outer = match specified.non_auto().flatten() {
None => inner_content_sizes None => expect(inner_content_sizes).clone(),
.as_ref()
.expect("Accessing content size that was not requested")
.clone(),
Some(length) => ContentSizes { Some(length) => ContentSizes {
min_content: length, min_content: length,
max_content: length, max_content: length,
@ -96,3 +93,20 @@ pub(crate) fn outer_inline_content_sizes_and_percentages(
(outer, pbm_percentages) (outer, pbm_percentages)
} }
/// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float
pub(crate) fn shrink_to_fit(
content_sizes: &Option<ContentSizes>,
available_size: Length,
) -> Length {
let content_sizes = expect(content_sizes);
available_size
.max(content_sizes.min_content)
.min(content_sizes.max_content)
}
fn expect(content_sizes: &Option<ContentSizes>) -> &ContentSizes {
content_sizes
.as_ref()
.expect("Accessing content size that was not requested")
}

View file

@ -45,7 +45,7 @@ pub(crate) trait ComputedValuesExt {
fn writing_mode(&self) -> (WritingMode, Direction); fn writing_mode(&self) -> (WritingMode, Direction);
fn writing_mode_is_horizontal(&self) -> bool; fn writing_mode_is_horizontal(&self) -> bool;
fn inline_size_is_auto(&self) -> bool; fn inline_size_is_auto(&self) -> bool;
fn inline_box_offsets_are_both_auto(&self) -> bool; fn inline_box_offsets_are_both_non_auto(&self) -> bool;
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>; fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>; fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
fn padding(&self) -> flow_relative::Sides<LengthPercentage>; fn padding(&self) -> flow_relative::Sides<LengthPercentage>;
@ -78,7 +78,7 @@ impl ComputedValuesExt for ComputedValues {
matches!(size, Size::Auto) matches!(size, Size::Auto)
} }
fn inline_box_offsets_are_both_auto(&self) -> bool { fn inline_box_offsets_are_both_non_auto(&self) -> bool {
let position = self.get_position(); let position = self.get_position();
let offsets = if self.writing_mode_is_horizontal() { let offsets = if self.writing_mode_is_horizontal() {
(position.left, position.right) (position.left, position.right)
@ -87,7 +87,10 @@ impl ComputedValuesExt for ComputedValues {
}; };
matches!( matches!(
offsets, offsets,
(LengthPercentageOrAuto::Auto, LengthPercentageOrAuto::Auto) (
LengthPercentageOrAuto::LengthPercentage(_),
LengthPercentageOrAuto::LengthPercentage(_),
)
) )
} }

View file

@ -1,2 +0,0 @@
[containing-block-008.xht]
expected: FAIL

View file

@ -1,2 +0,0 @@
[containing-block-010.xht]
expected: FAIL