Skip to content

Commit

Permalink
Multi Zoom Support for region for win32
Browse files Browse the repository at this point in the history
This commit adds the feature of scaling region based on the zoom level of the monitor it is drawn on. The mentioned functionality is attained by using a map to maintain the handle of the region scale as per zoom level. The handle can then be obtained by the method win32_getHandle by passing the zoom information from the client.

contributes to #62 and #127
  • Loading branch information
amartya4256 committed Jun 17, 2024
1 parent 7ac43c0 commit b4dcb80
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.eclipse.swt.graphics;

import static org.junit.Assert.assertEquals;

import org.eclipse.swt.internal.*;
import org.junit.*;

public class RegionWin32Tests extends Win32AutoscaleTestBase {

@Test
public void testRegionMustBeScaledOnHandleOfScaledZoomLevel() {
int zoom = DPIUtil.getDeviceZoom();
Region region = new Region(display);
region.add(0, 0, 5, 10);
long scaledRegionHandle = Region.win32_getHandle(region, zoom * 2);
Region scaledRegion = Region.win32_new(display, (int) scaledRegionHandle);
Rectangle scaledBounds = scaledRegion.getBounds();
Rectangle bounds = region.getBounds();
assertEquals("scaled region's height should be double of unscaled region", bounds.height * 2, scaledBounds.height);
assertEquals("scaled region's width should be double of unscaled region", bounds.width * 2, scaledBounds.width);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3384,7 +3384,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);
Expand All @@ -3397,26 +3397,26 @@ 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);
return;
}
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;
Expand All @@ -3433,7 +3433,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);
}
Expand Down Expand Up @@ -4371,7 +4371,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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package org.eclipse.swt.graphics;


import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
Expand Down Expand Up @@ -47,6 +49,8 @@ public final class Region extends Resource {
*/
public long handle;

private int initialZoom;

/**
* Constructs a new empty region.
* <p>
Expand Down Expand Up @@ -84,7 +88,9 @@ public Region () {
*/
public Region (Device device) {
super(device);
initialZoom = DPIUtil.getDeviceZoom();
handle = OS.CreateRectRgn (0, 0, 0, 0);
handleMap.put(initialZoom, handle);
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
init();
}
Expand Down Expand Up @@ -118,7 +124,7 @@ 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));
addInPixels(DPIUtil.autoScaleUp(pointArray, initialZoom));
}

void addInPixels (int[] pointArray) {
Expand All @@ -144,8 +150,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);
Rectangle r = DPIUtil.autoScaleUp(rect, initialZoom);
addInPixels(r.x, r.y, r.width, r.height);
}

/**
Expand All @@ -168,7 +174,7 @@ 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));
addInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom), DPIUtil.autoScaleUp(width, initialZoom), DPIUtil.autoScaleUp(height, initialZoom));
}

void addInPixels (int x, int y, int width, int height) {
Expand Down Expand Up @@ -215,7 +221,7 @@ 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) {
Expand All @@ -240,12 +246,13 @@ 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 () {
handleMap.values().forEach(handle -> OS.DeleteObject(handle));
OS.DeleteObject(handle);
handle = 0;
}
Expand Down Expand Up @@ -283,7 +290,7 @@ 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() {
Expand Down Expand Up @@ -326,8 +333,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);
Rectangle r = DPIUtil.autoScaleUp(rect, initialZoom);
intersectInPixels(r.x, r.y, r.width, r.height);
}

/**
Expand All @@ -350,7 +357,7 @@ 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));
intersectInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom), DPIUtil.autoScaleUp(width, initialZoom), DPIUtil.autoScaleUp(height, initialZoom));
}

void intersectInPixels (int x, int y, int width, int height) {
Expand Down Expand Up @@ -403,7 +410,7 @@ 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) {
Expand Down Expand Up @@ -432,8 +439,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);
}

/**
Expand Down Expand Up @@ -488,7 +495,7 @@ 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));
subtractInPixels(DPIUtil.autoScaleUp(pointArray, initialZoom));
}

void subtractInPixels (int[] pointArray) {
Expand Down Expand Up @@ -516,8 +523,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);
Rectangle r = DPIUtil.autoScaleUp(rect, initialZoom);
subtractInPixels(r.x, r.y, r.width, r.height);
}

/**
Expand All @@ -540,7 +547,7 @@ 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));
subtractInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom), DPIUtil.autoScaleUp(width, initialZoom), DPIUtil.autoScaleUp(height, initialZoom));
}

void subtractInPixels (int x, int y, int width, int height) {
Expand Down Expand Up @@ -589,7 +596,7 @@ 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));
translateInPixels(DPIUtil.autoScaleUp(x, initialZoom), DPIUtil.autoScaleUp(y, initialZoom));
}

void translateInPixels (int x, int y) {
Expand All @@ -614,8 +621,35 @@ 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);
Point p = DPIUtil.autoScaleUp(pt, initialZoom);
translateInPixels(p.x, p.y);
}

private HashMap<Integer, Long> handleMap = new HashMap<>();

/**
* <b>IMPORTANT:</b> 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 zoomLevel 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 zoomLevel) {
if(region.handleMap.get(zoomLevel) == null) {
Rectangle rect = DPIUtil.autoScaleBounds(region.getBounds(), zoomLevel, region.initialZoom);
region.handleMap.put(zoomLevel, OS.CreateRectRgn(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height));
}
return region.handleMap.get(zoomLevel);
}

/**
Expand Down Expand Up @@ -650,4 +684,4 @@ public static Region win32_new(Device device, int handle) {
return new Region(device, handle);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3686,7 +3686,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;
Expand Down

0 comments on commit b4dcb80

Please sign in to comment.