Load font family face variations on-demand, rather than all at startup. This breaks the linux build temporarily. Provides the Mac implementation for Issue #187.

This commit is contained in:
Brian J. Burg 2012-11-14 14:43:59 -08:00
parent fe29edb5f6
commit b14505e44d
6 changed files with 61 additions and 41 deletions

@ -1 +1 @@
Subproject commit 7fcbf5112ec163bdc14f096ddd9a45ef744ca6a6
Subproject commit 1f0bc6db0d23a9f1edd1918b3cb68e0ffba2cb9d

@ -1 +1 @@
Subproject commit 4c38ba65d4929ba418317c9fd9d16a0aa83945c9
Subproject commit 4914947bb5663f1b3f83757edc5be38f8f6f6d0d

View file

@ -34,6 +34,7 @@ type FontContextHandle/& = quartz::font_context::QuartzFontContextHandle;
type FontContextHandle/& = freetype::font_context::FreeTypeFontContextHandle;
trait FontContextHandleMethods {
pure fn clone(&const self) -> FontContextHandle;
fn create_font_from_identifier(~str, UsedFontStyle) -> Result<FontHandle, ()>;
}

View file

@ -24,9 +24,14 @@ pub impl FontListHandle {
type FontFamilyMap = linear::LinearMap<~str, @FontFamily>;
trait FontListHandleMethods {
fn get_available_families(&const self, fctx: &native::FontContextHandle) -> FontFamilyMap;
fn load_variations_for_family(&const self, family: @FontFamily);
}
pub struct FontList {
mut family_map: FontFamilyMap,
mut handle: FontListHandle,
handle: FontListHandle,
}
pub impl FontList {
@ -40,11 +45,13 @@ pub impl FontList {
return move list;
}
priv fn refresh(fctx: &native::FontContextHandle) {
priv fn refresh(_fctx: &native::FontContextHandle) {
// TODO(Issue #186): don't refresh unless something actually
// changed. Does OSX have a notification for this event?
//
// Should font families with entries be invalidated/refreshed too?
do util::time::time("gfx::font_list: regenerating available font families and faces") {
self.family_map = self.handle.get_available_families(fctx);
self.family_map = self.handle.get_available_families();
}
}
@ -57,7 +64,7 @@ pub impl FontList {
// if such family exists, try to match style to a font
do family.iter |fam| {
result = fam.find_font_for_style(style);
result = fam.find_font_for_style(&self.handle, style);
}
let decision = if result.is_some() { "Found" } else { "Couldn't find" };
@ -80,20 +87,27 @@ pub impl FontList {
// Holds a specific font family, and the various
pub struct FontFamily {
family_name: @str,
family_name: ~str,
entries: DVec<@FontEntry>,
}
pub impl FontFamily {
static fn new(family_name: &str) -> FontFamily {
FontFamily {
family_name: str::from_slice(family_name).to_managed(),
family_name: str::from_slice(family_name),
entries: DVec(),
}
}
pure fn find_font_for_style(style: &SpecifiedFontStyle) -> Option<@FontEntry> {
priv fn load_family_variations(@self, list: &native::FontListHandle) {
if self.entries.len() > 0 { return; }
list.load_variations_for_family(self);
assert self.entries.len() > 0;
}
fn find_font_for_style(@self, list: &native::FontListHandle, style: &SpecifiedFontStyle) -> Option<@FontEntry> {
self.load_family_variations(list);
// TODO(Issue #189): optimize lookup for
// regular/bold/italic/bolditalic with fixed offsets and a

View file

@ -23,6 +23,10 @@ pub impl QuartzFontContextHandle {
}
pub impl QuartzFontContextHandle : FontContextHandleMethods {
pure fn clone(&const self) -> QuartzFontContextHandle {
QuartzFontContextHandle { ctx: self.ctx }
}
fn create_font_from_identifier(name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> {
let ctfont_result = CTFont::new_from_name(move name, style.pt_size);
do result::chain(move ctfont_result) |ctfont| {

View file

@ -1,56 +1,57 @@
extern mod core_foundation;
extern mod core_text;
use quartz::font::{QuartzFontHandle};
use servo_gfx_font::FontHandle;
use servo_gfx_font_list::{FontEntry, FontFamily};
use cf = core_foundation;
use cf::array::CFArray;
use core::dvec::DVec;
use core::send_map::{linear, SendMap};
use cf::string::CFString;
use ct = core_text;
use ct::font::{CTFont, debug_font_names, debug_font_traits};
use ct::font_collection::CTFontCollection;
use ct::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, debug_descriptor};
use quartz::font::QuartzFontHandle;
use quartz::font_context::QuartzFontContextHandle;
use gfx_font::FontHandle;
use gfx_font_list::{FontEntry, FontFamily, FontFamilyMap};
use core::dvec::DVec;
use core::send_map::{linear, SendMap};
pub struct QuartzFontListHandle {
collection: CTFontCollection,
fctx: QuartzFontContextHandle,
}
pub impl QuartzFontListHandle {
static pub fn new(_fctx: &native::FontContextHandle) -> QuartzFontListHandle {
QuartzFontListHandle { collection: CTFontCollection::new() }
static fn new(fctx: &native::FontContextHandle) -> QuartzFontListHandle {
QuartzFontListHandle { fctx: fctx.clone() }
}
fn get_available_families(&const self,
fctx: &native::FontContextHandle)
-> linear::LinearMap<~str, @FontFamily> {
// since we mutate it repeatedly, must be mut variable.
let mut family_map : linear::LinearMap<~str, @FontFamily> = linear::LinearMap();
let descriptors : CFArray<CTFontDescriptorRef, CTFontDescriptor>;
descriptors = self.collection.get_descriptors();
for descriptors.each |desc: &CTFontDescriptor| {
// TODO: for each descriptor, make a FontEntry.
fn get_available_families() -> FontFamilyMap {
let family_names = CTFontCollection::get_family_names();
let mut family_map : FontFamilyMap = linear::LinearMap();
for family_names.each |family_name_cfstr: &CFString| {
let family_name = family_name_cfstr.to_str();
debug!("Creating new FontFamily for family: %s", family_name);
let new_family = @FontFamily::new(family_name);
family_map.insert(move family_name, new_family);
}
return move family_map;
}
fn load_variations_for_family(family: @FontFamily) {
let family_name = &family.family_name;
debug!("Looking for faces of family: %s", *family_name);
let family_collection = CTFontCollection::create_for_family(*family_name);
for family_collection.get_descriptors().each |desc: &CTFontDescriptor| {
let font = CTFont::new_from_descriptor(desc, 0.0);
let handle = result::unwrap(QuartzFontHandle::new_from_CTFont(fctx, move font));
let family_name = handle.family_name();
debug!("Looking for family name: %s", family_name);
let family = match family_map.find(&family_name) {
Some(fam) => fam,
None => {
debug!("Creating new FontFamily for family: %s", family_name);
let new_family = @FontFamily::new(family_name);
family_map.insert(move family_name, new_family);
new_family
}
};
let handle = result::unwrap(QuartzFontHandle::new_from_CTFont(&self.fctx, move font));
debug!("Creating new FontEntry for face: %s", handle.face_name());
let entry = @FontEntry::new(family, move handle);
family.entries.push(entry);
// TODO: append FontEntry to hashtable value
}
return move family_map;
}
}