use std::fmt::Write;
use crate::basic_type::{ST_Box, ST_RefID};
#[derive(Debug, Clone)]
pub struct StampAnnot {
pub id: String,
pub page_ref: ST_RefID,
pub boundary: ST_Box,
pub clip: Option<ST_Box>,
}
impl StampAnnot {
#[must_use]
pub fn new(id: impl Into<String>, page_ref: ST_RefID, boundary: ST_Box) -> Self {
Self {
id: id.into(),
page_ref,
boundary,
clip: None,
}
}
#[must_use]
pub fn clip(mut self, clip: ST_Box) -> Self {
self.clip = Some(clip);
self
}
#[must_use]
pub fn to_xml_string(&self) -> String {
let mut xml = format!(
r#"<ofd:StampAnnot ID="{}" PageRef="{}" Boundary="{}""#,
self.id,
self.page_ref.to_xml_string(),
self.boundary.to_xml_string()
);
if let Some(ref clip) = self.clip {
let _ = write!(xml, r#" Clip="{}""#, clip.to_xml_string());
}
xml.push_str(" />");
xml
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stamp_annot_new() {
let sa = StampAnnot::new("s1", ST_RefID::new(1), ST_Box::new(10.0, 20.0, 50.0, 80.0));
assert_eq!(sa.id, "s1");
assert_eq!(sa.page_ref.to_xml_string(), "1");
assert!(sa.clip.is_none());
}
#[test]
fn test_stamp_annot_with_clip() {
let sa = StampAnnot::new("s2", ST_RefID::new(3), ST_Box::new(0.0, 0.0, 100.0, 100.0))
.clip(ST_Box::new(5.0, 5.0, 90.0, 90.0));
assert!(sa.clip.is_some());
let clip = sa.clip.unwrap();
assert!((clip.top_left_x - 5.0).abs() < f64::EPSILON);
}
#[test]
fn test_stamp_annot_xml_without_clip() {
let sa = StampAnnot::new("s1", ST_RefID::new(1), ST_Box::new(10.0, 20.0, 50.0, 80.0));
let xml = sa.to_xml_string();
assert!(xml.contains(r#"ID="s1""#));
assert!(xml.contains("PageRef=\"1\""));
assert!(xml.contains("Boundary=\"10 20 50 80\""));
assert!(!xml.contains("Clip"));
assert!(xml.contains("/>"));
}
#[test]
fn test_stamp_annot_xml_with_clip() {
let sa = StampAnnot::new("s3", ST_RefID::new(2), ST_Box::new(0.0, 0.0, 200.0, 200.0))
.clip(ST_Box::new(10.0, 10.0, 180.0, 180.0));
let xml = sa.to_xml_string();
assert!(xml.contains(r#"ID="s3""#));
assert!(xml.contains("Clip=\"10 10 180 180\""));
}
}