docx_reader/reader/
drawing.rs

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