Skip to main content

euv_chart/geom/base/
struct.rs

1use super::*;
2
3/// A two-dimensional affine transform stored as the six meaningful entries
4/// of a 3×3 matrix.
5///
6/// The matrix is applied to a point `(x, y)` as:
7///
8/// ```text
9/// x' = a·x + c·y + e
10/// y' = b·x + d·y + f
11/// ```
12///
13/// This is the same layout SVG and Canvas2D use, so a transform built here
14/// can be handed to a Canvas2D context verbatim.
15#[derive(Clone, Copy, Debug, lombok_macros::Data, PartialEq)]
16pub struct Transform2D {
17    /// The horizontal scale / shear term applied to `x`.
18    #[get(type(copy))]
19    pub a: f64,
20    /// The vertical shear term applied to `x`.
21    #[get(type(copy))]
22    pub b: f64,
23    /// The horizontal shear term applied to `y`.
24    #[get(type(copy))]
25    pub c: f64,
26    /// The vertical scale / shear term applied to `y`.
27    #[get(type(copy))]
28    pub d: f64,
29    /// The horizontal translation.
30    #[get(type(copy))]
31    pub e: f64,
32    /// The vertical translation.
33    #[get(type(copy))]
34    pub f: f64,
35}
36
37/// An axis-aligned bounding box, stored as its minimum corner plus its
38/// extent.
39///
40/// The `min` / `max` form (rather than `x` / `y` / `width` / `height`)
41/// keeps the empty-box case representable: a box that has not been
42/// extended yet is `min > max` on every axis, which is the standard
43/// sentinel for "no geometry yet".
44#[derive(Clone, Copy, Debug, lombok_macros::Data, PartialEq)]
45pub struct BBox {
46    /// The smallest `x` reached by the geometry.
47    #[get(type(copy))]
48    pub min_x: f64,
49    /// The smallest `y` reached by the geometry.
50    #[get(type(copy))]
51    pub min_y: f64,
52    /// The largest `x` reached by the geometry.
53    #[get(type(copy))]
54    pub max_x: f64,
55    /// The largest `y` reached by the geometry.
56    #[get(type(copy))]
57    pub max_y: f64,
58}
59
60/// A point in path space.
61///
62/// Paths are stored in 32-bit floats: they are consumed by the GPU
63/// backends, which upload them verbatim, and pixel-space coordinates never
64/// need more than 24 bits of mantissa. Layout arithmetic happens in
65/// `f64` and is narrowed once, when a path is built.
66#[derive(Clone, Copy, Debug, Default, lombok_macros::Data, PartialEq)]
67pub struct Point {
68    /// The horizontal coordinate.
69    #[get(type(copy))]
70    pub x: f32,
71    /// The vertical coordinate.
72    #[get(type(copy))]
73    pub y: f32,
74}
75
76/// A closed polygon: a flat list of points plus an explicit count.
77///
78/// The flat representation keeps the hot triangulation loop free of
79/// indirection: the inner scan reads `points[i]` directly instead of
80/// chasing a per-vertex pointer.
81#[derive(Clone, Debug, Default, lombok_macros::Data, PartialEq)]
82pub struct Polygon {
83    /// The vertices, in order.
84    pub points: Vec<Point>,
85}
86
87/// A sequence of drawing commands describing one or more sub-paths.
88///
89/// A path is the unit of geometry in the chart renderer: axes, series
90/// polylines, pie slices, radar rings, and text decorations are all
91/// expressed as paths. Paths are immutable once built — the builder
92/// produces the final command buffer, and the tessellator consumes it
93/// without mutating it.
94#[derive(Clone, Debug, Default, lombok_macros::Data, PartialEq)]
95pub struct Path {
96    /// The command buffer.
97    #[get(pub(crate))]
98    #[get_mut(pub(crate))]
99    #[set(pub(crate))]
100    pub(crate) commands: Vec<PathCommand>,
101    /// The rule used to decide which parts of the path are inside it.
102    #[get(pub(crate), type(copy))]
103    #[get_mut(pub(crate))]
104    #[set(pub(crate))]
105    pub(crate) fill_rule: FillRule,
106}
107
108/// A fluent builder for [`Path`].
109///
110/// Every method returns `Self` so a path can be assembled in one
111/// expression without a mutable borrow in the middle of a call chain.
112#[derive(Clone, Debug, lombok_macros::Data)]
113pub struct PathBuilder {
114    /// The commands of the path under construction.
115    #[get(pub(crate))]
116    #[get_mut(pub(crate))]
117    #[set(pub(crate))]
118    pub(crate) commands: Vec<PathCommand>,
119    /// The rule the finished path is filled with.
120    #[get(pub(crate), type(copy))]
121    #[get_mut(pub(crate))]
122    #[set(pub(crate))]
123    pub(crate) fill_rule: FillRule,
124    /// The point the path is currently at.
125    #[get(pub(crate), type(copy))]
126    #[get_mut(pub(crate))]
127    #[set(pub(crate))]
128    pub(crate) current: Point,
129    /// The point the current sub-path started at.
130    #[get(pub(crate), type(copy))]
131    #[get_mut(pub(crate))]
132    #[set(pub(crate))]
133    pub(crate) start: Point,
134}
135
136/// An ellipse: the shape an arc is cut out of.
137///
138/// The type stays inside the crate: it gathers the four numbers an arc
139/// needs, so that the function that cuts the arc does not take eight
140/// of them.
141#[derive(Clone, Copy, Debug, PartialEq)]
142pub(crate) struct Ellipse {
143    /// The horizontal position of the centre.
144    pub(crate) center_x: f64,
145    /// The vertical position of the centre.
146    pub(crate) center_y: f64,
147    /// The radius along the horizontal axis.
148    pub(crate) radius_x: f64,
149    /// The radius along the vertical axis.
150    pub(crate) radius_y: f64,
151}
152
153/// The geometric parameters of a stroke.
154///
155/// The colour lives in the paint layer; this struct carries only what the
156/// tessellator needs to turn a path into stroke geometry.
157#[derive(Clone, Debug, lombok_macros::Data, PartialEq)]
158pub struct StrokeStyle {
159    /// The line width, in pixels.
160    #[get(type(copy))]
161    pub width: f32,
162    /// How the ends of an open stroke are drawn.
163    #[get(type(copy))]
164    pub cap: LineCap,
165    /// How the corners between segments are drawn.
166    #[get(type(copy))]
167    pub join: LineJoin,
168    /// The dash pattern applied along the stroke.
169    pub dash: DashPattern,
170}
171
172/// A dash pattern applied to a stroke.
173///
174/// `offset` shifts the pattern along the path; a negative offset moves the
175/// pattern backwards.
176#[derive(Clone, Debug, Default, lombok_macros::Data, PartialEq)]
177pub struct DashPattern {
178    /// The alternating on/off lengths, in pixels.
179    ///
180    /// An empty slice means "solid". An odd-length array is repeated twice
181    /// to make the on/off alternation well-defined.
182    pub pattern: Vec<f32>,
183    /// The distance into the pattern at which the dash starts.
184    #[get(type(copy))]
185    pub offset: f32,
186}