From 97b7b21452198cec0d3e827ba5ba4888d8888acc Mon Sep 17 00:00:00 2001 From: "Brian J. Burg" Date: Mon, 29 Oct 2012 14:54:47 -0700 Subject: [PATCH] Add Font.shape_text(), and instantiate/reuse Shaper instance off of Font lazily. Shaper now takes a font, text, and glyph storage. --- src/servo/text/font.rs | 26 +++++++++++++++++++++++++- src/servo/text/harfbuzz/shaper.rs | 19 +++++++++---------- src/servo/text/text_run.rs | 7 +------ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/servo/text/font.rs b/src/servo/text/font.rs index 06f4b09c78e..0f026821478 100644 --- a/src/servo/text/font.rs +++ b/src/servo/text/font.rs @@ -11,9 +11,10 @@ use gfx::render_context::RenderContext; use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; -use glyph::GlyphIndex; +use glyph::{GlyphStore, GlyphIndex}; use native_font::NativeFont; use servo_util::range::Range; +use shaper::Shaper; use text::text_run::TextRun; // Used to abstract over the shaper's choice of fixed int representation. @@ -83,6 +84,7 @@ struct Font { priv fontbuf: @~[u8], priv native_font: NativeFont, priv mut azure_font: Option, + priv mut shaper: Option<@Shaper>, style: FontStyle, metrics: FontMetrics, @@ -102,11 +104,25 @@ impl Font { fontbuf : fontbuf, native_font : move native_font, azure_font: None, + shaper: None, style: move style, metrics: move metrics, } } + priv fn get_shaper(&self) -> @Shaper { + // fast path: already created a shaper + match self.shaper { + Some(shaper) => { return shaper; }, + None => {} + } + + // XXX(Issue #163): wrong! use typedef (as commented out) + let shaper = @harfbuzz::shaper::HarfbuzzShaper::new(); + self.shaper = Some(shaper); + shaper + } + priv fn get_azure_font() -> AzScaledFontRef { use libc::{c_int, c_double}; use azure::{ @@ -207,6 +223,7 @@ impl Font { pub trait FontMethods { fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D); fn measure_text(&TextRun, Range) -> RunMetrics; + fn shape_text(&self, &str) -> GlyphStore; fn buf(&self) -> @~[u8]; // these are used to get glyphs and advances in the case that the @@ -301,6 +318,13 @@ pub impl Font : FontMethods { return metrics; } + fn shape_text(&self, text: &str) -> GlyphStore { + let store = GlyphStore(text.len()); + let shaper = self.get_shaper(); + shaper.shape_text(text, self, &store); + return move store; + } + fn buf(&self) -> @~[u8] { self.fontbuf } diff --git a/src/servo/text/harfbuzz/shaper.rs b/src/servo/text/harfbuzz/shaper.rs index 7ea385567d4..c3452e794d3 100644 --- a/src/servo/text/harfbuzz/shaper.rs +++ b/src/servo/text/harfbuzz/shaper.rs @@ -11,7 +11,6 @@ use libc::types::common::c99::int32_t; use libc::{c_uint, c_int, c_void, c_char}; use ptr::{null, to_unsafe_ptr, offset}; use std::arc; -use text_run::TextRun; use util::*; use harfbuzz::{HB_MEMORY_MODE_READONLY, @@ -59,13 +58,13 @@ pub impl HarfbuzzShaper { Calculate the layout metrics associated with a some given text when rendered in a specific font. */ - pub fn shape_textrun(run: &TextRun) { - debug!("shaping text '%s'", run.text); + pub fn shape_text(text: &str, font: &Font, glyphs: &GlyphStore) { + debug!("shaping text '%s'", text); // TODO(Issue #94): harfbuzz fonts and faces should be cached on the // Shaper object, which is owned by the Font instance. // TODO(Issue #92): font tables should be stored in Font object and cached per-task - let face_blob: *hb_blob_t = vec::as_imm_buf(*(run.font).fontbuf, |buf: *u8, len: uint| { + let face_blob: *hb_blob_t = vec::as_imm_buf(*(font).fontbuf, |buf: *u8, len: uint| { hb_blob_create(buf as *c_char, len as c_uint, HB_MEMORY_MODE_READONLY, @@ -77,7 +76,7 @@ pub impl HarfbuzzShaper { 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 = run.font.style.pt_size; + let pt_size = font.style.pt_size; hb_font_set_ppem(hb_font, pt_size as c_uint, pt_size as c_uint); // Set scaling. Note that this takes 16.16 fixed point. hb_font_set_scale(hb_font, float_to_fixed_hb(pt_size) as c_int, float_to_fixed_hb(pt_size) as c_int); @@ -87,7 +86,7 @@ pub impl HarfbuzzShaper { hb_font_funcs_set_glyph_h_advance_func(funcs, glyph_h_advance_func, null(), null()); unsafe { - let font_data: *c_void = core::ptr::addr_of(run.font) as *c_void; + let font_data: *c_void = core::ptr::addr_of(font) as *c_void; hb_font_set_funcs(hb_font, funcs, font_data, null()); }; @@ -95,12 +94,12 @@ pub impl HarfbuzzShaper { hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR); // Using as_buf because it never does a copy - we don't need the trailing null - str::as_buf(run.text, |ctext: *u8, _l: uint| { + str::as_buf(text, |ctext: *u8, _l: uint| { hb_buffer_add_utf8(hb_buffer, ctext as *c_char, - run.text.len() as c_int, + text.len() as c_int, 0 as c_uint, - run.text.len() as c_int); + text.len() as c_int); }); hb_shape(hb_font, hb_buffer, null(), 0 as c_uint); @@ -131,7 +130,7 @@ pub impl HarfbuzzShaper { i, codepoint, advance, offset); let data = GlyphData(codepoint, advance, offset, false, false, false); - run.glyphs.add_glyph_for_index(i, &data); + glyphs.add_glyph_for_index(i, &data); } /* unsafe */ } hb_buffer_destroy(hb_buffer); diff --git a/src/servo/text/text_run.rs b/src/servo/text/text_run.rs index c415ceca263..1d85a657272 100644 --- a/src/servo/text/text_run.rs +++ b/src/servo/text/text_run.rs @@ -42,17 +42,12 @@ impl TextRun { static fn new(font: @Font, text: ~str) -> TextRun { use shaper::Shaper; - let glyph_store = GlyphStore(text.len()); + let glyph_store = font.shape_text(text); let run = TextRun { text: move text, font: font, glyphs: move glyph_store, }; - - // XXX(Issue #163): wrong! use typedef (as commented out) - let shaper = harfbuzz::shaper::HarfbuzzShaper::new(); - // let shaper = Shaper::new(); - shaper.shape_textrun(&run); return move run; }