1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//! [`TextRenderer`] — stateful text rendering (current font applies).
use super::painter::Painter;
use super::types::{TextAlign, TextBaseline};
/// Text rendering — stateful (current font applies).
///
/// Has [`Painter`] as a supertrait so default impls can use
/// save/translate/rotate/restore without `where Self: Painter` clauses
/// (which would break dyn compatibility).
pub trait TextRenderer: Painter {
/// Set the current font using a CSS-style font string.
///
/// Examples: `"14px sans-serif"`, `"bold 16px monospace"`.
fn set_font(&mut self, font: &str);
/// Set text horizontal alignment.
fn set_text_align(&mut self, align: TextAlign);
/// Set text vertical baseline.
fn set_text_baseline(&mut self, baseline: TextBaseline);
/// Fill text at position `(x, y)` using the current font and fill style.
fn fill_text(&mut self, text: &str, x: f64, y: f64);
/// Stroke text outlines. Backends without native stroke-text provide a no-op.
fn stroke_text(&mut self, text: &str, x: f64, y: f64) {
let _ = (text, x, y);
}
/// Fill text with rotation around the anchor point.
///
/// Default uses save/translate/rotate/fill_text/restore.
/// Backends (vello-gpu) override for pre-rotation baseline correctness.
fn fill_text_rotated(&mut self, text: &str, x: f64, y: f64, angle: f64) {
if angle.abs() < 0.001 {
self.fill_text(text, x, y);
} else {
self.save();
self.translate(x, y);
self.rotate(angle);
self.fill_text(text, 0.0, 0.0);
self.restore();
}
}
/// Fill text centered at position.
///
/// Default sets [`TextAlign::Center`] + [`TextBaseline::Middle`] then calls
/// [`fill_text`](Self::fill_text).
fn fill_text_centered(&mut self, text: &str, x: f64, y: f64) {
self.set_text_align(TextAlign::Center);
self.set_text_baseline(TextBaseline::Middle);
self.fill_text(text, x, y);
}
}