@@ -1472,4 +1472,83 @@ mod tests {
14721472 assert_eq ! ( transform. x, 150.0 ) ;
14731473 assert_eq ! ( transform. y, 125.0 ) ;
14741474 }
1475+
1476+ // ------------------------------------------------------------------
1477+ // Rotation helpers
1478+ // ------------------------------------------------------------------
1479+
1480+ fn make_test_sprite ( w : u32 , h : u32 ) -> RgbaImage {
1481+ let mut img = RgbaImage :: new ( w, h) ;
1482+ // Paint a solid red pixel so we can verify the output is not empty.
1483+ img. put_pixel ( 0 , 0 , Rgba ( [ 255 , 0 , 0 , 255 ] ) ) ;
1484+ img
1485+ }
1486+
1487+ fn make_transform ( x : f32 , y : f32 , rotation_deg : f32 ) -> Transform {
1488+ Transform {
1489+ x,
1490+ y,
1491+ width : 100.0 ,
1492+ height : 50.0 ,
1493+ rotation_deg,
1494+ }
1495+ }
1496+
1497+ #[ test]
1498+ fn overlay_sprite_no_rotation_is_identity ( ) {
1499+ let mut canvas = RgbaImage :: new ( 300 , 300 ) ;
1500+ let sprite = make_test_sprite ( 20 , 20 ) ;
1501+ let transform = make_transform ( 50.0 , 50.0 , 0.0 ) ;
1502+ overlay_sprite_with_rotation ( & mut canvas, & sprite, & transform, false ) ;
1503+ // An unrotated sprite at (50, 50) should leave a red pixel there.
1504+ assert_eq ! ( canvas. get_pixel( 50 , 50 ) , & Rgba ( [ 255 , 0 , 0 , 255 ] ) ) ;
1505+ }
1506+
1507+ #[ test]
1508+ fn overlay_sprite_90deg_rotates ( ) {
1509+ let mut canvas = RgbaImage :: new ( 600 , 600 ) ;
1510+ // A large sprite in the center should stay visible after any rotation.
1511+ let sprite = make_test_sprite ( 100 , 100 ) ;
1512+ let transform = make_transform ( 250.0 , 250.0 , 90.0 ) ;
1513+ // The function must not panic.
1514+ overlay_sprite_with_rotation ( & mut canvas, & sprite, & transform, false ) ;
1515+ }
1516+
1517+ #[ test]
1518+ fn overlay_sprite_180deg_rotates ( ) {
1519+ let mut canvas = RgbaImage :: new ( 600 , 600 ) ;
1520+ let sprite = make_test_sprite ( 100 , 100 ) ;
1521+ let transform = make_transform ( 250.0 , 250.0 , 180.0 ) ;
1522+ overlay_sprite_with_rotation ( & mut canvas, & sprite, & transform, false ) ;
1523+ // Must not panic.
1524+ }
1525+
1526+ #[ test]
1527+ fn rotate_sprite_expand_zero_angle_is_identity ( ) {
1528+ let src = make_test_sprite ( 20 , 10 ) ;
1529+ let ( rotated, min_x, min_y) = rotate_sprite_expand_top_left ( & src, 0.0 ) ;
1530+ assert_eq ! ( rotated. width( ) , src. width( ) ) ;
1531+ assert_eq ! ( rotated. height( ) , src. height( ) ) ;
1532+ assert_eq ! ( min_x, 0.0 ) ;
1533+ assert_eq ! ( min_y, 0.0 ) ;
1534+ // The red pixel at (0,0) should be preserved.
1535+ assert_eq ! ( rotated. get_pixel( 0 , 0 ) , & Rgba ( [ 255 , 0 , 0 , 255 ] ) ) ;
1536+ }
1537+
1538+ #[ test]
1539+ fn rotate_sprite_expand_90deg_swaps_dimensions ( ) {
1540+ let src = make_test_sprite ( 40 , 20 ) ;
1541+ let ( rotated, _min_x, _min_y) = rotate_sprite_expand_top_left ( & src, std:: f32:: consts:: FRAC_PI_2 ) ;
1542+ // A 90° rotation swaps width and height, plus bilinear rounding = roughly 20×40.
1543+ assert ! (
1544+ rotated. width( ) >= 20 && rotated. width( ) <= 22 ,
1545+ "expected ~20-22 wide, got {}" ,
1546+ rotated. width( )
1547+ ) ;
1548+ assert ! (
1549+ rotated. height( ) >= 39 && rotated. height( ) <= 41 ,
1550+ "expected ~39-41 tall, got {}" ,
1551+ rotated. height( )
1552+ ) ;
1553+ }
14751554}
0 commit comments