diff --git a/crates/engine/src/cmd/webexport.rs b/crates/engine/src/cmd/webexport.rs index 52ed5c67..b33fd8cb 100644 --- a/crates/engine/src/cmd/webexport.rs +++ b/crates/engine/src/cmd/webexport.rs @@ -142,6 +142,17 @@ fn de_key<'de, T: Keyed, D: Deserializer<'de>>(d: D) -> std::result::Result>(d: D) -> std::result::Result, D::Error> { + let Some(v) = Option::::deserialize(d)? else { return Ok(None) }; + let px = v.round(); + if !(px.is_finite() && px >= 0.0 && px <= f64::from(u32::MAX)) { + return Err(D::Error::custom(format!("{v} is not a size in pixels"))); + } + // In range and whole: the cast is exact. + Ok(Some(px as u32)) +} + /// The file format. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -361,8 +372,10 @@ pub struct WebSettings { /// JPEG: embed the sRGB profile. pub embed_profile: bool, /// The image width in pixels (the height follows). + #[serde(deserialize_with = "de_pixels")] pub width: Option, /// The image height in pixels (the width follows). + #[serde(deserialize_with = "de_pixels")] pub height: Option, /// The image size in percent of the art's size in points. pub percent: Option, diff --git a/crates/engine/src/tests_webexport.rs b/crates/engine/src/tests_webexport.rs index 8f845807..0598579a 100644 --- a/crates/engine/src/tests_webexport.rs +++ b/crates/engine/src/tests_webexport.rs @@ -285,9 +285,16 @@ fn image_size_region_and_metadata() { assert_eq!(size(&mut s, json!({"width": 80})), (80, 60)); assert_eq!(size(&mut s, json!({"height": 15})), (20, 15)); assert_eq!(size(&mut s, json!({"percent": 150})), (60, 45)); + // The dialog's fields send decimal numbers: rounded to whole pixels. + assert_eq!(size(&mut s, json!({"width": 80.0})), (80, 60)); + assert_eq!(size(&mut s, json!({"height": 14.6})), (20, 15)); for bad in [ json!({"percent": 0}), json!({"width": 0}), + json!({"width": 0.2}), + json!({"width": -5}), + json!({"height": 1e300}), + json!({"height": "tall"}), json!({"format": "bmp"}), json!({"colors": "many"}), json!({"matte": "plaid"}),