mirror of
https://github.com/servo/servo.git
synced 2025-06-24 17:14:33 +01:00
Cache AzScaledFontRef inside of Font instances. Fixes #83.
This commit is contained in:
parent
a06b573e74
commit
eb0942593e
2 changed files with 131 additions and 110 deletions
|
@ -2,6 +2,10 @@ pub use font_cache::FontCache;
|
|||
|
||||
use au = gfx::geometry;
|
||||
use au::Au;
|
||||
use azure::{
|
||||
AzFloat,
|
||||
AzScaledFontRef,
|
||||
};
|
||||
use core::dvec::DVec;
|
||||
use gfx::render_context::RenderContext;
|
||||
use geom::point::Point2D;
|
||||
|
@ -20,11 +24,29 @@ A font handle. Layout can use this to calculate glyph metrics
|
|||
and the renderer can use it to render text.
|
||||
*/
|
||||
struct Font {
|
||||
// TODO: is this actually needed? -bjb
|
||||
// A back reference to keep the library alive
|
||||
lib: @FontCache,
|
||||
fontbuf: @~[u8],
|
||||
native_font: NativeFont,
|
||||
priv lib: @FontCache,
|
||||
priv fontbuf: @~[u8],
|
||||
priv native_font: NativeFont,
|
||||
priv mut azure_font: Option<AzScaledFontRef>,
|
||||
metrics: FontMetrics,
|
||||
|
||||
drop {
|
||||
use azure::bindgen::AzReleaseScaledFont;
|
||||
do (copy self.azure_font).iter |fontref| { AzReleaseScaledFont(*fontref); }
|
||||
}
|
||||
}
|
||||
|
||||
struct FontMetrics {
|
||||
underline_size: Au,
|
||||
underline_offset: Au,
|
||||
leading: Au,
|
||||
x_height: Au,
|
||||
em_size: Au,
|
||||
ascent: Au,
|
||||
descent: Au,
|
||||
max_advance: Au
|
||||
}
|
||||
|
||||
struct RunMetrics {
|
||||
|
@ -39,6 +61,109 @@ struct RunMetrics {
|
|||
bounding_box: Rect<Au>
|
||||
}
|
||||
|
||||
impl Font {
|
||||
// TODO: who should own fontbuf?
|
||||
static pub fn new(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
|
||||
let metrics = native_font.get_metrics();
|
||||
|
||||
Font {
|
||||
lib: lib,
|
||||
fontbuf : fontbuf,
|
||||
metrics: move metrics,
|
||||
native_font : move native_font,
|
||||
azure_font: None
|
||||
}
|
||||
}
|
||||
|
||||
priv fn get_azure_font() -> AzScaledFontRef {
|
||||
use libc::{c_int, c_double};
|
||||
use azure::{
|
||||
AzNativeFont,
|
||||
AZ_NATIVE_FONT_CAIRO_FONT_FACE
|
||||
};
|
||||
use azure::bindgen::AzCreateScaledFontWithCairo;
|
||||
use azure::cairo;
|
||||
use cairo::{cairo_font_face_t, cairo_scaled_font_t};
|
||||
use cairo::bindgen::cairo_scaled_font_destroy;
|
||||
|
||||
// fast path: we've already created the azure font resource
|
||||
match self.azure_font {
|
||||
Some(azfont) => { return azfont; },
|
||||
None => {}
|
||||
}
|
||||
|
||||
let nfont: AzNativeFont = {
|
||||
mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
|
||||
mFont: ptr::null()
|
||||
};
|
||||
|
||||
// TODO(Issue #64): we should be able to remove cairo stepping
|
||||
// stones and manual memory management, and put them inside of
|
||||
// azure_hl.rs and elsewhere instead.
|
||||
let cfont = get_cairo_font(&self);
|
||||
let azfont = AzCreateScaledFontWithCairo(ptr::to_unsafe_ptr(&nfont), 1f as AzFloat, cfont);
|
||||
assert azfont.is_not_null();
|
||||
cairo_scaled_font_destroy(cfont);
|
||||
|
||||
self.azure_font = Some(azfont);
|
||||
return azfont;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||
use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face};
|
||||
|
||||
let ftface = font.native_font.face;
|
||||
let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int);
|
||||
// FIXME: error handling
|
||||
return cface;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||
use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;
|
||||
|
||||
let cgfont = font.native_font.cgfont;
|
||||
let face = cairo_quartz_font_face_create_for_cgfont(cgfont);
|
||||
// FIXME: error handling
|
||||
return face;
|
||||
}
|
||||
|
||||
fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t {
|
||||
use cairo::cairo_matrix_t;
|
||||
use cairo::bindgen::{cairo_matrix_init_identity,
|
||||
cairo_matrix_scale,
|
||||
cairo_font_options_create,
|
||||
cairo_scaled_font_create,
|
||||
cairo_font_options_destroy,
|
||||
cairo_font_face_destroy};
|
||||
|
||||
// FIXME: error handling
|
||||
|
||||
let face = get_cairo_face(font);
|
||||
|
||||
let idmatrix: cairo_matrix_t = {
|
||||
xx: 0 as c_double,
|
||||
yx: 0 as c_double,
|
||||
xy: 0 as c_double,
|
||||
yy: 0 as c_double,
|
||||
x0: 0 as c_double,
|
||||
y0: 0 as c_double
|
||||
};
|
||||
cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));
|
||||
|
||||
let fontmatrix = idmatrix;
|
||||
cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), 21f as c_double, 21f as c_double);
|
||||
let options = cairo_font_options_create();
|
||||
let cfont = cairo_scaled_font_create(face, ptr::to_unsafe_ptr(&fontmatrix),
|
||||
ptr::to_unsafe_ptr(&idmatrix), options);
|
||||
cairo_font_options_destroy(options);
|
||||
cairo_font_face_destroy(face);
|
||||
|
||||
return cfont;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public API
|
||||
pub trait FontMethods {
|
||||
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>);
|
||||
|
@ -55,34 +180,14 @@ pub impl Font : FontMethods {
|
|||
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>) {
|
||||
use libc::types::common::c99::{uint16_t, uint32_t};
|
||||
use azure::{AzDrawOptions,
|
||||
AzFloat,
|
||||
AzGlyph,
|
||||
AzGlyphBuffer,
|
||||
AzNativeFont,
|
||||
AZ_NATIVE_FONT_CAIRO_FONT_FACE};
|
||||
AzGlyphBuffer};
|
||||
use azure::bindgen::{AzCreateColorPattern,
|
||||
AzCreateScaledFontWithCairo,
|
||||
AzDrawTargetFillGlyphs,
|
||||
AzReleaseScaledFont,
|
||||
AzReleaseColorPattern};
|
||||
use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t};
|
||||
use azure::cairo::bindgen::cairo_scaled_font_destroy;
|
||||
|
||||
let target = rctx.get_draw_target();
|
||||
// TODO(Issue #83): these should be cached on this Font, not created anew
|
||||
let nfont: AzNativeFont = {
|
||||
mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
|
||||
mFont: ptr::null()
|
||||
};
|
||||
|
||||
// TODO(Issue #64): we should be able to remove cairo stepping
|
||||
// stones and manual memory management, and put them inside of
|
||||
// azure_hl.rs and elsewhere instead.
|
||||
let cfont = get_cairo_font(&self);
|
||||
let azfont = AzCreateScaledFontWithCairo(ptr::to_unsafe_ptr(&nfont), 1f as AzFloat, cfont);
|
||||
assert azfont.is_not_null();
|
||||
cairo_scaled_font_destroy(cfont);
|
||||
|
||||
let azfont = self.get_azure_font();
|
||||
let color = {
|
||||
r: 0f as AzFloat,
|
||||
g: 0f as AzFloat,
|
||||
|
@ -128,67 +233,6 @@ pub impl Font : FontMethods {
|
|||
ptr::to_unsafe_ptr(&glyphbuf), pattern, ptr::to_unsafe_ptr(&options), ptr::null());
|
||||
|
||||
AzReleaseColorPattern(pattern);
|
||||
AzReleaseScaledFont(azfont);
|
||||
|
||||
// TODO: these should be private instance methods
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||
|
||||
use libc::c_int;
|
||||
use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face};
|
||||
|
||||
let ftface = font.native_font.face;
|
||||
let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int);
|
||||
// FIXME: error handling
|
||||
return cface;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||
use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;
|
||||
|
||||
let cgfont = font.native_font.cgfont;
|
||||
let face = cairo_quartz_font_face_create_for_cgfont(cgfont);
|
||||
// FIXME: error handling
|
||||
return face;
|
||||
}
|
||||
|
||||
fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t {
|
||||
|
||||
use libc::c_double;
|
||||
use azure::cairo;
|
||||
use cairo::cairo_matrix_t;
|
||||
use cairo::bindgen::{cairo_matrix_init_identity,
|
||||
cairo_matrix_scale,
|
||||
cairo_font_options_create,
|
||||
cairo_scaled_font_create,
|
||||
cairo_font_options_destroy,
|
||||
cairo_font_face_destroy};
|
||||
|
||||
// FIXME: error handling
|
||||
|
||||
let face = get_cairo_face(font);
|
||||
|
||||
let idmatrix: cairo_matrix_t = {
|
||||
xx: 0 as c_double,
|
||||
yx: 0 as c_double,
|
||||
xy: 0 as c_double,
|
||||
yy: 0 as c_double,
|
||||
x0: 0 as c_double,
|
||||
y0: 0 as c_double
|
||||
};
|
||||
cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));
|
||||
|
||||
let fontmatrix = idmatrix;
|
||||
cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), 21f as c_double, 21f as c_double);
|
||||
let options = cairo_font_options_create();
|
||||
let cfont = cairo_scaled_font_create(face, ptr::to_unsafe_ptr(&fontmatrix),
|
||||
ptr::to_unsafe_ptr(&idmatrix), options);
|
||||
cairo_font_options_destroy(options);
|
||||
cairo_font_face_destroy(face);
|
||||
|
||||
return cfont;
|
||||
}
|
||||
}
|
||||
|
||||
fn measure_text(run: &TextRun, range: Range) -> RunMetrics {
|
||||
|
@ -234,29 +278,6 @@ pub impl Font : FontMethods {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: who should own fontbuf?
|
||||
fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
|
||||
let metrics = native_font.get_metrics();
|
||||
|
||||
Font {
|
||||
lib: lib,
|
||||
fontbuf : fontbuf,
|
||||
metrics: move metrics,
|
||||
native_font : move native_font,
|
||||
}
|
||||
}
|
||||
|
||||
struct FontMetrics {
|
||||
underline_size: Au,
|
||||
underline_offset: Au,
|
||||
leading: Au,
|
||||
x_height: Au,
|
||||
em_size: Au,
|
||||
ascent: Au,
|
||||
descent: Au,
|
||||
max_advance: Au
|
||||
}
|
||||
|
||||
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
|
||||
|
||||
fn test_font_bin() -> ~[u8] {
|
||||
|
|
|
@ -44,7 +44,7 @@ fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<
|
|||
} else {
|
||||
return Err(native_font.get_err());
|
||||
};
|
||||
return Ok(@Font(lib, font_bin, move native_font));
|
||||
return Ok(@Font::new(lib, font_bin, move native_font));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue