Make for_maybe_position_relative take care of relative adjustment.

This commit is contained in:
Simon Sapin 2019-12-13 13:12:57 +01:00
parent b218957461
commit 58b7005a9b
6 changed files with 49 additions and 56 deletions

View file

@ -9,10 +9,10 @@ use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::CollapsedBlockMargins; use crate::fragments::CollapsedBlockMargins;
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment}; use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{relative_adjustement, AbsolutelyPositionedBox, PositioningContext};
use crate::sizing::ContentSizes; use crate::sizing::ContentSizes;
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
use crate::{relative_adjustement, ContainingBlock}; use crate::ContainingBlock;
use app_units::Au; use app_units::Au;
use gfx::text::text_run::GlyphRun; use gfx::text::text_run::GlyphRun;
use servo_arc::Arc; use servo_arc::Arc;
@ -367,11 +367,9 @@ impl InlineBox {
block: padding.block_start + border.block_start + margin.block_start, block: padding.block_start + border.block_start + margin.block_start,
inline: ifc.inline_position - ifc.current_nesting_level.inline_start, inline: ifc.inline_position - ifc.current_nesting_level.inline_start,
}; };
start_corner += &relative_adjustement( if style.clone_position().is_relative() {
&style, start_corner += &relative_adjustement(&style, ifc.containing_block)
ifc.containing_block.inline_size, }
ifc.containing_block.block_size,
);
PartialInlineBoxFragment { PartialInlineBoxFragment {
style, style,
start_corner, start_corner,
@ -457,11 +455,9 @@ fn layout_atomic<'box_tree>(
block: pbm.block_start, block: pbm.block_start,
inline: ifc.inline_position - ifc.current_nesting_level.inline_start, inline: ifc.inline_position - ifc.current_nesting_level.inline_start,
}; };
start_corner += &relative_adjustement( if atomic.style.clone_position().is_relative() {
&atomic.style, start_corner += &relative_adjustement(&atomic.style, ifc.containing_block)
ifc.containing_block.inline_size, }
ifc.containing_block.block_size,
);
let fragment = match atomic.as_replaced() { let fragment = match atomic.as_replaced() {
Ok(replaced) => { Ok(replaced) => {

View file

@ -14,7 +14,7 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::style_ext::ComputedValuesExt; use crate::style_ext::ComputedValuesExt;
use crate::{relative_adjustement, ContainingBlock}; use crate::ContainingBlock;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt; use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc; use servo_arc::Arc;
@ -271,6 +271,7 @@ impl BlockLevelBox {
BlockLevelBox::SameFormattingContextBlock { style, contents } => { BlockLevelBox::SameFormattingContextBlock { style, contents } => {
Fragment::Box(positioning_context.for_maybe_position_relative( Fragment::Box(positioning_context.for_maybe_position_relative(
layout_context, layout_context,
containing_block,
style, style,
|positioning_context| { |positioning_context| {
layout_in_flow_non_replaced_block_level( layout_in_flow_non_replaced_block_level(
@ -288,6 +289,7 @@ impl BlockLevelBox {
BlockLevelBox::Independent(contents) => { BlockLevelBox::Independent(contents) => {
Fragment::Box(positioning_context.for_maybe_position_relative( Fragment::Box(positioning_context.for_maybe_position_relative(
layout_context, layout_context,
containing_block,
&contents.style, &contents.style,
|positioning_context| match contents.as_replaced() { |positioning_context| match contents.as_replaced() {
Ok(replaced) => layout_in_flow_replaced_block_level( Ok(replaced) => layout_in_flow_replaced_block_level(
@ -470,14 +472,13 @@ fn layout_in_flow_non_replaced_block_level<'a>(
content_block_size = independent_layout.content_block_size; content_block_size = independent_layout.content_block_size;
}, },
}; };
let relative_adjustement = relative_adjustement(style, inline_size, block_size);
let block_size = block_size.auto_is(|| { let block_size = block_size.auto_is(|| {
content_block_size.clamp_between_extremums(min_box_size.block, max_box_size.block) content_block_size.clamp_between_extremums(min_box_size.block, max_box_size.block)
}); });
let content_rect = Rect { let content_rect = Rect {
start_corner: Vec2 { start_corner: Vec2 {
block: pb.block_start + relative_adjustement.block, block: pb.block_start,
inline: pb.inline_start + relative_adjustement.inline + margin.inline_start, inline: pb.inline_start,
}, },
size: Vec2 { size: Vec2 {
block: block_size, block: block_size,
@ -525,15 +526,10 @@ fn layout_in_flow_replaced_block_level<'a>(
block_end: computed_margin.block_end.auto_is(Length::zero), block_end: computed_margin.block_end.auto_is(Length::zero),
}; };
let fragments = replaced.make_fragments(style, size.clone()); let fragments = replaced.make_fragments(style, size.clone());
let relative_adjustement = relative_adjustement(
style,
size.inline,
LengthOrAuto::LengthPercentage(size.block),
);
let content_rect = Rect { let content_rect = Rect {
start_corner: Vec2 { start_corner: Vec2 {
block: pb.block_start + relative_adjustement.block, block: pb.block_start,
inline: pb.inline_start + relative_adjustement.inline + margin.inline_start, inline: pb.inline_start + margin.inline_start,
}, },
size, size,
}; };

View file

@ -27,11 +27,8 @@ pub mod wrapper;
pub use flow::{BoxTreeRoot, FragmentTreeRoot}; pub use flow::{BoxTreeRoot, FragmentTreeRoot};
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
use crate::style_ext::ComputedValuesExt;
use style::computed_values::position::T as Position;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::{Length, LengthOrAuto}; use style::values::computed::{Length, LengthOrAuto};
use style::Zero;
struct ContainingBlock<'a> { struct ContainingBlock<'a> {
inline_size: Length, inline_size: Length,
@ -53,30 +50,3 @@ impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> {
} }
} }
} }
/// https://drafts.csswg.org/css2/visuren.html#relative-positioning
fn relative_adjustement(
style: &ComputedValues,
inline_size: Length,
block_size: LengthOrAuto,
) -> Vec2<Length> {
if style.get_box().position != Position::Relative {
return Vec2::zero();
}
fn adjust(start: LengthOrAuto, end: LengthOrAuto) -> Length {
match (start, end) {
(LengthOrAuto::Auto, LengthOrAuto::Auto) => Length::zero(),
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => -end,
(LengthOrAuto::LengthPercentage(start), _) => start,
}
}
let block_size = block_size.auto_is(Length::zero);
let box_offsets = style.box_offsets().map_inline_and_block_axes(
|v| v.percentage_relative_to(inline_size),
|v| v.percentage_relative_to(block_size),
);
Vec2 {
inline: adjust(box_offsets.inline_start, box_offsets.inline_end),
block: adjust(box_offsets.block_start, box_offsets.block_end),
}
}

View file

@ -150,11 +150,17 @@ impl<'box_tree> PositioningContext<'box_tree> {
pub(crate) fn for_maybe_position_relative( pub(crate) fn for_maybe_position_relative(
&mut self, &mut self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
containing_block: &ContainingBlock,
style: &ComputedValues, style: &ComputedValues,
f: impl FnOnce(&mut Self) -> BoxFragment, f: impl FnOnce(&mut Self) -> BoxFragment,
) -> BoxFragment { ) -> BoxFragment {
if style.clone_position() == Position::Relative { if style.clone_position() == Position::Relative {
Self::for_positioned(layout_context, &mut self.for_initial_containing_block, f) let mut fragment =
// Establing a containing block for absolutely positioned descendants
Self::for_positioned(layout_context, &mut self.for_initial_containing_block, f);
fragment.content_rect.start_corner += &relative_adjustement(style, containing_block);
fragment
} else { } else {
f(self) f(self)
} }
@ -610,3 +616,27 @@ fn vec_append_owned<T>(a: &mut Vec<T>, mut b: Vec<T>) {
a.append(&mut b) a.append(&mut b)
} }
} }
/// https://drafts.csswg.org/css2/visuren.html#relative-positioning
pub(crate) fn relative_adjustement(
style: &ComputedValues,
containing_block: &ContainingBlock,
) -> Vec2<Length> {
let cbis = containing_block.inline_size;
let cbbs = containing_block.block_size.auto_is(Length::zero);
let box_offsets = style.box_offsets().map_inline_and_block_axes(
|v| v.percentage_relative_to(cbis),
|v| v.percentage_relative_to(cbbs),
);
fn adjust(start: LengthOrAuto, end: LengthOrAuto) -> Length {
match (start, end) {
(LengthOrAuto::Auto, LengthOrAuto::Auto) => Length::zero(),
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => -end,
(LengthOrAuto::LengthPercentage(start), _) => start,
}
}
Vec2 {
inline: adjust(box_offsets.inline_start, box_offsets.inline_end),
block: adjust(box_offsets.block_start, box_offsets.block_end),
}
}

View file

@ -55,6 +55,9 @@ impl computed_value::T {
pub fn is_absolutely_positioned(self) -> bool { pub fn is_absolutely_positioned(self) -> bool {
matches!(self, Self::Absolute | Self::Fixed) matches!(self, Self::Absolute | Self::Fixed)
} }
pub fn is_relative(self) -> bool {
self == Self::Relative
}
} }
</%helpers:single_keyword> </%helpers:single_keyword>

View file

@ -1,2 +0,0 @@
[block-in-inline-relpos-001.xht]
expected: FAIL