mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +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 type FontHandle/& = freetype::font::FreeTypeFontHandle;
|
||||||
|
|
||||||
pub trait FontHandleMethods {
|
pub trait FontHandleMethods {
|
||||||
|
// an identifier usable by FontContextHandle to recreate this FontHandle.
|
||||||
|
pure fn face_identifier() -> ~str;
|
||||||
pure fn family_name() -> ~str;
|
pure fn family_name() -> ~str;
|
||||||
pure fn face_name() -> ~str;
|
pure fn face_name() -> ~str;
|
||||||
pure fn is_italic() -> bool;
|
pure fn is_italic() -> bool;
|
||||||
|
@ -165,17 +167,17 @@ pub impl FontDescriptor : cmp::Eq {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontDescriptor {
|
pub impl FontDescriptor {
|
||||||
static pure fn new(style: &UsedFontStyle, selector: &FontSelector) -> FontDescriptor {
|
static pure fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor {
|
||||||
FontDescriptor {
|
FontDescriptor {
|
||||||
style: copy *style,
|
style: move style,
|
||||||
selector: copy *selector,
|
selector: move selector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A FontSelector is a platform-specific strategy for serializing face names.
|
// A FontSelector is a platform-specific strategy for serializing face names.
|
||||||
pub enum FontSelector {
|
pub enum FontSelector {
|
||||||
SelectorPlatformName(~str),
|
SelectorPlatformIdentifier(~str),
|
||||||
SelectorStubDummy, // aka, use Josephin Sans
|
SelectorStubDummy, // aka, use Josephin Sans
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,8 +185,8 @@ pub enum FontSelector {
|
||||||
pub impl FontSelector : cmp::Eq {
|
pub impl FontSelector : cmp::Eq {
|
||||||
pure fn eq(other: &FontSelector) -> bool {
|
pure fn eq(other: &FontSelector) -> bool {
|
||||||
match (&self, other) {
|
match (&self, other) {
|
||||||
|
(&SelectorPlatformIdentifier(a), &SelectorPlatformIdentifier(b)) => a == b,
|
||||||
(&SelectorStubDummy, &SelectorStubDummy) => true,
|
(&SelectorStubDummy, &SelectorStubDummy) => true,
|
||||||
(&SelectorPlatformName(a), &SelectorPlatformName(b)) => a == b,
|
|
||||||
_ => false
|
_ => 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,()> {
|
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@Font,()> {
|
||||||
|
|
||||||
// TODO(Issue #179): convert between specified and used font style here?
|
// TODO(Issue #179): convert between specified and used font style here?
|
||||||
|
@ -284,14 +300,7 @@ impl Font {
|
||||||
Err(()) => return Err(())
|
Err(()) => return Err(())
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(@Font {
|
return Ok(Font::new_from_adopted_handle(fctx, move styled_handle, style, backend));
|
||||||
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 {
|
||||||
|
@ -454,7 +463,7 @@ pub impl Font : FontMethods {
|
||||||
fn get_descriptor() -> FontDescriptor {
|
fn get_descriptor() -> FontDescriptor {
|
||||||
// TODO(Issue #174): implement by-platform-name FontSelectors,
|
// TODO(Issue #174): implement by-platform-name FontSelectors,
|
||||||
// probably by adding such an API to FontHandle.
|
// 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> {
|
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformName, SelectorStubDummy};
|
use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformIdentifier, SelectorStubDummy};
|
||||||
use font::{SpecifiedFontStyle};
|
use font::{SpecifiedFontStyle, UsedFontStyle};
|
||||||
use font_list::FontList;
|
use font_list::FontList;
|
||||||
use native::FontHandle;
|
use native::FontHandle;
|
||||||
use util::cache;
|
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")]
|
#[cfg(target_os = "macos")]
|
||||||
type FontContextHandle/& = quartz::font_context::QuartzFontContextHandle;
|
type FontContextHandle/& = quartz::font_context::QuartzFontContextHandle;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
type FontContextHandle/& = freetype::font_context::FreeTypeFontContextHandle;
|
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 {
|
pub impl FontContextHandle {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
static pub fn new() -> FontContextHandle {
|
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 {
|
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();
|
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.
|
// TODO(Issue #193): make iteration over 'font-family' more robust.
|
||||||
for str::split_char_each(style.families, ',') |family| {
|
for str::split_char_each(style.families, ',') |family| {
|
||||||
let family_name = str::trim(family);
|
let family_name = str::trim(family);
|
||||||
|
@ -108,13 +106,23 @@ pub impl FontContext {
|
||||||
|
|
||||||
let result = list.find_font_in_family(family_name, style);
|
let result = list.find_font_in_family(family_name, style);
|
||||||
do result.iter |font_entry| {
|
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); }
|
do result::iter(&instance) |font: &@Font| { fonts.push(*font); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Issue #194): attach a fallback font to the font list,
|
// TODO(Issue #194): *always* attach a fallback font to the
|
||||||
// so that this assertion will never fail.
|
// 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;
|
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;
|
||||||
|
@ -128,7 +136,12 @@ pub impl FontContext {
|
||||||
Font::new_from_buffer(&self, test_font_bin(), &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.
|
// 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 native::FontHandle;
|
||||||
|
|
||||||
use dvec::DVec;
|
use dvec::DVec;
|
||||||
|
@ -59,6 +59,10 @@ pub impl FontList {
|
||||||
do family.iter |fam| {
|
do family.iter |fam| {
|
||||||
result = fam.find_font_for_style(style);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +70,9 @@ pub impl FontList {
|
||||||
// look up canonical name
|
// look up canonical name
|
||||||
let family = self.family_map.find(&str::from_slice(family_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
|
// TODO(Issue #188): look up localized font family names if canonical name not found
|
||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,5 +188,9 @@ pub impl QuartzFontHandle : FontHandleMethods {
|
||||||
Some(data.copy_to_buf())
|
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 {
|
pub struct QuartzFontContextHandle {
|
||||||
ctx: (),
|
ctx: (),
|
||||||
|
|
||||||
|
@ -9,4 +20,13 @@ pub impl QuartzFontContextHandle {
|
||||||
static pub fn new() -> QuartzFontContextHandle {
|
static pub fn new() -> QuartzFontContextHandle {
|
||||||
QuartzFontContextHandle { ctx: () }
|
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;
|
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