orinium_browser/engine/bridge/text/mod.rs
1//! Text measurement abstraction for layout and rendering.
2//!
3//! # Overview
4//!
5//! This module defines the interface between the layout engine and
6//! platform-specific text measurement implementations.
7//!
8//! It does **not** own or define visual text styles.
9//! Instead, it consumes already-resolved text attributes provided
10//! by higher-level layout or rendering layers.
11//!
12//! # Responsibilities
13//!
14//! - Accept text content and layout-related parameters
15//! - Measure intrinsic text size (width, height, baseline)
16//! - Provide a backend-agnostic text measurement abstraction
17//!
18//! # Non-Responsibilities
19//!
20//! - CSS resolution or inheritance
21//! - Interpretation of visual styling semantics
22//! - Rendering or draw command generation
23//!
24//! # Data Flow
25//!
26//! ```text
27//! CSS → Layout → TextMeasurer → TextMetrics
28//! ```
29
30use std::fmt;
31
32/* ============================
33 * Style Type
34 * ============================ */
35
36#[derive(Debug, Clone)]
37pub struct TextAttribute {
38 pub style: TextStyle,
39 pub flow_style: TextFlowStyle,
40}
41
42/* ============================
43 * Measure Request
44 * ============================ */
45
46#[derive(Debug, Clone)]
47pub struct TextMeasureRequest {
48 /// UTF-8 text content
49 pub text: String,
50
51 /// Opaque, resolved text attributes provided by the caller
52 pub attribute: TextAttribute,
53}
54
55/* ============================
56 * Measured Result
57 * ============================ */
58
59/// A measured text fragment produced by [`TextMeasurer::measure_fragments`].
60///
61/// Contains the original text segment along with its measured dimensions,
62/// so callers can both retrieve the split text and obtain fragment widths
63/// for inline layout.
64#[derive(Debug, Clone)]
65pub struct MeasuredFragment {
66 pub text: String,
67 pub width: f32,
68 pub height: f32,
69}
70
71/* ============================
72 * Optional Glyph Info (Future)
73 * ============================ */
74
75#[derive(Debug, Clone)]
76pub struct GlyphMetrics {
77 pub glyph_id: u32,
78 pub x: f32,
79 pub y: f32,
80 pub advance: f32,
81}
82
83/* ============================
84 * Glyph Cluster (for FlowLayouter)
85 * ============================ */
86
87/// A single glyph cluster produced by text shaping.
88///
89/// Carries the cluster's byte offset in the original text, its advance
90/// width, and whether a line break is permitted after it.
91#[derive(Debug, Clone)]
92pub struct GlyphCluster {
93 /// Byte offset of this cluster's first character in the original text.
94 pub byte_offset: usize,
95 /// Advance width in pixels.
96 pub width: f32,
97 /// Whether a line break is permitted immediately after this cluster.
98 pub break_allowed: bool,
99}
100
101/* ============================
102 * Errors
103 * ============================ */
104
105#[derive(Debug)]
106pub enum TextMeasureError {
107 FontUnavailable,
108 UnsupportedScript,
109 LayoutOverflow,
110 Internal(String),
111}
112
113impl fmt::Display for TextMeasureError {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 Self::FontUnavailable => write!(f, "Font unavailable"),
117 Self::UnsupportedScript => write!(f, "Unsupported script"),
118 Self::LayoutOverflow => write!(f, "Layout overflow"),
119 Self::Internal(s) => write!(f, "Internal error: {s}"),
120 }
121 }
122}
123
124impl std::error::Error for TextMeasureError {}
125
126/* ============================
127 * Trait
128 * ============================ */
129
130pub trait TextMeasurer: Send + Sync {
131 /// Measure a single block of text and return its metrics.
132 fn measure(
133 &self,
134 request: &TextMeasureRequest,
135 ) -> Result<Vec<MeasuredFragment>, TextMeasureError>;
136
137 /// Shape text and return cluster-level break-opportunity data.
138 ///
139 /// Unlike [`measure`](Self::measure), this returns per-cluster
140 /// data suitable for use with [`TextFlowLayouter`].
141 fn measure_shaped(
142 &self,
143 request: &TextMeasureRequest,
144 ) -> Result<Vec<GlyphCluster>, TextMeasureError>;
145}
146
147/* ============================
148 * Fallback
149 * ============================ */
150
151pub mod fallback;
152pub use fallback::FallbackTextMeasurer;
153
154use crate::engine::layouter::types::{TextFlowStyle, TextStyle};