diff --git a/src/servo/text/font.rs b/src/servo/text/font.rs index 2073161ec85..32e3f5db8d7 100644 --- a/src/servo/text/font.rs +++ b/src/servo/text/font.rs @@ -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"); diff --git a/src/servo/text/native_font/quartz_native_font.rs b/src/servo/text/native_font/quartz_native_font.rs index 0db7a119465..bf848b234e1 100644 --- a/src/servo/text/native_font/quartz_native_font.rs +++ b/src/servo/text/native_font/quartz_native_font.rs @@ -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; } }