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,43 @@ 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+ }
610+ return function .apply (zoomToHandle .values ().iterator ().next ());
598611}
599612
600- private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <Long , T > function ) {
601- long temporaryHandle = newRegionHandle (operations , zoom );
613+ private static <T > T applyUsingTemporaryHandle (int zoom , List <Operation > operations , Function <RegionHandle , T > function ) {
614+ RegionHandle temporaryHandle = newRegionHandle (zoom , operations );
602615 try {
603616 return function .apply (temporaryHandle );
604617 } finally {
605- OS . DeleteObject ( temporaryHandle );
618+ temporaryHandle . destroy ( );
606619 }
607620}
608621
609- private static long newEmptyRegionHandle ( ) {
622+ private static RegionHandle newRegionHandle ( int zoom , List < Operation > operations ) {
610623 long newHandle = OS .CreateRectRgn (0 , 0 , 0 , 0 );
611624 if (newHandle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
612- return newHandle ;
625+ RegionHandle newRegionHandle = new RegionHandle (newHandle , zoom );
626+ for (Operation operation : operations ) {
627+ operation .apply (newRegionHandle );
628+ }
629+ return newRegionHandle ;
613630}
614631
615- private static long newRegionHandle ( List < Operation > operations , int zoom ) {
616- long newHandle = newEmptyRegionHandle ();
617- for ( Operation operation : operations ) {
618- operation . apply ( newHandle , zoom );
632+ private RegionHandle getRegionHandle ( int zoom ) {
633+ if (! zoomToHandle . containsKey ( zoom )) {
634+ RegionHandle regionHandle = newRegionHandle ( zoom , operations );
635+ zoomToHandle . put ( zoom , regionHandle );
619636 }
620- return newHandle ;
637+ return zoomToHandle . get ( zoom ) ;
621638}
622639
623640/**
@@ -638,14 +655,7 @@ private static long newRegionHandle(List<Operation> operations, int zoom) {
638655 * @noreference This method is not intended to be referenced by clients.
639656 */
640657public 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 );
658+ return region .getRegionHandle (zoom ).handle ();
649659}
650660
651661/**
@@ -660,20 +670,26 @@ public String toString () {
660670 return "Region {" + zoomToHandle .entrySet ().stream ().map (entry -> entry .getValue () + "(zoom:" + entry .getKey () + ")" ).collect (Collectors .joining ("," ));
661671}
662672
673+ private record RegionHandle (long handle , int zoom ) {
674+ void destroy () {
675+ OS .DeleteObject (handle ());
676+ }
677+ }
678+
663679@ FunctionalInterface
664680private interface OperationStrategy {
665681 void apply (Operation operation , long handle , int zoom );
666682}
667683
668684private abstract static class Operation {
669- private OperationStrategy operationStrategy ;
685+ private final OperationStrategy operationStrategy ;
670686
671687 Operation (OperationStrategy operationStrategy ) {
672688 this .operationStrategy = operationStrategy ;
673689 }
674690
675- void apply (long handle , int zoom ) {
676- operationStrategy .apply (this , handle , zoom );
691+ void apply (RegionHandle regionHandle ) {
692+ operationStrategy .apply (this , regionHandle . handle (), regionHandle . zoom () );
677693 }
678694
679695 abstract void add (long handle , int zoom );
@@ -686,8 +702,7 @@ void apply(long handle, int zoom) {
686702}
687703
688704private static class OperationWithRectangle extends Operation {
689-
690- Rectangle data ;
705+ private final Rectangle data ;
691706
692707 OperationWithRectangle (OperationStrategy operationStrategy , Rectangle data ) {
693708 super (operationStrategy );
@@ -745,8 +760,7 @@ private Rectangle getScaledRectangle(int zoom) {
745760}
746761
747762private static class OperationWithArray extends Operation {
748-
749- int [] data ;
763+ private final int [] data ;
750764
751765 public OperationWithArray (OperationStrategy operationStrategy , int [] data ) {
752766 super (operationStrategy );
@@ -793,8 +807,7 @@ private int[] getScaledPoints(int zoom) {
793807}
794808
795809private static class OperationWithPoint extends Operation {
796-
797- Point data ;
810+ private final Point data ;
798811
799812 public OperationWithPoint (OperationStrategy operationStrategy , Point data ) {
800813 super (operationStrategy );
@@ -835,21 +848,21 @@ private static class OperationWithRegion extends Operation {
835848 @ Override
836849 void add (long handle , int zoom ) {
837850 applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
838- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_OR );
851+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_OR );
839852 });
840853 }
841854
842855 @ Override
843856 void subtract (long handle , int zoom ) {
844857 applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
845- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_DIFF );
858+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_DIFF );
846859 });
847860 }
848861
849862 @ Override
850863 void intersect (long handle , int zoom ) {
851864 applyUsingTemporaryHandle (zoom , operations , regionHandle -> {
852- return OS .CombineRgn (handle , handle , regionHandle , OS .RGN_AND );
865+ return OS .CombineRgn (handle , handle , regionHandle . handle () , OS .RGN_AND );
853866 });
854867 }
855868
0 commit comments