//! The document default font size (`w:docDefaults/w:rPrDefault/w:rPr/w:sz`) across a save and //! reopen. An unset default is resolved as `DEFAULT_FONT_SIZE`; the writer must say so, because //! the reader reads an omitted size as 10 pt. use craft_wordmodel::Document; use craft_wordmodel::props::{CharProps, DEFAULT_FONT_SIZE}; use std::io::{Read, Write}; use std::sync::Arc; fn resolved(d: &Document) -> f32 { d.styles.resolve_char(None, &CharProps::default()).size } fn styles_xml(bytes: &[u8]) -> String { let mut archive = zip::ZipArchive::new(std::io::Cursor::new(bytes)).unwrap(); let mut xml = String::new(); archive.by_name("word/styles.xml").unwrap().read_to_string(&mut xml).unwrap(); xml } fn defaults(xml: &str) -> &str { xml.split("").nth(1).unwrap().split("").next().unwrap() } #[test] fn an_unset_default_size_keeps_its_effective_size_across_save_and_reopen() { let mut d = Document::new(); Arc::make_mut(&mut d.styles).default_chr.size = None; assert_eq!(resolved(&d), DEFAULT_FONT_SIZE); let bytes = craft_docx::write(&d).unwrap(); assert!(defaults(&styles_xml(&bytes)).contains(r#""#)); let reopened = craft_docx::read(&bytes).unwrap(); assert_eq!(resolved(&reopened), DEFAULT_FONT_SIZE); // Saving again changes nothing further. let again = craft_docx::read(&craft_docx::write(&reopened).unwrap()).unwrap(); assert_eq!(resolved(&again), DEFAULT_FONT_SIZE); } #[test] fn an_explicit_default_size_is_written_as_it_is() { for size in [8.0, 10.0, 11.0, 12.5, 18.0] { let mut d = Document::new(); Arc::make_mut(&mut d.styles).default_chr.size = Some(size); let bytes = craft_docx::write(&d).unwrap(); assert_eq!(resolved(&craft_docx::read(&bytes).unwrap()), size); } } #[test] fn a_file_that_omits_the_default_size_is_still_read_as_ten_points() { // The reader is unchanged: only what WordCraft writes differs. A package without a size // anywhere keeps its established reading. let root = r#""#; let doc = r#"x"#; let styles = r#""#; let rels = r#""#; let mut zw = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); for (name, body) in [("_rels/.rels", root), ("word/document.xml", doc), ("word/_rels/document.xml.rels", rels), ("word/styles.xml", styles)] { zw.start_file(name, zip::write::SimpleFileOptions::default()).unwrap(); zw.write_all(body.as_bytes()).unwrap(); } let d = craft_docx::read(&zw.finish().unwrap().into_inner()).unwrap(); assert_eq!(d.styles.default_chr.size, Some(10.0)); } #[test] fn an_unset_default_size_does_not_take_a_styles_size() { // The written default is the resolver's own fallback, not what the Normal style resolves to, // so a style that sets a size keeps it and one that does not still falls back to the default. let mut d = Document::new(); Arc::make_mut(&mut d.styles).default_chr.size = None; if let Some(normal) = Arc::make_mut(&mut d.styles).get_mut("Normal") { normal.chr.size = Some(14.0); } let reopened = craft_docx::read(&craft_docx::write(&d).unwrap()).unwrap(); assert_eq!(reopened.styles.default_chr.size, Some(DEFAULT_FONT_SIZE)); assert_eq!(resolved(&reopened), resolved(&d)); }