Skip to content

Commit

Permalink
Create FontStyle, FontFaceProperties, and hook up (hardcoded) adjusta…
Browse files Browse the repository at this point in the history
…ble font sizes. Also ripped out some native font tests that won't make sense with font machinery refactor.
  • Loading branch information
Brian J. Burg committed Oct 27, 2012
1 parent 2e5afb7 commit 9f94b54
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 125 deletions.
96 changes: 68 additions & 28 deletions src/servo/text/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@ use text::text_run::TextRun;
// Used to abstract over the shaper's choice of fixed int representation.
type FractionalPixel = float;

/**
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
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,
Expand All @@ -49,29 +30,80 @@ struct FontMetrics {
max_advance: Au
}

// TODO: use enum from CSS bindings
enum CSSFontWeight {
FontWeight100,
FontWeight200,
FontWeight300,
FontWeight400,
FontWeight500,
FontWeight600,
FontWeight700,
FontWeight800,
FontWeight900,
}

struct FontStyle {
pt_size: float,
weight: CSSFontWeight,
italic: bool,
oblique: bool,
}

struct FontFaceProperties {
family_name: @str,
face_name: ~str,
priv weight: u16,
priv italic: bool,
}

impl FontFaceProperties {
pure fn is_bold() -> bool { self.weight >= (500 as u16) }
pure fn is_italic() -> bool { self.italic }
}

struct RunMetrics {
// may be negative due to negative width
// may be negative due to negative width (i.e., kerning of '.' in 'P.T.')
advance_width: Au,

ascent: Au, // nonzero
descent: Au, // nonzero

// this bounding box is relative to the left origin baseline.
// so, bounding_box.position.y = -ascent
bounding_box: Rect<Au>
}

/**
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
priv lib: @FontCache,
priv fontbuf: @~[u8],
priv native_font: NativeFont,
priv mut azure_font: Option<AzScaledFontRef>,
style: FontStyle,
metrics: FontMetrics,

drop {
use azure::bindgen::AzReleaseScaledFont;
do (copy self.azure_font).iter |fontref| { AzReleaseScaledFont(*fontref); }
}
}

impl Font {
// TODO: who should own fontbuf?
static fn new(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
static fn new(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont, style: FontStyle) -> Font {
let metrics = native_font.get_metrics();

Font {
lib: lib,
fontbuf : fontbuf,
metrics: move metrics,
native_font : move native_font,
azure_font: None
azure_font: None,
style: move style,
metrics: move metrics,
}
}

Expand Down Expand Up @@ -100,13 +132,17 @@ impl Font {
// stones and manual memory management, and put them inside of
// azure_hl.rs and elsewhere instead.
let cfont = get_cairo_font(&self);
// TODO: This should probably not even use cairo
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;

// TODO: these cairo-related things should be in rust-cairo.
// creating a cairo font/face from a native font resource
// should be part of the NativeFont API, not exposed here.
#[cfg(target_os = "linux")]
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
use cairo::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face};
Expand Down Expand Up @@ -151,10 +187,14 @@ impl Font {
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);
cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix),
font.style.pt_size as c_double,
font.style.pt_size 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);
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);

Expand Down
16 changes: 13 additions & 3 deletions src/servo/text/font_cache.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use font::{Font, test_font_bin};
use font::{Font,
FontStyle,
FontWeight300,
test_font_bin};

struct FontCache {
native_lib: native::NativeFontCache,
Expand Down Expand Up @@ -37,13 +40,20 @@ fn FontCache() -> @FontCache {

fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> {
let font_bin = @test_font_bin();
let native_font = native_font::create(native_lib, font_bin);
let dummy_style = FontStyle {
pt_size: 40f,
weight: FontWeight300,
italic: false,
oblique: false
};
let native_font = native_font::create(native_lib, font_bin, dummy_style.pt_size);
let native_font = if native_font.is_ok() {
result::unwrap(move native_font)
} else {
return Err(native_font.get_err());
};
return Ok(@Font::new(lib, font_bin, move native_font));

return Ok(@Font::new(lib, font_bin, move native_font, move dummy_style));
}

#[cfg(target_os = "linux")]
Expand Down
54 changes: 5 additions & 49 deletions src/servo/text/native_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,13 @@ pub type NativeFont/& = quartz_native_font::QuartzNativeFont;
#[cfg(target_os = "linux")]
pub type NativeFont/& = ft_native_font::FreeTypeNativeFont;

// TODO: this should be part of trait NativeFont
#[cfg(target_os = "macos")]
pub fn create(_native_lib: &NativeFontCache, buf: @~[u8]) -> Result<NativeFont, ()> {
quartz_native_font::create(buf)
pub fn create(native_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> {
quartz_native_font::create(native_lib, buf, pt_size)
}

#[cfg(target_os = "linux")]
pub fn create(native_lib: &NativeFontCache, buf: @~[u8]) -> Result<NativeFont, ()> {
ft_native_font::create(native_lib, buf)
}

#[cfg(target_os = "macos")]
pub fn with_test_native_font(f: fn@(nf: &NativeFont)) {
quartz_native_font::with_test_native_font(f);
}

#[cfg(target_os = "linux")]
pub fn with_test_native_font(f: fn@(nf: &NativeFont)) {
ft_native_font::with_test_native_font(f);
}

#[test]
fn should_get_glyph_indexes() {
with_test_native_font(|font| {
let idx = font.glyph_index('w');
assert idx == Some(40u as GlyphIndex);
})
}

#[test]
fn should_return_none_glyph_index_for_bad_codepoints() {
with_test_native_font(|font| {
let idx = font.glyph_index(0 as char);
assert idx == None;
})
}

#[test]
#[ignore]
fn should_get_glyph_h_advance() {
with_test_native_font(|font| {
let adv = font.glyph_h_advance(40u as GlyphIndex);
// TODO: add correct advances; these are old
assert adv == Some(15f);
})
}

#[test]
#[ignore]
fn should_return_none_glyph_h_advance_for_bad_codepoints() {
with_test_native_font(|font| {
let adv = font.glyph_h_advance(-1 as GlyphIndex);
assert adv == None;
})
pub fn create(native_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> {
ft_native_font::create(native_lib, buf, pt_size)
}
34 changes: 6 additions & 28 deletions src/servo/text/native_font/ft_native_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,18 @@ pub impl FreeTypeNativeFont {
}
}

pub fn create(lib: &FT_Library, buf: @~[u8]) -> Result<FreeTypeNativeFont, ()> {
pub fn create(lib: &FT_Library, buf: @~[u8], pt_size: float) -> Result<FreeTypeNativeFont, ()> {
assert lib.is_not_null();
let face: FT_Face = null();
return vec_as_buf(*buf, |cbuf, _len| {
if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long,
0 as FT_Long, addr_of(&face)).succeeded() {
// FIXME: These values are placeholders
let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
let res = FT_Set_Char_Size(face, // the face
float_to_fixed_ft(pt_size), // char width
float_to_fixed_ft(pt_size), // char height
72, // horiz. DPI
72); // vert. DPI
if !res.succeeded() { fail ~"unable to set font char size" }
Ok(FreeTypeNativeFont(face, buf))
} else {
Expand All @@ -153,29 +157,3 @@ trait FTErrorMethods {
impl FT_Error : FTErrorMethods {
fn succeeded() -> bool { self == 0 as FT_Error }
}

pub fn with_test_native_font(f: fn@(nf: &NativeFont)) {
use font::test_font_bin;
use unwrap_result = result::unwrap;

with_lib(|lib| {
let buf = @test_font_bin();
let font = unwrap_result(create(lib, move buf));
f(&font);
})
}

fn with_lib(f: fn@((&FT_Library))) {
let lib: FT_Library = null();
assert FT_Init_FreeType(addr_of(&lib)).succeeded();
f(&lib);
FT_Done_FreeType(lib);
}

#[test]
fn create_should_return_err_if_buf_is_bogus() {
with_lib(|lib| {
let buf = @~[];
assert create(lib, buf).is_err();
})
}
23 changes: 6 additions & 17 deletions src/servo/text/native_font/quartz_native_font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ pub struct QuartzNativeFont {
}
}

fn QuartzNativeFont(fontprov: CGDataProviderRef, cgfont: CGFontRef) -> QuartzNativeFont {
fn QuartzNativeFont(fontprov: CGDataProviderRef, cgfont: CGFontRef, pt_size: float) -> QuartzNativeFont {
assert fontprov.is_not_null();
assert cgfont.is_not_null();

let ctfont = ctfont_from_cgfont(cgfont);
let ctfont = ctfont_from_cgfont(cgfont, pt_size);
assert ctfont.is_not_null();

QuartzNativeFont {
Expand Down Expand Up @@ -143,14 +143,13 @@ impl QuartzNativeFont {
}
}

fn ctfont_from_cgfont(cgfont: CGFontRef) -> CTFontRef {
fn ctfont_from_cgfont(cgfont: CGFontRef, pt_size: float) -> CTFontRef {
assert cgfont.is_not_null();

// TODO: use actual font size here!
CTFontCreateWithGraphicsFont(cgfont, 21f as CGFloat, null(), null())
CTFontCreateWithGraphicsFont(cgfont, pt_size as CGFloat, null(), null())
}

pub fn create(buf: @~[u8]) -> Result<QuartzNativeFont, ()> {
pub fn create(_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<QuartzNativeFont, ()> {
let fontprov = vec::as_imm_buf(*buf, |cbuf, len| {
CGDataProviderCreateWithData(
null(),
Expand All @@ -163,18 +162,8 @@ pub fn create(buf: @~[u8]) -> Result<QuartzNativeFont, ()> {
let cgfont = CGFontCreateWithDataProvider(fontprov);

match cgfont.is_not_null() {
true => Ok(QuartzNativeFont(fontprov, cgfont)),
true => Ok(QuartzNativeFont(fontprov, cgfont, pt_size)),
false => Err(())
}

}

pub fn with_test_native_font(f: fn@(nf: &NativeFont)) {
use font::test_font_bin;
use unwrap_result = result::unwrap;

let buf = @test_font_bin();
let res = create(buf);
let font = unwrap_result(move res);
f(&font);
}

0 comments on commit 9f94b54

Please sign in to comment.