mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
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:
parent
8ec5344f70
commit
556bfb7dff
27 changed files with 437 additions and 500 deletions
|
@ -22,7 +22,7 @@ use euclid::{Point2D, Scale, Size2D, Vector2D};
|
|||
use fnv::FnvHashMap;
|
||||
use fxhash::FxHashMap;
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx::font_context;
|
||||
use gfx::font_context::FontContext;
|
||||
use gfx_traits::{node_id_from_scroll_id, Epoch};
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
|
@ -41,7 +41,7 @@ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
|||
use metrics::{PaintTimeMetrics, ProfilerMetadataFactory};
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||
use net_traits::image_cache::{ImageCache, UsePlaceholder};
|
||||
use parking_lot::{ReentrantMutex, RwLock};
|
||||
use parking_lot::RwLock;
|
||||
use profile_traits::mem::{Report, ReportKind};
|
||||
use profile_traits::path;
|
||||
use profile_traits::time::{
|
||||
|
@ -121,7 +121,10 @@ pub struct LayoutThread {
|
|||
|
||||
/// Public interface to the font cache thread. This needs to be behind a [`ReentrantMutex`],
|
||||
/// because some font cache operations can trigger others.
|
||||
font_cache_thread: Arc<ReentrantMutex<FontCacheThread>>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
|
||||
/// A FontContext to be used during layout.
|
||||
font_context: Arc<FontContext<FontCacheThread>>,
|
||||
|
||||
/// Is this the first reflow in this LayoutThread?
|
||||
first_reflow: Cell<bool>,
|
||||
|
@ -484,13 +487,13 @@ impl LayoutThread {
|
|||
|
||||
// The device pixel ratio is incorrect (it does not have the hidpi value),
|
||||
// but it will be set correctly when the initial reflow takes place.
|
||||
let font_cache_thread = Arc::new(ReentrantMutex::new(font_cache_thread));
|
||||
let font_context = Arc::new(FontContext::new(font_cache_thread.clone()));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
QuirksMode::NoQuirks,
|
||||
window_size.initial_viewport,
|
||||
window_size.device_pixel_ratio,
|
||||
Box::new(LayoutFontMetricsProvider(font_cache_thread.clone())),
|
||||
Box::new(LayoutFontMetricsProvider(font_context.clone())),
|
||||
);
|
||||
|
||||
// Ask the router to proxy IPC messages from the font cache thread to layout.
|
||||
|
@ -514,6 +517,7 @@ impl LayoutThread {
|
|||
registered_painters: RegisteredPaintersImpl(Default::default()),
|
||||
image_cache,
|
||||
font_cache_thread,
|
||||
font_context,
|
||||
first_reflow: Cell::new(true),
|
||||
font_cache_sender: ipc_font_cache_sender,
|
||||
generation: Cell::new(0),
|
||||
|
@ -584,7 +588,7 @@ impl LayoutThread {
|
|||
traversal_flags,
|
||||
),
|
||||
image_cache: self.image_cache.clone(),
|
||||
font_cache_thread: self.font_cache_thread.clone(),
|
||||
font_context: self.font_context.clone(),
|
||||
webrender_image_cache: self.webrender_image_cache.clone(),
|
||||
pending_images: Mutex::new(vec![]),
|
||||
use_rayon,
|
||||
|
@ -616,10 +620,8 @@ impl LayoutThread {
|
|||
// Find all font-face rules and notify the font cache of them.
|
||||
// GWTODO: Need to handle unloading web fonts.
|
||||
if stylesheet.is_effective_for_device(self.stylist.device(), guard) {
|
||||
let newly_loading_font_count = self
|
||||
.font_cache_thread
|
||||
.lock()
|
||||
.add_all_web_fonts_from_stylesheet(
|
||||
let newly_loading_font_count =
|
||||
self.font_cache_thread.add_all_web_fonts_from_stylesheet(
|
||||
stylesheet,
|
||||
guard,
|
||||
self.stylist.device(),
|
||||
|
@ -637,7 +639,7 @@ impl LayoutThread {
|
|||
}
|
||||
|
||||
fn handle_web_font_loaded(&self) {
|
||||
font_context::invalidate_font_caches();
|
||||
self.font_context.invalidate_caches();
|
||||
self.script_chan
|
||||
.send(ConstellationControlMsg::WebFontLoaded(self.id))
|
||||
.unwrap();
|
||||
|
@ -1076,7 +1078,7 @@ impl LayoutThread {
|
|||
self.stylist.quirks_mode(),
|
||||
window_size_data.initial_viewport,
|
||||
window_size_data.device_pixel_ratio,
|
||||
Box::new(LayoutFontMetricsProvider(self.font_cache_thread.clone())),
|
||||
Box::new(LayoutFontMetricsProvider(self.font_context.clone())),
|
||||
);
|
||||
|
||||
// Preserve any previously computed root font size.
|
||||
|
@ -1235,7 +1237,7 @@ impl RegisteredSpeculativePainters for RegisteredPaintersImpl {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LayoutFontMetricsProvider(Arc<ReentrantMutex<FontCacheThread>>);
|
||||
struct LayoutFontMetricsProvider(Arc<FontContext<FontCacheThread>>);
|
||||
|
||||
impl FontMetricsProvider for LayoutFontMetricsProvider {
|
||||
fn query_font_metrics(
|
||||
|
@ -1246,55 +1248,55 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
|
|||
_in_media_query: bool,
|
||||
_retrieve_math_scales: bool,
|
||||
) -> FontMetrics {
|
||||
layout::context::with_thread_local_font_context(&self.0, move |font_context| {
|
||||
let font_group =
|
||||
font_context.font_group_with_size(ServoArc::new(font.clone()), base_size.into());
|
||||
let Some(first_font_metrics) = font_group
|
||||
.borrow_mut()
|
||||
.first(font_context)
|
||||
.map(|font| font.borrow().metrics.clone())
|
||||
else {
|
||||
return Default::default();
|
||||
};
|
||||
let font_context = &self.0;
|
||||
let font_group = self
|
||||
.0
|
||||
.font_group_with_size(ServoArc::new(font.clone()), base_size.into());
|
||||
|
||||
// Only use the x-height of this font if it is non-zero. Some fonts return
|
||||
// inaccurate metrics, which shouldn't be used.
|
||||
let x_height = Some(first_font_metrics.x_height)
|
||||
.filter(|x_height| !x_height.is_zero())
|
||||
.map(CSSPixelLength::from);
|
||||
let Some(first_font_metrics) = font_group
|
||||
.write()
|
||||
.first(font_context)
|
||||
.map(|font| font.metrics.clone())
|
||||
else {
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
let zero_advance_measure = first_font_metrics
|
||||
.zero_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.borrow_mut()
|
||||
.find_by_codepoint(font_context, '0')?
|
||||
.borrow()
|
||||
.metrics
|
||||
.zero_horizontal_advance
|
||||
})
|
||||
.map(CSSPixelLength::from);
|
||||
let ic_width = first_font_metrics
|
||||
.ic_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.borrow_mut()
|
||||
.find_by_codepoint(font_context, '\u{6C34}')?
|
||||
.borrow()
|
||||
.metrics
|
||||
.ic_horizontal_advance
|
||||
})
|
||||
.map(CSSPixelLength::from);
|
||||
// Only use the x-height of this font if it is non-zero. Some fonts return
|
||||
// inaccurate metrics, which shouldn't be used.
|
||||
let x_height = Some(first_font_metrics.x_height)
|
||||
.filter(|x_height| !x_height.is_zero())
|
||||
.map(CSSPixelLength::from);
|
||||
|
||||
FontMetrics {
|
||||
x_height,
|
||||
zero_advance_measure,
|
||||
cap_height: None,
|
||||
ic_width,
|
||||
ascent: first_font_metrics.ascent.into(),
|
||||
script_percent_scale_down: None,
|
||||
script_script_percent_scale_down: None,
|
||||
}
|
||||
})
|
||||
let zero_advance_measure = first_font_metrics
|
||||
.zero_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.write()
|
||||
.find_by_codepoint(font_context, '0')?
|
||||
.metrics
|
||||
.zero_horizontal_advance
|
||||
})
|
||||
.map(CSSPixelLength::from);
|
||||
|
||||
let ic_width = first_font_metrics
|
||||
.ic_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.write()
|
||||
.find_by_codepoint(font_context, '\u{6C34}')?
|
||||
.metrics
|
||||
.ic_horizontal_advance
|
||||
})
|
||||
.map(CSSPixelLength::from);
|
||||
|
||||
FontMetrics {
|
||||
x_height,
|
||||
zero_advance_measure,
|
||||
cap_height: None,
|
||||
ic_width,
|
||||
ascent: first_font_metrics.ascent.into(),
|
||||
script_percent_scale_down: None,
|
||||
script_script_percent_scale_down: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue