mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
font_cache: Handle filtering @font-face
rules in Servo (#31601)
Instead of letting Stylo filter `@font-face` rules, handle this filtering in Servo. It doesn't make sense that Stylo knows about what fonts Servo supports. This also cleans up a bit the way that this is handled, giving an entire stylesheet of rules to the font cache to process instead of letting each layout thread walk the rules. This brings more of the font-related code into the FontCacheThread itself. This is the first step toward adding WOFF2 support and fixing various web font related bugs.
This commit is contained in:
parent
b03411f567
commit
45344dca2b
15 changed files with 182 additions and 219 deletions
|
@ -17,8 +17,10 @@ use net_traits::{fetch_async, CoreResourceThread, FetchResponseMsg};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
use style::font_face::{EffectiveSources, Source};
|
||||
use style::values::computed::font::FamilyName;
|
||||
use style::font_face::{FontFaceSourceFormat, FontFaceSourceFormatKeyword, Source};
|
||||
use style::media_queries::Device;
|
||||
use style::shared_lock::SharedRwLockReadGuard;
|
||||
use style::stylesheets::{Stylesheet, StylesheetInDocument};
|
||||
use webrender_api::{FontInstanceKey, FontKey};
|
||||
|
||||
use crate::font::{FontFamilyDescriptor, FontFamilyName, FontSearchScope};
|
||||
|
@ -130,7 +132,7 @@ pub enum Command {
|
|||
IpcSender<Reply>,
|
||||
),
|
||||
GetFontInstance(FontKey, Au, IpcSender<FontInstanceKey>),
|
||||
AddWebFont(LowercaseString, EffectiveSources, IpcSender<()>),
|
||||
AddWebFont(LowercaseString, Vec<Source>, IpcSender<()>),
|
||||
AddDownloadedWebFont(LowercaseString, ServoUrl, Vec<u8>, IpcSender<()>),
|
||||
Exit(IpcSender<()>),
|
||||
Ping,
|
||||
|
@ -248,10 +250,10 @@ impl FontCache {
|
|||
fn handle_add_web_font(
|
||||
&mut self,
|
||||
family_name: LowercaseString,
|
||||
mut sources: EffectiveSources,
|
||||
mut sources: Vec<Source>,
|
||||
sender: IpcSender<()>,
|
||||
) {
|
||||
let src = if let Some(src) = sources.next() {
|
||||
let src = if let Some(src) = sources.pop() {
|
||||
src
|
||||
} else {
|
||||
sender.send(()).unwrap();
|
||||
|
@ -503,19 +505,58 @@ impl FontCacheThread {
|
|||
FontCacheThread { chan }
|
||||
}
|
||||
|
||||
pub fn add_web_font(
|
||||
pub fn add_all_web_fonts_from_stylesheet(
|
||||
&self,
|
||||
family: FamilyName,
|
||||
sources: EffectiveSources,
|
||||
sender: IpcSender<()>,
|
||||
) {
|
||||
self.chan
|
||||
.send(Command::AddWebFont(
|
||||
LowercaseString::new(&family.name),
|
||||
sources,
|
||||
sender,
|
||||
))
|
||||
.unwrap();
|
||||
stylesheet: &Stylesheet,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
device: &Device,
|
||||
font_cache_sender: &IpcSender<()>,
|
||||
synchronous: bool,
|
||||
) -> usize {
|
||||
let (sender, receiver) = if synchronous {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
(Some(sender), Some(receiver))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let mut number_loading = 0;
|
||||
stylesheet.effective_font_face_rules(&device, guard, |rule| {
|
||||
let font_face = match rule.font_face() {
|
||||
Some(font_face) => font_face,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let sources: Vec<Source> = font_face
|
||||
.sources()
|
||||
.0
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(is_supported_web_font_source)
|
||||
.cloned()
|
||||
.collect();
|
||||
if sources.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let sender = sender.as_ref().unwrap_or(font_cache_sender).clone();
|
||||
self.chan
|
||||
.send(Command::AddWebFont(
|
||||
LowercaseString::new(&font_face.family().name),
|
||||
sources,
|
||||
sender,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
// Either increment the count of loading web fonts, or wait for a synchronous load.
|
||||
if let Some(ref receiver) = receiver {
|
||||
receiver.recv().unwrap();
|
||||
} else {
|
||||
number_loading += 1;
|
||||
}
|
||||
});
|
||||
|
||||
number_loading
|
||||
}
|
||||
|
||||
pub fn exit(&self) {
|
||||
|
@ -624,3 +665,31 @@ impl fmt::Display for LowercaseString {
|
|||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_supported_web_font_source(source: &&Source) -> bool {
|
||||
let url_source = match source {
|
||||
Source::Url(ref url_source) => url_source,
|
||||
Source::Local(_) => return true,
|
||||
};
|
||||
let format_hint = match url_source.format_hint {
|
||||
Some(ref format_hint) => format_hint,
|
||||
None => return true,
|
||||
};
|
||||
|
||||
if matches!(
|
||||
format_hint,
|
||||
FontFaceSourceFormat::Keyword(
|
||||
FontFaceSourceFormatKeyword::Truetype |
|
||||
FontFaceSourceFormatKeyword::Opentype |
|
||||
FontFaceSourceFormatKeyword::Woff
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let FontFaceSourceFormat::String(string) = format_hint {
|
||||
return string == "truetype" || string == "opentype" || string == "woff";
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use style::values::computed::font::{
|
|||
FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSize, FontStretch, FontStyle,
|
||||
FontWeight, SingleFontFamily,
|
||||
};
|
||||
use style::values::computed::FontLanguageOverride;
|
||||
use webrender_api::{FontInstanceKey, FontKey, IdNamespace};
|
||||
|
||||
struct TestFontSource {
|
||||
|
@ -100,6 +101,7 @@ fn style() -> FontStyleStruct {
|
|||
font_size: FontSize::medium(),
|
||||
font_stretch: FontStretch::hundred(),
|
||||
hash: 0,
|
||||
font_language_override: FontLanguageOverride::normal(),
|
||||
};
|
||||
style.compute_font_hash();
|
||||
style
|
||||
|
|
|
@ -295,43 +295,6 @@ impl<'a, 'b: 'a> RwData<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_font_face_rules(
|
||||
stylesheet: &Stylesheet,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
device: &Device,
|
||||
font_cache_thread: &FontCacheThread,
|
||||
font_cache_sender: &IpcSender<()>,
|
||||
outstanding_web_fonts_counter: &Arc<AtomicUsize>,
|
||||
load_webfonts_synchronously: bool,
|
||||
) {
|
||||
if load_webfonts_synchronously {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
stylesheet.effective_font_face_rules(&device, guard, |rule| {
|
||||
if let Some(font_face) = rule.font_face() {
|
||||
let effective_sources = font_face.effective_sources();
|
||||
font_cache_thread.add_web_font(
|
||||
font_face.family().clone(),
|
||||
effective_sources,
|
||||
sender.clone(),
|
||||
);
|
||||
receiver.recv().unwrap();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
stylesheet.effective_font_face_rules(&device, guard, |rule| {
|
||||
if let Some(font_face) = rule.font_face() {
|
||||
let effective_sources = font_face.effective_sources();
|
||||
outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst);
|
||||
font_cache_thread.add_web_font(
|
||||
font_face.family().clone(),
|
||||
effective_sources,
|
||||
(*font_cache_sender).clone(),
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for LayoutThread {
|
||||
fn process(&mut self, msg: script_layout_interface::message::Msg) {
|
||||
self.handle_request(Request::FromScript(msg));
|
||||
|
@ -644,15 +607,16 @@ 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) {
|
||||
add_font_face_rules(
|
||||
&*stylesheet,
|
||||
&guard,
|
||||
self.stylist.device(),
|
||||
&self.font_cache_thread,
|
||||
&self.font_cache_sender,
|
||||
&self.outstanding_web_fonts,
|
||||
self.debug.load_webfonts_synchronously,
|
||||
);
|
||||
let newly_loading_font_count =
|
||||
self.font_cache_thread.add_all_web_fonts_from_stylesheet(
|
||||
&*stylesheet,
|
||||
&guard,
|
||||
self.stylist.device(),
|
||||
&self.font_cache_sender,
|
||||
self.debug.load_webfonts_synchronously,
|
||||
);
|
||||
self.outstanding_web_fonts
|
||||
.fetch_add(newly_loading_font_count, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -273,42 +273,6 @@ impl<'a, 'b: 'a> RwData<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_font_face_rules(
|
||||
stylesheet: &Stylesheet,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
device: &Device,
|
||||
font_cache_thread: &FontCacheThread,
|
||||
font_cache_sender: &IpcSender<()>,
|
||||
outstanding_web_fonts_counter: &Arc<AtomicUsize>,
|
||||
load_webfonts_synchronously: bool,
|
||||
) {
|
||||
if load_webfonts_synchronously {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
stylesheet.effective_font_face_rules(&device, guard, |rule| {
|
||||
if let Some(font_face) = rule.font_face() {
|
||||
let effective_sources = font_face.effective_sources();
|
||||
font_cache_thread.add_web_font(
|
||||
font_face.family().clone(),
|
||||
effective_sources,
|
||||
sender.clone(),
|
||||
);
|
||||
receiver.recv().unwrap();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
stylesheet.effective_font_face_rules(&device, guard, |rule| {
|
||||
if let Some(font_face) = rule.font_face() {
|
||||
let effective_sources = font_face.effective_sources();
|
||||
outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst);
|
||||
font_cache_thread.add_web_font(
|
||||
font_face.family().clone(),
|
||||
effective_sources,
|
||||
(*font_cache_sender).clone(),
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Layout for LayoutThread {
|
||||
fn process(&mut self, msg: script_layout_interface::message::Msg) {
|
||||
self.handle_request(Request::FromScript(msg));
|
||||
|
@ -578,15 +542,16 @@ 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) {
|
||||
add_font_face_rules(
|
||||
&*stylesheet,
|
||||
&guard,
|
||||
self.stylist.device(),
|
||||
&self.font_cache_thread,
|
||||
&self.font_cache_sender,
|
||||
&self.outstanding_web_fonts,
|
||||
self.debug.load_webfonts_synchronously,
|
||||
);
|
||||
let newly_loading_font_count =
|
||||
self.font_cache_thread.add_all_web_fonts_from_stylesheet(
|
||||
&*stylesheet,
|
||||
&guard,
|
||||
self.stylist.device(),
|
||||
&self.font_cache_sender,
|
||||
self.debug.load_webfonts_synchronously,
|
||||
);
|
||||
self.outstanding_web_fonts
|
||||
.fetch_add(newly_loading_font_count, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue