mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Finish implementing first cut at font matching. Closes #174.
This commit is contained in:
parent
ebb9392587
commit
0d135a4fa5
8 changed files with 89 additions and 34 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 3e5e34f4f46598a85465f4fb754ccaff04a98e4c
|
||||
Subproject commit 7fcbf5112ec163bdc14f096ddd9a45ef744ca6a6
|
|
@ -1 +1 @@
|
|||
Subproject commit dab5176896750f512410e24e33852ccaf13dbf08
|
||||
Subproject commit 4c38ba65d4929ba418317c9fd9d16a0aa83945c9
|
|
@ -23,6 +23,8 @@ pub type FontHandle/& = quartz::font::QuartzFontHandle;
|
|||
pub type FontHandle/& = freetype::font::FreeTypeFontHandle;
|
||||
|
||||
pub trait FontHandleMethods {
|
||||
// an identifier usable by FontContextHandle to recreate this FontHandle.
|
||||
pure fn face_identifier() -> ~str;
|
||||
pure fn family_name() -> ~str;
|
||||
pure fn face_name() -> ~str;
|
||||
pure fn is_italic() -> bool;
|
||||
|
@ -165,17 +167,17 @@ pub impl FontDescriptor : cmp::Eq {
|
|||
}
|
||||
|
||||
pub impl FontDescriptor {
|
||||
static pure fn new(style: &UsedFontStyle, selector: &FontSelector) -> FontDescriptor {
|
||||
static pure fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor {
|
||||
FontDescriptor {
|
||||
style: copy *style,
|
||||
selector: copy *selector,
|
||||
style: move style,
|
||||
selector: move selector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A FontSelector is a platform-specific strategy for serializing face names.
|
||||
pub enum FontSelector {
|
||||
SelectorPlatformName(~str),
|
||||
SelectorPlatformIdentifier(~str),
|
||||
SelectorStubDummy, // aka, use Josephin Sans
|
||||
}
|
||||
|
||||
|
@ -183,8 +185,8 @@ pub enum FontSelector {
|
|||
pub impl FontSelector : cmp::Eq {
|
||||
pure fn eq(other: &FontSelector) -> bool {
|
||||
match (&self, other) {
|
||||
(&SelectorPlatformIdentifier(a), &SelectorPlatformIdentifier(b)) => a == b,
|
||||
(&SelectorStubDummy, &SelectorStubDummy) => true,
|
||||
(&SelectorPlatformName(a), &SelectorPlatformName(b)) => a == b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +277,21 @@ impl Font {
|
|||
});
|
||||
}
|
||||
|
||||
static fn new_from_handle(fctx: &FontContext, handle: &FontHandle,
|
||||
static fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle,
|
||||
style: &SpecifiedFontStyle, backend: BackendType) -> @Font {
|
||||
let metrics = handle.get_metrics();
|
||||
|
||||
@Font {
|
||||
handle : move handle,
|
||||
azure_font: None,
|
||||
shaper: None,
|
||||
style: copy *style,
|
||||
metrics: move metrics,
|
||||
backend: backend,
|
||||
}
|
||||
}
|
||||
|
||||
static fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle,
|
||||
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font,()> {
|
||||
|
||||
// TODO(Issue #179): convert between specified and used font style here?
|
||||
|
@ -284,14 +300,7 @@ impl Font {
|
|||
Err(()) => return Err(())
|
||||
};
|
||||
|
||||
return Ok(@Font {
|
||||
handle : move styled_handle,
|
||||
azure_font: None,
|
||||
shaper: None,
|
||||
style: copy *style,
|
||||
metrics: handle.get_metrics(),
|
||||
backend: backend,
|
||||
});
|
||||
return Ok(Font::new_from_adopted_handle(fctx, move styled_handle, style, backend));
|
||||
}
|
||||
|
||||
priv fn get_shaper(@self) -> @Shaper {
|
||||
|
@ -454,7 +463,7 @@ pub impl Font : FontMethods {
|
|||
fn get_descriptor() -> FontDescriptor {
|
||||
// TODO(Issue #174): implement by-platform-name FontSelectors,
|
||||
// probably by adding such an API to FontHandle.
|
||||
FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy)
|
||||
FontDescriptor::new(copy self.style, SelectorPlatformIdentifier(self.handle.face_identifier()))
|
||||
}
|
||||
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformName, SelectorStubDummy};
|
||||
use font::{SpecifiedFontStyle};
|
||||
use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformIdentifier, SelectorStubDummy};
|
||||
use font::{SpecifiedFontStyle, UsedFontStyle};
|
||||
use font_list::FontList;
|
||||
use native::FontHandle;
|
||||
use util::cache;
|
||||
|
@ -27,14 +27,18 @@ pub fn dummy_style() -> FontStyle {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(Issue #163): this is a workaround for static methods and
|
||||
// typedefs not working well together. It should be removed.
|
||||
#[cfg(target_os = "macos")]
|
||||
type FontContextHandle/& = quartz::font_context::QuartzFontContextHandle;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
type FontContextHandle/& = freetype::font_context::FreeTypeFontContextHandle;
|
||||
|
||||
trait FontContextHandleMethods {
|
||||
fn create_font_from_identifier(~str, UsedFontStyle) -> Result<FontHandle, ()>;
|
||||
}
|
||||
|
||||
// TODO(Issue #163): this is a workaround for static methods, traits,
|
||||
// and typedefs not working well together. It should be removed.
|
||||
pub impl FontContextHandle {
|
||||
#[cfg(target_os = "macos")]
|
||||
static pub fn new() -> FontContextHandle {
|
||||
|
@ -91,16 +95,10 @@ pub impl FontContext {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO:(Issue #196): cache font groups on the font context.
|
||||
priv fn create_font_group(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||
// 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);
|
||||
|
@ -108,13 +106,23 @@ pub impl FontContext {
|
|||
|
||||
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);
|
||||
// TODO(Issue #203): route this instantion through FontContext's Font instance cache.
|
||||
let instance = Font::new_from_existing_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.
|
||||
// TODO(Issue #194): *always* attach a fallback font to the
|
||||
// font list, so that this assertion will never fail.
|
||||
|
||||
// assert fonts.len() > 0;
|
||||
if fonts.len() == 0 {
|
||||
let desc = FontDescriptor::new(font_context::dummy_style(), SelectorStubDummy);
|
||||
match self.get_font_by_descriptor(&desc) {
|
||||
Ok(instance) => fonts.push(instance),
|
||||
Err(()) => {}
|
||||
}
|
||||
}
|
||||
assert fonts.len() > 0;
|
||||
// TODO(Issue #179): Split FontStyle into specified and used styles
|
||||
let used_style = copy *style;
|
||||
|
@ -128,7 +136,12 @@ pub impl FontContext {
|
|||
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." }
|
||||
SelectorPlatformIdentifier(identifier) => {
|
||||
let result_handle = self.handle.create_font_from_identifier(identifier, copy desc.style);
|
||||
result::chain(move result_handle, |handle| {
|
||||
Ok(Font::new_from_adopted_handle(&self, move handle, &desc.style, self.backend))
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use font::{CSSFontWeight, SpecifiedFontStyle};
|
||||
use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle};
|
||||
use native::FontHandle;
|
||||
|
||||
use dvec::DVec;
|
||||
|
@ -59,6 +59,10 @@ pub impl FontList {
|
|||
do family.iter |fam| {
|
||||
result = fam.find_font_for_style(style);
|
||||
}
|
||||
|
||||
let decision = if result.is_some() { "Found" } else { "Couldn't find" };
|
||||
debug!("FontList: %s font face in family[%?] matching style: %?", decision, style, family_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -66,6 +70,9 @@ pub impl FontList {
|
|||
// look up canonical name
|
||||
let family = self.family_map.find(&str::from_slice(family_name));
|
||||
|
||||
let decision = if family.is_some() { "Found" } else { "Couldn't find" };
|
||||
debug!("FontList: %s font family with name=%s", decision, family_name);
|
||||
|
||||
// TODO(Issue #188): look up localized font family names if canonical name not found
|
||||
return family;
|
||||
}
|
||||
|
|
|
@ -188,5 +188,9 @@ pub impl QuartzFontHandle : FontHandleMethods {
|
|||
Some(data.copy_to_buf())
|
||||
});
|
||||
}
|
||||
|
||||
pure fn face_identifier() -> ~str {
|
||||
self.ctfont.postscript_name()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
extern mod core_foundation;
|
||||
extern mod core_graphics;
|
||||
extern mod core_text;
|
||||
|
||||
use ct = core_text;
|
||||
use ct::font::CTFont;
|
||||
|
||||
use gfx_font::{FontHandle, UsedFontStyle};
|
||||
use font::QuartzFontHandle;
|
||||
use gfx_font_context::FontContextHandleMethods;
|
||||
|
||||
pub struct QuartzFontContextHandle {
|
||||
ctx: (),
|
||||
|
||||
|
@ -9,4 +20,13 @@ pub impl QuartzFontContextHandle {
|
|||
static pub fn new() -> QuartzFontContextHandle {
|
||||
QuartzFontContextHandle { ctx: () }
|
||||
}
|
||||
}
|
||||
|
||||
pub impl QuartzFontContextHandle : FontContextHandleMethods {
|
||||
fn create_font_from_identifier(name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> {
|
||||
let ctfont_result = CTFont::new_from_name(move name, style.pt_size);
|
||||
do result::chain(move ctfont_result) |ctfont| {
|
||||
QuartzFontHandle::new_from_CTFont(&self, move ctfont)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -91,4 +91,6 @@ pub mod util {
|
|||
pub mod vec;
|
||||
}
|
||||
|
||||
use gfx_font = font;
|
||||
use gfx_font = font;
|
||||
use gfx_font_context = font_context;
|
||||
use gfx_font_list = font_list;
|
Loading…
Add table
Add a link
Reference in a new issue