diff --git a/src/components/gfx/font_context.rs b/src/components/gfx/font_context.rs index 9e8766bd3d0..9437e44299f 100644 --- a/src/components/gfx/font_context.rs +++ b/src/components/gfx/font_context.rs @@ -30,7 +30,7 @@ pub struct FontContextInfo { } pub trait FontContextHandleMethods { - fn create_font_from_identifier(&self, String, UsedFontStyle) -> Result; + fn create_font_from_identifier(&self, &str, Option<&UsedFontStyle>) -> Result; } 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( diff --git a/src/components/gfx/font_list.rs b/src/components/gfx/font_list.rs index 6a208107c07..3180e5e710c 100644 --- a/src/components/gfx/font_list.rs +++ b/src/components/gfx/font_list.rs @@ -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; -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; -} - /// 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 { - 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 diff --git a/src/components/gfx/platform/android/font.rs b/src/components/gfx/platform/android/font.rs index 1b564c6f7c4..e61d092ae07 100644 --- a/src/components/gfx/platform/android/font.rs +++ b/src/components/gfx/platform/android/font.rs @@ -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) } diff --git a/src/components/gfx/platform/android/font_context.rs b/src/components/gfx/platform/android/font_context.rs index dad6e6252cf..3196f25120e 100644 --- a/src/components/gfx/platform/android/font_context.rs +++ b/src/components/gfx/platform/android/font_context.rs @@ -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::() 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 { 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) } } diff --git a/src/components/gfx/platform/android/font_list.rs b/src/components/gfx/platform/android/font_list.rs index 378cf42e71f..d96cd8cdd0f 100644 --- a/src/components/gfx/platform/android/font_list.rs +++ b/src/components/gfx/platform/android/font_list.rs @@ -7,215 +7,99 @@ 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(); - unsafe { - let config = FcConfigGetCurrent(); - let fontSet = FcConfigGetFonts(config, FcSetSystem); - for i in range(0, (*fontSet).nfont as int) { - let font = (*fontSet).fonts.offset(i); - let family: *FcChar8 = ptr::null(); - let mut v: c_int = 0; - "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); - v += 1; - } - }); - } - } - return family_map; - } - - pub fn load_variations_for_family(&self, family: &mut FontFamily) { - debug!("getting variations for {:?}", family); - unsafe { - let config = FcConfigGetCurrent(); - let font_set = FcConfigGetFonts(config, FcSetSystem); - let font_set_array_ptr = &font_set; - 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| { - let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); - assert!(ok != 0); - }); - }); - - let object_set = FcObjectSetCreate(); - assert!(object_set.is_not_null()); - - "file".to_c_str().with_ref(|FC_FILE| { - FcObjectSetAdd(object_set, FC_FILE); - }); - "index".to_c_str().with_ref(|FC_INDEX| { - FcObjectSetAdd(object_set, FC_INDEX); - }); - - let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); - - debug!("found {} variations", (*matches).nfont); - - for i in range(0, (*matches).nfont as int) { - let font = (*matches).fonts.offset(i); - let file = "file".to_c_str().with_ref(|FC_FILE| { - let file: *FcChar8 = ptr::null(); - if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { - str::raw::from_c_str(file as *libc::c_char) - } else { - fail!(); - } - }); - let index = "index".to_c_str().with_ref(|FC_INDEX| { - let index: libc::c_int = 0; - if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { - index - } else { - fail!(); - } - }); - - 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); - } - - FcFontSetDestroy(matches); - FcPatternDestroy(pattern); - FcObjectSetDestroy(object_set); - } - } - - pub fn get_last_resort_font_families() -> Vec { - 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 { +pub fn get_available_families(callback: |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(()); + let fontSet = FcConfigGetFonts(config, FcSetSystem); + for i in range(0, (*fontSet).nfont as int) { + let font = (*fontSet).fonts.offset(i); + let family: *FcChar8 = ptr::null(); + let mut v: c_int = 0; + "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); + callback(family_name); + v += 1; } - }, - 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)) } } + +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); + let font_set_array_ptr = &font_set; + let pattern = FcPatternCreate(); + assert!(pattern.is_not_null()); + "family".to_c_str().with_ref(|FC_FAMILY| { + family_name.to_c_str().with_ref(|family_name| { + let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); + assert!(ok != 0); + }); + }); + + let object_set = FcObjectSetCreate(); + assert!(object_set.is_not_null()); + + "file".to_c_str().with_ref(|FC_FILE| { + FcObjectSetAdd(object_set, FC_FILE); + }); + "index".to_c_str().with_ref(|FC_INDEX| { + FcObjectSetAdd(object_set, FC_INDEX); + }); + + let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); + + debug!("found {} variations", (*matches).nfont); + + for i in range(0, (*matches).nfont as int) { + let font = (*matches).fonts.offset(i); + let file = "file".to_c_str().with_ref(|FC_FILE| { + let file: *FcChar8 = ptr::null(); + if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { + str::raw::from_c_str(file as *libc::c_char) + } else { + fail!(); + } + }); + let index = "index".to_c_str().with_ref(|FC_INDEX| { + let index: libc::c_int = 0; + if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { + index + } else { + fail!(); + } + }); + + debug!("variation file: {}", file); + debug!("variation index: {}", index); + + callback(file); + } + + FcFontSetDestroy(matches); + FcPatternDestroy(pattern); + FcObjectSetDestroy(object_set); + } +} + +pub fn get_last_resort_font_families() -> Vec { + vec!("Roboto".to_string()) +} diff --git a/src/components/gfx/platform/linux/font.rs b/src/components/gfx/platform/linux/font.rs index 1b564c6f7c4..e61d092ae07 100644 --- a/src/components/gfx/platform/linux/font.rs +++ b/src/components/gfx/platform/linux/font.rs @@ -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) } diff --git a/src/components/gfx/platform/linux/font_context.rs b/src/components/gfx/platform/linux/font_context.rs index dad6e6252cf..3196f25120e 100644 --- a/src/components/gfx/platform/linux/font_context.rs +++ b/src/components/gfx/platform/linux/font_context.rs @@ -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::() 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 { 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) } } diff --git a/src/components/gfx/platform/linux/font_list.rs b/src/components/gfx/platform/linux/font_list.rs index 9dafbd781c0..f76cde75c69 100644 --- a/src/components/gfx/platform/linux/font_list.rs +++ b/src/components/gfx/platform/linux/font_list.rs @@ -7,219 +7,103 @@ 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(); - unsafe { - let config = FcConfigGetCurrent(); - let fontSet = FcConfigGetFonts(config, FcSetSystem); - for i in range(0, (*fontSet).nfont as int) { - let font = (*fontSet).fonts.offset(i); - let family: *FcChar8 = ptr::null(); - let mut v: c_int = 0; - "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); - v += 1; - } - }); - } - } - return family_map; - } - - pub fn load_variations_for_family(&self, family: &mut FontFamily) { - debug!("getting variations for {:?}", family); - unsafe { - let config = FcConfigGetCurrent(); - let font_set = FcConfigGetFonts(config, FcSetSystem); - let font_set_array_ptr = &font_set; - 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| { - let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); - assert!(ok != 0); - }); - }); - - let object_set = FcObjectSetCreate(); - assert!(object_set.is_not_null()); - - "file".to_c_str().with_ref(|FC_FILE| { - FcObjectSetAdd(object_set, FC_FILE); - }); - "index".to_c_str().with_ref(|FC_INDEX| { - FcObjectSetAdd(object_set, FC_INDEX); - }); - - let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); - - debug!("found {} variations", (*matches).nfont); - - for i in range(0, (*matches).nfont as int) { - let font = (*matches).fonts.offset(i); - let file = "file".to_c_str().with_ref(|FC_FILE| { - let file: *FcChar8 = ptr::null(); - if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { - str::raw::from_c_str(file as *libc::c_char) - } else { - fail!(); - } - }); - let index = "index".to_c_str().with_ref(|FC_INDEX| { - let index: libc::c_int = 0; - if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { - index - } else { - fail!(); - } - }); - - 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); - } - - FcFontSetDestroy(matches); - FcPatternDestroy(pattern); - FcObjectSetDestroy(object_set); - } - } - - pub fn get_last_resort_font_families() -> Vec { - vec!( - "Fira Sans".to_string(), - "DejaVu Sans".to_string(), - "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 { +pub fn get_available_families(callback: |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(()); + let fontSet = FcConfigGetFonts(config, FcSetSystem); + for i in range(0, (*fontSet).nfont as int) { + let font = (*fontSet).fonts.offset(i); + let family: *FcChar8 = ptr::null(); + let mut v: c_int = 0; + "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); + callback(family_name); + v += 1; } - }, - 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)) } } + +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); + let font_set_array_ptr = &font_set; + let pattern = FcPatternCreate(); + assert!(pattern.is_not_null()); + "family".to_c_str().with_ref(|FC_FAMILY| { + family_name.to_c_str().with_ref(|family_name| { + let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); + assert!(ok != 0); + }); + }); + + let object_set = FcObjectSetCreate(); + assert!(object_set.is_not_null()); + + "file".to_c_str().with_ref(|FC_FILE| { + FcObjectSetAdd(object_set, FC_FILE); + }); + "index".to_c_str().with_ref(|FC_INDEX| { + FcObjectSetAdd(object_set, FC_INDEX); + }); + + let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); + + debug!("found {} variations", (*matches).nfont); + + for i in range(0, (*matches).nfont as int) { + let font = (*matches).fonts.offset(i); + let file = "file".to_c_str().with_ref(|FC_FILE| { + let file: *FcChar8 = ptr::null(); + if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { + str::raw::from_c_str(file as *libc::c_char) + } else { + fail!(); + } + }); + let index = "index".to_c_str().with_ref(|FC_INDEX| { + let index: libc::c_int = 0; + if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { + index + } else { + fail!(); + } + }); + + debug!("variation file: {}", file); + debug!("variation index: {}", index); + + callback(file); + } + + FcFontSetDestroy(matches); + FcPatternDestroy(pattern); + FcObjectSetDestroy(object_set); + } +} + +pub fn get_last_resort_font_families() -> Vec { + vec!( + "Fira Sans".to_string(), + "DejaVu Sans".to_string(), + "Arial".to_string() + ) +} diff --git a/src/components/gfx/platform/macos/font_context.rs b/src/components/gfx/platform/macos/font_context.rs index 58c79cd65e2..4b66aa6bbf8 100644 --- a/src/components/gfx/platform/macos/font_context.rs +++ b/src/components/gfx/platform/macos/font_context.rs @@ -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 { - 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) }) diff --git a/src/components/gfx/platform/macos/font_list.rs b/src/components/gfx/platform/macos/font_list.rs index 8f332bd24f4..65d375c5845 100644 --- a/src/components/gfx/platform/macos/font_list.rs +++ b/src/components/gfx/platform/macos/font_list.rs @@ -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 { - 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); - } - family_map - } - - pub fn load_variations_for_family(&self, family: &mut FontFamily) { - debug!("Looking for faces of family: {:s}", family.family_name); - - let family_collection = - core_text::font_collection::create_for_family(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) - } - } - - pub fn get_last_resort_font_families() -> Vec { - vec!("Arial Unicode MS".to_string(), "Arial".to_string()) +pub fn get_available_families(callback: |String|) { + let family_names = core_text::font_collection::get_family_names(); + 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(); + callback(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_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 postscript_name = desc.font_name(); + callback(postscript_name); + } +} + +pub fn get_last_resort_font_families() -> Vec { + vec!("Arial Unicode MS".to_string(), "Arial".to_string()) +}