mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
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:
parent
09686c234f
commit
97b7b21452
3 changed files with 35 additions and 17 deletions
|
@ -11,9 +11,10 @@ use gfx::render_context::RenderContext;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use glyph::GlyphIndex;
|
use glyph::{GlyphStore, GlyphIndex};
|
||||||
use native_font::NativeFont;
|
use native_font::NativeFont;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
use shaper::Shaper;
|
||||||
use text::text_run::TextRun;
|
use text::text_run::TextRun;
|
||||||
|
|
||||||
// Used to abstract over the shaper's choice of fixed int representation.
|
// Used to abstract over the shaper's choice of fixed int representation.
|
||||||
|
@ -83,6 +84,7 @@ struct Font {
|
||||||
priv fontbuf: @~[u8],
|
priv fontbuf: @~[u8],
|
||||||
priv native_font: NativeFont,
|
priv native_font: NativeFont,
|
||||||
priv mut azure_font: Option<AzScaledFontRef>,
|
priv mut azure_font: Option<AzScaledFontRef>,
|
||||||
|
priv mut shaper: Option<@Shaper>,
|
||||||
style: FontStyle,
|
style: FontStyle,
|
||||||
metrics: FontMetrics,
|
metrics: FontMetrics,
|
||||||
|
|
||||||
|
@ -102,11 +104,25 @@ impl Font {
|
||||||
fontbuf : fontbuf,
|
fontbuf : fontbuf,
|
||||||
native_font : move native_font,
|
native_font : move native_font,
|
||||||
azure_font: None,
|
azure_font: None,
|
||||||
|
shaper: None,
|
||||||
style: move style,
|
style: move style,
|
||||||
metrics: move metrics,
|
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 {
|
priv fn get_azure_font() -> AzScaledFontRef {
|
||||||
use libc::{c_int, c_double};
|
use libc::{c_int, c_double};
|
||||||
use azure::{
|
use azure::{
|
||||||
|
@ -207,6 +223,7 @@ impl Font {
|
||||||
pub trait FontMethods {
|
pub trait FontMethods {
|
||||||
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>);
|
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>);
|
||||||
fn measure_text(&TextRun, Range) -> RunMetrics;
|
fn measure_text(&TextRun, Range) -> RunMetrics;
|
||||||
|
fn shape_text(&self, &str) -> GlyphStore;
|
||||||
|
|
||||||
fn buf(&self) -> @~[u8];
|
fn buf(&self) -> @~[u8];
|
||||||
// these are used to get glyphs and advances in the case that the
|
// these are used to get glyphs and advances in the case that the
|
||||||
|
@ -301,6 +318,13 @@ pub impl Font : FontMethods {
|
||||||
return metrics;
|
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] {
|
fn buf(&self) -> @~[u8] {
|
||||||
self.fontbuf
|
self.fontbuf
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ use libc::types::common::c99::int32_t;
|
||||||
use libc::{c_uint, c_int, c_void, c_char};
|
use libc::{c_uint, c_int, c_void, c_char};
|
||||||
use ptr::{null, to_unsafe_ptr, offset};
|
use ptr::{null, to_unsafe_ptr, offset};
|
||||||
use std::arc;
|
use std::arc;
|
||||||
use text_run::TextRun;
|
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
use harfbuzz::{HB_MEMORY_MODE_READONLY,
|
use harfbuzz::{HB_MEMORY_MODE_READONLY,
|
||||||
|
@ -59,13 +58,13 @@ pub impl HarfbuzzShaper {
|
||||||
Calculate the layout metrics associated with a some given text
|
Calculate the layout metrics associated with a some given text
|
||||||
when rendered in a specific font.
|
when rendered in a specific font.
|
||||||
*/
|
*/
|
||||||
pub fn shape_textrun(run: &TextRun) {
|
pub fn shape_text(text: &str, font: &Font, glyphs: &GlyphStore) {
|
||||||
debug!("shaping text '%s'", run.text);
|
debug!("shaping text '%s'", text);
|
||||||
|
|
||||||
// TODO(Issue #94): harfbuzz fonts and faces should be cached on the
|
// TODO(Issue #94): harfbuzz fonts and faces should be cached on the
|
||||||
// Shaper object, which is owned by the Font instance.
|
// Shaper object, which is owned by the Font instance.
|
||||||
// TODO(Issue #92): font tables should be stored in Font object and cached per-task
|
// 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,
|
hb_blob_create(buf as *c_char,
|
||||||
len as c_uint,
|
len as c_uint,
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
|
@ -77,7 +76,7 @@ pub impl HarfbuzzShaper {
|
||||||
let hb_font: *hb_font_t = hb_font_create(hb_face);
|
let hb_font: *hb_font_t = hb_font_create(hb_face);
|
||||||
|
|
||||||
// Set points-per-em. if zero, performs no hinting in that direction.
|
// 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);
|
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.
|
// 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);
|
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());
|
hb_font_funcs_set_glyph_h_advance_func(funcs, glyph_h_advance_func, null(), null());
|
||||||
|
|
||||||
unsafe {
|
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());
|
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);
|
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
|
// 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,
|
hb_buffer_add_utf8(hb_buffer,
|
||||||
ctext as *c_char,
|
ctext as *c_char,
|
||||||
run.text.len() as c_int,
|
text.len() as c_int,
|
||||||
0 as c_uint,
|
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);
|
hb_shape(hb_font, hb_buffer, null(), 0 as c_uint);
|
||||||
|
@ -131,7 +130,7 @@ pub impl HarfbuzzShaper {
|
||||||
i, codepoint, advance, offset);
|
i, codepoint, advance, offset);
|
||||||
|
|
||||||
let data = GlyphData(codepoint, advance, offset, false, false, false);
|
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 */ }
|
} /* unsafe */ }
|
||||||
|
|
||||||
hb_buffer_destroy(hb_buffer);
|
hb_buffer_destroy(hb_buffer);
|
||||||
|
|
|
@ -42,17 +42,12 @@ impl TextRun {
|
||||||
static fn new(font: @Font, text: ~str) -> TextRun {
|
static fn new(font: @Font, text: ~str) -> TextRun {
|
||||||
use shaper::Shaper;
|
use shaper::Shaper;
|
||||||
|
|
||||||
let glyph_store = GlyphStore(text.len());
|
let glyph_store = font.shape_text(text);
|
||||||
let run = TextRun {
|
let run = TextRun {
|
||||||
text: move text,
|
text: move text,
|
||||||
font: font,
|
font: font,
|
||||||
glyphs: move glyph_store,
|
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;
|
return move run;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue