servo: Merge #2751 - First part of font refactoring. These changes simplify a few things (from glennw:font-refactor-1)

Source-Repo: https://github.com/servo/servo
Source-Revision: b0ffeaf53cd567e7bb97d6a1a7300dfce3ef76a5
This commit is contained in:
Glenn Watson 2014-07-03 11:53:00 -05:00
Родитель e6d510ef2a
Коммит f4be4f190a
10 изменённых файлов: 237 добавлений и 492 удалений

Просмотреть файл

@ -30,7 +30,7 @@ pub struct FontContextInfo {
}
pub trait FontContextHandleMethods {
fn create_font_from_identifier(&self, String, UsedFontStyle) -> Result<FontHandle, ()>;
fn create_font_from_identifier(&self, &str, Option<&UsedFontStyle>) -> Result<FontHandle, ()>;
}
pub struct FontContext {
@ -128,7 +128,7 @@ impl FontContext {
let result = match self.font_list {
Some(ref mut fl) => {
let font_in_family = fl.find_font_in_family(&transformed_family_name, style);
let font_in_family = fl.find_font_in_family(&self.handle, &transformed_family_name, style);
match font_in_family {
Some(font_entry) => {
let font_id =
@ -164,7 +164,7 @@ impl FontContext {
let font_desc = match self.font_list {
Some(ref mut font_list) => {
let font_desc = {
let font_entry = font_list.find_font_in_family(family, style);
let font_entry = font_list.find_font_in_family(&self.handle, family, style);
match font_entry {
Some(v) => {
let font_id =
@ -207,8 +207,8 @@ impl FontContext {
return match &desc.selector {
// TODO(Issue #174): implement by-platform-name font selectors.
&SelectorPlatformIdentifier(ref identifier) => {
let result_handle = self.handle.create_font_from_identifier((*identifier).clone(),
desc.style.clone());
let result_handle = self.handle.create_font_from_identifier(identifier.as_slice(),
Some(&desc.style));
result_handle.and_then(|handle| {
Ok(
Rc::new(

Просмотреть файл

@ -4,10 +4,11 @@
use std::collections::hashmap::HashMap;
use font::SpecifiedFontStyle;
use font_context::FontContextHandleMethods;
use gfx_font::FontHandleMethods;
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use platform::font_list::FontListHandle;
use platform::font_list;
use style::computed_values::{font_weight, font_style};
use servo_util::time::{TimeProfilerChan, profile};
@ -15,16 +16,9 @@ use servo_util::time;
pub type FontFamilyMap = HashMap<String, FontFamily>;
trait FontListHandleMethods {
fn get_available_families(&self, fctx: &FontContextHandle) -> FontFamilyMap;
fn load_variations_for_family(&self, family: &mut FontFamily);
fn get_last_resort_font_families() -> Vec<String>;
}
/// The platform-independent font list abstraction.
pub struct FontList {
family_map: FontFamilyMap,
handle: FontListHandle,
time_profiler_chan: TimeProfilerChan,
}
@ -32,9 +26,7 @@ impl FontList {
pub fn new(fctx: &FontContextHandle,
time_profiler_chan: TimeProfilerChan)
-> FontList {
let handle = FontListHandle::new(fctx);
let mut list = FontList {
handle: handle,
family_map: HashMap::new(),
time_profiler_chan: time_profiler_chan.clone(),
};
@ -48,11 +40,16 @@ impl FontList {
//
// Should font families with entries be invalidated/refreshed too?
profile(time::GfxRegenAvailableFontsCategory, self.time_profiler_chan.clone(), || {
self.family_map = self.handle.get_available_families();
self.family_map.clear();
font_list::get_available_families(|family_name| {
debug!("Creating new FontFamily for family: {:s}", family_name);
let new_family = FontFamily::new(family_name.as_slice());
self.family_map.insert(family_name, new_family);
});
});
}
pub fn find_font_in_family<'a>(&'a mut self,
pub fn find_font_in_family<'a>(&'a mut self, fctx: &FontContextHandle,
family_name: &String,
style: &SpecifiedFontStyle) -> Option<&'a FontEntry> {
// TODO(Issue #188): look up localized font family names if canonical name not found
@ -63,7 +60,7 @@ impl FontList {
let s: &'a mut FontFamily = self.family_map.get_mut(family_name);
// TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
// if such family exists, try to match style to a font
let result = s.find_font_for_style(&mut self.handle, style);
let result = s.find_font_for_style(fctx, style);
if result.is_some() {
return result;
}
@ -76,7 +73,7 @@ impl FontList {
}
pub fn get_last_resort_font_families() -> Vec<String> {
FontListHandle::get_last_resort_font_families()
font_list::get_last_resort_font_families()
}
}
@ -94,17 +91,24 @@ impl FontFamily {
}
}
fn load_family_variations(&mut self, list: &FontListHandle) {
fn load_family_variations(&mut self, fctx: &FontContextHandle) {
if self.entries.len() > 0 {
return
}
list.load_variations_for_family(self);
let mut entries = vec!();
font_list::load_variations_for_family(self.family_name.as_slice(), |file_path| {
let font_handle = fctx.create_font_from_identifier(file_path.as_slice(), None).unwrap();
debug!("Creating new FontEntry for face: {:s}", font_handle.face_name());
let entry = FontEntry::new(font_handle);
entries.push(entry);
});
self.entries = entries;
assert!(self.entries.len() > 0)
}
pub fn find_font_for_style<'a>(&'a mut self, list: &FontListHandle, style: &SpecifiedFontStyle)
pub fn find_font_for_style<'a>(&'a mut self, fctx: &FontContextHandle, style: &SpecifiedFontStyle)
-> Option<&'a FontEntry> {
self.load_family_variations(list);
self.load_family_variations(fctx);
// TODO(Issue #189): optimize lookup for
// regular/bold/italic/bolditalic with fixed offsets and a

Просмотреть файл

@ -118,9 +118,11 @@ impl FontHandleMethods for FontHandle {
// an identifier usable by FontContextHandle to recreate this FontHandle.
fn face_identifier(&self) -> String {
/* FT_Get_Postscript_Name seems like a better choice here, but it
doesn't give usable results for fontconfig when deserializing. */
unsafe { str::raw::from_c_str((*self.face).family_name) }
match self.source {
FontSourceFile(ref path) => path.clone(),
_ => unreachable!(), // This will be handled when the rest of the font
// refactor is complete. For now, it can never be hit.
}
}
fn family_name(&self) -> String {
unsafe { str::raw::from_c_str((*self.face).family_name) }

Просмотреть файл

@ -5,7 +5,6 @@
use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;
use freetype::freetype::FTErrorMethods;
use freetype::freetype::FT_Add_Default_Modules;
@ -65,7 +64,7 @@ impl FontContextHandle {
let ptr = libc::malloc(mem::size_of::<struct_FT_MemoryRec_>() as size_t);
let allocator: &mut struct_FT_MemoryRec_ = mem::transmute(ptr);
mem::overwrite(allocator, struct_FT_MemoryRec_ {
ptr::write(allocator, struct_FT_MemoryRec_ {
user: ptr::null(),
alloc: ft_alloc,
free: ft_free,
@ -87,13 +86,10 @@ impl FontContextHandle {
}
impl FontContextHandleMethods for FontContextHandle {
fn create_font_from_identifier(&self, name: String, style: UsedFontStyle)
fn create_font_from_identifier(&self, name: &str, style: Option<&UsedFontStyle>)
-> Result<FontHandle, ()> {
debug!("Creating font handle for {:s}", name);
path_from_identifier(name, &style).and_then(|file_name| {
debug!("Opening font face {:s}", file_name);
FontHandle::new_from_file(self, file_name.as_slice(), Some(&style))
})
FontHandle::new_from_file(self, name.as_slice(), style)
}
}

Просмотреть файл

@ -7,43 +7,21 @@
extern crate freetype;
extern crate fontconfig;
use fontconfig::fontconfig::{
FcChar8, FcResultMatch, FcSetSystem, FcPattern,
FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD, FC_SLANT_OBLIQUE
};
use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
FcFontMatch, FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
FcPatternDestroy, FcFontSetDestroy,
FcPatternCreate, FcPatternAddString,
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
FcObjectSetAdd, FcPatternGetInteger
};
use style::computed_values::font_style;
use font::{FontHandleMethods, UsedFontStyle};
use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use std::collections::hashmap::HashMap;
use libc;
use libc::{c_int, c_char};
use std::ptr;
use std::str;
pub struct FontListHandle {
pub fctx: FontContextHandle,
}
impl FontListHandle {
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
FontListHandle { fctx: fctx.clone() }
}
pub fn get_available_families(&self) -> FontFamilyMap {
let mut family_map : FontFamilyMap = HashMap::new();
pub fn get_available_families(callback: |String|) {
unsafe {
let config = FcConfigGetCurrent();
let fontSet = FcConfigGetFonts(config, FcSetSystem);
@ -54,19 +32,16 @@ impl FontListHandle {
"family".to_c_str().with_ref(|FC_FAMILY| {
while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
let family_name = str::raw::from_c_str(family as *c_char);
debug!("Creating new FontFamily for family: {:s}", family_name);
let new_family = FontFamily::new(family_name.as_slice());
family_map.insert(family_name, new_family);
callback(family_name);
v += 1;
}
});
}
}
return family_map;
}
pub fn load_variations_for_family(&self, family: &mut FontFamily) {
debug!("getting variations for {:?}", family);
pub fn load_variations_for_family(family_name: &str, callback: |String|) {
debug!("getting variations for {}", family_name);
unsafe {
let config = FcConfigGetCurrent();
let font_set = FcConfigGetFonts(config, FcSetSystem);
@ -74,7 +49,7 @@ impl FontListHandle {
let pattern = FcPatternCreate();
assert!(pattern.is_not_null());
"family".to_c_str().with_ref(|FC_FAMILY| {
family.family_name.to_c_str().with_ref(|family_name| {
family_name.to_c_str().with_ref(|family_name| {
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
assert!(ok != 0);
});
@ -116,13 +91,7 @@ impl FontListHandle {
debug!("variation file: {}", file);
debug!("variation index: {}", index);
let font_handle = FontHandle::new_from_file(&self.fctx,
file.as_slice(), None);
let font_handle = font_handle.unwrap();
debug!("Creating new FontEntry for face: {:s}", font_handle.face_name());
let entry = FontEntry::new(font_handle);
family.entries.push(entry);
callback(file);
}
FcFontSetDestroy(matches);
@ -134,88 +103,3 @@ impl FontListHandle {
pub fn get_last_resort_font_families() -> Vec<String> {
vec!("Roboto".to_string())
}
}
struct AutoPattern {
pattern: *FcPattern
}
impl Drop for AutoPattern {
fn drop(&mut self) {
unsafe {
FcPatternDestroy(self.pattern);
}
}
}
pub fn path_from_identifier(name: String, style: &UsedFontStyle) -> Result<String, ()> {
unsafe {
let config = FcConfigGetCurrent();
let wrapper = AutoPattern { pattern: FcPatternCreate() };
let pattern = wrapper.pattern;
let res = "family".to_c_str().with_ref(|FC_FAMILY| {
name.to_c_str().with_ref(|family| {
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
})
});
if res != 1 {
debug!("adding family to pattern failed");
return Err(());
}
match style.style {
font_style::normal => (),
font_style::italic => {
let res = "slant".to_c_str().with_ref(|FC_SLANT| {
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
});
if res != 1 {
debug!("adding slant to pattern failed");
return Err(());
}
},
font_style::oblique => {
let res = "slant".to_c_str().with_ref(|FC_SLANT| {
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_OBLIQUE)
});
if res != 1 {
debug!("adding slant(oblique) to pattern failed");
return Err(());
}
}
}
if style.weight.is_bold() {
let res = "weight".to_c_str().with_ref(|FC_WEIGHT| {
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
});
if res != 1 {
debug!("adding weight to pattern failed");
return Err(());
}
}
if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
debug!("substitution failed");
return Err(());
}
FcDefaultSubstitute(pattern);
let result = FcResultNoMatch;
let result_wrapper = AutoPattern { pattern: FcFontMatch(config, pattern, &result) };
let result_pattern = result_wrapper.pattern;
if result != FcResultMatch && result_pattern.is_null() {
debug!("obtaining match to pattern failed");
return Err(());
}
let file: *FcChar8 = ptr::null();
let res = "file".to_c_str().with_ref(|FC_FILE| {
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
});
if res != FcResultMatch {
debug!("getting filename for font failed");
return Err(());
}
Ok(str::raw::from_c_str(file as *c_char))
}
}

Просмотреть файл

@ -118,9 +118,11 @@ impl FontHandleMethods for FontHandle {
// an identifier usable by FontContextHandle to recreate this FontHandle.
fn face_identifier(&self) -> String {
/* FT_Get_Postscript_Name seems like a better choice here, but it
doesn't give usable results for fontconfig when deserializing. */
unsafe { str::raw::from_c_str((*self.face).family_name) }
match self.source {
FontSourceFile(ref path) => path.clone(),
_ => unreachable!(), // This will be handled when the rest of the font
// refactor is complete. For now, it can never be hit.
}
}
fn family_name(&self) -> String {
unsafe { str::raw::from_c_str((*self.face).family_name) }

Просмотреть файл

@ -5,7 +5,6 @@
use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;
use freetype::freetype::FTErrorMethods;
use freetype::freetype::FT_Add_Default_Modules;
@ -65,7 +64,7 @@ impl FontContextHandle {
let ptr = libc::malloc(mem::size_of::<struct_FT_MemoryRec_>() as size_t);
let allocator: &mut struct_FT_MemoryRec_ = mem::transmute(ptr);
mem::overwrite(allocator, struct_FT_MemoryRec_ {
ptr::write(allocator, struct_FT_MemoryRec_ {
user: ptr::null(),
alloc: ft_alloc,
free: ft_free,
@ -87,13 +86,10 @@ impl FontContextHandle {
}
impl FontContextHandleMethods for FontContextHandle {
fn create_font_from_identifier(&self, name: String, style: UsedFontStyle)
fn create_font_from_identifier(&self, name: &str, style: Option<&UsedFontStyle>)
-> Result<FontHandle, ()> {
debug!("Creating font handle for {:s}", name);
path_from_identifier(name, &style).and_then(|file_name| {
debug!("Opening font face {:s}", file_name);
FontHandle::new_from_file(self, file_name.as_slice(), Some(&style))
})
FontHandle::new_from_file(self, name.as_slice(), style)
}
}

Просмотреть файл

@ -7,43 +7,21 @@
extern crate freetype;
extern crate fontconfig;
use fontconfig::fontconfig::{
FcChar8, FcResultMatch, FcSetSystem, FcPattern,
FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD, FC_SLANT_OBLIQUE
};
use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
use fontconfig::fontconfig::{
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
FcFontMatch, FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
FcPatternDestroy, FcFontSetDestroy,
FcPatternCreate, FcPatternAddString,
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
FcObjectSetAdd, FcPatternGetInteger
};
use style::computed_values::font_style;
use font::{FontHandleMethods, UsedFontStyle};
use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use std::collections::hashmap::HashMap;
use libc;
use libc::{c_int, c_char};
use std::ptr;
use std::str;
pub struct FontListHandle {
pub fctx: FontContextHandle,
}
impl FontListHandle {
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
FontListHandle { fctx: fctx.clone() }
}
pub fn get_available_families(&self) -> FontFamilyMap {
let mut family_map : FontFamilyMap = HashMap::new();
pub fn get_available_families(callback: |String|) {
unsafe {
let config = FcConfigGetCurrent();
let fontSet = FcConfigGetFonts(config, FcSetSystem);
@ -54,19 +32,16 @@ impl FontListHandle {
"family".to_c_str().with_ref(|FC_FAMILY| {
while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
let family_name = str::raw::from_c_str(family as *c_char);
debug!("Creating new FontFamily for family: {:s}", family_name);
let new_family = FontFamily::new(family_name.as_slice());
family_map.insert(family_name, new_family);
callback(family_name);
v += 1;
}
});
}
}
return family_map;
}
pub fn load_variations_for_family(&self, family: &mut FontFamily) {
debug!("getting variations for {:?}", family);
pub fn load_variations_for_family(family_name: &str, callback: |String|) {
debug!("getting variations for {}", family_name);
unsafe {
let config = FcConfigGetCurrent();
let font_set = FcConfigGetFonts(config, FcSetSystem);
@ -74,7 +49,7 @@ impl FontListHandle {
let pattern = FcPatternCreate();
assert!(pattern.is_not_null());
"family".to_c_str().with_ref(|FC_FAMILY| {
family.family_name.to_c_str().with_ref(|family_name| {
family_name.to_c_str().with_ref(|family_name| {
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
assert!(ok != 0);
});
@ -116,13 +91,7 @@ impl FontListHandle {
debug!("variation file: {}", file);
debug!("variation index: {}", index);
let font_handle = FontHandle::new_from_file(&self.fctx,
file.as_slice(), None);
let font_handle = font_handle.unwrap();
debug!("Creating new FontEntry for face: {:s}", font_handle.face_name());
let entry = FontEntry::new(font_handle);
family.entries.push(entry);
callback(file);
}
FcFontSetDestroy(matches);
@ -138,88 +107,3 @@ impl FontListHandle {
"Arial".to_string()
)
}
}
struct AutoPattern {
pattern: *FcPattern
}
impl Drop for AutoPattern {
fn drop(&mut self) {
unsafe {
FcPatternDestroy(self.pattern);
}
}
}
pub fn path_from_identifier(name: String, style: &UsedFontStyle) -> Result<String, ()> {
unsafe {
let config = FcConfigGetCurrent();
let wrapper = AutoPattern { pattern: FcPatternCreate() };
let pattern = wrapper.pattern;
let res = "family".to_c_str().with_ref(|FC_FAMILY| {
name.to_c_str().with_ref(|family| {
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
})
});
if res != 1 {
debug!("adding family to pattern failed");
return Err(());
}
match style.style {
font_style::normal => (),
font_style::italic => {
let res = "slant".to_c_str().with_ref(|FC_SLANT| {
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
});
if res != 1 {
debug!("adding slant to pattern failed");
return Err(());
}
},
font_style::oblique => {
let res = "slant".to_c_str().with_ref(|FC_SLANT| {
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_OBLIQUE)
});
if res != 1 {
debug!("adding slant(oblique) to pattern failed");
return Err(());
}
}
}
if style.weight.is_bold() {
let res = "weight".to_c_str().with_ref(|FC_WEIGHT| {
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
});
if res != 1 {
debug!("adding weight to pattern failed");
return Err(());
}
}
if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
debug!("substitution failed");
return Err(());
}
FcDefaultSubstitute(pattern);
let result = FcResultNoMatch;
let result_wrapper = AutoPattern { pattern: FcFontMatch(config, pattern, &result) };
let result_pattern = result_wrapper.pattern;
if result != FcResultMatch && result_pattern.is_null() {
debug!("obtaining match to pattern failed");
return Err(());
}
let file: *FcChar8 = ptr::null();
let res = "file".to_c_str().with_ref(|FC_FILE| {
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
});
if res != FcResultMatch {
debug!("getting filename for font failed");
return Err(());
}
Ok(str::raw::from_c_str(file as *c_char))
}
}

Просмотреть файл

@ -23,10 +23,14 @@ impl FontContextHandle {
impl FontContextHandleMethods for FontContextHandle {
fn create_font_from_identifier(&self,
name: String,
style: UsedFontStyle)
name: &str,
style: Option<&UsedFontStyle>)
-> Result<FontHandle, ()> {
let ctfont_result = core_text::font::new_from_name(name.as_slice(), style.pt_size);
let pt_size = match style {
Some(style) => style.pt_size,
None => 0.0,
};
let ctfont_result = core_text::font::new_from_name(name.as_slice(), pt_size);
ctfont_result.and_then(|ctfont| {
FontHandle::new_from_CTFont(self, ctfont)
})

Просмотреть файл

@ -2,63 +2,36 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use font::FontHandleMethods;
use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::macos::font::FontHandle;
use platform::macos::font_context::FontContextHandle;
use std::collections::hashmap::HashMap;
use core_foundation::base::TCFType;
use core_foundation::string::{CFString, CFStringRef};
use core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef};
use core_text;
use std::mem;
pub struct FontListHandle {
fctx: FontContextHandle,
}
impl FontListHandle {
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
FontListHandle {
fctx: fctx.clone()
}
}
pub fn get_available_families(&self) -> FontFamilyMap {
pub fn get_available_families(callback: |String|) {
let family_names = core_text::font_collection::get_family_names();
let mut family_map: FontFamilyMap = HashMap::new();
for strref in family_names.iter() {
let family_name_ref: CFStringRef = unsafe { mem::transmute(strref) };
let family_name_cf: CFString = unsafe { TCFType::wrap_under_get_rule(family_name_ref) };
let family_name = family_name_cf.to_str();
debug!("Creating new FontFamily for family: {:s}", family_name);
let new_family = FontFamily::new(family_name.as_slice());
family_map.insert(family_name, new_family);
callback(family_name);
}
family_map
}
pub fn load_variations_for_family(&self, family: &mut FontFamily) {
debug!("Looking for faces of family: {:s}", family.family_name);
pub fn load_variations_for_family(family_name: &str, callback: |String|) {
debug!("Looking for faces of family: {:s}", family_name);
let family_collection =
core_text::font_collection::create_for_family(family.family_name.as_slice());
core_text::font_collection::create_for_family(family_name.as_slice());
let family_descriptors = family_collection.get_descriptors();
for descref in family_descriptors.iter() {
let descref: CTFontDescriptorRef = unsafe { mem::transmute(descref) };
let desc: CTFontDescriptor = unsafe { TCFType::wrap_under_get_rule(descref) };
let font = core_text::font::new_from_descriptor(&desc, 0.0);
let handle = FontHandle::new_from_CTFont(&self.fctx, font).unwrap();
debug!("Creating new FontEntry for face: {:s}", handle.face_name());
let entry = FontEntry::new(handle);
family.entries.push(entry)
let postscript_name = desc.font_name();
callback(postscript_name);
}
}
pub fn get_last_resort_font_families() -> Vec<String> {
vec!("Arial Unicode MS".to_string(), "Arial".to_string())
}
}