Add support for local font faces. Improves fonts on rust lang and guide.

This commit is contained in:
Glenn Watson 2014-10-14 15:47:21 +10:00
parent d04733cf59
commit 1827852810
5 changed files with 39 additions and 40 deletions

View file

@ -13,7 +13,7 @@ use sync::Arc;
use font_template::{FontTemplate, FontTemplateDescriptor}; use font_template::{FontTemplate, FontTemplateDescriptor};
use platform::font_template::FontTemplateData; use platform::font_template::FontTemplateData;
use servo_net::resource_task::{ResourceTask, load_whole_resource}; use servo_net::resource_task::{ResourceTask, load_whole_resource};
use url::Url; use style::{Source, LocalSource, UrlSource_};
/// A list of font templates that make up a given font family. /// A list of font templates that make up a given font family.
struct FontFamily { struct FontFamily {
@ -72,7 +72,7 @@ impl FontFamily {
pub enum Command { pub enum Command {
GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>), GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>),
GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>), GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>),
AddWebFont(String, Url, Sender<()>), AddWebFont(String, Source, Sender<()>),
Exit(Sender<()>), Exit(Sender<()>),
} }
@ -116,19 +116,31 @@ impl FontCache {
let font_template = self.get_last_resort_font_template(&descriptor); let font_template = self.get_last_resort_font_template(&descriptor);
result.send(GetFontTemplateReply(Some(font_template))); result.send(GetFontTemplateReply(Some(font_template)));
} }
AddWebFont(family_name, url, result) => { AddWebFont(family_name, src, result) => {
let maybe_resource = load_whole_resource(&self.resource_task, url.clone()); if !self.web_families.contains_key(&family_name) {
match maybe_resource { let family = FontFamily::new();
Ok((_, bytes)) => { self.web_families.insert(family_name.clone(), family);
if !self.web_families.contains_key(&family_name) { }
let family = FontFamily::new();
self.web_families.insert(family_name.clone(), family); match src {
UrlSource_(ref url_source) => {
let url = &url_source.url;
let maybe_resource = load_whole_resource(&self.resource_task, url.clone());
match maybe_resource {
Ok((_, bytes)) => {
let family = self.web_families.get_mut(&family_name);
family.add_template(url.to_string().as_slice(), Some(bytes));
},
Err(_) => {
debug!("Failed to load web font: family={} url={}", family_name, url);
}
} }
}
LocalSource(ref local_family_name) => {
let family = self.web_families.get_mut(&family_name); let family = self.web_families.get_mut(&family_name);
family.add_template(format!("{}", url).as_slice(), Some(bytes)); get_variations_for_family(local_family_name.as_slice(), |path| {
}, family.add_template(path.as_slice(), None);
Err(_) => { });
debug!("Failed to load web font: family={} url={}", family_name, url);
} }
} }
result.send(()); result.send(());
@ -290,9 +302,9 @@ impl FontCacheTask {
} }
} }
pub fn add_web_font(&self, family: String, url: Url) { pub fn add_web_font(&self, family: String, src: Source) {
let (response_chan, response_port) = channel(); let (response_chan, response_port) = channel();
self.chan.send(AddWebFont(family, url, response_chan)); self.chan.send(AddWebFont(family, src, response_chan));
response_port.recv(); response_port.recv();
} }

View file

