spectrusty_utils/printer/
image_spooler.rs1use std::io;
9
10#[cfg(feature = "snapshot")]
11use serde::{Serialize, Deserialize};
12#[allow(unused_imports)]
13use log::{error, warn, info, debug, trace};
14
15use spectrusty::peripherals::zxprinter::{DOTS_PER_LINE, BYTES_PER_LINE, Spooler};
16use super::*;
17
18#[derive(Clone, Default, Debug)]
24#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
25#[cfg_attr(feature = "snapshot", serde(default))]
26pub struct ImageSpooler {
27 spooling: bool,
28 #[cfg_attr(feature = "snapshot", serde(skip))]
29 buf: Vec<u8>
30}
31
32impl Spooler for ImageSpooler {
33 fn motor_on(&mut self) {
34 self.spooling = true;
35 }
36
37 fn push_line(&mut self, line: &[u8]) {
38 assert!(line.len() <= BYTES_PER_LINE as usize);
39 self.buf.extend_from_slice(line);
40 self.buf.resize(self.buf.len() + BYTES_PER_LINE as usize - line.len(), 0);
41 self.spooling = true;
42 debug!("printed line: {}", self.buf.len() / BYTES_PER_LINE as usize);
43 }
44
45 fn motor_off(&mut self) {
46 self.spooling = false;
47 debug!("end of printing");
48 }
49}
50
51impl DotMatrixGfx for ImageSpooler {
52 fn is_spooling(&self) -> bool {
53 self.spooling
54 }
55
56 fn lines_buffered(&self) -> usize {
57 (self.buf.len() + BYTES_PER_LINE as usize - 1) / BYTES_PER_LINE as usize
58 }
59
60 fn clear(&mut self) {
61 self.buf.clear();
62 }
63
64 fn write_svg_dot_gfx_lines(&self, description: &str, target: &mut dyn io::Write) -> io::Result<bool> {
65 let lines = self.lines_buffered();
66 if lines == 0 {
67 return Ok(false)
68 }
69 write!(target, r##"<?xml version="1.0" standalone="no"?>
70<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
71 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
72<svg width="110mm" height="{height_mm:.2}mm" version="1.1"
73 viewBox="0 0 {pixel_width} {pixel_height}" preserveAspectRatio="none"
74 xmlns="http://www.w3.org/2000/svg">
75 <desc>{description}</desc>
76 <g stroke-width="0.2" stroke="#b8b" fill="#646">
77"##,
78 description=description,
79 height_mm=0.4*lines as f32,
80 pixel_width=DOTS_PER_LINE,
81 pixel_height = lines)?;
82 for (index, mut dots) in self.buf.iter().copied().enumerate() {
83 let x = (index % BYTES_PER_LINE as usize) * 8;
84 let y = index / BYTES_PER_LINE as usize;
85 for i in 0..8 {
86 dots = dots.rotate_left(1);
87 if dots & 1 == 1 {
88 write!(target,
89 r##"<circle cx="{}" cy="{}" r="0.5"/>"##,
90 x + i, y)?;
91 }
92 }
93 }
94 target.write_all(b"</g></svg>")?;
95 Ok(true)
96 }
97
98 fn write_gfx_data(&mut self, target: &mut Vec<u8>) -> Option<(u32, u32)> {
99 let height = self.lines_buffered();
100 if height == 0 {
101 return None;
102 }
103 target.reserve_exact(DOTS_PER_LINE as usize * height);
104 target.extend(self.buf.iter().copied().flat_map(|mut bits| {
105 (0..8).map(move |_| {
106 bits = bits.rotate_left(1);
107 if bits & 1 == 1 { 0 } else { !0 }
108 })
109 }));
110 Some((DOTS_PER_LINE, height as u32))
111 }
112}