зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e6d510ef2a
Коммит
f4be4f190a
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче