Create font matchers and native equivalents. Add in a dummy font cache. Untangle some test font stuff.

This commit is contained in:
Brian J. Burg 2012-10-29 18:41:53 -07:00
parent 82434c749c
commit b545e4821e
12 changed files with 160 additions and 108 deletions

View file

@ -15,6 +15,7 @@ use render_context::RenderContext;
use render_layers::render_layers; use render_layers::render_layers;
use std::cell::Cell; use std::cell::Cell;
use text::font_cache::FontCache; use text::font_cache::FontCache;
use text::font_matcher::FontMatcher;
pub enum Msg { pub enum Msg {
RenderMsg(RenderLayer), RenderMsg(RenderLayer),
@ -35,7 +36,7 @@ pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask {
port: po, port: po,
compositor: move compositor, compositor: move compositor,
mut layer_buffer_set_port: Cell(move layer_buffer_set_port), mut layer_buffer_set_port: Cell(move layer_buffer_set_port),
font_cache: FontCache(), font_cache: @FontCache::new(@FontMatcher::new()),
}.start(); }.start();
} }
} }

View file

@ -26,6 +26,7 @@ use render_task::RenderTask;
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg}; use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use resource::local_image_cache::LocalImageCache; use resource::local_image_cache::LocalImageCache;
use servo_text::font_cache::FontCache; use servo_text::font_cache::FontCache;
use servo_text::font_matcher::FontMatcher;
use std::arc::ARC; use std::arc::ARC;
use std::net::url::Url; use std::net::url::Url;
use core::util::replace; use core::util::replace;
@ -89,7 +90,7 @@ fn Layout(render_task: RenderTask,
image_cache_task: image_cache_task.clone(), image_cache_task: image_cache_task.clone(),
local_image_cache: @LocalImageCache(move image_cache_task), local_image_cache: @LocalImageCache(move image_cache_task),
from_content: from_content, from_content: from_content,
font_cache: FontCache(), font_cache: @FontCache::new(@FontMatcher::new()),
layout_refs: DVec() layout_refs: DVec()
} }
} }

View file

