Add Font.shape_text(), and instantiate/reuse Shaper instance off of Font lazily. Shaper now takes a font, text, and glyph storage.

This commit is contained in:
Brian J. Burg 2012-10-29 14:54:47 -07:00
parent 09686c234f
commit 97b7b21452
3 changed files with 35 additions and 17 deletions

View file

@ -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<AzScaledFontRef>,
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<Au>);
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
}

View file

@ -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);

View file

@ -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;
}