diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-12-21 15:45:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-21 14:45:34 +0000 |
commit | 74798c4b7bf173fc99b96e219c6c2cab136d5c4c (patch) | |
tree | 7d3ec58e3b05e37fad3a4e2d4c6b9d7004832bd2 /components/layout_2020/flow/inline.rs | |
parent | d007d265bd5449d6c8e5abd18f946b79ca9f31f7 (diff) | |
download | servo-74798c4b7bf173fc99b96e219c6c2cab136d5c4c.tar.gz servo-74798c4b7bf173fc99b96e219c6c2cab136d5c4c.zip |
layout: Add support for `text-align-last` (#30905)
This change adds support for `text-align-last` as well as ensuring that
it also applies to lines before forced line breaks. Two tests start to
fail because they rely on right-to-left text to pass:
- /css/css-text/text-align/text-align-last-010.html.ini
- /css/css-text/text-align/text-align-last-011.html.ini
Diffstat (limited to 'components/layout_2020/flow/inline.rs')
-rw-r--r-- | components/layout_2020/flow/inline.rs | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index ca5360469ac..f67e95400f4 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -20,7 +20,7 @@ use style::properties::ComputedValues; use style::values::computed::Length; use style::values::generics::text::LineHeight; use style::values::specified::text::{TextAlignKeyword, TextDecorationLine}; -use style::values::specified::TextJustify; +use style::values::specified::{TextAlignLast, TextJustify}; use style::Zero; use webrender_api::FontInstanceKey; use xi_unicode::{linebreak_property, LineBreakLeafIter}; @@ -537,20 +537,19 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { // Finally we finish the line itself and convert all of the LineItems into // fragments. - self.finish_current_line_and_reset(true /* last_line */); + self.finish_current_line_and_reset(true /* last_line_or_forced_line_break */); } /// Finish layout of all inline boxes for the current line. This will gather all /// [`LineItem`]s and turn them into [`Fragment`]s, then reset the /// [`InlineFormattingContextState`] preparing it for laying out a new line. - fn finish_current_line_and_reset(&mut self, last_line: bool) { + fn finish_current_line_and_reset(&mut self, last_line_or_forced_line_break: bool) { let whitespace_trimmed = self.current_line.trim_trailing_whitespace(); - let (inline_start_position, mut justification_adjustment) = self - .calculate_current_line_inline_start_and_justification_adjustment(whitespace_trimmed); - - if last_line { - justification_adjustment = Length::zero(); - } + let (inline_start_position, justification_adjustment) = self + .calculate_current_line_inline_start_and_justification_adjustment( + whitespace_trimmed, + last_line_or_forced_line_break, + ); let block_start_position = self .current_line @@ -642,18 +641,32 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { fn calculate_current_line_inline_start_and_justification_adjustment( &self, whitespace_trimmed: Length, + last_line_or_forced_line_break: bool, ) -> (Length, Length) { enum TextAlign { Start, Center, End, } - let line_left_is_inline_start = self - .containing_block - .style - .writing_mode - .line_left_is_inline_start(); - let text_align_keyword = self.containing_block.style.clone_text_align(); + let style = self.containing_block.style; + let line_left_is_inline_start = style.writing_mode.line_left_is_inline_start(); + let mut text_align_keyword = style.clone_text_align(); + + if last_line_or_forced_line_break { + text_align_keyword = match style.clone_text_align_last() { + TextAlignLast::Auto if text_align_keyword == TextAlignKeyword::Justify => { + TextAlignKeyword::Start + }, + TextAlignLast::Auto => text_align_keyword, + TextAlignLast::Start => TextAlignKeyword::Start, + TextAlignLast::End => TextAlignKeyword::End, + TextAlignLast::Left => TextAlignKeyword::Left, + TextAlignLast::Right => TextAlignKeyword::Right, + TextAlignLast::Center => TextAlignKeyword::Center, + TextAlignLast::Justify => TextAlignKeyword::Justify, + }; + } + let text_align = match text_align_keyword { TextAlignKeyword::Start => TextAlign::Start, TextAlignKeyword::Center => TextAlign::Center, @@ -936,7 +949,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { } self.commit_current_segment_to_line(); - self.process_line_break(); + self.process_line_break(true /* forced_line_break */); self.linebreak_before_new_content = false; } @@ -1023,13 +1036,13 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { self.propagate_current_nesting_level_white_space_style(); } - fn process_line_break(&mut self) { + fn process_line_break(&mut self, forced_line_break: bool) { self.current_line_segment .prepare_for_placement_on_empty_line( &self.current_line, self.inline_box_state_stack.len(), ); - self.finish_current_line_and_reset(false /* last_line */); + self.finish_current_line_and_reset(forced_line_break); } /// Process a soft wrap opportunity. This will either commit the current unbreakble @@ -1052,7 +1065,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { }; if self.new_potential_line_size_causes_line_break(&potential_line_size) { - self.process_line_break(); + self.process_line_break(false /* forced_line_break */); } self.commit_current_segment_to_line(); } |