use crate::style::TextStyle;
use crate::system::TextSystem;
use parley::PositionedLayoutItem;
use parley::StyleProperty;
use parley::style::LineHeight;
use smudge_core::geometry::Size;
pub struct TextLayout {
pub(crate) layout: parley::Layout<()>,
}
impl TextLayout {
pub fn new(text: &str, style: &TextStyle, max_width: Option<f32>) -> TextLayout {
TextSystem::with(|system| {
let mut builder = system
.layouts
.ranged_builder(&mut system.fonts, text, 1.0, false);
builder.push_default(StyleProperty::FontFamily(style.family.clone()));
builder.push_default(StyleProperty::FontSize(style.size));
builder.push_default(StyleProperty::FontWeight(style.weight));
builder.push_default(StyleProperty::LineHeight(LineHeight::FontSizeRelative(
style.line_height,
)));
let mut layout = builder.build(text);
layout.break_all_lines(max_width);
TextLayout { layout }
})
}
pub(crate) fn rebreak(&mut self, max_width: Option<f32>) {
self.layout.break_all_lines(max_width);
}
pub fn size(&self) -> Size {
Size {
width: self.layout.width(),
height: self.layout.height(),
}
}
pub fn line_count(&self) -> usize {
self.layout.len()
}
pub fn glyph_runs(&self) -> impl Iterator<Item = parley::GlyphRun<'_, ()>> + Clone + '_ {
self.layout.lines().flat_map(|line| {
line.items().filter_map(|item| match item {
PositionedLayoutItem::GlyphRun(run) => Some(run),
PositionedLayoutItem::InlineBox(_) => None,
})
})
}
}
#[cfg(test)]
#[path = "layout_tests.rs"]
mod tests;