mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Clean up font-related constructor paths to not require a byte buffer;
add FontGroup construction and interaction with TextRun. Closes #178.
This commit is contained in:
parent
84216f838f
commit
a34f67d64b
6 changed files with 101 additions and 37 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 9c398db2b0627b150eba88edc0eb861dfb4a28ac
|
||||
Subproject commit 7a42dc503a6b4578f3957c69574e07175b2ca3c5
|
|
@ -26,6 +26,7 @@ pub trait FontHandleMethods {
|
|||
pure fn is_italic() -> bool;
|
||||
pure fn boldness() -> CSSFontWeight;
|
||||
|
||||
fn clone_with_style(fctx: &native::FontContextHandle, style: &UsedFontStyle) -> Result<FontHandle, ()>;
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
||||
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
||||
fn get_metrics() -> FontMetrics;
|
||||
|
@ -38,13 +39,13 @@ pub trait FontHandleMethods {
|
|||
|
||||
impl FontHandle {
|
||||
#[cfg(target_os = "macos")]
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, pt_size)
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||
quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, style)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
freetype::font::FreeTypeFontHandle::new(fctx, buf, pt_size)
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||
freetype::font::FreeTypeFontHandle::new(fctx, buf, style)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,6 +195,13 @@ pub impl FontGroup {
|
|||
fonts: move fonts,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_textrun(text: ~str) -> TextRun {
|
||||
assert self.fonts.len() > 0;
|
||||
|
||||
// TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable.
|
||||
return TextRun::new(self.fonts[0], move text);
|
||||
}
|
||||
}
|
||||
|
||||
struct RunMetrics {
|
||||
|
@ -211,7 +219,7 @@ A font instance. Layout can use this to calculate glyph metrics
|
|||
and the renderer can use it to render text.
|
||||
*/
|
||||
pub struct Font {
|
||||
priv fontbuf: @~[u8],
|
||||
priv mut fontbuf: Option<@~[u8]>,
|
||||
priv handle: FontHandle,
|
||||
priv mut azure_font: Option<AzScaledFontRef>,
|
||||
priv mut shaper: Option<@Shaper>,
|
||||
|
@ -226,22 +234,48 @@ pub struct Font {
|
|||
}
|
||||
|
||||
impl Font {
|
||||
// TODO: who should own fontbuf?
|
||||
static fn new(fontbuf: @~[u8],
|
||||
handle: FontHandle,
|
||||
style: UsedFontStyle,
|
||||
backend: BackendType) -> Font {
|
||||
let metrics = handle.get_metrics();
|
||||
static fn new_from_buffer(ctx: &FontContext, buffer: @~[u8],
|
||||
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font, ()> {
|
||||
|
||||
Font {
|
||||
fontbuf : fontbuf,
|
||||
let handle = FontHandle::new(&ctx.handle, buffer, style);
|
||||
let handle = if handle.is_ok() {
|
||||
result::unwrap(move handle)
|
||||
} else {
|
||||
return Err(handle.get_err());
|
||||
};
|
||||
|
||||
let metrics = handle.get_metrics();
|
||||
// TODO(Issue #179): convert between specified and used font style here?
|
||||
|
||||
return Ok(@Font {
|
||||
fontbuf : Some(buffer),
|
||||
handle : move handle,
|
||||
azure_font: None,
|
||||
shaper: None,
|
||||
style: move style,
|
||||
style: copy *style,
|
||||
metrics: move metrics,
|
||||
backend: backend
|
||||
}
|
||||
backend: backend,
|
||||
});
|
||||
}
|
||||
|
||||
static fn new_from_handle(fctx: &FontContext, handle: &FontHandle,
|
||||
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font,()> {
|
||||
|
||||
// TODO(Issue #179): convert between specified and used font style here?
|
||||
let styled_handle = match handle.clone_with_style(&fctx.handle, style) {
|
||||
Ok(move result) => move result,
|
||||
Err(()) => return Err(())
|
||||
};
|
||||
|
||||
return Ok(@Font {
|
||||
fontbuf : None,
|
||||
handle : move styled_handle,
|
||||
azure_font: None,
|
||||
shaper: None,
|
||||
style: copy *style,
|
||||
metrics: handle.get_metrics(),
|
||||
backend: backend,
|
||||
});
|
||||
}
|
||||
|
||||
priv fn get_shaper(@self) -> @Shaper {
|
||||
|
@ -413,7 +447,7 @@ pub impl Font : FontMethods {
|
|||
}
|
||||
|
||||
fn buf(&self) -> @~[u8] {
|
||||
self.fontbuf
|
||||
option::expect(self.fontbuf, ~"This font has no buffer")
|
||||
}
|
||||
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||
|
|
|
@ -67,6 +67,10 @@ pub impl FontContext {
|
|||
}
|
||||
}
|
||||
|
||||
priv pure fn get_font_list(&self) -> &self/FontList {
|
||||
option::get_ref(&self.font_list)
|
||||
}
|
||||
|
||||
fn get_resolved_font_for_style(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||
// TODO(Issue #178, E): implement a cache of FontGroup instances.
|
||||
self.create_font_group(style)
|
||||
|
@ -88,15 +92,29 @@ pub impl FontContext {
|
|||
}
|
||||
|
||||
priv fn create_font_group(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||
// TODO(Issue #178, D): implement private font matching
|
||||
// TODO(Issue #174): implement by-platform-name FontSelectors
|
||||
let desc = FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy);
|
||||
let fonts = DVec();
|
||||
|
||||
match self.get_font_by_descriptor(&desc) {
|
||||
Ok(instance) => fonts.push(instance),
|
||||
Err(()) => {}
|
||||
}
|
||||
|
||||
// TODO(Issue #193): make iteration over 'font-family' more robust.
|
||||
for str::split_char_each(style.families, ',') |family| {
|
||||
let family_name = str::trim(family);
|
||||
let list = self.get_font_list();
|
||||
|
||||
let result = list.find_font_in_family(family_name, style);
|
||||
do result.iter |font_entry| {
|
||||
let instance = Font::new_from_handle(&self, &font_entry.handle, style, self.backend);
|
||||
do result::iter(&instance) |font: &@Font| { fonts.push(*font); }
|
||||
};
|
||||
}
|
||||
|
||||
// TODO(Issue #194): attach a fallback font to the font list,
|
||||
// so that this assertion will never fail.
|
||||
assert fonts.len() > 0;
|
||||
// TODO(Issue #179): Split FontStyle into specified and used styles
|
||||
let used_style = copy *style;
|
||||
|
@ -105,20 +123,12 @@ pub impl FontContext {
|
|||
}
|
||||
|
||||
priv fn create_font_instance(desc: &FontDescriptor) -> Result<@Font, ()> {
|
||||
match desc.selector {
|
||||
return match desc.selector {
|
||||
SelectorStubDummy => {
|
||||
let font_bin = @test_font_bin();
|
||||
let handle = FontHandle::new(&self.handle, font_bin, desc.style.pt_size);
|
||||
let handle = if handle.is_ok() {
|
||||
result::unwrap(move handle)
|
||||
} else {
|
||||
return Err(handle.get_err());
|
||||
};
|
||||
|
||||
return Ok(@Font::new(font_bin, move handle, copy desc.style, self.backend));
|
||||
Font::new_from_buffer(&self, @test_font_bin(), &desc.style, self.backend)
|
||||
},
|
||||
// TODO(Issue #174): implement by-platform-name font selectors.
|
||||
SelectorPlatformName(_) => { fail ~"FontContext::create_font_instance() can't yet handle SelectorPlatformName." }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ pub impl FontList {
|
|||
let family = self.find_family(family_name);
|
||||
let mut result : Option<@FontEntry> = None;
|
||||
|
||||
// TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
|
||||
|
||||
// if such family exists, try to match style to a font
|
||||
do family.iter |fam| {
|
||||
result = fam.find_font_for_style(style);
|
||||
|
|
|
@ -3,10 +3,23 @@ extern mod core_graphics;
|
|||
extern mod core_text;
|
||||
|
||||
use font_context::QuartzFontContextHandle;
|
||||
use geometry::Au;
|
||||
use servo_gfx_font::{CSSFontWeight, FontHandleMethods, FontMetrics, FontWeight100, FontWeight200};
|
||||
use servo_gfx_font::{FontWeight300, FontWeight400, FontWeight500, FontWeight600, FontWeight700};
|
||||
use servo_gfx_font::{FontWeight800, FontWeight900, FractionalPixel};
|
||||
use gfx::au;
|
||||
use gfx::font::{
|
||||
CSSFontWeight,
|
||||
FontHandleMethods,
|
||||
FontMetrics,
|
||||
FontWeight100,
|
||||
FontWeight200,
|
||||
FontWeight300,
|
||||
FontWeight400,
|
||||
FontWeight500,
|
||||
FontWeight600,
|
||||
FontWeight700,
|
||||
FontWeight800,
|
||||
FontWeight900,
|
||||
FractionalPixel,
|
||||
SpecifiedFontStyle,
|
||||
};
|
||||
use text::glyph::GlyphIndex;
|
||||
|
||||
use cf = core_foundation;
|
||||
|
@ -37,7 +50,8 @@ pub struct QuartzFontHandle {
|
|||
}
|
||||
|
||||
pub impl QuartzFontHandle {
|
||||
static fn new_from_buffer(_fctx: &QuartzFontContextHandle, buf: @~[u8], pt_size: float) -> Result<QuartzFontHandle, ()> {
|
||||
static fn new_from_buffer(_fctx: &QuartzFontContextHandle, buf: @~[u8],
|
||||
style: &SpecifiedFontStyle) -> Result<QuartzFontHandle, ()> {
|
||||
let fontprov = vec::as_imm_buf(*buf, |cbuf, len| {
|
||||
CGDataProvider::new_from_buffer(cbuf, len)
|
||||
});
|
||||
|
@ -45,7 +59,7 @@ pub impl QuartzFontHandle {
|
|||
let cgfont = CGFontCreateWithDataProvider(fontprov.get_ref());
|
||||
if cgfont.is_null() { return Err(()); }
|
||||
|
||||
let ctfont = CTFont::new_from_CGFont(cgfont, pt_size);
|
||||
let ctfont = CTFont::new_from_CGFont(cgfont, style.pt_size);
|
||||
|
||||
let result = Ok(QuartzFontHandle {
|
||||
cgfont : Some(cgfont),
|
||||
|
@ -105,6 +119,10 @@ pub impl QuartzFontHandle : FontHandleMethods {
|
|||
else { return FontWeight900; }
|
||||
}
|
||||
|
||||
fn clone_with_style(fctx: &QuartzFontContextHandle, style: &SpecifiedFontStyle) -> Result<QuartzFontHandle,()> {
|
||||
let new_font = self.ctfont.clone_with_font_size(style.pt_size);
|
||||
return QuartzFontHandle::new_from_CTFont(fctx, move new_font);
|
||||
}
|
||||
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||
let characters: ~[UniChar] = ~[codepoint as UniChar];
|
||||
|
|
|
@ -239,7 +239,7 @@ impl TextRunScanner {
|
|||
// this is probably achieved by creating fontgroup above, and then letting FontGroup decide
|
||||
// which Font to stick into the TextRun.
|
||||
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style());
|
||||
let run = @TextRun::new(fontgroup.fonts[0], move transformed_text);
|
||||
let run = @fontgroup.create_textrun(move transformed_text);
|
||||
debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
|
||||
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump.begin()].d(), run,
|
||||
Range(0, run.text.len()));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue