This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 2b924c6f3f Fix Hop Web ClassNotFoundException for ImageDataProvider
after #7955 (#7980)
2b924c6f3f is described below
commit 2b924c6f3f3f66c8328825a69a99865d5ae6479b
Author: Lance <[email protected]>
AuthorDate: Sun Aug 16 19:07:09 2026 +0800
Fix Hop Web ClassNotFoundException for ImageDataProvider after #7955 (#7980)
Signed-off-by: lance <[email protected]>
---
.../org/apache/hop/core/SwtDesktopDpiImages.java | 42 ++++++++++++++++++++++
.../org/apache/hop/core/SwtUniversalImage.java | 30 ++++++++++------
.../org/apache/hop/core/SwtUniversalImageTest.java | 15 ++++++++
3 files changed, 77 insertions(+), 10 deletions(-)
diff --git a/ui/src/main/java/org/apache/hop/core/SwtDesktopDpiImages.java
b/ui/src/main/java/org/apache/hop/core/SwtDesktopDpiImages.java
new file mode 100644
index 0000000000..157d5de718
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/core/SwtDesktopDpiImages.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.core;
+
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageDataProvider;
+
+/**
+ * Desktop SWT HiDPI image helpers. RAP/RWT does not ship {@link
ImageDataProvider} or {@link
+ * Image#getImageData(int)}, so this class must never be loaded on Hop Web.
Keep all references
+ * behind {@code SWT.getPlatform() != "rap"} in {@link SwtUniversalImage}.
+ */
+final class SwtDesktopDpiImages {
+
+ private SwtDesktopDpiImages() {}
+
+ static Image create(Device device, SwtUniversalImage.ImageDataAtZoom
renderer) {
+ ImageDataProvider provider = renderer::render;
+ return new Image(device, provider);
+ }
+
+ static ImageData getImageData(Image image, int zoom) {
+ return image.getImageData(zoom);
+ }
+}
diff --git a/ui/src/main/java/org/apache/hop/core/SwtUniversalImage.java
b/ui/src/main/java/org/apache/hop/core/SwtUniversalImage.java
index b57f419f30..e2804fe4fe 100644
--- a/ui/src/main/java/org/apache/hop/core/SwtUniversalImage.java
+++ b/ui/src/main/java/org/apache/hop/core/SwtUniversalImage.java
@@ -25,7 +25,6 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.ImageDataProvider;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
@@ -121,9 +120,10 @@ public abstract class SwtUniversalImage {
/**
* SWT 3.134+ on Windows treats {@code new Image(device, ImageData)} as 100%
zoom and
- * raster-scales it to the monitor zoom (SMOOTH), which makes icons blurry
at 200% DPI. {@link
- * ImageDataProvider} re-rasterize at the requested zoom instead. RAP has no
per-monitor zoom, so
- * keep the ImageData constructor there.
+ * raster-scales it to the monitor zoom (SMOOTH), which makes icons blurry
at 200% DPI. Desktop
+ * SWT re-rasterizes via ImageDataProvider instead. RAP has no per-monitor
zoom and does not ship
+ * that type, so keep the ImageData constructor there and never link the
desktop API from this
+ * class.
*/
static boolean isDpiAwareImageProviderSupported() {
return !"rap".equals(SWT.getPlatform());
@@ -131,7 +131,7 @@ public abstract class SwtUniversalImage {
/**
* Pixel size of a logical extent at an SWT zoom percentage. Must be linear
({@code 200} → {@code
- * 2 * 100}) to satisfy the {@link ImageDataProvider} contract.
+ * 2 * 100}) to satisfy the desktop ImageDataProvider contract.
*/
static int pixelSize(int logical, int zoom) {
return Math.max(1, logical * zoom / 100);
@@ -139,19 +139,20 @@ public abstract class SwtUniversalImage {
/**
* Creates an {@link Image} that can supply native pixels for every SWT
zoom. On RAP the 100%
- * variant is used as-is.
+ * variant is used as-is. The renderer type is Hop-owned so RAP class
loading does not resolve
+ * desktop-only {@code org.eclipse.swt.graphics.ImageDataProvider}.
*/
- public static Image createDpiAwareImage(Device device, ImageDataProvider
provider) {
+ public static Image createDpiAwareImage(Device device, ImageDataAtZoom
renderer) {
if (!isDpiAwareImageProviderSupported()) {
- return new Image(device, provider.getImageData(100));
+ return new Image(device, renderer.render(100));
}
- return new Image(device, provider);
+ return SwtDesktopDpiImages.create(device, renderer);
}
/** ImageData at the given zoom, with a RAP-safe fallback that scales the
100% variant. */
public static ImageData getImageDataAtZoom(Image image, int zoom) {
if (isDpiAwareImageProviderSupported()) {
- return image.getImageData(zoom);
+ return SwtDesktopDpiImages.getImageData(image, zoom);
}
ImageData data = image.getImageData();
if (zoom == 100) {
@@ -190,6 +191,15 @@ public abstract class SwtUniversalImage {
return new Image(device, toImageData(img));
}
+ /**
+ * Supplies {@link ImageData} for an SWT zoom percentage (100, 150, 200, …).
Same contract as
+ * desktop ImageDataProvider, without depending on that RAP-missing type.
+ */
+ @FunctionalInterface
+ public interface ImageDataAtZoom {
+ ImageData render(int zoom);
+ }
+
@FunctionalInterface
protected interface ImageDataAtSize {
ImageData render(int width, int height);
diff --git a/ui/src/test/java/org/apache/hop/core/SwtUniversalImageTest.java
b/ui/src/test/java/org/apache/hop/core/SwtUniversalImageTest.java
index 95f4f1ce8e..da2a413384 100644
--- a/ui/src/test/java/org/apache/hop/core/SwtUniversalImageTest.java
+++ b/ui/src/test/java/org/apache/hop/core/SwtUniversalImageTest.java
@@ -18,8 +18,11 @@
package org.apache.hop.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import java.awt.image.BufferedImage;
+import java.lang.reflect.Method;
+import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.ImageData;
import org.junit.jupiter.api.Test;
@@ -44,4 +47,16 @@ class SwtUniversalImageTest {
assertEquals(8, data.height);
assertEquals(0x80, data.getAlpha(0, 0));
}
+
+ @Test
+ void createDpiAwareImageSignatureDoesNotReferenceDesktopImageDataProvider()
throws Exception {
+ Method method =
+ SwtUniversalImage.class.getMethod(
+ "createDpiAwareImage", Device.class,
SwtUniversalImage.ImageDataAtZoom.class);
+ for (Class<?> type : method.getParameterTypes()) {
+ assertFalse(
+ type.getName().contains("ImageDataProvider"),
+ "RAP class loading resolves method signatures; keep
ImageDataProvider off this API");
+ }
+ }
}