diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/RegionWin32Tests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/RegionWin32Tests.java
new file mode 100644
index 00000000000..48f68684b36
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/RegionWin32Tests.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2024 Yatta Solutions
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Yatta Solutions - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+import org.junit.jupiter.api.*;
+
+class RegionWin32Tests extends Win32AutoscaleTestBase {
+
+ @Test
+ public void testRegionMustBeScaledOnHandleOfScaledZoomLevel() {
+ int zoom = DPIUtil.getDeviceZoom();
+ int scalingFactor = 2;
+
+ Region region = new Region(display);
+ region.add(0, 0, 5, 10);
+ region.subtract(0,0,1,1);
+ region.translate(0, 5);
+ region.intersect(1,1,1,1);
+
+ long handle = Region.win32_getHandle(region, zoom);
+ long scaledRegionHandle = Region.win32_getHandle(region, zoom * scalingFactor);
+
+ RECT rect = new RECT();
+ OS.GetRgnBox(handle, rect);
+ Rectangle bounds = new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+
+ rect = new RECT();
+ OS.GetRgnBox(scaledRegionHandle, rect);
+ Rectangle scaledBounds = new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+
+ assertEquals("scaled region's height should be double of unscaled region", bounds.height * scalingFactor, scaledBounds.height);
+ assertEquals("scaled region's width should be double of unscaled region", bounds.width * scalingFactor, scaledBounds.width);
+ assertEquals("scaled region's x position should be double of unscaled region", bounds.x * scalingFactor, scaledBounds.x);
+ assertEquals("scaled region's y position should be double of unscaled region", bounds.y * scalingFactor, scaledBounds.y);
+ }
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
index 0f5b0aed74b..7bcde04a888 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
@@ -3386,7 +3386,7 @@ public void getClipping (Region region) {
Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
Gdip.Graphics_GetVisibleClipBounds(gdipGraphics, rect);
Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
- OS.SetRectRgn(region.handle, rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
+ OS.SetRectRgn(Region.win32_getHandle(region, getZoom()), rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
} else {
long matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
long identity = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
@@ -3399,7 +3399,7 @@ public void getClipping (Region region) {
POINT pt = new POINT ();
OS.GetWindowOrgEx (handle, pt);
OS.OffsetRgn (hRgn, pt.x, pt.y);
- OS.CombineRgn(region.handle, hRgn, 0, OS.RGN_COPY);
+ OS.CombineRgn(Region.win32_getHandle(region, getZoom()), hRgn, 0, OS.RGN_COPY);
OS.DeleteObject(hRgn);
}
Gdip.Region_delete(rgn);
@@ -3407,18 +3407,18 @@ public void getClipping (Region region) {
}
POINT pt = new POINT ();
OS.GetWindowOrgEx (handle, pt);
- int result = OS.GetClipRgn (handle, region.handle);
+ int result = OS.GetClipRgn (handle, Region.win32_getHandle(region, getZoom()));
if (result != 1) {
RECT rect = new RECT();
OS.GetClipBox(handle, rect);
- OS.SetRectRgn(region.handle, rect.left, rect.top, rect.right, rect.bottom);
+ OS.SetRectRgn(Region.win32_getHandle(region, getZoom()), rect.left, rect.top, rect.right, rect.bottom);
} else {
- OS.OffsetRgn (region.handle, pt.x, pt.y);
+ OS.OffsetRgn (Region.win32_getHandle(region, getZoom()), pt.x, pt.y);
}
long metaRgn = OS.CreateRectRgn (0, 0, 0, 0);
if (OS.GetMetaRgn (handle, metaRgn) != 0) {
OS.OffsetRgn (metaRgn, pt.x, pt.y);
- OS.CombineRgn (region.handle, metaRgn, region.handle, OS.RGN_AND);
+ OS.CombineRgn (Region.win32_getHandle(region, getZoom()), metaRgn, Region.win32_getHandle(region, getZoom()), OS.RGN_AND);
}
OS.DeleteObject(metaRgn);
long hwnd = data.hwnd;
@@ -3435,7 +3435,7 @@ public void getClipping (Region region) {
}
OS.MapWindowPoints (0, hwnd, pt, 1);
OS.OffsetRgn (sysRgn, pt.x, pt.y);
- OS.CombineRgn (region.handle, sysRgn, region.handle, OS.RGN_AND);
+ OS.CombineRgn (Region.win32_getHandle(region, getZoom()), sysRgn, Region.win32_getHandle(region, getZoom()), OS.RGN_AND);
}
OS.DeleteObject(sysRgn);
}
@@ -4374,7 +4374,7 @@ public void setClipping (Rectangle rect) {
public void setClipping (Region region) {
if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- setClipping(region != null ? region.handle : 0);
+ setClipping(region != null ? Region.win32_getHandle(region, getZoom()) : 0);
}
/**
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java
index 636c311536e..0a45bd54cd3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java
@@ -14,6 +14,9 @@
package org.eclipse.swt.graphics;
+import java.util.*;
+import java.util.stream.*;
+
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
@@ -33,19 +36,11 @@
*/
public final class Region extends Resource {
- /**
- * the OS resource for the region
- * (Warning: This field is platform dependent)
- *
- * IMPORTANT: This field is not part of the SWT
- * public API. It is marked public only so that it can be shared
- * within the packages provided by SWT. It is not available on all
- * platforms and should never be accessed from application code.
- *
- *
- * @noreference This field is not intended to be referenced by clients.
- */
- public long handle;
+ private int initialZoom;
+
+ private HashMap zoomToHandle = new HashMap<>();
+
+ private List operations = new ArrayList<>();
/**
* Constructs a new empty region.
@@ -84,7 +79,9 @@ public Region () {
*/
public Region (Device device) {
super(device);
- handle = OS.CreateRectRgn (0, 0, 0, 0);
+ initialZoom = DPIUtil.getDeviceZoom();
+ long handle = OS.CreateRectRgn (0, 0, 0, 0);
+ zoomToHandle.put(initialZoom, handle);
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
init();
}
@@ -107,13 +104,8 @@ public Region (Device device) {
public void add (int[] pointArray) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addInPixels(DPIUtil.autoScaleUp(pointArray));
-}
-
-void addInPixels (int[] pointArray) {
- long polyRgn = OS.CreatePolygonRgn(pointArray, pointArray.length / 2, OS.ALTERNATE);
- OS.CombineRgn (handle, handle, polyRgn, OS.RGN_OR);
- OS.DeleteObject (polyRgn);
+ final Operation operation = new OperationWithArray(Operation::add, Arrays.copyOf(pointArray, pointArray.length));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -133,8 +125,8 @@ void addInPixels (int[] pointArray) {
public void add (Rectangle rect) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- rect = DPIUtil.autoScaleUp(rect);
- addInPixels(rect.x, rect.y, rect.width, rect.height);
+ final Operation operation = new OperationWithRectangle(Operation::add, new Rectangle(rect.x, rect.y, rect.width, rect.height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -157,14 +149,8 @@ public void add (Rectangle rect) {
*/
public void add (int x, int y, int width, int height) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- addInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
-}
-
-void addInPixels (int x, int y, int width, int height) {
- if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
- OS.CombineRgn (handle, handle, rectRgn, OS.RGN_OR);
- OS.DeleteObject (rectRgn);
+ final Operation operation = new OperationWithRectangle(Operation::add, new Rectangle(x, y, width, height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -186,7 +172,8 @@ public void add (Region region) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- OS.CombineRgn (handle, handle, region.handle, OS.RGN_OR);
+ final Operation operation = new OperationWithRegion(Operation::add, region);
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -204,11 +191,11 @@ public void add (Region region) {
*/
public boolean contains (int x, int y) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- return containsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
+ return containsInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom));
}
boolean containsInPixels (int x, int y) {
- return OS.PtInRegion (handle, x, y);
+ return OS.PtInRegion (getHandleForInitialZoom(), x, y);
}
/**
@@ -229,14 +216,15 @@ boolean containsInPixels (int x, int y) {
public boolean contains (Point pt) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- pt = DPIUtil.autoScaleUp(pt);
- return containsInPixels(pt.x, pt.y);
+ Point p = DPIUtil.autoScaleUp(pt, initialZoom);
+ return containsInPixels(p.x, p.y);
}
@Override
void destroy () {
- OS.DeleteObject(handle);
- handle = 0;
+ zoomToHandle.values().forEach(handle -> OS.DeleteObject(handle));
+ zoomToHandle.clear();
+ operations.clear();
}
/**
@@ -254,7 +242,7 @@ public boolean equals (Object object) {
if (this == object) return true;
if (!(object instanceof Region)) return false;
Region rgn = (Region)object;
- return handle == rgn.handle;
+ return getHandleForInitialZoom() == rgn.getHandleForInitialZoom();
}
/**
@@ -272,12 +260,12 @@ public boolean equals (Object object) {
*/
public Rectangle getBounds () {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- return DPIUtil.autoScaleDown(getBoundsInPixels());
+ return DPIUtil.scaleDown(getBoundsInPixels(), initialZoom);
}
Rectangle getBoundsInPixels() {
RECT rect = new RECT();
- OS.GetRgnBox(handle, rect);
+ OS.GetRgnBox(getHandleForInitialZoom(), rect);
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
@@ -293,7 +281,7 @@ Rectangle getBoundsInPixels() {
*/
@Override
public int hashCode () {
- return (int)handle;
+ return (int)getHandleForInitialZoom();
}
/**
@@ -315,8 +303,8 @@ public int hashCode () {
public void intersect (Rectangle rect) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- rect = DPIUtil.autoScaleUp(rect);
- intersectInPixels(rect.x, rect.y, rect.width, rect.height);
+ final Operation operation = new OperationWithRectangle(Operation::intersect, new Rectangle(rect.x, rect.y, rect.width, rect.height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -339,14 +327,8 @@ public void intersect (Rectangle rect) {
*/
public void intersect (int x, int y, int width, int height) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- intersectInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
-}
-
-void intersectInPixels (int x, int y, int width, int height) {
- if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
- OS.CombineRgn (handle, handle, rectRgn, OS.RGN_AND);
- OS.DeleteObject (rectRgn);
+ final Operation operation = new OperationWithRectangle(Operation::intersect, new Rectangle(x, y, width, height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -370,7 +352,8 @@ public void intersect (Region region) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- OS.CombineRgn (handle, handle, region.handle, OS.RGN_AND);
+ final Operation operation = new OperationWithRegion(Operation::intersect, region);
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -392,13 +375,13 @@ public void intersect (Region region) {
*/
public boolean intersects (int x, int y, int width, int height) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- return intersectsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
+ return intersectsInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom), DPIUtil.autoScaleUp(width, initialZoom), DPIUtil.autoScaleUp(height, initialZoom));
}
boolean intersectsInPixels (int x, int y, int width, int height) {
RECT r = new RECT ();
OS.SetRect (r, x, y, x + width, y + height);
- return OS.RectInRegion (handle, r);
+ return OS.RectInRegion (getHandleForInitialZoom(), r);
}
/**
@@ -421,8 +404,8 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
public boolean intersects (Rectangle rect) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- rect = DPIUtil.autoScaleUp(rect);
- return intersectsInPixels(rect.x, rect.y, rect.width, rect.height);
+ Rectangle r = DPIUtil.autoScaleUp(rect, initialZoom);
+ return intersectsInPixels(r.x, r.y, r.width, r.height);
}
/**
@@ -437,7 +420,7 @@ public boolean intersects (Rectangle rect) {
*/
@Override
public boolean isDisposed() {
- return handle == 0;
+ return zoomToHandle.isEmpty();
}
/**
@@ -454,7 +437,7 @@ public boolean isDisposed() {
public boolean isEmpty () {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
RECT rect = new RECT ();
- int result = OS.GetRgnBox (handle, rect);
+ int result = OS.GetRgnBox (getHandleForInitialZoom(), rect);
if (result == OS.NULLREGION) return true;
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
}
@@ -477,13 +460,8 @@ public boolean isEmpty () {
public void subtract (int[] pointArray) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- subtractInPixels(DPIUtil.autoScaleUp(pointArray));
-}
-
-void subtractInPixels (int[] pointArray) {
- long polyRgn = OS.CreatePolygonRgn(pointArray, pointArray.length / 2, OS.ALTERNATE);
- OS.CombineRgn (handle, handle, polyRgn, OS.RGN_DIFF);
- OS.DeleteObject (polyRgn);
+ final Operation operation = new OperationWithArray(Operation::subtract, Arrays.copyOf(pointArray, pointArray.length));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -505,8 +483,8 @@ void subtractInPixels (int[] pointArray) {
public void subtract (Rectangle rect) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- rect = DPIUtil.autoScaleUp(rect);
- subtractInPixels(rect.x, rect.y, rect.width, rect.height);
+ final Operation operation = new OperationWithRectangle(Operation::subtract, new Rectangle(rect.x, rect.y, rect.width, rect.height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -529,14 +507,8 @@ public void subtract (Rectangle rect) {
*/
public void subtract (int x, int y, int width, int height) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- subtractInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
-}
-
-void subtractInPixels (int x, int y, int width, int height) {
- if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
- OS.CombineRgn (handle, handle, rectRgn, OS.RGN_DIFF);
- OS.DeleteObject (rectRgn);
+ final Operation operation = new OperationWithRectangle(Operation::subtract, new Rectangle(x, y, width, height));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -560,7 +532,8 @@ public void subtract (Region region) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- OS.CombineRgn (handle, handle, region.handle, OS.RGN_DIFF);
+ final Operation operation = new OperationWithRegion(Operation::subtract, region);
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -578,11 +551,8 @@ public void subtract (Region region) {
*/
public void translate (int x, int y) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- translateInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
-}
-
-void translateInPixels (int x, int y) {
- OS.OffsetRgn (handle, x, y);
+ final Operation operation = new OperationWithPoint(Operation::translate, new Point(x, y));
+ storeAndApplyOperationForAllHandles(operation);
}
/**
@@ -603,8 +573,45 @@ void translateInPixels (int x, int y) {
public void translate (Point pt) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- pt = DPIUtil.autoScaleUp(pt);
- translateInPixels(pt.x, pt.y);
+ final Operation operation = new OperationWithPoint(Operation::translate, new Point(pt.x, pt.y));
+ storeAndApplyOperationForAllHandles(operation);
+}
+
+private long getHandleForInitialZoom() {
+ return win32_getHandle(this, initialZoom);
+}
+
+private void storeAndApplyOperationForAllHandles(Operation operation) {
+ operations.add(operation);
+ zoomToHandle.forEach((zoom, handle) -> operation.apply(handle, zoom));
+}
+
+/**
+ * IMPORTANT: This method is not part of the public
+ * API for Image. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ * Gets the handle for the region scaled at required zoom level
+ *
+ * @param region the region to be scaled
+ *
+ * @param zoom the zoom level for which the region is needed
+ *
+ * @return the handle of the region scaled for the zoom level
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static long win32_getHandle(Region region, int zoom) {
+ if(!region.zoomToHandle.containsKey(zoom)) {
+ long handle = OS.CreateRectRgn(0, 0, 0, 0);
+ for(Operation operation : region.operations) {
+ operation.apply(handle, zoom);
+ }
+ region.zoomToHandle.put(zoom, handle);
+ }
+ return region.zoomToHandle.get(zoom);
}
/**
@@ -616,7 +623,208 @@ public void translate (Point pt) {
@Override
public String toString () {
if (isDisposed()) return "Region {*DISPOSED*}";
- return "Region {" + handle + "}";
+ return "Region {" + zoomToHandle.entrySet().stream().map(entry -> entry.getValue() + "(zoom:" + entry.getKey() + ")").collect(Collectors.joining(","));
+}
+
+@FunctionalInterface
+private interface OperationStrategy {
+ void apply(Operation operation, long handle, int zoom);
+}
+
+private abstract class Operation {
+ private OperationStrategy operationStrategy;
+
+ Operation(OperationStrategy operationStrategy) {
+ this.operationStrategy = operationStrategy;
+ }
+
+ void apply(long handle, int zoom) {
+ operationStrategy.apply(this, handle, zoom);
+ }
+
+ abstract void add(long handle, int zoom);
+
+ abstract void subtract(long handle, int zoom);
+
+ abstract void intersect(long handle, int zoom);
+
+ abstract void translate(long handle, int zoom);
+}
+
+private class OperationWithRectangle extends Operation {
+
+ Rectangle data;
+
+ OperationWithRectangle(OperationStrategy operationStrategy, Rectangle data) {
+ super(operationStrategy);
+ this.data = data;
+ }
+
+ @Override
+ void add(long handle, int zoom) {
+ Rectangle bounds = getScaledRectangle(zoom);
+ addInPixels(handle, bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+
+ @Override
+ void subtract(long handle, int zoom) {
+ Rectangle bounds = getScaledRectangle(zoom);
+ subtractInPixels(handle, bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+
+ @Override
+ void intersect(long handle, int zoom) {
+ Rectangle bounds = getScaledRectangle(zoom);
+ intersectInPixels(handle, bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+
+ @Override
+ void translate(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void addInPixels (long handle, int x, int y, int width, int height) {
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_OR);
+ OS.DeleteObject (rectRgn);
+ }
+
+ private void subtractInPixels (long handle, int x, int y, int width, int height) {
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_DIFF);
+ OS.DeleteObject (rectRgn);
+ }
+
+ private void intersectInPixels (long handle, int x, int y, int width, int height) {
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ long rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_AND);
+ OS.DeleteObject (rectRgn);
+ }
+
+ private Rectangle getScaledRectangle(int zoom) {
+ return DPIUtil.autoScaleUp(data, zoom);
+ }
+
+}
+
+private class OperationWithArray extends Operation {
+
+ int[] data;
+
+ public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
+ super(operationStrategy);
+ this.data = data;
+ }
+
+ @Override
+ void add(long handle, int zoom) {
+ int[] points = getScaledPoints(zoom);
+ addInPixels(handle, points);
+ }
+
+ @Override
+ void subtract(long handle, int zoom) {
+ int[] pointArray = getScaledPoints(zoom);
+ subtractInPixels(handle, pointArray);
+ }
+
+ @Override
+ void intersect(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void translate(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void addInPixels (long handle, int[] pointArray) {
+ long polyRgn = OS.CreatePolygonRgn(pointArray, pointArray.length / 2, OS.ALTERNATE);
+ OS.CombineRgn (handle, handle, polyRgn, OS.RGN_OR);
+ OS.DeleteObject (polyRgn);
+ }
+
+ private void subtractInPixels (long handle, int[] pointArray) {
+ long polyRgn = OS.CreatePolygonRgn(pointArray, pointArray.length / 2, OS.ALTERNATE);
+ OS.CombineRgn (handle, handle, polyRgn, OS.RGN_DIFF);
+ OS.DeleteObject (polyRgn);
+ }
+
+ private int[] getScaledPoints(int zoom) {
+ return DPIUtil.autoScaleUp(data, zoom);
+ }
+}
+
+private class OperationWithPoint extends Operation {
+
+ Point data;
+
+ public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
+ super(operationStrategy);
+ this.data = data;
+ }
+
+ @Override
+ void add(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void subtract(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void intersect(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void translate(long handle, int zoom) {
+ Point pt = DPIUtil.autoScaleUp((Point) data, zoom);
+ OS.OffsetRgn (handle, pt.x, pt.y);
+ }
+
}
+private class OperationWithRegion extends Operation {
+
+ Region data;
+
+ OperationWithRegion(OperationStrategy operationStrategy, Region data) {
+ super(operationStrategy);
+ this.data = data;
+ }
+
+ @Override
+ void add(long handle, int zoom) {
+ long scaledHandle = getHandleForScaledRegion(zoom);
+ OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_OR);
+ }
+
+ @Override
+ void subtract(long handle, int zoom) {
+ long scaledHandle = getHandleForScaledRegion(zoom);
+ OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_DIFF);
+ }
+
+ @Override
+ void intersect(long handle, int zoom) {
+ long scaledHandle = getHandleForScaledRegion(zoom);
+ OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_AND);
+ }
+
+ @Override
+ void translate(long handle, int zoom) {
+ throw new UnsupportedOperationException();
+ }
+
+ private long getHandleForScaledRegion(int zoom) {
+ if (data.isDisposed() || data == Region.this) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return win32_getHandle(data, zoom);
+ }
+}
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
index 944596751f7..9d71bd58ec7 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
@@ -3690,7 +3690,7 @@ public void setRegion (Region region) {
long hRegion = 0;
if (region != null) {
hRegion = OS.CreateRectRgn (0, 0, 0, 0);
- OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
+ OS.CombineRgn (hRegion, Region.win32_getHandle(region, getZoom()), hRegion, OS.RGN_OR);
}
OS.SetWindowRgn (handle, hRegion, true);
this.region = region;
@@ -5815,6 +5815,9 @@ private static void handleDPIChange(Widget widget, int newZoom, float scalingFac
control.setBackgroundImage(image);
}
}
+ if (control.getRegion() != null) {
+ control.setRegion(control.getRegion());
+ }
}
private static void resizeFont(Control control, int newZoom) {
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java
index a900d17be0f..014ca3eeca9 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java
@@ -712,7 +712,7 @@ private void logUnlessEquals(Appendable log, String message, Rectangle expected,
}
}
-//TODO This test was not hooked for running with the runTest override. It fails on GTK/Cocoa. Investigate.
+@Test
public void a_test_setRegion() {
Region region = new Region();
region.add(new Rectangle(10, 20, 100, 200));
@@ -727,7 +727,7 @@ public void a_test_setRegion() {
Shell shell2 = new Shell(display, SWT.NO_TRIM);
assertNull(":d:", shell2.getRegion());
shell2.setRegion(region);
- assertEquals(":e:", region.handle, shell2.getRegion().handle);
+ assertEquals(":e:", region, shell2.getRegion());
region.dispose();
assertTrue(":f:", shell2.getRegion().isDisposed());
shell2.setRegion(null);