mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +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 is_italic() -> bool;
|
||||||
pure fn boldness() -> CSSFontWeight;
|
pure fn boldness() -> CSSFontWeight;
|
||||||
|
|
||||||
|
fn clone_with_style(fctx: &native::FontContextHandle, style: &UsedFontStyle) -> Result<FontHandle, ()>;
|
||||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
fn glyph_index(codepoint: char) -> Option<GlyphIndex>;
|
||||||
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
fn glyph_h_advance(GlyphIndex) -> Option<FractionalPixel>;
|
||||||
fn get_metrics() -> FontMetrics;
|
fn get_metrics() -> FontMetrics;
|
||||||
|
@ -38,13 +39,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], pt_size: float) -> Result<FontHandle, ()> {
|
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||||
quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, pt_size)
|
quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, style)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||||
freetype::font::FreeTypeFontHandle::new(fctx, buf, pt_size)
|
freetype::font::FreeTypeFontHandle::new(fctx, buf, style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +195,13 @@ pub impl FontGroup {
|
||||||
fonts: move fonts,
|
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 {
|
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.
|
and the renderer can use it to render text.
|
||||||
*/
|
*/
|
||||||
pub struct Font {
|
pub struct Font {
|
||||||
priv fontbuf: @~[u8],
|
priv mut fontbuf: Option<@~[u8]>,
|
||||||
priv handle: FontHandle,
|
priv handle: FontHandle,
|
||||||
priv mut azure_font: Option<AzScaledFontRef>,
|
priv mut azure_font: Option<AzScaledFontRef>,
|
||||||
priv mut shaper: Option<@Shaper>,
|
priv mut shaper: Option<@Shaper>,
|
||||||
|
@ -226,22 +234,48 @@ pub struct Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Font {
|
impl Font {
|
||||||
// TODO: who should own fontbuf?
|
static fn new_from_buffer(ctx: &FontContext, buffer: @~[u8],
|
||||||
static fn new(fontbuf: @~[u8],
|
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font, ()> {
|
||||||
handle: FontHandle,
|
|
||||||
style: UsedFontStyle,
|
|
||||||
backend: BackendType) -> Font {
|
|
||||||
let metrics = handle.get_metrics();
|
|
||||||
|
|
||||||
Font {
|
let handle = FontHandle::new(&ctx.handle, buffer, style);
|
||||||
fontbuf : fontbuf,
|
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,
|
handle : move handle,
|
||||||
azure_font: None,
|
azure_font: None,
|
||||||
shaper: None,
|
shaper: None,
|
||||||
style: move style,
|
style: copy *style,
|
||||||
metrics: move metrics,
|
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 {
|
priv fn get_shaper(@self) -> @Shaper {
|
||||||
|
@ -413,7 +447,7 @@ pub impl Font : FontMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buf(&self) -> @~[u8] {
|
fn buf(&self) -> @~[u8] {
|
||||||
self.fontbuf
|
option::expect(self.fontbuf, ~"This font has no buffer")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
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 {
|
fn get_resolved_font_for_style(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||||
// TODO(Issue #178, E): implement a cache of FontGroup instances.
|
// TODO(Issue #178, E): implement a cache of FontGroup instances.
|
||||||
self.create_font_group(style)
|
self.create_font_group(style)
|
||||||
|
@ -88,15 +92,29 @@ pub impl FontContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn create_font_group(style: &SpecifiedFontStyle) -> @FontGroup {
|
priv fn create_font_group(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||||
// TODO(Issue #178, D): implement private font matching
|
|
||||||
// TODO(Issue #174): implement by-platform-name FontSelectors
|
// TODO(Issue #174): implement by-platform-name FontSelectors
|
||||||
let desc = FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy);
|
let desc = FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy);
|
||||||
let fonts = DVec();
|
let fonts = DVec();
|
||||||
|
|
||||||
match self.get_font_by_descriptor(&desc) {
|
match self.get_font_by_descriptor(&desc) {
|
||||||
Ok(instance) => fonts.push(instance),
|
Ok(instance) => fonts.push(instance),
|
||||||
Err(()) => {}
|
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;
|
assert fonts.len() > 0;
|
||||||
// TODO(Issue #179): Split FontStyle into specified and used styles
|
// TODO(Issue #179): Split FontStyle into specified and used styles
|
||||||
let used_style = copy *style;
|
let used_style = copy *style;
|
||||||
|
@ -105,20 +123,12 @@ pub impl FontContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn create_font_instance(desc: &FontDescriptor) -> Result<@Font, ()> {
|
priv fn create_font_instance(desc: &FontDescriptor) -> Result<@Font, ()> {
|
||||||
match desc.selector {
|
return match desc.selector {
|
||||||
SelectorStubDummy => {
|
SelectorStubDummy => {
|
||||||
let font_bin = @test_font_bin();
|
Font::new_from_buffer(&self, @test_font_bin(), &desc.style, self.backend)
|
||||||
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));
|
|
||||||
},
|
},
|
||||||
// TODO(Issue #174): implement by-platform-name font selectors.
|
// TODO(Issue #174): implement by-platform-name font selectors.
|
||||||
SelectorPlatformName(_) => { fail ~"FontContext::create_font_instance() can't yet handle SelectorPlatformName." }
|
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 family = self.find_family(family_name);
|
||||||
let mut result : Option<@FontEntry> = None;
|
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
|
// if such family exists, try to match style to a font
|
||||||
do family.iter |fam| {
|
do family.iter |fam| {
|
||||||
result = fam.find_font_for_style(style);
|
result = fam.find_font_for_style(style);
|
||||||
|
|
|
@ -3,10 +3,23 @@ extern mod core_graphics;
|
||||||
extern mod core_text;
|
extern mod core_text;
|
||||||
|
|
||||||
use font_context::QuartzFontContextHandle;
|
use font_context::QuartzFontContextHandle;
|
||||||
use geometry::Au;
|
use gfx::au;
|
||||||
use servo_gfx_font::{CSSFontWeight, FontHandleMethods, FontMetrics, FontWeight100, FontWeight200};
|
use gfx::font::{
|
||||||
use servo_gfx_font::{FontWeight300, FontWeight400, FontWeight500, FontWeight600, FontWeight700};
|
CSSFontWeight,
|
||||||
use servo_gfx_font::{FontWeight800, FontWeight900, FractionalPixel};
|
FontHandleMethods,
|
||||||
|
FontMetrics,
|
||||||
|
FontWeight100,
|
||||||
|
FontWeight200,
|
||||||
|
FontWeight300,
|
||||||
|
FontWeight400,
|
||||||
|
FontWeight500,
|
||||||
|
FontWeight600,
|
||||||
|
FontWeight700,
|
||||||
|
FontWeight800,
|
||||||
|
FontWeight900,
|
||||||
|
FractionalPixel,
|
||||||
|
SpecifiedFontStyle,
|
||||||
|
};
|
||||||
use text::glyph::GlyphIndex;
|
use text::glyph::GlyphIndex;
|
||||||
|
|
||||||
use cf = core_foundation;
|
use cf = core_foundation;
|
||||||
|
@ -37,7 +50,8 @@ pub struct QuartzFontHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl 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| {
|
let fontprov = vec::as_imm_buf(*buf, |cbuf, len| {
|
||||||
CGDataProvider::new_from_buffer(cbuf, len)
|
CGDataProvider::new_from_buffer(cbuf, len)
|
||||||
});
|
});
|
||||||
|
@ -45,7 +59,7 @@ pub impl QuartzFontHandle {
|
||||||
let cgfont = CGFontCreateWithDataProvider(fontprov.get_ref());
|
let cgfont = CGFontCreateWithDataProvider(fontprov.get_ref());
|
||||||
if cgfont.is_null() { return Err(()); }
|
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 {
|
let result = Ok(QuartzFontHandle {
|
||||||
cgfont : Some(cgfont),
|
cgfont : Some(cgfont),
|
||||||
|
@ -105,6 +119,10 @@ pub impl QuartzFontHandle : FontHandleMethods {
|
||||||
else { return FontWeight900; }
|
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> {
|
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||||
let characters: ~[UniChar] = ~[codepoint as UniChar];
|
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
|
// this is probably achieved by creating fontgroup above, and then letting FontGroup decide
|
||||||
// which Font to stick into the TextRun.
|
// which Font to stick into the TextRun.
|
||||||
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style());
|
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);
|
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,
|
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump.begin()].d(), run,
|
||||||
Range(0, run.text.len()));
|
Range(0, run.text.len()));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue