mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40: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 {
|
pub impl Font : FontMethods {
|
||||||
fn measure_text(run: &TextRun, offset: uint, length: uint) -> RunMetrics {
|
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: 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 advance = au(0);
|
||||||
let mut bounds = Rect(Point2D(au(0), em_size.scale_by(-em_ascent)),
|
let mut bounds = Rect(Point2D(au(0), -self.metrics.ascent),
|
||||||
Size2D(au(0), em_size.scale_by(em_ascent + em_descent)));
|
Size2D(au(0), self.metrics.ascent + self.metrics.descent));
|
||||||
do run.glyphs.iter_glyphs_for_range(offset, length) |_i, glyph| {
|
do run.glyphs.iter_glyphs_for_range(offset, length) |_i, glyph| {
|
||||||
advance += glyph.advance();
|
advance += glyph.advance();
|
||||||
bounds = bounds.translate(&Point2D(glyph.advance(), au(0)));
|
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
|
// ascent+descent and advance is sometimes too generous and
|
||||||
// looking at actual glyph extents can yield a tighter box.
|
// looking at actual glyph extents can yield a tighter box.
|
||||||
|
|
||||||
let metrics = RunMetrics { advance_width: advance,
|
let metrics = RunMetrics { advance_width: advance,
|
||||||
bounding_box: bounds,
|
bounding_box: bounds,
|
||||||
ascent: em_size.scale_by(em_ascent),
|
ascent: self.metrics.ascent,
|
||||||
descent: em_size.scale_by(em_descent),
|
descent: self.metrics.descent,
|
||||||
};
|
};
|
||||||
|
debug!("Measured text range '%s' with metrics:", run.text.substr(offset, length));
|
||||||
|
debug!("%?", metrics);
|
||||||
|
|
||||||
return 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?
|
// TODO: who should own fontbuf?
|
||||||
fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
|
fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
|
||||||
let metrics = native_font.get_metrics();
|
let metrics = native_font.get_metrics();
|
||||||
|
@ -103,24 +100,21 @@ fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font {
|
||||||
Font {
|
Font {
|
||||||
lib: lib,
|
lib: lib,
|
||||||
fontbuf : fontbuf,
|
fontbuf : fontbuf,
|
||||||
|
metrics: move metrics,
|
||||||
native_font : move native_font,
|
native_font : move native_font,
|
||||||
metrics: move metrics
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most of these metrics are in terms of em. Use em_size to convert to au.
|
// Most of these metrics are in terms of em. Use em_size to convert to au.
|
||||||
struct FontMetrics {
|
struct FontMetrics {
|
||||||
underline_size: float,
|
underline_size: au,
|
||||||
underline_offset: float,
|
underline_offset: au,
|
||||||
leading: float,
|
leading: au,
|
||||||
x_height: float,
|
x_height: au,
|
||||||
|
|
||||||
// how many appunits an em is equivalent to (based on point-to-au)
|
|
||||||
em_size: au,
|
em_size: au,
|
||||||
em_height: float,
|
ascent: au,
|
||||||
em_ascent: float,
|
descent: au,
|
||||||
em_descent: float,
|
max_advance: au
|
||||||
max_advance: float
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
|
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
|
||||||
|
|
|
@ -34,6 +34,7 @@ mod coretext {
|
||||||
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
|
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
|
||||||
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;
|
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;
|
||||||
|
|
||||||
|
// TODO: this is actually a libc::c_float on 32bit
|
||||||
pub type CGFloat = libc::c_double;
|
pub type CGFloat = libc::c_double;
|
||||||
|
|
||||||
pub struct CGSize {
|
pub struct CGSize {
|
||||||
|
@ -61,14 +62,16 @@ mod coretext {
|
||||||
pub fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *UniChar, glyphs: *CGGlyph, count: CFIndex) -> bool;
|
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 CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *CGGlyph, advances: *CGSize, count: CFIndex) -> libc::c_double;
|
||||||
|
|
||||||
|
pub fn CTFontGetSize(font: CTFontRef) -> CGFloat;
|
||||||
|
|
||||||
/* metrics API */
|
/* metrics API */
|
||||||
pub fn CTFontGetAscent(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetAscent(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetDescent(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetDescent(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetLeading(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetLeading(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
|
pub fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
|
||||||
pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetXHeight(font: CTFontRef) -> libc::c_float;
|
pub fn CTFontGetXHeight(font: CTFontRef) -> CGFloat;
|
||||||
pub fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
|
pub fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
|
||||||
|
|
||||||
pub fn CFRelease(font: CTFontRef);
|
pub fn CFRelease(font: CTFontRef);
|
||||||
|
@ -151,22 +154,26 @@ impl QuartzNativeFont {
|
||||||
let ctfont = self.ctfont;
|
let ctfont = self.ctfont;
|
||||||
assert ctfont.is_not_null();
|
assert ctfont.is_not_null();
|
||||||
|
|
||||||
let convFactor : float = 1.0 / (CTFontGetUnitsPerEm(ctfont) as float);
|
|
||||||
let bounding_rect: CGRect = CTFontGetBoundingBox(ctfont);
|
let bounding_rect: CGRect = CTFontGetBoundingBox(ctfont);
|
||||||
let em_ascent = CTFontGetAscent(ctfont) as float * convFactor;
|
let ascent = au::from_pt(CTFontGetAscent(ctfont) as float);
|
||||||
let em_descent = CTFontGetDescent(ctfont) as float * convFactor;
|
let descent = au::from_pt(CTFontGetDescent(ctfont) as float);
|
||||||
|
|
||||||
return FontMetrics {
|
let metrics = FontMetrics {
|
||||||
underline_size: CTFontGetUnderlineThickness(ctfont) as float * convFactor,
|
underline_size: au::from_pt(CTFontGetUnderlineThickness(ctfont) as float),
|
||||||
underline_offset: CTFontGetUnderlinePosition(ctfont) as float * convFactor,
|
// TODO: underline metrics are not reliable. Have to pull out of font table directly.
|
||||||
leading: CTFontGetLeading(ctfont) as float * convFactor,
|
// see also: https://bugs.webkit.org/show_bug.cgi?id=16768
|
||||||
x_height: CTFontGetXHeight(ctfont) as float * convFactor,
|
// see also: https://bugreports.qt-project.org/browse/QTBUG-13364
|
||||||
em_ascent: CTFontGetAscent(ctfont) as float * convFactor,
|
underline_offset: au::from_pt(CTFontGetUnderlinePosition(ctfont) as float),
|
||||||
em_descent: CTFontGetDescent(ctfont) as float * convFactor,
|
leading: au::from_pt(CTFontGetLeading(ctfont) as float),
|
||||||
em_height: em_ascent + em_descent,
|
x_height: au::from_pt(CTFontGetXHeight(ctfont) as float),
|
||||||
em_size: au::from_pt(21f),
|
em_size: ascent + descent,
|
||||||
max_advance: bounding_rect.size.width as float * convFactor,
|
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