@ -103,13 +103,16 @@ pub mod platform {
pub mod text { pub mod text {
pub mod font; pub mod font;
pub mod font_cache; pub mod font_cache;
pub mod font_matcher;
pub mod glyph; pub mod glyph;
pub mod native_font;
pub mod shaper;
pub mod text_run; pub mod text_run;
pub mod util; pub mod util;
// platform and library-specific implementations. // platform and library-specific implementations.
pub mod native_font;
pub mod native_font_matcher;
pub mod shaper;
pub mod harfbuzz { pub mod harfbuzz {
pub mod shaper; pub mod shaper;
} }
@ -117,11 +120,13 @@ pub mod text {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub mod quartz { pub mod quartz {
pub mod native_font; pub mod native_font;
pub mod native_font_matcher;
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub mod freetype { pub mod freetype {
pub mod native_font; pub mod native_font;
pub mod native_font_matcher;
} }
} }

View file

@ -78,9 +78,6 @@ A font handle. Layout can use this to calculate glyph metrics
and the renderer can use it to render text. and the renderer can use it to render text.
*/ */
struct Font { struct Font {
// TODO: is this actually needed? -bjb
// A back reference to keep the library alive
priv lib: @FontCache,
priv fontbuf: @~[u8], priv fontbuf: @~[u8],
priv native_font: NativeFont, priv native_font: NativeFont,
priv mut azure_font: Option<AzScaledFontRef>, priv mut azure_font: Option<AzScaledFontRef>,
@ -96,11 +93,10 @@ struct Font {
impl Font { impl Font {
// TODO: who should own fontbuf? // TODO: who should own fontbuf?
static fn new(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont, style: FontStyle) -> Font { static fn new(fontbuf: @~[u8], native_font: NativeFont, style: FontStyle) -> Font {
let metrics = native_font.get_metrics(); let metrics = native_font.get_metrics();
Font { Font {
lib: lib,
fontbuf : fontbuf, fontbuf : fontbuf,
native_font : move native_font, native_font : move native_font,
azure_font: None, azure_font: None,
@ -340,12 +336,6 @@ pub impl Font : FontMethods {
} }
} }
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
fn test_font_bin() -> ~[u8] {
return vec::from_fn(33004, |i| TEST_FONT[i]);
}
fn should_destruct_on_fail_without_leaking() { fn should_destruct_on_fail_without_leaking() {
#[test]; #[test];
#[should_fail]; #[should_fail];

View file

@ -1,96 +1,34 @@
use font::{Font, use font::{Font, FontStyle, FontWeight300};
FontStyle, use font_matcher::FontMatcher;
FontWeight300, // Dummy font cache.
test_font_bin};
use native_font::NativeFont;
struct FontCache { struct FontCache {
native_lib: native::NativeFontCache, matcher: @FontMatcher,
mut cached_font: Option<@Font>, mut cached_font: Option<@Font>
drop {
native::destroy_native_lib(&self.native_lib);
}
} }
impl FontCache { impl FontCache {
fn get_font(@self) -> @Font { static pub fn new(matcher: @FontMatcher) -> FontCache {
match self.cached_font { FontCache {
Some(font) => font, matcher: matcher,
None => match create_font(self, &self.native_lib) {
Ok(font) => {
self.cached_font = Some(font);
font
}
Err(*) => /* FIXME */ fail
}
}
}
fn get_test_font(@self) -> @Font {
self.get_font()
}
}
fn FontCache() -> @FontCache {
@FontCache {
native_lib: native::create_native_lib(),
cached_font: None cached_font: None
} }
} }
fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> { pub fn get_test_font(@self) -> @Font {
let font_bin = @test_font_bin();
let dummy_style = FontStyle { let dummy_style = FontStyle {
pt_size: 40f, pt_size: 40f,
weight: FontWeight300, weight: FontWeight300,
italic: false, italic: false,
oblique: false oblique: false
}; };
let native_font = NativeFont::new(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, move dummy_style)); return match self.cached_font {
} Some(font) => font,
None => match self.matcher.get_font(&dummy_style) {
#[cfg(target_os = "linux")] Ok(font) => { self.cached_font = Some(font); font }
pub mod native { Err(*) => /* FIXME */ fail
extern mod freetype; }
use ptr::{null, addr_of};
use freetype::{FT_Library, FT_Error};
use freetype::bindgen::{FT_Init_FreeType, FT_Done_FreeType};
pub type NativeFontCache = FT_Library;
pub fn create_native_lib() -> NativeFontCache {
let lib: FT_Library = null();
let res = FT_Init_FreeType(addr_of(&lib));
// FIXME: error handling
assert res == 0 as FT_Error;
return lib;
} }
pub fn destroy_native_lib(native_lib: &NativeFontCache) {
assert native_lib.is_not_null();
FT_Done_FreeType(*native_lib);
} }
} }
#[cfg(target_os = "macos")]
pub mod native {
pub type NativeFontCache = ();
pub fn create_native_lib() -> NativeFontCache { () }
pub fn destroy_native_lib(_native_lib: &NativeFontCache) { }
}
#[test]
pub fn should_get_fonts() {
let lib = FontCache();
lib.get_font();
}

View file

@ -0,0 +1,43 @@
use font::{Font, FontStyle};
use native_font::NativeFont;
use native_font_matcher::NativeFontMatcher;
// TODO(Issue #164): delete, and get default font from NativeFontMatcher
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
fn test_font_bin() -> ~[u8] {
return vec::from_fn(33004, |i| TEST_FONT[i]);
}
struct FontMatcher {
native_matcher: NativeFontMatcher,
// TODO(Issue #165): move into FontCache
mut cached_font: Option<@Font>,
}
impl FontMatcher {
static pub fn new() -> FontMatcher {
FontMatcher {
native_matcher: NativeFontMatcher::new(),
cached_font: None
}
}
// TODO: maybe FontStyle should be canonicalized when used in FontCache?
// TODO(Issue #166): move this to FontCache or something? At the least, use it there.
priv fn create_font(style: &FontStyle) -> Result<@Font, ()> {
let font_bin = @test_font_bin();
let native_font = NativeFont::new(&self.native_matcher, font_bin, 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(font_bin, move native_font, copy *style));
}
pub fn get_font(@self, style: &FontStyle) -> Result<@Font, ()> {
self.create_font(style)
}
}

View file

@ -1,6 +1,7 @@
extern mod freetype; extern mod freetype;
use font::{FontMetrics, FractionalPixel}; use font::{FontMetrics, FractionalPixel};
use native_font_matcher::FreeTypeNativeFontMatcher;
use gfx::geometry; use gfx::geometry;
use gfx::geometry::Au; use gfx::geometry::Au;
@ -44,11 +45,13 @@ pub struct FreeTypeNativeFont {
} }
pub impl FreeTypeNativeFont { pub impl FreeTypeNativeFont {
static pub fn new(lib: &FT_Library, buf: @~[u8], pt_size: float) -> Result<FreeTypeNativeFont, ()> { static pub fn new(matcher: &FreeTypeNativeFontMatcher,
buf: @~[u8], pt_size: float) -> Result<FreeTypeNativeFont, ()> {
let lib = matcher.ft_lib;
assert lib.is_not_null(); assert lib.is_not_null();
let face: FT_Face = null(); let face: FT_Face = null();
return vec_as_buf(*buf, |cbuf, _len| { return vec_as_buf(*buf, |cbuf, _len| {
if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long, if FT_New_Memory_Face(lib, cbuf, (*buf).len() as FT_Long,
0 as FT_Long, addr_of(&face)).succeeded() { 0 as FT_Long, addr_of(&face)).succeeded() {
let res = FT_Set_Char_Size(face, // the face let res = FT_Set_Char_Size(face, // the face
float_to_fixed_ft(pt_size) as FT_F26Dot6, // char width float_to_fixed_ft(pt_size) as FT_F26Dot6, // char width

View file

@ -0,0 +1,33 @@
extern mod freetype;
use freetype::{
FT_Error,
FT_Library,
};
use freetype::bindgen::{
FT_Init_FreeType,
FT_Done_FreeType
};
pub struct FreeTypeNativeFontMatcher {
ft_lib: FT_Library,
drop {
assert self.ft_lib.is_not_null();
FT_Done_FreeType(self.ft_lib);
}
}
pub impl FreeTypeNativeFontMatcher {
static pub fn new() -> FreeTypeNativeFontMatcher {
let lib: FT_Library = ptr::null();
let res = FT_Init_FreeType(ptr::addr_of(&lib));
// FIXME: error handling
assert res == 0 as FT_Error;
FreeTypeNativeFontMatcher {
ft_lib: lib,
}
}
}

View file

@ -5,7 +5,7 @@ needed by the text shaper as well as access to the underlying
font resources needed by the graphics layer to draw glyphs. font resources needed by the graphics layer to draw glyphs.
*/ */
use font_cache::native::NativeFontCache; use native_font_matcher::NativeFontMatcher;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub type NativeFont/& = quartz::native_font::QuartzNativeFont; pub type NativeFont/& = quartz::native_font::QuartzNativeFont;
@ -22,14 +22,14 @@ pub type NativeFont/& = freetype::native_font::FreeTypeNativeFont;
// to conditionally define the entire impl. // to conditionally define the entire impl.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
impl NativeFont { impl NativeFont {
static pub fn new(native_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> { static pub fn new(native_lib: &NativeFontMatcher, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> {
quartz::native_font::QuartzNativeFont::new(native_lib, buf, pt_size) quartz::native_font::QuartzNativeFont::new(native_lib, buf, pt_size)
} }
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
impl NativeFont { impl NativeFont {
static pub fn new(native_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> { static pub fn new(native_lib: &NativeFontMatcher, buf: @~[u8], pt_size: float) -> Result<NativeFont, ()> {
freetype::native_font::FreeTypeNativeFont::new(native_lib, buf, pt_size) freetype::native_font::FreeTypeNativeFont::new(native_lib, buf, pt_size)
} }
} }

View file

@ -0,0 +1,25 @@
// TODO(Issue #163): this is a workaround for static methods and
// typedefs not working well together. It should be removed.
// TODO(Rust #1723): #cfg doesn't work for impl methods, so we have
// to conditionally define the entire impl.
#[cfg(target_os = "macos")]
type NativeFontMatcher/& = quartz::native_font_matcher::QuartzNativeFontMatcher;
#[cfg(target_os = "linux")]
type NativeFontMatcher/& = freetype::native_font_matcher::FreeTypeNativeFontMatcher;
#[cfg(target_os = "macos")]
pub impl NativeFontMatcher {
static pub fn new() -> NativeFontMatcher {
quartz::native_font_matcher::QuartzNativeFontMatcher::new()
}
}
#[cfg(target_os = "linux")]
pub impl NativeFontMatcher {
static pub fn new() -> NativeFontMatcher {
freetype::native_font_matcher::FreeTypeNativeFontMatcher::new()
}
}

View file

@ -3,7 +3,7 @@ extern mod core_graphics;
extern mod core_text; extern mod core_text;
use font::{FontMetrics, FractionalPixel}; use font::{FontMetrics, FractionalPixel};
use font_cache::native::NativeFontCache; use native_font_matcher::QuartzNativeFontMatcher;
use au = gfx::geometry; use au = gfx::geometry;
use cast::transmute; use cast::transmute;
@ -68,7 +68,7 @@ pub struct QuartzNativeFont {
} }
pub impl QuartzNativeFont { pub impl QuartzNativeFont {
static pub fn new(_lib: &NativeFontCache, buf: @~[u8], pt_size: float) -> Result<QuartzNativeFont, ()> { static pub fn new(_lib: &QuartzNativeFontMatcher, buf: @~[u8], pt_size: float) -> Result<QuartzNativeFont, ()> {
let fontprov = vec::as_imm_buf(*buf, |cbuf, len| { let fontprov = vec::as_imm_buf(*buf, |cbuf, len| {
CGDataProviderCreateWithData( CGDataProviderCreateWithData(
null(), null(),

View file

@ -0,0 +1,13 @@
pub struct QuartzNativeFontMatcher {
dummy: int,
drop { }
}
pub impl QuartzNativeFontMatcher {
// this is a placeholder until NSFontManager or whatever is bound in here.
static pub fn new() -> QuartzNativeFontMatcher {
QuartzNativeFontMatcher { dummy: 42 }
}
}