Skip to content

Commit 3c87f89

Browse files
HeikoKlareakoch-yatta
authored andcommitted
[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 1c00a22 commit 3c87f89

File tree

1 file changed

+48
-34
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+48
-34
lines changed

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

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -136,30 +136,66 @@ public final class Image extends Resource implements Drawable {
136136

137137
private List<Consumer<Image>> onDisposeListeners;
138138

139-
private record CachedHandle(ImageHandle handleContainer, int requestedWidth, int requestedHeight) {
139+
private class HandleAtSize {
140+
private ImageHandle handleContainer = null;
141+
private int requestedWidth = -1;
142+
private int requestedHeight = -1;
140143

141144
public void destroy() {
142-
if (handleContainer != null) {
145+
if (handleContainer != null && !zoomLevelToImageHandle.containsValue(handleContainer)) {
143146
handleContainer.destroy();
144147
}
148+
handleContainer = null;
149+
requestedWidth = -1;
150+
requestedHeight = -1;
145151
}
146152

147-
public boolean isReusable(int height, int width) {
148-
if(handleContainer == null) {
153+
public ImageHandle refresh(int width, int height) {
154+
if (!isReusable(width, height)) {
155+
destroy();
156+
requestedWidth = width;
157+
requestedHeight = height;
158+
handleContainer = createHandleAtExactSize(width, height)
159+
.orElseGet(() -> getOrCreateImageHandleAtClosestSize(width, height));
160+
}
161+
return handleContainer;
162+
}
163+
164+
private boolean isReusable(int width, int height) {
165+
if (handleContainer == null || handleContainer.isDisposed()) {
149166
return false;
150167
}
151168
return (requestedHeight == height && requestedWidth == width)
152169
|| (handleContainer.height == height && handleContainer.width == width);
170+
}
153171

172+
private Optional<ImageHandle> createHandleAtExactSize(int width, int height) {
173+
Optional<ImageData> imageData = imageProvider.loadImageDataAtExactSize(width, height);
174+
if (imageData.isPresent()) {
175+
ImageData adaptedData = adaptImageDataIfDisabledOrGray(imageData.get());
176+
ImageHandle imageHandle = init(adaptedData, -1);
177+
return Optional.of(imageHandle);
178+
}
179+
return Optional.empty();
154180
}
155181

156-
public ImageHandle getHandle() {
157-
return handleContainer;
182+
private ImageHandle getOrCreateImageHandleAtClosestSize(int widthHint, int heightHint) {
183+
Rectangle bounds = getBounds(100);
184+
int imageZoomForWidth = 100 * widthHint / bounds.width;
185+
int imageZoomForHeight = 100 * heightHint / bounds.height;
186+
int imageZoom = DPIUtil.getZoomForAutoscaleProperty(Math.max(imageZoomForWidth, imageZoomForHeight));
187+
ImageHandle bestFittingHandle = zoomLevelToImageHandle.get(imageZoom);
188+
if (bestFittingHandle == null) {
189+
ImageData bestFittingImageData = imageProvider.loadImageData(imageZoom).element();
190+
ImageData adaptedData = adaptImageDataIfDisabledOrGray(bestFittingImageData);
191+
bestFittingHandle = init(adaptedData, -1);
192+
}
193+
return bestFittingHandle;
158194
}
159-
};
160195

161-
// Initialize lastRequestedHandle with -1 for size-related fields to indicate uninitialized values
162-
CachedHandle lastRequestedHandle = new CachedHandle(null, -1, -1);
196+
}
197+
198+
private final HandleAtSize lastRequestedHandle = new HandleAtSize();
163199

164200
private Image (Device device, int type, long handle, int nativeZoom) {
165201
super(device);
@@ -840,14 +876,8 @@ ImageHandle getHandle (int targetZoom, int nativeZoom) {
840876
}
841877

842878
void executeOnImageHandleAtBestFittingSize(Consumer<ImageHandle> handleAtSizeConsumer, int widthHint, int heightHint) {
843-
if (!lastRequestedHandle.isReusable(heightHint, widthHint)) {
844-
ImageData imageData;
845-
imageData = this.imageProvider.loadImageDataAtSize(widthHint, heightHint);
846-
lastRequestedHandle.destroy();
847-
ImageHandle handleContainer = init(imageData, -1);
848-
lastRequestedHandle = new CachedHandle(handleContainer, widthHint, heightHint);
849-
}
850-
handleAtSizeConsumer.accept(lastRequestedHandle.getHandle());
879+
ImageHandle imageHandle = lastRequestedHandle.refresh(widthHint, heightHint);
880+
handleAtSizeConsumer.accept(imageHandle);
851881
}
852882

853883
/**
@@ -1083,8 +1113,8 @@ void destroy () {
10831113
}
10841114

10851115
private void destroyHandles() {
1086-
destroyHandles(__ -> true);
10871116
lastRequestedHandle.destroy();
1117+
destroyHandles(__ -> true);
10881118
}
10891119

10901120
@Override
@@ -1992,22 +2022,6 @@ ElementAtZoom<ImageData> getClosestAvailableImageData(int zoom) {
19922022
return new ElementAtZoom<>(getImageMetadata(new ZoomContext(closestZoom)).getImageData(), closestZoom);
19932023
}
19942024

1995-
public ImageData loadImageDataAtSize(int widthHint, int heightHint) {
1996-
Optional<ImageData> exact = loadImageDataAtExactSize(widthHint, heightHint);
1997-
if (exact.isPresent()) {
1998-
return adaptImageDataIfDisabledOrGray(exact.get());
1999-
}
2000-
return loadImageDataClosestTo(widthHint, heightHint);
2001-
}
2002-
2003-
private ImageData loadImageDataClosestTo(int targetWidth, int targetHeight) {
2004-
Rectangle bounds = getBounds(100);
2005-
int imageZoomForWidth = 100 * targetWidth / bounds.width;
2006-
int imageZoomForHeight = 100 * targetHeight / bounds.height;
2007-
int imageZoom = DPIUtil.getZoomForAutoscaleProperty(Math.max(imageZoomForWidth, imageZoomForHeight));
2008-
return loadImageData(imageZoom).element();
2009-
}
2010-
20112025
protected Optional<ImageData> loadImageDataAtExactSize(int width, int height) {
20122026
return Optional.empty(); // exact size not available
20132027
}

0 commit comments

Comments
 (0)