use anyhow::bail;
use quick_xml::events::{BytesStart, Event};
use std::io::Read;
use crate::excel::XmlReader;
use crate::helper::{string_to_bool, string_to_int, string_to_unsignedint};
use crate::raw::drawing::st_types::{STPercentage, STPositiveTextPoint, STTextPoint};
use crate::raw::drawing::{
effect::{effect_container::XlsxEffectDag, effect_list::XlsxEffectList},
fill::{
blip_fill::XlsxBlipFill, gradient_fill::XlsxGradientFill, group_fill::XlsxGroupFill,
no_fill::XlsxNoFill, pattern_fill::XlsxPatternFill, solid_fill::XlsxSolidFill,
},
line::outline::XlsxOutline,
};
use super::{
font::{
complex_sript_font::XlsxComplexScriptFont, east_asian_font::XlsxEastAsianFont,
latin_font::XlsxLatinFont,
},
highlight_color::XlsxHighlightColor,
hyperlink_on_event::{XlsxHyperlinkOnClick, XlsxHyperlinkOnMouseOver},
right_to_left::XlsxRightToLeft,
symbol_font::XlsxSymbolFont,
underline::XlsxUnderline,
underline_fill::XlsxUnderlineFill,
underline_fill_text::XlsxUnderlineFillText,
underline_follow_text::XlsxUnderlineFollowsText,
};
pub type XlsxTextRunProperties = XlsxDefaultTextRunProperties;
pub(crate) fn load_text_run_properties(
reader: &mut XmlReader<impl Read>,
e: &BytesStart,
) -> anyhow::Result<XlsxTextRunProperties> {
return XlsxTextRunProperties::load_helper(reader, e, b"rPr");
}
pub type XlsxEndParagraphRunProperties = XlsxDefaultTextRunProperties;
pub(crate) fn load_end_paragraph_run_properties(
reader: &mut XmlReader<impl Read>,
e: &BytesStart,
) -> anyhow::Result<XlsxEndParagraphRunProperties> {
return XlsxEndParagraphRunProperties::load_helper(reader, e, b"endParaRPr");
}
#[derive(Debug, Clone, PartialEq)]
pub struct XlsxDefaultTextRunProperties {
pub blip_fill: Option<XlsxBlipFill>,
pub cs: Option<XlsxComplexScriptFont>,
pub ea: Option<XlsxEastAsianFont>,
pub effect_dag: Option<XlsxEffectDag>,
pub effect_list: Option<XlsxEffectList>,
pub gradient_fill: Option<XlsxGradientFill>,
pub group_fill: Option<XlsxGroupFill>,
pub highlight: Option<XlsxHighlightColor>,
pub hlink_click: Option<XlsxHyperlinkOnClick>,
pub hlink_mouse_over: Option<XlsxHyperlinkOnMouseOver>,
pub latin: Option<XlsxLatinFont>,
pub outline: Option<XlsxOutline>,
pub no_fill: Option<XlsxNoFill>,
pub pattern_fill: Option<XlsxPatternFill>,
pub rtl: Option<XlsxRightToLeft>,
pub solid_fill: Option<XlsxSolidFill>,
pub symbol_font: Option<XlsxSymbolFont>,
pub underline_fill: Option<XlsxUnderlineFill>,
pub underline_fill_text: Option<XlsxUnderlineFillText>,
pub underline_stroke: Option<XlsxUnderline>,
pub underline_follow_text: Option<XlsxUnderlineFollowsText>,
pub alternative_language: Option<String>,
pub baseline: Option<STPercentage>,
pub bold: Option<bool>,
pub bookmark: Option<String>,
pub capital: Option<String>,
pub dirty: Option<bool>,
pub font_size: Option<STPositiveTextPoint>,
pub italic: Option<bool>,
pub kerning: Option<STPositiveTextPoint>,
pub kumimoji: Option<bool>,
pub language: Option<String>,
pub no_proof: Option<bool>,
pub normalize_height: Option<bool>,
pub smart_tag_clean: Option<bool>,
pub smart_tag_id: Option<u64>,
pub spacing: Option<STTextPoint>,
pub spelling_error: Option<bool>,
pub strike: Option<String>,
pub underline: Option<String>,
}
impl XlsxDefaultTextRunProperties {
pub(crate) fn load(reader: &mut XmlReader<impl Read>, e: &BytesStart) -> anyhow::Result<Self> {
return Self::load_helper(reader, e, b"defRPr");
}
fn load_helper(
reader: &mut XmlReader<impl Read>,
e: &BytesStart,
tag: &[u8],
) -> anyhow::Result<Self> {
let mut buf = Vec::new();
let mut properties = Self {
blip_fill: None,
cs: None,
ea: None,
effect_dag: None,
effect_list: None,
gradient_fill: None,
group_fill: None,
highlight: None,
hlink_click: None,
hlink_mouse_over: None,
latin: None,
outline: None,
no_fill: None,
pattern_fill: None,
rtl: None,
solid_fill: None,
symbol_font: None,
underline_fill: None,
underline_fill_text: None,
underline_stroke: None,
underline_follow_text: None,
alternative_language: None,
baseline: None,
bold: None,
bookmark: None,
capital: None,
dirty: None,
font_size: None,
italic: None,
kerning: None,
kumimoji: None,
language: None,
no_proof: None,
normalize_height: None,
smart_tag_clean: None,
smart_tag_id: None,
spacing: None,
spelling_error: None,
strike: None,
underline: None,
};
for a in e.attributes() {
match a {
Ok(a) => {
let string_value = String::from_utf8(a.value.to_vec())?;
match a.key.local_name().as_ref() {
b"altLang" => {
properties.alternative_language = Some(string_value);
}
b"baseline" => {
properties.baseline = string_to_int(&string_value);
}
b"b" => {
properties.bold = string_to_bool(&string_value);
}
b"bmk" => {
properties.bookmark = Some(string_value);
}
b"cap" => {
properties.capital = Some(string_value);
}
b"dirty" => {
properties.dirty = string_to_bool(&string_value);
}
b"sz" => {
properties.font_size = string_to_unsignedint(&string_value);
}
b"i" => {
properties.italic = string_to_bool(&string_value);
}
b"kern" => {
properties.kerning = string_to_unsignedint(&string_value);
}
b"kumimoji" => {
properties.kumimoji = string_to_bool(&string_value);
}
b"lang" => {
properties.language = Some(string_value);
}
b"noProof" => {
properties.no_proof = string_to_bool(&string_value);
}
b"normalizeH" => {
properties.normalize_height = string_to_bool(&string_value);
}
b"smtClean" => {
properties.smart_tag_clean = string_to_bool(&string_value);
}
b"smtId" => {
properties.smart_tag_id = string_to_unsignedint(&string_value);
}
b"spc" => {
properties.spacing = string_to_unsignedint(&string_value);
}
b"err" => {
properties.spelling_error = string_to_bool(&string_value);
}
b"strike" => {
properties.strike = Some(string_value);
}
b"u" => {
properties.underline = Some(string_value);
}
_ => {}
}
}
Err(error) => {
bail!(error.to_string())
}
}
}
loop {
buf.clear();
match reader.read_event_into(&mut buf) {
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"extLst" => {
let _ = reader.read_to_end_into(e.to_end().to_owned().name(), &mut Vec::new());
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"blipFill" => {
properties.blip_fill = Some(XlsxBlipFill::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"cs" => {
properties.cs = Some(XlsxComplexScriptFont::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"ea" => {
properties.ea = Some(XlsxEastAsianFont::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"effectDag" => {
properties.effect_dag = Some(XlsxEffectDag::load_effect_dag(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"effectLst" => {
properties.effect_list = Some(XlsxEffectList::load(reader)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"gradFill" => {
properties.gradient_fill = Some(XlsxGradientFill::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"grpFill" => {
properties.group_fill = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"highlight" => {
properties.highlight = XlsxHighlightColor::load(reader, e)?;
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"hlinkClick" => {
properties.hlink_click = Some(XlsxHyperlinkOnClick::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"hlinkMouseOver" => {
properties.hlink_mouse_over = Some(XlsxHyperlinkOnMouseOver::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"latin" => {
properties.latin = Some(XlsxLatinFont::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"ln" => {
properties.outline = Some(XlsxOutline::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"noFill" => {
properties.no_fill = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"pattFill" => {
properties.pattern_fill = Some(XlsxPatternFill::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"rtl" => {
properties.rtl = Some(XlsxRightToLeft::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"solidFill" => {
properties.solid_fill = XlsxSolidFill::load(reader, b"solidFill")?;
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"sym" => {
properties.symbol_font = Some(XlsxSymbolFont::load(e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"uFill" => {
properties.underline_fill = XlsxUnderlineFill::load(reader, b"uFill")?;
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"uFillTx" => {
properties.underline_fill_text = Some(true);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"uLn" => {
properties.underline_stroke = Some(XlsxUnderline::load(reader, e)?);
}
Ok(Event::Start(ref e)) if e.local_name().as_ref() == b"uLnTx" => {
properties.underline_follow_text = Some(true);
}
Ok(Event::End(ref e)) if e.local_name().as_ref() == tag => break,
Ok(Event::Eof) => bail!("unexpected end of file."),
Err(e) => bail!(e.to_string()),
_ => (),
}
}
Ok(properties)
}
}