Fix the linux build by stubbing out FreeType handles that haven't been implemented yet. Add some glue to create ScaledFonts for Cairo backend on linux. Closes #207.

This commit is contained in:
Brian J. Burg 2012-11-13 18:29:07 -08:00
parent 8d5759d8a6
commit 77a5d8b107
8 changed files with 173 additions and 80 deletions

@ -1 +1 @@
Subproject commit 3889e647008218eb80d3f94141f542811bf0ffe4 Subproject commit 8db099ac74ddb4e416eef8f2d237d4ec47787fbe

@ -1 +1 @@
Subproject commit 47035c52e9737364019012459e8ea7bdc15933e5 Subproject commit 351d5a3398f088c39d5aec28760d185237a32c66

View file

@ -7,6 +7,7 @@ use text::glyph::{GlyphStore, GlyphIndex};
use text::{Shaper, TextRun}; use text::{Shaper, TextRun};
use azure::{AzFloat, AzScaledFontRef}; use azure::{AzFloat, AzScaledFontRef};
use azure::scaled_font::ScaledFont;
use azure::azure_hl::{BackendType, ColorPattern}; use azure::azure_hl::{BackendType, ColorPattern};
use core::dvec::DVec; use core::dvec::DVec;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
@ -44,13 +45,13 @@ pub trait FontHandleMethods {
impl FontHandle { impl FontHandle {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
static pub fn new(fctx: &native::FontContextHandle, buf: ~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> { static pub fn new_from_buffer(fctx: &native::FontContextHandle, buf: ~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
quartz::font::QuartzFontHandle::new_from_buffer(fctx, move buf, style) quartz::font::QuartzFontHandle::new_from_buffer(fctx, move buf, style)
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
static pub fn new(fctx: &native::FontContextHandle, buf: ~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> { static pub fn new_from_buffer(fctx: &native::FontContextHandle, buf: ~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
freetype::font::FreeTypeFontHandle::new(fctx, move buf, style) freetype::font::FreeTypeFontHandle::new_from_buffer(fctx, move buf, style)
} }
} }
@ -241,23 +242,18 @@ and the renderer can use it to render text.
*/ */
pub struct Font { pub struct Font {
priv handle: FontHandle, priv handle: FontHandle,
priv mut azure_font: Option<AzScaledFontRef>, priv mut azure_font: Option<ScaledFont>,
priv mut shaper: Option<@Shaper>, priv mut shaper: Option<@Shaper>,
style: UsedFontStyle, style: UsedFontStyle,
metrics: FontMetrics, metrics: FontMetrics,
backend: BackendType, backend: BackendType,
drop {
use azure::bindgen::AzReleaseScaledFont;
do (copy self.azure_font).iter |fontref| { AzReleaseScaledFont(*fontref); }
}
} }
impl Font { impl Font {
static fn new_from_buffer(ctx: &FontContext, buffer: ~[u8], static fn new_from_buffer(ctx: &FontContext, buffer: ~[u8],
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font, ()> { style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font, ()> {
let handle = FontHandle::new(&ctx.handle, move buffer, style); let handle = FontHandle::new_from_buffer(&ctx.handle, move buffer, style);
let handle = if handle.is_ok() { let handle = if handle.is_ok() {
result::unwrap(move handle) result::unwrap(move handle)
} else { } else {
@ -326,25 +322,34 @@ impl Font {
return move result; return move result;
} }
priv fn get_azure_font() -> AzScaledFontRef { // TODO: this should return a borrowed pointer, but I can't figure
// out why borrowck doesn't like my implementation.
priv fn get_azure_font(&self) -> AzScaledFontRef {
// fast path: we've already created the azure font resource // fast path: we've already created the azure font resource
match self.azure_font { match self.azure_font {
Some(azfont) => return azfont, Some(ref azfont) => return azfont.get_ref(),
None => {} None => {}
} }
let mut scaled_font = self.create_azure_font();
self.azure_font = Some(move scaled_font);
// try again.
return self.get_azure_font();
}
#[cfg(target_os="macos")]
priv fn create_azure_font() -> ScaledFont {
let ct_font = &self.handle.ctfont; let ct_font = &self.handle.ctfont;
let size = self.style.pt_size as AzFloat; let size = self.style.pt_size as AzFloat;
let scaled_font = azure::scaled_font::ScaledFont::new(self.backend, ct_font, size); ScaledFont::new(self.backend, ct_font, size)
}
let azure_scaled_font; #[cfg(target_os="linux")]
unsafe { priv fn create_azure_font() -> ScaledFont {
azure_scaled_font = scaled_font.azure_scaled_font; let cairo_font = self.handle.face;
cast::forget(move scaled_font); let size = self.style.pt_size as AzFloat;
} ScaledFont::new(self.backend, cairo_font, size)
self.azure_font = Some(azure_scaled_font);
azure_scaled_font
} }
} }
@ -380,7 +385,7 @@ pub impl Font : FontMethods {
AzReleaseColorPattern}; AzReleaseColorPattern};
let target = rctx.get_draw_target(); let target = rctx.get_draw_target();
let azfont = self.get_azure_font(); let azfontref = self.get_azure_font();
let pattern = ColorPattern(color); let pattern = ColorPattern(color);
let azure_pattern = pattern.azure_color_pattern; let azure_pattern = pattern.azure_color_pattern;
assert azure_pattern.is_not_null(); assert azure_pattern.is_not_null();
@ -418,7 +423,7 @@ pub impl Font : FontMethods {
// TODO(Issue #64): this call needs to move into azure_hl.rs // TODO(Issue #64): this call needs to move into azure_hl.rs
AzDrawTargetFillGlyphs(target.azure_draw_target, AzDrawTargetFillGlyphs(target.azure_draw_target,
azfont, azfontref,
ptr::to_unsafe_ptr(&glyphbuf), ptr::to_unsafe_ptr(&glyphbuf),
azure_pattern, azure_pattern,
ptr::to_unsafe_ptr(&options), ptr::to_unsafe_ptr(&options),

View file

@ -137,7 +137,7 @@ pub impl FontContext {
}, },
// TODO(Issue #174): implement by-platform-name font selectors. // TODO(Issue #174): implement by-platform-name font selectors.
SelectorPlatformIdentifier(identifier) => { SelectorPlatformIdentifier(identifier) => {
let result_handle = self.handle.create_font_from_identifier(identifier, copy desc.style); let result_handle = self.handle.create_font_from_identifier(copy identifier, copy desc.style);
result::chain(move result_handle, |handle| { result::chain(move result_handle, |handle| {
Ok(Font::new_from_adopted_handle(&self, move handle, &desc.style, self.backend)) Ok(Font::new_from_adopted_handle(&self, move handle, &desc.style, self.backend))
}) })

View file

@ -8,7 +8,7 @@ use send_map::{linear, SendMap};
type FontListHandle/& = quartz::font_list::QuartzFontListHandle; type FontListHandle/& = quartz::font_list::QuartzFontListHandle;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
type FontListHandle/& = freetype::font_list::FreeTypeFontListHandle; type FontListHandle/& = fontconfig::font_list::FontconfigFontListHandle;
pub impl FontListHandle { pub impl FontListHandle {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -18,7 +18,7 @@ pub impl FontListHandle {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
static pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> { static pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> {
Ok(freetype::font_list::FreeTypeFontListHandle::new(fctx)) Ok(fontconfig::font_list::FontconfigFontListHandle::new(fctx))
} }
} }

View file

@ -1,12 +1,27 @@
pub struct FontconfigFontContextHandle { extern mod freetype;
ctx: (), extern mod fontconfig;
drop { } use fc = fontconfig;
use ft = freetype;
use gfx_font::FontHandle;
use gfx_font_list::{FontEntry, FontFamily};
use core::dvec::DVec;
use core::send_map::{linear, SendMap};
pub struct FontconfigFontListHandle {
fctx: (),
} }
pub impl FontconfigFontContextHandle { pub impl FontconfigFontListHandle {
// this is a placeholder. static pub fn new(_fctx: &native::FontContextHandle) -> FontconfigFontListHandle {
static pub fn new() -> FontconfigFontContextHandle { FontconfigFontListHandle { fctx: () }
FontconfigFontContextHandle { ctx: () } }
fn get_available_families(&const self,
_fctx: &native::FontContextHandle)
-> linear::LinearMap<~str, @FontFamily> {
fail;
} }
} }

View file

@ -1,17 +1,35 @@
extern mod freetype; extern mod freetype;
use font::{FontMetrics, FractionalPixel}; use font_context::FreeTypeFontContextHandle;
use font_context::FreeTypeFontContext; use gfx_font::{
CSSFontWeight,
FontHandle,
FontHandleMethods,
FontMetrics,
FontTableTag,
FractionalPixel,
SpecifiedFontStyle,
UsedFontStyle,
};
use geometry::Au; use geometry::Au;
use text::glyph::GlyphIndex; use text::glyph::GlyphIndex;
use text::util::{float_to_fixed, fixed_to_float}; use text::util::{float_to_fixed, fixed_to_float};
use cast::reinterpret_cast; use freetype::{
use ptr::{addr_of, null}; FTErrorMethods,
use vec_as_buf = vec::as_imm_buf; FT_Error,
FT_F26Dot6,
use freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_Size, FT_SizeRec, FT_Face,
FT_UInt, FT_GlyphSlot, FT_Size_Metrics, FT_FaceRec, FT_F26Dot6 }; FT_FaceRec,
FT_GlyphSlot,
FT_Library,
FT_Long,
FT_ULong,
FT_Size,
FT_SizeRec,
FT_UInt,
FT_Size_Metrics,
};
use freetype::bindgen::{ use freetype::bindgen::{
FT_Init_FreeType, FT_Init_FreeType,
FT_Done_FreeType, FT_Done_FreeType,
@ -46,27 +64,70 @@ pub struct FreeTypeFontHandle {
} }
pub impl FreeTypeFontHandle { pub impl FreeTypeFontHandle {
static pub fn new(fctx: &FreeTypeFontContext, static pub fn new_from_buffer(fctx: &FreeTypeFontContextHandle,
buf: ~[u8], pt_size: float) -> Result<FreeTypeFontHandle, ()> { buf: ~[u8], style: &SpecifiedFontStyle) -> Result<FreeTypeFontHandle, ()> {
let ft_ctx = fctx.ctx; let ft_ctx: FT_Library = fctx.ctx;
assert ft_ctx.is_not_null(); if ft_ctx.is_null() { return Err(()); }
let face_result: Result<FT_Face,()> = vec_as_buf(buf, |cbuf, _len| {
if FT_New_Memory_Face(ft_ctx, cbuf, (*buf).len() as FT_Long, let face_result = do vec::as_imm_buf(buf) |bytes: *u8, len: uint| {
0 as FT_Long, addr_of(&face)).succeeded() { create_face_from_buffer(ft_ctx, bytes, len, style.pt_size)
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 height
72, // horiz. DPI
72); // vert. DPI
if !res.succeeded() { fail ~"unable to set font char size" }
Ok(face)
} else {
Err(())
}
});
return do result::chain(face_result) |face| {
Ok(FreeTypeFontHandle { face: face, buf: move buf })
}; };
// TODO: this could be more simply written as result::chain
// and moving buf into the struct ctor, but cant' move out of
// captured binding.
return match face_result {
Ok(face) => Ok(FreeTypeFontHandle { face: face, buf: move buf }),
Err(()) => Err(())
};
fn create_face_from_buffer(lib: FT_Library,
cbuf: *u8, cbuflen: uint, pt_size: float)
-> Result<FT_Face, ()> {
let mut face: FT_Face = ptr::null();
let face_index = 0 as FT_Long;
let result = FT_New_Memory_Face(lib, cbuf, cbuflen as FT_Long,
face_index, ptr::to_unsafe_ptr(&face));
if !result.succeeded() || face.is_null() {
return Err(());
}
let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6;
let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
let h_dpi = 72;
let v_dpi = 72;
let result = FT_Set_Char_Size(face, char_width, char_height, h_dpi, v_dpi);
if !result.succeeded() { return Err(()); }
Ok(face)
}
}
}
pub impl FreeTypeFontHandle : FontHandleMethods {
// an identifier usable by FontContextHandle to recreate this FontHandle.
pure fn face_identifier() -> ~str {
fail;
}
pure fn family_name() -> ~str {
fail;
}
pure fn face_name() -> ~str {
fail;
}
pure fn is_italic() -> bool {
fail;
}
pure fn boldness() -> CSSFontWeight {
fail;
}
fn clone_with_style(_fctx: &native::FontContextHandle,
_style: &UsedFontStyle) -> Result<FontHandle, ()> {
fail;
} }
pub fn glyph_index(codepoint: char) -> Option<GlyphIndex> { pub fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
@ -86,7 +147,7 @@ pub impl FreeTypeFontHandle {
if res.succeeded() { if res.succeeded() {
unsafe { unsafe {
let void_glyph = (*self.face).glyph; let void_glyph = (*self.face).glyph;
let slot: FT_GlyphSlot = reinterpret_cast(&void_glyph); let slot: FT_GlyphSlot = cast::transmute(void_glyph);
assert slot.is_not_null(); assert slot.is_not_null();
debug!("metrics: %?", (*slot).metrics); debug!("metrics: %?", (*slot).metrics);
let advance = (*slot).metrics.horiAdvance; let advance = (*slot).metrics.horiAdvance;
@ -123,6 +184,12 @@ pub impl FreeTypeFontHandle {
} }
} }
fn get_table_for_tag(_tag: FontTableTag) -> Option<~[u8]> {
fail;
}
}
pub impl FreeTypeFontHandle {
priv fn get_face_rec() -> &self/FT_FaceRec unsafe { priv fn get_face_rec() -> &self/FT_FaceRec unsafe {
&(*self.face) &(*self.face)
} }
@ -145,11 +212,3 @@ pub impl FreeTypeFontHandle {
return geometry::from_frac_px(value * x_scale); return geometry::from_frac_px(value * x_scale);
} }
} }
trait FTErrorMethods {
fn succeeded() -> bool;
}
impl FT_Error : FTErrorMethods {
fn succeeded() -> bool { self == 0 as FT_Error }
}

View file

@ -1,6 +1,7 @@
extern mod freetype; extern mod freetype;
use freetype::{ use freetype::{
FTErrorMethods,
FT_Error, FT_Error,
FT_Library, FT_Library,
}; };
@ -9,6 +10,11 @@ use freetype::bindgen::{
FT_Done_FreeType FT_Done_FreeType
}; };
use gfx_font::{
FontHandle,
UsedFontStyle,
};
use gfx_font_context::FontContextHandleMethods;
pub struct FreeTypeFontContextHandle { pub struct FreeTypeFontContextHandle {
ctx: FT_Library, ctx: FT_Library,
@ -21,13 +27,21 @@ pub struct FreeTypeFontContextHandle {
pub impl FreeTypeFontContextHandle { pub impl FreeTypeFontContextHandle {
static pub fn new() -> FreeTypeFontContextHandle { static pub fn new() -> FreeTypeFontContextHandle {
let lib: FT_Library = ptr::null(); let ctx: FT_Library = ptr::null();
let res = FT_Init_FreeType(ptr::addr_of(&lib)); let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
// FIXME: error handling if !result.succeeded() { fail; }
assert res == 0 as FT_Error;
FreeTypeFontContext { FreeTypeFontContextHandle {
ctx: lib, ctx: ctx,
} }
} }
} }
pub impl FreeTypeFontContextHandle : FontContextHandleMethods {
fn create_font_from_identifier(_identifier: ~str, _style: UsedFontStyle)
-> Result<FontHandle, ()> {
fail;
}
}