Skip to main content

ggplot_rs/render/
backend.rs

1use super::{Rect, RenderError};
2
3/// Point shape types.
4#[derive(Clone, Debug, Copy, PartialEq, Eq)]
5pub enum PointShape {
6    Circle,
7    Triangle,
8    Square,
9    Diamond,
10    Cross,
11    Plus,
12}
13
14impl PointShape {
15    /// All shapes in order (for discrete scale mapping).
16    pub const ALL: &[PointShape] = &[
17        PointShape::Circle,
18        PointShape::Triangle,
19        PointShape::Square,
20        PointShape::Diamond,
21        PointShape::Cross,
22        PointShape::Plus,
23    ];
24}
25
26/// Line type patterns.
27#[derive(Clone, Debug, Copy, PartialEq, Eq)]
28pub enum Linetype {
29    Solid,
30    Dashed,
31    Dotted,
32    DashDot,
33    LongDash,
34    TwoDash,
35}
36
37impl Linetype {
38    /// All linetypes in order (for discrete scale mapping).
39    pub const ALL: &[Linetype] = &[
40        Linetype::Solid,
41        Linetype::Dashed,
42        Linetype::Dotted,
43        Linetype::DashDot,
44        Linetype::LongDash,
45        Linetype::TwoDash,
46    ];
47
48    /// Get dash pattern as (draw_len, gap_len) pairs in pixels.
49    pub fn pattern(&self) -> &[(f64, f64)] {
50        match self {
51            Linetype::Solid => &[],
52            Linetype::Dashed => &[(6.0, 3.0)],
53            Linetype::Dotted => &[(2.0, 2.0)],
54            Linetype::DashDot => &[(6.0, 2.0), (2.0, 2.0)],
55            Linetype::LongDash => &[(10.0, 4.0)],
56            Linetype::TwoDash => &[(8.0, 3.0), (3.0, 3.0)],
57        }
58    }
59}
60
61/// Style for drawing points/circles.
62#[derive(Clone, Debug)]
63pub struct PointStyle {
64    pub color: (u8, u8, u8),
65    pub alpha: f64,
66    pub filled: bool,
67    pub shape: PointShape,
68}
69
70impl Default for PointStyle {
71    fn default() -> Self {
72        PointStyle {
73            color: (0, 0, 0),
74            alpha: 1.0,
75            filled: true,
76            shape: PointShape::Circle,
77        }
78    }
79}
80
81/// Style for drawing lines.
82#[derive(Clone, Debug)]
83pub struct LineStyle {
84    pub color: (u8, u8, u8),
85    pub alpha: f64,
86    pub width: f64,
87    pub linetype: Linetype,
88}
89
90impl Default for LineStyle {
91    fn default() -> Self {
92        LineStyle {
93            color: (0, 0, 0),
94            alpha: 1.0,
95            width: 1.0,
96            linetype: Linetype::Solid,
97        }
98    }
99}
100
101/// Style for drawing rectangles/polygons.
102#[derive(Clone, Debug)]
103pub struct RectStyle {
104    pub fill: Option<(u8, u8, u8)>,
105    pub stroke: Option<(u8, u8, u8)>,
106    pub stroke_width: f64,
107    pub alpha: f64,
108    /// Whether to clip this rect to the plot area. Default `true` for data elements.
109    /// Set to `false` for non-data elements (backgrounds, strips, legends).
110    pub clip: bool,
111}
112
113impl Default for RectStyle {
114    fn default() -> Self {
115        RectStyle {
116            fill: Some((128, 128, 128)),
117            stroke: None,
118            stroke_width: 1.0,
119            alpha: 1.0,
120            clip: true,
121        }
122    }
123}
124
125/// Style for drawing text.
126#[derive(Clone, Debug)]
127pub struct TextStyle {
128    pub color: (u8, u8, u8),
129    pub size: f64,
130    pub anchor: TextAnchor,
131    pub angle: f64,
132    /// Font family (e.g., "serif", "monospace"). None defaults to "sans-serif".
133    pub family: Option<String>,
134}
135
136impl Default for TextStyle {
137    fn default() -> Self {
138        TextStyle {
139            color: (50, 50, 50),
140            size: 12.0,
141            anchor: TextAnchor::Middle,
142            angle: 0.0,
143            family: None,
144        }
145    }
146}
147
148#[derive(Clone, Debug)]
149pub enum TextAnchor {
150    Start,
151    Middle,
152    End,
153}
154
155/// Our rendering abstraction, independent of plotters details.
156pub trait DrawBackend {
157    fn draw_circle(
158        &mut self,
159        center: (f64, f64),
160        radius: f64,
161        style: &PointStyle,
162    ) -> Result<(), RenderError>;
163    fn draw_line(&mut self, points: &[(f64, f64)], style: &LineStyle) -> Result<(), RenderError>;
164    fn draw_rect(
165        &mut self,
166        top_left: (f64, f64),
167        bottom_right: (f64, f64),
168        style: &RectStyle,
169    ) -> Result<(), RenderError>;
170    fn draw_text(
171        &mut self,
172        text: &str,
173        pos: (f64, f64),
174        style: &TextStyle,
175    ) -> Result<(), RenderError>;
176    fn draw_polygon(&mut self, points: &[(f64, f64)], style: &RectStyle)
177        -> Result<(), RenderError>;
178    fn plot_area(&self) -> Rect;
179    fn total_area(&self) -> Rect;
180
181    /// Draw a point with a specific shape. Default delegates to draw_circle for Circle.
182    fn draw_shape(
183        &mut self,
184        center: (f64, f64),
185        radius: f64,
186        style: &PointStyle,
187    ) -> Result<(), RenderError> {
188        match style.shape {
189            PointShape::Circle => self.draw_circle(center, radius, style),
190            _ => {
191                // Default: fall back to circle for unsupported backends
192                self.draw_circle(center, radius, style)
193            }
194        }
195    }
196}