Skip to content

Commit 01413be

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 01413be

File tree

2 files changed

+115
-8
lines changed

2 files changed

+115
-8
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+
});
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: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,16 @@ public boolean isEmpty () {
468468
});
469469
}
470470

471+
/**
472+
* Specific method for {@link GC#getClipping(Region)} because the current GC
473+
* clipping settings at that specific point in time of executing the getClipping
474+
* method need to be stored.
475+
*/
476+
void set(Function<Integer, Long> handleForZoomSupplier) {
477+
final Operation operation = new OperationWithRegionHandle(Operation::set, handleForZoomSupplier);
478+
storeAndApplyOperationForAllHandles(operation);
479+
}
480+
471481
/**
472482
* Subtracts the given polygon from the collection of polygons
473483
* the receiver maintains to describe its area.
@@ -705,6 +715,8 @@ void apply(RegionHandle regionHandle) {
705715
operationStrategy.apply(this, regionHandle.handle(), regionHandle.zoom());
706716
}
707717

718+
abstract void set(long handle, int zoom);
719+
708720
abstract void add(long handle, int zoom);
709721

710722
abstract void subtract(long handle, int zoom);
@@ -722,6 +734,11 @@ private static class OperationWithRectangle extends Operation {
722734
this.data = data;
723735
}
724736

737+
@Override
738+
void set(long handle, int zoom) {
739+
throw new UnsupportedOperationException();
740+
}
741+
725742
@Override
726743
void add(long handle, int zoom) {
727744
Rectangle bounds = getScaledRectangle(zoom);
@@ -780,6 +797,11 @@ public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
780797
this.data = data;
781798
}
782799

800+
@Override
801+
void set(long handle, int zoom) {
802+
throw new UnsupportedOperationException();
803+
}
804+
783805
@Override
784806
void add(long handle, int zoom) {
785807
int[] points = getScaledPoints(zoom);
@@ -827,6 +849,11 @@ public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
827849
this.data = data;
828850
}
829851

852+
@Override
853+
void set(long handle, int zoom) {
854+
throw new UnsupportedOperationException();
855+
}
856+
830857
@Override
831858
void add(long handle, int zoom) {
832859
throw new UnsupportedOperationException();
@@ -858,6 +885,11 @@ private static class OperationWithRegion extends Operation {
858885
this.operations = List.copyOf(operations);
859886
}
860887

888+
@Override
889+
void set(long handle, int zoom) {
890+
throw new UnsupportedOperationException();
891+
}
892+
861893
@Override
862894
void add(long handle, int zoom) {
863895
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
@@ -883,5 +915,41 @@ void intersect(long handle, int zoom) {
883915
void translate(long handle, int zoom) {
884916
throw new UnsupportedOperationException();
885917
}
918+
919+
}
920+
921+
private static class OperationWithRegionHandle extends Operation {
922+
private final Function<Integer, Long> handleForZoomProvider;
923+
924+
OperationWithRegionHandle(OperationStrategy operationStrategy, Function<Integer, Long> handleForZoomSupplier) {
925+
super(operationStrategy);
926+
this.handleForZoomProvider = handleForZoomSupplier;
927+
}
928+
929+
@Override
930+
void set(long handle, int zoom) {
931+
OS.CombineRgn(handle, handleForZoomProvider.apply(zoom), 0, OS.RGN_COPY);
932+
}
933+
934+
@Override
935+
void subtract(long handle, int zoom) {
936+
throw new UnsupportedOperationException();
937+
}
938+
939+
@Override
940+
void intersect(long handle, int zoom) {
941+
throw new UnsupportedOperationException();
942+
}
943+
944+
@Override
945+
void translate(long handle, int zoom) {
946+
throw new UnsupportedOperationException();
947+
}
948+
949+
@Override
950+
void add(long handle, int zoom) {
951+
throw new UnsupportedOperationException();
952+
}
953+
886954
}
887955
}

0 commit comments

Comments
 (0)