omage/components/
mod.rs

1#![allow(non_snake_case)]
2
3use crate::config::Config;
4use crate::error::CustomError;
5use circle::Circle;
6use image::{ImageBuffer, Rgba};
7use line::Line;
8use rectangle::Rectangle;
9use std::error::Error;
10use text::Text;
11
12mod circle;
13mod line;
14mod rectangle;
15mod text;
16
17/// A trait for drawing components on an image buffer.
18pub trait ComponentTrait {
19    /// Draws the component on the image buffer using the specified configuration.
20    ///
21    /// # Arguments
22    ///
23    /// * `config` - Configuration for the drawing canvas.
24    /// * `buffer` - Image buffer to draw the component on.
25    ///
26    /// # Errors
27    ///
28    /// Returns an error if there is an issue drawing the component.
29    fn draw(
30        &self,
31        config: Config,
32        buffer: &mut ImageBuffer<Rgba<u8>, Vec<u8>>,
33    ) -> Result<(), Box<dyn Error>>;
34}
35
36/// Enum representing different types of drawing components.
37pub enum Component {
38    /// Represents a circle component.
39    Circle {
40        /// X-coordinate of the circle's center.
41        cx: u32,
42        /// Y-coordinate of the circle's center.
43        cy: u32,
44        /// Radius of the circle.
45        r: u32,
46        /// Color of the circle in Rgba format.
47        color: Rgba<u8>,
48    },
49    /// Represents a rectangle component.
50    Rectangle {
51        /// Height of the rectangle.
52        h: u32,
53        /// Width of the rectangle.
54        w: u32,
55        /// X-coordinate of the top-left corner of the rectangle.
56        x: u32,
57        /// Y-coordinate of the top-left corner of the rectangle.
58        y: u32,
59        /// Color of the rectangle in Rgba format.
60        color: Rgba<u8>,
61    },
62    /// Represents a line component.
63    Line {
64        /// X-coordinate of the starting point of the line.
65        x1: u32,
66        /// Y-coordinate of the starting point of the line.
67        y1: u32,
68        /// X-coordinate of the ending point of the line.
69        x2: u32,
70        /// Y-coordinate of the ending point of the line.
71        y2: u32,
72        /// Color of the line in Rgba format.
73        color: Rgba<u8>,
74    },
75    /// Represents a text component.
76    Text {
77        /// X-coordinate of the top-left corner of the text.
78        x: u32,
79        /// Y-coordinate of the top-left corner of the text.
80        y: u32,
81        /// Size of the text.
82        size: u32,
83        /// Text field of the text.
84        text: &'static str,
85        /// Color of the rectangle in Rgba format.
86        color: Rgba<u8>,
87        /// Border.
88        border: Option<(Rgba<u8>, u32)>,
89    },
90}
91
92/// A struct providing convenience methods for creating different types of components.
93///
94/// The `Components` struct serves as a utility for easily generating instances of various graphical
95/// components in a 2D space. It offers methods for creating circles, rectangles, lines, and text
96/// components with specified attributes.
97///
98/// # Examples
99///
100/// ```
101/// use omage::{Components, Rgba};
102///
103/// // Create a new circle component
104/// let circle = Components::Circle(50, 50, 30, Rgba([255, 0, 0, 255]));
105///
106/// // Create a new rectangle component
107/// let rectangle = Components::Rectangle(40, 60, 10, 20, Rgba([0, 255, 0, 255]));
108///
109/// // Create a new line component
110/// let line = Components::Line(10, 10, 80, 80, Rgba([0, 0, 255, 255]));
111///
112/// // Create a new text component
113/// let text = Components::Text(30, 40, 16, "Hello, Rust!", Rgba([255, 255, 255, 255]), Some((Rgba([0, 0, 0, 255]), 2)));
114/// ```
115///
116/// # Methods
117///
118/// The `Components` struct provides the following methods:
119///
120/// - `Circle`: Creates a new circle component with specified attributes.
121/// - `Rectangle`: Creates a new rectangle component with specified attributes.
122/// - `Line`: Creates a new line component with specified attributes.
123/// - `Text`: Creates a new text component with specified attributes, including an optional border.
124///
125/// # Note
126///
127/// The `Components` struct is designed to simplify the process of creating graphical components
128/// for use in a 2D drawing context. It encapsulates the logic for constructing different types
129/// of components with ease.
130/// ```
131pub struct Components;
132
133impl Components {
134    /// Creates a new circle component.
135    ///
136    /// # Parameters
137    ///
138    /// - `cx`: X-coordinate of the center of the circle.
139    /// - `cy`: Y-coordinate of the center of the circle.
140    /// - `r`: Radius of the circle.
141    /// - `color`: RGBA color of the circle.
142    ///
143    /// # Returns
144    ///
145    /// A `Component::Circle` instance.
146    pub fn Circle(cx: u32, cy: u32, r: u32, color: Rgba<u8>) -> Component {
147        Component::Circle { cx, cy, r, color }
148    }
149
150    /// Creates a new rectangle component.
151    ///
152    /// # Parameters
153    ///
154    /// - `h`: Height of the rectangle.
155    /// - `w`: Width of the rectangle.
156    /// - `x`: X-coordinate of the top-left corner of the rectangle.
157    /// - `y`: Y-coordinate of the top-left corner of the rectangle.
158    /// - `color`: RGBA color of the rectangle.
159    ///
160    /// # Returns
161    ///
162    /// A `Component::Rectangle` instance.
163    pub fn Rectangle(h: u32, w: u32, x: u32, y: u32, color: Rgba<u8>) -> Component {
164        Component::Rectangle { h, w, x, y, color }
165    }
166
167    /// Creates a new line component.
168    ///
169    /// # Parameters
170    ///
171    /// - `x1`: X-coordinate of the starting point of the line.
172    /// - `y1`: Y-coordinate of the starting point of the line.
173    /// - `x2`: X-coordinate of the ending point of the line.
174    /// - `y2`: Y-coordinate of the ending point of the line.
175    /// - `color`: RGBA color of the line.
176    ///
177    /// # Returns
178    ///
179    /// A `Component::Line` instance.
180    pub fn Line(x1: u32, y1: u32, x2: u32, y2: u32, color: Rgba<u8>) -> Component {
181        Component::Line {
182            x1,
183            y1,
184            x2,
185            y2,
186            color,
187        }
188    }
189
190    /// Creates a new text component.
191    ///
192    /// # Parameters
193    ///
194    /// - `x`: X-coordinate of the text.
195    /// - `y`: Y-coordinate of the text.
196    /// - `size`: Font size of the text.
197    /// - `text`: The actual text content.
198    /// - `color`: RGBA color of the text.
199    /// - `border`: Optional border color and thickness as a tuple.
200    ///
201    /// # Returns
202    ///
203    /// A `Component::Text` instance.
204    pub fn Text(
205        x: u32,
206        y: u32,
207        size: u32,
208        text: &'static str,
209        color: Rgba<u8>,
210        border: Option<(Rgba<u8>, u32)>,
211    ) -> Component {
212        Component::Text {
213            x,
214            y,
215            size,
216            text,
217            color,
218            border,
219        }
220    }
221}
222
223impl ComponentTrait for Component {
224    fn draw(
225        &self,
226        config: Config,
227        buffer: &mut ImageBuffer<Rgba<u8>, Vec<u8>>,
228    ) -> Result<(), Box<dyn Error>> {
229        match *self {
230            Component::Circle { cx, cy, r, color } => {
231                let circle = Circle::new(cx, cy, r, color);
232                circle.draw(config, buffer)
233            }
234            Component::Rectangle { h, w, x, y, color } => {
235                let rectangle = Rectangle::new(h, w, x, y, color);
236                rectangle.draw(config, buffer)
237            }
238            Component::Line {
239                x1,
240                y1,
241                x2,
242                y2,
243                color,
244            } => {
245                let line = Line::new(x1, y1, x2, y2, color);
246                line.draw(config, buffer)
247            }
248            Component::Text {
249                x,
250                y,
251                size,
252                text,
253                color,
254                border,
255            } => {
256                let text = Text::new(x, y, size, text, color, border);
257                text.draw(config, buffer)
258            }
259        }
260    }
261}