From 595fc0b2cac68296ce1eef9654f948f098f2f519 Mon Sep 17 00:00:00 2001 From: arunjose696 Date: Mon, 11 Aug 2025 14:44:03 +0200 Subject: [PATCH] Unify strict checks and extend ImageDataProvider checks to GTK and Cocoa Move strict checks into a separate class. Extend strict check to verify if imageData is linearly scaled by an ImageDataProvider in GTK and Cocoa implementations. --- .../cocoa/org/eclipse/swt/graphics/Image.java | 22 +++++++--- .../org/eclipse/swt/internal/DPIUtil.java | 20 +++++++++ .../eclipse/swt/internal/StrictChecks.java | 40 +++++++++++++++++ .../gtk/org/eclipse/swt/graphics/Image.java | 21 ++++++--- .../gtk/org/eclipse/swt/widgets/Display.java | 6 +-- .../gtk/org/eclipse/swt/widgets/Shell.java | 4 +- .../org/eclipse/swt/graphics/Device.java | 2 - .../win32/org/eclipse/swt/graphics/GC.java | 8 ++-- .../win32/org/eclipse/swt/graphics/Image.java | 44 +++++-------------- 9 files changed, 109 insertions(+), 58 deletions(-) create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/StrictChecks.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java index 1e101a8e614..0dc7f5e36d5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java @@ -850,6 +850,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) { try { init (data, 100); init (); + StrictChecks.runIfStrictChecksEnabled(() -> { + DPIUtil.validateLinearScaling(imageDataProvider); + }); ImageData data2x = imageDataProvider.getImageData (200); if (data2x != null) { alphaInfo_200 = new AlphaInfo(); @@ -1822,13 +1825,18 @@ public String toString () { * @noreference This method is not intended to be referenced by clients. */ public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) { - Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); - gc.drawImage (imageToDraw, 0, 0, CocoaDPIUtil.pixelToPoint (width), CocoaDPIUtil.pixelToPoint (height), - /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors. - * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..). - */ - 0, 0, Math.round (CocoaDPIUtil.pixelToPoint (width * scaleFactor)), Math.round (CocoaDPIUtil.pixelToPoint (height * scaleFactor))); - imageToDraw.dispose(); + StrictChecks.runWithStrictChecksDisabled(() -> { + Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); + gc.drawImage(imageToDraw, 0, 0, CocoaDPIUtil.pixelToPoint(width), CocoaDPIUtil.pixelToPoint(height), + /* + * E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but + * avoiding rounding errors. Nevertheless, we still have some rounding errors + * due to the point-based API GC#drawImage(..). + */ + 0, 0, Math.round(CocoaDPIUtil.pixelToPoint(width * scaleFactor)), + Math.round(CocoaDPIUtil.pixelToPoint(height * scaleFactor))); + imageToDraw.dispose(); + }); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java index 6dce4cff809..44d67e71408 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java @@ -223,6 +223,26 @@ public static int mapZoomToDPI (int zoom) { return roundedDpi; } +public static void validateLinearScaling(ImageDataProvider provider) { + final int baseZoom = 100; + final int scaledZoom = 200; + final int scaleFactor = scaledZoom / baseZoom; + ImageData baseImageData = provider.getImageData(baseZoom); + ImageData scaledImageData = provider.getImageData(scaledZoom); + + if (scaledImageData == null) { + return; + } + + if (scaledImageData.width != scaleFactor * baseImageData.width + || scaledImageData.height != scaleFactor * baseImageData.height) { + System.err.println(String.format( + "***WARNING: ImageData should be linearly scaled across zooms but size is (%d, %d) at 100%% and (%d, %d) at 200%%.", + baseImageData.width, baseImageData.height, scaledImageData.width, scaledImageData.height)); + new Error().printStackTrace(System.err); + } +} + /** * Represents an element, such as some image data, at a specific zoom level. * diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/StrictChecks.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/StrictChecks.java new file mode 100644 index 00000000000..1a3ef48482f --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/StrictChecks.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2025 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.internal; + +public final class StrictChecks { + + private static final boolean STRICT_CHECKS_ENABLED = System + .getProperty("org.eclipse.swt.internal.enableStrictChecks") != null; + + private static boolean temporarilyDisabled = false; + + private StrictChecks() { + } + + public static void runIfStrictChecksEnabled(Runnable runnable) { + if (STRICT_CHECKS_ENABLED && !temporarilyDisabled) { + runnable.run(); + } + } + + public static void runWithStrictChecksDisabled(Runnable runnable) { + temporarilyDisabled = true; + try { + runnable.run(); + } finally { + temporarilyDisabled = false; + } + } +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java index bea752b53af..f77c83f79e9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java @@ -672,6 +672,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) { currentDeviceZoom = DPIUtil.getDeviceZoom(); initFromImageDataProvider(currentDeviceZoom); init (); + StrictChecks.runIfStrictChecksEnabled(() -> { + DPIUtil.validateLinearScaling(imageDataProvider); + }); } /** @@ -1583,13 +1586,17 @@ public String toString () { * @noreference This method is not intended to be referenced by clients. */ public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) { - Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); - gc.drawImage (imageToDraw, 0, 0, width, height, - /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors. - * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..). - */ - 0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor)); - imageToDraw.dispose(); + StrictChecks.runWithStrictChecksDisabled(() -> { + Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); + gc.drawImage(imageToDraw, 0, 0, width, height, + /* + * E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but + * avoiding rounding errors. Nevertheless, we still have some rounding errors + * due to the point-based API GC#drawImage(..). + */ + 0, 0, Math.round(width * scaleFactor), Math.round(height * scaleFactor)); + imageToDraw.dispose(); + }); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index 8e690f9d907..5b52c106f48 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -116,8 +116,6 @@ */ public class Display extends Device implements Executor { - static boolean strictChecks = System.getProperty("org.eclipse.swt.internal.enableStrictChecks") != null; - private static final int SLOT_IN_USE = -2; private static final int LAST_TABLE_INDEX = -1; @@ -880,12 +878,12 @@ void addWidget (long handle, Widget widget) { widgetTable = newWidgetTable; } int index = freeSlot + 1; - if(strictChecks) { + StrictChecks.runIfStrictChecksEnabled(() -> { long data = OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX); if(data > 0 && data != index) { SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, ". Potential leak of " + widget + debugInfoForIndex(data - 1)); } - } + }); OS.g_object_set_qdata (handle, SWT_OBJECT_INDEX, index); int oldSlot = freeSlot; freeSlot = indexTable[oldSlot]; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java index e05bb6c4ce1..0e46e1c5cec 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java @@ -3258,14 +3258,14 @@ void deregister () { if(shellHandle != 0 && !(disposed instanceof Shell)) { SWT.error(SWT.ERROR_INVALID_RETURN_VALUE, null, ". Wrong widgetTable entry: " + disposed + " removed for shell: " + this + display.dumpWidgetTableInfo()); } - if(Display.strictChecks) { + StrictChecks.runIfStrictChecksEnabled(() -> { Shell[] shells = display.getShells(); for (Shell shell : shells) { if(shell == this) { SWT.error(SWT.ERROR_INVALID_RETURN_VALUE, null, ". Disposed shell still in the widgetTable: " + this + display.dumpWidgetTableInfo()); } } - } + }); } boolean requiresUngrab () { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java index 887218f7c36..8d666f333f3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java @@ -34,8 +34,6 @@ */ public abstract class Device implements Drawable { - static boolean strictChecks = System.getProperty("org.eclipse.swt.internal.enableStrictChecks") != null; - /* Debugging */ public static boolean DEBUG; boolean debug = DEBUG; 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 1130ea0518c..1e48a77a51d 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 @@ -210,9 +210,9 @@ private void validateGCState() { } void checkGC(int mask) { - if (Device.strictChecks) { + StrictChecks.runIfStrictChecksEnabled(() -> { validateGCState(); - } + }); int state = data.state; if ((state & mask) == mask) return; state = (state ^ mask) & mask; @@ -4402,10 +4402,10 @@ private void init(Drawable drawable, GCData data, long hDC) { } private static int extractZoom(long hDC) { - if (Device.strictChecks) { + StrictChecks.runIfStrictChecksEnabled(() -> { System.err.println("***WARNING: GC is initialized with a missing zoom. This indicates an " + "incompatible custom Drawable implementation."); - } + }); long hwnd = OS.WindowFromDC(hDC); long parentWindow = OS.GetAncestor(hwnd, OS.GA_ROOT); long monitorParent = OS.MonitorFromWindow(parentWindow, OS.MONITOR_DEFAULTTONEAREST); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index eced80e14cc..ccec341525b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -612,33 +612,13 @@ public Image(Device device, ImageDataProvider imageDataProvider) { SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, ": ImageDataProvider [" + imageDataProvider + "] returns null ImageData at 100% zoom."); } - if (Device.strictChecks) { - validateLinearScaling(imageDataProvider); - } + StrictChecks.runIfStrictChecksEnabled(() -> { + DPIUtil.validateLinearScaling(imageDataProvider); + }); init(); this.device.registerResourceWithZoomSupport(this); } -private void validateLinearScaling(ImageDataProvider provider) { - final int baseZoom = 100; - final int scaledZoom = 200; - final int scaleFactor = scaledZoom / baseZoom; - ImageData baseImageData = provider.getImageData(baseZoom); - ImageData scaledImageData = provider.getImageData(scaledZoom); - - if (scaledImageData == null) { - return; - } - - if (scaledImageData.width != scaleFactor * baseImageData.width - || scaledImageData.height != scaleFactor * baseImageData.height) { - System.err.println(String.format( - "***WARNING: ImageData should be linearly scaled across zooms but size is (%d, %d) at 100%% and (%d, %d) at 200%%.", - baseImageData.width, baseImageData.height, scaledImageData.width, scaledImageData.height)); - new Error().printStackTrace(System.err); - } -} - /** * The provided ImageGcDrawer will be called on demand whenever a new variant of the * Image for an additional zoom is required. Depending on the OS-specific implementation @@ -851,13 +831,13 @@ public static long win32_getHandle (Image image, int zoom) { * @noreference This method is not intended to be referenced by clients. */ public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) { - boolean originalStrictChecks = Device.strictChecks; - Device.strictChecks = false; - Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); - gc.drawImage (imageToDraw, 0, 0, width, height, - 0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor), false); - Device.strictChecks = originalStrictChecks; - imageToDraw.dispose(); + + StrictChecks.runWithStrictChecksDisabled(() -> { + Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData); + gc.drawImage(imageToDraw, 0, 0, width, height, 0, 0, Math.round(width * scaleFactor), + Math.round(height * scaleFactor), false); + imageToDraw.dispose(); + }); } long [] createGdipImage(Integer zoom) { @@ -1753,9 +1733,9 @@ private long configureGC(GCData data, ZoomContext zoomContext) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); } - if (Device.strictChecks) { + StrictChecks.runIfStrictChecksEnabled(() -> { checkImageTypeForValidCustomDrawing(zoomContext.targetZoom()); - } + }); /* Create a compatible HDC for the device */ long hDC = device.internal_new_GC(null); long imageDC = OS.CreateCompatibleDC(hDC);