1use crate::font::Font;
2use format_bytes::write_bytes as wb;
3use std::collections::BTreeSet;
4
5#[derive(Default)]
7pub struct Page {
8 pub width: i16,
10
11 pub height: i16,
13
14 pub os: Vec<u8>,
16
17 pub ts: Vec<u8>,
19
20 pub text: Vec<u8>,
22
23 pub x: i16,
25
26 pub y: i16,
28
29 font_obj: usize,
31
32 font_size: i16,
34
35 pub sup: i16,
37
38 last_font_obj: usize,
40
41 last_font_size: i16,
43
44 pub fonts: BTreeSet<usize>,
46
47 pub xobjs: BTreeSet<usize>,
49}
50
51impl Page {
52 pub fn goto(&mut self, x: i16, y: i16) {
54 self.td(x - self.x, y - self.y);
55 }
56
57 pub fn td(&mut self, x: i16, y: i16) {
59 self.flush_text();
60 let _ = wb!(&mut self.ts, b"\n{} {} Td ", x, y);
61 self.x += x;
62 self.y += y;
63 }
64
65 pub fn text(&mut self, font: &dyn Font, size: i16, s: &str) {
67 if size != self.font_size || font.obj() != self.font_obj {
68 self.flush_text();
69 self.font_obj = font.obj();
70 self.font_size = size;
71 }
72 font.encode(s, &mut self.text);
73 }
74
75 fn flush_text(&mut self) {
77 if self.text.is_empty() {
78 return;
79 }
80 if self.font_obj != self.last_font_obj || self.font_size != self.last_font_size {
81 self.fonts.insert(self.font_obj);
82 let obj = self.font_obj;
83 let size = self.font_size;
84 let _ = wb!(&mut self.ts, b"/F{} {} Tf", obj, size);
85 self.last_font_obj = obj;
86 self.last_font_size = size;
87 }
88 let mut hex = false;
89 for b in &self.text {
90 if *b < 32 || *b >= 128 {
91 hex = true;
92 break;
93 }
94 }
95 if hex {
96 self.ts.push(b'<');
97 for b in &self.text {
98 let x = *b >> 4;
99 self.ts.push(x + if x < 10 { 48 } else { 55 });
100 let x = *b & 15;
101 self.ts.push(x + if x < 10 { 48 } else { 55 });
102 }
103 self.ts.extend_from_slice(b"> Tj");
104 } else {
105 self.ts.push(b'(');
106 for b in &self.text {
107 let b = *b;
108 if b == b'(' || b == b')' || b == b'\\' {
109 self.ts.push(b'\\');
110 }
111 self.ts.push(b);
112 }
113 self.ts.extend_from_slice(b") Tj");
114 }
115 self.text.clear();
116 }
117
118 pub fn finish(&mut self) {
120 self.flush_text();
121 self.os.extend_from_slice(b"\nBT");
122 self.os.extend_from_slice(&self.ts);
123 self.ts.clear();
124 self.os.extend_from_slice(b"\nET");
125 }
126
127 pub fn line(&mut self, x0: f64, y0: f64, x1: f64, y1: f64) {
131 let _ = wb!(&mut self.os, b"\n{} {} m {} {} l S", x0, y0, x1, y1);
132 }
133
134 pub fn rect(&mut self, x0: f64, y0: f64, x1: f64, y1: f64) {
136 let _ = wb!(&mut self.os, b"\n{} {} m {} {} re S", x0, y0, x1, y1);
137 }
138
139 pub fn set_sup(&mut self, sup: i16) {
141 if self.sup != sup {
142 self.flush_text();
143 self.sup = sup;
144 let _ = wb!(&mut self.ts, b" {} Ts", sup);
145 }
146 }
147}