Merge PR #3396: LR-EXP-DIM: export sizes keep the pixels typed (#3300)

docs/whats-new.md: keep both entries, newest first
This commit is contained in:
aiongg
2026-10-31 02:08:40 +00:00
3 changed files with 46 additions and 3 deletions
+4 -3
View File
@@ -202,11 +202,12 @@ pub(super) const QUALITY: ControlSpec = spec("export.quality", "Quality", 1.0, 1
pub(super) const LIMIT_KB: ControlSpec = spec("export.limitKb", "Limit file size (KB, 0 = off)", 0.0, 20_000.0, 0.0, 10.0);
const SIZE_PX: ControlSpec = spec("export.sizePx", "Pixels", 16.0, 20_000.0, 2048.0, 16.0);
// whole pixels: a typed size is snapped to the step, and 1080 or 1350 must stay what was typed
const SIZE_PX: ControlSpec = spec("export.sizePx", "Pixels", 16.0, 20_000.0, 2048.0, 1.0);
const SIZE_W: ControlSpec = spec("export.sizeW", "Width (px)", 16.0, 20_000.0, 2048.0, 16.0);
const SIZE_W: ControlSpec = spec("export.sizeW", "Width (px)", 16.0, 20_000.0, 2048.0, 1.0);
const SIZE_H: ControlSpec = spec("export.sizeH", "Height (px)", 16.0, 20_000.0, 2048.0, 16.0);
const SIZE_H: ControlSpec = spec("export.sizeH", "Height (px)", 16.0, 20_000.0, 2048.0, 1.0);
const SIZE_MP: ControlSpec = ControlSpec { decimals: 1, ..spec("export.sizeMp", "Megapixels", 0.1, 100.0, 12.0, 0.1) };
+36
View File
@@ -4966,3 +4966,39 @@ fn screenshot_request_is_answered_without_a_window() {
let r = h.request("ui.screenshot", json!({"headless": true}), SETTLE);
assert_eq!(r["result"]["width"], 640, "{r}");
}
/// A size typed in the Export dialog is the size exported: the pixel fields kept only multiples
/// of 16, so 1080 became 1088 and 3000 became 3008 (issue #3300).
#[test]
fn export_sizes_keep_the_pixels_typed() {
let mut h = demo([1400.0, 900.0]);
let t = Duration::from_secs(10);
h.request("engine.execute", json!({"command": "dialog.export", "params": {}}), t);
h.settle(SETTLE);
let type_value = |h: &mut Headless, id: &str, text: &str| {
let r = h.request("ui.clickWidget", json!({"id": id}), t);
assert_eq!(r["ok"], true, "{id}: {r}");
h.request("ui.text", json!({"text": text}), t);
h.request("ui.key", json!({"key": "Enter"}), t);
h.settle(SETTLE);
};
let resize = |h: &Headless| match &h.app.ui.dialog {
Some(crate::state::Dialog::Export { resize, .. }) => *resize,
_ => panic!("the dialog closed"),
};
if let Some(crate::state::Dialog::Export { full_size, resize, .. }) = &mut h.app.ui.dialog {
*full_size = false;
*resize = lightcraft_engine::export::Resize::long_edge(2048);
}
h.settle(SETTLE);
type_value(&mut h, "sliderValue:export.sizePx", "3000");
assert_eq!(resize(&h).value, 3000.0);
if let Some(crate::state::Dialog::Export { resize, .. }) = &mut h.app.ui.dialog {
resize.mode = lightcraft_engine::export::ResizeMode::WidthHeight;
resize.height = 2048;
}
h.settle(SETTLE);
type_value(&mut h, "sliderValue:export.sizeW", "1080");
type_value(&mut h, "sliderValue:export.sizeH", "1350");
assert_eq!((resize(&h).value, resize(&h).height), (1080.0, 1350));
}
+6
View File
@@ -1,5 +1,11 @@
# What's new in LightCraft
## 2026-10-30
### Export sizes keep the pixels typed
- Export ▸ Image Sizing kept pixel sizes only in steps of 16, so a typed 1080 became 1088 and 3000 became 3008. The
long edge, short edge, width and height fields now keep any whole number of pixels.
## 2026-10-27
### The Edit menu groups Select Only Active Photo and Paste Settings from Previous with their kin