@@ -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
172205private Image (Device device , int type , long handle , int nativeZoom ) {
173206 super (device );
@@ -854,15 +887,8 @@ interface HandleAtSizeConsumer {
854887}
855888
856889void 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
10981124private 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