1use crate::font::Font;
2use crate::*;
3use format_bytes::write_bytes as wb;
4use std::collections::BTreeSet;
5
6#[derive(Default)]
8pub struct Page {
9 pub width: Px,
11
12 pub height: Px,
14
15 pub os: Vec<u8>,
17
18 pub ts: Vec<u8>,
20
21 pub text: Vec<u8>,
23
24 pub x: Px,
26
27 pub y: Px,
29
30 font_obj: usize,
32
33 font_size: Px,
35
36 pub sup: Px,
38
39 last_font_obj: usize,
41
42 last_font_size: Px,
44
45 pub fonts: BTreeSet<usize>,
47
48 pub xobjs: BTreeSet<usize>,
50}
51
52impl Page {
53 pub fn goto(&mut self, x: Px, y: Px) {
55 self.td(x - self.x, y - self.y);
56 }
57
58 pub fn td(&mut self, x: Px, y: Px) {
60 self.flush_text();
61 let _ = wb!(&mut self.ts, b"\n{} {} Td ", x, y);
62 self.x += x;
63 self.y += y;
64 }
65
66 pub fn text(&mut self, font: &dyn Font, size: Px, s: &str) {
68 if size != self.font_size || font.obj() != self.font_obj {
69 self.flush_text();
70 self.font_obj = font.obj();
71 self.font_size = size;
72 }
73 font.encode(s, &mut self.text);
74 }
75
76 pub fn space(&mut self, amount: MPx) {
78 let amount = amount / (self.font_size as MPx);
79 let _ = wb!(&mut self.ts, b"[{}] TJ ", -amount);
80 }
81
82 pub fn flush_text(&mut self) {
84 if self.text.is_empty() {
85 return;
86 }
87 if self.font_obj != self.last_font_obj || self.font_size != self.last_font_size {
88 self.fonts.insert(self.font_obj);
89 let obj = self.font_obj;
90 let size = self.font_size;
91 let _ = wb!(&mut self.ts, b"/F{} {} Tf", obj, size);
92 self.last_font_obj = obj;
93 self.last_font_size = size;
94 }
95 let mut hex = false;
96 for b in &self.text {
97 if *b < 32 || *b >= 128 {
98 hex = true;
99 break;
100 }
101 }
102 if hex {
103 self.ts.push(b'<');
104 for b in &self.text {
105 let x = *b >> 4;
106 self.ts.push(x + if x < 10 { 48 } else { 55 });
107 let x = *b & 15;
108 self.ts.push(x + if x < 10 { 48 } else { 55 });
109 }
110 self.ts.extend_from_slice(b"> Tj");
111 } else {
112 self.ts.push(b'(');
113 for b in &self.text {
114 let b = *b;
115 if b == b'(' || b == b')' || b == b'\\' {
116 self.ts.push(b'\\');
117 }
118 self.ts.push(b);
119 }
120 self.ts.extend_from_slice(b") Tj");
121 }
122 self.text.clear();
123 }
124
125 pub fn finish(&mut self) {
127 self.flush_text();
128 self.os.extend_from_slice(b"\nBT");
129 self.os.extend_from_slice(&self.ts);
130 self.ts.clear();
131 self.os.extend_from_slice(b"\nET");
132 }
133
134 pub fn line(&mut self, x0: f64, y0: f64, x1: f64, y1: f64) {
138 let _ = wb!(&mut self.os, b"\n{} {} m {} {} l S", x0, y0, x1, y1);
139 }
140
141 pub fn rect(&mut self, x0: f64, y0: f64, x1: f64, y1: f64) {
143 let _ = wb!(&mut self.os, b"\n{} {} {} {} re S", x0, y0, x1, y1);
144 }
145
146 pub fn set_sup(&mut self, sup: Px) {
148 if self.sup != sup {
149 self.flush_text();
150 self.sup = sup;
151 let _ = wb!(&mut self.ts, b" {} Ts", sup);
152 }
153 }
154}