3737 */
3838public final class Region extends Resource {
3939
40- private int initialZoom ;
41-
42- private HashMap <Integer , Long > zoomToHandle = new HashMap <>();
40+ private Map <Integer , RegionHandle > zoomToHandle = new HashMap <>();
4341
4442 private List <Operation > operations = new ArrayList <>();
4543
44+ private boolean isDestroyed ;
45+
4646/**
4747 * Constructs a new empty region.
4848 * <p>
@@ -80,9 +80,6 @@ public Region () {
8080 */
8181public Region (Device device ) {
8282 super (device );
83- initialZoom = DPIUtil .getDeviceZoom ();
84- long handle = newEmptyRegionHandle ();
85- zoomToHandle .put (initialZoom , handle );
8683 init ();
8784 this .device .registerResourceWithZoomSupport (this );
8885}
@@ -192,11 +189,16 @@ public void add (Region region) {
192189 */
193190public boolean contains (int x , int y ) {
194191 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
195- return containsInPixels (DPIUtil .scaleUp (x , initialZoom ), DPIUtil .scaleUp (y , initialZoom ));
192+ return applyUsingAnyHandle (regionHandle -> {
193+ int zoom = regionHandle .zoom ;
194+ int xInPixels = DPIUtil .scaleUp (x , zoom );
195+ int yInPixels = DPIUtil .scaleUp (y , zoom );
196+ return containsInPixels (regionHandle .handle , xInPixels , yInPixels );
197+ });
196198}
197199
198- boolean containsInPixels (int x , int y ) {
199- return OS .PtInRegion (getHandleForInitialZoom () , x , y );
200+ boolean containsInPixels (long handle , int x , int y ) {
201+ return OS .PtInRegion (handle , x , y );
200202}
201203
202204/**
@@ -217,24 +219,27 @@ boolean containsInPixels (int x, int y) {
217219public boolean contains (Point pt ) {
218220 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
219221 if (pt == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
220- Point p = DPIUtil .scaleUp (pt , initialZoom );
221- return containsInPixels (p .x , p .y );
222+ return applyUsingAnyHandle (regionHandle -> {
223+ int zoom = regionHandle .zoom ;
224+ Point p = DPIUtil .scaleUp (pt , zoom );
225+ return containsInPixels (regionHandle .handle , p .x , p .y );
226+ });
222227}
223228
224229@ Override
225230void destroy () {
226231 device .deregisterResourceWithZoomSupport (this );
227- zoomToHandle .values ().forEach (handle -> OS . DeleteObject ( handle ) );
232+ zoomToHandle .values ().forEach (RegionHandle :: destroy );
228233 zoomToHandle .clear ();
229- operations . clear () ;
234+ this . isDestroyed = true ;
230235}
231236
232237@ Override
233238void destroyHandlesExcept (Set <Integer > zoomLevels ) {
234239 zoomToHandle .entrySet ().removeIf (entry -> {
235240 final Integer zoom = entry .getKey ();
236- if (!zoomLevels .contains (zoom ) && zoom != initialZoom ) {
237- OS . DeleteObject ( entry .getValue ());
241+ if (!zoomLevels .contains (zoom )) {
242+ entry .getValue (). destroy ( );
238243 return true ;
239244 }
240245 return false ;
@@ -271,12 +276,14 @@ public boolean equals (Object object) {
271276 */
272277public Rectangle getBounds () {
273278 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
274- return DPIUtil .scaleDown (getBoundsInPixels (), initialZoom );
279+ return applyUsingAnyHandle (regionHandle -> {
280+ return DPIUtil .scaleDown (getBoundsInPixels (regionHandle .handle ), regionHandle .zoom );
281+ });
275282}
276283
277- Rectangle getBoundsInPixels () {
284+ private Rectangle getBoundsInPixels (long handle ) {
278285 RECT rect = new RECT ();
279- OS .GetRgnBox (getHandleForInitialZoom () , rect );
286+ OS .GetRgnBox (handle , rect );
280287 return new Rectangle (rect .left , rect .top , rect .right - rect .left , rect .bottom - rect .top );
281288}
282289
@@ -294,7 +301,6 @@ Rectangle getBoundsInPixels() {
294301public int hashCode () {
295302 return super .hashCode ();
296303}
297-
298304/**
299305 * Intersects the given rectangle to the collection of polygons
300306 * the receiver maintains to describe its area.
@@ -389,10 +395,10 @@ public boolean intersects (int x, int y, int width, int height) {
389395 return intersects (new Rectangle (x , y , width , height ));
390396}
391397
392- boolean intersectsInPixels (int x , int y , int width , int height ) {
398+ boolean intersectsInPixels (long handle , int x , int y , int width , int height ) {
393399 RECT r = new RECT ();
394400 OS .SetRect (r , x , y , x + width , y + height );
395- return OS .RectInRegion ( getHandleForInitialZoom () , r );
401+ return OS .RectInRegion ( handle , r );
396402}
397403
398404/**
@@ -415,8 +421,10 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
415421public boolean intersects (Rectangle rect ) {
416422 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
417423 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 );
424+ return applyUsingAnyHandle (regionHandle -> {
425+ Rectangle r = DPIUtil .scaleUp (rect , regionHandle .zoom );
426+ return intersectsInPixels (regionHandle .handle , r .x , r .y , r .width , r .height );
427+ });
420428}
421429
422430/**
@@ -431,7 +439,7 @@ public boolean intersects (Rectangle rect) {
431439 */
432440@ Override
433441public boolean isDisposed () {
434- return zoomToHandle . isEmpty () ;
442+ return isDestroyed ;
435443}
436444
437445/**
@@ -448,9 +456,11 @@ public boolean isDisposed() {
448456public boolean isEmpty () {
449457 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
450458 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 );
459+ return applyUsingAnyHandle (regionHandle -> {
460+ int result = OS .GetRgnBox (regionHandle .handle , rect );
461+ if (result == OS .NULLREGION ) return true ;
462+ return ((rect .right - rect .left ) <= 0 ) || ((rect .bottom - rect .top ) <= 0 );
463+ });
454464}
455465
456466/**
@@ -588,36 +598,44 @@ public void translate (Point pt) {
588598 storeAndApplyOperationForAllHandles (operation );
589599}
590600
591- private long getHandleForInitialZoom () {
592- return win32_getHandle (this , initialZoom );
593- }
594-
595601private void storeAndApplyOperationForAllHandles (Operation operation ) {
596602 operations .add (operation );
597- zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle , zoom ));
603+ zoomToHandle .forEach ((zoom , handle ) -> operation .apply (handle ));
604+ }
605+
606+ private <T > T applyUsingAnyHandle (Function <RegionHandle , T > function ) {
607+ if (zoomToHandle .isEmpty ()) {
608+ return applyUsingTemporaryHandle (device .getDeviceZoom (), operations , function );
609+ } else {
610+ return function .apply (zoomToHandle .values ().iterator ().next ());
611+ }
598612}
599613
600- private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <Long , T > function ) {
601- long temporaryHandle = newRegionHandle (operations , zoom );
614+ private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <RegionHandle , T > function ) {
615+ RegionHandle temporaryHandle = newRegionHandle (zoom , operations );
602616 try {
603617 return function .apply (temporaryHandle );
604618 } finally {
605- OS . DeleteObject ( temporaryHandle );
619+ temporaryHandle . destroy ( );
606620 }
607621}
608622
609- private static long newEmptyRegionHandle ( ) {
623+ private static RegionHandle newRegionHandle ( int zoom , List < Operation > operations ) {
610624 long newHandle = OS .CreateRectRgn (0 , 0 , 0 , 0 );
611625 if (newHandle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
612- return newHandle ;
626+ RegionHandle newRegionHandle = new RegionHandle (newHandle , zoom );
627+ for (Operation operation : operations ) {
628+ operation .apply (newRegionHandle );
629+ }
630+ return newRegionHandle ;
613631}
614632
615- private static long newRegionHandle ( List < Operation > operations , int zoom ) {
616- long newHandle = newEmptyRegionHandle ();
617- for ( Operation operation : operations ) {
618- operation . apply ( newHandle , zoom );
633+ private RegionHandle getRegionHandle ( int zoom ) {
634+ if (! zoomToHandle . containsKey ( zoom )) {
635+ RegionHandle regionHandle = newRegionHandle ( zoom , operations );
636+ zoomToHandle . put ( zoom , regionHandle );
619637 }
620- return newHandle ;
638+ return zoomToHandle . get ( zoom ) ;
621639}
622640
623641/**
@@ -638,14 +656,7 @@ private static long newRegionHandle(List<Operation> operations, int zoom) {
638656 * @noreference This method is not intended to be referenced by clients.
639657 */
640658public 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 );
659+ return region .getRegionHandle (zoom ).handle ;
649660}
650661
651662/**
@@ -660,20 +671,26 @@ public String toString () {
660671 return "Region {" + zoomToHandle .entrySet ().stream ().map (entry -> entry .getValue () + "(zoom:" + entry .getKey () + ")" ).collect (Collectors .joining ("," ));
661672}
662673
674+ private record RegionHandle (long handle , int zoom ) {
675+ void destroy () {
676+ OS .DeleteObject (handle );
677+ }
678+ }
679+
663680@ FunctionalInterface
664681private interface OperationStrategy {
665682 void apply (Operation operation , long handle , int zoom );
666683}
667684
668685private abstract static class Operation {
669- private OperationStrategy operationStrategy ;
686+ private final OperationStrategy operationStrategy ;
670687
671688 Operation (OperationStrategy operationStrategy ) {
672689 this .operationStrategy = operationStrategy ;
673690 }
674691
675- void apply (long handle , int zoom ) {
676- operationStrategy .apply (this , handle , zoom );
692+ void apply (RegionHandle regionHandle ) {
693+ operationStrategy .apply (this , regionHandle . handle , regionHandle . zoom );
677694 }
678695
679696 abstract void add (long handle , int zoom );
@@ -686,8 +703,7 @@ void apply(long handle, int zoom) {
686703}
687704
688705private static class OperationWithRectangle extends Operation {
689-
690- Rectangle data ;
706+ private final Rectangle data ;
691707
692708 OperationWithRectangle (OperationStrategy operationStrategy , Rectangle data ) {
693709 super (operationStrategy );
@@ -745,8 +761,7 @@ private Rectangle getScaledRectangle(int zoom) {
745761}
746762
747763private static class OperationWithArray extends Operation {
748-
749- int [] data ;
764+ private final int [] data ;
750765
751766 public OperationWithArray (OperationStrategy operationStrategy , int [] data ) {
752767 super (operationStrategy );
@@ -793,8 +808,7 @@ private int[] getScaledPoints(int zoom) {
793808}
794809
795810private static class OperationWithPoint extends Operation {
796-
797- Point data ;
811+ private final Point data ;
798812
799813 public OperationWithPoint (OperationStrategy operationStrategy , Point data ) {
800814 super (operationStrategy );
@@ -825,31 +839,31 @@ void translate(long handle, int zoom) {
825839}
826840
827841private static class OperationWithRegion extends Operation {
828- private final List <Operation > operations ;
842+ private final List <Operation > regionOperations ;
829843
830844 OperationWithRegion (OperationStrategy operationStrategy , Region data ) {
831845 super (operationStrategy );
832- this .operations = data .operations ;
846+ this .regionOperations = data .operations ;
833847 }
834848
835849 @ Override
836850 void add (long handle , int zoom ) {
837- applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
838- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_OR );
851+ applyUsingTemporaryHandle (zoom , regionOperations , regionHandle -> {
852+ return OS .CombineRgn (handle , handle , regionHandle . handle , OS .RGN_OR );
839853 });
840854 }
841855
842856 @ Override
843857 void subtract (long handle , int zoom ) {
844- applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
845- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_DIFF );
858+ applyUsingTemporaryHandle (zoom , regionOperations , regionHandle -> {
859+ return OS .CombineRgn (handle , handle , regionHandle . handle , OS .RGN_DIFF );
846860 });
847861 }
848862
849863 @ Override
850864 void intersect (long handle , int zoom ) {
851- applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
852- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_AND );
865+ applyUsingTemporaryHandle (zoom , regionOperations , regionHandle -> {
866+ return OS .CombineRgn (handle , handle , regionHandle . handle , OS .RGN_AND );
853867 });
854868 }
855869
0 commit comments