diff options
Diffstat (limited to 'components/gfx/platform/macos')
-rw-r--r-- | components/gfx/platform/macos/font.rs | 185 | ||||
-rw-r--r-- | components/gfx/platform/macos/font_context.rs | 16 | ||||
-rw-r--r-- | components/gfx/platform/macos/font_list.rs | 37 | ||||
-rw-r--r-- | components/gfx/platform/macos/font_template.rs | 40 |
4 files changed, 278 insertions, 0 deletions
diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs new file mode 100644 index 00000000000..f616ef328bd --- /dev/null +++ b/components/gfx/platform/macos/font.rs @@ -0,0 +1,185 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +/// Implementation of Quartz (CoreGraphics) fonts. + +extern crate core_foundation; +extern crate core_graphics; +extern crate core_text; + +use font::{FontHandleMethods, FontMetrics, FontTableMethods}; +use font::FontTableTag; +use font::FractionalPixel; +use servo_util::geometry::{Au, px_to_pt}; +use servo_util::geometry; +use platform::macos::font_context::FontContextHandle; +use text::glyph::GlyphId; +use style::computed_values::font_weight; +use platform::font_template::FontTemplateData; + +use core_foundation::base::CFIndex; +use core_foundation::data::CFData; +use core_foundation::string::UniChar; +use core_graphics::font::CGGlyph; +use core_graphics::geometry::CGRect; +use core_text::font::CTFont; +use core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors}; +use core_text::font_descriptor::{kCTFontDefaultOrientation}; + +use std::ptr; +use sync::Arc; + +pub struct FontTable { + data: CFData, +} + +// Noncopyable. +impl Drop for FontTable { + fn drop(&mut self) {} +} + +impl FontTable { + pub fn wrap(data: CFData) -> FontTable { + FontTable { data: data } + } +} + +impl FontTableMethods for FontTable { + fn with_buffer(&self, blk: |*const u8, uint|) { + blk(self.data.bytes().as_ptr(), self.data.len() as uint); + } +} + +pub struct FontHandle { + pub font_data: Arc<FontTemplateData>, + pub ctfont: CTFont, +} + +impl FontHandleMethods for FontHandle { + fn new_from_template(_fctx: &FontContextHandle, + template: Arc<FontTemplateData>, + pt_size: Option<f64>) + -> Result<FontHandle, ()> { + let size = match pt_size { + Some(s) => s, + None => 0.0 + }; + match template.ctfont { + Some(ref ctfont) => { + Ok(FontHandle { + font_data: template.clone(), + ctfont: ctfont.clone_with_font_size(size), + }) + } + None => { + Err(()) + } + } + } + + fn get_template(&self) -> Arc<FontTemplateData> { + self.font_data.clone() + } + + fn family_name(&self) -> String { + self.ctfont.family_name() + } + + fn face_name(&self) -> String { + self.ctfont.face_name() + } + + fn is_italic(&self) -> bool { + self.ctfont.symbolic_traits().is_italic() + } + + fn boldness(&self) -> font_weight::T { + // -1.0 to 1.0 + let normalized = self.ctfont.all_traits().normalized_weight(); + // 0.0 to 9.0 + let normalized = (normalized + 1.0) / 2.0 * 9.0; + if normalized < 1.0 { return font_weight::Weight100; } + if normalized < 2.0 { return font_weight::Weight200; } + if normalized < 3.0 { return font_weight::Weight300; } + if normalized < 4.0 { return font_weight::Weight400; } + if normalized < 5.0 { return font_weight::Weight500; } + if normalized < 6.0 { return font_weight::Weight600; } + if normalized < 7.0 { return font_weight::Weight700; } + if normalized < 8.0 { return font_weight::Weight800; } + return font_weight::Weight900; + } + + fn glyph_index(&self, codepoint: char) -> Option<GlyphId> { + let characters: [UniChar, ..1] = [codepoint as UniChar]; + let mut glyphs: [CGGlyph, ..1] = [0 as CGGlyph]; + let count: CFIndex = 1; + + let result = self.ctfont.get_glyphs_for_characters(&characters[0], + &mut glyphs[0], + count); + + if !result { + // No glyph for this character + return None; + } + + assert!(glyphs[0] != 0); // FIXME: error handling + return Some(glyphs[0] as GlyphId); + } + + fn glyph_h_kerning(&self, _first_glyph: GlyphId, _second_glyph: GlyphId) + -> FractionalPixel { + // TODO: Implement on mac + 0.0 + } + + fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> { + let glyphs = [glyph as CGGlyph]; + let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation, + &glyphs[0], + ptr::mut_null(), + 1); + Some(advance as FractionalPixel) + } + + fn get_metrics(&self) -> FontMetrics { + let bounding_rect: CGRect = self.ctfont.bounding_box(); + let ascent = self.ctfont.ascent() as f64; + let descent = self.ctfont.descent() as f64; + let em_size = Au::from_frac_px(self.ctfont.pt_size() as f64); + let leading = self.ctfont.leading() as f64; + + let scale = px_to_pt(self.ctfont.pt_size() as f64) / (ascent + descent); + let line_gap = (ascent + descent + leading + 0.5).floor(); + + let metrics = FontMetrics { + underline_size: Au::from_pt(self.ctfont.underline_thickness() as f64), + // TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table + // directly. + // + // see also: https://bugs.webkit.org/show_bug.cgi?id=16768 + // see also: https://bugreports.qt-project.org/browse/QTBUG-13364 + underline_offset: Au::from_pt(self.ctfont.underline_position() as f64), + strikeout_size: geometry::from_pt(0.0), // FIXME(Issue #942) + strikeout_offset: geometry::from_pt(0.0), // FIXME(Issue #942) + leading: Au::from_pt(leading), + x_height: Au::from_pt(self.ctfont.x_height() as f64), + em_size: em_size, + ascent: Au::from_pt(ascent * scale), + descent: Au::from_pt(descent * scale), + max_advance: Au::from_pt(bounding_rect.size.width as f64), + line_gap: Au::from_frac_px(line_gap), + }; + debug!("Font metrics (@{:f} pt): {:?}", self.ctfont.pt_size() as f64, metrics); + return metrics; + } + + fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> { + let result: Option<CFData> = self.ctfont.get_font_table(tag); + result.and_then(|data| { + Some(FontTable::wrap(data)) + }) + } +} + diff --git a/components/gfx/platform/macos/font_context.rs b/components/gfx/platform/macos/font_context.rs new file mode 100644 index 00000000000..94730641c3d --- /dev/null +++ b/components/gfx/platform/macos/font_context.rs @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#[deriving(Clone)] +pub struct FontContextHandle { + ctx: () +} + +#[deriving(Clone)] +impl FontContextHandle { + // this is a placeholder until NSFontManager or whatever is bound in here. + pub fn new() -> FontContextHandle { + FontContextHandle { ctx: () } + } +} diff --git a/components/gfx/platform/macos/font_list.rs b/components/gfx/platform/macos/font_list.rs new file mode 100644 index 00000000000..4ec319ec6b2 --- /dev/null +++ b/components/gfx/platform/macos/font_list.rs @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 core_foundation::base::TCFType; +use core_foundation::string::{CFString, CFStringRef}; +use core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef}; +use core_text; +use std::mem; + +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_string(); + callback(family_name); + } +} + +pub fn get_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<String> { + vec!("Arial Unicode MS".to_string(), "Arial".to_string()) +} diff --git a/components/gfx/platform/macos/font_template.rs b/components/gfx/platform/macos/font_template.rs new file mode 100644 index 00000000000..8641d491523 --- /dev/null +++ b/components/gfx/platform/macos/font_template.rs @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 core_graphics::data_provider::CGDataProvider; +use core_graphics::font::CGFont; +use core_text::font::CTFont; +use core_text; + +/// Platform specific font representation for mac. +/// The identifier is a PostScript font name. The +/// CTFont object is cached here for use by the +/// render functions that create CGFont references. +pub struct FontTemplateData { + pub ctfont: Option<CTFont>, + pub identifier: String, +} + +impl FontTemplateData { + pub fn new(identifier: &str, font_data: Option<Vec<u8>>) -> FontTemplateData { + let ctfont = match font_data { + Some(bytes) => { + let fontprov = CGDataProvider::from_buffer(bytes.as_slice()); + let cgfont_result = CGFont::from_data_provider(fontprov); + match cgfont_result { + Ok(cgfont) => Some(core_text::font::new_from_CGFont(&cgfont, 0.0)), + Err(_) => None + } + }, + None => { + Some(core_text::font::new_from_name(identifier.as_slice(), 0.0).unwrap()) + } + }; + + FontTemplateData { + ctfont: ctfont, + identifier: identifier.to_string(), + } + } +} |