use crate::ir::{BorderLineStyle, BorderSide, CellBorder, Color, TextStyle};
use crate::parser::xml_util::parse_argb_color;
pub(super) fn border_style_to_width(style: &str) -> Option<f64> {
match style {
"hair" => Some(0.25),
"thin" | "dashed" | "dotted" | "dashDot" | "dashDotDot" => Some(0.5),
"medium" | "mediumDashed" | "mediumDashDot" | "mediumDashDotDot" | "double"
| "slantDashDot" => Some(1.0),
"thick" => Some(2.0),
_ => None, }
}
pub(super) fn extract_cell_text_style(cell: &umya_spreadsheet::Cell) -> TextStyle {
let style = cell.get_style();
let Some(font) = style.get_font() else {
return TextStyle::default();
};
let bold = if *font.get_bold() { Some(true) } else { None };
let italic = if *font.get_italic() { Some(true) } else { None };
let underline = match font.get_font_underline().get_val() {
umya_spreadsheet::UnderlineValues::None => None,
_ => Some(true),
};
let strikethrough = if *font.get_strikethrough() {
Some(true)
} else {
None
};
let font_name = font.get_name();
let font_family = if font_name.is_empty() || font_name == "Calibri" {
None
} else {
Some(font_name.to_string())
};
let raw_size = *font.get_size();
let font_size = if (raw_size - 11.0).abs() < 0.01 {
None
} else {
Some(raw_size)
};
let color_argb = font.get_color().get_argb();
let color = if color_argb.is_empty() || color_argb == "FF000000" {
None
} else {
parse_argb_color(color_argb)
};
TextStyle {
font_family,
font_size,
bold,
italic,
underline,
strikethrough,
color,
highlight: None,
vertical_align: None,
all_caps: None,
small_caps: None,
letter_spacing: None,
}
}
pub(super) fn apply_rich_run_font(base: &TextStyle, font: &umya_spreadsheet::Font) -> TextStyle {
let mut style = base.clone();
let font_name: &str = font.get_name();
if !font_name.is_empty() && font_name != "Calibri" {
style.font_family = Some(font_name.to_string());
}
let raw_size: f64 = *font.get_size();
if raw_size > 0.0 {
style.font_size = Some(raw_size);
}
if *font.get_bold() {
style.bold = Some(true);
}
if *font.get_italic() {
style.italic = Some(true);
}
if !matches!(
font.get_font_underline().get_val(),
umya_spreadsheet::UnderlineValues::None
) {
style.underline = Some(true);
}
if *font.get_strikethrough() {
style.strikethrough = Some(true);
}
let color_argb: &str = font.get_color().get_argb();
if !color_argb.is_empty()
&& let Some(color) = parse_argb_color(color_argb)
{
style.color = Some(color);
}
style
}
pub(super) fn extract_cell_background(cell: &umya_spreadsheet::Cell) -> Option<Color> {
let bg = cell.get_style().get_background_color()?;
parse_argb_color(bg.get_argb())
}
pub(super) fn border_style_to_line_style(style: &str) -> BorderLineStyle {
match style {
"dashed" | "mediumDashed" => BorderLineStyle::Dashed,
"dotted" => BorderLineStyle::Dotted,
"dashDot" | "mediumDashDot" | "slantDashDot" => BorderLineStyle::DashDot,
"dashDotDot" | "mediumDashDotDot" => BorderLineStyle::DashDotDot,
"double" => BorderLineStyle::Double,
_ => BorderLineStyle::Solid,
}
}
pub(super) fn extract_border_side(border: &umya_spreadsheet::Border) -> Option<BorderSide> {
let border_style_str = border.get_border_style();
let width = border_style_to_width(border_style_str)?;
let color = parse_argb_color(border.get_color().get_argb()).unwrap_or(Color::black());
let style = border_style_to_line_style(border_style_str);
Some(BorderSide {
width,
color,
style,
})
}
pub(super) fn extract_cell_borders(cell: &umya_spreadsheet::Cell) -> Option<CellBorder> {
let borders = cell.get_style().get_borders()?;
let top = extract_border_side(borders.get_top());
let bottom = extract_border_side(borders.get_bottom());
let left = extract_border_side(borders.get_left());
let right = extract_border_side(borders.get_right());
if top.is_none() && bottom.is_none() && left.is_none() && right.is_none() {
return None;
}
Some(CellBorder {
top,
bottom,
left,
right,
})
}
pub(super) fn extract_cell_alignment(
cell: &umya_spreadsheet::Cell,
) -> (
Option<crate::ir::Alignment>,
Option<crate::ir::CellVerticalAlign>,
) {
let Some(alignment) = cell.get_style().get_alignment() else {
return (None, None);
};
use umya_spreadsheet::{HorizontalAlignmentValues as H, VerticalAlignmentValues as V};
let horizontal = match alignment.get_horizontal() {
H::Center | H::CenterContinuous => Some(crate::ir::Alignment::Center),
H::Right => Some(crate::ir::Alignment::Right),
H::Left => Some(crate::ir::Alignment::Left),
H::Justify => Some(crate::ir::Alignment::Justify),
_ => None,
};
let vertical = match alignment.get_vertical() {
V::Center => Some(crate::ir::CellVerticalAlign::Center),
V::Top => Some(crate::ir::CellVerticalAlign::Top),
_ => None,
};
(horizontal, vertical)
}