mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Add a fast path for shaping ASCII text
This commit is contained in:
parent
477258f11b
commit
5991afafa4
9 changed files with 218 additions and 25 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
use app_units::Au;
|
||||
use euclid::Point2D;
|
||||
use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontTableMethods, FontTableTag};
|
||||
use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontHandleMethods, 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,10 +34,12 @@ 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');
|
||||
|
@ -199,7 +201,14 @@ 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
|
||||
|
@ -241,6 +250,47 @@ 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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue