Skip to content

Commit 4ea8b2b

Browse files
committed
[Win32] Reuse zoom handle for drawing image at size if appropriate
When drawing an image at a specified size, currently a new image handle is always created based on on-demand loaded image data. In case the fallback to loading image data for the best fitting zoom is used, a handle for that zoom may already exist and could be reused but is currently not considered. With this change, an existing handle is used if appropriate instead of unnecessarily creating a temporary handle.
1 parent 2b554d9 commit 4ea8b2b

File tree

1 file changed

+47
-37
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+47
-37
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -141,33 +141,66 @@ public final class Image extends Resource implements Drawable {
141141

142142
private List<Consumer<Image>> onDisposeListeners;
143143

144-
private record CachedHandle(ImageHandle handleContainer, int requestedWidth, int requestedHeight) {
144+
private class HandleAtSize {
145+
private ImageHandle handleContainer = null;
146+
private int requestedWidth = -1;
147+
private int requestedHeight = -1;
145148

146149
public void destroy() {
147-
if (handleContainer != null) {
150+
if (handleContainer != null && !zoomLevelToImageHandle.containsValue(handleContainer)) {
148151
handleContainer.destroy();
149152
}
153+
handleContainer = null;
154+
requestedWidth = -1;
155+
requestedHeight = -1;
150156
}
151157

152-
public boolean isReusable(int height, int width) {
153-
if(handleContainer == null) {
158+
public ImageHandle refresh(int width, int height) {
159+
if (!isReusable(width, height)) {
160+
destroy();
161+
requestedWidth = width;
162+
requestedHeight = height;
163+
handleContainer = createHandleAtExactSize(width, height)
164+
.orElseGet(() -> getOrCreateImageHandleAtClosestSize(width, height));
165+
}
166+
return handleContainer;
167+
}
168+
169+
private boolean isReusable(int width, int height) {
170+
if (handleContainer == null) {
154171
return false;
155172
}
156173
return (requestedHeight == height && requestedWidth == width)
157174
|| (handleContainer.height == height && handleContainer.width == width);
175+
}
158176

177+
private Optional<ImageHandle> createHandleAtExactSize(int widthHint, int heightHint) {
178+
Optional<ImageData> imageData = imageProvider.loadImageDataAtExactSize(widthHint, heightHint);
179+
if (imageData.isPresent()) {
180+
ImageData adaptedData = adaptImageDataIfDisabledOrGray(imageData.get());
181+
ImageHandle imageHandle = init(adaptedData, -1);
182+
return Optional.of(imageHandle);
183+
}
184+
return Optional.empty();
159185
}
160186

161-
public long getHandle() {
162-
if (handleContainer != null) {
163-
return handleContainer.handle;
187+
private ImageHandle getOrCreateImageHandleAtClosestSize(int widthHint, int heightHint) {
188+
Rectangle bounds = getBounds(100);
189+
int imageZoomForWidth = 100 * widthHint / bounds.width;
190+
int imageZoomForHeight = 100 * heightHint / bounds.height;
191+
int imageZoom = DPIUtil.getZoomForAutoscaleProperty(Math.max(imageZoomForWidth, imageZoomForHeight));
192+
ImageHandle bestFittingHandle = zoomLevelToImageHandle.get(imageZoom);
193+
if (bestFittingHandle == null) {
194+
ImageData bestFittingImageData = imageProvider.loadImageData(imageZoom).element();
195+
ImageData adaptedData = adaptImageDataIfDisabledOrGray(bestFittingImageData);
196+
bestFittingHandle = init(adaptedData, -1);
164197
}
165-
return -1;
198+
return bestFittingHandle;
166199
}
167-
};
168200

169-
// Initialize lastRequestedHandle with -1 for size-related fields to indicate uninitialized values
170-
CachedHandle lastRequestedHandle = new CachedHandle(null, -1, -1);
201+
}
202+
203+
private final HandleAtSize lastRequestedHandle = new HandleAtSize();
171204

172205
private Image (Device device, int type, long handle, int nativeZoom) {
173206
super(device);
@@ -854,15 +887,8 @@ interface HandleAtSizeConsumer {
854887
}
855888

856889
void executeOnImageHandleAtSize(HandleAtSizeConsumer handleAtSizeConsumer, int widthHint, int heightHint) {
857-
if (!lastRequestedHandle.isReusable(heightHint, widthHint)) {
858-
ImageData imageData;
859-
imageData = this.imageProvider.loadImageDataAtSize(widthHint, heightHint);
860-
lastRequestedHandle.destroy();
861-
ImageHandle handleContainer = init(imageData, -1);
862-
lastRequestedHandle = new CachedHandle(handleContainer, widthHint, heightHint);
863-
}
864-
handleAtSizeConsumer.accept(lastRequestedHandle.getHandle(),
865-
new Point(lastRequestedHandle.handleContainer().width, lastRequestedHandle.handleContainer().height));
890+
ImageHandle imageHandle = lastRequestedHandle.refresh(widthHint, heightHint);
891+
handleAtSizeConsumer.accept(imageHandle.handle, new Point(imageHandle.width, imageHandle.height));
866892
}
867893

868894
/**
@@ -1096,8 +1122,8 @@ void destroy () {
10961122
}
10971123

10981124
private void destroyHandles() {
1099-
destroyHandles(__ -> true);
11001125
lastRequestedHandle.destroy();
1126+
destroyHandles(__ -> true);
11011127
}
11021128

11031129
@Override
@@ -2007,22 +2033,6 @@ ElementAtZoom<ImageData> getClosestAvailableImageData(int zoom) {
20072033
return new ElementAtZoom<>(getImageMetadata(new ZoomContext(closestZoom)).getImageData(), closestZoom);
20082034
}
20092035

2010-
public ImageData loadImageDataAtSize(int widthHint, int heightHint) {
2011-
Optional<ImageData> exact = loadImageDataAtExactSize(widthHint, heightHint);
2012-
if (exact.isPresent()) {
2013-
return adaptImageDataIfDisabledOrGray(exact.get());
2014-
}
2015-
return loadImageDataClosestTo(widthHint, heightHint);
2016-
}
2017-
2018-
private ImageData loadImageDataClosestTo(int targetWidth, int targetHeight) {
2019-
Rectangle bounds = getBounds(100);
2020-
int imageZoomForWidth = 100 * targetWidth / bounds.width;
2021-
int imageZoomForHeight = 100 * targetHeight / bounds.height;
2022-
int imageZoom = DPIUtil.getZoomForAutoscaleProperty(Math.max(imageZoomForWidth, imageZoomForHeight));
2023-
return loadImageData(imageZoom).element();
2024-
}
2025-
20262036
protected Optional<ImageData> loadImageDataAtExactSize(int width, int height) {
20272037
return Optional.empty(); // exact size not available
20282038
}

0 commit comments

Comments
 (0)