work on pagesetup
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 6 Oct 2025 01:11:10 +0000 (18:11 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 6 Oct 2025 16:10:35 +0000 (09:10 -0700)
rust/Cargo.lock
rust/pspp/Cargo.toml
rust/pspp/src/output/page.rs

index 20418374eb0e064b1e0456ab35cdeb61e73df8f4..88ec82c1f7d90b23eef3054e3fa9744c2a767255 100644 (file)
@@ -1823,6 +1823,7 @@ dependencies = [
  "ordered-float",
  "pango",
  "pangocairo",
+ "paper-sizes",
  "pspp-derive",
  "quick-xml",
  "rand",
index 232a8282b8e3cf3fbbca24e2d3c6df1b4e67302c..5479134fb5de75ddcb6e8cc6f80338ffc662f1ce 100644 (file)
@@ -57,6 +57,7 @@ displaydoc = "0.2.5"
 codepage-437 = "0.1.0"
 serde_path_to_error = "0.1.20"
 html_parser = "0.7.0"
+paper-sizes = { path = "../paper-sizes" }
 
 [target.'cfg(windows)'.dependencies]
 windows-sys = { version = "0.48.0", features = ["Win32_Globalization"] }
index ab89d6c37556a945e673a2d8103f107a7a04c9a4..19ddcf801f0eea7cfe62c64f51d3c65c00710fc8 100644 (file)
 // You should have received a copy of the GNU General Public License along with
 // this program.  If not, see <http://www.gnu.org/licenses/>.
 
-use std::{path::Path, str::FromStr};
+use std::{path::Path, str::FromStr, sync::LazyLock};
 
 use enum_map::{EnumMap, enum_map};
-use serde::{Deserialize, Serialize};
+use paper_sizes::{Catalog, PaperSize};
+use serde::{Deserialize, Deserializer, Serialize, de::Error};
 
 use super::pivot::{Axis2, HorzAlign};
 
@@ -72,6 +73,7 @@ pub struct PageSetup {
     pub initial_page_number: i32,
 
     /// Paper size in inches.
+    #[serde(with = "paper_size_serde")]
     pub paper: EnumMap<Axis2, f64>,
 
     /// Margin width in inches.
@@ -90,11 +92,62 @@ pub struct PageSetup {
     pub headings: [Heading; 2],
 }
 
+static CATALOG: LazyLock<Catalog> = LazyLock::new(|| Catalog::new());
+
+mod paper_size_serde {
+    use std::str::FromStr;
+
+    use enum_map::EnumMap;
+    use paper_sizes::{PaperSize, Unit::Inch};
+    use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
+
+    use crate::{
+        output::{
+            page::{CATALOG, paper_size_to_enum_map},
+            pivot::Axis2,
+        },
+        util::ToSmallString,
+    };
+
+    pub fn deserialize<'de, D>(deserializer: D) -> Result<EnumMap<Axis2, f64>, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let size = String::deserialize(deserializer)?;
+        let paper_size = PaperSize::from_str(&size).or_else(|_| {
+            CATALOG
+                .get_by_name(&size)
+                .map(|spec| spec.size)
+                .ok_or_else(|| D::Error::custom("unknown or invalid paper size {size}"))
+        })?;
+        Ok(paper_size_to_enum_map(paper_size))
+    }
+
+    pub fn serialize<S>(paper_size: &EnumMap<Axis2, f64>, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        PaperSize::new(paper_size[Axis2::X], paper_size[Axis2::Y], Inch)
+            .to_string()
+            .serialize(serializer)
+    }
+}
+
+fn paper_size_to_enum_map(paper_size: PaperSize) -> EnumMap<Axis2, f64> {
+    let (w, h) = paper_size
+        .as_unit(paper_sizes::Unit::Inch)
+        .into_width_height();
+    enum_map! {
+        Axis2::X => w,
+        Axis2::Y => h
+    }
+}
+
 impl Default for PageSetup {
     fn default() -> Self {
         Self {
             initial_page_number: 1,
-            paper: enum_map! { Axis2::X => 8.5, Axis2::Y => 11.0 },
+            paper: paper_size_to_enum_map(CATALOG.default_paper().size),
             margins: enum_map! { Axis2::X => [0.5, 0.5], Axis2::Y => [0.5, 0.5] },
             orientation: Default::default(),
             object_spacing: 12.0 / 72.0,
@@ -109,4 +162,3 @@ impl PageSetup {
         EnumMap::from_fn(|axis| self.paper[axis] - self.margins[axis][0] - self.margins[axis][1])
     }
 }
-