mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Implement lazy font table loading from FontHandles for CoreText. Tracked by #195.
This commit is contained in:
parent
a34f67d64b
commit
7a3a79dc36
4 changed files with 94 additions and 19 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 7a42dc503a6b4578f3957c69574e07175b2ca3c5
|
||||
Subproject commit dab5176896750f512410e24e33852ccaf13dbf08
|
|
@ -22,6 +22,7 @@ pub type FontHandle/& = quartz::font::QuartzFontHandle;
|
|||
pub type FontHandle/& = freetype::font::FreeTypeFontHandle;
|
||||
|
||||
pub trait FontHandleMethods {
|
||||
pure fn family_name() -> ~str;
|
||||
pure fn face_name() -> ~str;
|
||||
pure fn is_italic() -> bool;
|
||||
pure fn boldness() -> CSSFontWeight;
|
||||
|
@ -30,6 +31,7 @@ pub trait FontHandleMethods {
|
|||
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
||||
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
||||
fn get_metrics() -> FontMetrics;
|
||||
fn get_table_for_tag(FontTableTag) -> Option<~[u8]>;
|
||||
}
|
||||
|
||||
// TODO: `new` should be part of trait FontHandleMethods
|
||||
|
@ -52,6 +54,22 @@ impl FontHandle {
|
|||
// Used to abstract over the shaper's choice of fixed int representation.
|
||||
type FractionalPixel = float;
|
||||
|
||||
pub type FontTableTag = u32;
|
||||
|
||||
trait FontTableTagConversions {
|
||||
pub pure fn tag_to_str() -> ~str;
|
||||
}
|
||||
|
||||
impl FontTableTag : FontTableTagConversions {
|
||||
pub pure fn tag_to_str() -> ~str unsafe {
|
||||
let reversed = str::raw::from_buf_len(cast::transmute(&self), 4);
|
||||
return str::from_chars([reversed.char_at(3),
|
||||
reversed.char_at(2),
|
||||
reversed.char_at(1),
|
||||
reversed.char_at(0)]);
|
||||
}
|
||||
}
|
||||
|
||||
struct FontMetrics {
|
||||
underline_size: Au,
|
||||
underline_offset: Au,
|
||||
|
@ -290,6 +308,17 @@ impl Font {
|
|||
shaper
|
||||
}
|
||||
|
||||
fn get_table_for_tag(tag: FontTableTag) -> Option<~[u8]> {
|
||||
let result = self.handle.get_table_for_tag(tag);
|
||||
let status = if result.is_some() { "Found" } else { "Didn't find" };
|
||||
|
||||
debug!("%s font table[%s] with family=%s, face=%s",
|
||||
status, tag.tag_to_str(),
|
||||
self.handle.family_name(), self.handle.face_name());
|
||||
|
||||
return move result;
|
||||
}
|
||||
|
||||
priv fn get_azure_font() -> AzScaledFontRef {
|
||||
// fast path: we've already created the azure font resource
|
||||
match self.azure_font {
|
||||
|
|
|
@ -8,6 +8,7 @@ use gfx::font::{
|
|||
CSSFontWeight,
|
||||
FontHandleMethods,
|
||||
FontMetrics,
|
||||
FontTableTag,
|
||||
FontWeight100,
|
||||
FontWeight200,
|
||||
FontWeight300,
|
||||
|
@ -23,7 +24,12 @@ use gfx::font::{
|
|||
use text::glyph::GlyphIndex;
|
||||
|
||||
use cf = core_foundation;
|
||||
use cf::base::{CFIndex, CFRelease, CFTypeRef};
|
||||
use cf::base::{
|
||||
CFIndex,
|
||||
CFRelease,
|
||||
CFTypeRef
|
||||
};
|
||||
use cf::data::CFData;
|
||||
use cf::string::UniChar;
|
||||
use cg = core_graphics;
|
||||
use cg::base::{CGFloat, CGAffineTransform};
|
||||
|
@ -175,5 +181,12 @@ pub impl QuartzFontHandle : FontHandleMethods {
|
|||
debug!("Font metrics (@%f pt): %?", self.ctfont.pt_size() as float, metrics);
|
||||
return metrics;
|
||||
}
|
||||
|
||||
fn get_table_for_tag(tag: FontTableTag) -> Option<~[u8]> {
|
||||
let result = self.ctfont.get_font_table(tag);
|
||||
return option::chain(move result, |data| {
|
||||
Some(data.copy_to_buf())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
extern mod harfbuzz;
|
||||
|
||||
use geometry::Au;
|
||||
use geom::Point2D;
|
||||
|
||||
use gfx::au;
|
||||
use gfx::{
|
||||
Au,
|
||||
Font,
|
||||
};
|
||||
use gfx::font::FontTableTag;
|
||||
|
||||
use glyph::{GlyphStore, GlyphIndex, GlyphData};
|
||||
use servo_gfx_font::Font;
|
||||
|
||||
|
@ -20,17 +28,33 @@ use harfbuzz::bindgen::{hb_font_set_funcs, hb_font_funcs_set_glyph_h_advance_fun
|
|||
use harfbuzz::bindgen::{hb_font_funcs_set_glyph_func, hb_font_funcs_set_glyph_h_kerning_func};
|
||||
use std::arc;
|
||||
|
||||
use harfbuzz::{HB_MEMORY_MODE_READONLY,
|
||||
HB_DIRECTION_LTR};
|
||||
use harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t, hb_buffer_t,
|
||||
hb_codepoint_t, hb_bool_t, hb_glyph_position_t,
|
||||
hb_glyph_info_t, hb_var_int_t, hb_position_t, hb_tag_t};
|
||||
use harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
|
||||
hb_face_create_for_tables, hb_face_destroy,
|
||||
hb_font_create, hb_font_destroy,
|
||||
hb_buffer_create, hb_buffer_destroy,
|
||||
hb_buffer_add_utf8, hb_shape,
|
||||
hb_buffer_get_glyph_infos,
|
||||
hb_buffer_get_glyph_positions,
|
||||
hb_font_set_ppem, hb_font_set_scale,
|
||||
hb_buffer_set_direction,
|
||||
hb_font_funcs_create, hb_font_funcs_destroy,
|
||||
hb_font_set_funcs,
|
||||
hb_font_funcs_set_glyph_h_advance_func,
|
||||
hb_font_funcs_set_glyph_func,
|
||||
hb_font_funcs_set_glyph_h_kerning_func};
|
||||
|
||||
pub struct HarfbuzzShaper {
|
||||
priv font: @Font,
|
||||
priv hb_blob: *hb_blob_t,
|
||||
font: @Font,
|
||||
priv hb_face: *hb_face_t,
|
||||
priv hb_font: *hb_font_t,
|
||||
priv hb_funcs: *hb_font_funcs_t,
|
||||
|
||||
drop {
|
||||
assert self.hb_blob.is_not_null();
|
||||
hb_blob_destroy(self.hb_blob);
|
||||
|
||||
assert self.hb_face.is_not_null();
|
||||
hb_face_destroy(self.hb_face);
|
||||
|
||||
|
@ -44,16 +68,7 @@ pub struct HarfbuzzShaper {
|
|||
|
||||
pub impl HarfbuzzShaper {
|
||||
static pub fn new(font: @Font) -> HarfbuzzShaper {
|
||||
// TODO(Issue #92): font tables should be stored in Font object and cached per-task
|
||||
let hb_blob: *hb_blob_t = vec::as_imm_buf(*(font).buf(), |buf: *u8, len: uint| {
|
||||
hb_blob_create(buf as *c_char,
|
||||
len as c_uint,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
null(),
|
||||
null())
|
||||
});
|
||||
|
||||
let hb_face: *hb_face_t = hb_face_create(hb_blob, 0 as c_uint);
|
||||
let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func, ptr::to_unsafe_ptr(font) as *c_void, ptr::null());
|
||||
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 = font.style.pt_size;
|
||||
|
@ -75,7 +90,6 @@ pub impl HarfbuzzShaper {
|
|||
|
||||
HarfbuzzShaper {
|
||||
font: font,
|
||||
hb_blob: hb_blob,
|
||||
hb_face: hb_face,
|
||||
hb_font: hb_font,
|
||||
hb_funcs: hb_funcs,
|
||||
|
@ -175,3 +189,22 @@ extern fn glyph_h_advance_func(_font: *hb_font_t,
|
|||
let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
|
||||
HarfbuzzShaper::float_to_fixed(advance)
|
||||
}
|
||||
|
||||
// Callback to get a font table out of a font.
|
||||
extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t unsafe {
|
||||
let font: *Font = user_data as *Font;
|
||||
assert font.is_not_null();
|
||||
|
||||
// TODO(Issue #197): reuse font table data, which will change return type here.
|
||||
// it will also require us to provide deletion callbacks to hb_blob_create, so
|
||||
// that refcounts of shared blobs can be managed.
|
||||
match (*font).get_table_for_tag(tag as FontTableTag) {
|
||||
None => return ptr::null(),
|
||||
Some(table_buffer) => {
|
||||
let blob: *hb_blob_t = vec::as_imm_buf(table_buffer, |buf: *u8, len: uint| {
|
||||
hb_blob_create(buf as *c_char, len as c_uint, HB_MEMORY_MODE_READONLY, null(), null())
|
||||
});
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue