diff options
Diffstat (limited to 'components/gfx/font_cache_thread.rs')
-rw-r--r-- | components/gfx/font_cache_thread.rs | 145 |
1 files changed, 75 insertions, 70 deletions
diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index a5c6a2b0974..797a12317d6 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -3,8 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::borrow::ToOwned; +use std::cell::RefCell; use std::collections::HashMap; use std::ops::Deref; +use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::{f32, fmt, mem, thread}; @@ -25,22 +27,23 @@ use webrender_api::{FontInstanceKey, FontKey}; use crate::font::{FontFamilyDescriptor, FontFamilyName, FontSearchScope}; use crate::font_context::FontSource; -use crate::font_template::{FontTemplate, FontTemplateDescriptor}; +use crate::font_template::{ + FontTemplate, FontTemplateDescriptor, FontTemplateRef, FontTemplateRefMethods, +}; use crate::platform::font_list::{ for_each_available_family, for_each_variation, system_default_family, LocalFontIdentifier, SANS_SERIF_FONT_FAMILY, }; -use crate::platform::font_template::FontTemplateData; /// A list of font templates that make up a given font family. #[derive(Default)] pub struct FontTemplates { - templates: Vec<FontTemplate>, + templates: Vec<FontTemplateRef>, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug)] pub struct FontTemplateInfo { - pub font_template: Arc<FontTemplateData>, + pub font_template: FontTemplateRef, pub font_key: FontKey, } @@ -59,13 +62,19 @@ pub enum FontIdentifier { #[derive(Debug, Deserialize, Serialize)] pub struct SerializedFontTemplate { identifier: FontIdentifier, + descriptor: Option<FontTemplateDescriptor>, bytes_receiver: ipc_channel::ipc::IpcBytesReceiver, } impl SerializedFontTemplate { - pub fn to_font_template_data(&self) -> FontTemplateData { + pub fn to_font_template(&self) -> FontTemplate { let font_data = self.bytes_receiver.recv().ok(); - FontTemplateData::new(self.identifier.clone(), font_data).unwrap() + FontTemplate { + identifier: self.identifier.clone(), + descriptor: self.descriptor.clone(), + data: font_data.map(Arc::new), + is_valid: true, + } } } @@ -74,40 +83,37 @@ impl FontTemplates { pub fn find_font_for_style( &mut self, desc: &FontTemplateDescriptor, - ) -> Option<Arc<FontTemplateData>> { + ) -> Option<FontTemplateRef> { // TODO(Issue #189): optimize lookup for // regular/bold/italic/bolditalic with fixed offsets and a // static decision table for fallback between these values. for template in &mut self.templates { - let maybe_template = template.data_for_descriptor(desc); - if maybe_template.is_some() { - return maybe_template; + if template.descriptor_matches(desc) { + return Some(template.clone()); } } // We didn't find an exact match. Do more expensive fuzzy matching. // TODO(#190): Do a better job. - let (mut best_template_data, mut best_distance) = (None, f32::MAX); - for template in &mut self.templates { - if let Some((template_data, distance)) = template.data_for_approximate_descriptor(desc) - { + let (mut best_template, mut best_distance) = (None, f32::MAX); + for template in self.templates.iter() { + if let Some(distance) = template.descriptor_distance(desc) { if distance < best_distance { - best_template_data = Some(template_data); + best_template = Some(template); best_distance = distance } } } - if best_template_data.is_some() { - return best_template_data; + if best_template.is_some() { + return best_template.cloned(); } // If a request is made for a font family that exists, // pick the first valid font in the family if we failed // to find an exact match for the descriptor. - for template in &mut self.templates { - let maybe_template = template.get(); - if maybe_template.is_some() { - return maybe_template; + for template in &mut self.templates.iter() { + if template.is_valid() { + return Some(template.clone()); } } @@ -116,13 +122,13 @@ impl FontTemplates { pub fn add_template(&mut self, identifier: FontIdentifier, maybe_data: Option<Vec<u8>>) { for template in &self.templates { - if *template.identifier() == identifier { + if *template.borrow().identifier() == identifier { return; } } if let Ok(template) = FontTemplate::new(identifier, maybe_data) { - self.templates.push(template); + self.templates.push(Rc::new(RefCell::new(template))); } } } @@ -196,29 +202,30 @@ impl FontCache { match msg { Command::GetFontTemplate(template_descriptor, family_descriptor, result) => { - let maybe_font_template = - self.find_font_template(&template_descriptor, &family_descriptor); - match maybe_font_template { - None => { - let _ = result.send(Reply::GetFontTemplateReply(None)); - }, - Some(font_template_info) => { - let (bytes_sender, bytes_receiver) = - ipc::bytes_channel().expect("failed to create IPC channel"); - let serialized_font_template = SerializedFontTemplate { - identifier: font_template_info.font_template.identifier.clone(), - bytes_receiver, - }; + let Some(font_template_info) = + self.find_font_template(&template_descriptor, &family_descriptor) + else { + let _ = result.send(Reply::GetFontTemplateReply(None)); + continue; + }; - let _ = result.send(Reply::GetFontTemplateReply(Some( - SerializedFontTemplateInfo { - serialized_font_template, - font_key: font_template_info.font_key, - }, - ))); - let _ = bytes_sender.send(&font_template_info.font_template.bytes()); - }, + let (bytes_sender, bytes_receiver) = + ipc::bytes_channel().expect("failed to create IPC channel"); + let serialized_font_template = SerializedFontTemplate { + identifier: font_template_info.font_template.borrow().identifier.clone(), + descriptor: font_template_info.font_template.borrow().descriptor.clone(), + bytes_receiver, }; + + let _ = result.send(Reply::GetFontTemplateReply(Some( + SerializedFontTemplateInfo { + serialized_font_template, + font_key: font_template_info.font_key, + }, + ))); + + // NB: This will load the font into memory if it hasn't been loaded already. + let _ = bytes_sender.send(&font_template_info.font_template.data()); }, Command::GetFontInstance(font_key, size, result) => { let webrender_api = &self.webrender_api; @@ -382,7 +389,7 @@ impl FontCache { &mut self, template_descriptor: &FontTemplateDescriptor, family_name: &FontFamilyName, - ) -> Option<Arc<FontTemplateData>> { + ) -> Option<FontTemplateRef> { let family_name = self.transform_family(family_name); // TODO(Issue #188): look up localized font family names if canonical name not found @@ -414,7 +421,7 @@ impl FontCache { &mut self, template_descriptor: &FontTemplateDescriptor, family_name: &FontFamilyName, - ) -> Option<Arc<FontTemplateData>> { + ) -> Option<FontTemplateRef> { let family_name = LowercaseString::from(family_name); if self.web_families.contains_key(&family_name) { @@ -425,25 +432,20 @@ impl FontCache { } } - fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo { + fn get_font_key_for_template(&mut self, template: &FontTemplateRef) -> FontKey { let webrender_api = &self.webrender_api; let webrender_fonts = &mut self.webrender_fonts; - - let font_key = *webrender_fonts - .entry(template.identifier.clone()) + *webrender_fonts + .entry(template.borrow().identifier.clone()) .or_insert_with(|| { - let font = match (template.bytes_if_in_memory(), template.native_font()) { + let template = template.borrow(); + let font = match (template.data_if_in_memory(), template.native_font_handle()) { (Some(bytes), _) => FontData::Raw((*bytes).clone()), (None, Some(native_font)) => FontData::Native(native_font), - (None, None) => FontData::Raw((*template.bytes()).clone()), + (None, None) => unreachable!("Font should either be local or a web font."), }; webrender_api.add_font(font) - }); - - FontTemplateInfo { - font_template: template, - font_key, - } + }) } fn find_font_template( @@ -462,7 +464,10 @@ impl FontCache { self.find_font_in_local_family(template_descriptor, &family_descriptor.name) }, } - .map(|t| self.get_font_template_info(t)) + .map(|font_template| FontTemplateInfo { + font_key: self.get_font_key_for_template(&font_template), + font_template, + }) } } @@ -618,17 +623,17 @@ impl FontSource for FontCacheThread { match reply.unwrap() { Reply::GetFontTemplateReply(maybe_serialized_font_template_info) => { - match maybe_serialized_font_template_info { - None => None, - Some(serialized_font_template_info) => Some(FontTemplateInfo { - font_template: Arc::new( - serialized_font_template_info - .serialized_font_template - .to_font_template_data(), - ), + maybe_serialized_font_template_info.map(|serialized_font_template_info| { + let font_template = Rc::new(RefCell::new( + serialized_font_template_info + .serialized_font_template + .to_font_template(), + )); + FontTemplateInfo { + font_template, font_key: serialized_font_template_info.font_key, - }), - } + } + }) }, } } |