@@ -41,7 +41,9 @@ public class Transform extends Resource {
4141
4242 private int initialZoom ;
4343
44- private HashMap <Integer , Long > zoomLevelToHandle = new HashMap <>();
44+ private Map <Integer , TransformHandle > zoomToHandle = new HashMap <>();
45+
46+ private List <Operation > operations = new ArrayList <>();
4547
4648/**
4749 * Constructs a new identity Transform.
@@ -143,7 +145,7 @@ public Transform (Device device, float m11, float m12, float m21, float m22, flo
143145 long handle = Gdip .Matrix_new (m11 , m12 , m21 , m22 ,
144146 DPIUtil .scaleUp (this .device , dx , initialZoom ), DPIUtil .scaleUp (this .device , dy , initialZoom ));
145147 if (handle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
146- zoomLevelToHandle .put (initialZoom , handle );
148+ zoomToHandle .put (initialZoom , new TransformHandle ( handle , initialZoom ) );
147149 init ();
148150 this .device .registerResourceWithZoomSupport (this );
149151}
@@ -157,16 +159,17 @@ static float[] checkTransform(float[] elements) {
157159@ Override
158160void destroy () {
159161 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 ();
162165}
163166
164167@ Override
165168void destroyHandlesExcept (Set <Integer > zoomLevels ) {
166- zoomLevelToHandle .entrySet ().removeIf (entry -> {
169+ zoomToHandle .entrySet ().removeIf (entry -> {
167170 final Integer zoom = entry .getKey ();
168171 if (!zoomLevels .contains (zoom ) && zoom != initialZoom ) {
169- Gdip . Matrix_delete ( entry .getValue ());
172+ entry .getValue (). destroy ( );
170173 return true ;
171174 }
172175 return false ;
@@ -191,10 +194,12 @@ public void getElements(float[] elements) {
191194 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
192195 if (elements == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
193196 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 );
195199 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 );
198203}
199204
200205/**
@@ -209,7 +214,9 @@ public void getElements(float[] elements) {
209214 */
210215public void identity () {
211216 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 ));
213220}
214221
215222/**
@@ -223,7 +230,7 @@ public void identity() {
223230 */
224231public void invert () {
225232 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 () );
227234}
228235
229236/**
@@ -238,7 +245,7 @@ public void invert() {
238245 */
239246@ Override
240247public boolean isDisposed () {
241- return zoomLevelToHandle .isEmpty ();
248+ return zoomToHandle .isEmpty ();
242249}
243250
244251/**
@@ -249,7 +256,8 @@ public boolean isDisposed() {
249256 */
250257public boolean isIdentity () {
251258 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 );
253261}
254262
255263/**
@@ -271,7 +279,7 @@ public void multiply(Transform matrix) {
271279 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
272280 if (matrix == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
273281 if (matrix .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
274- Gdip . Matrix_Multiply ( getHandle ( initialZoom ), matrix . getHandle ( initialZoom ), Gdip . MatrixOrderPrepend );
282+ storeAndApplyOperationForAllHandles ( new MultiplayOperation ( matrix ) );
275283}
276284
277285/**
@@ -289,7 +297,7 @@ public void multiply(Transform matrix) {
289297 */
290298public void rotate (float angle ) {
291299 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
292- Gdip . Matrix_Rotate ( getHandle ( initialZoom ), angle , Gdip . MatrixOrderPrepend );
300+ storeAndApplyOperationForAllHandles ( new RotateOperation ( angle ) );
293301}
294302
295303/**
@@ -305,7 +313,7 @@ public void rotate(float angle) {
305313 */
306314public void scale (float scaleX , float scaleY ) {
307315 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
308- Gdip . Matrix_Scale ( getHandle ( initialZoom ), scaleX , scaleY , Gdip . MatrixOrderPrepend );
316+ storeAndApplyOperationForAllHandles ( new ScaleOperation ( scaleX , scaleY ) );
309317}
310318
311319/**
@@ -325,8 +333,9 @@ public void scale(float scaleX, float scaleY) {
325333 */
326334public void setElements (float m11 , float m12 , float m21 , float m22 , float dx , float dy ) {
327335 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 ));
330339}
331340
332341/**
@@ -344,7 +353,7 @@ public void setElements(float m11, float m12, float m21, float m22, float dx, fl
344353 */
345354public void shear (float shearX , float shearY ) {
346355 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
347- Gdip . Matrix_Shear ( getHandle ( initialZoom ), shearX , shearY , Gdip . MatrixOrderPrepend );
356+ storeAndApplyOperationForAllHandles ( new ShearOperation ( shearX , shearY ) );
348357}
349358
350359/**
@@ -364,14 +373,15 @@ public void shear(float shearX, float shearY) {
364373public void transform (float [] pointArray ) {
365374 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
366375 if (pointArray == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
367- int length = pointArray .length ;
368376 Drawable drawable = getDevice ();
377+ TransformHandle transformHandle = getTransformHandle (initialZoom );
378+ int length = pointArray .length ;
369379 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 );
371381 }
372- Gdip .Matrix_TransformPoints (getHandle ( initialZoom ) , pointArray , length / 2 );
382+ Gdip .Matrix_TransformPoints (transformHandle . handle , pointArray , length / 2 );
373383 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 );
375385 }
376386}
377387
@@ -388,8 +398,107 @@ public void transform(float[] pointArray) {
388398 */
389399public void translate (float offsetX , float offsetY ) {
390400 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 record MultiplayOperation (Transform matrix ) implements Operation {
419+ @ Override
420+ public void apply (TransformHandle transformHandle ) {
421+ long handle = transformHandle .handle ;
422+ int zoom = transformHandle .zoom ;
423+ Gdip .Matrix_Multiply (handle , matrix .getHandle (zoom ), Gdip .MatrixOrderPrepend );
424+ }
425+ }
426+
427+ private record RotateOperation (float angle ) implements Operation {
428+ @ Override
429+ public void apply (TransformHandle transformHandle ) {
430+ long handle = transformHandle .handle ;
431+ Gdip .Matrix_Rotate (handle , angle , Gdip .MatrixOrderPrepend );
432+ }
433+ }
434+
435+ private record ScaleOperation (float scaleX , float scaleY ) implements Operation {
436+ @ Override
437+ public void apply (TransformHandle transformHandle ) {
438+ long handle = transformHandle .handle ;
439+ Gdip .Matrix_Scale (handle , scaleX , scaleY , Gdip .MatrixOrderPrepend );
440+ }
441+ }
442+
443+ private class SetElementsOperation implements Operation {
444+ private final float m11 ;
445+ private final float m12 ;
446+ private final float m21 ;
447+ private final float m22 ;
448+ private final float dx ;
449+ private final float dy ;
450+
451+ public SetElementsOperation (float m11 , float m12 , float m21 , float m22 , float dx , float dy ) {
452+ this .m11 = m11 ;
453+ this .m12 = m12 ;
454+ this .m21 = m21 ;
455+ this .m22 = m22 ;
456+ this .dx = dx ;
457+ this .dy = dy ;
458+ }
459+
460+ @ Override
461+ public void apply (TransformHandle transformHandle ) {
462+ Drawable drawable = getDevice ();
463+ long handle = transformHandle .handle ;
464+ int zoom = transformHandle .zoom ;
465+ Gdip .Matrix_SetElements (handle , m11 , m12 , m21 , m22 , DPIUtil .scaleUp (drawable , dx , zoom ), DPIUtil .scaleUp (drawable , dy , zoom ));
466+ }
467+ }
468+
469+ private record ShearOperation (float shearX , float shearY ) implements Operation {
470+ @ Override
471+ public void apply (TransformHandle transformHandle ) {
472+ long handle = transformHandle .handle ;
473+ Gdip .Matrix_Shear (handle , shearX , shearY , Gdip .MatrixOrderPrepend );
474+ }
475+ }
476+
477+ private class TranslateOperation implements Operation {
478+ private final float offsetX ;
479+ private final float offsetY ;
480+
481+ public TranslateOperation (float offsetX , float offsetY ) {
482+ this .offsetX = offsetX ;
483+ this .offsetY = offsetY ;
484+ }
485+
486+ @ Override
487+ public void apply (TransformHandle transformHandle ) {
488+ Drawable drawable = getDevice ();
489+ long handle = transformHandle .handle ;
490+ int zoom = transformHandle .zoom ;
491+ Gdip .Matrix_Translate (handle , DPIUtil .scaleUp (drawable , offsetX , zoom ), DPIUtil .scaleUp (drawable , offsetY , zoom ), Gdip .MatrixOrderPrepend );
492+ }
493+ }
494+
495+ private interface Operation {
496+ void apply (TransformHandle transformHandle );
497+ }
498+
499+ private void storeAndApplyOperationForAllHandles (Operation operation ) {
500+ operations .add (operation );
501+ zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle ));
393502}
394503
395504/**
@@ -405,17 +514,21 @@ public String toString() {
405514 getElements (elements );
406515 return "Transform {" + elements [0 ] + "," + elements [1 ] + "," +elements [2 ] + "," +elements [3 ] + "," +elements [4 ] + "," +elements [5 ] + "}" ;
407516}
408-
409- long getHandle (int zoomLevel ) {
410- if (zoomLevelToHandle .get (zoomLevel ) == null ) {
517+ private TransformHandle getTransformHandle (int zoom ) {
518+ if (zoomToHandle .get (zoom ) == null ) {
411519 float [] elements = new float [6 ];
412520 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 ]));
521+ elements [4 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [4 ], initialZoom ), zoom );
522+ elements [5 ] = DPIUtil .scaleUp (device , DPIUtil .scaleDown (device , elements [5 ], initialZoom ), zoom );
523+ long handle = Gdip .Matrix_new (elements [0 ], elements [1 ], elements [2 ], elements [3 ], elements [4 ], elements [5 ]);
524+ TransformHandle transformHandle = new TransformHandle (handle , zoom );
525+ zoomToHandle .put (zoom , transformHandle );
526+ return transformHandle ;
417527 }
418- return zoomLevelToHandle .get (zoomLevel );
528+ return zoomToHandle .get (zoom );
419529}
420530
531+ long getHandle (int zoomLevel ) {
532+ return getTransformHandle (zoomLevel ).handle ;
533+ }
421534}
0 commit comments