1use super::fmt::{parse_brc80, parse_brc97, parse_shd80, parse_shd_operand, Border, Shading};
7use super::sprm::{self, Sprm};
8
9#[derive(Debug, Default, Clone)]
10pub struct TableCell {
11 pub boundary_left: i32,
13 pub boundary_right: i32,
14 pub f_first_merged: bool,
15 pub f_merged: bool,
16 pub f_vert_merge: bool,
17 pub f_vert_restart: bool,
18 pub f_vertical: bool,
19 pub f_backward: bool,
20 pub vert_align: u8,
21 pub brc_top: Option<Border>,
22 pub brc_left: Option<Border>,
23 pub brc_bottom: Option<Border>,
24 pub brc_right: Option<Border>,
25 pub shd: Option<Shading>,
26}
27
28#[derive(Debug, Default, Clone)]
29pub struct Tap {
30 pub jc: u8,
31 pub dxa_gap_half: i16,
32 pub dya_row_height: i16,
33 pub f_cant_split: bool,
34 pub f_table_header: bool,
35 pub cells: Vec<TableCell>,
36 pub table_borders: [Option<Border>; 6], }
38
39impl Tap {
40 pub fn from_grpprl(grpprl: &[u8]) -> Tap {
41 let mut tap = Tap::default();
42 let mut shd_queue: Vec<Shading> = Vec::new();
43 let mut shd_assigned = 0usize;
44 for sprm in sprm::iterate(grpprl) {
45 tap.apply_sprm(&sprm, &mut shd_queue, &mut shd_assigned);
46 }
47 for (index, shading) in shd_queue.into_iter().enumerate() {
49 if let Some(cell) = tap.cells.get_mut(index) {
50 if cell.shd.is_none() && shading.is_visible() {
51 cell.shd = Some(shading);
52 }
53 }
54 }
55 tap
56 }
57
58 fn apply_sprm(
59 &mut self,
60 sprm: &Sprm<'_>,
61 shd_queue: &mut Vec<Shading>,
62 shd_assigned: &mut usize,
63 ) {
64 match sprm.opcode {
65 0x5400 | 0x548A => self.jc = sprm.byte(),
66 0x9602 => self.dxa_gap_half = sprm.i16_operand(),
67 0x9407 => self.dya_row_height = sprm.i16_operand(),
68 0x3403 => self.f_cant_split = sprm.byte() == 1,
69 0x3404 => self.f_table_header = sprm.byte() == 1,
70 0xD608 => self.apply_tdef_table(sprm.operand),
71 0xD605 => {
72 for (index, chunk) in sprm.operand.chunks_exact(4).take(6).enumerate() {
73 self.table_borders[index] = parse_brc80(chunk);
74 }
75 }
76 0xD613 => {
77 for (index, chunk) in sprm.operand.chunks_exact(8).take(6).enumerate() {
78 let border = parse_brc97(chunk);
79 if border.is_some() {
80 self.table_borders[index] = border;
81 }
82 }
83 }
84 0xD609 => {
85 for chunk in sprm.operand.chunks_exact(2) {
87 if let Some(shading) = parse_shd80(u16::from_le_bytes([chunk[0], chunk[1]])) {
88 shd_queue.push(shading);
89 }
90 }
91 let _ = shd_assigned;
92 }
93 0xD612 => {
94 for chunk in sprm.operand.chunks_exact(10) {
96 if let Some(shading) = parse_shd_operand(chunk) {
97 shd_queue.push(shading);
98 }
99 }
100 }
101 0xD620 => self.apply_set_brc80(sprm.operand),
102 0xD62B => {
103 if sprm.operand.len() >= 2 {
105 let itc = sprm.operand[0] as usize;
106 let code = sprm.operand[1];
107 if let Some(cell) = self.cells.get_mut(itc) {
108 cell.f_vert_merge = code & 0x01 != 0;
109 cell.f_vert_restart = code & 0x02 != 0;
110 }
111 }
112 }
113 0xD62C => {
114 if sprm.operand.len() >= 3 {
116 let first = sprm.operand[0] as usize;
117 let lim = sprm.operand[1] as usize;
118 for itc in first..lim.min(self.cells.len()) {
119 self.cells[itc].vert_align = sprm.operand[2];
120 }
121 }
122 }
123 0x7627 | 0x7628 => {
124 if sprm.operand.len() >= 4 {
127 let first = sprm.operand[0] as usize;
128 let lim = sprm.operand[1] as usize;
129 let shading = parse_shd80(u16::from_le_bytes([sprm.operand[2], sprm.operand[3]]));
130 if let Some(shading) = shading {
131 for itc in first..lim.min(self.cells.len()) {
132 self.cells[itc].shd = Some(shading.clone());
133 }
134 }
135 }
136 }
137 _ => {}
138 }
139 }
140
141 fn apply_tdef_table(&mut self, operand: &[u8]) {
143 let Some(&itc_mac) = operand.first() else {
144 return;
145 };
146 let count = itc_mac as usize;
147 let centers_end = 1 + (count + 1) * 2;
148 if operand.len() < centers_end || count == 0 {
149 return;
150 }
151 let mut centers = Vec::with_capacity(count + 1);
152 for index in 0..=count {
153 let offset = 1 + index * 2;
154 centers.push(i16::from_le_bytes([operand[offset], operand[offset + 1]]) as i32);
155 }
156
157 self.cells = (0..count)
158 .map(|index| {
159 let mut cell = TableCell {
160 boundary_left: centers[index],
161 boundary_right: centers[index + 1],
162 ..TableCell::default()
163 };
164 let tc_offset = centers_end + index * 20;
165 if let Some(tc) = operand.get(tc_offset..tc_offset + 20) {
166 let rgf = u16::from_le_bytes([tc[0], tc[1]]);
167 cell.f_first_merged = rgf & 0x0001 != 0;
168 cell.f_merged = rgf & 0x0002 != 0;
169 cell.f_vertical = rgf & 0x0004 != 0;
170 cell.f_backward = rgf & 0x0008 != 0;
171 cell.f_vert_merge = rgf & 0x0020 != 0;
172 cell.f_vert_restart = rgf & 0x0040 != 0;
173 cell.vert_align = ((rgf >> 7) & 0x3) as u8;
174 cell.brc_top = parse_brc80(&tc[4..8]);
175 cell.brc_left = parse_brc80(&tc[8..12]);
176 cell.brc_bottom = parse_brc80(&tc[12..16]);
177 cell.brc_right = parse_brc80(&tc[16..20]);
178 }
179 cell
180 })
181 .collect();
182 }
183
184 fn apply_set_brc80(&mut self, operand: &[u8]) {
187 if operand.len() < 7 {
188 return;
189 }
190 let first = operand[0] as usize;
191 let lim = operand[1] as usize;
192 let grfbrc = operand[2];
193 let border = parse_brc80(&operand[3..7]);
194 for itc in first..lim.min(self.cells.len()) {
195 let cell = &mut self.cells[itc];
196 if grfbrc & 0x01 != 0 {
197 cell.brc_top = border.clone();
198 }
199 if grfbrc & 0x02 != 0 {
200 cell.brc_left = border.clone();
201 }
202 if grfbrc & 0x04 != 0 {
203 cell.brc_bottom = border.clone();
204 }
205 if grfbrc & 0x08 != 0 {
206 cell.brc_right = border.clone();
207 }
208 }
209 }
210
211 pub fn row_left_edge(&self) -> i32 {
212 self.cells.first().map(|cell| cell.boundary_left).unwrap_or(0)
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use super::*;
219
220 fn tdef_operand(centers: &[i16], tc_flags: &[u16]) -> Vec<u8> {
221 let count = centers.len() - 1;
222 let mut operand = vec![count as u8];
223 for center in centers {
224 operand.extend_from_slice(¢er.to_le_bytes());
225 }
226 for index in 0..count {
227 let mut tc = [0u8; 20];
228 tc[..2].copy_from_slice(&tc_flags.get(index).copied().unwrap_or(0).to_le_bytes());
229 operand.extend_from_slice(&tc);
230 }
231 operand
232 }
233
234 #[test]
235 fn parses_tdef_table_boundaries() {
236 let operand = tdef_operand(&[0, 2400, 4800, 9360], &[0, 0, 0]);
237 let mut grpprl: Vec<u8> = vec![0x08, 0xD6];
238 grpprl.extend_from_slice(&((operand.len() + 1) as u16).to_le_bytes());
239 grpprl.extend_from_slice(&operand);
240
241 let tap = Tap::from_grpprl(&grpprl);
242 assert_eq!(tap.cells.len(), 3);
243 assert_eq!(tap.cells[0].boundary_left, 0);
244 assert_eq!(tap.cells[0].boundary_right, 2400);
245 assert_eq!(tap.cells[2].boundary_right, 9360);
246 }
247
248 #[test]
249 fn parses_vert_merge_flags() {
250 let operand = tdef_operand(&[0, 1000, 2000], &[0x0040, 0x0020]);
251 let mut grpprl: Vec<u8> = vec![0x08, 0xD6];
252 grpprl.extend_from_slice(&((operand.len() + 1) as u16).to_le_bytes());
253 grpprl.extend_from_slice(&operand);
254
255 let tap = Tap::from_grpprl(&grpprl);
256 assert!(tap.cells[0].f_vert_restart);
257 assert!(tap.cells[1].f_vert_merge);
258 assert!(!tap.cells[1].f_vert_restart);
259 }
260}