Skip to content

Commit

Permalink
Use the writing mode of the containing block when accessing CSS prope…
Browse files Browse the repository at this point in the history
…rties

… and converting them to flow-relative geometric values.

These values are almost always used to size and position a fragment within its containing block, so using the mode of the containing block seems more correct.

Note that the `writing-mode` and `direction` properties are disabled in Servo at the moment, so this PR by itself should have no effect: the writing mode of an element is always the same of that of its containing block since they’re both horizontal rtl.
  • Loading branch information
SimonSapin committed Jun 10, 2020
1 parent 554af02 commit 08f008a
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 64 deletions.
35 changes: 30 additions & 5 deletions components/layout_2020/flow/construct.rs
Expand Up @@ -21,6 +21,7 @@ use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc;
use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
use style::values::specified::text::TextDecorationLine;
Expand Down Expand Up @@ -67,7 +68,12 @@ impl BlockFormattingContext {
inline_level_boxes,
text_decoration_line,
};
let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context));
// FIXME: this is the wrong writing mode
// but we plan to remove eager content size computation.
let not_actually_containing_block_writing_mode = WritingMode::empty();
let content_sizes = content_sizes.compute(|| {
ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode)
});
let contents = BlockContainer::InlineFormattingContext(ifc);
let bfc = Self {
contents,
Expand Down Expand Up @@ -203,10 +209,13 @@ impl BlockContainer {
.is_empty()
{
if builder.block_level_boxes.is_empty() {
// FIXME: this is the wrong writing mode
// but we plan to remove eager content size computation.
let not_actually_containing_block_writing_mode = info.style.writing_mode;
let content_sizes = content_sizes.compute(|| {
builder
.ongoing_inline_formatting_context
.inline_content_sizes(context)
.inline_content_sizes(context, not_actually_containing_block_writing_mode)
});
let container = BlockContainer::InlineFormattingContext(
builder.ongoing_inline_formatting_context,
Expand Down Expand Up @@ -678,6 +687,9 @@ where
max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>,
) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
let info = &self.info;
// FIXME: this is the wrong writing mode
// but we plan to remove eager content size computation.
let not_actually_containing_block_writing_mode = info.style.writing_mode;
let (block_level_box, contains_floats) = match self.kind {
BlockLevelCreator::SameFormattingContextBlock(contents) => {
let (contents, contains_floats, box_content_sizes) = contents.finish(
Expand All @@ -689,7 +701,10 @@ where
),
);
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&box_content_sizes.outer_inline(&info.style))
to.max_assign(
&box_content_sizes
.outer_inline(&info.style, not_actually_containing_block_writing_mode),
)
}
let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
tag: Tag::from_node_and_style_info(info),
Expand All @@ -716,7 +731,12 @@ where
propagated_text_decoration_line,
);
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&contents.content_sizes.outer_inline(&contents.style))
to.max_assign(
&contents.content_sizes.outer_inline(
&contents.style,
not_actually_containing_block_writing_mode,
),
)
}
(
ArcRefCell::new(BlockLevelBox::Independent(contents)),
Expand Down Expand Up @@ -771,7 +791,12 @@ impl IntermediateBlockContainer {
)
},
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context));
// FIXME: this is the wrong writing mode
// but we plan to remove eager content size computation.
let not_actually_containing_block_writing_mode = info.style.writing_mode;
let content_sizes = content_sizes.compute(|| {
ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode)
});
// If that inline formatting context contained any float, those
// were already taken into account during the first phase of
// box construction.
Expand Down
45 changes: 28 additions & 17 deletions components/layout_2020/flow/inline.rs
Expand Up @@ -23,6 +23,7 @@ use app_units::Au;
use atomic_refcell::AtomicRef;
use gfx::text::text_run::GlyphRun;
use servo_arc::Arc;
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage, Percentage};
use style::values::specified::text::TextAlignKeyword;
Expand Down Expand Up @@ -139,24 +140,30 @@ impl InlineFormattingContext {
// This works on an already-constructed `InlineFormattingContext`,
// Which would have to change if/when
// `BlockContainer::construct` parallelize their construction.
pub(super) fn inline_content_sizes(&self, layout_context: &LayoutContext) -> ContentSizes {
struct Computation {
pub(super) fn inline_content_sizes(
&self,
layout_context: &LayoutContext,
containing_block_writing_mode: WritingMode,
) -> ContentSizes {
struct Computation<'a> {
layout_context: &'a LayoutContext<'a>,
containing_block_writing_mode: WritingMode,
paragraph: ContentSizes,
current_line: ContentSizes,
current_line_percentages: Percentage,
}
impl Computation {
fn traverse(
&mut self,
layout_context: &LayoutContext,
inline_level_boxes: &[ArcRefCell<InlineLevelBox>],
) {
impl Computation<'_> {
fn traverse(&mut self, inline_level_boxes: &[ArcRefCell<InlineLevelBox>]) {
for inline_level_box in inline_level_boxes {
match &*inline_level_box.borrow() {
InlineLevelBox::InlineBox(inline_box) => {
let padding = inline_box.style.padding();
let border = inline_box.style.border_width();
let margin = inline_box.style.margin();
let padding =
inline_box.style.padding(self.containing_block_writing_mode);
let border = inline_box
.style
.border_width(self.containing_block_writing_mode);
let margin =
inline_box.style.margin(self.containing_block_writing_mode);
macro_rules! add {
($condition: ident, $side: ident) => {
if inline_box.$condition {
Expand All @@ -170,15 +177,15 @@ impl InlineFormattingContext {
}

add!(first_fragment, inline_start);
self.traverse(layout_context, &inline_box.children);
self.traverse(&inline_box.children);
add!(last_fragment, inline_end);
},
InlineLevelBox::TextRun(text_run) => {
let BreakAndShapeResult {
runs,
break_at_start,
..
} = text_run.break_and_shape(layout_context);
} = text_run.break_and_shape(self.layout_context);
if break_at_start {
self.line_break_opportunity()
}
Expand All @@ -193,9 +200,10 @@ impl InlineFormattingContext {
}
},
InlineLevelBox::Atomic(atomic) => {
let (outer, pc) = atomic
.content_sizes
.outer_inline_and_percentages(&atomic.style);
let (outer, pc) = atomic.content_sizes.outer_inline_and_percentages(
&atomic.style,
self.containing_block_writing_mode,
);
self.current_line.min_content += outer.min_content;
self.current_line.max_content += outer.max_content;
self.current_line_percentages += pc;
Expand Down Expand Up @@ -239,11 +247,13 @@ impl InlineFormattingContext {
std::mem::replace(x, T::zero())
}
let mut computation = Computation {
layout_context,
containing_block_writing_mode,
paragraph: ContentSizes::zero(),
current_line: ContentSizes::zero(),
current_line_percentages: Percentage::zero(),
};
computation.traverse(layout_context, &self.inline_level_boxes);
computation.traverse(&self.inline_level_boxes);
computation.forced_line_break();
computation.paragraph
}
Expand Down Expand Up @@ -308,6 +318,7 @@ impl InlineFormattingContext {
box_.clone(),
initial_start_corner,
tree_rank,
ifc.containing_block,
);
let hoisted_fragment = hoisted_box.fragment.clone();
ifc.push_hoisted_box_to_positioning_context(hoisted_box);
Expand Down
8 changes: 6 additions & 2 deletions components/layout_2020/flow/mod.rs
Expand Up @@ -316,8 +316,12 @@ impl BlockLevelBox {
))
},
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
let hoisted_box =
AbsolutelyPositionedBox::to_hoisted(box_.clone(), Vec2::zero(), tree_rank);
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
box_.clone(),
Vec2::zero(),
tree_rank,
containing_block,
);
let hoisted_fragment = hoisted_box.fragment.clone();
positioning_context.push(hoisted_box);
Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment {
Expand Down
13 changes: 8 additions & 5 deletions components/layout_2020/positioned.rs
Expand Up @@ -100,6 +100,7 @@ impl AbsolutelyPositionedBox {
self_: ArcRefCell<Self>,
initial_start_corner: Vec2<Length>,
tree_rank: usize,
containing_block: &ContainingBlock,
) -> HoistedAbsolutelyPositionedBox {
fn absolute_box_offsets(
initial_static_start: Length,
Expand All @@ -123,7 +124,7 @@ impl AbsolutelyPositionedBox {

let box_offsets = {
let box_ = self_.borrow();
let box_offsets = box_.contents.style.box_offsets();
let box_offsets = box_.contents.style.box_offsets(containing_block);
Vec2 {
inline: absolute_box_offsets(
initial_start_corner.inline,
Expand Down Expand Up @@ -708,10 +709,12 @@ pub(crate) fn relative_adjustement(
) -> 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),
);
let box_offsets = style
.box_offsets(containing_block)
.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(),
Expand Down
23 changes: 15 additions & 8 deletions components/layout_2020/sizing.rs
Expand Up @@ -5,6 +5,7 @@
//! https://drafts.csswg.org/css-sizing/

use crate::style_ext::ComputedValuesExt;
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, LengthPercentage, Percentage};
Expand Down Expand Up @@ -105,19 +106,25 @@ impl BoxContentSizes {
}

/// https://dbaron.org/css/intrinsic/#outer-intrinsic
pub fn outer_inline(&self, style: &ComputedValues) -> ContentSizes {
let (mut outer, percentages) = self.outer_inline_and_percentages(style);
pub fn outer_inline(
&self,
style: &ComputedValues,
containing_block_writing_mode: WritingMode,
) -> ContentSizes {
let (mut outer, percentages) =
self.outer_inline_and_percentages(style, containing_block_writing_mode);
outer.adjust_for_pbm_percentages(percentages);
outer
}

pub(crate) fn outer_inline_and_percentages(
&self,
style: &ComputedValues,
containing_block_writing_mode: WritingMode,
) -> (ContentSizes, Percentage) {
let padding = style.padding();
let border = style.border_width();
let margin = style.margin();
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);

let mut pbm_percentages = Percentage::zero();
let mut decompose = |x: &LengthPercentage| {
Expand All @@ -136,20 +143,20 @@ impl BoxContentSizes {

let box_sizing = style.get_position().box_sizing;
let inline_size = style
.box_size()
.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()
.min_box_size(containing_block_writing_mode)
.inline
// Percentages for 'min-width' are treated as zero
.percentage_relative_to(Length::zero())
// FIXME: 'auto' is not zero in Flexbox
.auto_is(Length::zero);
let max_inline_size = style
.max_box_size()
.max_box_size(containing_block_writing_mode)
.inline
// Percentages for 'max-width' are treated as 'none'
.and_then(|lp| lp.to_length());
Expand Down

0 comments on commit 08f008a

Please sign in to comment.