fonts: Make FontContext thread-safe and share it per-Layout (#32205)

This allows sharing font templates, fonts, and platform fonts across
layout threads. It's the first step toward storing web fonts in the
layout versus the shared `FontCacheThread`. Now fonts and font groups
have some locking (especially on FreeType), which will probably affect
performance. On the other hand, we measured memory usage and this saves
roughly 40 megabytes of memory when loading servo.org based on data from
the memory profiler.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Martin Robinson 2024-05-02 12:34:10 +02:00 committed by GitHub
parent 8ec5344f70
commit 556bfb7dff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 437 additions and 500 deletions

View file

@ -130,6 +130,12 @@ pub struct Shaper {
font: *const Font,
}
// The HarfBuzz API is thread safe as well as our `Font`, so we can make the data
// structures here as thread-safe as well. This doesn't seem to be documented,
// but was expressed as one of the original goals of the HarfBuzz API.
unsafe impl Sync for Shaper {}
unsafe impl Send for Shaper {}
impl Drop for Shaper {
fn drop(&mut self) {
unsafe {

View file

@ -16,7 +16,7 @@ use unicode_bidi as bidi;
use webrender_api::FontInstanceKey;
use xi_unicode::LineBreakLeafIter;
use crate::font::{Font, FontMetrics, RunMetrics, ShapingFlags, ShapingOptions};
use crate::font::{FontMetrics, FontRef, RunMetrics, ShapingFlags, ShapingOptions};
use crate::text::glyph::{ByteIndex, GlyphStore};
thread_local! {
@ -180,13 +180,14 @@ impl<'a> Iterator for CharacterSliceIterator<'a> {
impl<'a> TextRun {
/// Constructs a new text run. Also returns if there is a line break at the beginning
pub fn new(
font: &mut Font,
font: FontRef,
text: String,
options: &ShapingOptions,
bidi_level: bidi::Level,
breaker: &mut Option<LineBreakLeafIter>,
) -> (TextRun, bool) {
let (glyphs, break_at_zero) = TextRun::break_and_shape(font, &text, options, breaker);
let (glyphs, break_at_zero) =
TextRun::break_and_shape(font.clone(), &text, options, breaker);
(
TextRun {
text: Arc::new(text),
@ -202,7 +203,7 @@ impl<'a> TextRun {
}
pub fn break_and_shape(
font: &mut Font,
font: FontRef,
text: &str,
options: &ShapingOptions,
breaker: &mut Option<LineBreakLeafIter>,