@@ -20,47 +20,88 @@ function rotateCurrentSprite(canvas, angle) {
20
20
// canvas.height = rotatedData.height;
21
21
// ctx.putImageData(rotatedData, 0, 0);
22
22
23
+ function flipImageData ( imageData ) {
24
+ const { width, height, data } = imageData ;
25
+ const rotatedImageData = new ImageData ( width , height ) ;
26
+ const rotatedData = rotatedImageData . data ;
27
+
28
+ for ( let y = 0 ; y < height ; y ++ ) {
29
+ for ( let x = 0 ; x < width ; x ++ ) {
30
+ const srcIndex = ( y * width + x ) * 4 ;
31
+ const dstIndex = ( ( height - y - 1 ) * width + ( width - x - 1 ) ) * 4 ;
32
+ rotatedData [ dstIndex + 0 ] = data [ srcIndex + 0 ] ;
33
+ rotatedData [ dstIndex + 1 ] = data [ srcIndex + 1 ] ;
34
+ rotatedData [ dstIndex + 2 ] = data [ srcIndex + 2 ] ;
35
+ rotatedData [ dstIndex + 3 ] = data [ srcIndex + 3 ] ;
36
+ }
37
+ }
38
+
39
+ return rotatedImageData ;
40
+ }
23
41
24
- // add padding
25
- const { diagonal, xMargin, yMargin } = getRotateDiagonal ( spriteCanv . width , spriteCanv . height ) ;
42
+ const flipped = angle > 90 && angle < 270 ;
43
+ // TODO: fix flip clipping
44
+ // TODO: fix padding clipping
45
+
46
+ let { diagonal, xMargin, yMargin } = getRotateDiagonal (
47
+ spriteCanv . width ,
48
+ spriteCanv . height ,
49
+ ) ;
26
50
const width = diagonal ;
27
51
const height = diagonal ;
28
52
29
- const copy = spriteCtx . getImageData ( 0 , 0 , spriteCanv . width , spriteCanv . height ) ;
53
+ const copy = spriteCtx . getImageData (
54
+ 0 ,
55
+ 0 ,
56
+ spriteCanv . width ,
57
+ spriteCanv . height ,
58
+ ) ;
30
59
31
60
spriteCanv . width = diagonal ;
32
61
spriteCanv . height = diagonal ;
33
62
34
- spriteCtx . putImageData ( copy , xMargin , yMargin ) ;
63
+ spriteCtx . putImageData ( flipped ? flipImageData ( copy ) : copy , xMargin , yMargin ) ;
35
64
36
65
const ctx = canvas . getContext ( '2d' ) ;
37
66
canvas . width = width ;
38
67
canvas . height = height ;
39
68
40
- // rotate
41
69
42
- const theta = angle * Math . PI / 180 ;
43
- const alpha = - Math . tan ( theta / 2 ) ;
44
- const beta = Math . sin ( theta ) ;
70
+ if ( flipped ) {
71
+ // // flip spriteCanv using ctx as a buffer
72
+ // ctx.save();
73
+ // ctx.translate(width / 2, height / 2);
74
+ // ctx.rotate(Math.PI);
75
+ // ctx.drawImage(spriteCanv, -width / 2, -width / 2);
76
+ // ctx.restore();
77
+ // spriteCtx.clearRect(0, 0, width, height);
78
+ // spriteCtx.drawImage(canvas, 0, 0, width, height);
79
+ // ctx.clearRect(0, 0, width, height);
80
+ }
45
81
82
+ // rotate
46
83
84
+ const clampedAngle = flipped ? angle - 180 : angle ;
85
+ const theta = ( clampedAngle * Math . PI ) / 180 ;
86
+ const alpha = - Math . tan ( theta / 2 ) ;
87
+ const beta = Math . sin ( theta ) ;
47
88
48
89
for ( let y = 0 ; y < height ; ++ y ) {
49
- const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
90
+ const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
50
91
ctx . drawImage ( spriteCanv , 0 , y , width , 1 , shear , y , width , 1 ) ;
51
92
}
52
93
spriteCtx . clearRect ( 0 , 0 , width , height ) ;
53
94
spriteCtx . drawImage ( canvas , 0 , 0 ) ;
54
95
ctx . clearRect ( 0 , 0 , width , height ) ;
55
96
for ( let x = 0 ; x < width ; ++ x ) {
56
- const shear = Math . round ( ( x - width / 2 ) * beta ) ;
97
+ const shear = Math . round ( ( x - width / 2 ) * beta ) ;
57
98
ctx . drawImage ( spriteCanv , x , 0 , 1 , height , x , shear , 1 , height ) ;
58
99
}
59
100
spriteCtx . clearRect ( 0 , 0 , width , height ) ;
60
101
spriteCtx . drawImage ( canvas , 0 , 0 ) ;
61
102
ctx . clearRect ( 0 , 0 , width , height ) ;
62
103
for ( let y = 0 ; y < height ; ++ y ) {
63
- const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
104
+ const shear = Math . round ( ( y - height / 2 ) * alpha ) ;
64
105
ctx . drawImage ( spriteCanv , 0 , y , width , 1 , shear , y , width , 1 ) ;
65
106
}
66
107
}
@@ -138,7 +179,9 @@ export const Rotate = observer(() => {
138
179
< Button color = "magenta" onClick = { mappingState . toggleRotate } >
139
180
close
140
181
</ Button >
141
- < Button color = "red" onClick = { reImport } > Import</ Button >
182
+ < Button color = "red" onClick = { reImport } >
183
+ Import
184
+ </ Button >
142
185
</ div >
143
186
</ Modal >
144
187
) ;
0 commit comments