use serde::Serialize;
use std::collections::HashMap;
#[derive(Debug, Clone, Default, PartialEq, Serialize)]
pub struct TextStyle {
pub bold: bool,
pub italic: bool,
pub underline: bool,
pub strikethrough: bool,
pub superscript: bool,
pub subscript: bool,
pub font_name: Option<String>,
pub font_size: Option<f32>,
pub color: Option<String>,
pub background_color: Option<String>,
}
impl TextStyle {
pub fn new() -> Self {
Self::default()
}
pub fn bold() -> Self {
Self {
bold: true,
..Default::default()
}
}
pub fn italic() -> Self {
Self {
italic: true,
..Default::default()
}
}
pub fn has_formatting(&self) -> bool {
self.bold
|| self.italic
|| self.underline
|| self.strikethrough
|| self.superscript
|| self.subscript
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize)]
pub struct ParagraphStyle {
pub heading_level: u8,
pub alignment: Alignment,
pub list_style: Option<ListStyle>,
pub indent_level: u8,
pub line_spacing: Option<f32>,
pub space_before: Option<f32>,
pub space_after: Option<f32>,
}
impl ParagraphStyle {
pub fn new() -> Self {
Self::default()
}
pub fn heading(level: u8) -> Self {
Self {
heading_level: level.min(6),
..Default::default()
}
}
pub fn is_heading(&self) -> bool {
self.heading_level > 0
}
pub fn is_list_item(&self) -> bool {
self.list_style.is_some()
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
pub enum Alignment {
#[default]
Left,
Center,
Right,
Justify,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub enum ListStyle {
Ordered,
Unordered,
CustomBullet(char),
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct NamedStyle {
pub name: String,
pub para_shape_id: u32,
pub char_shape_id: u32,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct StyleRegistry {
pub char_styles: HashMap<u32, TextStyle>,
pub para_styles: HashMap<u32, ParagraphStyle>,
pub named_styles: HashMap<String, u32>,
pub named_style_defs: HashMap<u32, NamedStyle>,
#[serde(skip)]
pub bindata_mapping: HashMap<u32, String>,
}
impl StyleRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register_char_style(&mut self, id: u32, style: TextStyle) {
self.char_styles.insert(id, style);
}
pub fn register_para_style(&mut self, id: u32, style: ParagraphStyle) {
self.para_styles.insert(id, style);
}
pub fn get_char_style(&self, id: u32) -> Option<&TextStyle> {
self.char_styles.get(&id)
}
pub fn get_para_style(&self, id: u32) -> Option<&ParagraphStyle> {
self.para_styles.get(&id)
}
pub fn register_bindata(&mut self, index: u32, filename: String) {
self.bindata_mapping.insert(index, filename);
}
pub fn get_bindata_filename(&self, index: u32) -> Option<&String> {
self.bindata_mapping.get(&index)
}
pub fn register_named_style(
&mut self,
id: u32,
name: String,
para_shape_id: u32,
char_shape_id: u32,
) {
if !name.is_empty() {
self.named_styles.insert(name.clone(), id);
}
self.named_style_defs.insert(
id,
NamedStyle {
name,
para_shape_id,
char_shape_id,
},
);
}
pub fn get_named_style_by_name(&self, name: &str) -> Option<&NamedStyle> {
self.named_styles
.get(name)
.and_then(|id| self.named_style_defs.get(id))
}
pub fn get_named_style(&self, id: u32) -> Option<&NamedStyle> {
self.named_style_defs.get(&id)
}
}