Skip to main content

jag_draw/
scene.rs

1#[derive(Clone, Copy, Debug, Default)]
2pub struct Transform2D {
3    // Affine 2D: [a, b, c, d, e, f] for matrix [[a c e],[b d f],[0 0 1]]
4    pub m: [f32; 6],
5}
6
7impl Transform2D {
8    pub fn identity() -> Self {
9        Self {
10            m: [1.0, 0.0, 0.0, 1.0, 0.0, 0.0],
11        }
12    }
13
14    /// Compose two transforms: self ∘ other (apply `other`, then `self`).
15    pub fn concat(self, other: Self) -> Self {
16        let [a1, b1, c1, d1, e1, f1] = self.m;
17        let [a2, b2, c2, d2, e2, f2] = other.m;
18        let a = a1 * a2 + c1 * b2;
19        let b = b1 * a2 + d1 * b2;
20        let c = a1 * c2 + c1 * d2;
21        let d = b1 * c2 + d1 * d2;
22        let e = a1 * e2 + c1 * f2 + e1;
23        let f = b1 * e2 + d1 * f2 + f1;
24        Self {
25            m: [a, b, c, d, e, f],
26        }
27    }
28
29    pub fn scale(sx: f32, sy: f32) -> Self {
30        Self {
31            m: [sx, 0.0, 0.0, sy, 0.0, 0.0],
32        }
33    }
34
35    pub fn translate(tx: f32, ty: f32) -> Self {
36        Self {
37            m: [1.0, 0.0, 0.0, 1.0, tx, ty],
38        }
39    }
40
41    /// Create a rotation transform (angle in radians, counter-clockwise).
42    pub fn rotate(angle: f32) -> Self {
43        let cos = angle.cos();
44        let sin = angle.sin();
45        Self {
46            m: [cos, sin, -sin, cos, 0.0, 0.0],
47        }
48    }
49
50    /// Create a rotation transform around a specific center point.
51    pub fn rotate_around(angle: f32, cx: f32, cy: f32) -> Self {
52        // Translate to origin, rotate, translate back
53        Self::translate(cx, cy)
54            .concat(Self::rotate(angle))
55            .concat(Self::translate(-cx, -cy))
56    }
57}
58
59#[derive(Clone, Copy, Debug, Default, PartialEq)]
60pub struct ColorLinPremul {
61    pub r: f32,
62    pub g: f32,
63    pub b: f32,
64    pub a: f32,
65}
66
67/// Alias for the premultiplied linear color type, for a friendlier name in APIs.
68pub type Color = ColorLinPremul;
69
70// Constructors for ColorLinPremul are defined in color.rs to keep scene.rs focused
71
72#[derive(Clone, Debug)]
73pub enum Brush {
74    Solid(ColorLinPremul),
75    LinearGradient {
76        start: [f32; 2],
77        end: [f32; 2],
78        stops: Vec<(f32, ColorLinPremul)>,
79    },
80    RadialGradient {
81        center: [f32; 2],
82        radius: f32,
83        stops: Vec<(f32, ColorLinPremul)>,
84    },
85    // Pattern, RadialGradient etc. can be added later.
86}
87
88#[derive(Clone, Copy, Debug, Default, PartialEq)]
89pub struct Rect {
90    pub x: f32,
91    pub y: f32,
92    pub w: f32,
93    pub h: f32,
94}
95
96#[derive(Clone, Copy, Debug, Default, PartialEq)]
97pub struct RoundedRadii {
98    pub tl: f32,
99    pub tr: f32,
100    pub br: f32,
101    pub bl: f32,
102}
103
104#[derive(Clone, Copy, Debug, PartialEq)]
105pub struct RoundedRect {
106    pub rect: Rect,
107    pub radii: RoundedRadii,
108}
109
110#[derive(Clone, Copy, Debug)]
111pub struct ClipRect(pub Rect);
112
113#[derive(Clone, Copy, Debug)]
114pub struct Stroke {
115    pub width: f32,
116}
117
118#[derive(Clone, Copy, Debug)]
119pub struct BoxShadowSpec {
120    pub offset: [f32; 2],
121    pub spread: f32,
122    pub blur_radius: f32,
123    pub color: ColorLinPremul,
124}
125
126#[derive(Clone, Debug)]
127pub enum Shape {
128    Rect(Rect),
129    RoundedRect(RoundedRect),
130}
131
132/// Font style for text rendering.
133#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
134pub enum FontStyle {
135    #[default]
136    Normal,
137    Italic,
138    Oblique,
139}
140
141#[derive(Clone, Debug)]
142pub struct TextRun {
143    pub text: String,
144    pub pos: [f32; 2],
145    pub size: f32,
146    pub color: ColorLinPremul,
147    /// CSS-like font weight in the 100–900 range (normal = 400, bold ≈ 700).
148    /// Renderers that do not support varying weights may ignore this.
149    pub weight: f32,
150    /// Font style (normal, italic, oblique).
151    /// Renderers that do not support font styles may ignore this.
152    pub style: FontStyle,
153    /// Font family name override. If None, uses the default font.
154    /// Renderers that do not support font families may ignore this.
155    pub family: Option<String>,
156}
157
158// --- Path geometry (for SVG import / lyon) ---
159
160#[derive(Clone, Copy, Debug)]
161pub enum FillRule {
162    NonZero,
163    EvenOdd,
164}
165
166#[derive(Clone, Debug)]
167pub enum PathCmd {
168    MoveTo([f32; 2]),
169    LineTo([f32; 2]),
170    QuadTo([f32; 2], [f32; 2]),
171    CubicTo([f32; 2], [f32; 2], [f32; 2]),
172    Close,
173}
174
175#[derive(Clone, Debug)]
176pub struct Path {
177    pub cmds: Vec<PathCmd>,
178    pub fill_rule: FillRule,
179}
180
181// --- Hyperlink ---
182
183/// Hyperlink element combining text, optional underline, and a URL target.
184#[derive(Clone, Debug)]
185pub struct Hyperlink {
186    /// The text content to display
187    pub text: String,
188    /// Position of the hyperlink (baseline-left of text)
189    pub pos: [f32; 2],
190    /// Font size in pixels
191    pub size: f32,
192    /// Text color (premultiplied linear)
193    pub color: ColorLinPremul,
194    /// Target URL
195    pub url: String,
196    /// Font weight (e.g. 400.0 for normal, 700.0 for bold)
197    pub weight: f32,
198    /// Optional pre-measured text width (logical pixels).
199    ///
200    /// When set, renderers/hit-testing should prefer this over heuristic
201    /// character-count estimates so inline links stay aligned with layout.
202    pub measured_width: Option<f32>,
203    /// Whether to show an underline decoration (default: true)
204    pub underline: bool,
205    /// Underline color (if None, uses text color)
206    pub underline_color: Option<ColorLinPremul>,
207    /// Font family name override. If None, uses the default font.
208    pub family: Option<String>,
209    /// Font style (normal, italic, oblique)
210    pub style: FontStyle,
211}