Skip to main content

graphitepdf_kit/
vector.rs

1use std::fmt;
2
3/// Represents an RGB color.
4#[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/// Line cap style.
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum LineCap {
52    Butt,
53    Round,
54    Square,
55}
56
57/// Line join style.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum LineJoin {
60    Miter,
61    Round,
62    Bevel,
63}
64
65/// Canvas for building vector graphics paths.
66#[derive(Debug, Clone)]
67pub struct Canvas {
68    buffer: Vec<u8>,
69}
70
71impl Canvas {
72    /// Creates a new canvas.
73    pub fn new() -> Self {
74        Self { buffer: Vec::new() }
75    }
76
77    /// Moves to a point without drawing a line.
78    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    /// Draws a line from the current point to a new point.
84    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    /// Draws a cubic Bezier curve.
90    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    /// Draws a rectangle.
97    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    /// Sets the stroke color.
104    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    /// Sets the fill color.
111    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    /// Sets the line width.
118    pub fn line_width(mut self, width: f64) -> Self {
119        self.buffer.extend(format!("{} w\n", width).as_bytes());
120        self
121    }
122
123    /// Closes the current path.
124    pub fn close_path(mut self) -> Self {
125        self.buffer.extend(b"h\n");
126        self
127    }
128
129    /// Fills the current path.
130    pub fn fill(mut self) -> Self {
131        self.buffer.extend(b"f\n");
132        self
133    }
134
135    /// Strokes the current path.
136    pub fn stroke(mut self) -> Self {
137        self.buffer.extend(b"S\n");
138        self
139    }
140
141    /// Fills and strokes the current path.
142    pub fn fill_stroke(mut self) -> Self {
143        self.buffer.extend(b"B\n");
144        self
145    }
146
147    /// Finishes the canvas and returns the PDF content stream bytes.
148    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}