mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
Clamp overflowing geometry to the limit and keep rotated resizes in range
An overflow to infinity (move x=1e308 dx=1e308) now lands on the limit instead of resetting to 0, and a rotated shape re-centred after a capped resize stays within POS_LIMIT (CodeRabbit review). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3e729bbf08
commit
efc279d6f2
@@ -170,13 +170,14 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
}
|
||||
|
||||
/// Keeps a side length in `0..=MAX_PT` so a huge value cannot exhaust memory when rendering.
|
||||
/// An overflow to infinity lands on the limit; NaN becomes 0.
|
||||
fn clamp_side(v: f64) -> f64 {
|
||||
if v.is_finite() { v.clamp(0.0, MAX_PT) } else { 0.0 }
|
||||
if v.is_nan() { 0.0 } else { v.clamp(0.0, MAX_PT) }
|
||||
}
|
||||
|
||||
/// Keeps a coordinate within `±POS_LIMIT`.
|
||||
fn clamp_pos(v: f64) -> f64 {
|
||||
if v.is_finite() { v.clamp(-POS_LIMIT, POS_LIMIT) } else { 0.0 }
|
||||
if v.is_nan() { 0.0 } else { v.clamp(-POS_LIMIT, POS_LIMIT) }
|
||||
}
|
||||
|
||||
fn move_by(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
@@ -216,8 +217,8 @@ fn resize(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
x.h = clamp_side(x.h);
|
||||
// Rotated shapes resize about their centre; others keep the top-left.
|
||||
if x.rot != 0.0 {
|
||||
x.x = cx - x.w / 2.0;
|
||||
x.y = cy - x.h / 2.0;
|
||||
x.x = clamp_pos(cx - x.w / 2.0);
|
||||
x.y = clamp_pos(cy - x.h / 2.0);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -3647,4 +3647,13 @@ fn shape_geometry_commands_limit_size_and_position() {
|
||||
s.execute("shape.move", &json!({"x": 1e100, "y": -1e100})).unwrap();
|
||||
let x = xfrm(&s);
|
||||
assert!(within(&s), "move stored {x:?}");
|
||||
// A move that overflows to infinity lands on the limit, not back at 0.
|
||||
s.execute("shape.move", &json!({"x": 1e308, "dx": 1e308})).unwrap();
|
||||
assert_eq!(xfrm(&s).x, 100_000.0);
|
||||
// A rotated shape resizes about its centre and still stays inside the limit.
|
||||
s.execute("shape.setBounds", &json!({"x": 99_000, "y": 0, "w": 10, "h": 10})).unwrap();
|
||||
s.execute("shape.rotate", &json!({"deg": 45})).unwrap();
|
||||
s.execute("shape.resize", &json!({"w": 1e100})).unwrap();
|
||||
let x = xfrm(&s);
|
||||
assert!(within(&s), "rotated resize stored {x:?}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user