mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
layout: Right-to-left support for other layout modes (#33375)
This change removes the `effective_writing_mode` concept and tries to properly implement right-to-left layout support for all non-inline writing modes. In general, what needs to happen is that rectangles need to be converted to physical rectangles using the containing block. A right-to-left rectangle's inline start is on the right physical side of the containing block. Likewise a positive inline offset in right-to-left text is a negative physical one. The implementation here is pretty good for most layout modes, but floats are still a bit in process. Currently, floats are processed in the logical layout of the block container, but there still might be issues with float interaction with mixed RTL and LTR. While this does move us closer to supporting vertical writing modes, this is still unsupported. New failures: - Vertical writing mode not supported: - `/css/CSS2/floats/floats-placement-vertical-001b.xht` - `/css/CSS2/floats/floats-placement-vertical-001c.xht` - Absolutes inlines should avoid floats (#33323) - `/css/css-position/position-absolute-dynamic-static-position-floats-004.html` - No support for grid - `/css/css-align/self-alignment/self-align-safe-unsafe-grid-003.html` - `/css/css-position/static-position/inline-level-absolute-in-block-level-context-009.html` - `/css/css-position/static-position/inline-level-absolute-in-block-level-context-010.html` - Cannot reproduce these locally on any platform. Very mysterious: - `/css/css-tables/row-group-margin-border-padding.html` - `/css/css-tables/row-margin-border-padding.html` - Exposes bugs we have related to hanging whitespace in preserved whitespace inlines: - `/css/css-text/white-space/trailing-space-and-text-alignment-rtl-003.html` - `/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-023.html` Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Rakhi Sharma <atbrakhi@igalia.com>
This commit is contained in:
parent
bc8d8b62c3
commit
027fc53e2f
99 changed files with 946 additions and 867 deletions
|
@ -707,7 +707,6 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
painting_area_override: None,
|
||||
positioning_area_override: Some(
|
||||
positioning_area
|
||||
.to_physical(self.fragment.style.effective_writing_mode())
|
||||
.translate(self.containing_block.origin.to_vector())
|
||||
.to_webrender(),
|
||||
),
|
||||
|
|
|
@ -171,13 +171,13 @@ impl FlexItemLayoutResult {
|
|||
let flags = fragment_info.flags;
|
||||
|
||||
let containing_block = flex_context.containing_block;
|
||||
let container_writing_mode = containing_block.effective_writing_mode();
|
||||
let container_writing_mode = containing_block.style.writing_mode;
|
||||
let style = item.box_.style();
|
||||
let mut fragment = BoxFragment::new(
|
||||
fragment_info,
|
||||
style.clone(),
|
||||
self.fragments,
|
||||
content_rect.to_physical(container_writing_mode),
|
||||
content_rect.to_physical(Some(flex_context.containing_block)),
|
||||
flex_context
|
||||
.sides_to_flow_relative(item.padding)
|
||||
.to_physical(container_writing_mode),
|
||||
|
@ -199,7 +199,7 @@ impl FlexItemLayoutResult {
|
|||
|
||||
if style.clone_position() == Position::Relative {
|
||||
fragment.content_rect.origin += relative_adjustement(style, containing_block)
|
||||
.to_physical_size(containing_block.effective_writing_mode())
|
||||
.to_physical_size(containing_block.style.writing_mode)
|
||||
}
|
||||
|
||||
(fragment, self.positioning_context)
|
||||
|
@ -409,7 +409,7 @@ impl FlexContainer {
|
|||
let mut sum_of_flex_shrink_factors = 0.0;
|
||||
let mut item_infos = vec![];
|
||||
|
||||
let container_is_horizontal = self.style.effective_writing_mode().is_horizontal();
|
||||
let container_is_horizontal = self.style.writing_mode.is_horizontal();
|
||||
for kid in self.children.iter() {
|
||||
let kid = &mut *kid.borrow_mut();
|
||||
match kid {
|
||||
|
@ -806,8 +806,8 @@ impl FlexContainer {
|
|||
all_baselines.last = line_all_baselines.last;
|
||||
}
|
||||
|
||||
let physical_line_position = flow_relative_line_position
|
||||
.to_physical_size(self.style.effective_writing_mode());
|
||||
let physical_line_position =
|
||||
flow_relative_line_position.to_physical_size(self.style.writing_mode);
|
||||
for (fragment, _) in &mut final_line_layout.item_fragments {
|
||||
fragment.content_rect.origin += physical_line_position;
|
||||
}
|
||||
|
@ -912,12 +912,13 @@ impl FlexContainer {
|
|||
start_corner: LogicalVec2::zero(),
|
||||
size: self.config.flex_axis.vec2_to_flow_relative(container_size),
|
||||
}
|
||||
.to_physical(containing_block.effective_writing_mode());
|
||||
.to_physical(Some(containing_block));
|
||||
|
||||
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
|
||||
absolutely_positioned_box,
|
||||
static_position_rect,
|
||||
logical_alignment,
|
||||
self.config.writing_mode,
|
||||
);
|
||||
let hoisted_fragment = hoisted_box.fragment.clone();
|
||||
positioning_context.push(hoisted_box);
|
||||
|
@ -995,14 +996,8 @@ 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!(
|
||||
parent_writing_mode, item_writing_mode,
|
||||
"Mixed writing modes are not supported yet"
|
||||
);
|
||||
let parent_writing_mode = containing_block.style.writing_mode;
|
||||
let item_writing_mode = box_.style().writing_mode;
|
||||
|
||||
let container_is_horizontal = parent_writing_mode.is_horizontal();
|
||||
let item_is_horizontal = item_writing_mode.is_horizontal();
|
||||
|
@ -1697,15 +1692,6 @@ impl FlexItem<'_> {
|
|||
)
|
||||
});
|
||||
|
||||
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
|
||||
let container_writing_mode = containing_block.effective_writing_mode();
|
||||
assert_eq!(
|
||||
container_writing_mode,
|
||||
self.box_.style().effective_writing_mode(),
|
||||
"Mixed writing modes are not supported yet"
|
||||
);
|
||||
// … and also the item’s inline axis.
|
||||
|
||||
let cross_size = match used_cross_size_override {
|
||||
Some(s) => AuOrAuto::LengthPercentage(s),
|
||||
None => self.content_box_size.cross.map(|cross_size| {
|
||||
|
@ -1717,14 +1703,11 @@ impl FlexItem<'_> {
|
|||
};
|
||||
|
||||
let ifc = &mut self.box_.independent_formatting_context;
|
||||
let item_writing_mode = ifc.style().effective_writing_mode();
|
||||
let item_writing_mode = ifc.style().writing_mode;
|
||||
let item_is_horizontal = item_writing_mode.is_horizontal();
|
||||
let flex_axis = flex_context.config.flex_axis;
|
||||
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
|
||||
containing_block
|
||||
.style
|
||||
.effective_writing_mode()
|
||||
.is_horizontal(),
|
||||
containing_block.style.writing_mode.is_horizontal(),
|
||||
item_is_horizontal,
|
||||
flex_axis,
|
||||
);
|
||||
|
@ -1769,6 +1752,7 @@ impl FlexItem<'_> {
|
|||
)
|
||||
};
|
||||
|
||||
let container_writing_mode = containing_block.style.writing_mode;
|
||||
match ifc {
|
||||
IndependentFormattingContext::Replaced(replaced) => {
|
||||
let size = replaced
|
||||
|
@ -1820,7 +1804,7 @@ impl FlexItem<'_> {
|
|||
|
||||
let item_writing_mode_is_orthogonal_to_container_writing_mode =
|
||||
flex_context.config.writing_mode.is_horizontal() !=
|
||||
non_replaced.style.effective_writing_mode().is_horizontal();
|
||||
non_replaced.style.writing_mode.is_horizontal();
|
||||
let has_compatible_baseline = match flex_context.config.flex_axis {
|
||||
FlexAxis::Row => !item_writing_mode_is_orthogonal_to_container_writing_mode,
|
||||
FlexAxis::Column => item_writing_mode_is_orthogonal_to_container_writing_mode,
|
||||
|
@ -2013,7 +1997,7 @@ impl FlexItemBox {
|
|||
let flex_axis = config.flex_axis;
|
||||
let main_start_cross_start = config.main_start_cross_start_sides_are;
|
||||
let style = self.style().clone();
|
||||
let item_writing_mode = style.effective_writing_mode();
|
||||
let item_writing_mode = style.writing_mode;
|
||||
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, flex_axis);
|
||||
|
|
|
@ -17,7 +17,6 @@ use crate::cell::ArcRefCell;
|
|||
use crate::formatting_contexts::IndependentFormattingContext;
|
||||
use crate::fragment_tree::BaseFragmentInfo;
|
||||
use crate::positioned::AbsolutelyPositionedBox;
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
|
||||
mod construct;
|
||||
mod geom;
|
||||
|
@ -69,7 +68,7 @@ impl FlexContainerConfig {
|
|||
|
||||
FlexContainerConfig {
|
||||
container_is_single_line,
|
||||
writing_mode: container_style.effective_writing_mode(),
|
||||
writing_mode: container_style.writing_mode,
|
||||
flex_axis,
|
||||
flex_direction,
|
||||
flex_direction_is_reversed,
|
||||
|
|
|
@ -16,6 +16,7 @@ use euclid::num::Zero;
|
|||
use serde::Serialize;
|
||||
use servo_arc::Arc;
|
||||
use style::computed_values::float::T as FloatProperty;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::Clear;
|
||||
|
@ -26,8 +27,8 @@ use crate::dom::NodeExt;
|
|||
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
|
||||
use crate::formatting_contexts::IndependentFormattingContext;
|
||||
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, CollapsedMargin};
|
||||
use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
|
||||
use crate::positioned::PositioningContext;
|
||||
use crate::geom::{LogicalRect, LogicalVec2, PhysicalPoint, PhysicalRect, ToLogical};
|
||||
use crate::positioned::{relative_adjustement, PositioningContext};
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, DisplayInside, PaddingBorderMargin};
|
||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||
|
||||
|
@ -412,7 +413,7 @@ impl FloatContext {
|
|||
|
||||
// The object fits perfectly here. Place it.
|
||||
match object.side {
|
||||
FloatSide::Left => {
|
||||
FloatSide::InlineStart => {
|
||||
let left_object_edge = match first_band.left {
|
||||
Some(band_left) => band_left.max(self.containing_block_info.inline_start),
|
||||
None => self.containing_block_info.inline_start,
|
||||
|
@ -422,7 +423,7 @@ impl FloatContext {
|
|||
block: first_band.top.max(ceiling),
|
||||
}
|
||||
},
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
let right_object_edge = match first_band.right {
|
||||
Some(band_right) => band_right.min(self.containing_block_info.inline_end),
|
||||
None => self.containing_block_info.inline_end,
|
||||
|
@ -441,8 +442,8 @@ impl FloatContext {
|
|||
let ceiling = self.ceiling();
|
||||
let new_float_origin = self.place_object(new_float, ceiling);
|
||||
let new_float_extent = match new_float.side {
|
||||
FloatSide::Left => new_float_origin.inline + new_float.size.inline,
|
||||
FloatSide::Right => new_float_origin.inline,
|
||||
FloatSide::InlineStart => new_float_origin.inline + new_float.size.inline,
|
||||
FloatSide::InlineEnd => new_float_origin.inline,
|
||||
};
|
||||
|
||||
let new_float_rect = LogicalRect {
|
||||
|
@ -459,11 +460,11 @@ impl FloatContext {
|
|||
|
||||
// Update clear.
|
||||
match new_float.side {
|
||||
FloatSide::Left => {
|
||||
FloatSide::InlineStart => {
|
||||
self.clear_left_position
|
||||
.max_assign(new_float_rect.max_block_position());
|
||||
},
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
self.clear_right_position
|
||||
.max_assign(new_float_rect.max_block_position());
|
||||
},
|
||||
|
@ -513,8 +514,8 @@ pub struct PlacementInfo {
|
|||
/// See CSS 2.1 § 9.5.1: <https://www.w3.org/TR/CSS2/visuren.html#float-position>
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum FloatSide {
|
||||
Left,
|
||||
Right,
|
||||
InlineStart,
|
||||
InlineEnd,
|
||||
}
|
||||
|
||||
/// Internal data structure that describes a nonoverlapping vertical region in which floats may be
|
||||
|
@ -536,11 +537,18 @@ pub struct FloatBand {
|
|||
}
|
||||
|
||||
impl FloatSide {
|
||||
fn from_style(style: &ComputedValues) -> Option<FloatSide> {
|
||||
match style.get_box().float {
|
||||
FloatProperty::None => None,
|
||||
FloatProperty::Left => Some(FloatSide::Left),
|
||||
FloatProperty::Right => Some(FloatSide::Right),
|
||||
fn from_style_and_container_writing_mode(
|
||||
style: &ComputedValues,
|
||||
container_writing_mode: WritingMode,
|
||||
) -> Option<FloatSide> {
|
||||
match (style.get_box().float, container_writing_mode.is_bidi_ltr()) {
|
||||
(FloatProperty::None, _) => None,
|
||||
(FloatProperty::Left, true) | (FloatProperty::Right, false) => {
|
||||
Some(FloatSide::InlineStart)
|
||||
},
|
||||
(FloatProperty::Right, true) | (FloatProperty::Left, false) => {
|
||||
Some(FloatSide::InlineEnd)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -549,7 +557,7 @@ impl FloatBand {
|
|||
/// Determines whether an object fits in a band. Returns true if the object fits.
|
||||
fn object_fits(&self, object: &PlacementInfo, walls: &ContainingBlockPositionInfo) -> bool {
|
||||
match object.side {
|
||||
FloatSide::Left => {
|
||||
FloatSide::InlineStart => {
|
||||
// Compute a candidate left position for the object.
|
||||
let candidate_left = match self.left {
|
||||
None => walls.inline_start,
|
||||
|
@ -570,7 +578,7 @@ impl FloatBand {
|
|||
}
|
||||
},
|
||||
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
// Compute a candidate right position for the object.
|
||||
let candidate_right = match self.right {
|
||||
None => walls.inline_end,
|
||||
|
@ -694,13 +702,13 @@ impl FloatBandNode {
|
|||
let mut new_band = self.band;
|
||||
if self.band.top >= range.start && self.band.top < range.end {
|
||||
match side {
|
||||
FloatSide::Left => {
|
||||
FloatSide::InlineStart => {
|
||||
new_band.left = match new_band.left {
|
||||
Some(old_value) => Some(std::cmp::max(old_value, new_value)),
|
||||
None => Some(new_value),
|
||||
};
|
||||
},
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
new_band.right = match new_band.right {
|
||||
Some(old_value) => Some(std::cmp::min(old_value, new_value)),
|
||||
None => Some(new_value),
|
||||
|
@ -984,23 +992,22 @@ impl FloatBox {
|
|||
);
|
||||
children = replaced.contents.make_fragments(
|
||||
&replaced.style,
|
||||
content_size
|
||||
.to_physical_size(containing_block.effective_writing_mode()),
|
||||
content_size.to_physical_size(containing_block.style.writing_mode),
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
let content_rect = LogicalRect {
|
||||
start_corner: LogicalVec2::zero(),
|
||||
size: content_size,
|
||||
};
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
let content_rect = PhysicalRect::new(
|
||||
PhysicalPoint::zero(),
|
||||
content_size.to_physical_size(containing_block_writing_mode),
|
||||
);
|
||||
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
BoxFragment::new(
|
||||
self.contents.base_fragment_info(),
|
||||
style.clone(),
|
||||
children,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect,
|
||||
pbm.padding.to_physical(containing_block_writing_mode),
|
||||
pbm.border.to_physical(containing_block_writing_mode),
|
||||
margin.to_physical(containing_block_writing_mode),
|
||||
|
@ -1203,7 +1210,7 @@ impl SequentialLayoutState {
|
|||
pub(crate) fn place_float_fragment(
|
||||
&mut self,
|
||||
box_fragment: &mut BoxFragment,
|
||||
container_writing_mode: WritingMode,
|
||||
containing_block: &ContainingBlock,
|
||||
margins_collapsing_with_parent_containing_block: CollapsedMargin,
|
||||
block_offset_from_containing_block_top: Au,
|
||||
) {
|
||||
|
@ -1218,19 +1225,35 @@ impl SequentialLayoutState {
|
|||
block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top,
|
||||
);
|
||||
|
||||
let pbm_sums = (box_fragment.padding + box_fragment.border + box_fragment.margin)
|
||||
let container_writing_mode = containing_block.style.writing_mode;
|
||||
let logical_float_size = box_fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(container_writing_mode);
|
||||
let pbm_sums = box_fragment
|
||||
.padding_border_margin()
|
||||
.to_logical(container_writing_mode);
|
||||
let content_rect = &box_fragment.content_rect.to_logical(container_writing_mode);
|
||||
let margin_box_start_corner = self.floats.add_float(&PlacementInfo {
|
||||
size: content_rect.size + pbm_sums.sum(),
|
||||
side: FloatSide::from_style(&box_fragment.style).expect("Float box wasn't floated!"),
|
||||
size: logical_float_size + pbm_sums.sum(),
|
||||
side: FloatSide::from_style_and_container_writing_mode(
|
||||
&box_fragment.style,
|
||||
container_writing_mode,
|
||||
)
|
||||
.expect("Float box wasn't floated!"),
|
||||
clear: box_fragment.style.get_box().clear,
|
||||
});
|
||||
|
||||
// Re-calculate relative adjustment so that it is not lost when the BoxFragment's
|
||||
// `content_rect` is overwritten below.
|
||||
let relative_offset = match box_fragment.style.clone_position() {
|
||||
Position::Relative => relative_adjustement(&box_fragment.style, containing_block),
|
||||
_ => LogicalVec2::zero(),
|
||||
};
|
||||
|
||||
// This is the position of the float in the float-containing block formatting context. We add the
|
||||
// existing start corner here because we may have already gotten some relative positioning offset.
|
||||
let new_position_in_bfc =
|
||||
margin_box_start_corner + pbm_sums.start_offset() + content_rect.start_corner;
|
||||
margin_box_start_corner + pbm_sums.start_offset() + relative_offset;
|
||||
|
||||
// This is the position of the float relative to the containing block start.
|
||||
let new_position_in_containing_block = LogicalVec2 {
|
||||
|
@ -1238,7 +1261,13 @@ impl SequentialLayoutState {
|
|||
block: new_position_in_bfc.block - block_start_of_containing_block_in_bfc,
|
||||
};
|
||||
|
||||
box_fragment.content_rect.origin =
|
||||
new_position_in_containing_block.to_physical_point(container_writing_mode);
|
||||
box_fragment.content_rect = LogicalRect {
|
||||
start_corner: new_position_in_containing_block,
|
||||
size: box_fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(container_writing_mode),
|
||||
}
|
||||
.to_physical(Some(&containing_block));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use app_units::Au;
|
||||
use bitflags::bitflags;
|
||||
use fonts::{FontMetrics, GlyphStore};
|
||||
use itertools::Either;
|
||||
use servo_arc::Arc;
|
||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -14,7 +15,6 @@ use style::values::generics::font::LineHeight;
|
|||
use style::values::specified::align::AlignFlags;
|
||||
use style::values::specified::box_::DisplayOutside;
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::values::Either;
|
||||
use style::Zero;
|
||||
use unicode_bidi::{BidiInfo, Level};
|
||||
use webrender_api::FontInstanceKey;
|
||||
|
@ -25,10 +25,11 @@ use crate::cell::ArcRefCell;
|
|||
use crate::fragment_tree::{
|
||||
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment,
|
||||
};
|
||||
use crate::geom::{LogicalRect, LogicalVec2};
|
||||
use crate::geom::{AuOrAuto, LogicalRect, LogicalVec2, PhysicalRect, ToLogical};
|
||||
use crate::positioned::{
|
||||
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
||||
};
|
||||
use crate::ContainingBlock;
|
||||
|
||||
pub(super) struct LineMetrics {
|
||||
/// The block offset of the line start in the containing
|
||||
|
@ -49,10 +50,10 @@ bitflags! {
|
|||
const HAD_ANY_LINE_ITEMS = 1 << 0;
|
||||
/// Whether or not the starting inline border, padding, or margin of the inline box
|
||||
/// was encountered.
|
||||
const HAD_START_PBM = 1 << 2;
|
||||
const HAD_LEFT_PBM = 1 << 2;
|
||||
/// Whether or not the ending inline border, padding, or margin of the inline box
|
||||
/// was encountered.
|
||||
const HAD_END_PBM = 1 << 3;
|
||||
const HAD_RIGHT_PBM = 1 << 3;
|
||||
/// Whether or not any floats were encountered while laying out this inline box.
|
||||
const HAD_ANY_FLOATS = 1 << 4;
|
||||
}
|
||||
|
@ -66,16 +67,21 @@ pub(super) struct LineItemLayoutInlineContainerState {
|
|||
/// that is currently being laid out.
|
||||
pub identifier: Option<InlineBoxIdentifier>,
|
||||
|
||||
/// The fragments that are laid out into this inline container on a line.
|
||||
pub fragments: Vec<Fragment>,
|
||||
/// The fragments and their logical rectangle relative within the current inline box (or
|
||||
/// line). These logical rectangles will be converted into physical ones and the Fragment's
|
||||
/// `content_rect` will be updated once the inline box's final size is known in
|
||||
/// [`LineItemLayout::end_inline_box`].
|
||||
pub fragments: Vec<(Fragment, LogicalRect<Au>)>,
|
||||
|
||||
/// The current inline adavnce of the layout in the coordinates of this inline box.
|
||||
/// The current inline advance of the layout in the coordinates of this inline box.
|
||||
pub inline_advance: Au,
|
||||
|
||||
/// Flags which track various features during layout.
|
||||
flags: LineLayoutInlineContainerFlags,
|
||||
|
||||
/// The offset of the parent, relative to the start position of the line.
|
||||
/// The offset of the parent, relative to the start position of the line, not including
|
||||
/// any inline start and end borders which are only processed when the inline box is
|
||||
/// finished.
|
||||
pub parent_offset: LogicalVec2<Au>,
|
||||
|
||||
/// The block offset of the parent's baseline relative to the block start of the line. This
|
||||
|
@ -117,7 +123,7 @@ impl LineItemLayoutInlineContainerState {
|
|||
None,
|
||||
LogicalVec2::zero(),
|
||||
baseline_offset,
|
||||
Either::Second(PositioningContextLength::zero()),
|
||||
Either::Right(PositioningContextLength::zero()),
|
||||
);
|
||||
state.inline_advance = starting_inline_advance;
|
||||
state
|
||||
|
@ -208,8 +214,8 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
// TODO: This level needs either to be last_level, or if there were
|
||||
// unicode characters inserted for the inline box, we need to get the
|
||||
// level from them.
|
||||
LineItem::StartInlineBoxPaddingBorderMargin(_) => last_level,
|
||||
LineItem::EndInlineBoxPaddingBorderMargin(_) => last_level,
|
||||
LineItem::LeftInlineBoxPaddingBorderMargin(_) => last_level,
|
||||
LineItem::RightInlineBoxPaddingBorderMargin(_) => last_level,
|
||||
LineItem::Atomic(_, atomic) => atomic.bidi_level,
|
||||
LineItem::AbsolutelyPositioned(..) => last_level,
|
||||
LineItem::Float(..) => {
|
||||
|
@ -227,7 +233,25 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
sort_by_indices_in_place(&mut line_items, BidiInfo::reorder_visual(&levels));
|
||||
}
|
||||
|
||||
for item in line_items.into_iter().by_ref() {
|
||||
// `BidiInfo::reorder_visual` will reorder the contents of the line so that they
|
||||
// are in the correct order as if one was looking at the line from left-to-right.
|
||||
// During this layout we do not lay out from left to right. Instead we lay out
|
||||
// from inline-start to inline-end. If the overall line contents have been flipped
|
||||
// for BiDi, flip them again so that they are in line start-to-end order rather
|
||||
// than left-to-right order.
|
||||
let line_item_iterator = if self
|
||||
.layout
|
||||
.containing_block
|
||||
.style
|
||||
.writing_mode
|
||||
.is_bidi_ltr()
|
||||
{
|
||||
Either::Left(line_items.into_iter())
|
||||
} else {
|
||||
Either::Right(line_items.into_iter().rev())
|
||||
};
|
||||
|
||||
for item in line_item_iterator.into_iter().by_ref() {
|
||||
// When preparing to lay out a new line item, start and end inline boxes, so that the current
|
||||
// inline box state reflects the item's parent. Items in the line are not necessarily in tree
|
||||
// order due to BiDi and other reordering so the inline box of the item could potentially be
|
||||
|
@ -238,15 +262,15 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
.flags
|
||||
.insert(LineLayoutInlineContainerFlags::HAD_ANY_LINE_ITEMS);
|
||||
match item {
|
||||
LineItem::StartInlineBoxPaddingBorderMargin(_) => {
|
||||
LineItem::LeftInlineBoxPaddingBorderMargin(_) => {
|
||||
self.current_state
|
||||
.flags
|
||||
.insert(LineLayoutInlineContainerFlags::HAD_START_PBM);
|
||||
.insert(LineLayoutInlineContainerFlags::HAD_LEFT_PBM);
|
||||
},
|
||||
LineItem::EndInlineBoxPaddingBorderMargin(_) => {
|
||||
LineItem::RightInlineBoxPaddingBorderMargin(_) => {
|
||||
self.current_state
|
||||
.flags
|
||||
.insert(LineLayoutInlineContainerFlags::HAD_END_PBM);
|
||||
.insert(LineLayoutInlineContainerFlags::HAD_RIGHT_PBM);
|
||||
},
|
||||
LineItem::TextRun(_, text_run) => self.layout_text_run(text_run),
|
||||
LineItem::Atomic(_, atomic) => self.layout_atomic(atomic),
|
||||
|
@ -257,11 +281,29 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
|
||||
// Move back to the root of the inline box tree, so that all boxes are ended.
|
||||
self.prepare_layout_for_inline_box(None);
|
||||
std::mem::take(&mut self.current_state.fragments)
|
||||
|
||||
let fragments_and_rectangles = std::mem::take(&mut self.current_state.fragments);
|
||||
fragments_and_rectangles
|
||||
.into_iter()
|
||||
.map(|(mut fragment, logical_rect)| {
|
||||
if matches!(fragment, Fragment::Float(_)) {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// We do not know the actual physical position of a logically laid out inline element, until
|
||||
// we know the width of the containing inline block. This step converts the logical rectangle
|
||||
// into a physical one based on the inline formatting context width.
|
||||
if let Some(content_rect) = fragment.content_rect_mut() {
|
||||
*content_rect = logical_rect.to_physical(Some(self.layout.containing_block))
|
||||
}
|
||||
|
||||
fragment
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn current_positioning_context_mut(&mut self) -> &mut PositioningContext {
|
||||
if let Either::First(ref mut positioning_context) = self
|
||||
if let Either::Left(ref mut positioning_context) = self
|
||||
.current_state
|
||||
.positioning_context_or_start_offset_in_parent
|
||||
{
|
||||
|
@ -272,8 +314,8 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
.rev()
|
||||
.find_map(
|
||||
|state| match state.positioning_context_or_start_offset_in_parent {
|
||||
Either::First(ref mut positioning_context) => Some(positioning_context),
|
||||
Either::Second(_) => None,
|
||||
Either::Left(ref mut positioning_context) => Some(positioning_context),
|
||||
Either::Right(_) => None,
|
||||
},
|
||||
)
|
||||
.unwrap_or(self.layout.positioning_context)
|
||||
|
@ -292,8 +334,8 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
|
||||
let positioning_context_or_start_offset_in_parent =
|
||||
match PositioningContext::new_for_style(style) {
|
||||
Some(positioning_context) => Either::First(positioning_context),
|
||||
None => Either::Second(self.current_positioning_context_mut().len()),
|
||||
Some(positioning_context) => Either::Left(positioning_context),
|
||||
None => Either::Right(self.current_positioning_context_mut().len()),
|
||||
};
|
||||
|
||||
let parent_offset = LogicalVec2 {
|
||||
|
@ -316,7 +358,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
|
||||
fn end_inline_box(&mut self) {
|
||||
let outer_state = self.state_stack.pop().expect("Ended unknown inline box");
|
||||
let mut inner_state = std::mem::replace(&mut self.current_state, outer_state);
|
||||
let inner_state = std::mem::replace(&mut self.current_state, outer_state);
|
||||
|
||||
let identifier = inner_state.identifier.expect("Ended unknown inline box");
|
||||
let inline_box_state =
|
||||
|
@ -328,12 +370,24 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
let mut border = inline_box_state.pbm.border;
|
||||
let mut margin = inline_box_state.pbm.margin.auto_is(Au::zero);
|
||||
|
||||
let had_start = inner_state
|
||||
let had_left = inner_state
|
||||
.flags
|
||||
.contains(LineLayoutInlineContainerFlags::HAD_START_PBM);
|
||||
let had_end = inner_state
|
||||
.contains(LineLayoutInlineContainerFlags::HAD_LEFT_PBM);
|
||||
let had_right = inner_state
|
||||
.flags
|
||||
.contains(LineLayoutInlineContainerFlags::HAD_END_PBM);
|
||||
.contains(LineLayoutInlineContainerFlags::HAD_RIGHT_PBM);
|
||||
|
||||
let (had_start, had_end) = if self
|
||||
.layout
|
||||
.containing_block
|
||||
.style
|
||||
.writing_mode
|
||||
.is_bidi_ltr()
|
||||
{
|
||||
(had_left, had_right)
|
||||
} else {
|
||||
(had_right, had_left)
|
||||
};
|
||||
|
||||
if !had_start {
|
||||
padding.inline_start = Au::zero();
|
||||
|
@ -368,14 +422,6 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
},
|
||||
};
|
||||
|
||||
let ifc_writing_mode = self.layout.containing_block.effective_writing_mode();
|
||||
for fragment in inner_state.fragments.iter_mut() {
|
||||
if let Fragment::Float(box_fragment) = fragment {
|
||||
box_fragment.content_rect.origin -=
|
||||
pbm_sums.start_offset().to_physical_size(ifc_writing_mode);
|
||||
}
|
||||
}
|
||||
|
||||
// Relative adjustment should not affect the rest of line layout, so we can
|
||||
// do it right before creating the Fragment.
|
||||
let style = &inline_box.style;
|
||||
|
@ -383,11 +429,40 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
content_rect.start_corner += relative_adjustement(style, self.layout.containing_block);
|
||||
}
|
||||
|
||||
let ifc_writing_mode = self.layout.containing_block.style.writing_mode;
|
||||
let inline_box_containing_block = ContainingBlock {
|
||||
inline_size: content_rect.size.inline,
|
||||
block_size: AuOrAuto::Auto,
|
||||
style: &self.layout.containing_block.style,
|
||||
};
|
||||
let fragments = inner_state
|
||||
.fragments
|
||||
.into_iter()
|
||||
.map(|(mut fragment, logical_rect)| {
|
||||
let is_float = matches!(fragment, Fragment::Float(_));
|
||||
if let Some(content_rect) = fragment.content_rect_mut() {
|
||||
if is_float {
|
||||
content_rect.origin -=
|
||||
pbm_sums.start_offset().to_physical_size(ifc_writing_mode);
|
||||
} else {
|
||||
// We do not know the actual physical position of a logically laid out inline element, until
|
||||
// we know the width of the containing inline block. This step converts the logical rectangle
|
||||
// into a physical one now that we've computed inline size of the containing inline block above.
|
||||
*content_rect = logical_rect.to_physical(Some(&inline_box_containing_block))
|
||||
}
|
||||
}
|
||||
fragment
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Previously all the fragment's children were positioned relative to the linebox,
|
||||
// but they need to be made relative to this fragment.
|
||||
let physical_content_rect = content_rect.to_physical(Some(self.layout.containing_block));
|
||||
let mut fragment = BoxFragment::new(
|
||||
inline_box.base_fragment_info,
|
||||
style.clone(),
|
||||
inner_state.fragments,
|
||||
content_rect.to_physical(ifc_writing_mode),
|
||||
fragments,
|
||||
physical_content_rect,
|
||||
padding.to_physical(ifc_writing_mode),
|
||||
border.to_physical(ifc_writing_mode),
|
||||
margin.to_physical(ifc_writing_mode),
|
||||
|
@ -395,28 +470,36 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
CollapsedBlockMargins::zero(),
|
||||
);
|
||||
|
||||
let offset_from_parent_ifc = LogicalVec2 {
|
||||
inline: pbm_sums.inline_start + self.current_state.inline_advance,
|
||||
block: content_rect.start_corner.block,
|
||||
}
|
||||
.to_physical_vector(self.layout.containing_block.style.writing_mode);
|
||||
|
||||
match inner_state.positioning_context_or_start_offset_in_parent {
|
||||
Either::First(mut positioning_context) => {
|
||||
Either::Left(mut positioning_context) => {
|
||||
positioning_context
|
||||
.layout_collected_children(self.layout.layout_context, &mut fragment);
|
||||
positioning_context.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&fragment.content_rect.origin.to_vector(),
|
||||
&offset_from_parent_ifc,
|
||||
PositioningContextLength::zero(),
|
||||
);
|
||||
self.current_positioning_context_mut()
|
||||
.append(positioning_context);
|
||||
},
|
||||
Either::Second(start_offset) => {
|
||||
Either::Right(start_offset) => {
|
||||
self.current_positioning_context_mut()
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&fragment.content_rect.origin.to_vector(),
|
||||
&offset_from_parent_ifc,
|
||||
start_offset,
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
self.current_state.inline_advance += inner_state.inline_advance + pbm_sums.inline_sum();
|
||||
self.current_state.fragments.push(Fragment::Box(fragment));
|
||||
self.current_state
|
||||
.fragments
|
||||
.push((Fragment::Box(fragment), content_rect));
|
||||
}
|
||||
|
||||
fn calculate_inline_box_block_start(
|
||||
|
@ -477,8 +560,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
text_item.font_metrics.ascent -
|
||||
self.current_state.parent_offset.block,
|
||||
};
|
||||
|
||||
let rect = LogicalRect {
|
||||
let content_rect = LogicalRect {
|
||||
start_corner,
|
||||
size: LogicalVec2 {
|
||||
block: text_item.font_metrics.line_gap,
|
||||
|
@ -487,29 +569,37 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
};
|
||||
|
||||
self.current_state.inline_advance += inline_advance;
|
||||
self.current_state
|
||||
.fragments
|
||||
.push(Fragment::Text(TextFragment {
|
||||
self.current_state.fragments.push((
|
||||
Fragment::Text(TextFragment {
|
||||
base: text_item.base_fragment_info.into(),
|
||||
parent_style: text_item.parent_style,
|
||||
rect: rect.to_physical(self.layout.containing_block.effective_writing_mode()),
|
||||
rect: PhysicalRect::zero(),
|
||||
font_metrics: text_item.font_metrics,
|
||||
font_key: text_item.font_key,
|
||||
glyphs: text_item.text,
|
||||
text_decoration_line: text_item.text_decoration_line,
|
||||
justification_adjustment: self.justification_adjustment,
|
||||
}));
|
||||
}),
|
||||
content_rect,
|
||||
));
|
||||
}
|
||||
|
||||
fn layout_atomic(&mut self, mut atomic: AtomicLineItem) {
|
||||
fn layout_atomic(&mut self, atomic: AtomicLineItem) {
|
||||
// The initial `start_corner` of the Fragment is only the PaddingBorderMargin sum start
|
||||
// offset, which is the sum of the start component of the padding, border, and margin.
|
||||
// This needs to be added to the calculated block and inline positions.
|
||||
// Make the final result relative to the parent box.
|
||||
let ifc_writing_mode = self.layout.containing_block.style.writing_mode;
|
||||
let padding_border_margin_sides = atomic
|
||||
.fragment
|
||||
.padding_border_margin()
|
||||
.to_logical(ifc_writing_mode);
|
||||
|
||||
let mut atomic_offset = LogicalVec2 {
|
||||
inline: self.current_state.inline_advance,
|
||||
inline: self.current_state.inline_advance + padding_border_margin_sides.inline_start,
|
||||
block: atomic.calculate_block_start(&self.line_metrics) -
|
||||
self.current_state.parent_offset.block,
|
||||
self.current_state.parent_offset.block +
|
||||
padding_border_margin_sides.block_start,
|
||||
};
|
||||
|
||||
if atomic.fragment.style.clone_position().is_relative() {
|
||||
|
@ -517,14 +607,25 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
relative_adjustement(&atomic.fragment.style, self.layout.containing_block);
|
||||
}
|
||||
|
||||
let ifc_writing_mode = self.layout.containing_block.effective_writing_mode();
|
||||
atomic.fragment.content_rect.origin += atomic_offset.to_physical_size(ifc_writing_mode);
|
||||
// Reconstruct a logical rectangle relative to the inline box container that will be used
|
||||
// after the inline box is procesed to find a final physical rectangle.
|
||||
let content_rect = LogicalRect {
|
||||
start_corner: atomic_offset,
|
||||
size: atomic
|
||||
.fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(ifc_writing_mode),
|
||||
};
|
||||
|
||||
if let Some(mut positioning_context) = atomic.positioning_context {
|
||||
let physical_rect_as_if_in_root =
|
||||
content_rect.to_physical(Some(self.layout.containing_block));
|
||||
positioning_context.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&atomic.fragment.content_rect.origin.to_vector(),
|
||||
&physical_rect_as_if_in_root.origin.to_vector(),
|
||||
PositioningContextLength::zero(),
|
||||
);
|
||||
|
||||
self.current_positioning_context_mut()
|
||||
.append(positioning_context);
|
||||
}
|
||||
|
@ -532,7 +633,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
self.current_state.inline_advance += atomic.size.inline;
|
||||
self.current_state
|
||||
.fragments
|
||||
.push(Fragment::Box(atomic.fragment));
|
||||
.push((Fragment::Box(atomic.fragment), content_rect));
|
||||
}
|
||||
|
||||
fn layout_absolute(&mut self, absolute: AbsolutelyPositionedLineItem) {
|
||||
|
@ -572,7 +673,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
start_corner: initial_start_corner,
|
||||
size: LogicalVec2::zero(),
|
||||
}
|
||||
.to_physical(self.layout.containing_block.effective_writing_mode());
|
||||
.to_physical(Some(self.layout.containing_block));
|
||||
|
||||
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
|
||||
absolute.absolutely_positioned_box.clone(),
|
||||
|
@ -581,12 +682,15 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
inline: AlignFlags::START,
|
||||
block: AlignFlags::START,
|
||||
},
|
||||
self.layout.containing_block.style.writing_mode,
|
||||
);
|
||||
|
||||
let hoisted_fragment = hoisted_box.fragment.clone();
|
||||
self.current_positioning_context_mut().push(hoisted_box);
|
||||
self.current_state
|
||||
.fragments
|
||||
.push(Fragment::AbsoluteOrFixedPositioned(hoisted_fragment));
|
||||
self.current_state.fragments.push((
|
||||
Fragment::AbsoluteOrFixedPositioned(hoisted_fragment),
|
||||
LogicalRect::zero(),
|
||||
));
|
||||
}
|
||||
|
||||
fn layout_float(&mut self, mut float: FloatLineItem) {
|
||||
|
@ -604,16 +708,17 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
block: self.line_metrics.block_offset + self.current_state.parent_offset.block,
|
||||
};
|
||||
float.fragment.content_rect.origin -= distance_from_parent_to_ifc
|
||||
.to_physical_size(self.layout.containing_block.effective_writing_mode());
|
||||
.to_physical_size(self.layout.containing_block.style.writing_mode);
|
||||
|
||||
self.current_state
|
||||
.fragments
|
||||
.push(Fragment::Float(float.fragment));
|
||||
.push((Fragment::Float(float.fragment), LogicalRect::zero()));
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) enum LineItem {
|
||||
StartInlineBoxPaddingBorderMargin(InlineBoxIdentifier),
|
||||
EndInlineBoxPaddingBorderMargin(InlineBoxIdentifier),
|
||||
LeftInlineBoxPaddingBorderMargin(InlineBoxIdentifier),
|
||||
RightInlineBoxPaddingBorderMargin(InlineBoxIdentifier),
|
||||
TextRun(Option<InlineBoxIdentifier>, TextRunLineItem),
|
||||
Atomic(Option<InlineBoxIdentifier>, AtomicLineItem),
|
||||
AbsolutelyPositioned(Option<InlineBoxIdentifier>, AbsolutelyPositionedLineItem),
|
||||
|
@ -623,8 +728,8 @@ pub(super) enum LineItem {
|
|||
impl LineItem {
|
||||
fn inline_box_identifier(&self) -> Option<InlineBoxIdentifier> {
|
||||
match self {
|
||||
LineItem::StartInlineBoxPaddingBorderMargin(identifier) => Some(*identifier),
|
||||
LineItem::EndInlineBoxPaddingBorderMargin(identifier) => Some(*identifier),
|
||||
LineItem::LeftInlineBoxPaddingBorderMargin(identifier) => Some(*identifier),
|
||||
LineItem::RightInlineBoxPaddingBorderMargin(identifier) => Some(*identifier),
|
||||
LineItem::TextRun(identifier, _) => *identifier,
|
||||
LineItem::Atomic(identifier, _) => *identifier,
|
||||
LineItem::AbsolutelyPositioned(identifier, _) => *identifier,
|
||||
|
@ -634,8 +739,8 @@ impl LineItem {
|
|||
|
||||
pub(super) fn trim_whitespace_at_end(&mut self, whitespace_trimmed: &mut Au) -> bool {
|
||||
match self {
|
||||
LineItem::StartInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::EndInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::LeftInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::RightInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::TextRun(_, ref mut item) => item.trim_whitespace_at_end(whitespace_trimmed),
|
||||
LineItem::Atomic(..) => false,
|
||||
LineItem::AbsolutelyPositioned(..) => true,
|
||||
|
@ -645,8 +750,8 @@ impl LineItem {
|
|||
|
||||
pub(super) fn trim_whitespace_at_start(&mut self, whitespace_trimmed: &mut Au) -> bool {
|
||||
match self {
|
||||
LineItem::StartInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::EndInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::LeftInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::RightInlineBoxPaddingBorderMargin(_) => true,
|
||||
LineItem::TextRun(_, ref mut item) => item.trim_whitespace_at_start(whitespace_trimmed),
|
||||
LineItem::Atomic(..) => false,
|
||||
LineItem::AbsolutelyPositioned(..) => true,
|
||||
|
|
|
@ -123,7 +123,7 @@ use crate::fragment_tree::{
|
|||
BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
|
||||
PositioningFragment,
|
||||
};
|
||||
use crate::geom::{LogicalRect, LogicalVec2, PhysicalRect, ToLogical};
|
||||
use crate::geom::{LogicalRect, LogicalVec2, PhysicalPoint, PhysicalRect, ToLogical};
|
||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||
use crate::sizing::ContentSizes;
|
||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||
|
@ -719,7 +719,7 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
inline_box_state.pbm.margin.inline_start.auto_is(Au::zero);
|
||||
self.current_line_segment
|
||||
.line_items
|
||||
.push(LineItem::StartInlineBoxPaddingBorderMargin(
|
||||
.push(LineItem::LeftInlineBoxPaddingBorderMargin(
|
||||
inline_box.identifier,
|
||||
));
|
||||
}
|
||||
|
@ -764,7 +764,7 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
self.current_line_segment.inline_size += pbm_end;
|
||||
self.current_line_segment
|
||||
.line_items
|
||||
.push(LineItem::EndInlineBoxPaddingBorderMargin(
|
||||
.push(LineItem::RightInlineBoxPaddingBorderMargin(
|
||||
inline_box_state.identifier,
|
||||
))
|
||||
}
|
||||
|
@ -872,30 +872,34 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
self.baselines.first.get_or_insert(baseline);
|
||||
self.baselines.last = Some(baseline);
|
||||
|
||||
let line_rect = LogicalRect {
|
||||
// The inline part of this start offset was taken into account when determining
|
||||
// the inline start of the line in `calculate_inline_start_for_current_line` so
|
||||
// we do not need to include it in the `start_corner` of the line's main Fragment.
|
||||
start_corner: LogicalVec2 {
|
||||
inline: Au::zero(),
|
||||
block: block_start_position,
|
||||
},
|
||||
// The inline part of this start offset was taken into account when determining
|
||||
// the inline start of the line in `calculate_inline_start_for_current_line` so
|
||||
// we do not need to include it in the `start_corner` of the line's main Fragment.
|
||||
let start_corner = LogicalVec2 {
|
||||
inline: Au::zero(),
|
||||
block: block_start_position,
|
||||
};
|
||||
|
||||
let logical_origin_in_physical_coordinates =
|
||||
start_corner.to_physical_vector(self.containing_block.style.writing_mode);
|
||||
self.positioning_context
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&logical_origin_in_physical_coordinates,
|
||||
start_positioning_context_length,
|
||||
);
|
||||
|
||||
let physical_line_rect = LogicalRect {
|
||||
start_corner,
|
||||
size: LogicalVec2 {
|
||||
inline: self.containing_block.inline_size,
|
||||
block: effective_block_advance.resolve(),
|
||||
},
|
||||
};
|
||||
|
||||
let line_rect = line_rect.to_physical(self.containing_block.effective_writing_mode());
|
||||
self.positioning_context
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&line_rect.origin.to_vector(),
|
||||
start_positioning_context_length,
|
||||
);
|
||||
|
||||
}
|
||||
.to_physical(Some(self.containing_block));
|
||||
self.fragments
|
||||
.push(Fragment::Positioning(PositioningFragment::new_anonymous(
|
||||
line_rect, fragments,
|
||||
physical_line_rect,
|
||||
fragments,
|
||||
)));
|
||||
}
|
||||
|
||||
|
@ -909,9 +913,9 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
last_line_or_forced_line_break: bool,
|
||||
) -> (Au, Au) {
|
||||
enum TextAlign {
|
||||
Left,
|
||||
Start,
|
||||
Center,
|
||||
Right,
|
||||
End,
|
||||
}
|
||||
let style = self.containing_block.style;
|
||||
let mut text_align_keyword = style.clone_text_align();
|
||||
|
@ -932,24 +936,24 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
}
|
||||
|
||||
let text_align = match text_align_keyword {
|
||||
TextAlignKeyword::Start => {
|
||||
if style.writing_mode.line_left_is_inline_start() {
|
||||
TextAlign::Left
|
||||
} else {
|
||||
TextAlign::Right
|
||||
}
|
||||
},
|
||||
TextAlignKeyword::Start => TextAlign::Start,
|
||||
TextAlignKeyword::Center | TextAlignKeyword::MozCenter => TextAlign::Center,
|
||||
TextAlignKeyword::End => {
|
||||
TextAlignKeyword::End => TextAlign::End,
|
||||
TextAlignKeyword::Left | TextAlignKeyword::MozLeft => {
|
||||
if style.writing_mode.line_left_is_inline_start() {
|
||||
TextAlign::Right
|
||||
TextAlign::Start
|
||||
} else {
|
||||
TextAlign::Left
|
||||
TextAlign::End
|
||||
}
|
||||
},
|
||||
TextAlignKeyword::Left | TextAlignKeyword::MozLeft => TextAlign::Left,
|
||||
TextAlignKeyword::Right | TextAlignKeyword::MozRight => TextAlign::Right,
|
||||
TextAlignKeyword::Justify => TextAlign::Left,
|
||||
TextAlignKeyword::Right | TextAlignKeyword::MozRight => {
|
||||
if style.writing_mode.line_left_is_inline_start() {
|
||||
TextAlign::End
|
||||
} else {
|
||||
TextAlign::Start
|
||||
}
|
||||
},
|
||||
TextAlignKeyword::Justify => TextAlign::Start,
|
||||
};
|
||||
|
||||
let (line_start, available_space) = match self.current_line.placement_among_floats.get() {
|
||||
|
@ -970,8 +974,8 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
let line_length = self.current_line.inline_position - whitespace_trimmed - text_indent;
|
||||
let adjusted_line_start = line_start +
|
||||
match text_align {
|
||||
TextAlign::Left => text_indent,
|
||||
TextAlign::Right => (available_space - line_length).max(text_indent),
|
||||
TextAlign::Start => text_indent,
|
||||
TextAlign::End => (available_space - line_length).max(text_indent),
|
||||
TextAlign::Center => (available_space - line_length + text_indent)
|
||||
.scale_by(0.5)
|
||||
.max(text_indent),
|
||||
|
@ -1015,7 +1019,7 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
state.current_containing_block_offset();
|
||||
state.place_float_fragment(
|
||||
fragment,
|
||||
self.containing_block.effective_writing_mode(),
|
||||
self.containing_block,
|
||||
CollapsedMargin::zero(),
|
||||
block_offset_from_containining_block_top,
|
||||
);
|
||||
|
@ -1034,11 +1038,12 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
float_item: &mut FloatLineItem,
|
||||
line_inline_size_without_trailing_whitespace: Au,
|
||||
) {
|
||||
let margin_box = float_item
|
||||
let logical_margin_rect_size = float_item
|
||||
.fragment
|
||||
.margin_rect()
|
||||
.to_logical(self.containing_block.effective_writing_mode());
|
||||
let inline_size = margin_box.size.inline.max(Au::zero());
|
||||
.size
|
||||
.to_logical(self.containing_block.style.writing_mode);
|
||||
let inline_size = logical_margin_rect_size.inline.max(Au::zero());
|
||||
|
||||
let available_inline_size = match self.current_line.placement_among_floats.get() {
|
||||
Some(placement_among_floats) => placement_among_floats.size.inline,
|
||||
|
@ -1902,36 +1907,22 @@ impl IndependentFormattingContext {
|
|||
bidi_level: Level,
|
||||
) {
|
||||
let style = self.style();
|
||||
let container_writing_mode = layout.containing_block.style.effective_writing_mode();
|
||||
let container_writing_mode = layout.containing_block.style.writing_mode;
|
||||
let pbm = style.padding_border_margin(layout.containing_block);
|
||||
let margin = pbm.margin.auto_is(Au::zero);
|
||||
let pbm_sums = pbm.padding + pbm.border + margin;
|
||||
let pbm_physical_origin = pbm_sums
|
||||
.start_offset()
|
||||
.to_physical_point(container_writing_mode);
|
||||
let mut child_positioning_context = None;
|
||||
|
||||
// We need to know the inline size of the atomic before deciding whether to do the line break.
|
||||
let fragment = match self {
|
||||
let (fragments, content_rect, baselines, mut child_positioning_context) = match self {
|
||||
IndependentFormattingContext::Replaced(replaced) => {
|
||||
let size = replaced
|
||||
.contents
|
||||
.used_size_as_if_inline_element(layout.containing_block, &replaced.style, &pbm)
|
||||
.to_physical_size(container_writing_mode);
|
||||
let fragments = replaced.contents.make_fragments(&replaced.style, size);
|
||||
let content_rect = PhysicalRect::new(pbm_physical_origin, size);
|
||||
|
||||
BoxFragment::new(
|
||||
replaced.base_fragment_info,
|
||||
replaced.style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
pbm.padding.to_physical(container_writing_mode),
|
||||
pbm.border.to_physical(container_writing_mode),
|
||||
margin.to_physical(container_writing_mode),
|
||||
None, /* clearance */
|
||||
CollapsedBlockMargins::zero(),
|
||||
)
|
||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), size);
|
||||
(fragments, content_rect, None, None)
|
||||
},
|
||||
IndependentFormattingContext::NonReplaced(non_replaced) => {
|
||||
let box_size = non_replaced
|
||||
|
@ -2010,7 +2001,7 @@ impl IndependentFormattingContext {
|
|||
};
|
||||
|
||||
let content_rect = PhysicalRect::new(
|
||||
pbm_physical_origin,
|
||||
PhysicalPoint::zero(),
|
||||
LogicalVec2 {
|
||||
block: block_size,
|
||||
inline: inline_size,
|
||||
|
@ -2018,32 +2009,50 @@ impl IndependentFormattingContext {
|
|||
.to_physical_size(container_writing_mode),
|
||||
);
|
||||
|
||||
let mut fragment = BoxFragment::new(
|
||||
non_replaced.base_fragment_info,
|
||||
non_replaced.style.clone(),
|
||||
(
|
||||
independent_layout.fragments,
|
||||
content_rect,
|
||||
pbm.padding.to_physical(container_writing_mode),
|
||||
pbm.border.to_physical(container_writing_mode),
|
||||
margin.to_physical(container_writing_mode),
|
||||
None,
|
||||
CollapsedBlockMargins::zero(),
|
||||
Some(independent_layout.baselines),
|
||||
Some(positioning_context),
|
||||
)
|
||||
.with_baselines(independent_layout.baselines);
|
||||
|
||||
if fragment
|
||||
.style
|
||||
.establishes_containing_block_for_absolute_descendants(fragment.base.flags)
|
||||
{
|
||||
positioning_context
|
||||
.layout_collected_children(layout.layout_context, &mut fragment);
|
||||
}
|
||||
child_positioning_context = Some(positioning_context);
|
||||
|
||||
fragment
|
||||
},
|
||||
};
|
||||
|
||||
// Offset the content rectangle by the physical offset of the padding, border, and margin.
|
||||
let pbm_physical_offset = pbm_sums
|
||||
.start_offset()
|
||||
.to_physical_size(container_writing_mode);
|
||||
let content_rect = content_rect.translate(pbm_physical_offset.to_vector());
|
||||
|
||||
let fragment = BoxFragment::new(
|
||||
self.base_fragment_info(),
|
||||
self.style().clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
pbm.padding.to_physical(container_writing_mode),
|
||||
pbm.border.to_physical(container_writing_mode),
|
||||
margin.to_physical(container_writing_mode),
|
||||
None, /* clearance */
|
||||
CollapsedBlockMargins::zero(),
|
||||
);
|
||||
|
||||
// Apply baselines if necessary.
|
||||
let mut fragment = match baselines {
|
||||
Some(baselines) => fragment.with_baselines(baselines),
|
||||
None => fragment,
|
||||
};
|
||||
|
||||
// Lay out absolutely positioned children if this new atomic establishes a containing block
|
||||
// for absolutes.
|
||||
if let Some(positioning_context) = child_positioning_context.as_mut() {
|
||||
if fragment
|
||||
.style
|
||||
.establishes_containing_block_for_absolute_descendants(fragment.base.flags)
|
||||
{
|
||||
positioning_context.layout_collected_children(layout.layout_context, &mut fragment);
|
||||
}
|
||||
}
|
||||
|
||||
if layout.text_wrap_mode == TextWrapMode::Wrap &&
|
||||
!layout
|
||||
.ifc
|
||||
|
@ -2055,8 +2064,8 @@ impl IndependentFormattingContext {
|
|||
let size = pbm_sums.sum() +
|
||||
fragment
|
||||
.content_rect
|
||||
.to_logical(container_writing_mode)
|
||||
.size;
|
||||
.size
|
||||
.to_logical(container_writing_mode);
|
||||
let baseline_offset = self
|
||||
.pick_baseline(&fragment.baselines(container_writing_mode))
|
||||
.map(|baseline| pbm_sums.block_start + baseline)
|
||||
|
|
|
@ -12,7 +12,6 @@ use serde::Serialize;
|
|||
use servo_arc::Arc;
|
||||
use style::computed_values::clear::T as Clear;
|
||||
use style::computed_values::float::T as Float;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, Size};
|
||||
use style::values::specified::align::AlignFlags;
|
||||
|
@ -32,6 +31,7 @@ use crate::fragment_tree::{
|
|||
};
|
||||
use crate::geom::{
|
||||
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalRect, PhysicalSides, ToLogical,
|
||||
ToLogicalWithContainingBlock,
|
||||
};
|
||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||
use crate::replaced::ReplacedContent;
|
||||
|
@ -245,7 +245,6 @@ impl OutsideMarker {
|
|||
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
|
||||
|
@ -265,7 +264,7 @@ impl OutsideMarker {
|
|||
);
|
||||
},
|
||||
}
|
||||
.to_logical(containing_block_writing_mode)
|
||||
.to_logical(&containing_block_for_children)
|
||||
.max_inline_position(),
|
||||
)
|
||||
});
|
||||
|
@ -297,7 +296,7 @@ impl OutsideMarker {
|
|||
base_fragment_info,
|
||||
self.marker_style.clone(),
|
||||
flow_layout.fragments,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect.to_physical(Some(containing_block)),
|
||||
PhysicalSides::zero(),
|
||||
PhysicalSides::zero(),
|
||||
PhysicalSides::zero(),
|
||||
|
@ -534,7 +533,7 @@ fn layout_block_level_children(
|
|||
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
||||
) -> FlowLayout {
|
||||
let mut placement_state =
|
||||
PlacementState::new(collapsible_with_parent_start_margin, containing_block.style);
|
||||
PlacementState::new(collapsible_with_parent_start_margin, containing_block);
|
||||
|
||||
let fragments = match sequential_layout_state {
|
||||
Some(ref mut sequential_layout_state) => layout_block_level_children_sequentially(
|
||||
|
@ -705,6 +704,9 @@ impl BlockLevelBox {
|
|||
},
|
||||
},
|
||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
|
||||
// The static position of zero here is incorrect, however we do not know
|
||||
// the correct positioning until later, in place_block_level_fragment, and
|
||||
// this value will be adjusted there.
|
||||
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
|
||||
box_.clone(),
|
||||
// This is incorrect, however we do not know the correct positioning
|
||||
|
@ -715,6 +717,7 @@ impl BlockLevelBox {
|
|||
inline: AlignFlags::START,
|
||||
block: AlignFlags::START,
|
||||
},
|
||||
containing_block.style.writing_mode,
|
||||
);
|
||||
let hoisted_fragment = hoisted_box.fragment.clone();
|
||||
positioning_context.push(hoisted_box);
|
||||
|
@ -934,12 +937,12 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
|
|||
},
|
||||
};
|
||||
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
BoxFragment::new(
|
||||
base_fragment_info,
|
||||
style.clone(),
|
||||
flow_layout.fragments,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect.to_physical(Some(containing_block)),
|
||||
pbm.padding.to_physical(containing_block_writing_mode),
|
||||
pbm.border.to_physical(containing_block_writing_mode),
|
||||
margin.to_physical(containing_block_writing_mode),
|
||||
|
@ -1019,12 +1022,12 @@ impl NonReplacedFormattingContext {
|
|||
};
|
||||
|
||||
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
BoxFragment::new(
|
||||
self.base_fragment_info,
|
||||
self.style.clone(),
|
||||
layout.fragments,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect.to_physical(Some(containing_block)),
|
||||
pbm.padding.to_physical(containing_block_writing_mode),
|
||||
pbm.border.to_physical(containing_block_writing_mode),
|
||||
margin.to_physical(containing_block_writing_mode),
|
||||
|
@ -1269,12 +1272,12 @@ impl NonReplacedFormattingContext {
|
|||
};
|
||||
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
|
||||
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
BoxFragment::new(
|
||||
self.base_fragment_info,
|
||||
self.style.clone(),
|
||||
layout.fragments,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect.to_physical(Some(containing_block)),
|
||||
pbm.padding.to_physical(containing_block_writing_mode),
|
||||
pbm.border.to_physical(containing_block_writing_mode),
|
||||
margin.to_physical(containing_block_writing_mode),
|
||||
|
@ -1303,7 +1306,7 @@ fn layout_in_flow_replaced_block_level(
|
|||
let effective_margin_inline_start;
|
||||
let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(&pbm);
|
||||
|
||||
let containing_block_writing_mode = containing_block.effective_writing_mode();
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
let physical_content_size = content_size.to_physical_size(containing_block_writing_mode);
|
||||
let fragments = replaced.make_fragments(style, physical_content_size);
|
||||
|
||||
|
@ -1371,11 +1374,12 @@ fn layout_in_flow_replaced_block_level(
|
|||
clearance.unwrap_or_else(Au::zero),
|
||||
inline: pbm.padding.inline_start + pbm.border.inline_start + effective_margin_inline_start,
|
||||
};
|
||||
let content_rect = LogicalRect {
|
||||
start_corner,
|
||||
size: content_size,
|
||||
}
|
||||
.to_physical(Some(containing_block));
|
||||
|
||||
let content_rect = PhysicalRect::new(
|
||||
start_corner.to_physical_point(containing_block_writing_mode),
|
||||
physical_content_size,
|
||||
);
|
||||
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
|
||||
|
||||
BoxFragment::new(
|
||||
|
@ -1455,9 +1459,12 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
|||
};
|
||||
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
|
||||
assert_eq!(
|
||||
containing_block.effective_writing_mode(),
|
||||
containing_block_for_children.effective_writing_mode(),
|
||||
"Mixed writing modes are not supported yet"
|
||||
containing_block.style.writing_mode.is_horizontal(),
|
||||
containing_block_for_children
|
||||
.style
|
||||
.writing_mode
|
||||
.is_horizontal(),
|
||||
"Vertical writing modes are not supported yet"
|
||||
);
|
||||
ContainingBlockPaddingAndBorder {
|
||||
containing_block: containing_block_for_children,
|
||||
|
@ -1510,16 +1517,8 @@ fn justify_self_alignment(containing_block: &ContainingBlock, free_space: Au) ->
|
|||
debug_assert!(free_space >= Au::zero());
|
||||
match style.clone_text_align() {
|
||||
TextAlignKeyword::MozCenter => free_space / 2,
|
||||
TextAlignKeyword::MozLeft
|
||||
if !style.effective_writing_mode().line_left_is_inline_start() =>
|
||||
{
|
||||
free_space
|
||||
},
|
||||
TextAlignKeyword::MozRight
|
||||
if style.effective_writing_mode().line_left_is_inline_start() =>
|
||||
{
|
||||
free_space
|
||||
},
|
||||
TextAlignKeyword::MozLeft if !style.writing_mode.line_left_is_inline_start() => free_space,
|
||||
TextAlignKeyword::MozRight if style.writing_mode.line_left_is_inline_start() => free_space,
|
||||
_ => Au::zero(),
|
||||
}
|
||||
}
|
||||
|
@ -1643,7 +1642,7 @@ fn solve_clearance_and_inline_margins_avoiding_floats(
|
|||
///
|
||||
/// In parallel mode, this placement is done after all child blocks are laid out. In
|
||||
/// sequential mode, this is done right after each block is laid out.
|
||||
struct PlacementState {
|
||||
struct PlacementState<'container> {
|
||||
next_in_flow_margin_collapses_with_parent_start_margin: bool,
|
||||
last_in_flow_margin_collapses_with_parent_end_margin: bool,
|
||||
start_margin: CollapsedMargin,
|
||||
|
@ -1658,17 +1657,18 @@ struct PlacementState {
|
|||
/// position of the placement.
|
||||
marker_block_size: Option<Au>,
|
||||
|
||||
/// The [`WritingMode`] of the containing fragment where these fragments are being laid out.
|
||||
writing_mode: WritingMode,
|
||||
/// The [`ContainingBlock`] of the container into which this [`PlacementState`] is laying out
|
||||
/// fragments. This is used to convert between physical and logical geometry.
|
||||
containing_block: &'container ContainingBlock<'container>,
|
||||
}
|
||||
|
||||
impl PlacementState {
|
||||
impl<'container> PlacementState<'container> {
|
||||
fn new(
|
||||
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
||||
containing_block_style: &ComputedValues,
|
||||
containing_block: &'container ContainingBlock<'container>,
|
||||
) -> PlacementState {
|
||||
let is_inline_block_context =
|
||||
containing_block_style.get_box().clone_display() == Display::InlineBlock;
|
||||
containing_block.style.get_box().clone_display() == Display::InlineBlock;
|
||||
PlacementState {
|
||||
next_in_flow_margin_collapses_with_parent_start_margin:
|
||||
collapsible_with_parent_start_margin.0,
|
||||
|
@ -1679,7 +1679,7 @@ impl PlacementState {
|
|||
inflow_baselines: Baselines::default(),
|
||||
is_inline_block_context,
|
||||
marker_block_size: None,
|
||||
writing_mode: containing_block_style.effective_writing_mode(),
|
||||
containing_block,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1708,9 +1708,10 @@ impl PlacementState {
|
|||
let box_block_offset = box_fragment
|
||||
.content_rect
|
||||
.origin
|
||||
.to_logical(self.writing_mode)
|
||||
.to_logical(self.containing_block)
|
||||
.block;
|
||||
let box_fragment_baselines = box_fragment.baselines(self.writing_mode);
|
||||
let box_fragment_baselines =
|
||||
box_fragment.baselines(self.containing_block.style.writing_mode);
|
||||
if let (None, Some(first)) = (self.inflow_baselines.first, box_fragment_baselines.first) {
|
||||
self.inflow_baselines.first = Some(first + box_block_offset);
|
||||
}
|
||||
|
@ -1746,7 +1747,7 @@ impl PlacementState {
|
|||
fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(self.writing_mode)
|
||||
.to_logical(self.containing_block.style.writing_mode)
|
||||
.block,
|
||||
);
|
||||
return;
|
||||
|
@ -1755,8 +1756,8 @@ impl PlacementState {
|
|||
let fragment_block_margins = &fragment.block_margins_collapsed_with_children;
|
||||
let mut fragment_block_size = fragment
|
||||
.border_rect()
|
||||
.to_logical(self.writing_mode)
|
||||
.size
|
||||
.to_logical(self.containing_block.style.writing_mode)
|
||||
.block;
|
||||
|
||||
// We use `last_in_flow_margin_collapses_with_parent_end_margin` to implement
|
||||
|
@ -1798,7 +1799,7 @@ impl PlacementState {
|
|||
inline: Au::zero(),
|
||||
block: self.current_margin.solve() + self.current_block_direction_position,
|
||||
}
|
||||
.to_physical_size(self.writing_mode);
|
||||
.to_physical_size(self.containing_block.style.writing_mode);
|
||||
|
||||
if fragment_block_margins.collapsed_through {
|
||||
// `fragment_block_size` is typically zero when collapsing through,
|
||||
|
@ -1823,7 +1824,7 @@ impl PlacementState {
|
|||
},
|
||||
size: LogicalVec2::zero(),
|
||||
}
|
||||
.to_physical(self.writing_mode);
|
||||
.to_physical(Some(self.containing_block));
|
||||
},
|
||||
Fragment::Float(box_fragment) => {
|
||||
let sequential_layout_state = sequential_layout_state
|
||||
|
@ -1832,7 +1833,7 @@ impl PlacementState {
|
|||
self.current_block_direction_position + self.current_margin.solve();
|
||||
sequential_layout_state.place_float_fragment(
|
||||
box_fragment,
|
||||
self.writing_mode,
|
||||
self.containing_block,
|
||||
self.start_margin,
|
||||
block_offset_from_containing_block_top,
|
||||
);
|
||||
|
|
|
@ -16,9 +16,7 @@ use style::Zero;
|
|||
use super::{BaseFragment, BaseFragmentInfo, CollapsedBlockMargins, Fragment};
|
||||
use crate::cell::ArcRefCell;
|
||||
use crate::formatting_contexts::Baselines;
|
||||
use crate::geom::{
|
||||
AuOrAuto, LogicalRect, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, ToLogical,
|
||||
};
|
||||
use crate::geom::{AuOrAuto, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, ToLogical};
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
|
||||
/// Describes how a [`BoxFragment`] paints its background.
|
||||
|
@ -36,7 +34,7 @@ pub(crate) enum BackgroundMode {
|
|||
|
||||
pub(crate) struct ExtraBackground {
|
||||
pub style: ServoArc<ComputedValues>,
|
||||
pub rect: LogicalRect<Au>,
|
||||
pub rect: PhysicalRect<Au>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -165,16 +163,15 @@ impl BoxFragment {
|
|||
/// Get the baselines for this [`BoxFragment`] if they are compatible with the given [`WritingMode`].
|
||||
/// If they are not compatible, [`Baselines::default()`] is returned.
|
||||
pub fn baselines(&self, writing_mode: WritingMode) -> Baselines {
|
||||
let mut baselines = if writing_mode.is_horizontal() ==
|
||||
self.style.effective_writing_mode().is_horizontal()
|
||||
{
|
||||
self.baselines
|
||||
} else {
|
||||
// If the writing mode of the container requesting baselines is not
|
||||
// compatible, ensure that the baselines established by this fragment are
|
||||
// not used.
|
||||
Baselines::default()
|
||||
};
|
||||
let mut baselines =
|
||||
if writing_mode.is_horizontal() == self.style.writing_mode.is_horizontal() {
|
||||
self.baselines
|
||||
} else {
|
||||
// If the writing mode of the container requesting baselines is not
|
||||
// compatible, ensure that the baselines established by this fragment are
|
||||
// not used.
|
||||
Baselines::default()
|
||||
};
|
||||
|
||||
// From the https://drafts.csswg.org/css-align-3/#baseline-export section on "block containers":
|
||||
// > However, for legacy reasons if its baseline-source is auto (the initial
|
||||
|
@ -185,12 +182,12 @@ impl BoxFragment {
|
|||
// This applies even if there is no baseline set, so we unconditionally set the value here
|
||||
// and ignore anything that is set via [`Self::with_baselines`].
|
||||
if self.style.establishes_scroll_container() {
|
||||
let content_rect = self.content_rect.to_logical(writing_mode);
|
||||
let content_rect_size = self.content_rect.size.to_logical(writing_mode);
|
||||
let padding = self.padding.to_logical(writing_mode);
|
||||
let border = self.border.to_logical(writing_mode);
|
||||
let margin = self.margin.to_logical(writing_mode);
|
||||
baselines.last = Some(
|
||||
content_rect.size.block + padding.block_end + border.block_end + margin.block_end,
|
||||
content_rect_size.block + padding.block_end + border.block_end + margin.block_end,
|
||||
)
|
||||
}
|
||||
baselines
|
||||
|
@ -229,6 +226,10 @@ impl BoxFragment {
|
|||
self.border_rect().outer_rect(self.margin)
|
||||
}
|
||||
|
||||
pub(crate) fn padding_border_margin(&self) -> PhysicalSides<Au> {
|
||||
self.margin + self.border + self.padding
|
||||
}
|
||||
|
||||
pub fn print(&self, tree: &mut PrintTree) {
|
||||
tree.new_level(format!(
|
||||
"Box\
|
||||
|
|
|
@ -109,6 +109,17 @@ impl Fragment {
|
|||
Fragment::Float(fragment) => &fragment.base,
|
||||
})
|
||||
}
|
||||
pub(crate) fn content_rect_mut(&mut self) -> Option<&mut PhysicalRect<Au>> {
|
||||
match self {
|
||||
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
|
||||
Some(&mut box_fragment.content_rect)
|
||||
},
|
||||
Fragment::Positioning(_) | Fragment::AbsoluteOrFixedPositioned(_) => None,
|
||||
Fragment::Text(text_fragment) => Some(&mut text_fragment.rect),
|
||||
Fragment::Image(image_fragment) => Some(&mut image_fragment.rect),
|
||||
Fragment::IFrame(iframe_fragment) => Some(&mut iframe_fragment.rect),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> Option<Tag> {
|
||||
self.base().and_then(|base| base.tag)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use app_units::Au;
|
||||
use serde::Serialize;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::values::specified::align::AlignFlags;
|
||||
|
||||
use super::Fragment;
|
||||
|
@ -26,17 +27,24 @@ pub(crate) struct HoistedSharedFragment {
|
|||
/// These values are dependent on the layout mode (currently only interesting for
|
||||
/// flexbox).
|
||||
pub resolved_alignment: LogicalVec2<AlignFlags>,
|
||||
/// This is the [`WritingMode`] of the original parent of the element that created this
|
||||
/// hoisted absolutely-positioned fragment. This helps to interpret the offset for
|
||||
/// static positioning. If the writing mode is right-to-left or bottom-to-top, the static
|
||||
/// offset needs to be adjusted by the absolutely positioned element's inline size.
|
||||
pub original_parent_writing_mode: WritingMode,
|
||||
}
|
||||
|
||||
impl HoistedSharedFragment {
|
||||
pub(crate) fn new(
|
||||
static_position_rect: PhysicalRect<Au>,
|
||||
resolved_alignment: LogicalVec2<AlignFlags>,
|
||||
original_parent_writing_mode: WritingMode,
|
||||
) -> Self {
|
||||
HoistedSharedFragment {
|
||||
fragment: None,
|
||||
static_position_rect,
|
||||
resolved_alignment,
|
||||
original_parent_writing_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,19 +70,6 @@ impl<T: Clone> LogicalVec2<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_physical_point(physical_point: &PhysicalPoint<T>, mode: WritingMode) -> Self {
|
||||
// https://drafts.csswg.org/css-writing-modes/#logical-to-physical
|
||||
let (i, b) = if mode.is_horizontal() {
|
||||
(&physical_point.x, &physical_point.y)
|
||||
} else {
|
||||
(&physical_point.y, &physical_point.x)
|
||||
};
|
||||
LogicalVec2 {
|
||||
inline: i.clone(),
|
||||
block: b.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map<U>(&self, f: impl Fn(&T) -> U) -> LogicalVec2<U> {
|
||||
LogicalVec2 {
|
||||
inline: f(&self.inline),
|
||||
|
@ -271,15 +258,48 @@ impl<T: Clone> LogicalVec2<T> {
|
|||
};
|
||||
PhysicalSize::new(x.clone(), y.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_physical_point(&self, mode: WritingMode) -> PhysicalPoint<T> {
|
||||
// https://drafts.csswg.org/css-writing-modes/#logical-to-physical
|
||||
let (x, y) = if mode.is_horizontal() {
|
||||
(&self.inline, &self.block)
|
||||
impl<T: Copy + Neg<Output = T>> LogicalVec2<T> {
|
||||
pub fn to_physical_vector(&self, mode: WritingMode) -> PhysicalVec<T> {
|
||||
if mode.is_horizontal() {
|
||||
if mode.is_bidi_ltr() {
|
||||
PhysicalVec::new(self.inline, self.block)
|
||||
} else {
|
||||
PhysicalVec::new(-self.inline, self.block)
|
||||
}
|
||||
} else {
|
||||
(&self.block, &self.inline)
|
||||
};
|
||||
PhysicalPoint::new(x.clone(), y.clone())
|
||||
if mode.is_inline_tb() {
|
||||
PhysicalVec::new(self.block, self.inline)
|
||||
} else {
|
||||
PhysicalVec::new(-self.block, self.inline)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogicalVec2<Au> {
|
||||
#[inline]
|
||||
pub fn to_physical_point(
|
||||
&self,
|
||||
containing_block: Option<&ContainingBlock>,
|
||||
) -> PhysicalPoint<Au> {
|
||||
let mode = containing_block.map_or_else(WritingMode::horizontal_tb, |containing_block| {
|
||||
containing_block.style.writing_mode
|
||||
});
|
||||
if mode.is_vertical() {
|
||||
// TODO: Bottom-to-top writing modes are not supported yet.
|
||||
PhysicalPoint::new(self.block, self.inline)
|
||||
} else {
|
||||
let y = self.block;
|
||||
let x = match containing_block {
|
||||
Some(containing_block) if !mode.is_bidi_ltr() => {
|
||||
containing_block.inline_size - self.inline
|
||||
},
|
||||
_ => self.inline,
|
||||
};
|
||||
PhysicalPoint::new(x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,15 +560,36 @@ impl<T> LogicalRect<T> {
|
|||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_physical(&self, mode: WritingMode) -> PhysicalRect<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
PhysicalRect::new(
|
||||
self.start_corner.to_physical_point(mode),
|
||||
self.size.to_physical_size(mode),
|
||||
)
|
||||
impl LogicalRect<Au> {
|
||||
pub fn to_physical<'a>(
|
||||
&self,
|
||||
containing_block: Option<&ContainingBlock<'a>>,
|
||||
) -> PhysicalRect<Au> {
|
||||
let mode = containing_block.map_or_else(WritingMode::horizontal_tb, |containing_block| {
|
||||
containing_block.style.writing_mode
|
||||
});
|
||||
let (x, y, width, height) = if mode.is_vertical() {
|
||||
// TODO: Bottom-to-top writing modes are not supported.
|
||||
(
|
||||
self.start_corner.block,
|
||||
self.start_corner.inline,
|
||||
self.size.block,
|
||||
self.size.inline,
|
||||
)
|
||||
} else {
|
||||
let y = self.start_corner.block;
|
||||
let x = match containing_block {
|
||||
Some(containing_block) if !mode.is_bidi_ltr() => {
|
||||
containing_block.inline_size - self.max_inline_position()
|
||||
},
|
||||
_ => self.start_corner.inline,
|
||||
};
|
||||
(x, y, self.size.inline, self.size.block)
|
||||
};
|
||||
|
||||
PhysicalRect::new(PhysicalPoint::new(x, y), PhysicalSize::new(width, height))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -592,32 +633,74 @@ pub(crate) trait ToLogical<Unit, LogicalType> {
|
|||
fn to_logical(&self, writing_mode: WritingMode) -> LogicalType;
|
||||
}
|
||||
|
||||
impl<Unit: Copy> ToLogical<Unit, LogicalRect<Unit>> for PhysicalRect<Unit> {
|
||||
fn to_logical(&self, writing_mode: WritingMode) -> LogicalRect<Unit> {
|
||||
LogicalRect {
|
||||
start_corner: LogicalVec2::from_physical_size(
|
||||
&PhysicalSize::new(self.origin.x, self.origin.y),
|
||||
writing_mode,
|
||||
),
|
||||
size: LogicalVec2::from_physical_size(&self.size, writing_mode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit: Copy> ToLogical<Unit, LogicalVec2<Unit>> for PhysicalSize<Unit> {
|
||||
fn to_logical(&self, writing_mode: WritingMode) -> LogicalVec2<Unit> {
|
||||
LogicalVec2::from_physical_size(self, writing_mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit: Copy> ToLogical<Unit, LogicalVec2<Unit>> for PhysicalPoint<Unit> {
|
||||
fn to_logical(&self, writing_mode: WritingMode) -> LogicalVec2<Unit> {
|
||||
LogicalVec2::from_physical_point(self, writing_mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit: Copy> ToLogical<Unit, LogicalSides<Unit>> for PhysicalSides<Unit> {
|
||||
fn to_logical(&self, writing_mode: WritingMode) -> LogicalSides<Unit> {
|
||||
LogicalSides::from_physical(self, writing_mode)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ToLogicalWithContainingBlock<LogicalType> {
|
||||
fn to_logical(&self, containing_block: &ContainingBlock) -> LogicalType;
|
||||
}
|
||||
|
||||
impl ToLogicalWithContainingBlock<LogicalVec2<Au>> for PhysicalPoint<Au> {
|
||||
fn to_logical(&self, containing_block: &ContainingBlock) -> LogicalVec2<Au> {
|
||||
let writing_mode = containing_block.style.writing_mode;
|
||||
// TODO: Bottom-to-top and right-to-left vertical writing modes are not supported yet.
|
||||
if writing_mode.is_vertical() {
|
||||
LogicalVec2 {
|
||||
inline: self.y,
|
||||
block: self.x,
|
||||
}
|
||||
} else {
|
||||
LogicalVec2 {
|
||||
inline: if writing_mode.is_bidi_ltr() {
|
||||
self.x
|
||||
} else {
|
||||
containing_block.inline_size - self.x
|
||||
},
|
||||
block: self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToLogicalWithContainingBlock<LogicalRect<Au>> for PhysicalRect<Au> {
|
||||
fn to_logical(&self, containing_block: &ContainingBlock) -> LogicalRect<Au> {
|
||||
let inline_start;
|
||||
let block_start;
|
||||
let inline;
|
||||
let block;
|
||||
|
||||
let writing_mode = containing_block.style.writing_mode;
|
||||
if writing_mode.is_vertical() {
|
||||
// TODO: Bottom-to-top and right-to-left vertical writing modes are not supported yet.
|
||||
inline = self.size.height;
|
||||
block = self.size.width;
|
||||
block_start = self.origin.x;
|
||||
inline_start = self.origin.y;
|
||||
} else {
|
||||
inline = self.size.width;
|
||||
block = self.size.height;
|
||||
block_start = self.origin.y;
|
||||
if writing_mode.is_bidi_ltr() {
|
||||
inline_start = self.origin.x;
|
||||
} else {
|
||||
inline_start = containing_block.inline_size - (self.origin.x + self.size.width);
|
||||
}
|
||||
}
|
||||
LogicalRect {
|
||||
start_corner: LogicalVec2 {
|
||||
inline: inline_start,
|
||||
block: block_start,
|
||||
},
|
||||
size: LogicalVec2 { inline, block },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ use app_units::Au;
|
|||
pub use flow::BoxTree;
|
||||
pub use fragment_tree::FragmentTree;
|
||||
use geom::AuOrAuto;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style_ext::{Clamp, ComputedValuesExt};
|
||||
|
||||
|
@ -107,12 +106,6 @@ pub struct ContainingBlock<'a> {
|
|||
style: &'a ComputedValues,
|
||||
}
|
||||
|
||||
impl<'a> ContainingBlock<'a> {
|
||||
pub(crate) fn effective_writing_mode(&self) -> WritingMode {
|
||||
self.style.effective_writing_mode()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'_ IndefiniteContainingBlock<'a>> for ContainingBlock<'a> {
|
||||
type Error = &'static str;
|
||||
|
||||
|
@ -135,12 +128,6 @@ struct DefiniteContainingBlock<'a> {
|
|||
style: &'a ComputedValues,
|
||||
}
|
||||
|
||||
impl<'a> DefiniteContainingBlock<'a> {
|
||||
pub(crate) fn effective_writing_mode(&self) -> WritingMode {
|
||||
self.style.effective_writing_mode()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> {
|
||||
fn from(definite: &DefiniteContainingBlock<'a>) -> Self {
|
||||
ContainingBlock {
|
||||
|
|
|
@ -7,6 +7,7 @@ use rayon::iter::IntoParallelRefMutIterator;
|
|||
use rayon::prelude::{IndexedParallelIterator, ParallelIterator};
|
||||
use serde::Serialize;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::specified::align::{AlignFlags, AxisDirection};
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
|
@ -22,7 +23,7 @@ use crate::fragment_tree::{
|
|||
};
|
||||
use crate::geom::{
|
||||
AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint,
|
||||
PhysicalRect, PhysicalVec, ToLogical,
|
||||
PhysicalRect, PhysicalVec, ToLogical, ToLogicalWithContainingBlock,
|
||||
};
|
||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||
use crate::{ContainingBlock, DefiniteContainingBlock, IndefiniteContainingBlock};
|
||||
|
@ -73,11 +74,13 @@ impl AbsolutelyPositionedBox {
|
|||
absolutely_positioned_box: ArcRefCell<Self>,
|
||||
static_position_rectangle: PhysicalRect<Au>,
|
||||
resolved_alignment: LogicalVec2<AlignFlags>,
|
||||
original_parent_writing_mode: WritingMode,
|
||||
) -> HoistedAbsolutelyPositionedBox {
|
||||
HoistedAbsolutelyPositionedBox {
|
||||
fragment: ArcRefCell::new(HoistedSharedFragment::new(
|
||||
static_position_rectangle,
|
||||
resolved_alignment,
|
||||
original_parent_writing_mode,
|
||||
)),
|
||||
absolutely_positioned_box,
|
||||
}
|
||||
|
@ -211,7 +214,7 @@ impl PositioningContext {
|
|||
|
||||
if style.clone_position() == Position::Relative {
|
||||
new_fragment.content_rect.origin += relative_adjustement(style, containing_block)
|
||||
.to_physical_size(containing_block.effective_writing_mode())
|
||||
.to_physical_vector(containing_block.style.writing_mode)
|
||||
}
|
||||
|
||||
new_fragment
|
||||
|
@ -233,7 +236,7 @@ impl PositioningContext {
|
|||
let containing_block = DefiniteContainingBlock {
|
||||
size: padding_rect
|
||||
.size
|
||||
.to_logical(new_fragment.style.effective_writing_mode()),
|
||||
.to_logical(new_fragment.style.writing_mode),
|
||||
style: &new_fragment.style,
|
||||
};
|
||||
|
||||
|
@ -376,7 +379,7 @@ impl PositioningContext {
|
|||
}
|
||||
|
||||
/// A data structure which stores the size of a positioning context.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub(crate) struct PositioningContextLength {
|
||||
/// The number of boxes that will be hoisted the the nearest positioned ancestor for
|
||||
/// layout.
|
||||
|
@ -452,9 +455,10 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
let cbis = containing_block.size.inline;
|
||||
let cbbs = containing_block.size.block;
|
||||
let mut absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut();
|
||||
let containing_block_writing_mode = containing_block.style.effective_writing_mode();
|
||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||
let style = absolutely_positioned_box.context.style().clone();
|
||||
let pbm = style.padding_border_margin(&containing_block.into());
|
||||
let indefinite_containing_block = containing_block.into();
|
||||
|
||||
let computed_size = match &absolutely_positioned_box.context {
|
||||
IndependentFormattingContext::Replaced(replaced) => {
|
||||
|
@ -470,17 +474,16 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
block: AuOrAuto::LengthPercentage(used_size.block),
|
||||
}
|
||||
},
|
||||
IndependentFormattingContext::NonReplaced(..) => {
|
||||
style.content_box_size(&containing_block.into(), &pbm)
|
||||
},
|
||||
IndependentFormattingContext::NonReplaced(non_replaced) => non_replaced
|
||||
.style
|
||||
.content_box_size(&indefinite_containing_block, &pbm),
|
||||
};
|
||||
|
||||
let shared_fragment = self.fragment.borrow();
|
||||
let static_position_rect = shared_fragment
|
||||
.static_position_rect
|
||||
.to_logical(containing_block_writing_mode);
|
||||
.to_logical(&indefinite_containing_block);
|
||||
|
||||
let indefinite_containing_block = containing_block.into();
|
||||
let box_offset = style.box_offsets(&indefinite_containing_block);
|
||||
|
||||
// When the "static-position rect" doesn't come into play, we do not do any alignment
|
||||
|
@ -504,6 +507,8 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
box_offsets: inline_box_offsets,
|
||||
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Inline),
|
||||
alignment: inline_alignment,
|
||||
flip_anchor: !(shared_fragment.original_parent_writing_mode.is_bidi_ltr() ==
|
||||
indefinite_containing_block.style.writing_mode.is_bidi_ltr()),
|
||||
};
|
||||
|
||||
// When the "static-position rect" doesn't come into play, we re-resolve "align-self"
|
||||
|
@ -526,6 +531,7 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
box_offsets: block_box_offsets,
|
||||
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Block),
|
||||
alignment: block_alignment,
|
||||
flip_anchor: false,
|
||||
};
|
||||
let overconstrained = LogicalVec2 {
|
||||
inline: inline_axis_solver.is_overconstrained_for_size(computed_size.inline),
|
||||
|
@ -535,8 +541,7 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
let mut inline_axis = inline_axis_solver.solve_for_size(computed_size.inline);
|
||||
let mut block_axis = block_axis_solver.solve_for_size(computed_size.block);
|
||||
|
||||
let mut positioning_context =
|
||||
PositioningContext::new_for_style(absolutely_positioned_box.context.style()).unwrap();
|
||||
let mut positioning_context = PositioningContext::new_for_style(&style).unwrap();
|
||||
let mut new_fragment = {
|
||||
let content_size: LogicalVec2<Au>;
|
||||
let fragments;
|
||||
|
@ -544,10 +549,9 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
IndependentFormattingContext::Replaced(replaced) => {
|
||||
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
||||
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
|
||||
let style = &replaced.style;
|
||||
content_size = computed_size.auto_is(|| unreachable!());
|
||||
fragments = replaced.contents.make_fragments(
|
||||
style,
|
||||
&style,
|
||||
content_size.to_physical_size(containing_block_writing_mode),
|
||||
);
|
||||
},
|
||||
|
@ -558,8 +562,7 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
.style
|
||||
.content_min_box_size(&indefinite_containing_block, &pbm)
|
||||
.map(|t| t.map(Au::from).auto_is(Au::zero));
|
||||
let max_size = non_replaced
|
||||
.style
|
||||
let max_size = style
|
||||
.content_max_box_size(&containing_block.into(), &pbm)
|
||||
.map(|t| t.map(Au::from));
|
||||
|
||||
|
@ -622,13 +625,16 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
let containing_block_for_children = ContainingBlock {
|
||||
inline_size,
|
||||
block_size: size,
|
||||
style: &non_replaced.style,
|
||||
style: &style,
|
||||
};
|
||||
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
|
||||
assert_eq!(
|
||||
containing_block.effective_writing_mode(),
|
||||
containing_block_for_children.effective_writing_mode(),
|
||||
"Mixed writing modes are not supported yet"
|
||||
containing_block.style.writing_mode.is_horizontal(),
|
||||
containing_block_for_children
|
||||
.style
|
||||
.writing_mode
|
||||
.is_horizontal(),
|
||||
"Mixed horizontal and vertical writing modes are not supported yet"
|
||||
);
|
||||
|
||||
// Clear the context since we will lay out the same descendants
|
||||
|
@ -732,13 +738,13 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
inline_axis_solver.solve_alignment(margin_box_rect, &mut content_rect);
|
||||
|
||||
let physical_overconstrained =
|
||||
overconstrained.to_physical_size(containing_block.effective_writing_mode());
|
||||
overconstrained.to_physical_size(containing_block.style.writing_mode);
|
||||
|
||||
BoxFragment::new_with_overconstrained(
|
||||
absolutely_positioned_box.context.base_fragment_info(),
|
||||
absolutely_positioned_box.context.style().clone(),
|
||||
style,
|
||||
fragments,
|
||||
content_rect.to_physical(containing_block_writing_mode),
|
||||
content_rect.to_physical(Some(&containing_block.into())),
|
||||
pbm.padding.to_physical(containing_block_writing_mode),
|
||||
pbm.border.to_physical(containing_block_writing_mode),
|
||||
margin.to_physical(containing_block_writing_mode),
|
||||
|
@ -826,8 +832,8 @@ struct AbsoluteAxisSolver<'a> {
|
|||
box_offsets: AbsoluteBoxOffsets<'a>,
|
||||
static_position_rect_axis: RectAxis,
|
||||
alignment: AlignFlags,
|
||||
flip_anchor: bool,
|
||||
}
|
||||
|
||||
impl<'a> AbsoluteAxisSolver<'a> {
|
||||
/// This unifies some of the parts in common in:
|
||||
///
|
||||
|
@ -846,7 +852,11 @@ impl<'a> AbsoluteAxisSolver<'a> {
|
|||
self.box_offsets.end.non_auto(),
|
||||
) {
|
||||
(None, None) => AxisResult {
|
||||
anchor: Anchor::Start(self.static_position_rect_axis.origin),
|
||||
anchor: if self.flip_anchor {
|
||||
Anchor::End(self.containing_size - self.static_position_rect_axis.origin)
|
||||
} else {
|
||||
Anchor::Start(self.static_position_rect_axis.origin)
|
||||
},
|
||||
size: computed_size,
|
||||
margin_start: self.computed_margin_start.auto_is(Au::zero),
|
||||
margin_end: self.computed_margin_end.auto_is(Au::zero),
|
||||
|
|
|
@ -32,7 +32,6 @@ use style::values::generics::font::LineHeight;
|
|||
use style_traits::{ParsingMode, ToCss};
|
||||
|
||||
use crate::fragment_tree::{BoxFragment, Fragment, FragmentFlags, FragmentTree, Tag};
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
|
||||
pub fn process_content_box_request(
|
||||
requested_node: OpaqueNode,
|
||||
|
@ -136,7 +135,7 @@ pub fn process_resolved_style_request<'dom>(
|
|||
return style.computed_value_to_string(PropertyDeclarationId::Custom(name));
|
||||
},
|
||||
}
|
||||
.to_physical(style.effective_writing_mode());
|
||||
.to_physical(style.writing_mode);
|
||||
|
||||
let computed_style =
|
||||
|| style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id));
|
||||
|
|
|
@ -235,7 +235,7 @@ impl ReplacedContent {
|
|||
|
||||
fn flow_relative_intrinsic_size(&self, style: &ComputedValues) -> LogicalVec2<Option<Au>> {
|
||||
let intrinsic_size = PhysicalSize::new(self.intrinsic.width, self.intrinsic.height);
|
||||
LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode())
|
||||
LogicalVec2::from_physical_size(&intrinsic_size, style.writing_mode)
|
||||
}
|
||||
|
||||
fn inline_size_over_block_size_intrinsic_ratio(
|
||||
|
@ -243,7 +243,7 @@ impl ReplacedContent {
|
|||
style: &ComputedValues,
|
||||
) -> Option<CSSFloat> {
|
||||
self.intrinsic.ratio.map(|width_over_height| {
|
||||
if style.effective_writing_mode().is_vertical() {
|
||||
if style.writing_mode.is_vertical() {
|
||||
1. / width_over_height
|
||||
} else {
|
||||
width_over_height
|
||||
|
@ -351,7 +351,7 @@ impl ReplacedContent {
|
|||
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(),
|
||||
containing_block.style.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ impl ReplacedContent {
|
|||
min_box_size: LogicalVec2<Au>,
|
||||
max_box_size: LogicalVec2<Option<Au>>,
|
||||
) -> LogicalVec2<Au> {
|
||||
let mode = style.effective_writing_mode();
|
||||
let mode = style.writing_mode;
|
||||
let intrinsic_size = self.flow_relative_intrinsic_size(style);
|
||||
let intrinsic_ratio = self.preferred_aspect_ratio(&containing_block.into(), style);
|
||||
|
||||
|
|
|
@ -139,13 +139,6 @@ impl PaddingBorderMargin {
|
|||
padding_border_sums: LogicalVec2::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn border_padding_start(&self) -> LogicalVec2<Au> {
|
||||
LogicalVec2 {
|
||||
inline: self.border.inline_start + self.padding.inline_start,
|
||||
block: self.border.block_start + self.padding.block_start,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolved `aspect-ratio` property with respect to a specific element. Depends
|
||||
|
@ -186,7 +179,6 @@ impl AspectRatio {
|
|||
}
|
||||
|
||||
pub(crate) trait ComputedValuesExt {
|
||||
fn effective_writing_mode(&self) -> WritingMode;
|
||||
fn box_offsets(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
|
@ -291,10 +283,6 @@ pub(crate) trait ComputedValuesExt {
|
|||
}
|
||||
|
||||
impl ComputedValuesExt for ComputedValues {
|
||||
fn effective_writing_mode(&self) -> WritingMode {
|
||||
WritingMode::horizontal_tb()
|
||||
}
|
||||
|
||||
fn box_offsets(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
|
@ -307,7 +295,7 @@ impl ComputedValuesExt for ComputedValues {
|
|||
position.bottom.as_ref(),
|
||||
position.left.as_ref(),
|
||||
),
|
||||
containing_block.effective_writing_mode(),
|
||||
containing_block.style.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -362,7 +350,7 @@ impl ComputedValuesExt for ComputedValues {
|
|||
pbm: &PaddingBorderMargin,
|
||||
) -> LogicalVec2<AuOrAuto> {
|
||||
let box_size = self
|
||||
.box_size(containing_block.effective_writing_mode())
|
||||
.box_size(containing_block.style.writing_mode)
|
||||
.percentages_relative_to(containing_block);
|
||||
self.content_box_size_for_box_size(box_size, pbm)
|
||||
}
|
||||
|
@ -393,7 +381,7 @@ impl ComputedValuesExt for ComputedValues {
|
|||
pbm: &PaddingBorderMargin,
|
||||
) -> LogicalVec2<AuOrAuto> {
|
||||
let box_size = self
|
||||
.min_box_size(containing_block.effective_writing_mode())
|
||||
.min_box_size(containing_block.style.writing_mode)
|
||||
.percentages_relative_to(containing_block);
|
||||
self.content_min_box_size_for_min_size(box_size, pbm)
|
||||
}
|
||||
|
@ -423,7 +411,7 @@ impl ComputedValuesExt for ComputedValues {
|
|||
pbm: &PaddingBorderMargin,
|
||||
) -> LogicalVec2<Option<Au>> {
|
||||
let max_box_size = self
|
||||
.max_box_size(containing_block.effective_writing_mode())
|
||||
.max_box_size(containing_block.style.writing_mode)
|
||||
.percentages_relative_to(containing_block);
|
||||
|
||||
self.content_max_box_size_for_max_size(max_box_size, pbm)
|
||||
|
@ -495,23 +483,10 @@ impl ComputedValuesExt for ComputedValues {
|
|||
}
|
||||
|
||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin {
|
||||
let cbis = containing_block.inline_size;
|
||||
let padding = self
|
||||
.padding(containing_block.effective_writing_mode())
|
||||
.percentages_relative_to(cbis);
|
||||
let border = self.border_width(containing_block.effective_writing_mode());
|
||||
let margin = self
|
||||
.margin(containing_block.effective_writing_mode())
|
||||
.percentages_relative_to(cbis);
|
||||
PaddingBorderMargin {
|
||||
padding_border_sums: LogicalVec2 {
|
||||
inline: (padding.inline_sum() + border.inline_sum()),
|
||||
block: (padding.block_sum() + border.block_sum()),
|
||||
},
|
||||
padding,
|
||||
border,
|
||||
margin,
|
||||
}
|
||||
self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||
containing_block.style.writing_mode,
|
||||
containing_block.inline_size,
|
||||
)
|
||||
}
|
||||
|
||||
fn padding_border_margin_for_intrinsic_size(
|
||||
|
|
|
@ -28,8 +28,8 @@ use crate::fragment_tree::{
|
|||
PositioningFragment,
|
||||
};
|
||||
use crate::geom::{
|
||||
AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalSides,
|
||||
ToLogical,
|
||||
AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint,
|
||||
PhysicalRect, PhysicalSides, ToLogical, ToLogicalWithContainingBlock,
|
||||
};
|
||||
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
|
||||
use crate::sizing::ContentSizes;
|
||||
|
@ -1135,14 +1135,14 @@ impl<'a> TableLayout<'a> {
|
|||
let border: LogicalSides<Au> = self
|
||||
.get_collapsed_borders_for_cell(cell, coordinates)
|
||||
.unwrap_or_else(|| {
|
||||
cell.style.border_width(
|
||||
containing_block_for_table.effective_writing_mode(),
|
||||
)
|
||||
});
|
||||
cell.style
|
||||
.border_width(containing_block_for_table.style.writing_mode)
|
||||
})
|
||||
.into();
|
||||
|
||||
let padding: LogicalSides<Au> = cell
|
||||
.style
|
||||
.padding(containing_block_for_table.effective_writing_mode())
|
||||
.padding(containing_block_for_table.style.writing_mode)
|
||||
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
||||
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
|
||||
|
||||
|
@ -1541,7 +1541,7 @@ impl<'a> TableLayout<'a> {
|
|||
style: containing_block.style,
|
||||
};
|
||||
|
||||
let mut box_fragment = context.layout_in_flow_block_level(
|
||||
let box_fragment = context.layout_in_flow_block_level(
|
||||
layout_context,
|
||||
positioning_context
|
||||
.as_mut()
|
||||
|
@ -1550,16 +1550,6 @@ impl<'a> TableLayout<'a> {
|
|||
None, /* sequential_layout_state */
|
||||
);
|
||||
|
||||
let margin_offset = LogicalVec2 {
|
||||
inline: Au::zero(),
|
||||
block: box_fragment
|
||||
.block_margins_collapsed_with_children
|
||||
.start
|
||||
.solve(),
|
||||
}
|
||||
.to_physical_size(containing_block.effective_writing_mode());
|
||||
box_fragment.content_rect.origin += margin_offset;
|
||||
|
||||
if let Some(positioning_context) = positioning_context.take() {
|
||||
parent_positioning_context.append(positioning_context);
|
||||
}
|
||||
|
@ -1576,10 +1566,10 @@ impl<'a> TableLayout<'a> {
|
|||
containing_block_for_children: &ContainingBlock,
|
||||
containing_block_for_table: &ContainingBlock,
|
||||
) -> IndependentLayout {
|
||||
let writing_mode = containing_block_for_children.effective_writing_mode();
|
||||
let grid_min_max = self.compute_grid_min_max(layout_context, writing_mode);
|
||||
let table_writing_mode = containing_block_for_children.style.writing_mode;
|
||||
let grid_min_max = self.compute_grid_min_max(layout_context, table_writing_mode);
|
||||
let caption_minimum_inline_size =
|
||||
self.compute_caption_minimum_inline_size(layout_context, writing_mode);
|
||||
self.compute_caption_minimum_inline_size(layout_context, table_writing_mode);
|
||||
self.compute_table_width(
|
||||
containing_block_for_children,
|
||||
containing_block_for_table,
|
||||
|
@ -1596,10 +1586,23 @@ impl<'a> TableLayout<'a> {
|
|||
//
|
||||
// TODO: This is a pretty large hack. It would be nicer to actually have the grid sized properly,
|
||||
// but it works for now.
|
||||
//
|
||||
// Get the padding, border, and margin of the table using the inline size of the table's containing
|
||||
// block but in the writing of the table itself.
|
||||
// TODO: This is broken for orthoganol flows, because the inline size of the parent isn't necessarily
|
||||
// the inline size of the table.
|
||||
let containing_block_for_logical_conversion = ContainingBlock {
|
||||
inline_size: self.table_width,
|
||||
block_size: containing_block_for_table.block_size,
|
||||
style: containing_block_for_children.style,
|
||||
};
|
||||
let table_pbm = self
|
||||
.table
|
||||
.style
|
||||
.padding_border_margin(containing_block_for_table);
|
||||
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
|
||||
table_writing_mode,
|
||||
containing_block_for_table.inline_size,
|
||||
);
|
||||
let offset_from_wrapper = -table_pbm.padding - table_pbm.border;
|
||||
let mut current_block_offset = offset_from_wrapper.block_start;
|
||||
|
||||
|
@ -1609,7 +1612,6 @@ impl<'a> TableLayout<'a> {
|
|||
content_inline_size_for_table: None,
|
||||
baselines: Baselines::default(),
|
||||
};
|
||||
let table_writing_mode = containing_block_for_children.effective_writing_mode();
|
||||
|
||||
table_layout
|
||||
.fragments
|
||||
|
@ -1627,12 +1629,23 @@ impl<'a> TableLayout<'a> {
|
|||
positioning_context,
|
||||
);
|
||||
|
||||
let caption_offset = LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start,
|
||||
block: current_block_offset,
|
||||
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
||||
// for the table children and only then convert the result to physical geometry.
|
||||
let caption_pbm = caption_fragment
|
||||
.padding_border_margin()
|
||||
.to_logical(table_writing_mode);
|
||||
caption_fragment.content_rect = LogicalRect {
|
||||
start_corner: LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start + caption_pbm.inline_start,
|
||||
block: current_block_offset + caption_pbm.block_start,
|
||||
},
|
||||
size: caption_fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(table_writing_mode),
|
||||
}
|
||||
.to_physical_size(table_writing_mode);
|
||||
caption_fragment.content_rect.origin += caption_offset;
|
||||
.to_physical(Some(&containing_block_for_logical_conversion));
|
||||
|
||||
current_block_offset += caption_fragment
|
||||
.margin_rect()
|
||||
.size
|
||||
|
@ -1652,22 +1665,37 @@ impl<'a> TableLayout<'a> {
|
|||
layout_context,
|
||||
&table_pbm,
|
||||
positioning_context,
|
||||
&containing_block_for_logical_conversion,
|
||||
containing_block_for_children,
|
||||
containing_block_for_table,
|
||||
);
|
||||
|
||||
// Take the baseline of the grid fragment, after adjusting it to be in the coordinate system
|
||||
// of the table wrapper.
|
||||
let logical_grid_content_rect = grid_fragment.content_rect.to_logical(table_writing_mode);
|
||||
table_layout.baselines = grid_fragment
|
||||
.baselines(table_writing_mode)
|
||||
.offset(current_block_offset + logical_grid_content_rect.start_corner.block);
|
||||
let logical_grid_content_rect = grid_fragment
|
||||
.content_rect
|
||||
.to_logical(&containing_block_for_logical_conversion);
|
||||
let grid_pbm = grid_fragment
|
||||
.padding_border_margin()
|
||||
.to_logical(table_writing_mode);
|
||||
table_layout.baselines = grid_fragment.baselines(table_writing_mode).offset(
|
||||
current_block_offset +
|
||||
logical_grid_content_rect.start_corner.block +
|
||||
grid_pbm.block_start,
|
||||
);
|
||||
|
||||
grid_fragment.content_rect.origin += LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start,
|
||||
block: current_block_offset,
|
||||
grid_fragment.content_rect = LogicalRect {
|
||||
start_corner: LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start + grid_pbm.inline_start,
|
||||
block: current_block_offset + grid_pbm.block_start,
|
||||
},
|
||||
size: grid_fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(table_writing_mode),
|
||||
}
|
||||
.to_physical_size(table_writing_mode);
|
||||
.to_physical(Some(&containing_block_for_logical_conversion));
|
||||
|
||||
current_block_offset += grid_fragment
|
||||
.border_rect()
|
||||
.size
|
||||
|
@ -1698,12 +1726,23 @@ impl<'a> TableLayout<'a> {
|
|||
positioning_context,
|
||||
);
|
||||
|
||||
let caption_offset = LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start,
|
||||
block: current_block_offset,
|
||||
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
||||
// for the table children and only then convert the result to physical geometry.
|
||||
let caption_pbm = caption_fragment
|
||||
.padding_border_margin()
|
||||
.to_logical(table_writing_mode);
|
||||
caption_fragment.content_rect = LogicalRect {
|
||||
start_corner: LogicalVec2 {
|
||||
inline: offset_from_wrapper.inline_start + caption_pbm.inline_start,
|
||||
block: current_block_offset + caption_pbm.block_start,
|
||||
},
|
||||
size: caption_fragment
|
||||
.content_rect
|
||||
.size
|
||||
.to_logical(table_writing_mode),
|
||||
}
|
||||
.to_physical_size(containing_block_for_children.effective_writing_mode());
|
||||
caption_fragment.content_rect.origin += caption_offset;
|
||||
.to_physical(Some(&containing_block_for_logical_conversion));
|
||||
|
||||
current_block_offset += caption_fragment
|
||||
.margin_rect()
|
||||
.size
|
||||
|
@ -1729,6 +1768,7 @@ impl<'a> TableLayout<'a> {
|
|||
layout_context: &LayoutContext,
|
||||
table_pbm: &PaddingBorderMargin,
|
||||
positioning_context: &mut PositioningContext,
|
||||
containing_block_for_logical_conversion: &ContainingBlock,
|
||||
containing_block_for_children: &ContainingBlock,
|
||||
containing_block_for_table: &ContainingBlock,
|
||||
) -> BoxFragment {
|
||||
|
@ -1738,8 +1778,8 @@ impl<'a> TableLayout<'a> {
|
|||
containing_block_for_children,
|
||||
positioning_context,
|
||||
);
|
||||
let writing_mode = containing_block_for_children.effective_writing_mode();
|
||||
let first_layout_row_heights = self.do_first_row_layout(writing_mode);
|
||||
let table_writing_mode = containing_block_for_children.style.writing_mode;
|
||||
let first_layout_row_heights = self.do_first_row_layout(table_writing_mode);
|
||||
self.compute_table_height_and_final_row_heights(
|
||||
first_layout_row_heights,
|
||||
containing_block_for_children,
|
||||
|
@ -1749,16 +1789,15 @@ impl<'a> TableLayout<'a> {
|
|||
assert_eq!(self.table.size.height, self.row_sizes.len());
|
||||
assert_eq!(self.table.size.width, self.distributed_column_widths.len());
|
||||
|
||||
let table_writing_mode = containing_block_for_children.effective_writing_mode();
|
||||
if self.table.size.width == 0 && self.table.size.height == 0 {
|
||||
let content_rect = LogicalRect {
|
||||
start_corner: table_pbm.border_padding_start(),
|
||||
start_corner: LogicalVec2::zero(),
|
||||
size: LogicalVec2 {
|
||||
inline: self.table_width,
|
||||
block: self.final_table_height,
|
||||
},
|
||||
}
|
||||
.to_physical(table_writing_mode);
|
||||
.to_physical(Some(containing_block_for_logical_conversion));
|
||||
return BoxFragment::new(
|
||||
self.table.grid_base_fragment_info,
|
||||
self.table.grid_style.clone(),
|
||||
|
@ -1804,8 +1843,12 @@ impl<'a> TableLayout<'a> {
|
|||
}
|
||||
|
||||
let table_row = &self.table.rows[row_index];
|
||||
let mut row_fragment_layout =
|
||||
RowFragmentLayout::new(table_row, row_index, &table_and_track_dimensions);
|
||||
let mut row_fragment_layout = RowFragmentLayout::new(
|
||||
table_row,
|
||||
row_index,
|
||||
&table_and_track_dimensions,
|
||||
&self.table.style,
|
||||
);
|
||||
|
||||
let old_row_group_index = row_group_fragment_layout
|
||||
.as_ref()
|
||||
|
@ -1816,6 +1859,7 @@ impl<'a> TableLayout<'a> {
|
|||
table_fragments.push(Fragment::Box(old_row_group_layout.finish(
|
||||
layout_context,
|
||||
positioning_context,
|
||||
containing_block_for_logical_conversion,
|
||||
containing_block_for_children,
|
||||
)));
|
||||
}
|
||||
|
@ -1837,31 +1881,21 @@ impl<'a> TableLayout<'a> {
|
|||
continue;
|
||||
}
|
||||
|
||||
// The PositioningContext for cells is, in order or preference, the PositioningContext of the row,
|
||||
// the PositioningContext of the row group, or the PositioningContext of the table.
|
||||
let row_group_positioning_context = row_group_fragment_layout
|
||||
.as_mut()
|
||||
.and_then(|layout| layout.positioning_context.as_mut());
|
||||
let positioning_context_for_cells = row_fragment_layout
|
||||
.positioning_context
|
||||
.as_mut()
|
||||
.or(row_group_positioning_context)
|
||||
.unwrap_or(positioning_context);
|
||||
|
||||
self.do_final_cell_layout(
|
||||
row_index,
|
||||
column_index,
|
||||
&table_and_track_dimensions,
|
||||
&row_fragment_layout.rect,
|
||||
positioning_context_for_cells,
|
||||
&mut baselines,
|
||||
&mut row_fragment_layout.fragments,
|
||||
&mut row_fragment_layout,
|
||||
row_group_fragment_layout.as_mut(),
|
||||
positioning_context,
|
||||
);
|
||||
}
|
||||
|
||||
let row_fragment = Fragment::Box(row_fragment_layout.finish(
|
||||
layout_context,
|
||||
positioning_context,
|
||||
containing_block_for_logical_conversion,
|
||||
containing_block_for_children,
|
||||
&mut row_group_fragment_layout,
|
||||
));
|
||||
|
@ -1876,18 +1910,19 @@ impl<'a> TableLayout<'a> {
|
|||
table_fragments.push(Fragment::Box(row_group_layout.finish(
|
||||
layout_context,
|
||||
positioning_context,
|
||||
containing_block_for_logical_conversion,
|
||||
containing_block_for_children,
|
||||
)));
|
||||
}
|
||||
|
||||
let content_rect = LogicalRect {
|
||||
start_corner: table_pbm.border_padding_start(),
|
||||
start_corner: LogicalVec2::zero(),
|
||||
size: LogicalVec2 {
|
||||
inline: table_and_track_dimensions.table_rect.max_inline_position(),
|
||||
block: table_and_track_dimensions.table_rect.max_block_position(),
|
||||
},
|
||||
}
|
||||
.to_physical(table_writing_mode);
|
||||
.to_physical(Some(containing_block_for_logical_conversion));
|
||||
BoxFragment::new(
|
||||
self.table.grid_base_fragment_info,
|
||||
self.table.grid_style.clone(),
|
||||
|
@ -1930,17 +1965,26 @@ impl<'a> TableLayout<'a> {
|
|||
col_group.style.get_inherited_box().visibility == Visibility::Collapse
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn do_final_cell_layout(
|
||||
&mut self,
|
||||
row_index: usize,
|
||||
column_index: usize,
|
||||
dimensions: &TableAndTrackDimensions,
|
||||
row_rect: &LogicalRect<Au>,
|
||||
positioning_context: &mut PositioningContext,
|
||||
baselines: &mut Baselines,
|
||||
cell_fragments: &mut Vec<Fragment>,
|
||||
row_fragment_layout: &mut RowFragmentLayout,
|
||||
row_group_fragment_layout: Option<&mut RowGroupFragmentLayout>,
|
||||
positioning_context_for_table: &mut PositioningContext,
|
||||
) {
|
||||
// The PositioningContext for cells is, in order or preference, the PositioningContext of the row,
|
||||
// the PositioningContext of the row group, or the PositioningContext of the table.
|
||||
let row_group_positioning_context =
|
||||
row_group_fragment_layout.and_then(|layout| layout.positioning_context.as_mut());
|
||||
let positioning_context = row_fragment_layout
|
||||
.positioning_context
|
||||
.as_mut()
|
||||
.or(row_group_positioning_context)
|
||||
.unwrap_or(positioning_context_for_table);
|
||||
|
||||
let layout = match self.cells_laid_out[row_index][column_index].take() {
|
||||
Some(layout) => layout,
|
||||
None => {
|
||||
|
@ -1955,7 +1999,8 @@ impl<'a> TableLayout<'a> {
|
|||
},
|
||||
};
|
||||
|
||||
let row_block_offset = row_rect.start_corner.block;
|
||||
// If this cell has baseline alignment, it can adjust the table's overall baseline.
|
||||
let row_block_offset = row_fragment_layout.rect.start_corner.block;
|
||||
let row_baseline = self.row_baselines[row_index];
|
||||
if cell.effective_vertical_align() == VerticalAlignKeyword::Baseline && !layout.is_empty() {
|
||||
let baseline = row_block_offset + row_baseline;
|
||||
|
@ -1969,21 +2014,43 @@ impl<'a> TableLayout<'a> {
|
|||
cell.rowspan,
|
||||
cell.colspan,
|
||||
);
|
||||
row_relative_cell_rect.start_corner -= row_rect.start_corner;
|
||||
row_relative_cell_rect.start_corner -= row_fragment_layout.rect.start_corner;
|
||||
let mut fragment = cell.create_fragment(
|
||||
layout,
|
||||
row_relative_cell_rect,
|
||||
row_baseline,
|
||||
positioning_context,
|
||||
&self.table.style,
|
||||
&row_fragment_layout.containing_block,
|
||||
);
|
||||
|
||||
// Make a table part rectangle relative to the row fragment for the purposes of
|
||||
// drawing extra backgrounds.
|
||||
//
|
||||
// This rectangle is an offset between the row fragment and the other table
|
||||
// part rectangle (row group, column, column group). Everything between them
|
||||
// is laid out in a left-to-right fashion, but respecting the veritcality of
|
||||
// the writing mode. This is why below, only the axes are flipped, but the
|
||||
// rectangle is not flipped for RTL.
|
||||
let make_relative_to_row_start = |mut rect: LogicalRect<Au>| {
|
||||
rect.start_corner -= row_fragment_layout.rect.start_corner;
|
||||
let writing_mode = row_fragment_layout.containing_block.style.writing_mode;
|
||||
PhysicalRect::new(
|
||||
if !writing_mode.is_vertical() {
|
||||
PhysicalPoint::new(rect.start_corner.inline, rect.start_corner.block)
|
||||
} else {
|
||||
PhysicalPoint::new(rect.start_corner.block, rect.start_corner.inline)
|
||||
},
|
||||
rect.size.to_physical_size(writing_mode),
|
||||
)
|
||||
};
|
||||
|
||||
let column = self.table.columns.get(column_index);
|
||||
let column_group = column
|
||||
.and_then(|column| column.group_index)
|
||||
.and_then(|index| self.table.column_groups.get(index));
|
||||
if let Some(column_group) = column_group {
|
||||
let mut rect = dimensions.get_column_group_rect(column_group);
|
||||
rect.start_corner -= row_rect.start_corner;
|
||||
let rect = make_relative_to_row_start(dimensions.get_column_group_rect(column_group));
|
||||
fragment.add_extra_background(ExtraBackground {
|
||||
style: column_group.style.clone(),
|
||||
rect,
|
||||
|
@ -1991,8 +2058,7 @@ impl<'a> TableLayout<'a> {
|
|||
}
|
||||
if let Some(column) = column {
|
||||
if !column.is_anonymous {
|
||||
let mut rect = dimensions.get_column_rect(column_index);
|
||||
rect.start_corner -= row_rect.start_corner;
|
||||
let rect = make_relative_to_row_start(dimensions.get_column_rect(column_index));
|
||||
fragment.add_extra_background(ExtraBackground {
|
||||
style: column.style.clone(),
|
||||
rect,
|
||||
|
@ -2004,24 +2070,20 @@ impl<'a> TableLayout<'a> {
|
|||
.and_then(|row| row.group_index)
|
||||
.and_then(|index| self.table.row_groups.get(index));
|
||||
if let Some(row_group) = row_group {
|
||||
let mut rect = dimensions.get_row_group_rect(row_group);
|
||||
rect.start_corner -= row_rect.start_corner;
|
||||
let rect = make_relative_to_row_start(dimensions.get_row_group_rect(row_group));
|
||||
fragment.add_extra_background(ExtraBackground {
|
||||
style: row_group.style.clone(),
|
||||
rect,
|
||||
})
|
||||
}
|
||||
if let Some(row) = row {
|
||||
let mut rect = *row_rect;
|
||||
rect.start_corner = LogicalVec2::zero();
|
||||
let rect = make_relative_to_row_start(row_fragment_layout.rect);
|
||||
fragment.add_extra_background(ExtraBackground {
|
||||
style: row.style.clone(),
|
||||
rect,
|
||||
})
|
||||
}
|
||||
cell_fragments.push(Fragment::Box(fragment));
|
||||
|
||||
// If this cell has baseline alignment, it can adjust the table's overall baseline.
|
||||
row_fragment_layout.fragments.push(Fragment::Box(fragment));
|
||||
}
|
||||
|
||||
fn make_fragments_for_columns_and_column_groups(
|
||||
|
@ -2029,14 +2091,13 @@ impl<'a> TableLayout<'a> {
|
|||
dimensions: &TableAndTrackDimensions,
|
||||
fragments: &mut Vec<Fragment>,
|
||||
) {
|
||||
let table_writing_mode = self.table.style.effective_writing_mode();
|
||||
for column_group in self.table.column_groups.iter() {
|
||||
if !column_group.is_empty() {
|
||||
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
||||
column_group.base_fragment_info,
|
||||
dimensions
|
||||
.get_column_group_rect(column_group)
|
||||
.to_physical(table_writing_mode),
|
||||
.to_physical(None),
|
||||
column_group.style.clone(),
|
||||
)));
|
||||
}
|
||||
|
@ -2045,9 +2106,7 @@ impl<'a> TableLayout<'a> {
|
|||
for (column_index, column) in self.table.columns.iter().enumerate() {
|
||||
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
||||
column.base_fragment_info,
|
||||
dimensions
|
||||
.get_column_rect(column_index)
|
||||
.to_physical(table_writing_mode),
|
||||
dimensions.get_column_rect(column_index).to_physical(None),
|
||||
column.style.clone(),
|
||||
)));
|
||||
}
|
||||
|
@ -2117,16 +2176,29 @@ impl<'a> TableLayout<'a> {
|
|||
struct RowFragmentLayout<'a> {
|
||||
row: &'a TableTrack,
|
||||
rect: LogicalRect<Au>,
|
||||
containing_block: ContainingBlock<'a>,
|
||||
positioning_context: Option<PositioningContext>,
|
||||
fragments: Vec<Fragment>,
|
||||
}
|
||||
|
||||
impl<'a> RowFragmentLayout<'a> {
|
||||
fn new(table_row: &'a TableTrack, index: usize, dimensions: &TableAndTrackDimensions) -> Self {
|
||||
fn new(
|
||||
table_row: &'a TableTrack,
|
||||
index: usize,
|
||||
dimensions: &TableAndTrackDimensions,
|
||||
table_style: &'a ComputedValues,
|
||||
) -> Self {
|
||||
let rect = dimensions.get_row_rect(index);
|
||||
let containing_block = ContainingBlock {
|
||||
inline_size: rect.size.inline,
|
||||
block_size: AuOrAuto::LengthPercentage(rect.size.inline),
|
||||
style: table_style,
|
||||
};
|
||||
Self {
|
||||
row: table_row,
|
||||
rect: dimensions.get_row_rect(index),
|
||||
rect,
|
||||
positioning_context: PositioningContext::new_for_style(&table_row.style),
|
||||
containing_block,
|
||||
fragments: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -2134,23 +2206,40 @@ impl<'a> RowFragmentLayout<'a> {
|
|||
mut self,
|
||||
layout_context: &LayoutContext,
|
||||
table_positioning_context: &mut PositioningContext,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_for_logical_conversion: &ContainingBlock,
|
||||
containing_block_for_children: &ContainingBlock,
|
||||
row_group_fragment_layout: &mut Option<RowGroupFragmentLayout>,
|
||||
) -> BoxFragment {
|
||||
if self.positioning_context.is_some() {
|
||||
self.rect.start_corner += relative_adjustement(&self.row.style, containing_block);
|
||||
self.rect.start_corner +=
|
||||
relative_adjustement(&self.row.style, containing_block_for_children);
|
||||
}
|
||||
|
||||
if let Some(ref row_group_layout) = row_group_fragment_layout {
|
||||
self.rect.start_corner -= row_group_layout.rect.start_corner;
|
||||
}
|
||||
let (inline_size, block_size) =
|
||||
if let Some(ref row_group_layout) = row_group_fragment_layout {
|
||||
self.rect.start_corner -= row_group_layout.rect.start_corner;
|
||||
(
|
||||
row_group_layout.rect.size.inline,
|
||||
AuOrAuto::LengthPercentage(row_group_layout.rect.size.block),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
containing_block_for_logical_conversion.inline_size,
|
||||
containing_block_for_logical_conversion.block_size,
|
||||
)
|
||||
};
|
||||
|
||||
let row_group_containing_block = ContainingBlock {
|
||||
inline_size,
|
||||
block_size,
|
||||
style: containing_block_for_logical_conversion.style,
|
||||
};
|
||||
|
||||
let mut row_fragment = BoxFragment::new(
|
||||
self.row.base_fragment_info,
|
||||
self.row.style.clone(),
|
||||
self.fragments,
|
||||
self.rect
|
||||
.to_physical(containing_block.effective_writing_mode()),
|
||||
self.rect.to_physical(Some(&row_group_containing_block)),
|
||||
PhysicalSides::zero(), /* padding */
|
||||
PhysicalSides::zero(), /* border */
|
||||
PhysicalSides::zero(), /* margin */
|
||||
|
@ -2203,10 +2292,12 @@ impl RowGroupFragmentLayout {
|
|||
mut self,
|
||||
layout_context: &LayoutContext,
|
||||
table_positioning_context: &mut PositioningContext,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_for_logical_conversion: &ContainingBlock,
|
||||
containing_block_for_children: &ContainingBlock,
|
||||
) -> BoxFragment {
|
||||
if self.positioning_context.is_some() {
|
||||
self.rect.start_corner += relative_adjustement(&self.style, containing_block);
|
||||
self.rect.start_corner +=
|
||||
relative_adjustement(&self.style, containing_block_for_children);
|
||||
}
|
||||
|
||||
let mut row_group_fragment = BoxFragment::new(
|
||||
|
@ -2214,7 +2305,7 @@ impl RowGroupFragmentLayout {
|
|||
self.style,
|
||||
self.fragments,
|
||||
self.rect
|
||||
.to_physical(containing_block.effective_writing_mode()),
|
||||
.to_physical(Some(containing_block_for_logical_conversion)),
|
||||
PhysicalSides::zero(), /* padding */
|
||||
PhysicalSides::zero(), /* border */
|
||||
PhysicalSides::zero(), /* margin */
|
||||
|
@ -2414,7 +2505,7 @@ impl Table {
|
|||
layout_context: &LayoutContext,
|
||||
containing_block_for_children: &IndefiniteContainingBlock,
|
||||
) -> ContentSizes {
|
||||
let writing_mode = containing_block_for_children.style.effective_writing_mode();
|
||||
let writing_mode = containing_block_for_children.style.writing_mode;
|
||||
let mut layout = TableLayout::new(self);
|
||||
let mut table_content_sizes = layout.compute_grid_min_max(layout_context, writing_mode);
|
||||
|
||||
|
@ -2536,6 +2627,7 @@ impl TableSlotCell {
|
|||
cell_baseline: Au,
|
||||
positioning_context: &mut PositioningContext,
|
||||
table_style: &ComputedValues,
|
||||
containing_block: &ContainingBlock,
|
||||
) -> BoxFragment {
|
||||
// This must be scoped to this function because it conflicts with euclid's Zero.
|
||||
use style::Zero as StyleZero;
|
||||
|
@ -2570,7 +2662,7 @@ impl TableSlotCell {
|
|||
block: vertical_align_offset,
|
||||
};
|
||||
let vertical_align_fragment = PositioningFragment::new_anonymous(
|
||||
vertical_align_fragment_rect.to_physical(table_style.effective_writing_mode()),
|
||||
vertical_align_fragment_rect.to_physical(None),
|
||||
layout.layout.fragments,
|
||||
);
|
||||
|
||||
|
@ -2581,8 +2673,7 @@ impl TableSlotCell {
|
|||
// TODO(mrobinson): This is correct for absolutes that are direct children of the table
|
||||
// cell, but wrong for absolute fragments that are more deeply nested in the hierarchy of
|
||||
// fragments.
|
||||
let physical_cell_rect =
|
||||
cell_content_rect.to_physical(table_style.effective_writing_mode());
|
||||
let physical_cell_rect = cell_content_rect.to_physical(Some(containing_block));
|
||||
layout
|
||||
.positioning_context
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
|
@ -2596,12 +2687,8 @@ impl TableSlotCell {
|
|||
self.style.clone(),
|
||||
vec![Fragment::Positioning(vertical_align_fragment)],
|
||||
physical_cell_rect,
|
||||
layout
|
||||
.padding
|
||||
.to_physical(table_style.effective_writing_mode()),
|
||||
layout
|
||||
.border
|
||||
.to_physical(table_style.effective_writing_mode()),
|
||||
layout.padding.to_physical(table_style.writing_mode),
|
||||
layout.border.to_physical(table_style.writing_mode),
|
||||
PhysicalSides::zero(), /* margin */
|
||||
None, /* clearance */
|
||||
CollapsedBlockMargins::zero(),
|
||||
|
|
|
@ -83,9 +83,9 @@ impl Arbitrary for FloatRangeInput {
|
|||
FloatRangeInput {
|
||||
start_index,
|
||||
side: if is_left {
|
||||
FloatSide::Left
|
||||
FloatSide::InlineStart
|
||||
} else {
|
||||
FloatSide::Right
|
||||
FloatSide::InlineEnd
|
||||
},
|
||||
length,
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ fn check_node_range_setting(
|
|||
) {
|
||||
if node.band.top >= block_range.start && node.band.top < block_range.end {
|
||||
match side {
|
||||
FloatSide::Left => assert!(node.band.left.unwrap() >= value),
|
||||
FloatSide::Right => assert!(node.band.right.unwrap() <= value),
|
||||
FloatSide::InlineStart => assert!(node.band.left.unwrap() >= value),
|
||||
FloatSide::InlineEnd => assert!(node.band.right.unwrap() <= value),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,9 +357,9 @@ impl Arbitrary for FloatInput {
|
|||
block: Au::from_f32_px(height as f32),
|
||||
},
|
||||
side: if is_left {
|
||||
FloatSide::Left
|
||||
FloatSide::InlineStart
|
||||
} else {
|
||||
FloatSide::Right
|
||||
FloatSide::InlineEnd
|
||||
},
|
||||
clear: new_clear(clear),
|
||||
},
|
||||
|
@ -504,10 +504,10 @@ impl FloatPlacement {
|
|||
fn check_floats_rule_1(placement: &FloatPlacement) {
|
||||
for placed_float in &placement.placed_floats {
|
||||
match placed_float.info.side {
|
||||
FloatSide::Left => assert!(
|
||||
FloatSide::InlineStart => assert!(
|
||||
placed_float.origin.inline >= placed_float.containing_block_info.inline_start
|
||||
),
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
assert!(
|
||||
placed_float.rect().max_inline_position() <=
|
||||
placed_float.containing_block_info.inline_end
|
||||
|
@ -526,19 +526,20 @@ fn check_floats_rule_2(placement: &FloatPlacement) {
|
|||
for (this_float_index, this_float) in placement.placed_floats.iter().enumerate() {
|
||||
for prev_float in &placement.placed_floats[0..this_float_index] {
|
||||
match (this_float.info.side, prev_float.info.side) {
|
||||
(FloatSide::Left, FloatSide::Left) => {
|
||||
(FloatSide::InlineStart, FloatSide::InlineStart) => {
|
||||
assert!(
|
||||
this_float.origin.inline >= prev_float.rect().max_inline_position() ||
|
||||
this_float.origin.block >= prev_float.rect().max_block_position()
|
||||
);
|
||||
},
|
||||
(FloatSide::Right, FloatSide::Right) => {
|
||||
(FloatSide::InlineEnd, FloatSide::InlineEnd) => {
|
||||
assert!(
|
||||
this_float.rect().max_inline_position() <= prev_float.origin.inline ||
|
||||
this_float.origin.block >= prev_float.rect().max_block_position()
|
||||
);
|
||||
},
|
||||
(FloatSide::Left, FloatSide::Right) | (FloatSide::Right, FloatSide::Left) => {},
|
||||
(FloatSide::InlineStart, FloatSide::InlineEnd) |
|
||||
(FloatSide::InlineEnd, FloatSide::InlineStart) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -568,13 +569,14 @@ fn check_floats_rule_3(placement: &FloatPlacement) {
|
|||
}
|
||||
|
||||
match (this_float.info.side, other_float.info.side) {
|
||||
(FloatSide::Left, FloatSide::Right) => {
|
||||
(FloatSide::InlineStart, FloatSide::InlineEnd) => {
|
||||
assert!(this_float.rect().max_inline_position() <= other_float.origin.inline);
|
||||
},
|
||||
(FloatSide::Right, FloatSide::Left) => {
|
||||
(FloatSide::InlineEnd, FloatSide::InlineStart) => {
|
||||
assert!(this_float.origin.inline >= other_float.rect().max_inline_position());
|
||||
},
|
||||
(FloatSide::Left, FloatSide::Left) | (FloatSide::Right, FloatSide::Right) => {},
|
||||
(FloatSide::InlineStart, FloatSide::InlineStart) |
|
||||
(FloatSide::InlineEnd, FloatSide::InlineEnd) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -616,14 +618,14 @@ fn check_floats_rule_7(placement: &FloatPlacement) {
|
|||
for (placed_float_index, placed_float) in placement.placed_floats.iter().enumerate() {
|
||||
// Only consider floats that stick out.
|
||||
match placed_float.info.side {
|
||||
FloatSide::Left => {
|
||||
FloatSide::InlineStart => {
|
||||
if placed_float.rect().max_inline_position() <=
|
||||
placed_float.containing_block_info.inline_end
|
||||
{
|
||||
continue;
|
||||
}
|
||||
},
|
||||
FloatSide::Right => {
|
||||
FloatSide::InlineEnd => {
|
||||
if placed_float.origin.inline >= placed_float.containing_block_info.inline_start {
|
||||
continue;
|
||||
}
|
||||
|
@ -686,8 +688,8 @@ fn check_floats_rule_9(floats_and_perturbations: Vec<(FloatInput, u32)>) {
|
|||
let placed_float = &mut placement.placed_floats[float_index];
|
||||
let perturbation = Au::from_f32_px(perturbation as f32);
|
||||
match placed_float.info.side {
|
||||
FloatSide::Left => placed_float.origin.inline -= perturbation,
|
||||
FloatSide::Right => placed_float.origin.inline += perturbation,
|
||||
FloatSide::InlineStart => placed_float.origin.inline -= perturbation,
|
||||
FloatSide::InlineEnd => placed_float.origin.inline += perturbation,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,8 +739,8 @@ fn check_floats_rule_10(placement: &FloatPlacement) {
|
|||
}
|
||||
|
||||
match this_float.info.clear {
|
||||
Clear::Left => assert_ne!(other_float.info.side, FloatSide::Left),
|
||||
Clear::Right => assert_ne!(other_float.info.side, FloatSide::Right),
|
||||
Clear::Left => assert_ne!(other_float.info.side, FloatSide::InlineStart),
|
||||
Clear::Right => assert_ne!(other_float.info.side, FloatSide::InlineEnd),
|
||||
Clear::Both => assert!(false),
|
||||
Clear::None => unreachable!(),
|
||||
}
|
||||
|
|
2
tests/wpt/meta/css/CSS2/floats/floats-placement-vertical-001b.xht.ini
vendored
Normal file
2
tests/wpt/meta/css/CSS2/floats/floats-placement-vertical-001b.xht.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[floats-placement-vertical-001b.xht]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/CSS2/floats/floats-placement-vertical-001c.xht.ini
vendored
Normal file
2
tests/wpt/meta/css/CSS2/floats/floats-placement-vertical-001c.xht.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[floats-placement-vertical-001c.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[margin-right-100.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[margin-right-101.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[margin-right-102.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[padding-right-061.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[padding-right-062.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[padding-right-073.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[block-in-inline-margins-002a.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[block-in-inline-margins-002b.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-002.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-005.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-012.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-021.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-022.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-023.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-non-replaced-width-024.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-replaced-width-015.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-replaced-width-020.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-replaced-width-034.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-replaced-width-071.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[absolute-replaced-width-076.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[abspos-024.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[abspos-block-level-001.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[position-relative-010.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[position-relative-038.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[relpos-calcs-006.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[right-113.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[text-align-white-space-005.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[text-indent-rtl-001.xht]
|
||||
expected: FAIL
|
|
@ -17,20 +17,20 @@
|
|||
[.item 12]
|
||||
expected: FAIL
|
||||
|
||||
[.item 19]
|
||||
[.item 13]
|
||||
expected: FAIL
|
||||
|
||||
[.item 20]
|
||||
[.item 14]
|
||||
expected: FAIL
|
||||
|
||||
[.item 21]
|
||||
[.item 15]
|
||||
expected: FAIL
|
||||
|
||||
[.item 22]
|
||||
[.item 16]
|
||||
expected: FAIL
|
||||
|
||||
[.item 23]
|
||||
[.item 17]
|
||||
expected: FAIL
|
||||
|
||||
[.item 24]
|
||||
[.item 18]
|
||||
expected: FAIL
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
[.item 6]
|
||||
expected: FAIL
|
||||
|
||||
[.item 13]
|
||||
[.item 19]
|
||||
expected: FAIL
|
||||
|
||||
[.item 14]
|
||||
[.item 20]
|
||||
expected: FAIL
|
||||
|
||||
[.item 15]
|
||||
[.item 21]
|
||||
expected: FAIL
|
||||
|
||||
[.item 16]
|
||||
[.item 22]
|
||||
expected: FAIL
|
||||
|
||||
[.item 17]
|
||||
[.item 23]
|
||||
expected: FAIL
|
||||
|
||||
[.item 18]
|
||||
[.item 24]
|
||||
expected: FAIL
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
[.item 12]
|
||||
expected: FAIL
|
||||
|
||||
[.item 13]
|
||||
[.item 19]
|
||||
expected: FAIL
|
||||
|
||||
[.item 14]
|
||||
[.item 20]
|
||||
expected: FAIL
|
||||
|
||||
[.item 15]
|
||||
[.item 21]
|
||||
expected: FAIL
|
||||
|
||||
[.item 16]
|
||||
[.item 22]
|
||||
expected: FAIL
|
||||
|
||||
[.item 17]
|
||||
[.item 23]
|
||||
expected: FAIL
|
||||
|
||||
[.item 18]
|
||||
[.item 24]
|
||||
expected: FAIL
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
[.item 12]
|
||||
expected: FAIL
|
||||
|
||||
[.item 13]
|
||||
[.item 19]
|
||||
expected: FAIL
|
||||
|
||||
[.item 14]
|
||||
[.item 20]
|
||||
expected: FAIL
|
||||
|
||||
[.item 15]
|
||||
[.item 21]
|
||||
expected: FAIL
|
||||
|
||||
[.item 16]
|
||||
[.item 22]
|
||||
expected: FAIL
|
||||
|
||||
[.item 17]
|
||||
[.item 23]
|
||||
expected: FAIL
|
||||
|
||||
[.item 18]
|
||||
[.item 24]
|
||||
expected: FAIL
|
||||
|
|
2
tests/wpt/meta/css/css-align/self-alignment/self-align-safe-unsafe-grid-003.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-align/self-alignment/self-align-safe-unsafe-grid-003.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[self-align-safe-unsafe-grid-003.html]
|
||||
expected: FAIL
|
|
@ -1,19 +1,10 @@
|
|||
[position-absolute-001.html]
|
||||
[.flexbox 38]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 39]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 34]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 36]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 37]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 89]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -35,18 +26,6 @@
|
|||
[.flexbox 86]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 16]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 17]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 18]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 19]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 108]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -59,9 +38,6 @@
|
|||
[.flexbox 96]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 97]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 95]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -98,9 +74,6 @@
|
|||
[.flexbox 64]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 69]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 68]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -140,9 +113,6 @@
|
|||
[.flexbox 115]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 116]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 117]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -164,9 +134,6 @@
|
|||
[.flexbox 41]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 40]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 43]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -194,12 +161,6 @@
|
|||
[.flexbox 104]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 6]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 9]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 58]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -224,32 +185,32 @@
|
|||
[.flexbox 55]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 27]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 24]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 20]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 120]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 7]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 26]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 52]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 71]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 87]
|
||||
[.flexbox 29]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 106]
|
||||
[.flexbox 47]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 57]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 66]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 76]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 109]
|
||||
expected: FAIL
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
[.flexbox 5]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 4]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 8]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
[position-absolute-003.html]
|
||||
[.rect 13]
|
||||
expected: FAIL
|
||||
|
||||
[.rect 15]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -17,9 +14,6 @@
|
|||
[.rect 5]
|
||||
expected: FAIL
|
||||
|
||||
[.rect 14]
|
||||
expected: FAIL
|
||||
|
||||
[.rect 16]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -190,3 +190,15 @@
|
|||
|
||||
[.flexbox 95]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 38]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 46]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 54]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 62]
|
||||
expected: FAIL
|
||||
|
|
|
@ -862,3 +862,57 @@
|
|||
|
||||
[.flexbox 432]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 152]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 166]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 168]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 179]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 187]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 189]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 200]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 214]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 216]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 227]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 235]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 237]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 247]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 249]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 263]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 274]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 276]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 284]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[flex-direction-row-vertical.html]
|
||||
expected: FAIL
|
|
@ -8,15 +8,9 @@
|
|||
[.flexbox 4]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 7]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 2]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 8]
|
||||
expected: FAIL
|
||||
|
||||
[.flexbox 1]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-align-self-vert-rtl-001.xhtml]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-align-self-vert-rtl-002.xhtml]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-align-self-vert-rtl-003.xhtml]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-align-self-vert-rtl-004.xhtml]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-mbp-horiz-001-rtl-reverse.xhtml]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox-mbp-horiz-001-rtl.xhtml]
|
||||
expected: FAIL
|
|
@ -1,24 +1,3 @@
|
|||
[flexbox_justifycontent-rtl-001.html]
|
||||
[.container > div 1]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 2]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 5]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 7]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 8]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 9]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 10]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 12]
|
||||
[.container > div 11]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
[flexbox_justifycontent-rtl-002.html]
|
||||
[.container > div 1]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 2]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 3]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 4]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 5]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 6]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 7]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 8]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 9]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 10]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 11]
|
||||
expected: FAIL
|
||||
|
||||
[.container > div 12]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[flexbox_rtl-direction.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[gap-001-rtl.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[gap-004-rtl.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[gap-007-rtl.html]
|
||||
expected: FAIL
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-border-color.html]
|
||||
[Test that logical border-*-color properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-color shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-color properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-color properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical border-*-color properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
[logical-box-border-radius.html]
|
||||
[Test that logical border-*-radius properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-radius properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-radius properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical border-*-radius properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-border-style.html]
|
||||
[Test that logical border-*-style properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-style shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-style properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-style properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical border-*-style properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-border-width.html]
|
||||
[Test that logical border-*-width properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-width shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-width properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that border-*-width properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical border-*-width properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-inset.html]
|
||||
[Test that logical inset-* properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that inset-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that inset-* properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that inset-* properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical inset-* properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-margin.html]
|
||||
[Test that logical margin-* properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that margin-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that margin-* properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that margin-* properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical margin-* properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
[logical-box-padding.html]
|
||||
[Test that logical padding-* properties share computed values with their physical associates, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* shorthands set the computed value of both logical and physical longhands, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* properties honor order of appearance when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that padding-* properties honor selector specificty when both logical and physical associates are declared, with 'writing-mode: horizontal-tb; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that logical padding-* properties share computed values with their physical associates, with 'writing-mode: vertical-rl; direction: rtl; '.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[position-absolute-dynamic-static-position-floats-004.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[inline-level-absolute-in-block-level-context-007.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[inline-level-absolute-in-block-level-context-009.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[inline-level-absolute-in-block-level-context-010.html]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-tables/row-group-margin-border-padding.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-tables/row-group-margin-border-padding.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[row-group-margin-border-padding.html]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-tables/row-margin-border-padding.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-tables/row-margin-border-padding.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[row-margin-border-padding.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[trailing-space-and-text-alignment-rtl-002.html]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-text/white-space/trailing-space-and-text-alignment-rtl-003.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-text/white-space/trailing-space-and-text-alignment-rtl-003.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[trailing-space-and-text-alignment-rtl-003.html]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-023.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-023.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[white-space-pre-wrap-trailing-spaces-023.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[word-break-normal-ar-000.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[getClientRects-inline.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[table-direction.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[table-row-direction.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[table-row-group-direction.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[textarea-padding-iend-overlaps-content-001.tentative.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[textarea-padding-istart-moves-content-001.tentative.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[bdi-neutral-wrapped.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[direction_style_caching.html]
|
||||
expected: FAIL
|
2
tests/wpt/mozilla/meta/css/rtl_body.html.ini
vendored
2
tests/wpt/mozilla/meta/css/rtl_body.html.ini
vendored
|
@ -1,2 +0,0 @@
|
|||
[rtl_body.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[rtl_margin_a.html]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue