GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
src/widget/display/text_label.rs (2.7K)
1
2 #[derive(Debug, Clone)]
3 pub struct TextLabel {
4 pub text: String,
5 pub x: f32,
6 pub y: f32,
7 pub font_size: f32,
8 pub color: [u8; 3],
9 }
10
11 impl TextLabel {
12 pub fn estimate_width(text: &str, font_size: f32) -> f32 {
13 let mut weight_sum = 0.0;
14 for c in text.chars() {
15 weight_sum += match c {
16 'i' | 'l' | 't' | 'j' | 'I' | ' ' | '.' | ',' | '!' | ';' | ':' | '\'' | '1' | '-' | '(' | ')' | '[' | ']' => 0.26,
17 'f' | 'r' | 's' | 'J' => 0.35,
18 'w' | 'm' | 'M' | 'W' => 0.72,
19 'A' | 'B' | 'C' | 'D' | 'E' | 'G' | 'H' | 'K' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'X' | 'Y' | 'Z' => 0.65,
20 _ => 0.52,
21 };
22 }
23 (weight_sum * font_size * 1.30).ceil()
24 }
25
26 pub fn curved_layout(
27 text: &str,
28 cx: f32,
29 cy: f32,
30 r: f32,
31 start_angle: f32,
32 end_angle: f32,
33 font_size: f32,
34 color: [u8; 3],
35 ) -> Vec<TextLabel> {
36 let mut labels = Vec::new();
37 let font_fam = crate::layout::menubar_font_parsed().0;
38 let char_widths: Vec<f32> = text.chars().map(|c| {
39 crate::widget::display::measure_text_width(&c.to_string(), &font_fam, font_size)
40 }).collect();
41 let total_width: f32 = char_widths.iter().sum();
42
43 let mid_angle = (start_angle + end_angle) / 2.0;
44 let angular_width = total_width / r;
45 let text_start_angle = mid_angle - angular_width / 2.0;
46
47 let mut current_angle = text_start_angle;
48 for (i, c) in text.chars().enumerate() {
49 let cw = char_widths[i];
50 let dtheta = cw / r;
51 let char_center_angle = current_angle + dtheta / 2.0;
52
53 let x = cx + r * char_center_angle.cos() - cw / 2.0;
54 let y = cy + r * char_center_angle.sin() - font_size / 2.0;
55
56 labels.push(TextLabel {
57 text: c.to_string(),
58 x,
59 y,
60 font_size,
61 color,
62 });
63
64 current_angle += dtheta;
65 }
66 labels
67 }
68
69 pub fn is_covered_by(&self, px: f32, py: f32, pw: f32, ph: f32) -> bool {
70 let text_w = crate::widget::display::measure_text(&self.text, self.font_size);
71 let x_overlap = self.x <= px + pw && (self.x + text_w) >= px;
72 let y_overlap = self.y <= py + ph && (self.y + self.font_size) >= py;
73 x_overlap && y_overlap
74 }
75 }
76
77 pub(crate) fn make_widget_text_buffer(fs: &mut cosmic_text::FontSystem, text: &str, size: f32, font_family: &str) -> cosmic_text::Buffer {
78 crate::backend::window_runner::get_text_buffer(fs, text, size, Some(font_family))
79 }