escpos/
printer.rs

1//! Printer
2
3use super::errors::Result;
4#[cfg(feature = "ui")]
5use crate::domain::ui::line::Line;
6use crate::printer_options::PrinterOptions;
7use crate::{domain::*, driver::Driver, utils::Protocol};
8use log::debug;
9
10/// Printer
11///
12/// Print a document
13///
14/// # Example
15///
16/// ```rust
17/// use escpos::printer::Printer;
18/// use escpos::utils::*;
19/// use escpos::{driver::*, errors::Result};
20///
21/// fn main() -> Result<()> {
22///     let driver = ConsoleDriver::open(false);
23///     let mut printer = Printer::new(driver, Protocol::default(), None);
24///     printer.init()?
25///         .debug_mode(Some(DebugMode::Dec))
26///         .writeln("My example")?
27///         .print_cut()?;
28///
29///     Ok(())
30/// }
31/// ```
32#[derive(Clone)]
33pub struct Printer<D: Driver> {
34    driver: D,
35    protocol: Protocol,
36    options: PrinterOptions,
37    instructions: Vec<Instruction>,
38    style_state: PrinterStyleState,
39}
40
41impl<D: Driver> Printer<D> {
42    /// Create a new `Printer`
43    ///
44    /// If no printer options are provided, the default options are used.
45    ///
46    /// # Example
47    ///
48    /// ```rust
49    /// use escpos::printer::Printer;
50    /// use escpos::utils::*;
51    /// use escpos::{driver::*, errors::Result};
52    ///
53    /// fn main() -> Result<()> {
54    ///     let driver = ConsoleDriver::open(false);
55    ///     Printer::new(driver, Protocol::default(), None);
56    ///
57    ///     Ok(())
58    /// }
59    /// ```
60    pub fn new(driver: D, protocol: Protocol, options: Option<PrinterOptions>) -> Self {
61        Self {
62            driver,
63            protocol,
64            options: options.unwrap_or_default(),
65            instructions: vec![],
66            style_state: PrinterStyleState::default(),
67        }
68    }
69
70    /// Get the printer protocol
71    pub fn protocol(&self) -> &Protocol {
72        &self.protocol
73    }
74
75    /// Get the printer options
76    pub fn options(&self) -> &PrinterOptions {
77        &self.options
78    }
79
80    /// Get the printer style state
81    ///
82    /// # Examples
83    /// ```
84    /// use escpos::printer::{Printer, PrinterStyleState};
85    /// use escpos::utils::*;
86    /// use escpos::{driver::*, errors::Result};
87    ///
88    /// fn main() -> Result<()> {
89    /// let driver = ConsoleDriver::open(false);
90    ///     let mut printer = Printer::new(driver, Protocol::default(), None);
91    ///     printer.bold(true)?
92    ///         .flip(true)?
93    ///         .font(Font::B)?;
94    ///
95    ///     let style_state = printer.style_state();
96    ///
97    ///     assert!(style_state.bold);
98    ///     assert!(style_state.flip);
99    ///     assert!(!style_state.reverse);
100    ///     assert!(!style_state.double_strike);
101    ///     assert_eq!(style_state.font, Font::B);
102    ///     assert_eq!(style_state.justify_mode, JustifyMode::default());
103    ///     assert_eq!(style_state.underline_mode, UnderlineMode::default());
104    ///     assert_eq!(style_state.text_size, (1, 1));
105    ///
106    ///     printer.print()?;
107    ///
108    ///     // Style state is reset after flushing the buffer
109    ///     assert_eq!(printer.style_state(), PrinterStyleState::default());
110    ///
111    ///     Ok(())
112    /// }
113    /// ```
114    pub fn style_state(&self) -> PrinterStyleState {
115        self.style_state.clone()
116    }
117
118    /// Reset the printer style state
119    pub fn reset_style_state(&mut self) -> &mut Self {
120        self.style_state = PrinterStyleState::default();
121        self
122    }
123
124    /// Flush the buffer, reset the style state and clean the instructions
125    fn flush(&mut self) -> Result<&mut Self> {
126        for instruction in self.instructions.iter() {
127            self.driver.write(&instruction.flatten_commands())?
128        }
129        self.driver.flush()?;
130        self.instructions = vec![];
131        self.reset_style_state();
132
133        Ok(self)
134    }
135
136    /// Set debug mode
137    pub fn debug_mode(&mut self, mode: Option<DebugMode>) -> &mut Self {
138        self.options.debug_mode(mode);
139        self
140    }
141
142    /// Print the data
143    ///
144    /// All the instructions are sent at the same time to avoid printing partial data
145    /// if an error occurred before the `print` command.
146    pub fn print(&mut self) -> Result<&mut Self> {
147        self.flush()?;
148
149        if self.options.get_debug_mode().is_some() {
150            debug!("[print]");
151        }
152
153        Ok(self)
154    }
155
156    /// Add command to instructions, write data and display debug information
157    fn command(&mut self, label: &str, cmd: &[Command]) -> Result<&mut Self> {
158        let instruction = Instruction::new(label, cmd, self.options.get_debug_mode());
159
160        if !label.is_empty() && self.options.get_debug_mode().is_some() {
161            debug!("{:?}", instruction.clone());
162        }
163
164        self.instructions.push(instruction);
165
166        Ok(self)
167    }
168
169    /// Hardware initialization
170    pub fn init(&mut self) -> Result<&mut Self> {
171        let cmd = self.protocol.init();
172        self.command("initialization", &[cmd])?;
173
174        // Set page code
175        if let Some(page_code) = self.options.get_page_code() {
176            let cmd = self.protocol.page_code(page_code);
177            self.command("character page code", &[cmd])?;
178        }
179
180        Ok(self)
181    }
182
183    /// Hardware reset
184    pub fn reset(&mut self) -> Result<&mut Self> {
185        let cmd = self.protocol.reset();
186        self.command("reset", &[cmd])
187    }
188
189    /// Paper full cut
190    pub fn cut(&mut self) -> Result<&mut Self> {
191        let cmd = self.protocol.cut(false);
192        self.command("full paper cut", &[cmd])
193    }
194
195    /// Paper partial cut
196    pub fn partial_cut(&mut self) -> Result<&mut Self> {
197        let cmd = self.protocol.cut(true);
198        self.command("partial paper cut", &[cmd])
199    }
200
201    /// Print and paper full cut
202    pub fn print_cut(&mut self) -> Result<&mut Self> {
203        let cmd = self.protocol.cut(false);
204        self.command("full paper cut", &[cmd])?.print()
205    }
206
207    /// Character page code
208    pub fn page_code(&mut self, code: PageCode) -> Result<&mut Self> {
209        self.options.page_code(Some(code));
210
211        let cmd = self.protocol.page_code(code);
212        self.command("character page code", &[cmd])
213    }
214
215    /// International character set
216    pub fn character_set(&mut self, code: CharacterSet) -> Result<&mut Self> {
217        let cmd = self.protocol.character_set(code);
218        self.command("international character set", &[cmd])
219    }
220
221    /// Text bold
222    pub fn bold(&mut self, enabled: bool) -> Result<&mut Self> {
223        let cmd = self.protocol.bold(enabled);
224        self.style_state.bold = enabled;
225        self.command("text bold", &[cmd])
226    }
227
228    /// Text underline
229    pub fn underline(&mut self, mode: UnderlineMode) -> Result<&mut Self> {
230        let cmd = self.protocol.underline(mode);
231        self.style_state.underline_mode = mode;
232        self.command("text underline", &[cmd])
233    }
234
235    /// Text double strike
236    pub fn double_strike(&mut self, enabled: bool) -> Result<&mut Self> {
237        let cmd = self.protocol.double_strike(enabled);
238        self.style_state.double_strike = enabled;
239        self.command("text double strike", &[cmd])
240    }
241
242    /// Text font
243    pub fn font(&mut self, font: Font) -> Result<&mut Self> {
244        let cmd = self.protocol.font(font);
245        self.style_state.font = font;
246        self.command("text font", &[cmd])
247    }
248
249    /// Text flip
250    pub fn flip(&mut self, enabled: bool) -> Result<&mut Self> {
251        let cmd = self.protocol.flip(enabled);
252        self.style_state.flip = enabled;
253        self.command("text flip", &[cmd])
254    }
255
256    /// Text justify
257    pub fn justify(&mut self, mode: JustifyMode) -> Result<&mut Self> {
258        let cmd = self.protocol.justify(mode);
259        self.style_state.justify_mode = mode;
260        self.command("text justify", &[cmd])
261    }
262
263    /// Text reverse colour
264    pub fn reverse(&mut self, enabled: bool) -> Result<&mut Self> {
265        let cmd = self.protocol.reverse_colours(enabled);
266        self.style_state.reverse = enabled;
267        self.command("text reverse colour", &[cmd])
268    }
269
270    /// Text size
271    pub fn size(&mut self, width: u8, height: u8) -> Result<&mut Self> {
272        let cmd = self.protocol.text_size(width, height)?;
273        self.style_state.text_size = (width, height);
274        self.command("text size", &[cmd])
275    }
276
277    /// Reset text size
278    pub fn reset_size(&mut self) -> Result<&mut Self> {
279        let cmd = self.protocol.text_size(1, 1)?;
280        self.style_state.text_size = (1, 1);
281        self.command("text size", &[cmd])
282    }
283
284    /// Smoothing mode
285    pub fn smoothing(&mut self, enabled: bool) -> Result<&mut Self> {
286        let cmd = self.protocol.smoothing(enabled);
287        self.command("smoothing mode", &[cmd])
288    }
289
290    /// Line feed
291    pub fn feed(&mut self) -> Result<&mut Self> {
292        let cmd = self.protocol.feed(1);
293        self.command("line feed", &[cmd])
294    }
295
296    /// Custom line feed
297    pub fn feeds(&mut self, lines: u8) -> Result<&mut Self> {
298        let cmd = self.protocol.feed(lines);
299        self.command("line feeds", &[cmd])
300    }
301
302    /// Line spacing
303    pub fn line_spacing(&mut self, value: u8) -> Result<&mut Self> {
304        let cmd = self.protocol.line_spacing(value);
305        self.command("line spacing", &[cmd])
306    }
307
308    /// Reset line spacing
309    pub fn reset_line_spacing(&mut self) -> Result<&mut Self> {
310        let cmd = self.protocol.reset_line_spacing();
311        self.command("reset line spacing", &[cmd])
312    }
313
314    /// Upside-down mode
315    pub fn upside_down(&mut self, enabled: bool) -> Result<&mut Self> {
316        let cmd = self.protocol.upside_down(enabled);
317        self.command("upside-down mode", &[cmd])
318    }
319
320    /// Cash drawer
321    pub fn cash_drawer(&mut self, pin: CashDrawer) -> Result<&mut Self> {
322        let cmd = self.protocol.cash_drawer(pin);
323        self.command("cash drawer", &[cmd])
324    }
325
326    /// Text
327    pub fn write(&mut self, text: &str) -> Result<&mut Self> {
328        let cmd = self.protocol.text(text, self.options.get_page_code(), None)?;
329        self.command("text", &[cmd])
330    }
331
332    /// Text + Line feed
333    pub fn writeln(&mut self, text: &str) -> Result<&mut Self> {
334        self.write(text)?.feed()
335    }
336
337    /// Custom command
338    ///
339    /// ```rust
340    /// use escpos::printer::Printer;
341    /// use escpos::utils::*;
342    /// use escpos::{driver::*, errors::Result};
343    ///
344    /// const EURO: &[u8] = &[0xD5]; // '€' in code page PC858
345    ///
346    /// fn main() -> Result<()> {
347    ///     let driver = ConsoleDriver::open(false);
348    ///     Printer::new(driver, Protocol::default(), None)
349    ///         .init()?
350    ///         .page_code(PageCode::PC858)?
351    ///         .custom(EURO)?
352    ///         .feed()?
353    ///         .print_cut()?;
354    ///
355    ///     Ok(())
356    /// }
357    /// ```
358    pub fn custom(&mut self, cmd: &[u8]) -> Result<&mut Self> {
359        self.command("custom command", &[cmd.to_vec()])
360    }
361
362    /// Custom command with page code
363    ///
364    /// ```rust
365    /// use escpos::printer::Printer;
366    /// use escpos::utils::*;
367    /// use escpos::{driver::*, errors::Result};
368    ///
369    /// const EURO: &[u8] = &[0xD5]; // '€' in code page PC858
370    ///
371    /// fn main() -> Result<()> {
372    ///     let driver = ConsoleDriver::open(false);
373    ///     Printer::new(driver, Protocol::default(), None)
374    ///         .init()?
375    ///         .custom_with_page_code(EURO, PageCode::PC858)?
376    ///         .page_code(PageCode::PC437)?
377    ///         .writeln("My test")?
378    ///         .print_cut()?;
379    ///
380    ///     Ok(())
381    /// }
382    /// ```
383    pub fn custom_with_page_code(&mut self, cmd: &[u8], page_code: PageCode) -> Result<&mut Self> {
384        self.page_code(page_code)?;
385        self.command(&format!("custom command width page code {page_code}"), &[cmd.to_vec()])
386    }
387
388    /// Set horizontal and vertical motion units
389    pub fn motion_units(&mut self, x: u8, y: u8) -> Result<&mut Self> {
390        let cmd = self.protocol.motion_units(x, y);
391        self.command("set motion units", &[cmd])
392    }
393
394    /// Ask printer to send real-time status
395    pub fn real_time_status(&mut self, status: RealTimeStatusRequest) -> Result<&mut Self> {
396        let cmd = self.protocol.real_time_status(status);
397        self.command("real-time status", &[cmd])
398    }
399
400    /// Send printer status commands
401    pub fn send_status(&mut self) -> Result<&mut Self> {
402        self.flush()?;
403
404        if self.options.get_debug_mode().is_some() {
405            debug!("[send printer status]");
406        }
407
408        Ok(self)
409    }
410
411    #[cfg(feature = "barcodes")]
412    /// Print barcode
413    fn barcode(&mut self, barcode: Barcode) -> Result<&mut Self> {
414        let commands = self.protocol.barcode(&barcode.data, barcode.system, barcode.option)?;
415        self.command(&format!("print {} barcode", barcode.system), commands.as_slice())
416    }
417
418    #[cfg(feature = "barcodes")]
419    /// Print EAN13 barcode with default option
420    pub fn ean13(&mut self, data: &str) -> Result<&mut Self> {
421        self.barcode(Barcode::new(BarcodeSystem::EAN13, data, BarcodeOption::default())?)
422    }
423
424    #[cfg(feature = "barcodes")]
425    /// Print EAN13 barcode with option
426    pub fn ean13_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
427        self.barcode(Barcode::new(BarcodeSystem::EAN13, data, option)?)
428    }
429
430    #[cfg(feature = "barcodes")]
431    /// Print EAN8 barcode with default option
432    pub fn ean8(&mut self, data: &str) -> Result<&mut Self> {
433        self.barcode(Barcode::new(BarcodeSystem::EAN8, data, BarcodeOption::default())?)
434    }
435
436    #[cfg(feature = "barcodes")]
437    /// Print EAN8 barcode with option
438    pub fn ean8_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
439        self.barcode(Barcode::new(BarcodeSystem::EAN8, data, option)?)
440    }
441
442    #[cfg(feature = "barcodes")]
443    /// Print UPC-A barcode with default option
444    pub fn upca(&mut self, data: &str) -> Result<&mut Self> {
445        self.barcode(Barcode::new(BarcodeSystem::UPCA, data, BarcodeOption::default())?)
446    }
447
448    #[cfg(feature = "barcodes")]
449    /// Print UPC-A barcode with option
450    pub fn upca_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
451        self.barcode(Barcode::new(BarcodeSystem::UPCA, data, option)?)
452    }
453
454    #[cfg(feature = "barcodes")]
455    /// Print UPC-E barcode with default option
456    pub fn upce(&mut self, data: &str) -> Result<&mut Self> {
457        self.barcode(Barcode::new(BarcodeSystem::UPCE, data, BarcodeOption::default())?)
458    }
459
460    #[cfg(feature = "barcodes")]
461    /// Print UPC-E barcode with option
462    pub fn upce_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
463        self.barcode(Barcode::new(BarcodeSystem::UPCE, data, option)?)
464    }
465
466    #[cfg(feature = "barcodes")]
467    /// Print CODE 39 barcode with default option
468    pub fn code39(&mut self, data: &str) -> Result<&mut Self> {
469        self.barcode(Barcode::new(BarcodeSystem::CODE39, data, BarcodeOption::default())?)
470    }
471
472    #[cfg(feature = "barcodes")]
473    /// Print CODE 39 barcode with option
474    pub fn code39_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
475        self.barcode(Barcode::new(BarcodeSystem::CODE39, data, option)?)
476    }
477
478    #[cfg(feature = "barcodes")]
479    /// Print CODABAR barcode with default option
480    pub fn codabar(&mut self, data: &str) -> Result<&mut Self> {
481        self.barcode(Barcode::new(BarcodeSystem::CODABAR, data, BarcodeOption::default())?)
482    }
483
484    #[cfg(feature = "barcodes")]
485    /// Print CODABAR barcode with option
486    pub fn codabar_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
487        self.barcode(Barcode::new(BarcodeSystem::CODABAR, data, option)?)
488    }
489
490    #[cfg(feature = "barcodes")]
491    /// Print ITF barcode with default option
492    pub fn itf(&mut self, data: &str) -> Result<&mut Self> {
493        self.barcode(Barcode::new(BarcodeSystem::ITF, data, BarcodeOption::default())?)
494    }
495
496    #[cfg(feature = "barcodes")]
497    /// Print ITF barcode with option
498    pub fn itf_option(&mut self, data: &str, option: BarcodeOption) -> Result<&mut Self> {
499        self.barcode(Barcode::new(BarcodeSystem::ITF, data, option)?)
500    }
501
502    #[cfg(feature = "codes_2d")]
503    /// Construct QR code
504    fn qrcode_builder(&mut self, data: &str, option: Option<QRCodeOption>) -> Result<&mut Self> {
505        let qrcode = QRCode::new(data, option)?;
506        let commands = self.protocol.qrcode(&qrcode.data, qrcode.option)?;
507        self.command("print qrcode", commands.as_slice())
508    }
509
510    #[cfg(feature = "codes_2d")]
511    /// Print QR code with default option
512    pub fn qrcode(&mut self, data: &str) -> Result<&mut Self> {
513        self.qrcode_builder(data, None)
514    }
515
516    #[cfg(feature = "codes_2d")]
517    /// Print QR code with option
518    pub fn qrcode_option(&mut self, data: &str, option: QRCodeOption) -> Result<&mut Self> {
519        self.qrcode_builder(data, Some(option))
520    }
521
522    #[cfg(feature = "codes_2d")]
523    /// Construct 2D GS1 DataBar with custom option
524    pub fn gs1_databar_2d_option(&mut self, data: &str, option: GS1DataBar2DOption) -> Result<&mut Self> {
525        let code = GS1DataBar2D::new(data, option)?;
526        let commands = self.protocol.gs1_databar_2d(&code.data, code.option)?;
527        self.command("print 2D GS1 DataBar", commands.as_slice())
528    }
529
530    #[cfg(feature = "codes_2d")]
531    /// Construct 2D GS1 DataBar
532    pub fn gs1_databar_2d(&mut self, data: &str) -> Result<&mut Self> {
533        self.gs1_databar_2d_option(data, GS1DataBar2DOption::default())
534    }
535
536    #[cfg(feature = "codes_2d")]
537    /// PDF417
538    pub fn pdf417_option(&mut self, data: &str, option: Pdf417Option) -> Result<&mut Self> {
539        let code = Pdf417::new(data, option);
540        let commands = self.protocol.pdf417(&code.data, code.option)?;
541        self.command("print PDF417", commands.as_slice())
542    }
543
544    #[cfg(feature = "codes_2d")]
545    /// PDF417
546    pub fn pdf417(&mut self, data: &str) -> Result<&mut Self> {
547        let code = Pdf417::new(data, Pdf417Option::default());
548        self.pdf417_option(data, code.option)
549    }
550
551    #[cfg(feature = "codes_2d")]
552    /// MaxiCode
553    pub fn maxi_code_option(&mut self, data: &str, mode: MaxiCodeMode) -> Result<&mut Self> {
554        let code = MaxiCode::new(data, mode);
555        let commands = self.protocol.maxi_code(&code.data, code.mode)?;
556        self.command("print MaxiCode", commands.as_slice())
557    }
558
559    #[cfg(feature = "codes_2d")]
560    /// MaxiCode
561    pub fn maxi_code(&mut self, data: &str) -> Result<&mut Self> {
562        let code = MaxiCode::new(data, MaxiCodeMode::default());
563        self.maxi_code_option(data, code.mode)
564    }
565
566    #[cfg(feature = "codes_2d")]
567    /// DataMatrix
568    pub fn data_matrix_option(&mut self, data: &str, option: DataMatrixOption) -> Result<&mut Self> {
569        let code = DataMatrix::new(data, option);
570        let commands = self.protocol.data_matrix(&code.data, code.option)?;
571        self.command("print DataMatrix", commands.as_slice())
572    }
573
574    #[cfg(feature = "codes_2d")]
575    /// DataMatrix
576    pub fn data_matrix(&mut self, data: &str) -> Result<&mut Self> {
577        let code = DataMatrix::new(data, DataMatrixOption::default());
578        self.data_matrix_option(data, code.option)
579    }
580
581    #[cfg(feature = "codes_2d")]
582    /// Aztec code
583    pub fn aztec_option(&mut self, data: &str, option: AztecOption) -> Result<&mut Self> {
584        let code = Aztec::new(data, option);
585        let commands = self.protocol.aztec(&code.data, code.option)?;
586        self.command("print Aztec", commands.as_slice())
587    }
588
589    #[cfg(feature = "codes_2d")]
590    /// Aztec code
591    pub fn aztec(&mut self, data: &str) -> Result<&mut Self> {
592        let code = Aztec::new(data, AztecOption::default());
593        self.aztec_option(data, code.option)
594    }
595
596    #[cfg(feature = "graphics")]
597    /// Print image
598    pub fn bit_image_option(&mut self, path: &str, option: BitImageOption) -> Result<&mut Self> {
599        let cmd = self.protocol.cancel();
600        self.command("cancel data", &[cmd])?;
601
602        let cmd = self.protocol.bit_image(path, option)?;
603        self.command("print bit image", &[cmd])
604    }
605
606    #[cfg(feature = "graphics")]
607    /// Print image
608    pub fn bit_image(&mut self, path: &str) -> Result<&mut Self> {
609        self.bit_image_option(path, BitImageOption::default())
610    }
611
612    #[cfg(feature = "graphics")]
613    /// Print image
614    pub fn bit_image_from_bytes_option(&mut self, bytes: &[u8], option: BitImageOption) -> Result<&mut Self> {
615        let cmd = self.protocol.cancel();
616        self.command("cancel data", &[cmd])?;
617
618        let cmd = self.protocol.bit_image_from_bytes(bytes, option)?;
619        self.command("print bit image from bytes", &[cmd])
620    }
621
622    #[cfg(feature = "graphics")]
623    /// Print image
624    pub fn bit_image_from_bytes(&mut self, bytes: &[u8]) -> Result<&mut Self> {
625        self.bit_image_from_bytes_option(bytes, BitImageOption::default())
626    }
627
628    #[cfg(feature = "ui")]
629    /// Print line
630    pub fn draw_line(&mut self, line: Line) -> Result<&mut Self> {
631        let commands = self
632            .protocol
633            .draw_line(line, self.options.clone(), self.style_state.clone())?;
634        self.command("draw line", commands.as_slice())
635    }
636
637    // #[cfg(feature = "graphics")]
638    // /// Print image
639    // fn _image(&mut self, path: &str) -> Result<&mut Self> {
640    //     let cmd = self.protocol.graphic_density(GraphicDensity::Low);
641    //     self.command("set graphic density", cmd)?;
642    //
643    //     let cmd = self.protocol.graphic_data(path)?;
644    //     self.command("set graphic data", cmd)?;
645    //
646    //     // Print
647    //     let cmd = self.protocol.graphic_print();
648    //     self.command("print graphic", cmd)
649    // }
650}
651
652#[derive(Debug, Clone, PartialEq)]
653pub struct PrinterStyleState {
654    pub text_size: (u8, u8),
655    pub justify_mode: JustifyMode,
656    pub font: Font,
657    pub underline_mode: UnderlineMode,
658    pub bold: bool,
659    pub double_strike: bool,
660    pub reverse: bool,
661    pub flip: bool,
662}
663
664impl Default for PrinterStyleState {
665    fn default() -> Self {
666        Self {
667            text_size: (1, 1),
668            justify_mode: JustifyMode::default(),
669            font: Font::default(),
670            underline_mode: UnderlineMode::default(),
671            bold: false,
672            double_strike: false,
673            reverse: false,
674            flip: false,
675        }
676    }
677}
678
679impl PrinterStyleState {}
680
681#[cfg(test)]
682mod tests {
683    use super::*;
684    use crate::driver::ConsoleDriver;
685
686    #[test]
687    fn test_command() {
688        let driver = ConsoleDriver::open(false);
689        let debug_mode = None;
690        let mut printer = Printer::new(driver, Protocol::default(), None);
691        printer.debug_mode(debug_mode).init().unwrap();
692        let cmd = printer.protocol.cut(false);
693        let printer = printer.command("test paper cut", &[cmd]).unwrap();
694
695        let expected = vec![
696            Instruction::new("initialization", &[vec![27, 64]], debug_mode),
697            Instruction::new("test paper cut", &[vec![29, 86, 65, 0]], debug_mode),
698        ];
699
700        assert_eq!(printer.instructions, expected);
701    }
702}