orinium_browser/engine/bridge/text/
fallback.rs

1//! Fallback text measurer without font engine dependency.
2
3use super::{TextMeasureError, TextMeasureRequest, TextMeasurer, TextMetrics};
4use crate::engine::layouter::types::TextStyle;
5
6/// Fallback text measurer.
7///
8/// This implementation does not rely on any font engine.
9/// It uses a simple heuristic based on font size and character count.
10/// Intended for testing, bring-up, and environments without font support.
11#[derive(Debug, Default)]
12pub struct FallbackTextMeasurer;
13
14impl TextMeasurer<TextStyle> for FallbackTextMeasurer {
15    fn measure(
16        &self,
17        request: &TextMeasureRequest<TextStyle>,
18    ) -> Result<TextMetrics, TextMeasureError> {
19        let font_size = request.style.font_size.max(1.0);
20
21        // Heuristic constants
22        let char_width = font_size * 0.6;
23        let line_height = font_size * 1.2;
24
25        let mut current_line_width = 0.0;
26        let mut max_line_width: f32 = 0.0;
27        let mut line_count = 1;
28
29        for ch in request.text.chars() {
30            if ch == '\n' {
31                max_line_width = max_line_width.max(current_line_width);
32                current_line_width = 0.0;
33                line_count += 1;
34                continue;
35            }
36
37            current_line_width += char_width;
38
39            if request.wrap
40                && let Some(max_width) = request.max_width
41                && current_line_width > max_width
42            {
43                max_line_width = max_line_width.max(current_line_width - char_width);
44                current_line_width = char_width;
45                line_count += 1;
46            }
47        }
48
49        max_line_width = max_line_width.max(current_line_width);
50
51        Ok(TextMetrics {
52            width: max_line_width,
53            height: line_height * line_count as f32,
54            baseline: font_size,
55            line_count,
56        })
57    }
58}