ori_graphics/
text.rs

1use std::{fmt::Display, str::FromStr};
2
3use glam::Vec2;
4
5use crate::{Color, Rect};
6
7#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
8pub enum TextAlign {
9    #[default]
10    Start,
11    Center,
12    End,
13}
14
15impl Display for TextAlign {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            TextAlign::Start => write!(f, "start"),
19            TextAlign::Center => write!(f, "center"),
20            TextAlign::End => write!(f, "end"),
21        }
22    }
23}
24
25impl FromStr for TextAlign {
26    type Err = ();
27
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        match s {
30            "left" | "start" => Ok(TextAlign::Start),
31            "center" => Ok(TextAlign::Center),
32            "right" | "end" => Ok(TextAlign::End),
33            _ => Err(()),
34        }
35    }
36}
37
38impl TextAlign {
39    pub fn align(&self, start: f32, end: f32) -> f32 {
40        match self {
41            TextAlign::Start => start,
42            TextAlign::Center => (start + end) / 2.0,
43            TextAlign::End => end,
44        }
45    }
46}
47
48#[derive(Clone, Debug)]
49pub struct TextSection {
50    pub rect: Rect,
51    pub scale: f32,
52    pub h_align: TextAlign,
53    pub v_align: TextAlign,
54    pub wrap: bool,
55    pub text: String,
56    pub font: Option<String>,
57    pub color: Color,
58}
59
60impl Default for TextSection {
61    fn default() -> Self {
62        Self {
63            rect: Rect::new(Vec2::ZERO, Vec2::splat(f32::INFINITY)),
64            scale: 16.0,
65            h_align: TextAlign::Start,
66            v_align: TextAlign::Start,
67            wrap: true,
68            text: String::new(),
69            font: None,
70            color: Color::BLACK,
71        }
72    }
73}
74
75impl TextSection {
76    pub fn aligned_rect(&self) -> Rect {
77        let x = self.h_align.align(self.rect.min.x, self.rect.max.x);
78        let y = self.v_align.align(self.rect.min.y, self.rect.max.y);
79        let position = Vec2::new(x, y);
80
81        Rect::min_size(position, self.rect.size())
82    }
83}
84
85#[derive(Clone, Copy, Debug, PartialEq)]
86pub struct TextHit {
87    pub inside: bool,
88    pub index: usize,
89    pub delta: Vec2,
90}