Skip to content

Commit 17948a7

Browse files
akoch-yattafedejeanne
authored andcommitted
[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 971b9a6 commit 17948a7

File tree

1 file changed

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

1 file changed

+89
-69
lines changed

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

Lines changed: 89 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,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
}
@@ -173,8 +170,10 @@ public void add (Region region) {
173170
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
174171
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
175172
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+
}
178177
}
179178

180179
/**
@@ -192,11 +191,16 @@ public void add (Region region) {
192191
*/
193192
public boolean contains (int x, int y) {
194193
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+
});
196200
}
197201

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);
200204
}
201205

202206
/**
@@ -217,24 +221,28 @@ boolean containsInPixels (int x, int y) {
217221
public boolean contains (Point pt) {
218222
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
219223
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+
});
222229
}
223230

224231
@Override
225232
void destroy () {
226233
device.deregisterResourceWithZoomSupport(this);
227-
zoomToHandle.values().forEach(handle -> OS.DeleteObject(handle));
234+
zoomToHandle.values().forEach(RegionHandle::destroy);
228235
zoomToHandle.clear();
229236
operations.clear();
237+
this.isDestroyed = true;
230238
}
231239

232240
@Override
233241
void destroyHandlesExcept(Set<Integer> zoomLevels) {
234242
zoomToHandle.entrySet().removeIf(entry -> {
235243
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();
238246
return true;
239247
}
240248
return false;
@@ -271,12 +279,14 @@ public boolean equals (Object object) {
271279
*/
272280
public Rectangle getBounds () {
273281
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+
});
275285
}
276286

277-
Rectangle getBoundsInPixels() {
287+
private Rectangle getBoundsInPixels(long handle) {
278288
RECT rect = new RECT();
279-
OS.GetRgnBox(getHandleForInitialZoom(), rect);
289+
OS.GetRgnBox(handle, rect);
280290
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
281291
}
282292

@@ -294,7 +304,6 @@ Rectangle getBoundsInPixels() {
294304
public int hashCode () {
295305
return super.hashCode();
296306
}
297-
298307
/**
299308
* Intersects the given rectangle to the collection of polygons
300309
* the receiver maintains to describe its area.
@@ -363,8 +372,10 @@ public void intersect (Region region) {
363372
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
364373
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
365374
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+
}
368379
}
369380

370381
/**
@@ -389,10 +400,10 @@ public boolean intersects (int x, int y, int width, int height) {
389400
return intersects(new Rectangle(x, y, width, height));
390401
}
391402

392-
boolean intersectsInPixels (int x, int y, int width, int height) {
403+
boolean intersectsInPixels (long handle, int x, int y, int width, int height) {
393404
RECT r = new RECT ();
394405
OS.SetRect (r, x, y, x + width, y + height);
395-
return OS.RectInRegion (getHandleForInitialZoom(), r);
406+
return OS.RectInRegion(handle, r);
396407
}
397408

398409
/**
@@ -415,8 +426,10 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
415426
public boolean intersects (Rectangle rect) {
416427
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
417428
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+
});
420433
}
421434

422435
/**
@@ -431,7 +444,7 @@ public boolean intersects (Rectangle rect) {
431444
*/
432445
@Override
433446
public boolean isDisposed() {
434-
return zoomToHandle.isEmpty();
447+
return isDestroyed;
435448
}
436449

437450
/**
@@ -448,9 +461,11 @@ public boolean isDisposed() {
448461
public boolean isEmpty () {
449462
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
450463
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+
});
454469
}
455470

456471
/**
@@ -543,8 +558,10 @@ public void subtract (Region region) {
543558
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
544559
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
545560
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+
}
548565
}
549566

550567
/**
@@ -588,36 +605,43 @@ public void translate (Point pt) {
588605
storeAndApplyOperationForAllHandles(operation);
589606
}
590607

591-
private long getHandleForInitialZoom() {
592-
return win32_getHandle(this, initialZoom);
593-
}
594-
595608
private void storeAndApplyOperationForAllHandles(Operation operation) {
596609
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());
598618
}
599619

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);
602622
try {
603623
return function.apply(temporaryHandle);
604624
} finally {
605-
OS.DeleteObject(temporaryHandle);
625+
temporaryHandle.destroy();
606626
}
607627
}
608628

609-
private static long newEmptyRegionHandle() {
629+
private static RegionHandle newRegionHandle(int zoom, List<Operation> operations) {
610630
long newHandle = OS.CreateRectRgn (0, 0, 0, 0);
611631
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;
613637
}
614638

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);
619643
}
620-
return newHandle;
644+
return zoomToHandle.get(zoom);
621645
}
622646

623647
/**
@@ -638,14 +662,7 @@ private static long newRegionHandle(List<Operation> operations, int zoom) {
638662
* @noreference This method is not intended to be referenced by clients.
639663
*/
640664
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();
649666
}
650667

651668
/**
@@ -660,20 +677,26 @@ public String toString () {
660677
return "Region {" + zoomToHandle.entrySet().stream().map(entry -> entry.getValue() + "(zoom:" + entry.getKey() + ")").collect(Collectors.joining(","));
661678
}
662679

680+
private record RegionHandle(long handle, int zoom) {
681+
void destroy() {
682+
OS.DeleteObject(handle());
683+
}
684+
}
685+
663686
@FunctionalInterface
664687
private interface OperationStrategy {
665688
void apply(Operation operation, long handle, int zoom);
666689
}
667690

668691
private abstract static class Operation {
669-
private OperationStrategy operationStrategy;
692+
private final OperationStrategy operationStrategy;
670693

671694
Operation(OperationStrategy operationStrategy) {
672695
this.operationStrategy = operationStrategy;
673696
}
674697

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());
677700
}
678701

679702
abstract void add(long handle, int zoom);
@@ -686,8 +709,7 @@ void apply(long handle, int zoom) {
686709
}
687710

688711
private static class OperationWithRectangle extends Operation {
689-
690-
Rectangle data;
712+
private final Rectangle data;
691713

692714
OperationWithRectangle(OperationStrategy operationStrategy, Rectangle data) {
693715
super(operationStrategy);
@@ -745,8 +767,7 @@ private Rectangle getScaledRectangle(int zoom) {
745767
}
746768

747769
private static class OperationWithArray extends Operation {
748-
749-
int[] data;
770+
private final int[] data;
750771

751772
public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
752773
super(operationStrategy);
@@ -793,8 +814,7 @@ private int[] getScaledPoints(int zoom) {
793814
}
794815

795816
private static class OperationWithPoint extends Operation {
796-
797-
Point data;
817+
private final Point data;
798818

799819
public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
800820
super(operationStrategy);
@@ -827,29 +847,29 @@ void translate(long handle, int zoom) {
827847
private static class OperationWithRegion extends Operation {
828848
private final List<Operation> operations;
829849

830-
OperationWithRegion(OperationStrategy operationStrategy, Region data) {
850+
OperationWithRegion(OperationStrategy operationStrategy, List<Operation> operations) {
831851
super(operationStrategy);
832-
this.operations = data.operations;
852+
this.operations = List.copyOf(operations);
833853
}
834854

835855
@Override
836856
void add(long handle, int zoom) {
837857
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);
839859
});
840860
}
841861

842862
@Override
843863
void subtract(long handle, int zoom) {
844864
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);
846866
});
847867
}
848868

849869
@Override
850870
void intersect(long handle, int zoom) {
851871
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);
853873
});
854874
}
855875

0 commit comments

Comments
 (0)