@@ -41,7 +41,9 @@ public class Transform extends Resource {
41
41
42
42
private int initialZoom ;
43
43
44
- private HashMap <Integer , Long > zoomLevelToHandle = new HashMap <>();
44
+ private Map <Integer , TransformHandle > zoomToHandle = new HashMap <>();
45
+
46
+ private List <Operation > operations = new ArrayList <>();
45
47
46
48
/**
47
49
* Constructs a new identity Transform.
@@ -143,7 +145,7 @@ public Transform (Device device, float m11, float m12, float m21, float m22, flo
143
145
long handle = Gdip .Matrix_new (m11 , m12 , m21 , m22 ,
144
146
DPIUtil .scaleUp (this .device , dx , initialZoom ), DPIUtil .scaleUp (this .device , dy , initialZoom ));
145
147
if (handle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
146
- zoomLevelToHandle .put (initialZoom , handle );
148
+ zoomToHandle .put (initialZoom , new TransformHandle ( handle , initialZoom ) );
147
149
init ();
148
150
this .device .registerResourceWithZoomSupport (this );
149
151
}
@@ -157,16 +159,17 @@ static float[] checkTransform(float[] elements) {
157
159
@ Override
158
160
void destroy () {
159
161
device .deregisterResourceWithZoomSupport (this );
160
- zoomLevelToHandle .values ().forEach (Gdip ::Matrix_delete );
161
- zoomLevelToHandle .clear ();
162
+ zoomToHandle .values ().forEach (TransformHandle ::destroy );
163
+ zoomToHandle .clear ();
164
+ operations .clear ();
162
165
}
163
166
164
167
@ Override
165
168
void destroyHandlesExcept (Set <Integer > zoomLevels ) {
166
- zoomLevelToHandle .entrySet ().removeIf (entry -> {
169
+ zoomToHandle .entrySet ().removeIf (entry -> {
167
170
final Integer zoom = entry .getKey ();
168
171
if (!zoomLevels .contains (zoom ) && zoom != initialZoom ) {
169
- Gdip . Matrix_delete ( entry .getValue ());
172
+ entry .getValue (). destroy ( );
170
173
return true ;
171
174
}
172
175
return false ;
@@ -191,10 +194,12 @@ public void getElements(float[] elements) {
191
194
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
192
195
if (elements == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
193
196
if (elements .length < 6 ) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
194
- Gdip .Matrix_GetElements (getHandle (initialZoom ), elements );
197
+ TransformHandle transformHandle = getTransformHandle (initialZoom );
198
+ Gdip .Matrix_GetElements (transformHandle .handle , elements );
195
199
Drawable drawable = getDevice ();
196
- elements [4 ] = DPIUtil .scaleDown (drawable , elements [4 ], initialZoom );
197
- elements [5 ] = DPIUtil .scaleDown (drawable , elements [5 ], initialZoom );
200
+ int zoom = transformHandle .zoom ;
201
+ elements [4 ] = DPIUtil .scaleDown (drawable , elements [4 ], zoom );
202
+ elements [5 ] = DPIUtil .scaleDown (drawable , elements [5 ], zoom );
198
203
}
199
204
200
205
/**
@@ -209,7 +214,9 @@ public void getElements(float[] elements) {
209
214
*/
210
215
public void identity () {
211
216
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
212
- Gdip .Matrix_SetElements (getHandle (initialZoom ), 1 , 0 , 0 , 1 , 0 , 0 );
217
+ // identity invalidates all previous operations, so we remove them
218
+ operations .clear ();
219
+ storeAndApplyOperationForAllHandles (new SetElementsOperation (1 , 0 , 0 , 1 , 0 , 0 ));
213
220
}
214
221
215
222
/**
@@ -223,7 +230,7 @@ public void identity() {
223
230
*/
224
231
public void invert () {
225
232
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
226
- if ( Gdip . Matrix_Invert ( getHandle ( initialZoom )) != 0 ) SWT . error ( SWT . ERROR_CANNOT_INVERT_MATRIX );
233
+ storeAndApplyOperationForAllHandles ( new InvertOperation () );
227
234
}
228
235
229
236
/**
@@ -238,7 +245,7 @@ public void invert() {
238
245
*/
239
246
@ Override
240
247
public boolean isDisposed () {
241
- return zoomLevelToHandle .isEmpty ();
248
+ return zoomToHandle .isEmpty ();
242
249
}
243
250
244
251
/**
@@ -249,7 +256,8 @@ public boolean isDisposed() {
249
256
*/
250
257
public boolean isIdentity () {
251
258
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
252
- return Gdip .Matrix_IsIdentity (getHandle (initialZoom ));
259
+ TransformHandle transformHandle = getTransformHandle (initialZoom );
260
+ return Gdip .Matrix_IsIdentity (transformHandle .handle );
253
261
}
254
262
255
263
/**
@@ -271,7 +279,7 @@ public void multiply(Transform matrix) {
271
279
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
272
280
if (matrix == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
273
281
if (matrix .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
274
- Gdip . Matrix_Multiply ( getHandle ( initialZoom ), matrix . getHandle ( initialZoom ), Gdip . MatrixOrderPrepend );
282
+ storeAndApplyOperationForAllHandles ( new MultiplyOperation ( matrix ) );
275
283
}
276
284
277
285
/**
@@ -289,7 +297,7 @@ public void multiply(Transform matrix) {
289
297
*/
290
298
public void rotate (float angle ) {
291
299
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
292
- Gdip . Matrix_Rotate ( getHandle ( initialZoom ), angle , Gdip . MatrixOrderPrepend );
300
+ storeAndApplyOperationForAllHandles ( new RotateOperation ( angle ) );
293
301
}
294
302
295
303
/**
@@ -305,7 +313,7 @@ public void rotate(float angle) {
305
313
*/
306
314
public void scale (float scaleX , float scaleY ) {
307
315
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
308
- Gdip . Matrix_Scale ( getHandle ( initialZoom ), scaleX , scaleY , Gdip . MatrixOrderPrepend );
316
+ storeAndApplyOperationForAllHandles ( new ScaleOperation ( scaleX , scaleY ) );
309
317
}
310
318
311
319
/**
@@ -325,8 +333,9 @@ public void scale(float scaleX, float scaleY) {
325
333
*/
326
334
public void setElements (float m11 , float m12 , float m21 , float m22 , float dx , float dy ) {
327
335
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
328
- Drawable drawable = getDevice ();
329
- Gdip .Matrix_SetElements (getHandle (initialZoom ), m11 , m12 , m21 , m22 , DPIUtil .scaleUp (drawable , dx , initialZoom ), DPIUtil .scaleUp (drawable , dy , initialZoom ));
336
+ // setElements invalidates all previous operations, so we remove them
337
+ operations .clear ();
338
+ storeAndApplyOperationForAllHandles (new SetElementsOperation (m11 , m12 , m21 , m22 , dx , dy ));
330
339
}
331
340
332
341
/**
@@ -344,7 +353,7 @@ public void setElements(float m11, float m12, float m21, float m22, float dx, fl
344
353
*/
345
354
public void shear (float shearX , float shearY ) {
346
355
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
347
- Gdip . Matrix_Shear ( getHandle ( initialZoom ), shearX , shearY , Gdip . MatrixOrderPrepend );
356
+ storeAndApplyOperationForAllHandles ( new ShearOperation ( shearX , shearY ) );
348
357
}
349
358
350
359
/**
@@ -364,14 +373,15 @@ public void shear(float shearX, float shearY) {
364
373
public void transform (float [] pointArray ) {
365
374
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
366
375
if (pointArray == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
367
- int length = pointArray .length ;
368
376
Drawable drawable = getDevice ();
377
+ TransformHandle transformHandle = getTransformHandle (initialZoom );
378
+ int length = pointArray .length ;
369
379
for (int i = 0 ; i < length ; i ++) {
370
- pointArray [i ] = DPIUtil .scaleUp (drawable , pointArray [i ], initialZoom );
380
+ pointArray [i ] = DPIUtil .scaleUp (drawable , pointArray [i ], transformHandle . zoom );
371
381
}
372
- Gdip .Matrix_TransformPoints (getHandle ( initialZoom ) , pointArray , length / 2 );
382
+ Gdip .Matrix_TransformPoints (transformHandle . handle , pointArray , length / 2 );
373
383
for (int i = 0 ; i < length ; i ++) {
374
- pointArray [i ] = DPIUtil .scaleDown (drawable , pointArray [i ], initialZoom );
384
+ pointArray [i ] = DPIUtil .scaleDown (drawable , pointArray [i ], transformHandle . zoom );
375
385
}
376
386
}
377
387
@@ -388,8 +398,123 @@ public void transform(float[] pointArray) {
388
398
*/
389
399
public void translate (float offsetX , float offsetY ) {
390
400
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
391
- Drawable drawable = getDevice ();
392
- Gdip .Matrix_Translate (getHandle (initialZoom ), DPIUtil .scaleUp (drawable , offsetX , initialZoom ), DPIUtil .scaleUp (drawable , offsetY , initialZoom ), Gdip .MatrixOrderPrepend );
401
+ storeAndApplyOperationForAllHandles (new TranslateOperation (offsetX , offsetY ));
402
+ }
403
+
404
+ private record TransformHandle (long handle , int zoom ) {
405
+ void destroy () {
406
+ Gdip .Matrix_delete (handle );
407
+ }
408
+ }
409
+
410
+ private record InvertOperation () implements Operation {
411
+ @ Override
412
+ public void apply (TransformHandle transformHandle ) {
413
+ long handle = transformHandle .handle ;
414
+ if (Gdip .Matrix_Invert (handle ) != 0 ) SWT .error (SWT .ERROR_CANNOT_INVERT_MATRIX );
415
+ }
416
+ }
417
+
418
+ private class MultiplyOperation implements Operation {
419
+ private final float [] elements ;
420
+
421
+ public MultiplyOperation (Transform matrix ) {
422
+ // As operation are executed on demand on new handles the passed matrix could
423
+ // already be disposed. Therefore, we need to store the elements to restore
424
+ // a temporary matrix for this operation on demand
425
+ elements = new float [6 ];
426
+ matrix .getElements (elements );
427
+ }
428
+
429
+ @ Override
430
+ public void apply (TransformHandle transformHandle ) {
431
+ long handle = transformHandle .handle ;
432
+ int zoom = transformHandle .zoom ;
433
+ long newHandle = Gdip .Matrix_new (elements [0 ], elements [1 ], elements [2 ], elements [3 ], DPIUtil .scaleUp (elements [4 ], zoom ), DPIUtil .scaleUp (elements [5 ], zoom ));
434
+ if (newHandle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
435
+ try {
436
+ Gdip .Matrix_Multiply (handle , newHandle , Gdip .MatrixOrderPrepend );
437
+ } finally {
438
+ Gdip .Matrix_delete (newHandle );
439
+ }
440
+ }
441
+ }
442
+
443
+ private record RotateOperation (float angle ) implements Operation {
444
+ @ Override
445
+ public void apply (TransformHandle transformHandle ) {
446
+ long handle = transformHandle .handle ;
447
+ Gdip .Matrix_Rotate (handle , angle , Gdip .MatrixOrderPrepend );
448
+ }
449
+ }
450
+
451
+ private record ScaleOperation (float scaleX , float scaleY ) implements Operation {
452
+ @ Override
453
+ public void apply (TransformHandle transformHandle ) {
454
+ long handle = transformHandle .handle ;
455
+ Gdip .Matrix_Scale (handle , scaleX , scaleY , Gdip .MatrixOrderPrepend );
456
+ }
457
+ }
458
+
459
+ private class SetElementsOperation implements Operation {
460
+ private final float m11 ;
461
+ private final float m12 ;
462
+ private final float m21 ;
463
+ private final float m22 ;
464
+ private final float dx ;
465
+ private final float dy ;
466
+
467
+ public SetElementsOperation (float m11 , float m12 , float m21 , float m22 , float dx , float dy ) {
468
+ this .m11 = m11 ;
469
+ this .m12 = m12 ;
470
+ this .m21 = m21 ;
471
+ this .m22 = m22 ;
472
+ this .dx = dx ;
473
+ this .dy = dy ;
474
+ }
475
+
476
+ @ Override
477
+ public void apply (TransformHandle transformHandle ) {
478
+ Drawable drawable = getDevice ();
479
+ long handle = transformHandle .handle ;
480
+ int zoom = transformHandle .zoom ;
481
+ Gdip .Matrix_SetElements (handle , m11 , m12 , m21 , m22 , DPIUtil .scaleUp (drawable , dx , zoom ), DPIUtil .scaleUp (drawable , dy , zoom ));
482
+ }
483
+ }
484
+
485
+ private record ShearOperation (float shearX , float shearY ) implements Operation {
486
+ @ Override
487
+ public void apply (TransformHandle transformHandle ) {
488
+ long handle = transformHandle .handle ;
489
+ Gdip .Matrix_Shear (handle , shearX , shearY , Gdip .MatrixOrderPrepend );
490
+ }
491
+ }
492
+
493
+ private class TranslateOperation implements Operation {
494
+ private final float offsetX ;
495
+ private final float offsetY ;
496
+
497
+ public TranslateOperation (float offsetX , float offsetY ) {
498
+ this .offsetX = offsetX ;
499
+ this .offsetY = offsetY ;
500
+ }
501
+
502
+ @ Override
503
+ public void apply (TransformHandle transformHandle ) {
504
+ Drawable drawable = getDevice ();
505
+ long handle = transformHandle .handle ;
506
+ int zoom = transformHandle .zoom ;
507
+ Gdip .Matrix_Translate (handle , DPIUtil .scaleUp (drawable , offsetX , zoom ), DPIUtil .scaleUp (drawable , offsetY , zoom ), Gdip .MatrixOrderPrepend );
508
+ }
509
+ }
510
+
511
+ private interface Operation {
512
+ void apply (TransformHandle transformHandle );
513
+ }
514
+
515
+ private void storeAndApplyOperationForAllHandles (Operation operation ) {
516
+ operations .add (operation );
517
+ zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle ));
393
518
}
394
519
395
520
/**
@@ -405,17 +530,21 @@ public String toString() {
405
530
getElements (elements );
406
531
return "Transform {" + elements [0 ] + "," + elements [1 ] + "," +elements [2 ] + "," +elements [3 ] + "," +elements [4 ] + "," +elements [5 ] + "}" ;
407
532
}
408
-
409
- long getHandle (int zoomLevel ) {
410
- if (zoomLevelToHandle .get (zoomLevel ) == null ) {
533
+ private TransformHandle getTransformHandle (int zoom ) {
534
+ if (zoomToHandle .get (zoom ) == null ) {
411
535
float [] elements = new float [6 ];
412
536
getElements (elements );
413
- elements [4 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [4 ], initialZoom ), zoomLevel );
414
- elements [5 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [5 ], initialZoom ), zoomLevel );
415
-
416
- zoomLevelToHandle .put (zoomLevel , Gdip .Matrix_new (elements [0 ], elements [1 ], elements [2 ], elements [3 ], elements [4 ], elements [5 ]));
537
+ elements [4 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [4 ], initialZoom ), zoom );
538
+ elements [5 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [5 ], initialZoom ), zoom );
539
+ long handle = Gdip .Matrix_new (elements [0 ], elements [1 ], elements [2 ], elements [3 ], elements [4 ], elements [5 ]);
540
+ TransformHandle transformHandle = new TransformHandle (handle , zoom );
541
+ zoomToHandle .put (zoom , transformHandle );
542
+ return transformHandle ;
417
543
}
418
- return zoomLevelToHandle .get (zoomLevel );
544
+ return zoomToHandle .get (zoom );
419
545
}
420
546
547
+ long getHandle (int zoomLevel ) {
548
+ return getTransformHandle (zoomLevel ).handle ;
549
+ }
421
550
}
0 commit comments