mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Create FontStyle, FontFaceProperties, and hook up (hardcoded) adjustable font sizes. Also ripped out some native font tests that won't make sense with font machinery refactor.
This commit is contained in:
parent
2e5afb7050
commit
9f94b54c89
5 changed files with 99 additions and 126 deletions
|
@ -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,
|
||||
|
@ -49,29 +30,80 @@ struct FontMetrics {
|
|||
max_advance: Au
|
||||
}
|
||||
|
||||
struct RunMetrics {
|
||||
// may be negative due to negative width
|
||||
advance_width: 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 (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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +132,7 @@ 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);
|
||||
|
@ -107,6 +140,9 @@ impl Font {
|
|||
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};
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use font::{Font, test_font_bin};
|
||||
use font::{Font,
|
||||
FontStyle,
|
||||
FontWeight300,
|
||||
test_font_bin};
|
||||
|
||||
struct FontCache {
|
||||
native_lib: native::NativeFontCache,
|
||||
|
@ -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")]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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();
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue