// 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};
pub initial_page_number: i32,
/// Paper size in inches.
+ #[serde(with = "paper_size_serde")]
pub paper: EnumMap<Axis2, f64>,
/// Margin width in inches.
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,
EnumMap::from_fn(|axis| self.paper[axis] - self.margins[axis][0] - self.margins[axis][1])
}
}
-