mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +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 type FontHandle/& = freetype::font::FreeTypeFontHandle;
|
||||||
|
|
||||||
pub trait FontHandleMethods {
|
pub trait FontHandleMethods {
|
||||||
|
pure fn family_name() -> ~str;
|
||||||
pure fn face_name() -> ~str;
|
pure fn face_name() -> ~str;
|
||||||
pure fn is_italic() -> bool;
|
pure fn is_italic() -> bool;
|
||||||
pure fn boldness() -> CSSFontWeight;
|
pure fn boldness() -> CSSFontWeight;
|
||||||
|
@ -30,6 +31,7 @@ pub trait FontHandleMethods {
|
||||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
||||||
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
||||||
fn get_metrics() -> FontMetrics;
|
fn get_metrics() -> FontMetrics;
|
||||||
|
fn get_table_for_tag(FontTableTag) -> Option<~[u8]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: `new` should be part of trait FontHandleMethods
|
// 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.
|
// Used to abstract over the shaper's choice of fixed int representation.
|
||||||
type FractionalPixel = float;
|
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 {
|
struct FontMetrics {
|
||||||
underline_size: Au,
|
underline_size: Au,
|
||||||
underline_offset: Au,
|
underline_offset: Au,
|
||||||
|
@ -290,6 +308,17 @@ impl Font {
|
||||||
shaper
|
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 {
|
priv fn get_azure_font() -> AzScaledFontRef {
|
||||||
// fast path: we've already created the azure font resource
|
// fast path: we've already created the azure font resource
|
||||||
match self.azure_font {
|
match self.azure_font {
|
||||||
|
|
|
@ -8,6 +8,7 @@ use gfx::font::{
|
||||||
CSSFontWeight,
|
CSSFontWeight,
|
||||||
FontHandleMethods,
|
FontHandleMethods,
|
||||||
FontMetrics,
|
FontMetrics,
|
||||||
|
FontTableTag,
|
||||||
FontWeight100,
|
FontWeight100,
|
||||||
FontWeight200,
|
FontWeight200,
|
||||||
FontWeight300,
|
FontWeight300,
|
||||||
|
@ -23,7 +24,12 @@ use gfx::font::{
|
||||||
use text::glyph::GlyphIndex;
|
use text::glyph::GlyphIndex;
|
||||||
|
|
||||||
use cf = core_foundation;
|
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 cf::string::UniChar;
|
||||||
use cg = core_graphics;
|
use cg = core_graphics;
|
||||||
use cg::base::{CGFloat, CGAffineTransform};
|
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);
|
debug!("Font metrics (@%f pt): %?", self.ctfont.pt_size() as float, metrics);
|
||||||
return 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;
|
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 glyph::{GlyphStore, GlyphIndex, GlyphData};
|
||||||
use servo_gfx_font::Font;
|
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 harfbuzz::bindgen::{hb_font_funcs_set_glyph_func, hb_font_funcs_set_glyph_h_kerning_func};
|
||||||
use std::arc;
|
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 {
|
pub struct HarfbuzzShaper {
|
||||||
priv font: @Font,
|
font: @Font,
|
||||||
priv hb_blob: *hb_blob_t,
|
|
||||||
priv hb_face: *hb_face_t,
|
priv hb_face: *hb_face_t,
|
||||||
priv hb_font: *hb_font_t,
|
priv hb_font: *hb_font_t,
|
||||||
priv hb_funcs: *hb_font_funcs_t,
|
priv hb_funcs: *hb_font_funcs_t,
|
||||||
|
|
||||||
drop {
|
drop {
|
||||||
assert self.hb_blob.is_not_null();
|
|
||||||
hb_blob_destroy(self.hb_blob);
|
|
||||||
|
|
||||||
assert self.hb_face.is_not_null();
|
assert self.hb_face.is_not_null();
|
||||||
hb_face_destroy(self.hb_face);
|
hb_face_destroy(self.hb_face);
|
||||||
|
|
||||||
|
@ -44,16 +68,7 @@ pub struct HarfbuzzShaper {
|
||||||
|
|
||||||
pub impl HarfbuzzShaper {
|
pub impl HarfbuzzShaper {
|
||||||
static pub fn new(font: @Font) -> 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_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_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_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 = font.style.pt_size;
|
let pt_size = font.style.pt_size;
|
||||||
|
@ -75,7 +90,6 @@ pub impl HarfbuzzShaper {
|
||||||
|
|
||||||
HarfbuzzShaper {
|
HarfbuzzShaper {
|
||||||
font: font,
|
font: font,
|
||||||
hb_blob: hb_blob,
|
|
||||||
hb_face: hb_face,
|
hb_face: hb_face,
|
||||||
hb_font: hb_font,
|
hb_font: hb_font,
|
||||||
hb_funcs: hb_funcs,
|
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);
|
let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
|
||||||
HarfbuzzShaper::float_to_fixed(advance)
|
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