///|
/// Measure text with this font profile.
pub fn FontMetrics::measure(self : FontMetrics, text : String) -> TextMetrics {
let lines = text.split("\n").to_array()
let measure_line = (line : StringView) => {
let (_, advance, glyph_count) = line.fold(init=(None, 0.0F, 0), (
state,
char,
) => {
let (previous, advance, glyph_count) = state
let char_advance = if char == '\t' {
let tab_width = (self.char_advance(' ') * Float::from_int(self.tab_size)).max(
1.0F,
)
tab_width - Float::mod(advance, tab_width)
} else {
self.char_advance(char) +
({
guard char != ' ' else {
Float::from_int(self.word_spacing) * 1000.0F
}
0.0
})
}
let pair_adjustment = {
guard self.profile != Sans else { 0.0F }
previous.map_or(0.0F, left => self.kerning(left, char))
}
let next_previous = {
guard char_advance > 0.0F else { previous }
Some(char)
}
(
next_previous,
advance + char_advance + pair_adjustment,
glyph_count + (if char_advance > 0.0F { 1 } else { 0 }),
)
})
advance +
Float::from_int((glyph_count - 1).max(0) * self.letter_spacing) * 1000.0F
}
let width_units = lines.fold(init=0.0F, (widest, line) => {
widest.max(measure_line(line))
})
let advance_width = width_units.ceil_pixels()
let (ink_left, ink_right) = {
guard self.style is Italic && advance_width > 0 else { (0, 0) }
(self.italic_overhang, self.italic_overhang)
}
{
width: advance_width + ink_left + ink_right,
advance_width,
height: lines.length().max(1) * self.line_height,
ascent: self.ascent,
descent: self.descent,
baseline: self.ascent,
ink_left,
ink_right,
}
}