layout: Linebreak the entire InlineFormattingContext at once (#32483)

Instead of linebreaking inside each single-font text segment, linebreak
the entire inline formatting context at once. This has several benefits:

1. It allows us to use `icu_segmenter` (already in use from style),
   which is written against a newer version of the Unicode spec --
   preventing breaking emoji clusters.
2. Opens up the possibility of changing the way that linebreaking and
   shaping work -- eventually allowing shaping across inline box
   boundaries and line breaking *after* shaping.

Co-authored-by: Rakhi Sharma <atbrakhi@igalia.com>
This commit is contained in:
Martin Robinson 2024-06-13 22:12:14 +02:00 committed by GitHub
parent 43a7dd5da0
commit bae9f6d844
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 356 additions and 220 deletions

View file

@ -70,6 +70,7 @@
pub mod construct;
pub mod line;
mod line_breaker;
pub mod text_run;
use std::cell::OnceCell;
@ -84,6 +85,7 @@ use line::{
layout_line_items, AbsolutelyPositionedLineItem, AtomicLineItem, FloatLineItem,
InlineBoxLineItem, LineItem, LineItemLayoutState, LineMetrics, TextRunLineItem,
};
use line_breaker::LineBreaker;
use serde::Serialize;
use servo_arc::Arc;
use style::computed_values::text_wrap_mode::T as TextWrapMode;
@ -1593,13 +1595,13 @@ impl InlineFormattingContext {
let text_content: String = builder.text_segments.into_iter().collect();
let mut font_metrics = Vec::new();
let mut linebreaker = None;
let mut new_linebreaker = LineBreaker::new(text_content.as_str());
inline_formatting_context.foreach(|iter_item| match iter_item {
InlineFormattingContextIterItem::Item(InlineLevelBox::TextRun(ref mut text_run)) => {
text_run.break_and_shape(
&text_content[text_run.text_range.clone()],
text_run.segment_and_shape(
&text_content,
&layout_context.font_context,
&mut linebreaker,
&mut new_linebreaker,
&mut font_metrics,
);
},