1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Color {
6 pub r: f64,
7 pub g: f64,
8 pub b: f64,
9}
10
11impl Color {
12 pub const RED: Self = Self {
13 r: 1.0,
14 g: 0.0,
15 b: 0.0,
16 };
17 pub const GREEN: Self = Self {
18 r: 0.0,
19 g: 1.0,
20 b: 0.0,
21 };
22 pub const BLUE: Self = Self {
23 r: 0.0,
24 g: 0.0,
25 b: 1.0,
26 };
27 pub const BLACK: Self = Self {
28 r: 0.0,
29 g: 0.0,
30 b: 0.0,
31 };
32 pub const WHITE: Self = Self {
33 r: 1.0,
34 g: 1.0,
35 b: 1.0,
36 };
37
38 pub const fn rgb(r: f64, g: f64, b: f64) -> Self {
39 Self { r, g, b }
40 }
41}
42
43impl From<(f64, f64, f64)> for Color {
44 fn from((r, g, b): (f64, f64, f64)) -> Self {
45 Self { r, g, b }
46 }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum LineCap {
52 Butt,
53 Round,
54 Square,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum LineJoin {
60 Miter,
61 Round,
62 Bevel,
63}
64
65#[derive(Debug, Clone)]
67pub struct Canvas {
68 buffer: Vec<u8>,
69}
70
71impl Canvas {
72 pub fn new() -> Self {
74 Self { buffer: Vec::new() }
75 }
76
77 pub fn move_to(mut self, x: f64, y: f64) -> Self {
79 self.buffer.extend(format!("{} {} m\n", x, y).as_bytes());
80 self
81 }
82
83 pub fn line_to(mut self, x: f64, y: f64) -> Self {
85 self.buffer.extend(format!("{} {} l\n", x, y).as_bytes());
86 self
87 }
88
89 pub fn curve_to(mut self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> Self {
91 self.buffer
92 .extend(format!("{} {} {} {} {} {} c\n", x1, y1, x2, y2, x3, y3).as_bytes());
93 self
94 }
95
96 pub fn rect(mut self, x: f64, y: f64, width: f64, height: f64) -> Self {
98 self.buffer
99 .extend(format!("{} {} {} {} re\n", x, y, width, height).as_bytes());
100 self
101 }
102
103 pub fn stroke_color(mut self, color: Color) -> Self {
105 self.buffer
106 .extend(format!("{} {} {} RG\n", color.r, color.g, color.b).as_bytes());
107 self
108 }
109
110 pub fn fill_color(mut self, color: Color) -> Self {
112 self.buffer
113 .extend(format!("{} {} {} rg\n", color.r, color.g, color.b).as_bytes());
114 self
115 }
116
117 pub fn line_width(mut self, width: f64) -> Self {
119 self.buffer.extend(format!("{} w\n", width).as_bytes());
120 self
121 }
122
123 pub fn close_path(mut self) -> Self {
125 self.buffer.extend(b"h\n");
126 self
127 }
128
129 pub fn fill(mut self) -> Self {
131 self.buffer.extend(b"f\n");
132 self
133 }
134
135 pub fn stroke(mut self) -> Self {
137 self.buffer.extend(b"S\n");
138 self
139 }
140
141 pub fn fill_stroke(mut self) -> Self {
143 self.buffer.extend(b"B\n");
144 self
145 }
146
147 pub fn finish(self) -> Vec<u8> {
149 self.buffer
150 }
151}
152
153impl Default for Canvas {
154 fn default() -> Self {
155 Self::new()
156 }
157}
158
159impl AsRef<[u8]> for Canvas {
160 fn as_ref(&self) -> &[u8] {
161 &self.buffer
162 }
163}
164
165impl fmt::Write for Canvas {
166 fn write_str(&mut self, s: &str) -> fmt::Result {
167 self.buffer.extend(s.as_bytes());
168 Ok(())
169 }
170}