Skip to content

Commit 8dbbfc8

Browse files
committed
[win32] Dynamic handle creation for region
This commit refactors Region in the win32 implementation to better support multiple handles for different zoom settings by creating all handles only on demand.
1 parent 2974864 commit 8dbbfc8

File tree

1 file changed

+81
-67
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+81
-67
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java

Lines changed: 81 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@
3737
*/
3838
public 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
*/
8181
public 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
*/
193190
public 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) {
217219
public 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
225230
void 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
233238
void 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
*/
272277
public 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() {
294301
public 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) {
415421
public 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
433441
public boolean isDisposed() {
434-
return zoomToHandle.isEmpty();
442+
return isDestroyed;
435443
}
436444

437445
/**
@@ -448,9 +456,11 @@ public boolean isDisposed() {
448456
public 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-
595601
private 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
*/
640658
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);
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
664681
private interface OperationStrategy {
665682
void apply(Operation operation, long handle, int zoom);
666683
}
667684

668685
private 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

688705
private 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

747763
private 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

795810
private 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

827841
private 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

Comments
 (0)