use std::cell::RefCell;
use std::ops::Range;
use kurbo::{Affine, Point, Size};
use peniko::Brush;
use frust_scene::GlyphRun;
pub(crate) struct LineInfo {
pub range: Range<usize>,
pub width: f32,
}
pub struct TextLayout {
layout: parley::Layout<Brush>,
size: Size,
base_runs: RefCell<Option<Vec<GlyphRun>>>,
}
impl TextLayout {
pub(crate) fn new(layout: parley::Layout<Brush>) -> Self {
let size = Size::new(layout.width() as f64, layout.height() as f64);
Self {
layout,
size,
base_runs: RefCell::new(None),
}
}
pub fn size(&self) -> Size {
self.size
}
pub fn to_scene_runs(&self, origin: Point) -> Vec<GlyphRun> {
let mut memo = self.base_runs.borrow_mut();
let base = memo.get_or_insert_with(|| {
crate::convert::layout_to_scene_runs(&self.layout, Point::ORIGIN)
});
let transform = Affine::translate((origin.x, origin.y));
base.iter()
.map(|run| GlyphRun {
transform,
..run.clone()
})
.collect()
}
pub(crate) fn line_count(&self) -> usize {
self.layout.len()
}
pub(crate) fn line_info(&self, index: usize) -> Option<LineInfo> {
let line = self.layout.get(index)?;
let metrics = line.metrics();
Some(LineInfo {
range: line.text_range(),
width: (metrics.advance - metrics.trailing_whitespace).max(0.0),
})
}
}