docx_rs/reader/
drawing.rs1#![allow(clippy::single_match)]
2
3use std::io::Read;
4use std::str::FromStr;
5
6use xml::attribute::OwnedAttribute;
7use xml::reader::{EventReader, XmlEvent};
8
9use crate::types::*;
10use crate::{DrawingPositionType, RelativeFromHType, RelativeFromVType};
11
12use super::*;
13
14fn read_position_h<R: Read>(
15 r: &mut EventReader<R>,
16 attrs: &[OwnedAttribute],
17) -> Result<(RelativeFromHType, i32), ReaderError> {
18 let mut offset: i32 = 0;
19 let mut relative_from_h = RelativeFromHType::default();
20
21 loop {
22 if let Some(h) = read(attrs, "relativeFrom") {
23 if let Ok(h) = RelativeFromHType::from_str(&h) {
24 relative_from_h = h;
25 }
26 }
27 let e = r.next();
28 match e {
29 Ok(XmlEvent::Characters(c)) => {
30 if let Ok(p) = f64::from_str(&c) {
31 offset = p as i32;
32 }
33 }
34 Ok(XmlEvent::EndElement { name, .. }) => {
35 let e = WpXMLElement::from_str(&name.local_name).unwrap();
36 if e == WpXMLElement::PositionH {
37 return Ok((relative_from_h, offset));
38 }
39 }
40 Err(_) => return Err(ReaderError::XMLReadError),
41 _ => {}
42 }
43 }
44}
45
46fn read_position_v<R: Read>(
47 r: &mut EventReader<R>,
48 attrs: &[OwnedAttribute],
49) -> Result<(RelativeFromVType, i32), ReaderError> {
50 let mut offset: i32 = 0;
51 let mut relative_from_v = RelativeFromVType::default();
52 loop {
53 if let Some(v) = read(attrs, "relativeFrom") {
54 if let Ok(v) = RelativeFromVType::from_str(&v) {
55 relative_from_v = v;
56 }
57 }
58
59 let e = r.next();
60 match e {
61 Ok(XmlEvent::Characters(c)) => {
62 if let Ok(p) = f64::from_str(&c) {
63 offset = p as i32;
64 }
65 }
66 Ok(XmlEvent::EndElement { name, .. }) => {
67 let e = WpXMLElement::from_str(&name.local_name).unwrap();
68 if e == WpXMLElement::PositionV {
69 return Ok((relative_from_v, offset));
70 }
71 }
72 Err(_) => return Err(ReaderError::XMLReadError),
73 _ => {}
74 }
75 }
76}
77
78fn read_textbox_content<R: Read>(
79 r: &mut EventReader<R>,
80 _attrs: &[OwnedAttribute],
81) -> Result<Vec<TextBoxContentChild>, ReaderError> {
82 let mut children = vec![];
83 loop {
84 let e = r.next();
85 match e {
86 Ok(XmlEvent::StartElement {
87 attributes, name, ..
88 }) => {
89 let e = XMLElement::from_str(&name.local_name).unwrap();
90 match e {
91 XMLElement::Paragraph => {
92 let p = Paragraph::read(r, &attributes)?;
93 children.push(TextBoxContentChild::Paragraph(Box::new(p)));
94 continue;
95 }
96 XMLElement::Table => {
97 let t = Table::read(r, &attributes)?;
98 children.push(TextBoxContentChild::Table(Box::new(t)));
99 continue;
100 }
101 _ => {}
102 }
103 }
104 Ok(XmlEvent::EndElement { name, .. }) => {
105 let e = WpsXMLElement::from_str(&name.local_name).unwrap();
106 if e == WpsXMLElement::Txbx {
107 return Ok(children);
108 }
109 }
110 Err(_) => return Err(ReaderError::XMLReadError),
111 _ => {}
112 }
113 }
114}
115
116impl ElementReader for Drawing {
117 fn read<R: Read>(
118 r: &mut EventReader<R>,
119 _attrs: &[OwnedAttribute],
120 ) -> Result<Self, ReaderError> {
121 let mut drawing = Drawing::new();
122 let mut drawing_position_type = DrawingPositionType::Inline;
123
124 let mut simple_pos = false;
125 let mut simple_pos_x = 0;
126 let mut simple_pos_y = 0;
127 let mut layout_in_cell = true;
128 let mut relative_height = 0;
129 let mut position_h = 0;
130 let mut position_v = 0;
131 let mut relative_from_h = RelativeFromHType::default();
132 let mut relative_from_v = RelativeFromVType::default();
133 let mut allow_overlap = true;
134 let mut dist_t = 0;
135 let mut dist_b = 0;
136 let mut dist_l = 0;
137 let mut dist_r = 0;
138
139 loop {
140 let e = r.next();
141 match e {
142 Ok(XmlEvent::StartElement {
143 name, attributes, ..
144 }) => {
145 if let Ok(wpe) = WpXMLElement::from_str(&name.local_name) {
147 match wpe {
148 WpXMLElement::Anchor => {
149 drawing_position_type = DrawingPositionType::Anchor;
150 if let Some(v) = read(&attributes, "simplePos") {
151 if !is_false(&v) {
152 simple_pos = true;
153 }
154 }
155 if let Some(d) = read(&attributes, "distT") {
156 if let Ok(d) = f64::from_str(&d) {
157 dist_t = d as i32;
158 }
159 }
160 if let Some(d) = read(&attributes, "distB") {
161 if let Ok(d) = f64::from_str(&d) {
162 dist_b = d as i32;
163 }
164 }
165 if let Some(d) = read(&attributes, "distL") {
166 if let Ok(d) = f64::from_str(&d) {
167 dist_l = d as i32;
168 }
169 }
170 if let Some(d) = read(&attributes, "distR") {
171 if let Ok(d) = f64::from_str(&d) {
172 dist_r = d as i32;
173 }
174 }
175 if let Some(d) = read(&attributes, "layoutInCell") {
176 if is_false(&d) {
177 layout_in_cell = false;
178 }
179 }
180 if let Some(d) = read(&attributes, "relativeHeight") {
181 if let Ok(d) = f64::from_str(&d) {
182 relative_height = d as u32;
183 }
184 }
185 if let Some(d) = read(&attributes, "allowOverlap") {
186 if is_false(&d) {
187 allow_overlap = false;
188 }
189 }
190 }
191 WpXMLElement::Inline => {
192 drawing_position_type = DrawingPositionType::Inline;
193 if let Some(d) = read(&attributes, "distT") {
194 if let Ok(d) = f64::from_str(&d) {
195 dist_t = d as i32;
196 }
197 }
198 if let Some(d) = read(&attributes, "distB") {
199 if let Ok(d) = f64::from_str(&d) {
200 dist_b = d as i32;
201 }
202 }
203 if let Some(d) = read(&attributes, "distL") {
204 if let Ok(d) = f64::from_str(&d) {
205 dist_l = d as i32;
206 }
207 }
208 if let Some(d) = read(&attributes, "distR") {
209 if let Ok(d) = i32::from_str(&d) {
210 dist_r = d;
211 }
212 }
213 }
214 WpXMLElement::SimplePos => {
215 if let Some(x) = read(&attributes, "x") {
216 if let Ok(x) = f64::from_str(&x) {
217 simple_pos_x = x as i32;
218 }
219 }
220 if let Some(y) = read(&attributes, "y") {
221 if let Ok(y) = f64::from_str(&y) {
222 simple_pos_y = y as i32;
223 }
224 }
225 }
226 WpXMLElement::PositionH => {
227 if let Ok(p) = read_position_h(r, &attributes) {
228 relative_from_h = p.0;
229 position_h = p.1;
230 }
231 }
232 WpXMLElement::PositionV => {
233 if let Ok(p) = read_position_v(r, &attributes) {
234 relative_from_v = p.0;
235 position_v = p.1;
236 }
237 }
238 _ => {}
239 }
240 }
241 if let Ok(PicXMLElement::Pic) = PicXMLElement::from_str(&name.local_name) {
243 if let Ok(mut pic) = Pic::read(r, &attributes) {
244 pic.position_type = drawing_position_type;
245 pic.simple_pos = simple_pos;
246 pic.simple_pos_x = simple_pos_x;
247 pic.simple_pos_y = simple_pos_y;
248 pic.layout_in_cell = layout_in_cell;
249 pic.relative_height = relative_height;
250 pic.allow_overlap = allow_overlap;
251 pic.dist_r = dist_r;
252 pic.dist_t = dist_t;
253 pic.dist_b = dist_b;
254 pic.dist_l = dist_l;
255 pic.dist_r = dist_r;
256 pic.relative_from_h = relative_from_h;
257 pic.relative_from_v = relative_from_v;
258 pic.position_v = DrawingPosition::Offset(position_v);
259 pic.position_h = DrawingPosition::Offset(position_h);
260 drawing = drawing.pic(pic);
261 }
262 }
263
264 if let Ok(WpsXMLElement::Txbx) = WpsXMLElement::from_str(&name.local_name) {
266 if let Ok(children) = read_textbox_content(r, &attributes) {
267 let mut text_box = TextBox::new();
268 text_box.position_type = drawing_position_type;
269 text_box.simple_pos = simple_pos;
270 text_box.simple_pos_x = simple_pos_x;
271 text_box.simple_pos_y = simple_pos_y;
272 text_box.layout_in_cell = layout_in_cell;
273 text_box.relative_height = relative_height;
274 text_box.allow_overlap = allow_overlap;
275 text_box.dist_r = dist_r;
276 text_box.dist_t = dist_t;
277 text_box.dist_b = dist_b;
278 text_box.dist_l = dist_l;
279 text_box.dist_r = dist_r;
280 text_box.relative_from_h = relative_from_h;
281 text_box.relative_from_v = relative_from_v;
282 text_box.position_v = DrawingPosition::Offset(position_v);
283 text_box.position_h = DrawingPosition::Offset(position_h);
284 text_box.children = children;
285 drawing = drawing.text_box(text_box);
286 }
287 }
288 }
289 Ok(XmlEvent::EndElement { name, .. }) => {
290 let e = XMLElement::from_str(&name.local_name).unwrap();
291 if e == XMLElement::Drawing {
292 return Ok(drawing);
293 }
294 }
295 Err(_) => return Err(ReaderError::XMLReadError),
296 _ => {}
297 }
298 }
299 }
300}