mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Fix CoreText font metrics bindings.
This commit is contained in:
parent
ec9cbeb150
commit
a81bf8692e
2 changed files with 43 additions and 42 deletions
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue