From b9adf8b7ac3673f135c796b2262bd2b07dc3b85c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 5 Dec 2019 11:31:35 +0100 Subject: [PATCH 1/6] =?UTF-8?q?Don=E2=80=99t=20store=20computed=20values?= =?UTF-8?q?=20of=20logical=20properties=20in=20style=20structs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are not used. --- components/style/properties/properties.mako.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 0a26ae4555b..38243aa45e4 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2590,8 +2590,10 @@ pub mod style_structs { /// The ${style_struct.name} style struct. pub struct ${style_struct.name} { % for longhand in style_struct.longhands: - /// The ${longhand.name} computed value. - pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, + % if not longhand.logical: + /// The ${longhand.name} computed value. + pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, + % endif % endfor % if style_struct.name == "InheritedText": /// The "used" text-decorations that apply to this box. @@ -3836,7 +3838,9 @@ mod lazy_static_module { % for style_struct in data.active_style_structs(): ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} { % for longhand in style_struct.longhands: - ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(), + % if not longhand.logical: + ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(), + % endif % endfor % if style_struct.name == "InheritedText": text_decorations_in_effect: From 40ad9a722d3824dfb2fcbf598b77b3a46659ba03 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 5 Dec 2019 12:33:44 +0100 Subject: [PATCH 2/6] Use the WritingMode bitflags from Stylo --- components/layout_2020/display_list.rs | 9 +++-- components/layout_2020/flow/inline.rs | 2 +- components/layout_2020/flow/mod.rs | 7 ++-- components/layout_2020/flow/root.rs | 5 +-- components/layout_2020/fragments.rs | 6 ++-- components/layout_2020/geom.rs | 44 +++++++++++------------ components/layout_2020/lib.rs | 8 +++-- components/layout_2020/positioned.rs | 9 ++--- components/layout_2020/style_ext.rs | 48 ++++++-------------------- components/style/logical_geometry.rs | 5 +++ 10 files changed, 62 insertions(+), 81 deletions(-) diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs index f578988f9c0..e8a43be33b4 100644 --- a/components/layout_2020/display_list.rs +++ b/components/layout_2020/display_list.rs @@ -4,7 +4,6 @@ use crate::fragments::{BoxFragment, Fragment}; use crate::geom::physical::{Rect, Vec2}; -use crate::style_ext::ComputedValuesExt; use euclid::{Point2D, SideOffsets2D}; use gfx::text::glyph::GlyphStore; use std::sync::Arc; @@ -55,7 +54,7 @@ impl Fragment { is_contentful.0 = true; let rect = t .content_rect - .to_physical(t.parent_style.writing_mode(), containing_block) + .to_physical(t.parent_style.writing_mode, containing_block) .translate(&containing_block.top_left); let mut baseline_origin = rect.top_left.clone(); baseline_origin.y += t.ascent; @@ -81,7 +80,7 @@ impl Fragment { is_contentful.0 = true; let rect = i .content_rect - .to_physical(i.style.writing_mode(), containing_block) + .to_physical(i.style.writing_mode, containing_block) .translate(&containing_block.top_left); let common = CommonItemProperties { clip_rect: rect.clone().into(), @@ -117,7 +116,7 @@ impl BoxFragment { ) { let border_rect = self .border_rect() - .to_physical(self.style.writing_mode(), containing_block) + .to_physical(self.style.writing_mode, containing_block) .translate(&containing_block.top_left) .into(); let common = CommonItemProperties { @@ -133,7 +132,7 @@ impl BoxFragment { self.border_display_items(builder, &common, border_rect); let content_rect = self .content_rect - .to_physical(self.style.writing_mode(), containing_block) + .to_physical(self.style.writing_mode, containing_block) .translate(&containing_block.top_left); for child in &self.children { child.build_display_list(builder, is_contentful, &content_rect) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 4c6e364a8fa..5b73737d151 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -446,7 +446,7 @@ fn layout_atomic<'box_tree>( let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: atomic.style.writing_mode(), + mode: atomic.style.writing_mode, }; assert_eq!( ifc.containing_block.mode, containing_block_for_children.mode, diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index cbbefdabb1b..aafaf1eb0fa 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -14,11 +14,12 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::adjust_static_positions; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment}; use crate::replaced::ReplacedContent; -use crate::style_ext::{ComputedValuesExt, Position}; +use crate::style_ext::ComputedValuesExt; use crate::{relative_adjustement, ContainingBlock}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; +use style::computed_values::position::T as Position; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::values::generics::length::MaxSize; @@ -412,7 +413,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: style.writing_mode(), + mode: style.writing_mode, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows assert_eq!( @@ -520,7 +521,7 @@ fn layout_in_flow_replaced_block_level<'a>( let border = style.border_width(); let computed_margin = style.margin().percentages_relative_to(cbis); let pb = &padding + &border; - let mode = style.writing_mode(); + let mode = style.writing_mode; // FIXME(nox): We shouldn't pretend we always have a fully known intrinsic size. let intrinsic_size = replaced.intrinsic_size.size_to_flow_relative(mode); // FIXME(nox): This can divide by zero. diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 6396b4dd658..882a6b0f58d 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -15,11 +15,12 @@ use crate::geom::flow_relative::Vec2; use crate::positioned::AbsolutelyPositionedBox; use crate::replaced::ReplacedContent; use crate::sizing::ContentSizesRequest; -use crate::style_ext::{Direction, Display, DisplayGeneratingBox, DisplayInside, WritingMode}; +use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator}; use script_layout_interface::wrapper_traits::LayoutNode; use servo_arc::Arc; +use style::logical_geometry::WritingMode; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; use style_traits::CSSPixel; @@ -107,7 +108,7 @@ impl BoxTreeRoot { block_size: LengthOrAuto::LengthPercentage(initial_containing_block_size.block), // FIXME: use the document’s mode: // https://drafts.csswg.org/css-writing-modes/#principal-flow - mode: (WritingMode::HorizontalTb, Direction::Ltr), + mode: WritingMode::empty(), }; let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index e0c335eb3c9..3effe5436e3 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -3,10 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::geom::flow_relative::{Rect, Sides}; -use crate::style_ext::{Direction, WritingMode}; use gfx::text::glyph::GlyphStore; use servo_arc::Arc as ServoArc; use std::sync::Arc; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::Length; use style::Zero; @@ -51,7 +51,7 @@ pub(crate) struct CollapsedMargin { pub(crate) struct AnonymousFragment { pub rect: Rect, pub children: Vec, - pub mode: (WritingMode, Direction), + pub mode: WritingMode, } pub(crate) struct TextFragment { @@ -69,7 +69,7 @@ pub(crate) struct ImageFragment { } impl AnonymousFragment { - pub fn no_op(mode: (WritingMode, Direction)) -> Self { + pub fn no_op(mode: WritingMode) -> Self { Self { children: vec![], rect: Rect::zero(), diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 39c7cb331e4..73cc8fef2a7 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::style_ext::{Direction, WritingMode}; use std::fmt; use std::ops::{Add, AddAssign, Sub}; +use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection, PhysicalCorner, WritingMode}; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; use style_traits::CSSPixel; @@ -94,9 +94,9 @@ where } impl physical::Vec2 { - pub fn size_to_flow_relative(&self, mode: (WritingMode, Direction)) -> flow_relative::Vec2 { + pub fn size_to_flow_relative(&self, mode: WritingMode) -> flow_relative::Vec2 { // https://drafts.csswg.org/css-writing-modes/#logical-to-physical - let (i, b) = if let (WritingMode::HorizontalTb, _) = mode { + let (i, b) = if mode.is_horizontal() { (&self.x, &self.y) } else { (&self.y, &self.x) @@ -160,9 +160,9 @@ impl flow_relative::Rect { } impl flow_relative::Vec2 { - pub fn size_to_physical(&self, mode: (WritingMode, Direction)) -> physical::Vec2 { + pub fn size_to_physical(&self, mode: WritingMode) -> physical::Vec2 { // https://drafts.csswg.org/css-writing-modes/#logical-to-physical - let (x, y) = if let (WritingMode::HorizontalTb, _) = mode { + let (x, y) = if mode.is_horizontal() { (&self.inline, &self.block) } else { (&self.block, &self.inline) @@ -181,21 +181,20 @@ impl From> for Point { } impl physical::Sides { - pub fn to_flow_relative(&self, mode: (WritingMode, Direction)) -> flow_relative::Sides { - use Direction::*; - use WritingMode::*; - + pub fn to_flow_relative(&self, mode: WritingMode) -> flow_relative::Sides { // https://drafts.csswg.org/css-writing-modes/#logical-to-physical - let (bs, be) = match mode.0 { - HorizontalTb => (&self.top, &self.bottom), - VerticalRl => (&self.right, &self.left), - VerticalLr => (&self.left, &self.right), + let block_flow = mode.block_flow_direction(); + let (bs, be) = match mode.block_flow_direction() { + BlockFlowDirection::TopToBottom => (&self.top, &self.bottom), + BlockFlowDirection::RightToLeft => (&self.right, &self.left), + BlockFlowDirection::LeftToRight => (&self.left, &self.right), }; - let (is, ie) = match mode { - (HorizontalTb, Ltr) => (&self.left, &self.right), - (HorizontalTb, Rtl) => (&self.right, &self.left), - (VerticalRl, Ltr) | (VerticalLr, Ltr) => (&self.top, &self.bottom), - (VerticalRl, Rtl) | (VerticalLr, Rtl) => (&self.bottom, &self.top), + use BlockFlowDirection::TopToBottom; + let (is, ie) = match (block_flow, mode.inline_base_direction()) { + (TopToBottom, InlineBaseDirection::LeftToRight) => (&self.left, &self.right), + (TopToBottom, InlineBaseDirection::RightToLeft) => (&self.right, &self.left), + (_, InlineBaseDirection::LeftToRight) => (&self.top, &self.bottom), + (_, InlineBaseDirection::RightToLeft) => (&self.bottom, &self.top), }; flow_relative::Sides { inline_start: is.clone(), @@ -298,7 +297,7 @@ impl flow_relative::Rect { pub fn to_physical( &self, - mode: (WritingMode, Direction), + mode: WritingMode, // Will be needed for other writing modes // FIXME: what if the containing block has a different mode? // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows @@ -308,10 +307,9 @@ impl flow_relative::Rect { T: Clone, { // Top-left corner - let (tl_x, tl_y) = if let (WritingMode::HorizontalTb, Direction::Ltr) = mode { - (&self.start_corner.inline, &self.start_corner.block) - } else { - unimplemented!() + let (tl_x, tl_y) = match mode.start_start_physical_corner() { + PhysicalCorner::TopLeft => (&self.start_corner.inline, &self.start_corner.block), + _ => unimplemented!(), }; physical::Rect { top_left: physical::Vec2 { diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index dd589e1819b..654c35f6941 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -27,7 +27,9 @@ pub mod wrapper; pub use flow::{BoxTreeRoot, FragmentTreeRoot}; use crate::geom::flow_relative::Vec2; -use crate::style_ext::{ComputedValuesExt, Direction, Position, WritingMode}; +use crate::style_ext::ComputedValuesExt; +use style::computed_values::position::T as Position; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; @@ -35,12 +37,12 @@ use style::Zero; struct ContainingBlock { inline_size: Length, block_size: LengthOrAuto, - mode: (WritingMode, Direction), + mode: WritingMode, } struct DefiniteContainingBlock { size: Vec2, - mode: (WritingMode, Direction), + mode: WritingMode, } /// https://drafts.csswg.org/css2/visuren.html#relative-positioning diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 06d88709165..1748c9f8f3b 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -8,10 +8,11 @@ use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::sizing::ContentSizesRequest; -use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, WritingMode}; +use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use servo_arc::Arc; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; @@ -128,7 +129,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { fragments: &mut Vec, content_rect_size: &Vec2, padding: &Sides, - mode: (WritingMode, Direction), + mode: WritingMode, ) { if absolute.is_empty() { return; @@ -324,7 +325,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: style.writing_mode(), + mode: style.writing_mode, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows assert_eq!( @@ -369,7 +370,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { &mut independent_layout.fragments, &content_rect.size, &padding, - style.writing_mode(), + style.writing_mode, ); Fragment::Box(BoxFragment { diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index 5748eac1b02..59c87fd633c 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -9,10 +9,6 @@ use style::values::computed::{NonNegativeLengthPercentage, Size}; use style::values::generics::length::MaxSize; use style::values::specified::box_ as stylo; -pub use style::computed_values::direction::T as Direction; -pub use style::computed_values::position::T as Position; -pub use style::computed_values::writing_mode::T as WritingMode; - #[derive(Clone, Copy, Eq, PartialEq)] pub(crate) enum Display { None, @@ -44,8 +40,6 @@ pub(crate) enum DisplayInside { } pub(crate) trait ComputedValuesExt { - fn writing_mode(&self) -> (WritingMode, Direction); - fn writing_mode_is_horizontal(&self) -> bool; fn inline_size_is_auto(&self) -> bool; fn inline_box_offsets_are_both_non_auto(&self) -> bool; fn box_offsets(&self) -> flow_relative::Sides; @@ -58,44 +52,24 @@ pub(crate) trait ComputedValuesExt { } impl ComputedValuesExt for ComputedValues { - fn writing_mode(&self) -> (WritingMode, Direction) { - let inherited_box = self.get_inherited_box(); - let writing_mode = inherited_box.writing_mode; - let direction = inherited_box.direction; - (writing_mode, direction) - } - - fn writing_mode_is_horizontal(&self) -> bool { - match self.get_inherited_box().writing_mode { - WritingMode::HorizontalTb => true, - WritingMode::VerticalLr | WritingMode::VerticalRl => false, - } - } - fn inline_size_is_auto(&self) -> bool { let position = self.get_position(); - let size = if self.writing_mode_is_horizontal() { + let size = if self.writing_mode.is_horizontal() { position.width } else { position.height }; - matches!(size, Size::Auto) + size == Size::Auto } fn inline_box_offsets_are_both_non_auto(&self) -> bool { let position = self.get_position(); - let offsets = if self.writing_mode_is_horizontal() { + let (a, b) = if self.writing_mode.is_horizontal() { (position.left, position.right) } else { (position.top, position.bottom) }; - matches!( - offsets, - ( - LengthPercentageOrAuto::LengthPercentage(_), - LengthPercentageOrAuto::LengthPercentage(_), - ) - ) + a != LengthPercentageOrAuto::Auto && b != LengthPercentageOrAuto::Auto } #[inline] @@ -107,7 +81,7 @@ impl ComputedValuesExt for ComputedValues { bottom: position.bottom, right: position.right, } - .to_flow_relative(self.writing_mode()) + .to_flow_relative(self.writing_mode) } #[inline] @@ -117,7 +91,7 @@ impl ComputedValuesExt for ComputedValues { x: size_to_length(position.width), y: size_to_length(position.height), } - .size_to_flow_relative(self.writing_mode()) + .size_to_flow_relative(self.writing_mode) } #[inline] @@ -127,7 +101,7 @@ impl ComputedValuesExt for ComputedValues { x: size_to_length(position.min_width), y: size_to_length(position.min_height), } - .size_to_flow_relative(self.writing_mode()) + .size_to_flow_relative(self.writing_mode) } #[inline] @@ -141,7 +115,7 @@ impl ComputedValuesExt for ComputedValues { x: unwrap(position.max_width), y: unwrap(position.max_height), } - .size_to_flow_relative(self.writing_mode()) + .size_to_flow_relative(self.writing_mode) } #[inline] @@ -153,7 +127,7 @@ impl ComputedValuesExt for ComputedValues { bottom: padding.padding_bottom.0, right: padding.padding_right.0, } - .to_flow_relative(self.writing_mode()) + .to_flow_relative(self.writing_mode) } fn border_width(&self) -> flow_relative::Sides { @@ -164,7 +138,7 @@ impl ComputedValuesExt for ComputedValues { bottom: border.border_bottom_width.0, right: border.border_right_width.0, } - .to_flow_relative(self.writing_mode()) + .to_flow_relative(self.writing_mode) } fn margin(&self) -> flow_relative::Sides { @@ -175,7 +149,7 @@ impl ComputedValuesExt for ComputedValues { bottom: margin.margin_bottom, right: margin.margin_right, } - .to_flow_relative(self.writing_mode()) + .to_flow_relative(self.writing_mode) } } diff --git a/components/style/logical_geometry.rs b/components/style/logical_geometry.rs index cad7e1d001b..9019d252cdb 100644 --- a/components/style/logical_geometry.rs +++ b/components/style/logical_geometry.rs @@ -173,6 +173,11 @@ impl WritingMode { self.intersects(WritingMode::VERTICAL) } + #[inline] + pub fn is_horizontal(&self) -> bool { + !self.is_vertical() + } + /// Assuming .is_vertical(), does the block direction go left to right? #[inline] pub fn is_vertical_lr(&self) -> bool { From fa1adf2ad31206a3dcade6015569c1266fd95ecd Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 7 Dec 2019 13:40:57 +0100 Subject: [PATCH 3/6] Containing blocks contains styles rather than just a writing mode --- components/layout_2020/flow/inline.rs | 9 +++++---- components/layout_2020/flow/mod.rs | 14 +++++++++----- components/layout_2020/flow/root.rs | 7 ++++--- components/layout_2020/geom.rs | 3 ++- components/layout_2020/lib.rs | 9 ++++----- components/layout_2020/positioned.rs | 14 +++++++------- 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 5b73737d151..3c763fbe390 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -69,7 +69,7 @@ struct PartialInlineBoxFragment<'box_tree> { struct InlineFormattingContextState<'box_tree, 'a> { absolutely_positioned_fragments: &'a mut Vec>, - containing_block: &'a ContainingBlock, + containing_block: &'a ContainingBlock<'a>, line_boxes: LinesBoxes, inline_position: Length, partial_inline_boxes_stack: Vec>, @@ -292,7 +292,7 @@ impl LinesBoxes { self.boxes.push(Fragment::Anonymous(AnonymousFragment { children: std::mem::take(&mut top_nesting_level.fragments_so_far), rect: Rect { start_corner, size }, - mode: containing_block.mode, + mode: containing_block.style.writing_mode, })) } } @@ -446,10 +446,11 @@ fn layout_atomic<'box_tree>( let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: atomic.style.writing_mode, + style: &atomic.style, }; assert_eq!( - ifc.containing_block.mode, containing_block_for_children.mode, + ifc.containing_block.style.writing_mode, + containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); // FIXME is this correct? diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index aafaf1eb0fa..7138ffe3eb0 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -324,11 +324,15 @@ impl BlockLevelBox { }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { absolutely_positioned_fragments.push(box_.layout(Vec2::zero(), tree_rank)); - Fragment::Anonymous(AnonymousFragment::no_op(containing_block.mode)) + Fragment::Anonymous(AnonymousFragment::no_op( + containing_block.style.writing_mode, + )) }, BlockLevelBox::OutOfFlowFloatBox(_box_) => { // TODO - Fragment::Anonymous(AnonymousFragment::no_op(containing_block.mode)) + Fragment::Anonymous(AnonymousFragment::no_op( + containing_block.style.writing_mode, + )) }, } } @@ -413,11 +417,11 @@ fn layout_in_flow_non_replaced_block_level<'a>( let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: style.writing_mode, + style, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows assert_eq!( - containing_block.mode, containing_block_for_children.mode, + containing_block.style.writing_mode, containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); @@ -494,7 +498,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( &mut flow_layout.fragments, &content_rect.size, &padding, - containing_block_for_children.mode, + style, ) } BoxFragment { diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 882a6b0f58d..f1c301771f9 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -20,7 +20,7 @@ use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator}; use script_layout_interface::wrapper_traits::LayoutNode; use servo_arc::Arc; -use style::logical_geometry::WritingMode; +use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; use style_traits::CSSPixel; @@ -98,6 +98,7 @@ impl BoxTreeRoot { layout_context: &LayoutContext, viewport: geom::Size, ) -> FragmentTreeRoot { + let style = ComputedValues::initial_values(); let initial_containing_block_size = Vec2 { inline: Length::new(viewport.width), block: Length::new(viewport.height), @@ -108,7 +109,7 @@ impl BoxTreeRoot { block_size: LengthOrAuto::LengthPercentage(initial_containing_block_size.block), // FIXME: use the document’s mode: // https://drafts.csswg.org/css-writing-modes/#principal-flow - mode: WritingMode::empty(), + style, }; let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; @@ -121,7 +122,7 @@ impl BoxTreeRoot { let initial_containing_block = DefiniteContainingBlock { size: initial_containing_block_size, - mode: initial_containing_block.mode, + style, }; independent_layout.fragments.par_extend( absolutely_positioned_fragments diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 73cc8fef2a7..2eafb78051e 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -4,7 +4,8 @@ use std::fmt; use std::ops::{Add, AddAssign, Sub}; -use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection, PhysicalCorner, WritingMode}; +use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection}; +use style::logical_geometry::{PhysicalCorner, WritingMode}; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; use style_traits::CSSPixel; diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index 654c35f6941..f0c56afa6f1 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -29,20 +29,19 @@ pub use flow::{BoxTreeRoot, FragmentTreeRoot}; use crate::geom::flow_relative::Vec2; use crate::style_ext::ComputedValuesExt; use style::computed_values::position::T as Position; -use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; -struct ContainingBlock { +struct ContainingBlock<'a> { inline_size: Length, block_size: LengthOrAuto, - mode: WritingMode, + style: &'a ComputedValues, } -struct DefiniteContainingBlock { +struct DefiniteContainingBlock<'a> { size: Vec2, - mode: WritingMode, + style: &'a ComputedValues, } /// https://drafts.csswg.org/css2/visuren.html#relative-positioning diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 1748c9f8f3b..7aed850a5ca 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -12,7 +12,6 @@ use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use servo_arc::Arc; -use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; @@ -129,7 +128,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { fragments: &mut Vec, content_rect_size: &Vec2, padding: &Sides, - mode: WritingMode, + style: &ComputedValues, ) { if absolute.is_empty() { return; @@ -142,7 +141,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { .inflate(&padding); let containing_block = DefiniteContainingBlock { size: padding_rect.size.clone(), - mode, + style, }; fragments.push(Fragment::Anonymous(AnonymousFragment { children: absolute @@ -150,7 +149,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { .map(|a| a.layout(layout_context, &containing_block)) .collect(), rect: padding_rect, - mode, + mode: style.writing_mode, })) } @@ -325,11 +324,12 @@ impl<'a> AbsolutelyPositionedFragment<'a> { let containing_block_for_children = ContainingBlock { inline_size, block_size, - mode: style.writing_mode, + style, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows assert_eq!( - containing_block.mode, containing_block_for_children.mode, + containing_block.style.writing_mode, + containing_block_for_children.style.writing_mode, "Mixed writing modes are not supported yet" ); let dummy_tree_rank = 0; @@ -370,7 +370,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { &mut independent_layout.fragments, &content_rect.size, &padding, - style.writing_mode, + style, ); Fragment::Box(BoxFragment { From ce9fc3e651ca09fc11140972d4b771629f99adf3 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 7 Dec 2019 13:47:04 +0100 Subject: [PATCH 4/6] Rename LineBoxes to Lines, since it contains fragments --- components/layout_2020/flow/inline.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 3c763fbe390..25546325c1d 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -70,14 +70,15 @@ struct PartialInlineBoxFragment<'box_tree> { struct InlineFormattingContextState<'box_tree, 'a> { absolutely_positioned_fragments: &'a mut Vec>, containing_block: &'a ContainingBlock<'a>, - line_boxes: LinesBoxes, + lines: Lines, inline_position: Length, partial_inline_boxes_stack: Vec>, current_nesting_level: InlineNestingLevelState<'box_tree>, } -struct LinesBoxes { - boxes: Vec, +struct Lines { + // One anonymous fragment per line + fragments: Vec, next_line_block_position: Length, } @@ -201,8 +202,8 @@ impl InlineFormattingContext { absolutely_positioned_fragments, containing_block, partial_inline_boxes_stack: Vec::new(), - line_boxes: LinesBoxes { - boxes: Vec::new(), + lines: Lines { + fragments: Vec::new(), next_line_block_position: Length::zero(), }, inline_position: Length::zero(), @@ -233,7 +234,7 @@ impl InlineFormattingContext { DisplayOutside::Inline => ifc.inline_position, DisplayOutside::Block => Length::zero(), }, - block: ifc.line_boxes.next_line_block_position, + block: ifc.lines.next_line_block_position, }, Display::Contents => { panic!("display:contents does not generate an abspos box") @@ -259,11 +260,11 @@ impl InlineFormattingContext { ); ifc.current_nesting_level = partial.parent_nesting_level } else { - ifc.line_boxes + ifc.lines .finish_line(&mut ifc.current_nesting_level, containing_block); return FlowLayout { - fragments: ifc.line_boxes.boxes, - content_block_size: ifc.line_boxes.next_line_block_position, + fragments: ifc.lines.fragments, + content_block_size: ifc.lines.next_line_block_position, collapsible_margins_in_children: CollapsedBlockMargins::zero(), }; } @@ -271,7 +272,7 @@ impl InlineFormattingContext { } } -impl LinesBoxes { +impl Lines { fn finish_line( &mut self, top_nesting_level: &mut InlineNestingLevelState, @@ -289,7 +290,7 @@ impl LinesBoxes { ), }; self.next_line_block_position += size.block; - self.boxes.push(Fragment::Anonymous(AnonymousFragment { + self.fragments.push(Fragment::Anonymous(AnonymousFragment { children: std::mem::take(&mut top_nesting_level.fragments_so_far), rect: Rect { start_corner, size }, mode: containing_block.style.writing_mode, @@ -638,8 +639,7 @@ impl TextRun { partial.parent_nesting_level.inline_start = Length::zero(); nesting_level = &mut partial.parent_nesting_level; } - ifc.line_boxes - .finish_line(nesting_level, ifc.containing_block); + ifc.lines.finish_line(nesting_level, ifc.containing_block); ifc.inline_position = Length::zero(); } } From 6d91d77fba1e2151f32379bfd7552444b00bdde7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 7 Dec 2019 14:05:37 +0100 Subject: [PATCH 5/6] Rename content_rect to rect in TextFragment and ImageFragment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since they don’t have padding etc. --- components/layout_2020/display_list.rs | 4 ++-- components/layout_2020/flow/inline.rs | 4 ++-- components/layout_2020/fragments.rs | 4 ++-- components/layout_2020/replaced.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs index e8a43be33b4..dabdb32b88b 100644 --- a/components/layout_2020/display_list.rs +++ b/components/layout_2020/display_list.rs @@ -53,7 +53,7 @@ impl Fragment { Fragment::Text(t) => { is_contentful.0 = true; let rect = t - .content_rect + .rect .to_physical(t.parent_style.writing_mode, containing_block) .translate(&containing_block.top_left); let mut baseline_origin = rect.top_left.clone(); @@ -79,7 +79,7 @@ impl Fragment { use style::computed_values::image_rendering::T as ImageRendering; is_contentful.0 = true; let rect = i - .content_rect + .rect .to_physical(i.style.writing_mode, containing_block) .translate(&containing_block.top_left); let common = CommonItemProperties { diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 25546325c1d..bd1f2768723 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -601,7 +601,7 @@ impl TextRun { LineHeight::Number(n) => font_size * n.0, LineHeight::Length(l) => l.0, }; - let content_rect = Rect { + let rect = Rect { start_corner: Vec2 { block: Length::zero(), inline: ifc.inline_position - ifc.current_nesting_level.inline_start, @@ -619,7 +619,7 @@ impl TextRun { .fragments_so_far .push(Fragment::Text(TextFragment { parent_style: self.parent_style.clone(), - content_rect, + rect, ascent: font_ascent.into(), font_key, glyphs, diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 3effe5436e3..4dbacc5611e 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -56,7 +56,7 @@ pub(crate) struct AnonymousFragment { pub(crate) struct TextFragment { pub parent_style: ServoArc, - pub content_rect: Rect, + pub rect: Rect, pub ascent: Length, pub font_key: FontInstanceKey, pub glyphs: Vec>, @@ -64,7 +64,7 @@ pub(crate) struct TextFragment { pub(crate) struct ImageFragment { pub style: ServoArc, - pub content_rect: Rect, + pub rect: Rect, pub image_key: ImageKey, } diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index 8cb77d267bd..8a28cbf763c 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -45,7 +45,7 @@ impl ReplacedContent { .map(|image_key| { Fragment::Image(ImageFragment { style: style.clone(), - content_rect: flow_relative::Rect { + rect: flow_relative::Rect { start_corner: flow_relative::Vec2::zero(), size, }, From 9f4b1a0f147de0d81d89862007aea4e6cce3a743 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 7 Dec 2019 14:08:11 +0100 Subject: [PATCH 6/6] Implement `text-align` (except `justify`) --- components/layout_2020/flow/inline.rs | 62 ++++++++++++++++--- components/layout_2020/fragments.rs | 13 +++- components/style/logical_geometry.rs | 14 +++++ .../longhands/inherited_text.mako.rs | 1 - components/style/values/specified/text.rs | 7 ++- 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index bd1f2768723..0cacfb794a7 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -18,6 +18,7 @@ use gfx::text::text_run::GlyphRun; use servo_arc::Arc; use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage, Percentage}; +use style::values::specified::text::TextAlignKeyword; use style::Zero; use webrender_api::FontInstanceKey; @@ -260,8 +261,11 @@ impl InlineFormattingContext { ); ifc.current_nesting_level = partial.parent_nesting_level } else { - ifc.lines - .finish_line(&mut ifc.current_nesting_level, containing_block); + ifc.lines.finish_line( + &mut ifc.current_nesting_level, + containing_block, + ifc.inline_position, + ); return FlowLayout { fragments: ifc.lines.fragments, content_block_size: ifc.lines.next_line_block_position, @@ -277,21 +281,62 @@ impl Lines { &mut self, top_nesting_level: &mut InlineNestingLevelState, containing_block: &ContainingBlock, + line_content_inline_size: Length, ) { + let mut line_contents = std::mem::take(&mut top_nesting_level.fragments_so_far); + let line_block_size = std::mem::replace( + &mut top_nesting_level.max_block_size_of_fragments_so_far, + Length::zero(), + ); + enum TextAlign { + Start, + Center, + End, + } + let line_left_is_inline_start = containing_block + .style + .writing_mode + .line_left_is_inline_start(); + let text_align = match containing_block.style.clone_text_align() { + TextAlignKeyword::Start => TextAlign::Start, + TextAlignKeyword::Center => TextAlign::Center, + TextAlignKeyword::End => TextAlign::End, + TextAlignKeyword::Left => { + if line_left_is_inline_start { + TextAlign::Start + } else { + TextAlign::End + } + }, + TextAlignKeyword::Right => { + if line_left_is_inline_start { + TextAlign::End + } else { + TextAlign::Start + } + }, + }; + let move_by = match text_align { + TextAlign::Start => Length::zero(), + TextAlign::Center => (containing_block.inline_size - line_content_inline_size) / 2., + TextAlign::End => containing_block.inline_size - line_content_inline_size, + }; + if move_by > Length::zero() { + for fragment in &mut line_contents { + fragment.position_mut().inline += move_by; + } + } let start_corner = Vec2 { inline: Length::zero(), block: self.next_line_block_position, }; let size = Vec2 { inline: containing_block.inline_size, - block: std::mem::replace( - &mut top_nesting_level.max_block_size_of_fragments_so_far, - Length::zero(), - ), + block: line_block_size, }; self.next_line_block_position += size.block; self.fragments.push(Fragment::Anonymous(AnonymousFragment { - children: std::mem::take(&mut top_nesting_level.fragments_so_far), + children: line_contents, rect: Rect { start_corner, size }, mode: containing_block.style.writing_mode, })) @@ -639,7 +684,8 @@ impl TextRun { partial.parent_nesting_level.inline_start = Length::zero(); nesting_level = &mut partial.parent_nesting_level; } - ifc.lines.finish_line(nesting_level, ifc.containing_block); + ifc.lines + .finish_line(nesting_level, ifc.containing_block, ifc.inline_position); ifc.inline_position = Length::zero(); } } diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 4dbacc5611e..29f9db8e0b3 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::geom::flow_relative::{Rect, Sides}; +use crate::geom::flow_relative::{Rect, Sides, Vec2}; use gfx::text::glyph::GlyphStore; use servo_arc::Arc as ServoArc; use std::sync::Arc; @@ -68,6 +68,17 @@ pub(crate) struct ImageFragment { pub image_key: ImageKey, } +impl Fragment { + pub fn position_mut(&mut self) -> &mut Vec2 { + match self { + Fragment::Box(f) => &mut f.content_rect.start_corner, + Fragment::Anonymous(f) => &mut f.rect.start_corner, + Fragment::Text(f) => &mut f.rect.start_corner, + Fragment::Image(f) => &mut f.rect.start_corner, + } + } +} + impl AnonymousFragment { pub fn no_op(mode: WritingMode) -> Self { Self { diff --git a/components/style/logical_geometry.rs b/components/style/logical_geometry.rs index 9019d252cdb..cb45544146b 100644 --- a/components/style/logical_geometry.rs +++ b/components/style/logical_geometry.rs @@ -206,6 +206,20 @@ impl WritingMode { self.intersects(WritingMode::UPRIGHT) } + /// https://drafts.csswg.org/css-writing-modes/#logical-to-physical + /// + /// | Return | line-left is… | line-right is… | + /// |---------|---------------|----------------| + /// | `true` | inline-start | inline-end | + /// | `false` | inline-end | inline-start | + #[inline] + pub fn line_left_is_inline_start(&self) -> bool { + // https://drafts.csswg.org/css-writing-modes/#inline-start + // “For boxes with a used direction value of ltr, this means the line-left side. + // For boxes with a used direction value of rtl, this means the line-right side.” + self.is_bidi_ltr() + } + #[inline] pub fn inline_start_physical_side(&self) -> PhysicalSide { match (self.is_vertical(), self.is_inline_tb(), self.is_bidi_ltr()) { diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 428b40a101f..e7cfbba377b 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -156,7 +156,6 @@ ${helpers.predefined_type( "TextAlign", "computed::TextAlign::Start", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", animation_value_type="discrete", spec="https://drafts.csswg.org/css-text/#propdef-text-align", servo_restyle_damage = "reflow", diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 946e97eb619..cc4bcee1a55 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -544,6 +544,7 @@ pub enum TextAlignKeyword { Left, Right, Center, + #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] Justify, #[cfg(feature = "gecko")] MozCenter, @@ -551,11 +552,11 @@ pub enum TextAlignKeyword { MozLeft, #[cfg(feature = "gecko")] MozRight, - #[cfg(feature = "servo")] + #[cfg(feature = "servo-layout-2013")] ServoCenter, - #[cfg(feature = "servo")] + #[cfg(feature = "servo-layout-2013")] ServoLeft, - #[cfg(feature = "servo")] + #[cfg(feature = "servo-layout-2013")] ServoRight, #[css(skip)] #[cfg(feature = "gecko")]