mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-14 19:26:56 -04:00
Fix #839: Save for Web accepts a typed width or height
The dialog's W and H fields send decimal numbers (300.0) and the settings wanted a whole u32, so the preview failed with "invalid type: floating point". Pixel sizes now take any number and round it to whole pixels; negative, huge and non-numeric sizes are still refused. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
021a9474f8
commit
5df4ddd4b6
2 files changed
+20
No files matched your search
@@ -142,6 +142,17 @@ fn de_key<'de, T: Keyed, D: Deserializer<'de>>(d: D) -> std::result::Result<T, D
|
||||
T::parse(&s).ok_or_else(|| D::Error::custom(format!("`{s}`: {}", T::KEYS)))
|
||||
}
|
||||
|
||||
/// A size in pixels: a number, rounded to whole pixels (`300.0` is 300).
|
||||
fn de_pixels<'de, D: Deserializer<'de>>(d: D) -> std::result::Result<Option<u32>, D::Error> {
|
||||
let Some(v) = Option::<f64>::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<u32>,
|
||||
/// The image height in pixels (the width follows).
|
||||
#[serde(deserialize_with = "de_pixels")]
|
||||
pub height: Option<u32>,
|
||||
/// The image size in percent of the art's size in points.
|
||||
pub percent: Option<f64>,
|
||||
|
||||
@@ -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"}),
|
||||
|
||||
Reference in new issue
Block a user