use hwpforge_foundation::{
Alignment, CharShapeIndex, Color, HwpUnit, ParaShapeIndex, StyleIndex, UnderlineType,
};
pub trait StyleLookup {
fn char_bold(&self, _id: CharShapeIndex) -> Option<bool> {
None
}
fn char_italic(&self, _id: CharShapeIndex) -> Option<bool> {
None
}
fn char_underline(&self, _id: CharShapeIndex) -> Option<UnderlineType> {
None
}
fn char_strikeout(&self, _id: CharShapeIndex) -> Option<bool> {
None
}
fn char_superscript(&self, _id: CharShapeIndex) -> Option<bool> {
None
}
fn char_subscript(&self, _id: CharShapeIndex) -> Option<bool> {
None
}
fn char_font_name(&self, _id: CharShapeIndex) -> Option<&str> {
None
}
fn char_font_axis_names(&self, id: CharShapeIndex) -> Vec<&str> {
self.char_font_name(id).into_iter().collect()
}
fn char_font_size(&self, _id: CharShapeIndex) -> Option<HwpUnit> {
None
}
fn char_text_color(&self, _id: CharShapeIndex) -> Option<Color> {
None
}
fn para_alignment(&self, _id: ParaShapeIndex) -> Option<Alignment> {
None
}
fn para_indent_left(&self, _id: ParaShapeIndex) -> Option<HwpUnit> {
None
}
fn para_indent_first_line(&self, _id: ParaShapeIndex) -> Option<HwpUnit> {
None
}
fn para_list_type(&self, _id: ParaShapeIndex) -> Option<&str> {
None
}
fn para_list_level(&self, _id: ParaShapeIndex) -> Option<u8> {
None
}
fn para_checked_state(&self, _id: ParaShapeIndex) -> Option<bool> {
None
}
fn para_style_name(&self, _id: ParaShapeIndex) -> Option<&str> {
None
}
fn para_heading_level(&self, _id: ParaShapeIndex) -> Option<u8> {
None
}
fn style_name(&self, _id: StyleIndex) -> Option<&str> {
None
}
fn style_heading_level(&self, _id: StyleIndex) -> Option<u8> {
None
}
fn image_resolve_filename(&self, _key: &str) -> Option<&str> {
None
}
fn image_data(&self, _key: &str) -> Option<&[u8]> {
None
}
fn border_fill_lines(&self, _id: u32) -> Option<BorderFillLines> {
None
}
fn border_fill_face(&self, _id: u32) -> Option<FillKind> {
None
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BorderLineKind {
None,
Solid,
Other,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub struct BorderLine {
pub kind: BorderLineKind,
pub width: HwpUnit,
pub color: Color,
}
impl BorderLine {
#[must_use]
pub fn new(kind: BorderLineKind, width: HwpUnit, color: Color) -> Self {
Self { kind, width, color }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub struct BorderFillLines {
pub left: BorderLine,
pub right: BorderLine,
pub top: BorderLine,
pub bottom: BorderLine,
}
impl BorderFillLines {
#[must_use]
pub fn new(left: BorderLine, right: BorderLine, top: BorderLine, bottom: BorderLine) -> Self {
Self { left, right, top, bottom }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum FillKind {
None,
Solid(Color),
Unsupported,
}
#[cfg(test)]
mod tests {
use super::*;
use hwpforge_foundation::{ParaShapeIndex, StyleIndex};
struct NoopStore;
impl StyleLookup for NoopStore {}
#[test]
fn noop_store_returns_none_for_all_methods() {
let store = NoopStore;
let cs = CharShapeIndex::new(0);
let ps = ParaShapeIndex::new(0);
let si = StyleIndex::new(0);
assert!(store.char_bold(cs).is_none());
assert!(store.char_italic(cs).is_none());
assert!(store.char_underline(cs).is_none());
assert!(store.char_strikeout(cs).is_none());
assert!(store.char_superscript(cs).is_none());
assert!(store.char_subscript(cs).is_none());
assert!(store.char_font_name(cs).is_none());
assert!(store.char_font_size(cs).is_none());
assert!(store.char_text_color(cs).is_none());
assert!(store.para_alignment(ps).is_none());
assert!(store.para_indent_left(ps).is_none());
assert!(store.para_indent_first_line(ps).is_none());
assert!(store.para_list_type(ps).is_none());
assert!(store.para_list_level(ps).is_none());
assert!(store.para_checked_state(ps).is_none());
assert!(store.para_style_name(ps).is_none());
assert!(store.para_heading_level(ps).is_none());
assert!(store.style_name(si).is_none());
assert!(store.style_heading_level(si).is_none());
assert!(store.image_data("image1.jpg").is_none());
assert!(store.border_fill_lines(1).is_none());
assert!(store.border_fill_face(1).is_none());
}
#[test]
fn partial_impl_returns_some_for_overridden_methods() {
struct BoldOnly;
impl StyleLookup for BoldOnly {
fn char_bold(&self, _id: CharShapeIndex) -> Option<bool> {
Some(true)
}
}
let store = BoldOnly;
assert_eq!(store.char_bold(CharShapeIndex::new(0)), Some(true));
assert!(store.char_italic(CharShapeIndex::new(0)).is_none());
}
#[test]
fn trait_object_works() {
let store: &dyn StyleLookup = &NoopStore;
assert!(store.char_bold(CharShapeIndex::new(0)).is_none());
}
#[test]
fn default_axis_names_mirror_single_font_name() {
let cs = CharShapeIndex::new(0);
assert!(NoopStore.char_font_axis_names(cs).is_empty());
struct OneFont;
impl StyleLookup for OneFont {
fn char_font_name(&self, _id: CharShapeIndex) -> Option<&str> {
Some("함초롬바탕")
}
}
assert_eq!(OneFont.char_font_axis_names(cs), vec!["함초롬바탕"]);
}
}