mirror of
https://github.com/servo/servo.git
synced 2025-08-08 15:05:35 +01:00
Create font matchers and native equivalents. Add in a dummy font cache. Untangle some test font stuff.
This commit is contained in:
parent
82434c749c
commit
b545e4821e
12 changed files with 160 additions and 108 deletions
|
@ -15,6 +15,7 @@ use render_context::RenderContext;
|
|||
use render_layers::render_layers;
|
||||
use std::cell::Cell;
|
||||
use text::font_cache::FontCache;
|
||||
use text::font_matcher::FontMatcher;
|
||||
|
||||
pub enum Msg {
|
||||
RenderMsg(RenderLayer),
|
||||
|
@ -35,7 +36,7 @@ pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask {
|
|||
port: po,
|
||||
compositor: move compositor,
|
||||
mut layer_buffer_set_port: Cell(move layer_buffer_set_port),
|
||||
font_cache: FontCache(),
|
||||
font_cache: @FontCache::new(@FontMatcher::new()),
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use render_task::RenderTask;
|
|||
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||
use resource::local_image_cache::LocalImageCache;
|
||||
use servo_text::font_cache::FontCache;
|
||||
use servo_text::font_matcher::FontMatcher;
|
||||
use std::arc::ARC;
|
||||
use std::net::url::Url;
|
||||
use core::util::replace;
|
||||
|
@ -89,7 +90,7 @@ fn Layout(render_task: RenderTask,
|
|||
image_cache_task: image_cache_task.clone(),
|
||||
local_image_cache: @LocalImageCache(move image_cache_task),
|
||||
from_content: from_content,
|
||||
font_cache: FontCache(),
|
||||
font_cache: @FontCache::new(@FontMatcher::new()),
|
||||
layout_refs: DVec()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,13 +103,16 @@ pub mod platform {
|
|||
pub mod text {
|
||||
pub mod font;
|
||||
pub mod font_cache;
|
||||
pub mod font_matcher;
|
||||
pub mod glyph;
|
||||
pub mod native_font;
|
||||
pub mod shaper;
|
||||
pub mod text_run;
|
||||
pub mod util;
|
||||
|
||||
// platform and library-specific implementations.
|
||||
pub mod native_font;
|
||||
pub mod native_font_matcher;
|
||||
pub mod shaper;
|
||||
|
||||
pub mod harfbuzz {
|
||||
pub mod shaper;
|
||||
}
|
||||
|
@ -117,11 +120,13 @@ pub mod text {
|
|||
#[cfg(target_os = "macos")]
|
||||
pub mod quartz {
|
||||
pub mod native_font;
|
||||
pub mod native_font_matcher;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod freetype {
|
||||
pub mod native_font;
|
||||
pub mod native_font_matcher;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,9 +78,6 @@ 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>,
|
||||
|
@ -96,11 +93,10 @@ struct Font {
|
|||
|
||||
impl Font {
|
||||
// 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();
|
||||
|
||||
Font {
|
||||
lib: lib,
|
||||
fontbuf : fontbuf,
|
||||
native_font : move native_font,
|
||||
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() {
|
||||
#[test];
|
||||
#[should_fail];
|
||||
|
|
|
@ -1,96 +1,34 @@
|
|||
use font::{Font,
|
||||
FontStyle,
|
||||
FontWeight300,
|
||||
test_font_bin};
|
||||
use native_font::NativeFont;
|
||||
use font::{Font, FontStyle, FontWeight300};
|
||||
use font_matcher::FontMatcher;
|
||||
// Dummy font cache.
|
||||
|
||||
struct FontCache {
|
||||
native_lib: native::NativeFontCache,
|
||||
mut cached_font: Option<@Font>,
|
||||
|
||||
drop {
|
||||
native::destroy_native_lib(&self.native_lib);
|
||||
}
|
||||
matcher: @FontMatcher,
|
||||
mut cached_font: Option<@Font>
|
||||
}
|
||||
|
||||
impl FontCache {
|
||||
fn get_font(@self) -> @Font {
|
||||
match self.cached_font {
|
||||
static pub fn new(matcher: @FontMatcher) -> FontCache {
|
||||
FontCache {
|
||||
matcher: matcher,
|
||||
cached_font: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_test_font(@self) -> @Font {
|
||||
let dummy_style = FontStyle {
|
||||
pt_size: 40f,
|
||||
weight: FontWeight300,
|
||||
italic: false,
|
||||
oblique: false
|
||||
};
|
||||
|
||||
return match self.cached_font {
|
||||
Some(font) => font,
|
||||
None => match create_font(self, &self.native_lib) {
|
||||
Ok(font) => {
|
||||
self.cached_font = Some(font);
|
||||
font
|
||||
}
|
||||
None => match self.matcher.get_font(&dummy_style) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> {
|
||||
let font_bin = @test_font_bin();
|
||||
let dummy_style = FontStyle {
|
||||
pt_size: 40f,
|
||||
weight: FontWeight300,
|
||||
italic: 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));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod native {
|
||||
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();
|
||||
}
|
||||
}
|
43
src/servo/text/font_matcher.rs
Normal file
43
src/servo/text/font_matcher.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
extern mod freetype;
|
||||
|
||||
use font::{FontMetrics, FractionalPixel};
|
||||
use native_font_matcher::FreeTypeNativeFontMatcher;
|
||||
|
||||
use gfx::geometry;
|
||||
use gfx::geometry::Au;
|
||||
|
@ -44,11 +45,13 @@ pub struct 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();
|
||||
let face: FT_Face = null();
|
||||
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() {
|
||||
let res = FT_Set_Char_Size(face, // the face
|
||||
float_to_fixed_ft(pt_size) as FT_F26Dot6, // char width
|
||||
|
|
33
src/servo/text/freetype/native_font_matcher.rs
Normal file
33
src/servo/text/freetype/native_font_matcher.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
||||
use font_cache::native::NativeFontCache;
|
||||
use native_font_matcher::NativeFontMatcher;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub type NativeFont/& = quartz::native_font::QuartzNativeFont;
|
||||
|
@ -22,14 +22,14 @@ pub type NativeFont/& = freetype::native_font::FreeTypeNativeFont;
|
|||
// to conditionally define the entire impl.
|
||||
#[cfg(target_os = "macos")]
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
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)
|
||||
}
|
||||
}
|
25
src/servo/text/native_font_matcher.rs
Normal file
25
src/servo/text/native_font_matcher.rs
Normal 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()
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ extern mod core_graphics;
|
|||
extern mod core_text;
|
||||
|
||||
use font::{FontMetrics, FractionalPixel};
|
||||
use font_cache::native::NativeFontCache;
|
||||
use native_font_matcher::QuartzNativeFontMatcher;
|
||||
|
||||
use au = gfx::geometry;
|
||||
use cast::transmute;
|
||||
|
@ -68,7 +68,7 @@ pub struct 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| {
|
||||
CGDataProviderCreateWithData(
|
||||
null(),
|
||||
|
|
13
src/servo/text/quartz/native_font_matcher.rs
Normal file
13
src/servo/text/quartz/native_font_matcher.rs
Normal 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 }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue