zpl_forge/engine/common.rs
1pub use crate::ast::commons::Barcode1DKind;
2
3/// Represents a self-contained ZPL instruction ready for rendering.
4///
5/// Unlike AST commands, instructions are calculated based on the cumulative
6/// state of the parser (e.g., coordinates are absolute, fonts are resolved).
7#[derive(Debug)]
8pub enum ZplInstruction {
9 /// Starts a new page. Emitted between consecutive `^XA...^XZ` blocks.
10 ///
11 /// Backends that support multi-page output (PDF) start a fresh page;
12 /// single-surface backends (PNG) may ignore it.
13 PageBreak,
14 /// Renders a text field.
15 Text {
16 /// Absolute X coordinate.
17 x: u32,
18 /// Absolute Y coordinate.
19 y: u32,
20 /// Font identifier.
21 font: char,
22 /// Height in dots.
23 height: Option<u32>,
24 /// Width in dots.
25 width: Option<u32>,
26 /// Field orientation from `^A` (N, R, I, B).
27 orientation: char,
28 /// Text content.
29 text: String,
30 /// Whether to print white-on-black.
31 reverse_print: bool,
32 /// Custom text color.
33 color: Option<String>,
34 /// `^FB` block formatting (wrap, max lines, justification).
35 block: Option<TextBlock>,
36 /// Condition for this instruction.
37 condition: Option<(String, String)>,
38 },
39 /// Draws a rectangular box.
40 GraphicBox {
41 x: u32,
42 y: u32,
43 width: u32,
44 height: u32,
45 thickness: u32,
46 color: char,
47 custom_color: Option<String>,
48 rounding: u32,
49 reverse_print: bool,
50 condition: Option<(String, String)>,
51 },
52 /// Draws a circle.
53 GraphicCircle {
54 x: u32,
55 y: u32,
56 radius: u32,
57 thickness: u32,
58 color: char,
59 custom_color: Option<String>,
60 reverse_print: bool,
61 condition: Option<(String, String)>,
62 },
63 /// Draws an ellipse.
64 GraphicEllipse {
65 x: u32,
66 y: u32,
67 width: u32,
68 height: u32,
69 thickness: u32,
70 color: char,
71 custom_color: Option<String>,
72 reverse_print: bool,
73 condition: Option<(String, String)>,
74 },
75 /// Renders a bitmap graphic.
76 GraphicField {
77 x: u32,
78 y: u32,
79 width: u32,
80 height: u32,
81 data: Vec<u8>,
82 reverse_print: bool,
83 condition: Option<(String, String)>,
84 },
85 /// Renders a custom color image (extension).
86 CustomImage {
87 /// Absolute X coordinate.
88 x: u32,
89 /// Absolute Y coordinate.
90 y: u32,
91 /// Requested width (0 for natural/proportional).
92 width: u32,
93 /// Requested height (0 for natural/proportional).
94 height: u32,
95 /// Base64 encoded image data.
96 data: String,
97 condition: Option<(String, String)>,
98 },
99 /// Draws a Code 128 barcode.
100 Code128 {
101 x: u32,
102 y: u32,
103 orientation: char,
104 height: u32,
105 module_width: u32,
106 interpretation_line: char,
107 interpretation_line_above: char,
108 check_digit: char,
109 mode: char,
110 data: String,
111 reverse_print: bool,
112 condition: Option<(String, String)>,
113 },
114 /// Draws a QR Code.
115 QRCode {
116 x: u32,
117 y: u32,
118 orientation: char,
119 model: u32,
120 magnification: u32,
121 error_correction: char,
122 mask: u32,
123 data: String,
124 reverse_print: bool,
125 condition: Option<(String, String)>,
126 },
127 /// Draws a generic 1-D barcode (EAN-13, UPC-A, ITF, Code 93).
128 Barcode1D {
129 kind: Barcode1DKind,
130 x: u32,
131 y: u32,
132 orientation: char,
133 height: u32,
134 module_width: u32,
135 /// `^BY` wide:narrow ratio. ZPL defaults to 3.0.
136 ratio: f32,
137 /// Check-digit mode as spelled by the symbology's own command.
138 check_digit: char,
139 interpretation_line: char,
140 interpretation_line_above: char,
141 data: String,
142 reverse_print: bool,
143 condition: Option<(String, String)>,
144 },
145 /// Draws a MicroPDF417 2D barcode (`^BF`).
146 MicroPdf417 {
147 x: u32,
148 y: u32,
149 orientation: char,
150 height: u32,
151 mode: u32,
152 data: String,
153 reverse_print: bool,
154 condition: Option<(String, String)>,
155 },
156 /// Draws an Aztec Code 2D barcode (`^B0`/`^BO`).
157 AztecCode {
158 x: u32,
159 y: u32,
160 orientation: char,
161 magnification: u32,
162 data: String,
163 reverse_print: bool,
164 condition: Option<(String, String)>,
165 },
166 /// Draws a diagonal line (`^GD`).
167 GraphicDiagonal {
168 x: u32,
169 y: u32,
170 width: u32,
171 height: u32,
172 thickness: u32,
173 color: char,
174 custom_color: Option<String>,
175 /// Leaning: 'R' (`/`) or 'L' (`\`).
176 diagonal_orientation: char,
177 reverse_print: bool,
178 condition: Option<(String, String)>,
179 },
180 /// Draws a Data Matrix (ECC 200) barcode.
181 DataMatrix {
182 x: u32,
183 y: u32,
184 orientation: char,
185 /// Module size in dots (`^BX` dimensional height).
186 module_size: u32,
187 data: String,
188 reverse_print: bool,
189 condition: Option<(String, String)>,
190 },
191 /// Draws a PDF417 barcode.
192 Pdf417 {
193 x: u32,
194 y: u32,
195 orientation: char,
196 /// Row height in dots.
197 row_height: u32,
198 /// Module width in dots (from `^BY`).
199 module_width: u32,
200 /// Error correction security level (0-8).
201 security_level: u32,
202 data: String,
203 reverse_print: bool,
204 condition: Option<(String, String)>,
205 },
206 /// Draws a Code 39 barcode.
207 Code39 {
208 x: u32,
209 y: u32,
210 orientation: char,
211 check_digit: char,
212 height: u32,
213 module_width: u32,
214 /// `^BY` wide:narrow ratio. ZPL defaults to 3.0.
215 ratio: f32,
216 interpretation_line: char,
217 interpretation_line_above: char,
218 data: String,
219 reverse_print: bool,
220 condition: Option<(String, String)>,
221 },
222}
223
224/// `^FB` field-block formatting parameters.
225#[derive(Debug, Clone, Copy, PartialEq)]
226pub struct TextBlock {
227 /// Block width in dots; lines wrap to fit it.
228 pub width: u32,
229 /// Maximum number of lines (default 1).
230 pub max_lines: u32,
231 /// Extra space added between lines, in dots.
232 pub line_spacing: i32,
233 /// Justification: 'L', 'C', 'R' or 'J' (J renders as L).
234 pub justification: char,
235 /// Hanging indent applied from the second line onwards, in dots.
236 pub indent: u32,
237}
238
239/// Represents common printer resolutions.
240#[derive(Debug, Clone, Copy, PartialEq)]
241pub enum Resolution {
242 /// 152 DPI (6 dots/mm)
243 Dpi152,
244 /// 203 DPI (8 dots/mm) - Zebra Standard
245 Dpi203,
246 /// 300 DPI (12 dots/mm)
247 Dpi300,
248 /// 600 DPI (24 dots/mm)
249 Dpi600,
250 /// Custom DPI value
251 Custom(f32),
252}
253
254impl Resolution {
255 /// Returns the dots per millimeter for this resolution.
256 pub fn dpmm(&self) -> f32 {
257 match self {
258 Resolution::Dpi152 => 6.0,
259 Resolution::Dpi203 => 8.0,
260 Resolution::Dpi300 => 12.0,
261 Resolution::Dpi600 => 24.0,
262 Resolution::Custom(val) => val / 25.4,
263 }
264 }
265
266 /// Returns the dots per inch for this resolution.
267 ///
268 /// These are the *nominal* ratings Zebra prints on its hardware, not the
269 /// exact `dpmm * 25.4` conversions (which would give 203.2 / 304.8 /
270 /// 609.6). Firmware maps inches to dots with the nominal value, so a 4 x 6
271 /// in label is exactly 812 x 1218 dots at 8 dpmm rather than 813 x 1219.
272 /// Using the exact conversion put every canvas one dot over.
273 pub fn dpi(&self) -> f32 {
274 match self {
275 Resolution::Dpi152 => 152.0,
276 Resolution::Dpi203 => 203.0,
277 Resolution::Dpi300 => 300.0,
278 Resolution::Dpi600 => 600.0,
279 Resolution::Custom(val) => *val,
280 }
281 }
282}
283
284/// Physical units of measurement supported by the engine.
285#[derive(Debug, Clone, Copy, PartialEq)]
286pub enum Unit {
287 /// Raw dots.
288 Dots(u32),
289 /// Inches.
290 Inches(f32),
291 /// Millimeters.
292 Millimeters(f32),
293 /// Centimeters.
294 Centimeters(f32),
295}
296
297impl Unit {
298 /// Converts the unit to dots based on the provided resolution.
299 pub fn to_dots(&self, resolution: Resolution) -> u32 {
300 match self {
301 Unit::Dots(dots) => *dots,
302 Unit::Inches(inches) => (inches.max(0.0) * resolution.dpi()).round() as u32,
303 Unit::Millimeters(mm) => (mm.max(0.0) * resolution.dpmm()).round() as u32,
304 Unit::Centimeters(cm) => (cm.max(0.0) * 10.0 * resolution.dpmm()).round() as u32,
305 }
306 }
307}