diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs index f578988f9c0..dabdb32b88b 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; @@ -54,8 +53,8 @@ impl Fragment { Fragment::Text(t) => { is_contentful.0 = true; let rect = t - .content_rect - .to_physical(t.parent_style.writing_mode(), containing_block) + .rect + .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; @@ -80,8 +79,8 @@ impl Fragment { use style::computed_values::image_rendering::T as ImageRendering; is_contentful.0 = true; let rect = i - .content_rect - .to_physical(i.style.writing_mode(), containing_block) + .rect + .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..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; @@ -69,15 +70,16 @@ struct PartialInlineBoxFragment<'box_tree> { struct InlineFormattingContextState<'box_tree, 'a> { absolutely_positioned_fragments: &'a mut Vec>, - containing_block: &'a ContainingBlock, - line_boxes: LinesBoxes, + containing_block: &'a ContainingBlock<'a>, + 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 +203,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 +235,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 +261,14 @@ impl InlineFormattingContext { ); ifc.current_nesting_level = partial.parent_nesting_level } else { - ifc.line_boxes - .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.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,28 +276,69 @@ impl InlineFormattingContext { } } -impl LinesBoxes { +impl Lines { fn finish_line( &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.boxes.push(Fragment::Anonymous(AnonymousFragment { - children: std::mem::take(&mut top_nesting_level.fragments_so_far), + self.fragments.push(Fragment::Anonymous(AnonymousFragment { + children: line_contents, rect: Rect { start_corner, size }, - mode: containing_block.mode, + mode: containing_block.style.writing_mode, })) } } @@ -446,10 +492,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? @@ -599,7 +646,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, @@ -617,7 +664,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, @@ -637,8 +684,8 @@ 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); ifc.inline_position = Length::zero(); } } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index cbbefdabb1b..7138ffe3eb0 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; @@ -323,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, + )) }, } } @@ -412,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" ); @@ -493,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 { @@ -520,7 +525,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..f1c301771f9 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::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; use style_traits::CSSPixel; @@ -97,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), @@ -107,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::HorizontalTb, Direction::Ltr), + style, }; let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; @@ -120,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/fragments.rs b/components/layout_2020/fragments.rs index e0c335eb3c9..29f9db8e0b3 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -2,11 +2,11 @@ * 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::style_ext::{Direction, WritingMode}; +use crate::geom::flow_relative::{Rect, Sides, Vec2}; 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,12 +51,12 @@ 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 { pub parent_style: ServoArc, - pub content_rect: Rect, + pub rect: Rect, pub ascent: Length, pub font_key: FontInstanceKey, pub glyphs: Vec>, @@ -64,12 +64,23 @@ pub(crate) struct TextFragment { pub(crate) struct ImageFragment { pub style: ServoArc, - pub content_rect: Rect, + pub rect: Rect, 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, 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..2eafb78051e 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -2,9 +2,10 @@ * 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}; +use style::logical_geometry::{PhysicalCorner, WritingMode}; use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; use style_traits::CSSPixel; @@ -94,9 +95,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 +161,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 +182,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 +298,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 +308,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..f0c56afa6f1 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -27,20 +27,21 @@ 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::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; -struct ContainingBlock { +struct ContainingBlock<'a> { inline_size: Length, block_size: LengthOrAuto, - mode: (WritingMode, Direction), + style: &'a ComputedValues, } -struct DefiniteContainingBlock { +struct DefiniteContainingBlock<'a> { size: Vec2, - mode: (WritingMode, Direction), + 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 06d88709165..7aed850a5ca 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -8,7 +8,7 @@ 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; @@ -128,7 +128,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { fragments: &mut Vec, content_rect_size: &Vec2, padding: &Sides, - mode: (WritingMode, Direction), + style: &ComputedValues, ) { if absolute.is_empty() { return; @@ -141,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 @@ -149,7 +149,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { .map(|a| a.layout(layout_context, &containing_block)) .collect(), rect: padding_rect, - mode, + mode: style.writing_mode, })) } @@ -324,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; @@ -369,7 +370,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { &mut independent_layout.fragments, &content_rect.size, &padding, - style.writing_mode(), + style, ); Fragment::Box(BoxFragment { 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, }, 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..cb45544146b 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 { @@ -201,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/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: 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")]