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 3c2b278529d..3cbff0ea90a 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
@@ -198,9 +198,9 @@ void checkGC(int mask) {
Pattern pattern = data.foregroundPattern;
if (pattern != null) {
if(data.alpha == 0xFF) {
- brush = pattern.handle;
+ brush = pattern.getHandle(getZoom());
} else {
- brush = data.gdipFgPatternBrushAlpha != 0 ? Gdip.Brush_Clone(data.gdipFgPatternBrushAlpha) : createAlphaTextureBrush(pattern.handle, data.alpha);
+ brush = data.gdipFgPatternBrushAlpha != 0 ? Gdip.Brush_Clone(data.gdipFgPatternBrushAlpha) : createAlphaTextureBrush(pattern.getHandle(getZoom()), data.alpha);
data.gdipFgPatternBrushAlpha = brush;
}
if ((data.style & SWT.MIRRORED) != 0) {
@@ -289,9 +289,9 @@ void checkGC(int mask) {
Pattern pattern = data.backgroundPattern;
if (pattern != null) {
if(data.alpha == 0xFF) {
- data.gdipBrush = pattern.handle;
+ data.gdipBrush = pattern.getHandle(getZoom());
} else {
- long brush = data.gdipBgPatternBrushAlpha != 0 ? Gdip.Brush_Clone(data.gdipBgPatternBrushAlpha) : createAlphaTextureBrush(pattern.handle, data.alpha);
+ long brush = data.gdipBgPatternBrushAlpha != 0 ? Gdip.Brush_Clone(data.gdipBgPatternBrushAlpha) : createAlphaTextureBrush(pattern.getHandle(getZoom()), data.alpha);
data.gdipBrush = data.gdipBgBrush /*= data.gdipBgPatternBrushAlpha */ = brush;
}
if ((data.style & SWT.MIRRORED) != 0) {
@@ -3440,7 +3440,7 @@ public void getClipping (Region region) {
}
long getFgBrush() {
- return data.foregroundPattern != null ? data.foregroundPattern.handle : data.gdipFgBrush;
+ return data.foregroundPattern != null ? data.foregroundPattern.getHandle(getZoom()) : data.gdipFgBrush;
}
/**
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java
index 38a9eb8629a..e4ed934cbf6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java
@@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.swt.graphics;
+import java.util.*;
+
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gdip.*;
@@ -39,22 +41,19 @@
*/
public class Pattern extends Resource {
- /**
- * the OS resource for the Pattern
- * (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 Runnable bitmapDestructor;
+ private Image image;
+
+ private float x1, y1, x2, y2;
+ private Color color1, color2;
+ private int alpha1, alpha2;
+ private final boolean isImagePattern;
+
+ private HashMap handleMap = new HashMap<>();
+
/**
* Constructs a new Pattern given an image. Drawing with the resulting
* pattern will cause the image to be tiled over the resulting area.
@@ -85,14 +84,23 @@ public class Pattern extends Resource {
*/
public Pattern(Device device, Image image) {
super(device);
+ isImagePattern = true;
if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
this.device.checkGDIP();
- long[] gdipImage = image.createGdipImage();
+ this.image = image;
+ initialZoom = DPIUtil.getDeviceZoom();
+ setImageHandle(image, initialZoom);
+ init();
+}
+
+void setImageHandle(Image image, int zoomLevel) {
+ long[] gdipImage = image.createGdipImage(zoomLevel);
long img = gdipImage[0];
int width = Gdip.Image_GetWidth(img);
int height = Gdip.Image_GetHeight(img);
- handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
+ long handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
+ handleMap.put(zoomLevel, handle);
bitmapDestructor = () -> {
Gdip.Bitmap_delete(img);
if (gdipImage[1] != 0) {
@@ -104,7 +112,6 @@ public Pattern(Device device, Image image) {
bitmapDestructor.run();
SWT.error(SWT.ERROR_NO_HANDLES);
}
- init();
}
/**
@@ -187,10 +194,37 @@ public Pattern(Device device, float x1, float y1, float x2, float y2, Color colo
*/
public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
super(device);
- x1 = DPIUtil.autoScaleUp(x1);
- y1 = DPIUtil.autoScaleUp(y1);
- x2 = DPIUtil.autoScaleUp(x2);
- y2 = DPIUtil.autoScaleUp(y2);
+ this.x1 = x1;
+ this.x2 = x2;
+ this.y1 = y1;
+ this.y2 = y2;
+ this.color1 = color1;
+ this.color2 = color2;
+ this.alpha1 = alpha1;
+ this.alpha2 = alpha2;
+ this.isImagePattern = false;
+ initialZoom = DPIUtil.getDeviceZoom();
+ initializeSize(initialZoom);
+}
+
+long getHandle(int zoomLevel) {
+ if(!this.handleMap.containsKey(zoomLevel)) {
+ if (this.isImagePattern) {
+ setImageHandle(image, zoomLevel);
+ } else {
+ initializeSize(zoomLevel);
+ }
+ }
+ return this.handleMap.get(zoomLevel);
+}
+
+private void initializeSize(int zoomLevel) {
+ float x1, y1, x2, y2;
+ long handle;
+ x1 = DPIUtil.autoScaleUp(this.x1, zoomLevel);
+ y1 = DPIUtil.autoScaleUp(this.y1, zoomLevel);
+ x2 = DPIUtil.autoScaleUp(this.x2, zoomLevel);
+ y2 = DPIUtil.autoScaleUp(this.y2, zoomLevel);
if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
@@ -221,27 +255,32 @@ public Pattern(Device device, float x1, float y1, float x2, float y2, Color colo
Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int [] {foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3);
}
}
+ this.handleMap.put(zoomLevel, handle);
init();
}
+
+
@Override
void destroy() {
- int type = Gdip.Brush_GetType(handle);
- switch (type) {
- case Gdip.BrushTypeSolidColor:
- Gdip.SolidBrush_delete(handle);
- break;
- case Gdip.BrushTypeHatchFill:
- Gdip.HatchBrush_delete(handle);
- break;
- case Gdip.BrushTypeLinearGradient:
- Gdip.LinearGradientBrush_delete(handle);
- break;
- case Gdip.BrushTypeTextureFill:
- Gdip.TextureBrush_delete(handle);
- break;
+ for (long handle: handleMap.values()) {
+ int type = Gdip.Brush_GetType(handle);
+ switch (type) {
+ case Gdip.BrushTypeSolidColor:
+ Gdip.SolidBrush_delete(handle);
+ break;
+ case Gdip.BrushTypeHatchFill:
+ Gdip.HatchBrush_delete(handle);
+ break;
+ case Gdip.BrushTypeLinearGradient:
+ Gdip.LinearGradientBrush_delete(handle);
+ break;
+ case Gdip.BrushTypeTextureFill:
+ Gdip.TextureBrush_delete(handle);
+ break;
+ }
}
- handle = 0;
+ handleMap.clear();
if (bitmapDestructor != null) {
bitmapDestructor.run();
bitmapDestructor = null;
@@ -260,7 +299,7 @@ void destroy() {
*/
@Override
public boolean isDisposed() {
- return handle == 0;
+ return handleMap.isEmpty();
}
/**
@@ -272,7 +311,7 @@ public boolean isDisposed() {
@Override
public String toString() {
if (isDisposed()) return "Pattern {*DISPOSED*}";
- return "Pattern {" + handle + "}";
+ return "Pattern {" + handleMap + "}";
}
-}
+}
\ No newline at end of file
diff --git a/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/widgets/PatternWin32ManualTest.java b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/widgets/PatternWin32ManualTest.java
new file mode 100644
index 00000000000..9c2de14ae70
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/widgets/PatternWin32ManualTest.java
@@ -0,0 +1,51 @@
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Pattern;
+import org.eclipse.swt.internal.DPIUtil;
+
+public class PatternWin32ManualTest {
+ private static Display display = Display.getDefault();
+
+ public static void main (String [] args) {
+ int zoom = DPIUtil.getDeviceZoom();
+ int scaledZoom = zoom * 3;
+ int width = 400;
+ int height = 300;
+ final Pattern pat = new Pattern(display, 0, 0, width, height, new Color(null, 200, 200, 200), 0, new Color(null, 255, 0, 0), 255);
+
+ Shell shell = new Shell(display);
+ shell.setText("Unscaled shell");
+ shell.setSize(width, height);
+ shell.addPaintListener(e -> {
+ e.gc.setBackground(new Color(null, 100, 200, 0));
+ e.gc.fillRectangle(0, 0, shell.getBounds().width, shell.getBounds().height);
+ e.gc.setBackground(new Color(null, 255, 0, 0));
+ e.gc.setBackgroundPattern(pat);
+ e.gc.fillRectangle(0, 0, shell.getBounds().width, shell.getBounds().height);
+ });
+ shell.open();
+
+ DPIUtil.setDeviceZoom(scaledZoom);
+ Shell shell2 = new Shell(display);
+ shell2.nativeZoom = scaledZoom;
+ shell2.setText("Scaled shell");
+ shell2.setSize(width, height);
+ shell2.addPaintListener(e -> {
+ e.gc.setBackground(new Color(null, 100, 200, 0));
+ e.gc.fillRectangle(0, 0, shell2.getBounds().width, shell2.getBounds().height);
+ e.gc.setBackground(new Color(null, 255, 0, 0));
+ e.gc.setBackgroundPattern(pat);
+ e.gc.fillRectangle(0, 0, shell2.getBounds().width, shell2.getBounds().height);
+ });
+ shell2.open();
+
+ while (!shell.isDisposed() || !shell2.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ pat.dispose();
+ shell.dispose();
+ shell2.dispose();
+ }
+}