Fix CoreText font metrics bindings.

This commit is contained in:
Brian J. Burg 2012-10-15 15:09:24 -07:00
parent ec9cbeb150
commit a81bf8692e
2 changed files with 43 additions and 42 deletions

View file

@ -52,29 +52,27 @@ pub trait FontMethods {
pub impl Font : FontMethods {
fn measure_text(run: &TextRun, offset: uint, length: uint) -> RunMetrics {
let em_size = self.metrics.em_size;
let em_ascent = self.metrics.em_ascent;
let em_descent = self.metrics.em_descent;
// TODO: alter advance direction for RTL
// TODO: using inter-char and inter-word spacing settings when measuring text
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
let mut advance = au(0);
let mut bounds = Rect(Point2D(au(0), em_size.scale_by(-em_ascent)),
Size2D(au(0), em_size.scale_by(em_ascent + em_descent)));
let mut bounds = Rect(Point2D(au(0), -self.metrics.ascent),
Size2D(au(0), self.metrics.ascent + self.metrics.descent));
do run.glyphs.iter_glyphs_for_range(offset, length) |_i, glyph| {
advance += glyph.advance();
bounds = bounds.translate(&Point2D(glyph.advance(), au(0)));
}
// TODO: support loose and tight bounding boxes; using the
// TODO(Issue #125): support loose and tight bounding boxes; using the
// ascent+descent and advance is sometimes too generous and
// looking at actual glyph extents can yield a tighter box.
let metrics = RunMetrics { advance_width: advance,
bounding_box: bounds,
ascent: em_size.scale_by(em_ascent),
descent: em_size.scale_by(em_descent),
ascent: self.metrics.ascent,
descent: self.metrics.descent,
};
debug!("Measured text range '%s' with metrics:", run.text.substr(offset, length));
debug!("%?", metrics);
return metrics;
}
@ -95,7 +93,6 @@ pub impl Font : FontMethods {
}
}
// TODO: font should compute its own metrics using native_font.
// TODO: who should own fontbuf?
fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
let metrics = native_font.get_metrics();
@ -103,24 +100,21 @@ fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
Font {
lib: lib,
fontbuf : fontbuf,
metrics: move metrics,
native_font : move native_font,
metrics: move metrics
}
}
// Most of these metrics are in terms of em. Use em_size to convert to au.
struct FontMetrics {
underline_size: float,
underline_offset: float,
leading: float,
x_height: float,
// how many appunits an em is equivalent to (based on point-to-au)
underline_size: au,
underline_offset: au,
leading: au,
x_height: au,
em_size: au,
em_height: float,
em_ascent: float,
em_descent: float,
max_advance: float
ascent: au,
descent: au,
max_advance: au
}
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");

View file

@ -34,6 +34,7 @@ mod coretext {
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;
// TODO: this is actually a libc::c_float on 32bit
pub type CGFloat = libc::c_double;
pub struct CGSize {
@ -61,14 +62,16 @@ mod coretext {
pub fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *UniChar, glyphs: *CGGlyph, count: CFIndex) -> bool;
pub fn CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *CGGlyph, advances: *CGSize, count: CFIndex) -> libc::c_double;
pub fn CTFontGetSize(font: CTFontRef) -> CGFloat;
/* metrics API */
pub fn CTFontGetAscent(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetDescent(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetLeading(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetAscent(font: CTFontRef) -> CGFloat;
pub fn CTFontGetDescent(font: CTFontRef) -> CGFloat;
pub fn CTFontGetLeading(font: CTFontRef) -> CGFloat;
pub fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetXHeight(font: CTFontRef) -> libc::c_float;
pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat;
pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat;
pub fn CTFontGetXHeight(font: CTFontRef) -> CGFloat;
pub fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
pub fn CFRelease(font: CTFontRef);
@ -151,22 +154,26 @@ impl QuartzNativeFont {
let ctfont = self.ctfont;
assert ctfont.is_not_null();
let convFactor : float = 1.0 / (CTFontGetUnitsPerEm(ctfont) as float);
let bounding_rect: CGRect = CTFontGetBoundingBox(ctfont);
let em_ascent = CTFontGetAscent(ctfont) as float * convFactor;
let em_descent = CTFontGetDescent(ctfont) as float * convFactor;
let ascent = au::from_pt(CTFontGetAscent(ctfont) as float);
let descent = au::from_pt(CTFontGetDescent(ctfont) as float);
return FontMetrics {
underline_size: CTFontGetUnderlineThickness(ctfont) as float * convFactor,
underline_offset: CTFontGetUnderlinePosition(ctfont) as float * convFactor,
leading: CTFontGetLeading(ctfont) as float * convFactor,
x_height: CTFontGetXHeight(ctfont) as float * convFactor,
em_ascent: CTFontGetAscent(ctfont) as float * convFactor,
em_descent: CTFontGetDescent(ctfont) as float * convFactor,
em_height: em_ascent + em_descent,
em_size: au::from_pt(21f),
max_advance: bounding_rect.size.width as float * convFactor,
}
let metrics = FontMetrics {
underline_size: au::from_pt(CTFontGetUnderlineThickness(ctfont) as float),
// TODO: underline metrics are not reliable. Have to pull out of font table directly.
// see also: https://bugs.webkit.org/show_bug.cgi?id=16768
// see also: https://bugreports.qt-project.org/browse/QTBUG-13364
underline_offset: au::from_pt(CTFontGetUnderlinePosition(ctfont) as float),
leading: au::from_pt(CTFontGetLeading(ctfont) as float),
x_height: au::from_pt(CTFontGetXHeight(ctfont) as float),
em_size: ascent + descent,
ascent: ascent,
descent: descent,
max_advance: au::from_pt(bounding_rect.size.width as float)
};
debug!("Font metrics (@%f pt): %?", CTFontGetSize(ctfont) as float, metrics);
return metrics;
}
}