Skip to content

Commit 157abd2

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 fa94196 commit 157abd2

File tree

1 file changed

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

1 file changed

+81
-69
lines changed

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

Lines changed: 81 additions & 69 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,10 +80,6 @@ public Region () {
8080
*/
8181
public Region (Device device) {
8282
super(device);
83-
initialZoom = DPIUtil.getDeviceZoom();
84-
long handle = OS.CreateRectRgn (0, 0, 0, 0);
85-
zoomToHandle.put(initialZoom, handle);
86-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
8783
init();
8884
this.device.registerResourceWithZoomSupport(this);
8985
}
@@ -193,11 +189,16 @@ public void add (Region region) {
193189
*/
194190
public boolean contains (int x, int y) {
195191
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
196-
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+
});
197198
}
198199

199-
boolean containsInPixels (int x, int y) {
200-
return OS.PtInRegion (getHandleForInitialZoom(), x, y);
200+
boolean containsInPixels (long handle, int x, int y) {
201+
return OS.PtInRegion (handle, x, y);
201202
}
202203

203204
/**
@@ -218,28 +219,26 @@ boolean containsInPixels (int x, int y) {
218219
public boolean contains (Point pt) {
219220
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
220221
if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
221-
Point p = DPIUtil.scaleUp(pt, initialZoom);
222-
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+
});
223227
}
224228

225229
@Override
226230
void destroy () {
227231
device.deregisterResourceWithZoomSupport(this);
228-
zoomToHandle.values().forEach(handle -> OS.DeleteObject(handle));
232+
zoomToHandle.values().forEach(RegionHandle::destroy);
229233
zoomToHandle.clear();
230-
operations.clear();
234+
this.isDestroyed = true;
231235
}
232236

233237
@Override
234238
void destroyHandlesExcept(Set<Integer> zoomLevels) {
235-
zoomToHandle.entrySet().removeIf(entry -> {
236-
final Integer zoom = entry.getKey();
237-
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
238-
OS.DeleteObject(entry.getValue());
239-
return true;
240-
}
241-
return false;
242-
});
239+
// As long as we keep the operations, we can cleanup all handles
240+
zoomToHandle.values().forEach(RegionHandle::destroy);
241+
zoomToHandle.clear();
243242
}
244243

245244
/**
@@ -272,12 +271,14 @@ public boolean equals (Object object) {
272271
*/
273272
public Rectangle getBounds () {
274273
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
275-
return DPIUtil.scaleDown(getBoundsInPixels(), initialZoom);
274+
return applyUsingAnyHandle(regionHandle -> {
275+
return DPIUtil.scaleDown(getBoundsInPixels(regionHandle.handle), regionHandle.zoom);
276+
});
276277
}
277278

278-
Rectangle getBoundsInPixels() {
279+
private Rectangle getBoundsInPixels(long handle) {
279280
RECT rect = new RECT();
280-
OS.GetRgnBox(getHandleForInitialZoom(), rect);
281+
OS.GetRgnBox(handle, rect);
281282
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
282283
}
283284

@@ -295,7 +296,6 @@ Rectangle getBoundsInPixels() {
295296
public int hashCode () {
296297
return super.hashCode();
297298
}
298-
299299
/**
300300
* Intersects the given rectangle to the collection of polygons
301301
* the receiver maintains to describe its area.
@@ -390,10 +390,10 @@ public boolean intersects (int x, int y, int width, int height) {
390390
return intersects(new Rectangle(x, y, width, height));
391391
}
392392

393-
boolean intersectsInPixels (int x, int y, int width, int height) {
393+
boolean intersectsInPixels (long handle, int x, int y, int width, int height) {
394394
RECT r = new RECT ();
395395
OS.SetRect (r, x, y, x + width, y + height);
396-
return OS.RectInRegion (getHandleForInitialZoom(), r);
396+
return OS.RectInRegion(handle, r);
397397
}
398398

399399
/**
@@ -416,8 +416,10 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
416416
public boolean intersects (Rectangle rect) {
417417
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
418418
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
419-
Rectangle r = DPIUtil.scaleUp(rect, initialZoom);
420-
return intersectsInPixels(r.x, r.y, r.width, r.height);
419+
return applyUsingAnyHandle(regionHandle -> {
420+
Rectangle r = DPIUtil.scaleUp(rect, regionHandle.zoom);
421+
return intersectsInPixels(regionHandle.handle, r.x, r.y, r.width, r.height);
422+
});
421423
}
422424

423425
/**
@@ -432,7 +434,7 @@ public boolean intersects (Rectangle rect) {
432434
*/
433435
@Override
434436
public boolean isDisposed() {
435-
return zoomToHandle.isEmpty();
437+
return isDestroyed;
436438
}
437439

438440
/**
@@ -449,9 +451,11 @@ public boolean isDisposed() {
449451
public boolean isEmpty () {
450452
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
451453
RECT rect = new RECT ();
452-
int result = OS.GetRgnBox (getHandleForInitialZoom(), rect);
453-
if (result == OS.NULLREGION) return true;
454-
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
454+
return applyUsingAnyHandle(regionHandle -> {
455+
int result = OS.GetRgnBox(regionHandle.handle, rect);
456+
if (result == OS.NULLREGION) return true;
457+
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
458+
});
455459
}
456460

457461
/**
@@ -589,36 +593,48 @@ public void translate (Point pt) {
589593
storeAndApplyOperationForAllHandles(operation);
590594
}
591595

592-
private long getHandleForInitialZoom() {
593-
return win32_getHandle(this, initialZoom);
594-
}
595-
596596
private void storeAndApplyOperationForAllHandles(Operation operation) {
597597
operations.add(operation);
598-
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle, zoom));
598+
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle));
599+
}
600+
601+
private <T> T applyUsingAnyHandle(Function<RegionHandle, T> function) {
602+
if (zoomToHandle.isEmpty()) {
603+
return applyUsingTemporaryHandle(device.getDeviceZoom(), operations, function);
604+
} else {
605+
return function.apply(zoomToHandle.values().iterator().next());
606+
}
599607
}
600608

601-
private static <T> T applyUsingTemporaryHandle(int zoom, List<Operation> operations, Function<Long, T> function) {
602-
long temporaryHandle = newRegionHandle(operations, zoom);
609+
private static <T> T applyUsingTemporaryHandle(int zoom, List<Operation> operations, Function<RegionHandle, T> function) {
610+
RegionHandle temporaryHandle = newRegionHandle(zoom, operations);
603611
try {
604612
return function.apply(temporaryHandle);
605613
} finally {
606-
OS.DeleteObject(temporaryHandle);
614+
temporaryHandle.destroy();
607615
}
608616
}
609617

610-
private static long newEmptyRegionHandle() {
618+
private static RegionHandle newRegionHandle(int zoom, List<Operation> operations) {
619+
RegionHandle newHandle = newEmptyRegionHandle(zoom);
620+
for (Operation operation : operations) {
621+
operation.apply(newHandle);
622+
}
623+
return newHandle;
624+
}
625+
626+
private static RegionHandle newEmptyRegionHandle(int zoom) {
611627
long newHandle = OS.CreateRectRgn (0, 0, 0, 0);
612628
if (newHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
613-
return newHandle;
629+
return new RegionHandle(newHandle, zoom);
614630
}
615631

616-
private static long newRegionHandle(List<Operation> operations, int zoom) {
617-
long newHandle = newEmptyRegionHandle();
618-
for (Operation operation : operations) {
619-
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);
620636
}
621-
return newHandle;
637+
return zoomToHandle.get(zoom);
622638
}
623639

624640
/**
@@ -639,14 +655,7 @@ private static long newRegionHandle(List<Operation> operations, int zoom) {
639655
* @noreference This method is not intended to be referenced by clients.
640656
*/
641657
public static long win32_getHandle(Region region, int zoom) {
642-
if (!region.zoomToHandle.containsKey(zoom)) {
643-
long handle = newEmptyRegionHandle();
644-
for (Operation operation : region.operations) {
645-
operation.apply(handle, zoom);
646-
}
647-
region.zoomToHandle.put(zoom, handle);
648-
}
649-
return region.zoomToHandle.get(zoom);
658+
return region.getRegionHandle(zoom).handle;
650659
}
651660

652661
/**
@@ -661,20 +670,26 @@ public String toString () {
661670
return "Region {" + zoomToHandle.entrySet().stream().map(entry -> entry.getValue() + "(zoom:" + entry.getKey() + ")").collect(Collectors.joining(","));
662671
}
663672

673+
private record RegionHandle(long handle, int zoom) {
674+
void destroy() {
675+
OS.DeleteObject(handle);
676+
}
677+
}
678+
664679
@FunctionalInterface
665680
private interface OperationStrategy {
666681
void apply(Operation operation, long handle, int zoom);
667682
}
668683

669684
private abstract static class Operation {
670-
private OperationStrategy operationStrategy;
685+
private final OperationStrategy operationStrategy;
671686

672687
Operation(OperationStrategy operationStrategy) {
673688
this.operationStrategy = operationStrategy;
674689
}
675690

676-
void apply(long handle, int zoom) {
677-
operationStrategy.apply(this, handle, zoom);
691+
void apply(RegionHandle regionHandle) {
692+
operationStrategy.apply(this, regionHandle.handle, regionHandle.zoom);
678693
}
679694

680695
abstract void add(long handle, int zoom);
@@ -687,8 +702,7 @@ void apply(long handle, int zoom) {
687702
}
688703

689704
private static class OperationWithRectangle extends Operation {
690-
691-
Rectangle data;
705+
private final Rectangle data;
692706

693707
OperationWithRectangle(OperationStrategy operationStrategy, Rectangle data) {
694708
super(operationStrategy);
@@ -746,8 +760,7 @@ private Rectangle getScaledRectangle(int zoom) {
746760
}
747761

748762
private static class OperationWithArray extends Operation {
749-
750-
int[] data;
763+
private final int[] data;
751764

752765
public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
753766
super(operationStrategy);
@@ -794,8 +807,7 @@ private int[] getScaledPoints(int zoom) {
794807
}
795808

796809
private static class OperationWithPoint extends Operation {
797-
798-
Point data;
810+
private final Point data;
799811

800812
public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
801813
super(operationStrategy);
@@ -836,21 +848,21 @@ private static class OperationWithRegion extends Operation {
836848
@Override
837849
void add(long handle, int zoom) {
838850
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
839-
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_OR);
851+
return OS.CombineRgn (handle, handle, regionHandle.handle, OS.RGN_OR);
840852
});
841853
}
842854

843855
@Override
844856
void subtract(long handle, int zoom) {
845857
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
846-
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_DIFF);
858+
return OS.CombineRgn (handle, handle, regionHandle.handle, OS.RGN_DIFF);
847859
});
848860
}
849861

850862
@Override
851863
void intersect(long handle, int zoom) {
852864
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
853-
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_AND);
865+
return OS.CombineRgn (handle, handle, regionHandle.handle, OS.RGN_AND);
854866
});
855867
}
856868

0 commit comments

Comments
 (0)