From 743a25b76a9202adf7623c8524d81df0e8d27122 Mon Sep 17 00:00:00 2001 From: kevin9327 <5299031+kevin9327@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:09:27 +0900 Subject: [PATCH] fix(plot-style): keep custom lineweights at full precision when saving Saving a plot style table wrote every value of its custom lineweight table with two decimals, so a pen such as 0.035 mm came back as 0.04 mm after a save and reload, and every color using it plotted with the wrong weight. Write the lineweights in full, through the same formatting the scale factor already uses, which keeps the decimal point on a whole value. Co-Authored-By: Claude Opus 5 --- src/io/plot_style.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/io/plot_style.rs b/src/io/plot_style.rs index becceca44..89b2033c6 100644 --- a/src/io/plot_style.rs +++ b/src/io/plot_style.rs @@ -357,13 +357,8 @@ impl PlotStyleTable { let description = self.description.replace(['\r', '\n'], " "); s.push_str(&format!("description=\"{description}\n")); s.push_str("aci_table_available=TRUE\n"); - // The factor scales every lineweight when applied, so write it in full, - // keeping the decimal point on a whole value. - let mut scale_factor = self.scale_factor.to_string(); - if scale_factor.chars().all(|c| c.is_ascii_digit() || c == '-') { - scale_factor.push_str(".0"); - } - s.push_str(&format!("scale_factor={scale_factor}\n")); + // The factor scales every lineweight when applied, so write it in full. + s.push_str(&format!("scale_factor={}\n", full_real(self.scale_factor))); s.push_str(&format!( "apply_factor={}\n", if self.apply_factor { "TRUE" } else { "FALSE" } @@ -420,7 +415,7 @@ impl PlotStyleTable { } s.push_str("}\ncustom_lineweight_table{\n"); for (index, weight) in self.lineweights.iter().enumerate() { - s.push_str(&format!(" {index}={weight:.2}\n")); + s.push_str(&format!(" {index}={}\n", full_real(*weight))); } s.push_str("}\n"); s @@ -512,6 +507,15 @@ fn adler32(bytes: &[u8]) -> u32 { (b << 16) | a } +/// A real number written in full, keeping the decimal point on a whole value. +fn full_real(value: f32) -> String { + let mut text = value.to_string(); + if text.chars().all(|c| c.is_ascii_digit() || c == '-') { + text.push_str(".0"); + } + text +} + fn packed_rgb([r, g, b]: [u8; 3]) -> i32 { u32::from_be_bytes([0xC2, r, g, b]) as i32 } @@ -780,4 +784,16 @@ mod round_trip_tests { assert!(table.to_text().contains("\nscale_factor=1.0\n")); assert_eq!(saved_and_reloaded(&table).scale_factor, 1.0); } + + /// Saving keeps each custom lineweight as the table holds it. They used to + /// be cut to two decimals, so a 0.035 mm pen came back as a 0.04 mm one. + #[test] + fn custom_lineweights_survive_a_save() { + let mut table = PlotStyleTable::identity("pens.ctb"); + table.lineweights[1] = 0.035; + table.aci_entries[1].lineweight = 1; + let reloaded = saved_and_reloaded(&table); + assert_eq!(reloaded.lineweights, table.lineweights); + assert_eq!(reloaded.resolve_lineweight(1), Some(0.035)); + } }