aboutsummaryrefslogtreecommitdiffstats
path: root/components/gfx/platform/macos
diff options
context:
space:
mode:
Diffstat (limited to 'components/gfx/platform/macos')
-rw-r--r--components/gfx/platform/macos/font.rs185
-rw-r--r--components/gfx/platform/macos/font_context.rs16
-rw-r--r--components/gfx/platform/macos/font_list.rs37
-rw-r--r--components/gfx/platform/macos/font_template.rs40
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(),
+ }
+ }
+}