use crate::backend::TextBackend;
use crate::error::TextError;
use crate::types::{ShapedLine, TextAlignment};
#[inline]
pub fn compute_alignment_offset(
line_width_lpx: f32,
container_width_lpx: f32,
alignment: TextAlignment,
) -> f32 {
match alignment {
TextAlignment::Left => 0.0,
TextAlignment::Center => (container_width_lpx - line_width_lpx) / 2.0,
TextAlignment::Right => container_width_lpx - line_width_lpx,
}
}
pub fn truncate_with_ellipsis<B: TextBackend>(
backend: &B,
font: &B::Font,
shaped: &ShapedLine,
max_width_lpx: f32,
) -> Result<ShapedLine, TextError> {
if shaped.width_lpx <= max_width_lpx {
return Ok(shaped.clone());
}
let ellipsis = backend.shape_line(font, "...")?;
let target_width = max_width_lpx - ellipsis.width_lpx;
if target_width <= 0.0 {
return Ok(ShapedLine {
glyphs: ellipsis.glyphs,
width_lpx: ellipsis.width_lpx,
ascent_lpx: shaped.ascent_lpx,
descent_lpx: shaped.descent_lpx,
y_offset_lpx: shaped.y_offset_lpx,
base_direction: shaped.base_direction,
runs: Vec::new(),
});
}
let mut cumulative = 0.0f32;
let mut cut_idx = 0;
for (i, g) in shaped.glyphs.iter().enumerate() {
if cumulative + g.x_advance_lpx > target_width {
break;
}
cumulative += g.x_advance_lpx;
cut_idx = i + 1;
}
let mut truncated_glyphs = shaped.glyphs[..cut_idx].to_vec();
let truncated_width = cumulative;
for eg in &ellipsis.glyphs {
let mut shifted = *eg;
shifted.position_lpx[0] += truncated_width;
truncated_glyphs.push(shifted);
}
Ok(ShapedLine {
glyphs: truncated_glyphs,
width_lpx: truncated_width + ellipsis.width_lpx,
ascent_lpx: shaped.ascent_lpx,
descent_lpx: shaped.descent_lpx,
y_offset_lpx: shaped.y_offset_lpx,
base_direction: shaped.base_direction,
runs: Vec::new(),
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn alignment_offsets() {
assert_eq!(
compute_alignment_offset(100.0, 200.0, TextAlignment::Left),
0.0
);
assert_eq!(
compute_alignment_offset(100.0, 200.0, TextAlignment::Center),
50.0
);
assert_eq!(
compute_alignment_offset(100.0, 200.0, TextAlignment::Right),
100.0
);
}
#[test]
fn alignment_wider_than_container() {
assert_eq!(
compute_alignment_offset(200.0, 100.0, TextAlignment::Left),
0.0
);
assert_eq!(
compute_alignment_offset(200.0, 100.0, TextAlignment::Center),
-50.0
);
assert_eq!(
compute_alignment_offset(200.0, 100.0, TextAlignment::Right),
-100.0
);
}
}