Skip to content

Commit a68fd8d

Browse files
committed
[Win32] Represent GC#getClipping(Region) operation in Region #2346
The GC#getClipping(Region) call sets the passed region to the current clipping region of the GC. Currently, this is not represented as an operation inside the passed Region, such that when calculating a handle for a different zoom of that region or when copying that region the according application of GC#getClipping(Region) to that region is missing. This change adds the missing operation to the Region. Since the clipping needs to be calculated at the of executing the GC#getClipping(Region) method and not at the time of applying the region operation when retrieving a handle, the GC#getClipping(Region) stores an operation inside GC that maintains handles for the according clipping region at the time of executing the GC#getClipping(Region) method for every zoom at which the GC is requested. This ensures that the proper clipping state is available to the Region. Fixes #2346
1 parent 0334215 commit a68fd8d

File tree

2 files changed

+134
-9
lines changed

2 files changed

+134
-9
lines changed

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

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3790,6 +3790,44 @@ public void getClipping (Region region) {
37903790
checkNonDisposed();
37913791
if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
37923792
if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
3793+
storeAndApplyOperationForExistingHandle(new GetClippingOperation(region));
3794+
}
3795+
3796+
private class GetClippingOperation extends Operation {
3797+
private final Map<Integer, Long> zoomToRegionHandle = new HashMap<>();
3798+
3799+
public GetClippingOperation(Region region) {
3800+
region.set(zoom -> {
3801+
if (!zoomToRegionHandle.containsKey(zoom)) {
3802+
System.err.println("No clipping handle for zoom " + zoom + " has been created on this GC");
3803+
return zoomToRegionHandle.values().iterator().next();
3804+
}
3805+
return zoomToRegionHandle.get(zoom);
3806+
}, getZoom());
3807+
}
3808+
3809+
// Whenever the GC handle is recalculated for a new zoom, we compute and store the clipping
3810+
// at the times when getClipping(Region) was originally called, such that the region to which
3811+
// that clipping is set can retrieve it from the storage when required.
3812+
@Override
3813+
void apply() {
3814+
zoomToRegionHandle.computeIfAbsent(getZoom(), __ -> getClippingRegion());
3815+
}
3816+
3817+
@Override
3818+
void disposeAll() {
3819+
for (long handle : zoomToRegionHandle.values()) {
3820+
OS.DeleteObject(handle);
3821+
}
3822+
super.disposeAll();
3823+
}
3824+
}
3825+
3826+
/**
3827+
* @return a region handle with the current clipping region of this GC
3828+
*/
3829+
private long getClippingRegion () {
3830+
long regionHandle = OS.CreateRectRgn(0, 0, 0, 0);
37933831
long gdipGraphics = data.gdipGraphics;
37943832
if (gdipGraphics != 0) {
37953833
long rgn = Gdip.Region_new();
@@ -3799,7 +3837,7 @@ public void getClipping (Region region) {
37993837
Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
38003838
Gdip.Graphics_GetVisibleClipBounds(gdipGraphics, rect);
38013839
Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
3802-
OS.SetRectRgn(Region.win32_getHandle(region, getZoom()), rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
3840+
OS.SetRectRgn(regionHandle, rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
38033841
} else {
38043842
long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
38053843
long identity = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
@@ -3812,26 +3850,26 @@ public void getClipping (Region region) {
38123850
POINT pt = new POINT ();
38133851
OS.GetWindowOrgEx (handle, pt);
38143852
OS.OffsetRgn (hRgn, pt.x, pt.y);
3815-
OS.CombineRgn(Region.win32_getHandle(region, getZoom()), hRgn, 0, OS.RGN_COPY);
3853+
OS.CombineRgn(regionHandle, hRgn, 0, OS.RGN_COPY);
38163854
OS.DeleteObject(hRgn);
38173855
}
38183856
Gdip.Region_delete(rgn);
3819-
return;
3857+
return regionHandle;
38203858
}
38213859
POINT pt = new POINT ();
38223860
OS.GetWindowOrgEx (handle, pt);
3823-
int result = OS.GetClipRgn (handle, Region.win32_getHandle(region, getZoom()));
3861+
int result = OS.GetClipRgn (handle, regionHandle);
38243862
if (result != 1) {
38253863
RECT rect = new RECT();
38263864
OS.GetClipBox(handle, rect);
3827-
OS.SetRectRgn(Region.win32_getHandle(region, getZoom()), rect.left, rect.top, rect.right, rect.bottom);
3865+
OS.SetRectRgn(regionHandle, rect.left, rect.top, rect.right, rect.bottom);
38283866
} else {
3829-
OS.OffsetRgn (Region.win32_getHandle(region, getZoom()), pt.x, pt.y);
3867+
OS.OffsetRgn (regionHandle, pt.x, pt.y);
38303868
}
38313869
long metaRgn = OS.CreateRectRgn (0, 0, 0, 0);
38323870
if (OS.GetMetaRgn (handle, metaRgn) != 0) {
38333871
OS.OffsetRgn (metaRgn, pt.x, pt.y);
3834-
OS.CombineRgn (Region.win32_getHandle(region, getZoom()), metaRgn, Region.win32_getHandle(region, getZoom()), OS.RGN_AND);
3872+
OS.CombineRgn (regionHandle, metaRgn, regionHandle, OS.RGN_AND);
38353873
}
38363874
OS.DeleteObject(metaRgn);
38373875
long hwnd = data.hwnd;
@@ -3848,10 +3886,11 @@ public void getClipping (Region region) {
38483886
}
38493887
OS.MapWindowPoints (0, hwnd, pt, 1);
38503888
OS.OffsetRgn (sysRgn, pt.x, pt.y);
3851-
OS.CombineRgn (Region.win32_getHandle(region, getZoom()), sysRgn, Region.win32_getHandle(region, getZoom()), OS.RGN_AND);
3889+
OS.CombineRgn (regionHandle, sysRgn, regionHandle, OS.RGN_AND);
38523890
}
38533891
OS.DeleteObject(sysRgn);
38543892
}
3893+
return regionHandle;
38553894
}
38563895

38573896
long getFgBrush() {

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

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public final class Region extends Resource {
4343

4444
private boolean isDestroyed;
4545

46+
private int temporaryHandleZoomHint = 0;
47+
4648
/**
4749
* Constructs a new empty region.
4850
* <p>
@@ -171,11 +173,18 @@ public void add (Region region) {
171173
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
172174
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
173175
if (!region.operations.isEmpty()) {
176+
adoptTemporaryHandleZoomHint(region);
174177
final Operation operation = new OperationWithRegion(Operation::add, region.operations);
175178
storeAndApplyOperationForAllHandles(operation);
176179
}
177180
}
178181

182+
private void adoptTemporaryHandleZoomHint(Region region) {
183+
if (temporaryHandleZoomHint == 0 && region.temporaryHandleZoomHint != 0) {
184+
this.temporaryHandleZoomHint = region.temporaryHandleZoomHint;
185+
}
186+
}
187+
179188
/**
180189
* Returns <code>true</code> if the point specified by the
181190
* arguments is inside the area specified by the receiver,
@@ -373,6 +382,7 @@ public void intersect (Region region) {
373382
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
374383
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
375384
if (!region.operations.isEmpty()) {
385+
adoptTemporaryHandleZoomHint(region);
376386
final Operation operation = new OperationWithRegion(Operation::intersect, region.operations);
377387
storeAndApplyOperationForAllHandles(operation);
378388
}
@@ -468,6 +478,21 @@ public boolean isEmpty () {
468478
});
469479
}
470480

481+
/**
482+
* Specific method for {@link GC#getClipping(Region)} because the current GC
483+
* clipping settings at that specific point in time of executing the getClipping
484+
* method need to be stored.
485+
* <p>
486+
* The context zoom is used as a hint for the case of creating temporary
487+
* handles, such that they can be created for a zoom for which we know that the
488+
* supplier is capable of providing a proper handle.
489+
*/
490+
void set(Function<Integer, Long> handleForZoomSupplier, int contextZoom) {
491+
this.temporaryHandleZoomHint = contextZoom;
492+
final Operation operation = new OperationWithRegionHandle(Operation::set, handleForZoomSupplier);
493+
storeAndApplyOperationForAllHandles(operation);
494+
}
495+
471496
/**
472497
* Subtracts the given polygon from the collection of polygons
473498
* the receiver maintains to describe its area.
@@ -559,6 +584,7 @@ public void subtract (Region region) {
559584
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
560585
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
561586
if (!region.operations.isEmpty()) {
587+
adoptTemporaryHandleZoomHint(region);
562588
final Operation operation = new OperationWithRegion(Operation::subtract, region.operations);
563589
storeAndApplyOperationForAllHandles(operation);
564590
}
@@ -612,7 +638,8 @@ private void storeAndApplyOperationForAllHandles(Operation operation) {
612638

613639
private <T> T applyUsingAnyHandle(Function<RegionHandle, T> function) {
614640
if (zoomToHandle.isEmpty()) {
615-
return applyUsingTemporaryHandle(device.getDeviceZoom(), operations, function);
641+
int temporaryHandleZoom = temporaryHandleZoomHint != 0 ? temporaryHandleZoomHint : device.getDeviceZoom();
642+
return applyUsingTemporaryHandle(temporaryHandleZoom, operations, function);
616643
}
617644
return function.apply(zoomToHandle.values().iterator().next());
618645
}
@@ -646,6 +673,7 @@ private RegionHandle getRegionHandle(int zoom) {
646673

647674
Region copy() {
648675
Region region = new Region();
676+
region.temporaryHandleZoomHint = temporaryHandleZoomHint;
649677
region.operations.addAll(operations);
650678
return region;
651679
}
@@ -705,6 +733,8 @@ void apply(RegionHandle regionHandle) {
705733
operationStrategy.apply(this, regionHandle.handle(), regionHandle.zoom());
706734
}
707735

736+
abstract void set(long handle, int zoom);
737+
708738
abstract void add(long handle, int zoom);
709739

710740
abstract void subtract(long handle, int zoom);
@@ -722,6 +752,11 @@ private static class OperationWithRectangle extends Operation {
722752
this.data = data;
723753
}
724754

755+
@Override
756+
void set(long handle, int zoom) {
757+
throw new UnsupportedOperationException();
758+
}
759+
725760
@Override
726761
void add(long handle, int zoom) {
727762
Rectangle bounds = getScaledRectangle(zoom);
@@ -780,6 +815,11 @@ public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
780815
this.data = data;
781816
}
782817

818+
@Override
819+
void set(long handle, int zoom) {
820+
throw new UnsupportedOperationException();
821+
}
822+
783823
@Override
784824
void add(long handle, int zoom) {
785825
int[] points = getScaledPoints(zoom);
@@ -827,6 +867,11 @@ public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
827867
this.data = data;
828868
}
829869

870+
@Override
871+
void set(long handle, int zoom) {
872+
throw new UnsupportedOperationException();
873+
}
874+
830875
@Override
831876
void add(long handle, int zoom) {
832877
throw new UnsupportedOperationException();
@@ -858,6 +903,11 @@ private static class OperationWithRegion extends Operation {
858903
this.operations = List.copyOf(operations);
859904
}
860905

906+
@Override
907+
void set(long handle, int zoom) {
908+
throw new UnsupportedOperationException();
909+
}
910+
861911
@Override
862912
void add(long handle, int zoom) {
863913
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
@@ -883,5 +933,41 @@ void intersect(long handle, int zoom) {
883933
void translate(long handle, int zoom) {
884934
throw new UnsupportedOperationException();
885935
}
936+
937+
}
938+
939+
private static class OperationWithRegionHandle extends Operation {
940+
private final Function<Integer, Long> handleForZoomProvider;
941+
942+
OperationWithRegionHandle(OperationStrategy operationStrategy, Function<Integer, Long> handleForZoomSupplier) {
943+
super(operationStrategy);
944+
this.handleForZoomProvider = handleForZoomSupplier;
945+
}
946+
947+
@Override
948+
void set(long handle, int zoom) {
949+
OS.CombineRgn(handle, handleForZoomProvider.apply(zoom), 0, OS.RGN_COPY);
950+
}
951+
952+
@Override
953+
void subtract(long handle, int zoom) {
954+
throw new UnsupportedOperationException();
955+
}
956+
957+
@Override
958+
void intersect(long handle, int zoom) {
959+
throw new UnsupportedOperationException();
960+
}
961+
962+
@Override
963+
void translate(long handle, int zoom) {
964+
throw new UnsupportedOperationException();
965+
}
966+
967+
@Override
968+
void add(long handle, int zoom) {
969+
throw new UnsupportedOperationException();
970+
}
971+
886972
}
887973
}

0 commit comments

Comments
 (0)