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 14, 2024
1 parent 4c4074f commit 3147c73
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -3399,26 +3399,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 @@ -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);
}
Expand Down Expand Up @@ -4373,7 +4373,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 initalZoom;

/**
* Constructs a new empty region.
* <p>
Expand Down Expand Up @@ -84,7 +88,9 @@ public Region () {
*/
public Region (Device device) {
super(device);
initalZoom = DPIUtil.getDeviceZoom();
handle = OS.CreateRectRgn (0, 0, 0, 0);
handleMap.put(initalZoom, 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, initalZoom));
}

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, initalZoom);
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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom), DPIUtil.autoScaleUp(width, initalZoom), DPIUtil.autoScaleUp(height, initalZoom));
}

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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom));
}

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, initalZoom);
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(), initalZoom);
}

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, initalZoom);
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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom), DPIUtil.autoScaleUp(width, initalZoom), DPIUtil.autoScaleUp(height, initalZoom));
}

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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom), DPIUtil.autoScaleUp(width, initalZoom), DPIUtil.autoScaleUp(height, initalZoom));
}

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, initalZoom);
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, initalZoom));
}

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, initalZoom);
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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom), DPIUtil.autoScaleUp(width, initalZoom), DPIUtil.autoScaleUp(height, initalZoom));
}

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, initalZoom), DPIUtil.autoScaleUp(y, initalZoom));
}

void translateInPixels (int x, int y) {
Expand All @@ -614,8 +621,29 @@ 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, initalZoom);
translateInPixels(p.x, p.y);
}

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

/**
* 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
*
* @since 3.126
*/
public static long win32_getHandle(Region region, int zoomLevel) {
if(region.handleMap.get(zoomLevel) == null) {
Rectangle rect = DPIUtil.autoScaleBounds(region.getBounds(), zoomLevel, region.initalZoom);
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 +678,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
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.eclipse.swt.graphics;

import static org.junit.Assert.assertEquals;

import org.eclipse.swt.internal.DPIUtil;
import org.eclipse.swt.widgets.Display;
import org.junit.Before;
import org.junit.Test;

public class RegionWin32Tests {
private Display display;

@Before
public void setUp() {
display = Display.getDefault();
}

@Test
public void regionMustBeScaledOnHandleOfScaledZoomLevel() {
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);
}

}

0 comments on commit 3147c73

Please sign in to comment.