Don't create HarfBuzz shaper if it isn't used

Move the fast shaping code out of the HarfBuzz shaper, and initialize the
shaper lazily to avoid creating any HarfBuzz objects.
This commit is contained in:
Matt Brubeck 2016-05-23 10:11:35 -07:00
parent 7bf6a41553
commit 43e12f7eba
2 changed files with 67 additions and 79 deletions

View file

@ -4,7 +4,7 @@
use app_units::Au;
use euclid::Point2D;
use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontHandleMethods, FontTableMethods, FontTableTag};
use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontTableMethods, FontTableTag};
use font::{IGNORE_LIGATURES_SHAPING_FLAG, KERN, RTL_FLAG, ShapingOptions};
use harfbuzz::{HB_DIRECTION_LTR, HB_DIRECTION_RTL, HB_MEMORY_MODE_READONLY};
use harfbuzz::{hb_blob_create, hb_face_create_for_tables};
@ -34,12 +34,10 @@ use harfbuzz::{hb_glyph_position_t};
use harfbuzz::{hb_position_t, hb_tag_t};
use libc::{c_char, c_int, c_uint, c_void};
use platform::font::FontTable;
use std::ascii::AsciiExt;
use std::{char, cmp, ptr};
use text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore};
use text::shaping::ShaperMethods;
use text::util::{fixed_to_float, float_to_fixed, is_bidi_control};
use unicode_script::Script;
const NO_GLYPH: i32 = -1;
const LIGA: u32 = ot_tag!('l', 'i', 'g', 'a');
@ -130,7 +128,7 @@ impl ShapedGlyphData {
pub struct Shaper {
hb_face: *mut hb_face_t,
hb_font: *mut hb_font_t,
font: *mut Font,
font: *const Font,
}
impl Drop for Shaper {
@ -146,16 +144,16 @@ impl Drop for Shaper {
}
impl Shaper {
pub fn new(font: &mut Font) -> Shaper {
pub fn new(font: *const Font) -> Shaper {
unsafe {
let hb_face: *mut hb_face_t =
hb_face_create_for_tables(Some(font_table_func),
font as *mut _ as *mut c_void,
font as *const c_void as *mut c_void,
None);
let hb_font: *mut hb_font_t = hb_font_create(hb_face);
// Set points-per-em. if zero, performs no hinting in that direction.
let pt_size = font.actual_pt_size.to_f64_px();
let pt_size = (*font).actual_pt_size.to_f64_px();
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.
@ -187,14 +185,7 @@ impl ShaperMethods for Shaper {
/// Calculate the layout metrics associated with the given text when painted in a specific
/// font.
fn shape_text(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore) {
if self.can_use_fast_path(text, options) {
debug!("shape_text: Using ASCII fast path.");
self.shape_text_fast(text, options, glyphs);
return;
}
unsafe {
debug!("shape_text: Using Harfbuzz.");
let hb_buffer: *mut hb_buffer_t = hb_buffer_create();
hb_buffer_set_direction(hb_buffer, if options.flags.contains(RTL_FLAG) {
HB_DIRECTION_RTL
@ -236,47 +227,6 @@ impl ShaperMethods for Shaper {
}
impl Shaper {
fn can_use_fast_path(&self, text: &str, options: &ShapingOptions) -> bool {
let font = self.font_and_shaping_options.font;
options.script == Script::Latin &&
!options.flags.contains(RTL_FLAG) &&
unsafe { (*font).handle.can_do_fast_shaping() } &&
text.is_ascii()
}
/// Fast path for ASCII text that only needs simple horizontal LTR kerning.
fn shape_text_fast(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore) {
let font = unsafe { &mut *self.font_and_shaping_options.font };
let mut prev_glyph_id = None;
for (i, byte) in text.bytes().enumerate() {
let character = byte as char;
let glyph_id = match font.glyph_index(character) {
Some(id) => id,
None => continue,
};
let mut advance = Au::from_f64_px(font.glyph_h_advance(glyph_id));
if character == ' ' {
advance += options.word_spacing;
}
if let Some(letter_spacing) = options.letter_spacing {
advance += letter_spacing;
}
let offset = prev_glyph_id.map(|prev| {
let h_kerning = Au::from_f64_px(font.glyph_h_kerning(prev, glyph_id));
advance += h_kerning;
Point2D::new(h_kerning, Au(0))
});
let glyph = GlyphData::new(glyph_id, advance, offset, true, true);
glyphs.add_glyph_for_byte_index(ByteIndex(i as isize), character, &glyph);
prev_glyph_id = Some(glyph_id);
}
glyphs.finalize_changes();
}
fn save_glyph_results(&self,
text: &str,
options: &ShapingOptions,
@ -507,7 +457,7 @@ extern fn glyph_h_advance_func(_: *mut hb_font_t,
}
}
fn glyph_space_advance(font: *mut Font) -> (hb_codepoint_t, f64) {
fn glyph_space_advance(font: *const Font) -> (hb_codepoint_t, f64) {
let space_unicode = ' ';
let space_glyph: hb_codepoint_t;
match unsafe { (*font).glyph_index(space_unicode) } {