#![allow(clippy::single_match)] use std::io::Read; use std::str::FromStr; use xml::attribute::OwnedAttribute; use xml::reader::{EventReader, XmlEvent}; use crate::types::*; use crate::{DrawingPositionType, RelativeFromHType, RelativeFromVType}; use super::*; fn read_position_h( r: &mut EventReader, attrs: &[OwnedAttribute], ) -> Result<(RelativeFromHType, i32), ReaderError> { let mut offset: i32 = 0; let mut relative_from_h = RelativeFromHType::default(); loop { if let Some(h) = read(attrs, "relativeFrom") { if let Ok(h) = RelativeFromHType::from_str(&h) { relative_from_h = h; } } let e = r.next(); match e { Ok(XmlEvent::Characters(c)) => { if let Ok(p) = f64::from_str(&c) { offset = p as i32; } } Ok(XmlEvent::EndElement { name, .. }) => { let e = WpXMLElement::from_str(&name.local_name).unwrap(); if e == WpXMLElement::PositionH { return Ok((relative_from_h, offset)); } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } } fn read_position_v( r: &mut EventReader, attrs: &[OwnedAttribute], ) -> Result<(RelativeFromVType, i32), ReaderError> { let mut offset: i32 = 0; let mut relative_from_v = RelativeFromVType::default(); loop { if let Some(v) = read(attrs, "relativeFrom") { if let Ok(v) = RelativeFromVType::from_str(&v) { relative_from_v = v; } } let e = r.next(); match e { Ok(XmlEvent::Characters(c)) => { if let Ok(p) = f64::from_str(&c) { offset = p as i32; } } Ok(XmlEvent::EndElement { name, .. }) => { let e = WpXMLElement::from_str(&name.local_name).unwrap(); if e == WpXMLElement::PositionV { return Ok((relative_from_v, offset)); } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } } fn read_textbox_content( r: &mut EventReader, _attrs: &[OwnedAttribute], ) -> Result, ReaderError> { let mut children = vec![]; loop { let e = r.next(); match e { Ok(XmlEvent::StartElement { attributes, name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); match e { XMLElement::Paragraph => { let p = Paragraph::read(r, &attributes)?; children.push(TextBoxContentChild::Paragraph(Box::new(p))); continue; } XMLElement::Table => { let t = Table::read(r, &attributes)?; children.push(TextBoxContentChild::Table(Box::new(t))); continue; } _ => {} } } Ok(XmlEvent::EndElement { name, .. }) => { let e = WpsXMLElement::from_str(&name.local_name).unwrap(); if e == WpsXMLElement::Txbx { return Ok(children); } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } } impl ElementReader for Drawing { fn read( r: &mut EventReader, _attrs: &[OwnedAttribute], ) -> Result { let mut drawing = Drawing::new(); let mut drawing_position_type = DrawingPositionType::Inline; let mut simple_pos = false; let mut simple_pos_x = 0; let mut simple_pos_y = 0; let mut layout_in_cell = true; let mut relative_height = 0; let mut position_h = 0; let mut position_v = 0; let mut relative_from_h = RelativeFromHType::default(); let mut relative_from_v = RelativeFromVType::default(); let mut allow_overlap = true; let mut dist_t = 0; let mut dist_b = 0; let mut dist_l = 0; let mut dist_r = 0; loop { let e = r.next(); match e { Ok(XmlEvent::StartElement { name, attributes, .. }) => { // wp: if let Ok(wpe) = WpXMLElement::from_str(&name.local_name) { match wpe { WpXMLElement::Anchor => { drawing_position_type = DrawingPositionType::Anchor; if let Some(v) = read(&attributes, "simplePos") { if !is_false(&v) { simple_pos = true; } } if let Some(d) = read(&attributes, "distT") { if let Ok(d) = f64::from_str(&d) { dist_t = d as i32; } } if let Some(d) = read(&attributes, "distB") { if let Ok(d) = f64::from_str(&d) { dist_b = d as i32; } } if let Some(d) = read(&attributes, "distL") { if let Ok(d) = f64::from_str(&d) { dist_l = d as i32; } } if let Some(d) = read(&attributes, "distR") { if let Ok(d) = f64::from_str(&d) { dist_r = d as i32; } } if let Some(d) = read(&attributes, "layoutInCell") { if is_false(&d) { layout_in_cell = false; } } if let Some(d) = read(&attributes, "relativeHeight") { if let Ok(d) = f64::from_str(&d) { relative_height = d as u32; } } if let Some(d) = read(&attributes, "allowOverlap") { if is_false(&d) { allow_overlap = false; } } } WpXMLElement::Inline => { drawing_position_type = DrawingPositionType::Inline; if let Some(d) = read(&attributes, "distT") { if let Ok(d) = f64::from_str(&d) { dist_t = d as i32; } } if let Some(d) = read(&attributes, "distB") { if let Ok(d) = f64::from_str(&d) { dist_b = d as i32; } } if let Some(d) = read(&attributes, "distL") { if let Ok(d) = f64::from_str(&d) { dist_l = d as i32; } } if let Some(d) = read(&attributes, "distR") { if let Ok(d) = i32::from_str(&d) { dist_r = d; } } } WpXMLElement::SimplePos => { if let Some(x) = read(&attributes, "x") { if let Ok(x) = f64::from_str(&x) { simple_pos_x = x as i32; } } if let Some(y) = read(&attributes, "y") { if let Ok(y) = f64::from_str(&y) { simple_pos_y = y as i32; } } } WpXMLElement::PositionH => { if let Ok(p) = read_position_h(r, &attributes) { relative_from_h = p.0; position_h = p.1; } } WpXMLElement::PositionV => { if let Ok(p) = read_position_v(r, &attributes) { relative_from_v = p.0; position_v = p.1; } } _ => {} } } // pic: if let Ok(PicXMLElement::Pic) = PicXMLElement::from_str(&name.local_name) { if let Ok(mut pic) = Pic::read(r, &attributes) { pic.position_type = drawing_position_type; pic.simple_pos = simple_pos; pic.simple_pos_x = simple_pos_x; pic.simple_pos_y = simple_pos_y; pic.layout_in_cell = layout_in_cell; pic.relative_height = relative_height; pic.allow_overlap = allow_overlap; pic.dist_r = dist_r; pic.dist_t = dist_t; pic.dist_b = dist_b; pic.dist_l = dist_l; pic.dist_r = dist_r; pic.relative_from_h = relative_from_h; pic.relative_from_v = relative_from_v; pic.position_v = DrawingPosition::Offset(position_v); pic.position_h = DrawingPosition::Offset(position_h); drawing = drawing.pic(pic); } } // wps: if let Ok(WpsXMLElement::Txbx) = WpsXMLElement::from_str(&name.local_name) { if let Ok(children) = read_textbox_content(r, &attributes) { let mut text_box = TextBox::new(); text_box.position_type = drawing_position_type; text_box.simple_pos = simple_pos; text_box.simple_pos_x = simple_pos_x; text_box.simple_pos_y = simple_pos_y; text_box.layout_in_cell = layout_in_cell; text_box.relative_height = relative_height; text_box.allow_overlap = allow_overlap; text_box.dist_r = dist_r; text_box.dist_t = dist_t; text_box.dist_b = dist_b; text_box.dist_l = dist_l; text_box.dist_r = dist_r; text_box.relative_from_h = relative_from_h; text_box.relative_from_v = relative_from_v; text_box.position_v = DrawingPosition::Offset(position_v); text_box.position_h = DrawingPosition::Offset(position_h); text_box.children = children; drawing = drawing.text_box(text_box); } } } Ok(XmlEvent::EndElement { name, .. }) => { let e = XMLElement::from_str(&name.local_name).unwrap(); if e == XMLElement::Drawing { return Ok(drawing); } } Err(_) => return Err(ReaderError::XMLReadError), _ => {} } } } }