lgui_core/text/
service.rs1use std::{cell::RefCell, sync::Arc};
2
3use crate::core::UiRect;
4
5use super::{TextLayout, TextLayoutRequest, TextMeasureRequest, TextMetrics};
6
7pub trait TextSystem: Send + Sync + 'static {
8 fn measure(&self, request: &TextMeasureRequest<'_>) -> Option<TextMetrics>;
9
10 fn layout(&self, _request: &TextLayoutRequest<'_>) -> Option<TextLayout> {
11 None
12 }
13}
14
15#[derive(Clone)]
16pub struct TextSystemHandle(Arc<dyn TextSystem>);
17
18impl TextSystemHandle {
19 pub fn new(system: impl TextSystem) -> Self {
20 Self(Arc::new(system))
21 }
22
23 fn measure(&self, request: &TextMeasureRequest<'_>) -> Option<TextMetrics> {
24 self.0.measure(request)
25 }
26
27 fn layout(&self, request: &TextLayoutRequest<'_>) -> Option<TextLayout> {
28 self.0.layout(request)
29 }
30}
31
32thread_local! {
33 static TEXT_SYSTEM: RefCell<Option<TextSystemHandle>> = const { RefCell::new(None) };
34}
35
36pub(crate) struct TextSystemGuard {
37 previous: Option<TextSystemHandle>,
38}
39
40impl Drop for TextSystemGuard {
41 fn drop(&mut self) {
42 TEXT_SYSTEM.with(|current| {
43 *current.borrow_mut() = self.previous.take();
44 });
45 }
46}
47
48pub(crate) fn install_text_system(system: TextSystemHandle) -> TextSystemGuard {
49 let previous = TEXT_SYSTEM.with(|current| current.borrow_mut().replace(system));
50 TextSystemGuard { previous }
51}
52
53pub fn measure(request: &TextMeasureRequest<'_>) -> Option<TextMetrics> {
54 TEXT_SYSTEM.with(|current| {
55 current
56 .borrow()
57 .as_ref()
58 .and_then(|system| system.measure(request))
59 })
60}
61
62pub fn layout(request: &TextLayoutRequest<'_>) -> Option<TextLayout> {
63 TEXT_SYSTEM.with(|current| {
64 current
65 .borrow()
66 .as_ref()
67 .and_then(|system| system.layout(request))
68 })
69}
70
71pub fn measure_width(text: &str, rect: UiRect, font_height: f32, font_weight: i32) -> Option<f32> {
72 let request = TextLayoutRequest::single_line(text, rect, font_height, font_weight);
73 layout(&request).map(|layout| layout.width).or_else(|| {
74 measure(&TextMeasureRequest {
75 text,
76 bounds: rect,
77 font_height,
78 font_weight,
79 })
80 .map(|metrics| metrics.width)
81 })
82}