diff --git a/src/rust-core-text b/src/rust-core-text index 7a42dc503a6..dab51768967 160000 --- a/src/rust-core-text +++ b/src/rust-core-text @@ -1 +1 @@ -Subproject commit 7a42dc503a6b4578f3957c69574e07175b2ca3c5 +Subproject commit dab5176896750f512410e24e33852ccaf13dbf08 diff --git a/src/servo-gfx/font.rs b/src/servo-gfx/font.rs index e126a1fb4c3..424db468ead 100644 --- a/src/servo-gfx/font.rs +++ b/src/servo-gfx/font.rs @@ -22,6 +22,7 @@ pub type FontHandle/& = quartz::font::QuartzFontHandle; pub type FontHandle/& = freetype::font::FreeTypeFontHandle; pub trait FontHandleMethods { + pure fn family_name() -> ~str; pure fn face_name() -> ~str; pure fn is_italic() -> bool; pure fn boldness() -> CSSFontWeight; @@ -30,6 +31,7 @@ pub trait FontHandleMethods { fn glyph_index(codepoint: char) -> Option; fn glyph_h_advance(GlyphIndex) -> Option; fn get_metrics() -> FontMetrics; + fn get_table_for_tag(FontTableTag) -> Option<~[u8]>; } // TODO: `new` should be part of trait FontHandleMethods @@ -52,6 +54,22 @@ impl FontHandle { // Used to abstract over the shaper's choice of fixed int representation. type FractionalPixel = float; +pub type FontTableTag = u32; + +trait FontTableTagConversions { + pub pure fn tag_to_str() -> ~str; +} + +impl FontTableTag : FontTableTagConversions { + pub pure fn tag_to_str() -> ~str unsafe { + let reversed = str::raw::from_buf_len(cast::transmute(&self), 4); + return str::from_chars([reversed.char_at(3), + reversed.char_at(2), + reversed.char_at(1), + reversed.char_at(0)]); + } +} + struct FontMetrics { underline_size: Au, underline_offset: Au, @@ -290,6 +308,17 @@ impl Font { shaper } + fn get_table_for_tag(tag: FontTableTag) -> Option<~[u8]> { + let result = self.handle.get_table_for_tag(tag); + let status = if result.is_some() { "Found" } else { "Didn't find" }; + + debug!("%s font table[%s] with family=%s, face=%s", + status, tag.tag_to_str(), + self.handle.family_name(), self.handle.face_name()); + + return move result; + } + priv fn get_azure_font() -> AzScaledFontRef { // fast path: we've already created the azure font resource match self.azure_font { diff --git a/src/servo-gfx/quartz/font.rs b/src/servo-gfx/quartz/font.rs index 6ab3986978a..3b97d4e6eaa 100644 --- a/src/servo-gfx/quartz/font.rs +++ b/src/servo-gfx/quartz/font.rs @@ -8,6 +8,7 @@ use gfx::font::{ CSSFontWeight, FontHandleMethods, FontMetrics, + FontTableTag, FontWeight100, FontWeight200, FontWeight300, @@ -23,7 +24,12 @@ use gfx::font::{ use text::glyph::GlyphIndex; use cf = core_foundation; -use cf::base::{CFIndex, CFRelease, CFTypeRef}; +use cf::base::{ + CFIndex, + CFRelease, + CFTypeRef +}; +use cf::data::CFData; use cf::string::UniChar; use cg = core_graphics; use cg::base::{CGFloat, CGAffineTransform}; @@ -175,5 +181,12 @@ pub impl QuartzFontHandle : FontHandleMethods { debug!("Font metrics (@%f pt): %?", self.ctfont.pt_size() as float, metrics); return metrics; } + + fn get_table_for_tag(tag: FontTableTag) -> Option<~[u8]> { + let result = self.ctfont.get_font_table(tag); + return option::chain(move result, |data| { + Some(data.copy_to_buf()) + }); + } } diff --git a/src/servo-gfx/text/harfbuzz/shaper.rs b/src/servo-gfx/text/harfbuzz/shaper.rs index 16944f05a52..e8529e24d9a 100644 --- a/src/servo-gfx/text/harfbuzz/shaper.rs +++ b/src/servo-gfx/text/harfbuzz/shaper.rs @@ -1,6 +1,14 @@ extern mod harfbuzz; -use geometry::Au; +use geom::Point2D; + +use gfx::au; +use gfx::{ + Au, + Font, +}; +use gfx::font::FontTableTag; + use glyph::{GlyphStore, GlyphIndex, GlyphData}; use servo_gfx_font::Font; @@ -20,17 +28,33 @@ use harfbuzz::bindgen::{hb_font_set_funcs, hb_font_funcs_set_glyph_h_advance_fun use harfbuzz::bindgen::{hb_font_funcs_set_glyph_func, hb_font_funcs_set_glyph_h_kerning_func}; use std::arc; +use harfbuzz::{HB_MEMORY_MODE_READONLY, + HB_DIRECTION_LTR}; +use harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t, hb_buffer_t, + hb_codepoint_t, hb_bool_t, hb_glyph_position_t, + hb_glyph_info_t, hb_var_int_t, hb_position_t, hb_tag_t}; +use harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy, + hb_face_create_for_tables, hb_face_destroy, + hb_font_create, hb_font_destroy, + hb_buffer_create, hb_buffer_destroy, + hb_buffer_add_utf8, hb_shape, + hb_buffer_get_glyph_infos, + hb_buffer_get_glyph_positions, + hb_font_set_ppem, hb_font_set_scale, + hb_buffer_set_direction, + hb_font_funcs_create, hb_font_funcs_destroy, + hb_font_set_funcs, + hb_font_funcs_set_glyph_h_advance_func, + hb_font_funcs_set_glyph_func, + hb_font_funcs_set_glyph_h_kerning_func}; + pub struct HarfbuzzShaper { - priv font: @Font, - priv hb_blob: *hb_blob_t, + font: @Font, priv hb_face: *hb_face_t, priv hb_font: *hb_font_t, priv hb_funcs: *hb_font_funcs_t, drop { - assert self.hb_blob.is_not_null(); - hb_blob_destroy(self.hb_blob); - assert self.hb_face.is_not_null(); hb_face_destroy(self.hb_face); @@ -44,16 +68,7 @@ pub struct HarfbuzzShaper { pub impl HarfbuzzShaper { static pub fn new(font: @Font) -> HarfbuzzShaper { - // TODO(Issue #92): font tables should be stored in Font object and cached per-task - let hb_blob: *hb_blob_t = vec::as_imm_buf(*(font).buf(), |buf: *u8, len: uint| { - hb_blob_create(buf as *c_char, - len as c_uint, - HB_MEMORY_MODE_READONLY, - null(), - null()) - }); - - let hb_face: *hb_face_t = hb_face_create(hb_blob, 0 as c_uint); + let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func, ptr::to_unsafe_ptr(font) as *c_void, ptr::null()); let hb_font: *hb_font_t = hb_font_create(hb_face); // Set points-per-em. if zero, performs no hinting in that direction. let pt_size = font.style.pt_size; @@ -75,7 +90,6 @@ pub impl HarfbuzzShaper { HarfbuzzShaper { font: font, - hb_blob: hb_blob, hb_face: hb_face, hb_font: hb_font, hb_funcs: hb_funcs, @@ -175,3 +189,22 @@ extern fn glyph_h_advance_func(_font: *hb_font_t, let advance = (*font).glyph_h_advance(glyph as GlyphIndex); HarfbuzzShaper::float_to_fixed(advance) } + +// Callback to get a font table out of a font. +extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t unsafe { + let font: *Font = user_data as *Font; + assert font.is_not_null(); + + // TODO(Issue #197): reuse font table data, which will change return type here. + // it will also require us to provide deletion callbacks to hb_blob_create, so + // that refcounts of shared blobs can be managed. + match (*font).get_table_for_tag(tag as FontTableTag) { + None => return ptr::null(), + Some(table_buffer) => { + let blob: *hb_blob_t = vec::as_imm_buf(table_buffer, |buf: *u8, len: uint| { + hb_blob_create(buf as *c_char, len as c_uint, HB_MEMORY_MODE_READONLY, null(), null()) + }); + return blob; + } + } +} \ No newline at end of file