mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
Keep 1st collapsible space after a preserved one (#32037)
The logic was to remove any collapsible white space preceded by other white space. However, this should only happen if the preceding space is also collapsible. Also fixing the logic in ContentSizesComputation, which was wrong but previously it didn't matter.
This commit is contained in:
parent
5083dc7d17
commit
1898394cb3
3 changed files with 19 additions and 17 deletions
|
@ -2306,7 +2306,8 @@ struct ContentSizesComputation<'a> {
|
||||||
current_line: ContentSizes,
|
current_line: ContentSizes,
|
||||||
/// Size for whitepsace pending to be added to this line.
|
/// Size for whitepsace pending to be added to this line.
|
||||||
pending_whitespace: Au,
|
pending_whitespace: Au,
|
||||||
/// Whether or not this IFC has seen any content, excluding collapsed whitespace.
|
/// Whether or not the current line has seen any content (excluding collapsed whitespace),
|
||||||
|
/// when sizing under a max-content constraint.
|
||||||
had_content_yet: bool,
|
had_content_yet: bool,
|
||||||
/// Stack of ending padding, margin, and border to add to the length
|
/// Stack of ending padding, margin, and border to add to the length
|
||||||
/// when an inline box finishes.
|
/// when an inline box finishes.
|
||||||
|
@ -2366,7 +2367,6 @@ impl<'a> ContentSizesComputation<'a> {
|
||||||
// If this run is a forced line break, we *must* break the line
|
// If this run is a forced line break, we *must* break the line
|
||||||
// and start measuring from the inline origin once more.
|
// and start measuring from the inline origin once more.
|
||||||
if text_run.glyph_run_is_preserved_newline(run) {
|
if text_run.glyph_run_is_preserved_newline(run) {
|
||||||
self.had_content_yet = true;
|
|
||||||
self.forced_line_break();
|
self.forced_line_break();
|
||||||
self.current_line = ContentSizes::zero();
|
self.current_line = ContentSizes::zero();
|
||||||
continue;
|
continue;
|
||||||
|
@ -2375,12 +2375,12 @@ impl<'a> ContentSizesComputation<'a> {
|
||||||
let white_space =
|
let white_space =
|
||||||
text_run.parent_style.get_inherited_text().white_space;
|
text_run.parent_style.get_inherited_text().white_space;
|
||||||
if !white_space.preserve_spaces() {
|
if !white_space.preserve_spaces() {
|
||||||
// Discard any leading whitespace in the IFC. This will always be trimmed.
|
// TODO: need to handle !white_space.allow_wrap().
|
||||||
|
self.line_break_opportunity();
|
||||||
|
// Discard any leading whitespace in the line. This will always be trimmed.
|
||||||
if self.had_content_yet {
|
if self.had_content_yet {
|
||||||
// Wait to take into account other whitespace until we see more content.
|
// Wait to take into account other whitespace until we see more content.
|
||||||
// Whitespace at the end of the IFC will always be trimmed.
|
// Whitespace at the end of the line will always be trimmed.
|
||||||
// TODO: need to handle !white_space.allow_wrap().
|
|
||||||
self.line_break_opportunity();
|
|
||||||
self.pending_whitespace += advance;
|
self.pending_whitespace += advance;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -2433,6 +2433,7 @@ impl<'a> ContentSizesComputation<'a> {
|
||||||
self.paragraph.max_content =
|
self.paragraph.max_content =
|
||||||
std::cmp::max(self.paragraph.max_content, self.current_line.max_content);
|
std::cmp::max(self.paragraph.max_content, self.current_line.max_content);
|
||||||
self.current_line.max_content = Au::zero();
|
self.current_line.max_content = Au::zero();
|
||||||
|
self.had_content_yet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit_pending_whitespace(&mut self) {
|
fn commit_pending_whitespace(&mut self) {
|
||||||
|
|
|
@ -211,13 +211,13 @@ impl TextRun {
|
||||||
font_context: &mut FontContext<FontCacheThread>,
|
font_context: &mut FontContext<FontCacheThread>,
|
||||||
linebreaker: &mut Option<LineBreakLeafIter>,
|
linebreaker: &mut Option<LineBreakLeafIter>,
|
||||||
font_cache: &mut Vec<FontKeyAndMetrics>,
|
font_cache: &mut Vec<FontKeyAndMetrics>,
|
||||||
last_inline_box_ended_with_white_space: &mut bool,
|
last_inline_box_ended_with_collapsible_white_space: &mut bool,
|
||||||
on_word_boundary: &mut bool,
|
on_word_boundary: &mut bool,
|
||||||
) {
|
) {
|
||||||
let segment_results = self.segment_text(
|
let segment_results = self.segment_text(
|
||||||
font_context,
|
font_context,
|
||||||
font_cache,
|
font_cache,
|
||||||
last_inline_box_ended_with_white_space,
|
last_inline_box_ended_with_collapsible_white_space,
|
||||||
on_word_boundary,
|
on_word_boundary,
|
||||||
);
|
);
|
||||||
let inherited_text_style = self.parent_style.get_inherited_text().clone();
|
let inherited_text_style = self.parent_style.get_inherited_text().clone();
|
||||||
|
@ -282,7 +282,7 @@ impl TextRun {
|
||||||
&mut self,
|
&mut self,
|
||||||
font_context: &mut FontContext<FontCacheThread>,
|
font_context: &mut FontContext<FontCacheThread>,
|
||||||
font_cache: &mut Vec<FontKeyAndMetrics>,
|
font_cache: &mut Vec<FontKeyAndMetrics>,
|
||||||
last_inline_box_ended_with_white_space: &mut bool,
|
last_inline_box_ended_with_collapsible_white_space: &mut bool,
|
||||||
on_word_boundary: &mut bool,
|
on_word_boundary: &mut bool,
|
||||||
) -> Vec<(TextRunSegment, FontRef)> {
|
) -> Vec<(TextRunSegment, FontRef)> {
|
||||||
let font_group = font_context.font_group(self.parent_style.clone_font());
|
let font_group = font_context.font_group(self.parent_style.clone_font());
|
||||||
|
@ -291,10 +291,11 @@ impl TextRun {
|
||||||
|
|
||||||
// TODO: Eventually the text should come directly from the Cow strings of the DOM nodes.
|
// TODO: Eventually the text should come directly from the Cow strings of the DOM nodes.
|
||||||
let text = std::mem::take(&mut self.text);
|
let text = std::mem::take(&mut self.text);
|
||||||
|
let white_space = self.parent_style.clone_white_space();
|
||||||
let collapsed = WhitespaceCollapse::new(
|
let collapsed = WhitespaceCollapse::new(
|
||||||
text.as_str().chars(),
|
text.as_str().chars(),
|
||||||
self.parent_style.clone_white_space(),
|
white_space,
|
||||||
*last_inline_box_ended_with_white_space,
|
*last_inline_box_ended_with_collapsible_white_space,
|
||||||
);
|
);
|
||||||
|
|
||||||
let text_transform = self.parent_style.clone_text_transform();
|
let text_transform = self.parent_style.clone_text_transform();
|
||||||
|
@ -304,8 +305,9 @@ impl TextRun {
|
||||||
// `TextTransformation` doesn't support capitalization, so we must capitalize the whole
|
// `TextTransformation` doesn't support capitalization, so we must capitalize the whole
|
||||||
// string at once and make a copy. Here `on_word_boundary` indicates whether or not the
|
// string at once and make a copy. Here `on_word_boundary` indicates whether or not the
|
||||||
// inline formatting context as a whole is on a word boundary. This is different from
|
// inline formatting context as a whole is on a word boundary. This is different from
|
||||||
// `last_inline_box_ended_with_white_space` because the word boundaries are between
|
// `last_inline_box_ended_with_collapsible_white_space` because the word boundaries are
|
||||||
// atomic inlines and at the start of the IFC.
|
// between atomic inlines and at the start of the IFC, and because preserved spaces
|
||||||
|
// are a word boundary.
|
||||||
let collapsed_string: String = collapsed.collect();
|
let collapsed_string: String = collapsed.collect();
|
||||||
collected_text = capitalize_string(&collapsed_string, *on_word_boundary);
|
collected_text = capitalize_string(&collapsed_string, *on_word_boundary);
|
||||||
Box::new(collected_text.chars())
|
Box::new(collected_text.chars())
|
||||||
|
@ -323,8 +325,9 @@ impl TextRun {
|
||||||
let current_byte_index = next_byte_index;
|
let current_byte_index = next_byte_index;
|
||||||
next_byte_index += character.len_utf8();
|
next_byte_index += character.len_utf8();
|
||||||
|
|
||||||
*last_inline_box_ended_with_white_space = character.is_whitespace();
|
*on_word_boundary = character.is_whitespace();
|
||||||
*on_word_boundary = *last_inline_box_ended_with_white_space;
|
*last_inline_box_ended_with_collapsible_white_space =
|
||||||
|
*on_word_boundary && !white_space.preserve_spaces();
|
||||||
|
|
||||||
let prevents_soft_wrap_opportunity =
|
let prevents_soft_wrap_opportunity =
|
||||||
char_prevents_soft_wrap_opportunity_when_before_or_after_atomic(character);
|
char_prevents_soft_wrap_opportunity_when_before_or_after_atomic(character);
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[white-space-mixed-002.xht]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue