diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 4271efd75a8..af84b49149d 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -844,20 +844,20 @@ impl IOCompositor { }, ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFont( + font_key, data, index, - key_sender, )) => { - let _ = key_sender.send(self.add_font(index, data)); + self.add_font(font_key, index, data); }, ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::AddFontInstance( + font_instance_key, font_key, size, flags, - sender, )) => { - let _ = sender.send(self.add_font_instance(font_key, size, flags)); + self.add_font_instance(font_instance_key, font_key, size, flags); }, ForwardedToCompositorMsg::Layout(ScriptToCompositorMsg::RemoveFonts( @@ -884,33 +884,45 @@ impl IOCompositor { .send_transaction(self.webrender_document, txn); }, + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys( + number_of_font_keys, + number_of_font_instance_keys, + result_sender, + )) => { + let font_keys = (0..number_of_font_keys) + .map(|_| self.webrender_api.generate_font_key()) + .collect(); + let font_instance_keys = (0..number_of_font_instance_keys) + .map(|_| self.webrender_api.generate_font_instance_key()) + .collect(); + let _ = result_sender.send((font_keys, font_instance_keys)); + }, + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance( + font_instance_key, font_key, size, flags, - sender, )) => { - let _ = sender.send(self.add_font_instance(font_key, size, flags)); + self.add_font_instance(font_instance_key, font_key, size, flags); }, ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont( - key_sender, + font_key, index, data, )) => { - let _ = key_sender.send(self.add_font(index, data)); + self.add_font(font_key, index, data); }, ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont( - key_sender, + font_key, native_handle, )) => { - let font_key = self.webrender_api.generate_font_key(); let mut transaction = Transaction::new(); transaction.add_native_font(font_key, native_handle); self.webrender_api .send_transaction(self.webrender_document, transaction); - let _ = key_sender.send(font_key); }, ForwardedToCompositorMsg::Canvas(CanvasToCompositorMsg::GenerateKey(sender)) => { @@ -956,26 +968,6 @@ impl IOCompositor { self.remove_pipeline_root_layer(pipeline_id); let _ = sender.send(()); }, - CompositorMsg::Forwarded(ForwardedToCompositorMsg::SystemFontService( - FontToCompositorMsg::AddFontInstance(_, _, _, sender), - )) => { - let _ = sender.send(self.webrender_api.generate_font_instance_key()); - }, - CompositorMsg::Forwarded(ForwardedToCompositorMsg::Layout( - ScriptToCompositorMsg::AddFontInstance(_, _, _, sender), - )) => { - let _ = sender.send(self.webrender_api.generate_font_instance_key()); - }, - CompositorMsg::Forwarded(ForwardedToCompositorMsg::SystemFontService( - FontToCompositorMsg::AddFont(sender, _, _), - )) => { - let _ = sender.send(self.webrender_api.generate_font_key()); - }, - CompositorMsg::Forwarded(ForwardedToCompositorMsg::Layout( - ScriptToCompositorMsg::AddFont(_, _, sender), - )) => { - let _ = sender.send(self.webrender_api.generate_font_key()); - }, CompositorMsg::Forwarded(ForwardedToCompositorMsg::Canvas( CanvasToCompositorMsg::GenerateKey(sender), )) => { @@ -2527,11 +2519,11 @@ impl IOCompositor { fn add_font_instance( &mut self, + instance_key: FontInstanceKey, font_key: FontKey, size: f32, flags: FontInstanceFlags, - ) -> FontInstanceKey { - let instance_key = self.webrender_api.generate_font_instance_key(); + ) { let mut transaction = Transaction::new(); let font_instance_options = FontInstanceOptions { @@ -2549,15 +2541,12 @@ impl IOCompositor { self.webrender_api .send_transaction(self.webrender_document, transaction); - instance_key } - fn add_font(&mut self, index: u32, data: Arc) -> FontKey { - let font_key = self.webrender_api.generate_font_key(); + fn add_font(&mut self, font_key: FontKey, index: u32, data: Arc) { let mut transaction = Transaction::new(); transaction.add_raw_font(font_key, (**data).into(), index); self.webrender_api .send_transaction(self.webrender_document, transaction); - font_key } } diff --git a/components/fonts/font.rs b/components/fonts/font.rs index 47de63bad2c..dce89c78746 100644 --- a/components/fonts/font.rs +++ b/components/fonts/font.rs @@ -224,7 +224,7 @@ pub struct Font { pub descriptor: FontDescriptor, shaper: OnceLock, cached_shape_data: RwLock, - pub font_key: FontInstanceKey, + pub font_instance_key: OnceLock, /// If this is a synthesized small caps font, then this font reference is for /// the version of the font used to replace lowercase ASCII letters. It's up @@ -252,7 +252,9 @@ impl malloc_size_of::MallocSizeOf for Font { self.metrics.size_of(ops) + self.descriptor.size_of(ops) + self.cached_shape_data.read().size_of(ops) + - self.font_key.size_of(ops) + self.font_instance_key + .get() + .map_or(0, |key| key.size_of(ops)) } } @@ -278,7 +280,7 @@ impl Font { descriptor, metrics, cached_shape_data: Default::default(), - font_key: FontInstanceKey::default(), + font_instance_key: Default::default(), synthesized_small_caps, has_color_bitmap_or_colr_table: OnceLock::new(), can_do_fast_shaping: OnceLock::new(), @@ -301,6 +303,12 @@ impl Font { self.table_for_tag(COLR).is_some() }) } + + pub fn key(&self, font_context: &FontContext) -> FontInstanceKey { + *self + .font_instance_key + .get_or_init(|| font_context.create_font_instance_key(self)) + } } bitflags! { diff --git a/components/fonts/font_context.rs b/components/fonts/font_context.rs index 896007c5829..66fed552e7b 100644 --- a/components/fonts/font_context.rs +++ b/components/fonts/font_context.rs @@ -12,7 +12,6 @@ use app_units::Au; use crossbeam_channel::unbounded; use fnv::FnvHasher; use fonts_traits::WebFontLoadFinishedCallback; -use ipc_channel::ipc; use log::{debug, trace}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of_derive::MallocSizeOf; @@ -36,7 +35,7 @@ use webrender_traits::{ScriptToCompositorMsg, WebRenderScriptApi}; use crate::font::{ Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope, }; -use crate::font_store::{CrossThreadFontStore, CrossThreadWebRenderFontStore}; +use crate::font_store::CrossThreadFontStore; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods}; use crate::platform::font::PlatformFont; use crate::system_font_service::{CSSFontFaceDescriptors, FontIdentifier}; @@ -66,7 +65,15 @@ pub struct FontContext { RwLock>, BuildHasherDefault>>, web_fonts: CrossThreadFontStore, - webrender_font_store: CrossThreadWebRenderFontStore, + + /// A collection of WebRender [`FontKey`]s generated for the web fonts that this + /// [`FontContext`] controls. + webrender_font_keys: RwLock>, + + /// A collection of WebRender [`FontInstanceKey`]s generated for the web fonts that + /// this [`FontContext`] controls. + webrender_font_instance_keys: RwLock>, + have_removed_web_fonts: AtomicBool, } @@ -104,7 +111,8 @@ impl FontContext { fonts: Default::default(), resolved_font_groups: Default::default(), web_fonts: Arc::new(RwLock::default()), - webrender_font_store: Arc::new(RwLock::default()), + webrender_font_keys: RwLock::default(), + webrender_font_instance_keys: RwLock::default(), have_removed_web_fonts: AtomicBool::new(false), } } @@ -274,71 +282,82 @@ impl FontContext { font_descriptor: FontDescriptor, synthesized_small_caps: Option, ) -> Result { - let mut font = Font::new( + Ok(Arc::new(Font::new( font_template.clone(), font_descriptor.clone(), self.get_font_data(&font_template.identifier()), synthesized_small_caps, - )?; + )?)) + } - font.font_key = match font_template.identifier() { + pub(crate) fn create_font_instance_key(&self, font: &Font) -> FontInstanceKey { + let result = match font.template.identifier() { FontIdentifier::Local(_) | FontIdentifier::Mock(_) => { self.system_font_service_proxy.get_system_font_instance( - font_template.identifier(), - font_descriptor.pt_size, + font.template.identifier(), + font.descriptor.pt_size, font.webrender_font_instance_flags(), ) }, - FontIdentifier::Web(_) => self.webrender_font_store.write().get_font_instance( + FontIdentifier::Web(_) => self.create_web_font_instance( self, - font_template.clone(), - font_descriptor.pt_size, + font.template.clone(), + font.descriptor.pt_size, font.webrender_font_instance_flags(), ), }; + result + } - Ok(Arc::new(font)) + pub(crate) fn create_web_font_instance( + &self, + font_context: &FontContext, + font_template: FontTemplateRef, + pt_size: Au, + flags: FontInstanceFlags, + ) -> FontInstanceKey { + let identifier = font_template.identifier().clone(); + let font_data = font_context.get_font_data(&identifier); + let font_key = *self + .webrender_font_keys + .write() + .entry(identifier.clone()) + .or_insert_with(|| { + let font_key = self.system_font_service_proxy.generate_font_key(); + let _ = self + .webrender_api + .lock() + .sender() + .send(ScriptToCompositorMsg::AddFont( + font_key, + font_data.as_ipc_shared_memory(), + identifier.index(), + )); + font_key + }); + + let key = *self + .webrender_font_instance_keys + .write() + .entry((font_key, pt_size)) + .or_insert_with(|| { + let font_instance_key = self.system_font_service_proxy.generate_font_instance_key(); + let _ = self.webrender_api.lock().sender().send( + ScriptToCompositorMsg::AddFontInstance( + font_instance_key, + font_key, + pt_size.to_f32_px(), + flags, + ), + ); + font_instance_key + }); + key } fn invalidate_font_groups_after_web_font_load(&self) { self.resolved_font_groups.write().clear(); } - - pub(crate) fn get_web_font(&self, data: Arc, index: u32) -> FontKey { - let (result_sender, result_receiver) = - ipc::channel().expect("failed to create IPC channel"); - let _ = self - .webrender_api - .lock() - .sender() - .send(ScriptToCompositorMsg::AddFont( - data.as_ipc_shared_memory(), - index, - result_sender, - )); - result_receiver.recv().unwrap() - } - - pub(crate) fn get_web_font_instance( - &self, - font_key: FontKey, - font_size: f32, - font_flags: FontInstanceFlags, - ) -> FontInstanceKey { - let (result_sender, result_receiver) = - ipc::channel().expect("failed to create IPC channel"); - let _ = self - .webrender_api - .lock() - .sender() - .send(ScriptToCompositorMsg::AddFontInstance( - font_key, - font_size, - font_flags, - result_sender, - )); - result_receiver.recv().unwrap() - } } #[derive(Clone)] @@ -538,9 +557,16 @@ impl FontContextWebFontMethods for Arc { all: bool, ) -> (Vec, Vec) { if all { - let mut webrender_font_store = self.webrender_font_store.write(); + let mut webrender_font_keys = self.webrender_font_keys.write(); + let mut webrender_font_instance_keys = self.webrender_font_instance_keys.write(); self.have_removed_web_fonts.store(false, Ordering::Relaxed); - return webrender_font_store.remove_all_fonts(); + return ( + webrender_font_keys.drain().map(|(_, key)| key).collect(), + webrender_font_instance_keys + .drain() + .map(|(_, key)| key) + .collect(), + ); } if !self.have_removed_web_fonts.load(Ordering::Relaxed) { @@ -551,13 +577,11 @@ impl FontContextWebFontMethods for Arc { let mut web_fonts = self.web_fonts.write(); let _fonts = self.fonts.write(); let _font_groups = self.resolved_font_groups.write(); - let mut webrender_font_store = self.webrender_font_store.write(); + let mut webrender_font_keys = self.webrender_font_keys.write(); + let mut webrender_font_instance_keys = self.webrender_font_instance_keys.write(); - let mut unused_identifiers: HashSet = webrender_font_store - .webrender_font_key_map - .keys() - .cloned() - .collect(); + let mut unused_identifiers: HashSet = + webrender_font_keys.keys().cloned().collect(); for templates in web_fonts.families.values() { templates.for_all_identifiers(|identifier| { unused_identifiers.remove(identifier); @@ -567,7 +591,31 @@ impl FontContextWebFontMethods for Arc { web_fonts.remove_all_font_data_for_identifiers(&unused_identifiers); self.have_removed_web_fonts.store(false, Ordering::Relaxed); - webrender_font_store.remove_all_fonts_for_identifiers(&unused_identifiers) + + let mut removed_keys: HashSet = HashSet::new(); + webrender_font_keys.retain(|identifier, font_key| { + if unused_identifiers.contains(identifier) { + removed_keys.insert(*font_key); + false + } else { + true + } + }); + + let mut removed_instance_keys: HashSet = HashSet::new(); + webrender_font_instance_keys.retain(|(font_key, _), instance_key| { + if removed_keys.contains(font_key) { + removed_instance_keys.insert(*instance_key); + false + } else { + true + } + }); + + ( + removed_keys.into_iter().collect(), + removed_instance_keys.into_iter().collect(), + ) } } diff --git a/components/fonts/font_store.rs b/components/fonts/font_store.rs index aad3c3e89a8..d0a79456ef6 100644 --- a/components/fonts/font_store.rs +++ b/components/fonts/font_store.rs @@ -5,7 +5,6 @@ use std::collections::{HashMap, HashSet}; use std::sync::{Arc, OnceLock}; -use app_units::Au; use atomic_refcell::AtomicRefCell; use ipc_channel::ipc::IpcSharedMemory; use log::warn; @@ -13,13 +12,11 @@ use parking_lot::RwLock; use serde::{Deserialize, Serialize}; use style::stylesheets::DocumentStyleSheet; use style::values::computed::{FontStyle, FontWeight}; -use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey}; use crate::font::FontDescriptor; use crate::font_context::WebFontDownloadState; use crate::font_template::{FontTemplate, FontTemplateRef, FontTemplateRefMethods, IsOblique}; use crate::system_font_service::{FontIdentifier, LowercaseFontFamilyName}; -use crate::FontContext; /// A data structure to store data for fonts. If sent across IPC channels and only a /// [`IpcSharedMemory`] handle is sent, avoiding the overhead of serialization and @@ -186,84 +183,6 @@ impl FontStore { } } -#[derive(Default)] -pub struct WebRenderFontStore { - pub(crate) webrender_font_key_map: HashMap, - pub(crate) webrender_font_instance_map: HashMap<(FontKey, Au), FontInstanceKey>, -} -pub(crate) type CrossThreadWebRenderFontStore = Arc>; - -impl WebRenderFontStore { - pub(crate) fn get_font_instance( - &mut self, - font_context: &FontContext, - font_template: FontTemplateRef, - pt_size: Au, - flags: FontInstanceFlags, - ) -> FontInstanceKey { - let webrender_font_key_map = &mut self.webrender_font_key_map; - let identifier = font_template.identifier().clone(); - - let font_key = *webrender_font_key_map - .entry(identifier.clone()) - .or_insert_with(|| { - let data = font_context.get_font_data(&identifier); - font_context.get_web_font(data, identifier.index()) - }); - - *self - .webrender_font_instance_map - .entry((font_key, pt_size)) - .or_insert_with(|| { - font_context.get_web_font_instance(font_key, pt_size.to_f32_px(), flags) - }) - } - - pub(crate) fn remove_all_fonts(&mut self) -> (Vec, Vec) { - ( - self.webrender_font_key_map - .drain() - .map(|(_, key)| key) - .collect(), - self.webrender_font_instance_map - .drain() - .map(|(_, key)| key) - .collect(), - ) - } - - pub(crate) fn remove_all_fonts_for_identifiers( - &mut self, - identifiers: &HashSet, - ) -> (Vec, Vec) { - let mut removed_keys: HashSet = HashSet::new(); - self.webrender_font_key_map.retain(|identifier, font_key| { - if identifiers.contains(identifier) { - removed_keys.insert(*font_key); - false - } else { - true - } - }); - - let mut removed_instance_keys: HashSet = HashSet::new(); - self.webrender_font_instance_map - .retain(|(font_key, _), instance_key| { - if removed_keys.contains(font_key) { - removed_instance_keys.insert(*instance_key); - false - } else { - true - } - }); - - ( - removed_keys.into_iter().collect(), - removed_instance_keys.into_iter().collect(), - ) - } -} - /// A struct that represents the available templates in a "simple family." A simple family /// is one that contains <= 4 available faces: regular, bold, italic, and bold italic. Having /// this simple family abstraction makes font matching much faster for families that don't diff --git a/components/fonts/system_font_service.rs b/components/fonts/system_font_service.rs index e1070b49021..36130c5ed8b 100644 --- a/components/fonts/system_font_service.rs +++ b/components/fonts/system_font_service.rs @@ -74,6 +74,8 @@ pub enum SystemFontServiceMessage { FontInstanceFlags, IpcSender, ), + GetFontKey(IpcSender), + GetFontInstanceKey(IpcSender), Exit(IpcSender<()>), Ping, } @@ -99,6 +101,18 @@ pub struct SystemFontService { webrender_fonts: HashMap, font_instances: HashMap<(FontKey, Au), FontInstanceKey>, generic_fonts: ResolvedGenericFontFamilies, + + /// This is an optimization that allows the [`SystemFontService`] to send font data to + /// the compositor asynchronously for creating WebRender fonts, while immediately + /// returning a font key for that data. Once the free keys are exhausted, the + /// [`SystemFontService`] will fetch a new batch. + free_font_keys: Vec, + + /// This is an optimization that allows the [`SystemFontService`] to create WebRender font + /// instances in the compositor asynchronously, while immediately returning a font + /// instance key for the instance. Once the free keys are exhausted, the + /// [`SystemFontService`] will fetch a new batch. + free_font_instance_keys: Vec, } #[derive(Clone, Deserialize, Serialize)] @@ -129,6 +143,8 @@ impl SystemFontService { webrender_fonts: HashMap::new(), font_instances: HashMap::new(), generic_fonts: Default::default(), + free_font_keys: Default::default(), + free_font_instance_keys: Default::default(), }; cache.refresh_local_families(); @@ -158,6 +174,14 @@ impl SystemFontService { SystemFontServiceMessage::GetFontInstance(identifier, pt_size, flags, result) => { let _ = result.send(self.get_font_instance(identifier, pt_size, flags)); }, + SystemFontServiceMessage::GetFontKey(result_sender) => { + self.fetch_new_keys(); + let _ = result_sender.send(self.free_font_keys.pop().unwrap()); + }, + SystemFontServiceMessage::GetFontInstanceKey(result_sender) => { + self.fetch_new_keys(); + let _ = result_sender.send(self.free_font_instance_keys.pop().unwrap()); + }, SystemFontServiceMessage::Ping => (), SystemFontServiceMessage::Exit(result) => { let _ = result.send(()); @@ -167,6 +191,22 @@ impl SystemFontService { } } + fn fetch_new_keys(&mut self) { + if !self.free_font_keys.is_empty() && !self.free_font_instance_keys.is_empty() { + return; + } + + const FREE_FONT_KEYS_BATCH_SIZE: usize = 20; + const FREE_FONT_INSTANCE_KEYS_BATCH_SIZE: usize = 20; + let (mut new_font_keys, mut new_font_instance_keys) = self.webrender_api.fetch_font_keys( + FREE_FONT_KEYS_BATCH_SIZE - self.free_font_keys.len(), + FREE_FONT_INSTANCE_KEYS_BATCH_SIZE - self.free_font_instance_keys.len(), + ); + self.free_font_keys.append(&mut new_font_keys); + self.free_font_instance_keys + .append(&mut new_font_instance_keys); + } + fn get_font_templates( &mut self, font_descriptor: Option, @@ -239,6 +279,8 @@ impl SystemFontService { pt_size: Au, flags: FontInstanceFlags, ) -> FontInstanceKey { + self.fetch_new_keys(); + let webrender_font_api = &self.webrender_api; let webrender_fonts = &mut self.webrender_fonts; let font_data = self.local_families.get_or_initialize_font_data(&identifier); @@ -246,6 +288,7 @@ impl SystemFontService { let font_key = *webrender_fonts .entry(identifier.clone()) .or_insert_with(|| { + let font_key = self.free_font_keys.pop().unwrap(); // CoreText cannot reliably create CoreTextFonts for system fonts stored // as part of TTC files, so on CoreText platforms, create a system font in // WebRender using the LocalFontIdentifier. This has the downside of @@ -253,18 +296,31 @@ impl SystemFontService { // this for those platforms. #[cfg(target_os = "macos")] if let FontIdentifier::Local(local_font_identifier) = identifier { - return webrender_font_api - .add_system_font(local_font_identifier.native_font_handle()); + webrender_font_api + .add_system_font(font_key, local_font_identifier.native_font_handle()); + return font_key; } - webrender_font_api.add_font(font_data.as_ipc_shared_memory(), identifier.index()) + webrender_font_api.add_font( + font_key, + font_data.as_ipc_shared_memory(), + identifier.index(), + ); + font_key }); *self .font_instances .entry((font_key, pt_size)) .or_insert_with(|| { - webrender_font_api.add_font_instance(font_key, pt_size.to_f32_px(), flags) + let font_instance_key = self.free_font_instance_keys.pop().unwrap(); + webrender_font_api.add_font_instance( + font_instance_key, + font_key, + pt_size.to_f32_px(), + flags, + ); + font_instance_key }) } @@ -514,6 +570,30 @@ impl SystemFontServiceProxy { pub(crate) fn get_font_data(&self, identifier: &FontIdentifier) -> Option> { self.data_cache.read().get(identifier).cloned() } + + pub(crate) fn generate_font_key(&self) -> FontKey { + let (result_sender, result_receiver) = + ipc::channel().expect("failed to create IPC channel"); + self.sender + .lock() + .send(SystemFontServiceMessage::GetFontKey(result_sender)) + .expect("failed to send message to system font service"); + result_receiver + .recv() + .expect("Failed to communicate with system font service.") + } + + pub(crate) fn generate_font_instance_key(&self) -> FontInstanceKey { + let (result_sender, result_receiver) = + ipc::channel().expect("failed to create IPC channel"); + self.sender + .lock() + .send(SystemFontServiceMessage::GetFontInstanceKey(result_sender)) + .expect("failed to send message to system font service"); + result_receiver + .recv() + .expect("Failed to communicate with system font service.") + } } #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)] diff --git a/components/fonts/tests/font_context.rs b/components/fonts/tests/font_context.rs index de706451569..036bcde7aec 100644 --- a/components/fonts/tests/font_context.rs +++ b/components/fonts/tests/font_context.rs @@ -32,7 +32,7 @@ use style::values::computed::font::{ use style::values::computed::{FontLanguageOverride, XLang}; use style::values::generics::font::LineHeight; use style::ArcSlice; -use webrender_api::{FontInstanceKey, IdNamespace}; +use webrender_api::{FontInstanceKey, FontKey, IdNamespace}; use webrender_traits::WebRenderScriptApi; struct TestContext { @@ -125,9 +125,13 @@ impl MockSystemFontService { template_data, }); }, + SystemFontServiceMessage::GetFontInstanceKey(result_sender) | SystemFontServiceMessage::GetFontInstance(_, _, _, result_sender) => { let _ = result_sender.send(FontInstanceKey(IdNamespace(0), 0)); }, + SystemFontServiceMessage::GetFontKey(result_sender) => { + let _ = result_sender.send(FontKey(IdNamespace(0), 0)); + }, SystemFontServiceMessage::Exit(result_sender) => { let _ = result_sender.send(()); break; diff --git a/components/layout/text.rs b/components/layout/text.rs index fa75753a47d..01c8fee6325 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -378,8 +378,10 @@ impl TextRunScanner { }, }; + let font_instance_key = font.key(font_context); let (run, break_at_zero) = TextRun::new( font, + font_instance_key, run_info.text, &options, run_info.bidi_level, diff --git a/components/layout/text_run.rs b/components/layout/text_run.rs index 0810512ab9b..9bddc5078b8 100644 --- a/components/layout/text_run.rs +++ b/components/layout/text_run.rs @@ -160,6 +160,7 @@ impl<'a> TextRun { /// Constructs a new text run. Also returns if there is a line break at the beginning pub fn new( font: FontRef, + font_key: FontInstanceKey, text: String, options: &ShapingOptions, bidi_level: bidi::Level, @@ -171,7 +172,7 @@ impl<'a> TextRun { TextRun { text: Arc::new(text), font_metrics: font.metrics.clone(), - font_key: font.font_key, + font_key, pt_size: font.descriptor.pt_size, glyphs: Arc::new(glyphs), bidi_level, diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index 56d17bd54b9..8a2c47ef282 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -1528,8 +1528,11 @@ impl InlineFormattingContext { &inline_box.style, &layout_context.font_context, ) { - inline_box.default_font_index = - Some(add_or_get_font(&font, &mut font_metrics)); + inline_box.default_font_index = Some(add_or_get_font( + &font, + &mut font_metrics, + &layout_context.font_context, + )); } }, InlineItem::Atomic(_, index_in_text, bidi_level) => { diff --git a/components/layout_2020/flow/inline/text_run.rs b/components/layout_2020/flow/inline/text_run.rs index d5438a103e1..76ec3032d0e 100644 --- a/components/layout_2020/flow/inline/text_run.rs +++ b/components/layout_2020/flow/inline/text_run.rs @@ -109,6 +109,7 @@ impl TextRunSegment { script: Script, bidi_level: Level, fonts: &[FontKeyAndMetrics], + font_context: &FontContext, ) -> bool { fn is_specific(script: Script) -> bool { script != Script::Common && script != Script::Inherited @@ -119,7 +120,7 @@ impl TextRunSegment { } let current_font_key_and_metrics = &fonts[self.font_index]; - if new_font.font_key != current_font_key_and_metrics.key || + if new_font.key(font_context) != current_font_key_and_metrics.key || new_font.descriptor.pt_size != current_font_key_and_metrics.pt_size { return false; @@ -440,15 +441,18 @@ impl TextRun { let script = Script::from(character); let bidi_level = bidi_info.levels[current_byte_index]; if let Some(current) = current.as_mut() { - if current - .0 - .update_if_compatible(&font, script, bidi_level, font_cache) - { + if current.0.update_if_compatible( + &font, + script, + bidi_level, + font_cache, + font_context, + ) { continue; } } - let font_index = add_or_get_font(&font, font_cache); + let font_index = add_or_get_font(&font, font_cache, font_context); // Add the new segment and finish the existing one, if we had one. If the first // characters in the run were control characters we may be creating the first @@ -473,7 +477,7 @@ impl TextRun { // of those cases, just use the first font. if current.is_none() { current = font_group.write().first(font_context).map(|font| { - let font_index = add_or_get_font(&font, font_cache); + let font_index = add_or_get_font(&font, font_cache, font_context); ( TextRunSegment::new( font_index, @@ -539,15 +543,22 @@ fn char_does_not_change_font(character: char) -> bool { class == XI_LINE_BREAKING_CLASS_ZWJ } -pub(super) fn add_or_get_font(font: &FontRef, ifc_fonts: &mut Vec) -> usize { +pub(super) fn add_or_get_font( + font: &FontRef, + ifc_fonts: &mut Vec, + font_context: &FontContext, +) -> usize { + let font_instance_key = font.key(font_context); for (index, ifc_font_info) in ifc_fonts.iter().enumerate() { - if ifc_font_info.key == font.font_key && ifc_font_info.pt_size == font.descriptor.pt_size { + if ifc_font_info.key == font_instance_key && + ifc_font_info.pt_size == font.descriptor.pt_size + { return index; } } ifc_fonts.push(FontKeyAndMetrics { metrics: font.metrics.clone(), - key: font.font_key, + key: font_instance_key, pt_size: font.descriptor.pt_size, }); ifc_fonts.len() - 1 diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 7c44981600d..ff5a1e54efd 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -1096,34 +1096,48 @@ struct WebRenderFontApiCompositorProxy(CompositorProxy); impl WebRenderFontApi for WebRenderFontApiCompositorProxy { fn add_font_instance( &self, + font_instance_key: FontInstanceKey, font_key: FontKey, size: f32, flags: FontInstanceFlags, - ) -> FontInstanceKey { - let (sender, receiver) = unbounded(); + ) { self.0.send(CompositorMsg::Forwarded( ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFontInstance( - font_key, size, flags, sender, + font_instance_key, + font_key, + size, + flags, )), )); - receiver.recv().unwrap() } - fn add_font(&self, data: Arc, index: u32) -> FontKey { - let (sender, receiver) = unbounded(); + fn add_font(&self, font_key: FontKey, data: Arc, index: u32) { self.0.send(CompositorMsg::Forwarded( ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddFont( - sender, index, data, + font_key, index, data, )), )); - receiver.recv().unwrap() } - fn add_system_font(&self, handle: NativeFontHandle) -> FontKey { - let (sender, receiver) = unbounded(); + fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) { self.0.send(CompositorMsg::Forwarded( ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::AddSystemFont( - sender, handle, + font_key, handle, + )), + )); + } + + fn fetch_font_keys( + &self, + number_of_font_keys: usize, + number_of_font_instance_keys: usize, + ) -> (Vec, Vec) { + let (sender, receiver) = unbounded(); + self.0.send(CompositorMsg::Forwarded( + ForwardedToCompositorMsg::SystemFontService(FontToCompositorMsg::GenerateKeys( + number_of_font_keys, + number_of_font_instance_keys, + sender, )), )); receiver.recv().unwrap() diff --git a/components/shared/webrender/lib.rs b/components/shared/webrender/lib.rs index accb73df316..58580175e7d 100644 --- a/components/shared/webrender/lib.rs +++ b/components/shared/webrender/lib.rs @@ -186,12 +186,18 @@ impl ExternalImageHandler for WebrenderExternalImageHandlers { pub trait WebRenderFontApi { fn add_font_instance( &self, + font_instance_key: FontInstanceKey, font_key: FontKey, size: f32, flags: FontInstanceFlags, - ) -> FontInstanceKey; - fn add_font(&self, data: Arc, index: u32) -> FontKey; - fn add_system_font(&self, handle: NativeFontHandle) -> FontKey; + ); + fn add_font(&self, font_key: FontKey, data: Arc, index: u32); + fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle); + fn fetch_font_keys( + &self, + number_of_font_keys: usize, + number_of_font_instance_keys: usize, + ) -> (Vec, Vec); } pub enum CanvasToCompositorMsg { @@ -200,9 +206,10 @@ pub enum CanvasToCompositorMsg { } pub enum FontToCompositorMsg { - AddFontInstance(FontKey, f32, FontInstanceFlags, Sender), - AddFont(Sender, u32, Arc), - AddSystemFont(Sender, NativeFontHandle), + GenerateKeys(usize, usize, Sender<(Vec, Vec)>), + AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), + AddFont(FontKey, u32, Arc), + AddSystemFont(FontKey, NativeFontHandle), } #[derive(Deserialize, Serialize)] @@ -242,8 +249,8 @@ pub enum ScriptToCompositorMsg { UpdateImages(Vec), /// Remove the given font resources from our WebRender instance. RemoveFonts(Vec, Vec), - AddFontInstance(FontKey, f32, FontInstanceFlags, IpcSender), - AddFont(Arc, u32, IpcSender), + AddFontInstance(FontInstanceKey, FontKey, f32, FontInstanceFlags), + AddFont(FontKey, Arc, u32), } /// A mechanism to send messages from networking to the WebRender instance.