From c92c1c661f9c6fc096b9327f90180f8f2c359e39 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 24 Jun 2012 20:14:52 -0700 Subject: [PATCH] Implement FreeTypeNativeFont.glyph_h_advance --- src/servo/text/native_font.rs | 32 +++++++++-- src/servo/text/native_font/ft_native_font.rs | 56 ++++++++++++++++--- .../text/native_font/quartz_native_font.rs | 9 ++- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/servo/text/native_font.rs b/src/servo/text/native_font.rs index 1c6287e72cc..abd78f244e9 100644 --- a/src/servo/text/native_font.rs +++ b/src/servo/text/native_font.rs @@ -15,12 +15,18 @@ type NativeFont/& = quartz_native_font::QuartzNativeFont; #[cfg(target_os = "linux")] type NativeFont/& = ft_native_font::FreeTypeNativeFont; +#[cfg(target_os = "macos")] fn with_test_native_font(f: fn@(NativeFont)) { - fail + quartz_native_font::with_test_native_font(f); +} + +#[cfg(target_os = "linux")] +fn with_test_native_font(f: fn@(nf: &NativeFont)) { + ft_native_font::with_test_native_font(f); } #[test] -#[ignore] +#[ignore(cfg(target_os = "macos"))] fn should_get_glyph_indexes() { with_test_native_font { |font| let idx = font.glyph_index('w'); @@ -29,10 +35,28 @@ fn should_get_glyph_indexes() { } #[test] -#[ignore] +#[ignore(cfg(target_os = "macos"))] +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(cfg(target_os = "macos"))] fn should_get_glyph_h_advance() { with_test_native_font { |font| let adv = font.glyph_h_advance(40u); - assert adv == 15; + assert adv == some(15); + } +} + +#[test] +#[ignore(cfg(target_os = "macos"))] +fn should_return_none_glyph_h_advance_for_bad_codepoints() { + with_test_native_font { |font| + let adv = font.glyph_h_advance(-1 as uint); + assert adv == none; } } diff --git a/src/servo/text/native_font/ft_native_font.rs b/src/servo/text/native_font/ft_native_font.rs index c670f1ddad4..e95ff636d6a 100644 --- a/src/servo/text/native_font/ft_native_font.rs +++ b/src/servo/text/native_font/ft_native_font.rs @@ -1,16 +1,20 @@ -export FreeTypeNativeFont; +export FreeTypeNativeFont, with_test_native_font; import vec_as_buf = vec::as_buf; import result::{result, ok, err}; import ptr::{addr_of, null}; +import unsafe::reinterpret_cast; import glyph::GlyphIndex; import azure::freetype; -import freetype::{ FT_Error, FT_Library, FT_Face, FT_Long }; +import freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_UInt, FT_GlyphSlot }; import freetype::bindgen::{ FT_Init_FreeType, FT_Done_FreeType, FT_New_Memory_Face, - FT_Done_Face + FT_Done_Face, + FT_Get_Char_Index, + FT_Load_Glyph, + FT_Set_Char_Size }; class FreeTypeNativeFont/& { @@ -28,13 +32,36 @@ class FreeTypeNativeFont/& { } } - fn glyph_index(_codepoint: char) -> option { - fail; + fn glyph_index(codepoint: char) -> option { + assert self.face.is_not_null(); + let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong); + ret if idx != 0 as FT_UInt { + some(idx as GlyphIndex) + } else { + #warn("Invalid codepoint: %?", codepoint); + none + }; } // FIXME: What unit is this returning? Let's have a custom type - fn glyph_h_advance(_glyph: GlyphIndex) -> int { - fail; + fn glyph_h_advance(glyph: GlyphIndex) -> option { + assert self.face.is_not_null(); + let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0); + if res.succeeded() { + unsafe { + let void_glyph = (*self.face).glyph; + let slot: FT_GlyphSlot = reinterpret_cast(void_glyph); + assert slot.is_not_null(); + let advance = (*slot).metrics.horiAdvance; + #debug("h_advance for %? is %?", glyph, advance); + // FIXME: Dividing by 64 converts to pixels, which + // is not the unit we should be using + ret some((advance / 64) as int); + } + } else { + #warn("Unable to load glyph %?. reason: %?", glyph, res); + ret none; + } } } @@ -44,6 +71,9 @@ fn create(lib: FT_Library, buf: &[u8]) -> result { ret vec_as_buf(*buf) {|cbuf| 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); + if !res.succeeded() { fail "unable to set font char size" } ok(FreeTypeNativeFont(face)) } else { err(()) @@ -55,6 +85,18 @@ impl methods for FT_Error { fn succeeded() -> bool { self == 0 as FT_Error } } +#[cfg(target_os = "linux")] +fn with_test_native_font(f: fn@(nf: &NativeFont)) { + import font::test_font_bin; + import unwrap_result = result::unwrap; + + with_lib { |lib| + let buf = test_font_bin(); + let font = unwrap_result(create(lib, &buf)); + f(&font); + } +} + #[cfg(test)] fn with_lib(f: fn@(FT_Library)) { let lib: FT_Library = null(); diff --git a/src/servo/text/native_font/quartz_native_font.rs b/src/servo/text/native_font/quartz_native_font.rs index 05e5bfbb2c6..795ceae718d 100644 --- a/src/servo/text/native_font/quartz_native_font.rs +++ b/src/servo/text/native_font/quartz_native_font.rs @@ -1,3 +1,5 @@ +export QuartzNativeFont, with_test_native_font; + import glyph::GlyphIndex; class QuartzNativeFont/& { @@ -10,7 +12,12 @@ class QuartzNativeFont/& { } // FIXME: What unit is this returning? Let's have a custom type - fn glyph_h_advance(_glyph: GlyphIndex) -> int { + fn glyph_h_advance(_glyph: GlyphIndex) -> option { fail; } } + +#[cfg(target_os = "linux")] +fn with_test_native_font(f: fn@(nf: &NativeFont)) { + fail +}