37
37
*/
38
38
public final class Region extends Resource {
39
39
40
- private int initialZoom ;
41
-
42
- private HashMap <Integer , Long > zoomToHandle = new HashMap <>();
40
+ private Map <Integer , RegionHandle > zoomToHandle = new HashMap <>();
43
41
44
42
private List <Operation > operations = new ArrayList <>();
45
43
44
+ private boolean isDestroyed ;
45
+
46
46
/**
47
47
* Constructs a new empty region.
48
48
* <p>
@@ -80,9 +80,6 @@ public Region () {
80
80
*/
81
81
public Region (Device device ) {
82
82
super (device );
83
- initialZoom = DPIUtil .getDeviceZoom ();
84
- long handle = newEmptyRegionHandle ();
85
- zoomToHandle .put (initialZoom , handle );
86
83
init ();
87
84
this .device .registerResourceWithZoomSupport (this );
88
85
}
@@ -173,8 +170,10 @@ public void add (Region region) {
173
170
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
174
171
if (region == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
175
172
if (region .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
176
- final Operation operation = new OperationWithRegion (Operation ::add , region );
177
- storeAndApplyOperationForAllHandles (operation );
173
+ if (!region .operations .isEmpty ()) {
174
+ final Operation operation = new OperationWithRegion (Operation ::add , region .operations );
175
+ storeAndApplyOperationForAllHandles (operation );
176
+ }
178
177
}
179
178
180
179
/**
@@ -192,11 +191,16 @@ public void add (Region region) {
192
191
*/
193
192
public boolean contains (int x , int y ) {
194
193
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
195
- return containsInPixels (DPIUtil .scaleUp (x , initialZoom ), DPIUtil .scaleUp (y , initialZoom ));
194
+ return applyUsingAnyHandle (regionHandle -> {
195
+ int zoom = regionHandle .zoom ();
196
+ int xInPixels = DPIUtil .scaleUp (x , zoom );
197
+ int yInPixels = DPIUtil .scaleUp (y , zoom );
198
+ return containsInPixels (regionHandle .handle (), xInPixels , yInPixels );
199
+ });
196
200
}
197
201
198
- boolean containsInPixels (int x , int y ) {
199
- return OS .PtInRegion (getHandleForInitialZoom () , x , y );
202
+ boolean containsInPixels (long handle , int x , int y ) {
203
+ return OS .PtInRegion (handle , x , y );
200
204
}
201
205
202
206
/**
@@ -217,24 +221,28 @@ boolean containsInPixels (int x, int y) {
217
221
public boolean contains (Point pt ) {
218
222
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
219
223
if (pt == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
220
- Point p = DPIUtil .scaleUp (pt , initialZoom );
221
- return containsInPixels (p .x , p .y );
224
+ return applyUsingAnyHandle (regionHandle -> {
225
+ int zoom = regionHandle .zoom ();
226
+ Point p = DPIUtil .scaleUp (pt , zoom );
227
+ return containsInPixels (regionHandle .handle (), p .x , p .y );
228
+ });
222
229
}
223
230
224
231
@ Override
225
232
void destroy () {
226
233
device .deregisterResourceWithZoomSupport (this );
227
- zoomToHandle .values ().forEach (handle -> OS . DeleteObject ( handle ) );
234
+ zoomToHandle .values ().forEach (RegionHandle :: destroy );
228
235
zoomToHandle .clear ();
229
236
operations .clear ();
237
+ this .isDestroyed = true ;
230
238
}
231
239
232
240
@ Override
233
241
void destroyHandlesExcept (Set <Integer > zoomLevels ) {
234
242
zoomToHandle .entrySet ().removeIf (entry -> {
235
243
final Integer zoom = entry .getKey ();
236
- if (!zoomLevels .contains (zoom ) && zoom != initialZoom ) {
237
- OS . DeleteObject ( entry .getValue ());
244
+ if (!zoomLevels .contains (zoom )) {
245
+ entry .getValue (). destroy ( );
238
246
return true ;
239
247
}
240
248
return false ;
@@ -271,12 +279,14 @@ public boolean equals (Object object) {
271
279
*/
272
280
public Rectangle getBounds () {
273
281
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
274
- return DPIUtil .scaleDown (getBoundsInPixels (), initialZoom );
282
+ return applyUsingAnyHandle (regionHandle -> {
283
+ return DPIUtil .scaleDown (getBoundsInPixels (regionHandle .handle ()), regionHandle .zoom ());
284
+ });
275
285
}
276
286
277
- Rectangle getBoundsInPixels () {
287
+ private Rectangle getBoundsInPixels (long handle ) {
278
288
RECT rect = new RECT ();
279
- OS .GetRgnBox (getHandleForInitialZoom () , rect );
289
+ OS .GetRgnBox (handle , rect );
280
290
return new Rectangle (rect .left , rect .top , rect .right - rect .left , rect .bottom - rect .top );
281
291
}
282
292
@@ -294,7 +304,6 @@ Rectangle getBoundsInPixels() {
294
304
public int hashCode () {
295
305
return super .hashCode ();
296
306
}
297
-
298
307
/**
299
308
* Intersects the given rectangle to the collection of polygons
300
309
* the receiver maintains to describe its area.
@@ -363,8 +372,10 @@ public void intersect (Region region) {
363
372
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
364
373
if (region == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
365
374
if (region .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
366
- final Operation operation = new OperationWithRegion (Operation ::intersect , region );
367
- storeAndApplyOperationForAllHandles (operation );
375
+ if (!region .operations .isEmpty ()) {
376
+ final Operation operation = new OperationWithRegion (Operation ::intersect , region .operations );
377
+ storeAndApplyOperationForAllHandles (operation );
378
+ }
368
379
}
369
380
370
381
/**
@@ -389,10 +400,10 @@ public boolean intersects (int x, int y, int width, int height) {
389
400
return intersects (new Rectangle (x , y , width , height ));
390
401
}
391
402
392
- boolean intersectsInPixels (int x , int y , int width , int height ) {
403
+ boolean intersectsInPixels (long handle , int x , int y , int width , int height ) {
393
404
RECT r = new RECT ();
394
405
OS .SetRect (r , x , y , x + width , y + height );
395
- return OS .RectInRegion ( getHandleForInitialZoom () , r );
406
+ return OS .RectInRegion ( handle , r );
396
407
}
397
408
398
409
/**
@@ -415,8 +426,10 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
415
426
public boolean intersects (Rectangle rect ) {
416
427
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
417
428
if (rect == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
418
- Rectangle r = DPIUtil .scaleUp (rect , initialZoom );
419
- return intersectsInPixels (r .x , r .y , r .width , r .height );
429
+ return applyUsingAnyHandle (regionHandle -> {
430
+ Rectangle r = DPIUtil .scaleUp (rect , regionHandle .zoom ());
431
+ return intersectsInPixels (regionHandle .handle (), r .x , r .y , r .width , r .height );
432
+ });
420
433
}
421
434
422
435
/**
@@ -431,7 +444,7 @@ public boolean intersects (Rectangle rect) {
431
444
*/
432
445
@ Override
433
446
public boolean isDisposed () {
434
- return zoomToHandle . isEmpty () ;
447
+ return isDestroyed ;
435
448
}
436
449
437
450
/**
@@ -448,9 +461,11 @@ public boolean isDisposed() {
448
461
public boolean isEmpty () {
449
462
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
450
463
RECT rect = new RECT ();
451
- int result = OS .GetRgnBox (getHandleForInitialZoom (), rect );
452
- if (result == OS .NULLREGION ) return true ;
453
- return ((rect .right - rect .left ) <= 0 ) || ((rect .bottom - rect .top ) <= 0 );
464
+ return applyUsingAnyHandle (regionHandle -> {
465
+ int result = OS .GetRgnBox (regionHandle .handle (), rect );
466
+ if (result == OS .NULLREGION ) return true ;
467
+ return ((rect .right - rect .left ) <= 0 ) || ((rect .bottom - rect .top ) <= 0 );
468
+ });
454
469
}
455
470
456
471
/**
@@ -543,8 +558,10 @@ public void subtract (Region region) {
543
558
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
544
559
if (region == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
545
560
if (region .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
546
- final Operation operation = new OperationWithRegion (Operation ::subtract , region );
547
- storeAndApplyOperationForAllHandles (operation );
561
+ if (!region .operations .isEmpty ()) {
562
+ final Operation operation = new OperationWithRegion (Operation ::subtract , region .operations );
563
+ storeAndApplyOperationForAllHandles (operation );
564
+ }
548
565
}
549
566
550
567
/**
@@ -588,36 +605,43 @@ public void translate (Point pt) {
588
605
storeAndApplyOperationForAllHandles (operation );
589
606
}
590
607
591
- private long getHandleForInitialZoom () {
592
- return win32_getHandle (this , initialZoom );
593
- }
594
-
595
608
private void storeAndApplyOperationForAllHandles (Operation operation ) {
596
609
operations .add (operation );
597
- zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle , zoom ));
610
+ zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle ));
611
+ }
612
+
613
+ private <T > T applyUsingAnyHandle (Function <RegionHandle , T > function ) {
614
+ if (zoomToHandle .isEmpty ()) {
615
+ return applyUsingTemporaryHandle (device .getDeviceZoom (), operations , function );
616
+ }
617
+ return function .apply (zoomToHandle .values ().iterator ().next ());
598
618
}
599
619
600
- private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <Long , T > function ) {
601
- long temporaryHandle = newRegionHandle (operations , zoom );
620
+ private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <RegionHandle , T > function ) {
621
+ RegionHandle temporaryHandle = newRegionHandle (zoom , operations );
602
622
try {
603
623
return function .apply (temporaryHandle );
604
624
} finally {
605
- OS . DeleteObject ( temporaryHandle );
625
+ temporaryHandle . destroy ( );
606
626
}
607
627
}
608
628
609
- private static long newEmptyRegionHandle ( ) {
629
+ private static RegionHandle newRegionHandle ( int zoom , List < Operation > operations ) {
610
630
long newHandle = OS .CreateRectRgn (0 , 0 , 0 , 0 );
611
631
if (newHandle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
612
- return newHandle ;
632
+ RegionHandle newRegionHandle = new RegionHandle (newHandle , zoom );
633
+ for (Operation operation : operations ) {
634
+ operation .apply (newRegionHandle );
635
+ }
636
+ return newRegionHandle ;
613
637
}
614
638
615
- private static long newRegionHandle ( List < Operation > operations , int zoom ) {
616
- long newHandle = newEmptyRegionHandle ();
617
- for ( Operation operation : operations ) {
618
- operation . apply ( newHandle , zoom );
639
+ private RegionHandle getRegionHandle ( int zoom ) {
640
+ if (! zoomToHandle . containsKey ( zoom )) {
641
+ RegionHandle regionHandle = newRegionHandle ( zoom , operations );
642
+ zoomToHandle . put ( zoom , regionHandle );
619
643
}
620
- return newHandle ;
644
+ return zoomToHandle . get ( zoom ) ;
621
645
}
622
646
623
647
/**
@@ -638,14 +662,7 @@ private static long newRegionHandle(List<Operation> operations, int zoom) {
638
662
* @noreference This method is not intended to be referenced by clients.
639
663
*/
640
664
public static long win32_getHandle (Region region , int zoom ) {
641
- if (!region .zoomToHandle .containsKey (zoom )) {
642
- long handle = newEmptyRegionHandle ();
643
- for (Operation operation : region .operations ) {
644
- operation .apply (handle , zoom );
645
- }
646
- region .zoomToHandle .put (zoom , handle );
647
- }
648
- return region .zoomToHandle .get (zoom );
665
+ return region .getRegionHandle (zoom ).handle ();
649
666
}
650
667
651
668
/**
@@ -660,20 +677,26 @@ public String toString () {
660
677
return "Region {" + zoomToHandle .entrySet ().stream ().map (entry -> entry .getValue () + "(zoom:" + entry .getKey () + ")" ).collect (Collectors .joining ("," ));
661
678
}
662
679
680
+ private record RegionHandle (long handle , int zoom ) {
681
+ void destroy () {
682
+ OS .DeleteObject (handle ());
683
+ }
684
+ }
685
+
663
686
@ FunctionalInterface
664
687
private interface OperationStrategy {
665
688
void apply (Operation operation , long handle , int zoom );
666
689
}
667
690
668
691
private abstract static class Operation {
669
- private OperationStrategy operationStrategy ;
692
+ private final OperationStrategy operationStrategy ;
670
693
671
694
Operation (OperationStrategy operationStrategy ) {
672
695
this .operationStrategy = operationStrategy ;
673
696
}
674
697
675
- void apply (long handle , int zoom ) {
676
- operationStrategy .apply (this , handle , zoom );
698
+ void apply (RegionHandle regionHandle ) {
699
+ operationStrategy .apply (this , regionHandle . handle (), regionHandle . zoom () );
677
700
}
678
701
679
702
abstract void add (long handle , int zoom );
@@ -686,8 +709,7 @@ void apply(long handle, int zoom) {
686
709
}
687
710
688
711
private static class OperationWithRectangle extends Operation {
689
-
690
- Rectangle data ;
712
+ private final Rectangle data ;
691
713
692
714
OperationWithRectangle (OperationStrategy operationStrategy , Rectangle data ) {
693
715
super (operationStrategy );
@@ -745,8 +767,7 @@ private Rectangle getScaledRectangle(int zoom) {
745
767
}
746
768
747
769
private static class OperationWithArray extends Operation {
748
-
749
- int [] data ;
770
+ private final int [] data ;
750
771
751
772
public OperationWithArray (OperationStrategy operationStrategy , int [] data ) {
752
773
super (operationStrategy );
@@ -793,8 +814,7 @@ private int[] getScaledPoints(int zoom) {
793
814
}
794
815
795
816
private static class OperationWithPoint extends Operation {
796
-
797
- Point data ;
817
+ private final Point data ;
798
818
799
819
public OperationWithPoint (OperationStrategy operationStrategy , Point data ) {
800
820
super (operationStrategy );
@@ -827,29 +847,29 @@ void translate(long handle, int zoom) {
827
847
private static class OperationWithRegion extends Operation {
828
848
private final List <Operation > operations ;
829
849
830
- OperationWithRegion (OperationStrategy operationStrategy , Region data ) {
850
+ OperationWithRegion (OperationStrategy operationStrategy , List < Operation > operations ) {
831
851
super (operationStrategy );
832
- this .operations = data . operations ;
852
+ this .operations = List . copyOf ( operations ) ;
833
853
}
834
854
835
855
@ Override
836
856
void add (long handle , int zoom ) {
837
857
applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
838
- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_OR );
858
+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_OR );
839
859
});
840
860
}
841
861
842
862
@ Override
843
863
void subtract (long handle , int zoom ) {
844
864
applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
845
- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_DIFF );
865
+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_DIFF );
846
866
});
847
867
}
848
868
849
869
@ Override
850
870
void intersect (long handle , int zoom ) {
851
871
applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
852
- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_AND );
872
+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_AND );
853
873
});
854
874
}
855
875
0 commit comments