Skip to main content

orinium_browser/engine/bridge/text/
fallback.rs

1//! Fallback text measurer without font engine dependency.
2
3use super::{GlyphCluster, TextMeasureError, TextMeasureRequest, TextMeasurer};
4use crate::engine::bridge::text::MeasuredFragment;
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 for FallbackTextMeasurer {
15    fn measure(
16        &self,
17        request: &TextMeasureRequest,
18    ) -> Result<Vec<MeasuredFragment>, TextMeasureError> {
19        let font_size = request.attribute.flow_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 fragments: Vec<MeasuredFragment> = request
26            .text
27            .split('\n')
28            .map(|line| {
29                let w = line.len() as f32 * char_width;
30                MeasuredFragment {
31                    text: line.to_string(),
32                    width: w,
33                    height: line_height,
34                }
35            })
36            .collect();
37
38        Ok(fragments)
39    }
40
41    fn measure_shaped(
42        &self,
43        request: &TextMeasureRequest,
44    ) -> Result<Vec<GlyphCluster>, TextMeasureError> {
45        let font_size = request.attribute.flow_style.font_size.max(1.0);
46        let char_width = font_size * 0.6;
47
48        let mut clusters = Vec::new();
49        let text = &request.text;
50        let mut i = 0;
51
52        while i < text.len() {
53            let ch = text[i..].chars().next().unwrap();
54            let byte_len = ch.len_utf8();
55            let is_space = ch.is_whitespace();
56            let w = char_width;
57
58            clusters.push(GlyphCluster {
59                byte_offset: i,
60                width: w,
61                break_allowed: is_space,
62            });
63
64            i += byte_len;
65        }
66
67        Ok(clusters)
68    }
69}