Don't load all font faces sources

We stop at the first one we manage to load.
This commit is contained in:
Anthony Ramine 2016-06-10 12:41:24 +02:00
parent 04b682195d
commit b97c7a8c4d
4 changed files with 131 additions and 117 deletions

View file

@ -21,7 +21,7 @@ use std::ops::Deref;
use std::sync::{Arc, Mutex};
use std::u32;
use string_cache::Atom;
use style::font_face::Source;
use style::font_face::{EffectiveSources, Source};
use style::properties::longhands::font_family::computed_value::FontFamily;
use url::Url;
use util::prefs;
@ -105,8 +105,8 @@ impl FontTemplates {
pub enum Command {
GetFontTemplate(FontFamily, FontTemplateDescriptor, IpcSender<Reply>),
GetLastResortFontTemplate(FontTemplateDescriptor, IpcSender<Reply>),
AddWebFont(FontFamily, Source, IpcSender<()>),
AddDownloadedWebFont(FontFamily, Url, Vec<u8>, IpcSender<()>),
AddWebFont(LowercaseString, EffectiveSources, IpcSender<()>),
AddDownloadedWebFont(LowercaseString, Url, Vec<u8>, IpcSender<()>),
Exit(IpcSender<()>),
}
@ -171,87 +171,10 @@ impl FontCache {
let font_template = self.last_resort_font_template(&descriptor);
result.send(Reply::GetFontTemplateReply(Some(font_template))).unwrap();
}
Command::AddWebFont(family, src, result) => {
let family_name = LowercaseString::new(family.name());
if !self.web_families.contains_key(&family_name) {
let templates = FontTemplates::new();
self.web_families.insert(family_name.clone(), templates);
}
match src {
Source::Url(ref url_source) => {
let url = &url_source.url;
let load = PendingAsyncLoad::new(LoadContext::Font,
self.core_resource_thread.clone(),
url.clone(),
None,
None,
None,
RequestSource::None);
let (data_sender, data_receiver) = ipc::channel().unwrap();
let data_target = AsyncResponseTarget {
sender: data_sender,
};
load.load_async(data_target);
let channel_to_self = self.channel_to_self.clone();
let url = (*url).clone();
let bytes = Mutex::new(Vec::new());
let response_valid = Mutex::new(false);
ROUTER.add_route(data_receiver.to_opaque(), box move |message| {
let response: ResponseAction = message.to().unwrap();
match response {
ResponseAction::HeadersAvailable(meta_result) => {
let is_response_valid = match meta_result {
Ok(ref metadata) => {
metadata.content_type.as_ref().map_or(false, |content_type| {
let mime = &content_type.0;
is_supported_font_type(&mime.0, &mime.1)
})
}
Err(_) => false,
};
info!("{} font with MIME type {}",
if is_response_valid { "Loading" } else { "Ignoring" },
meta_result.map(|ref meta| format!("{:?}", meta.content_type))
.unwrap_or(format!("<Network Error>")));
*response_valid.lock().unwrap() = is_response_valid;
}
ResponseAction::DataAvailable(new_bytes) => {
if *response_valid.lock().unwrap() {
bytes.lock().unwrap().extend(new_bytes.into_iter())
}
}
ResponseAction::ResponseComplete(response) => {
if response.is_err() || !*response_valid.lock().unwrap() {
drop(result.send(()));
return;
}
let mut bytes = bytes.lock().unwrap();
let bytes = mem::replace(&mut *bytes, Vec::new());
let command =
Command::AddDownloadedWebFont(family.clone(),
url.clone(),
bytes,
result.clone());
channel_to_self.send(command).unwrap();
}
}
});
}
Source::Local(ref font) => {
let font_face_name = LowercaseString::new(font.name());
let templates = &mut self.web_families.get_mut(&family_name).unwrap();
for_each_variation(&font_face_name, |path| {
templates.add_template(Atom::from(&*path), None);
});
result.send(()).unwrap();
}
}
Command::AddWebFont(family_name, sources, result) => {
self.handle_add_web_font(family_name, sources, result);
}
Command::AddDownloadedWebFont(family, url, bytes, result) => {
let family_name = LowercaseString::new(family.name());
Command::AddDownloadedWebFont(family_name, url, bytes, result) => {
let templates = &mut self.web_families.get_mut(&family_name).unwrap();
templates.add_template(Atom::from(url.to_string()), Some(bytes));
drop(result.send(()));
@ -264,6 +187,95 @@ impl FontCache {
}
}
fn handle_add_web_font(&mut self,
family_name: LowercaseString,
mut sources: EffectiveSources,
sender: IpcSender<()>) {
let src = if let Some(src) = sources.next() {
src
} else {
sender.send(()).unwrap();
return;
};
if !self.web_families.contains_key(&family_name) {
let templates = FontTemplates::new();
self.web_families.insert(family_name.clone(), templates);
}
match src {
Source::Url(ref url_source) => {
let url = &url_source.url;
let load = PendingAsyncLoad::new(LoadContext::Font,
self.core_resource_thread.clone(),
url.clone(),
None,
None,
None,
RequestSource::None);
let (data_sender, data_receiver) = ipc::channel().unwrap();
let data_target = AsyncResponseTarget {
sender: data_sender,
};
load.load_async(data_target);
let channel_to_self = self.channel_to_self.clone();
let url = (*url).clone();
let bytes = Mutex::new(Vec::new());
let response_valid = Mutex::new(false);
ROUTER.add_route(data_receiver.to_opaque(), box move |message| {
let response: ResponseAction = message.to().unwrap();
match response {
ResponseAction::HeadersAvailable(meta_result) => {
let is_response_valid = match meta_result {
Ok(ref metadata) => {
metadata.content_type.as_ref().map_or(false, |content_type| {
let mime = &content_type.0;
is_supported_font_type(&mime.0, &mime.1)
})
}
Err(_) => false,
};
info!("{} font with MIME type {}",
if is_response_valid { "Loading" } else { "Ignoring" },
meta_result.map(|ref meta| format!("{:?}", meta.content_type))
.unwrap_or(format!("<Network Error>")));
*response_valid.lock().unwrap() = is_response_valid;
}
ResponseAction::DataAvailable(new_bytes) => {
if *response_valid.lock().unwrap() {
bytes.lock().unwrap().extend(new_bytes.into_iter())
}
}
ResponseAction::ResponseComplete(response) => {
if response.is_err() || !*response_valid.lock().unwrap() {
let msg = Command::AddWebFont(family_name.clone(), sources.clone(), sender.clone());
channel_to_self.send(msg).unwrap();
return;
}
let mut bytes = bytes.lock().unwrap();
let bytes = mem::replace(&mut *bytes, Vec::new());
let command =
Command::AddDownloadedWebFont(family_name.clone(),
url.clone(),
bytes,
sender.clone());
channel_to_self.send(command).unwrap();
}
}
});
}
Source::Local(ref font) => {
let font_face_name = LowercaseString::new(font.name());
let templates = &mut self.web_families.get_mut(&family_name).unwrap();
for_each_variation(&font_face_name, |path| {
templates.add_template(Atom::from(&*path), None);
});
sender.send(()).unwrap();
}
}
}
fn refresh_local_families(&mut self) {
self.local_families.clear();
for_each_available_family(|family_name| {
@ -431,8 +443,8 @@ impl FontCacheThread {
}
}
pub fn add_web_font(&self, family: FontFamily, src: Source, sender: IpcSender<()>) {
self.chan.send(Command::AddWebFont(family, src, sender)).unwrap();
pub fn add_web_font(&self, family: FontFamily, sources: EffectiveSources, sender: IpcSender<()>) {
self.chan.send(Command::AddWebFont(LowercaseString::new(family.name()), sources, sender)).unwrap();
}
pub fn exit(&self) {

View file

@ -358,21 +358,19 @@ fn add_font_face_rules(stylesheet: &Stylesheet,
if opts::get().load_webfonts_synchronously {
let (sender, receiver) = ipc::channel().unwrap();
for font_face in stylesheet.effective_rules(&device).font_face() {
for source in font_face.effective_sources() {
font_cache_thread.add_web_font(font_face.family.clone(),
(*source).clone(),
sender.clone());
receiver.recv().unwrap();
}
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 {
for font_face in stylesheet.effective_rules(&device).font_face() {
for source in font_face.effective_sources() {
outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst);
font_cache_thread.add_web_font(font_face.family.clone(),
(*source).clone(),
(*font_cache_sender).clone());
}
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());
}
}
}

View file

@ -7,7 +7,6 @@ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error};
use properties::longhands::font_family::parse_one_family;
use std::iter;
use std::slice;
use url::Url;
#[derive(Clone, Debug, HeapSizeOf, PartialEq, Eq, Deserialize, Serialize)]
@ -60,21 +59,15 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
}
}
pub struct EffectiveSourcesIter<'a>(slice::Iter<'a, Source>);
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EffectiveSources(Vec<Source>);
impl FontFaceRule {
/// Returns the list of effective sources for that font-face, that is the
/// sources which don't list any format hint, or the ones which list at
/// least "truetype" or "opentype".
pub fn effective_sources(&self) -> EffectiveSourcesIter {
EffectiveSourcesIter(self.sources.iter())
}
}
impl<'a> iter::Iterator for EffectiveSourcesIter<'a> {
type Item = &'a Source;
fn next(&mut self) -> Option<&'a Source> {
self.0.find(|source| {
pub fn effective_sources(&self) -> EffectiveSources {
EffectiveSources(self.sources.iter().rev().filter(|source| {
if let Source::Url(ref url_source) = **source {
let hints = &url_source.format_hints;
// We support only opentype fonts and truetype is an alias for
@ -86,7 +79,14 @@ impl<'a> iter::Iterator for EffectiveSourcesIter<'a> {
} else {
true
}
})
}).cloned().collect())
}
}
impl iter::Iterator for EffectiveSources {
type Item = Source;
fn next(&mut self) -> Option<Source> {
self.0.pop()
}
}

View file

@ -5,17 +5,21 @@
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc;
use style::computed_values::font_family::FontFamily;
use style::font_face::Source;
use style::font_face::{FontFaceRule, Source};
#[test]
fn test_local_web_font() {
let (inp_chan, _) = ipc::channel().unwrap();
let (out_chan, out_receiver) = ipc::channel().unwrap();
let font_cache_thread = FontCacheThread::new(inp_chan, None);
let family_name = FontFamily::FamilyName(From::from("test family"));
let variant_name = FontFamily::FamilyName(From::from("test font face"));
let (inp_chan, _) = ipc::channel().unwrap();
let (out_chan, out_receiver) = ipc::channel().unwrap();
let font_cache_thread = FontCacheThread::new(inp_chan, None);
let family_name = FontFamily::FamilyName(From::from("test family"));
let variant_name = FontFamily::FamilyName(From::from("test font face"));
let font_face_rule = FontFaceRule {
family: family_name.clone(),
sources: vec![Source::Local(variant_name)],
};
font_cache_thread.add_web_font(family_name, Source::Local(variant_name), out_chan);
font_cache_thread.add_web_font(family_name, font_face_rule.effective_sources(), out_chan);
assert_eq!(out_receiver.recv().unwrap(), ());
assert_eq!(out_receiver.recv().unwrap(), ());
}