@ -469,8 +469,8 @@ impl LayoutTask {
fn handle_add_stylesheet<'a>(&'a self, sheet: Stylesheet, possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { fn handle_add_stylesheet<'a>(&'a self, sheet: Stylesheet, possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
// Find all font-face rules and notify the font cache of them. // Find all font-face rules and notify the font cache of them.
// GWTODO: Need to handle unloading web fonts (when we handle unloading stylesheets!) // GWTODO: Need to handle unloading web fonts (when we handle unloading stylesheets!)
iter_font_face_rules(&sheet, |family, url| { iter_font_face_rules(&sheet, |family, src| {
self.font_cache_task.add_web_font(family.to_string(), url.clone()); self.font_cache_task.add_web_font(family.to_string(), (*src).clone());
}); });
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
rw_data.stylist.add_stylesheet(sheet, AuthorOrigin); rw_data.stylist.add_stylesheet(sheet, AuthorOrigin);

View file

@ -14,10 +14,7 @@ use media_queries::{Device, Screen};
use url::{Url, UrlParser}; use url::{Url, UrlParser};
static SUPPORTED_FORMATS: &'static [&'static str] = &["truetype", "opentype"]; pub fn iter_font_face_rules_inner(rules: &[CSSRule], callback: |family: &str, source: &Source|) {
pub fn iter_font_face_rules_inner(rules: &[CSSRule], callback: |family: &str, source: &Url|) {
let device = &Device { media_type: Screen }; // TODO, use Print when printing let device = &Device { media_type: Screen }; // TODO, use Print when printing
for rule in rules.iter() { for rule in rules.iter() {
match *rule { match *rule {
@ -27,22 +24,20 @@ pub fn iter_font_face_rules_inner(rules: &[CSSRule], callback: |family: &str, so
}, },
CSSFontFaceRule(ref rule) => { CSSFontFaceRule(ref rule) => {
for source in rule.sources.iter() { for source in rule.sources.iter() {
if source.format_hints.is_empty() || source.format_hints.iter().any( callback(rule.family.as_slice(), source)
|f| SUPPORTED_FORMATS.iter().any(
|s| f.as_slice().eq_ignore_ascii_case(*s))) {
callback(rule.family.as_slice(), &source.url)
}
} }
}, },
} }
} }
} }
enum Source { #[deriving(Clone)]
pub enum Source {
UrlSource_(UrlSource), UrlSource_(UrlSource),
LocalSource(String), LocalSource(String),
} }
#[deriving(Clone)]
pub struct UrlSource { pub struct UrlSource {
pub url: Url, pub url: Url,
pub format_hints: Vec<String>, pub format_hints: Vec<String>,
@ -50,7 +45,7 @@ pub struct UrlSource {
pub struct FontFaceRule { pub struct FontFaceRule {
pub family: String, pub family: String,
pub sources: Vec<UrlSource>, // local() is not supported yet pub sources: Vec<Source>,
} }
pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_url: &Url) { pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_url: &Url) {
@ -93,7 +88,7 @@ pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_
}, },
"src" => { "src" => {
match parse_slice_comma_separated( match parse_slice_comma_separated(
value.as_slice(), |iter| parse_one_url_src(iter, base_url)) { value.as_slice(), |iter| parse_one_src(iter, base_url)) {
Ok(sources) => maybe_sources = Some(sources), Ok(sources) => maybe_sources = Some(sources),
Err(()) => log_css_error(location, "Invalid src in @font-face"), Err(()) => log_css_error(location, "Invalid src in @font-face"),
}; };
@ -117,15 +112,6 @@ pub fn parse_font_face_rule(rule: AtRule, parent_rules: &mut Vec<CSSRule>, base_
} }
/// local() is not supported yet
fn parse_one_url_src(iter: ParserIter, base_url: &Url) -> Result<UrlSource, ()> {
match parse_one_src(iter, base_url) {
Ok(UrlSource_(source)) => Ok(source),
_ => Err(())
}
}
fn parse_one_src(iter: ParserIter, base_url: &Url) -> Result<Source, ()> { fn parse_one_src(iter: ParserIter, base_url: &Url) -> Result<Source, ()> {
let url = match iter.next() { let url = match iter.next() {
// Parsing url() // Parsing url()

View file

@ -48,6 +48,7 @@ pub use selectors::{PseudoElement, Before, After, SelectorList, parse_selector_l
pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace}; pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace};
pub use selectors::{SimpleSelector,LocalNameSelector}; pub use selectors::{SimpleSelector,LocalNameSelector};
pub use cssparser::{Color, RGBA}; pub use cssparser::{Color, RGBA};
pub use font_face::{Source, LocalSource, UrlSource_};
mod stylesheets; mod stylesheets;
mod errors; mod errors;

View file

@ -16,7 +16,7 @@ use errors::{ErrorLoggerIterator, log_css_error};
use namespaces::{NamespaceMap, parse_namespace_rule}; use namespaces::{NamespaceMap, parse_namespace_rule};
use media_queries::{MediaRule, parse_media_rule}; use media_queries::{MediaRule, parse_media_rule};
use media_queries; use media_queries;
use font_face::{FontFaceRule, parse_font_face_rule, iter_font_face_rules_inner}; use font_face::{FontFaceRule, Source, parse_font_face_rule, iter_font_face_rules_inner};
pub struct Stylesheet { pub struct Stylesheet {
@ -173,6 +173,6 @@ pub fn iter_stylesheet_style_rules(stylesheet: &Stylesheet, device: &media_queri
#[inline] #[inline]
pub fn iter_font_face_rules(stylesheet: &Stylesheet, callback: |family: &str, sources: &Url|) { pub fn iter_font_face_rules(stylesheet: &Stylesheet, callback: |family: &str, source: &Source|) {
iter_font_face_rules_inner(stylesheet.rules.as_slice(), callback) iter_font_face_rules_inner(stylesheet.rules.as_slice(), callback)
} }