docx_rs/reader/
run_property.rs1use std::io::Read;
2use std::str::FromStr;
3
4use crate::{ThemeColor, VertAlignType};
5
6use super::*;
7
8fn read_color(rp: RunProperty, attributes: &[OwnedAttribute]) -> RunProperty {
15 let val = read(attributes, "val").unwrap_or_else(|| "auto".to_string());
16 let mut rp = rp.color(val);
17 if let Some(tc) = read(attributes, "themeColor") {
18 if let Ok(theme) = ThemeColor::from_str(&tc) {
19 rp = rp.theme_color(theme);
20 }
21 }
22 if let Some(ts) = read(attributes, "themeShade") {
23 rp = rp.theme_shade(ts);
24 }
25 if let Some(tt) = read(attributes, "themeTint") {
26 rp = rp.theme_tint(tt);
27 }
28 rp
29}
30
31fn read_run_fonts(attributes: &[OwnedAttribute]) -> Result<RunFonts, ReaderError> {
32 let mut f = RunFonts::new();
33 for a in attributes {
34 let local_name = &a.name.local_name;
35 match local_name.as_str() {
36 "asciiTheme" => {
37 f = f.ascii_theme(&a.value);
38 }
39 "eastAsiaTheme" => {
40 f = f.east_asia_theme(&a.value);
41 }
42 "hAnsiTheme" => {
43 f = f.hi_ansi_theme(&a.value);
44 }
45 "cstheme" => {
46 f = f.cs_theme(&a.value);
47 }
48 "ascii" => {
49 f = f.ascii(&a.value);
50 }
51 "eastAsia" => {
52 f = f.east_asia(&a.value);
53 }
54 "hAnsi" => {
55 f = f.hi_ansi(&a.value);
56 }
57 "cs" => {
58 f = f.cs(&a.value);
59 }
60 "hint" => {
61 f = f.hint(&a.value);
62 }
63 _ => {}
64 }
65 }
66 Ok(f)
67}
68
69impl ElementReader for RunProperty {
70 fn read<R: Read>(
71 r: &mut EventReader<R>,
72 _attrs: &[OwnedAttribute],
73 ) -> Result<Self, ReaderError> {
74 let mut rp = RunProperty::new();
75 loop {
76 let e = r.next_event();
77 match e {
78 Ok(XmlEvent::StartElement {
79 attributes, name, ..
80 }) => {
81 let e = XMLElement::from_str(&name.local_name).unwrap();
82
83 ignore::ignore_element(e.clone(), XMLElement::RunPropertyChange, r);
84
85 match e {
86 XMLElement::RunStyle => {
87 if let Some(v) = read_val(&attributes) {
88 rp = rp.style(&v);
89 }
90 }
91 XMLElement::Bold => {
92 if !read_bool(&attributes) {
93 rp = rp.disable_bold();
94 continue;
95 }
96 rp = rp.bold();
97 }
98 XMLElement::Caps => {
99 if !read_bool(&attributes) {
100 rp.caps = Some(Caps::new().disable());
101 continue;
102 }
103 rp = rp.caps();
104 }
105 XMLElement::PTab => {
106 if let Ok(v) = PositionalTab::read(r, &attributes) {
107 rp = rp.ptab(v)
108 }
109 }
110 XMLElement::Highlight => rp = rp.highlight(attributes[0].value.clone()),
111 XMLElement::Strike => {
112 if !read_bool(&attributes) {
113 rp.strike = Some(Strike::new().disable());
114 continue;
115 }
116 rp = rp.strike();
117 }
118 XMLElement::Dstrike => {
119 if !read_bool(&attributes) {
120 rp.dstrike = Some(Dstrike::new().disable());
121 continue;
122 }
123 rp = rp.dstrike();
124 }
125 XMLElement::VertAlign => {
126 if let Ok(v) = VertAlignType::from_str(&attributes[0].value) {
127 rp = rp.vert_align(v)
128 }
129 }
130 XMLElement::Color => rp = read_color(rp, &attributes),
131 XMLElement::Size => {
132 rp = rp.size(f64::from_str(&attributes[0].value)? as usize)
133 }
134 XMLElement::Spacing => {
135 if let Some(v) = read_val(&attributes) {
136 if let Ok(s) = f64::from_str(&v) {
137 rp = rp.spacing(s as i32)
138 }
139 }
140 }
141 XMLElement::FitText => {
142 if let Some(v) = read_val(&attributes) {
143 if let Ok(val) = usize::from_str(&v) {
144 let id = read(&attributes, "id")
145 .and_then(|id| u32::from_str(&id).ok());
146 rp = rp.fit_text(val, id);
147 }
148 }
149 }
150 XMLElement::RunFonts => {
151 if let Ok(f) = read_run_fonts(&attributes) {
152 rp = rp.fonts(f);
153 }
154 }
155 XMLElement::Underline => rp = rp.underline(attributes[0].value.clone()),
156 XMLElement::Italic => {
157 if !read_bool(&attributes) {
158 rp = rp.disable_italic();
159 continue;
160 }
161 rp = rp.italic();
162 }
163 XMLElement::Shading => {
164 if let Ok(shd) = Shading::read(r, &attributes) {
165 rp = rp.shading(shd);
166 }
167 }
168 XMLElement::Vanish => rp = rp.vanish(),
169 XMLElement::SpecVanish => rp = rp.spec_vanish(),
170 XMLElement::TextBorder => {
171 if let Ok(attr) = read_border(&attributes) {
172 let mut border = TextBorder::new()
173 .border_type(attr.border_type)
174 .color(attr.color);
175 if let Some(size) = attr.size {
176 border = border.size(size as usize);
177 };
178 rp = rp.text_border(border);
179 continue;
180 }
181 }
182 XMLElement::Insert => {
183 if let Ok(ins) = Insert::read(r, &attributes) {
184 rp = rp.insert(ins);
185 }
186 }
187 XMLElement::Delete => {
188 if let Ok(del) = Delete::read(r, &attributes) {
189 rp = rp.delete(del);
190 }
191 }
192 _ => {}
193 }
194 }
195 Ok(XmlEvent::EndElement { name, .. }) => {
196 let e = XMLElement::from_str(&name.local_name).unwrap();
197 if e == XMLElement::RunProperty {
198 return Ok(rp);
199 }
200 }
201 Err(_) => return Err(ReaderError::XMLReadError),
202 _ => {}
203 }
204 }
205 }
206}