Skip to content

Commit 10cc2e6

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Introduce ZoomContext in Image
This commit extends the internal zoom used in Image in the windows implementation to a complex object. This is preparatory work to provide a consistent behavior independent of the auto scale mode, e.g. when an Image is drawn with a GC.
1 parent 51d6029 commit 10cc2e6

File tree

1 file changed

+90
-70
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+90
-70
lines changed

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

Lines changed: 90 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -803,11 +803,12 @@ private ImageData applyGrayImageData(ImageData data, int pHeight, int pWidth) {
803803
return newData;
804804
}
805805

806-
private ImageHandle getImageMetadata(int zoom) {
807-
if (zoomLevelToImageHandle.get(zoom) != null) {
808-
return zoomLevelToImageHandle.get(zoom);
806+
private ImageHandle getImageMetadata(ZoomContext zoomContext) {
807+
int targetZoom = zoomContext.targetZoom();
808+
if (zoomLevelToImageHandle.get(targetZoom) != null) {
809+
return zoomLevelToImageHandle.get(targetZoom);
809810
}
810-
return imageProvider.newImageHandle(zoom);
811+
return imageProvider.newImageHandle(zoomContext);
811812
}
812813

813814

@@ -828,10 +829,10 @@ private ImageHandle getImageMetadata(int zoom) {
828829
* @noreference This method is not intended to be referenced by clients.
829830
*/
830831
public static long win32_getHandle (Image image, int zoom) {
831-
if(image.isDisposed()) {
832+
if (image.isDisposed()) {
832833
return 0L;
833834
}
834-
return image.getImageMetadata(zoom).handle;
835+
return image.getImageMetadata(new ZoomContext(zoom)).handle;
835836
}
836837

837838
/**
@@ -1265,7 +1266,7 @@ public ImageData getImageData (int zoom) {
12651266
if (zoomLevelToImageHandle.containsKey(zoom)) {
12661267
return zoomLevelToImageHandle.get(zoom).getImageData();
12671268
}
1268-
return this.imageProvider.newImageData(zoom);
1269+
return this.imageProvider.newImageData(new ZoomContext(zoom));
12691270
}
12701271

12711272

@@ -1742,7 +1743,7 @@ public long internal_new_GC (GCData data) {
17421743
return this.imageProvider.configureGCData(data);
17431744
}
17441745

1745-
private long configureGC(GCData data, int zoom) {
1746+
private long configureGC(GCData data, ZoomContext zoomContext) {
17461747
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
17471748
/*
17481749
* Create a new GC that can draw into the image.
@@ -1753,7 +1754,7 @@ private long configureGC(GCData data, int zoom) {
17531754
}
17541755

17551756
if (Device.strictChecks) {
1756-
checkImageTypeForValidCustomDrawing(zoom);
1757+
checkImageTypeForValidCustomDrawing(zoomContext.targetZoom());
17571758
}
17581759
/* Create a compatible HDC for the device */
17591760
long hDC = device.internal_new_GC(null);
@@ -1770,9 +1771,9 @@ private long configureGC(GCData data, int zoom) {
17701771
data.style |= SWT.LEFT_TO_RIGHT;
17711772
}
17721773
data.device = device;
1773-
data.nativeZoom = zoom;
1774+
data.nativeZoom = zoomContext.nativeZoom();
17741775
data.image = this;
1775-
data.font = SWTFontProvider.getSystemFont(device, zoom);
1776+
data.font = SWTFontProvider.getSystemFont(device, zoomContext.nativeZoom());
17761777
}
17771778
return imageDC;
17781779
}
@@ -1882,7 +1883,7 @@ public String toString () {
18821883

18831884
<T> T applyUsingAnyHandle(Function<ImageHandle, T> function) {
18841885
if (zoomLevelToImageHandle.isEmpty()) {
1885-
ImageHandle temporaryHandle = this.imageProvider.newImageHandle(DPIUtil.getDeviceZoom());
1886+
ImageHandle temporaryHandle = this.imageProvider.newImageHandle(new ZoomContext(DPIUtil.getDeviceZoom(), DPIUtil.getNativeDeviceZoom()));
18861887
try {
18871888
return function.apply(temporaryHandle);
18881889
} finally {
@@ -1913,42 +1914,57 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
19131914
return new Image(device, type, handle, nativeZoom);
19141915
}
19151916

1917+
/**
1918+
* ZoomContext holds information about zoom details used to create and cache the image
1919+
*
1920+
* @param targetZoom zoom value the OS handle will be created, cached and served for,
1921+
* it is usually an auto-scaled zoom
1922+
* @param nativeZoom native zoom that can be used as context for the creation
1923+
* of the handle, e.g. as font zoom for drawing on the image with a GC
1924+
*/
1925+
private record ZoomContext(int targetZoom, int nativeZoom) {
1926+
1927+
private ZoomContext(int targetZoom) {
1928+
this(targetZoom, targetZoom);
1929+
}
1930+
}
1931+
19161932
private abstract class AbstractImageProviderWrapper {
19171933

19181934
protected abstract Rectangle getBounds(int zoom);
19191935

19201936
protected long configureGCData(GCData data) {
1921-
return configureGC(data, 100);
1937+
return configureGC(data, new ZoomContext(100));
19221938
}
19231939

19241940
public Collection<Integer> getPreservedZoomLevels() {
19251941
return Collections.emptySet();
19261942
}
19271943

1928-
abstract ImageData newImageData(int zoom);
1944+
abstract ImageData newImageData(ZoomContext zoomContext);
19291945

19301946
abstract AbstractImageProviderWrapper createCopy(Image image);
19311947

19321948
ImageData getScaledImageData (int zoom) {
19331949
TreeSet<Integer> availableZooms = new TreeSet<>(zoomLevelToImageHandle.keySet());
19341950
int closestZoom = Optional.ofNullable(availableZooms.higher(zoom)).orElse(availableZooms.lower(zoom));
1935-
return DPIUtil.scaleImageData(device, getImageMetadata(closestZoom).getImageData(), zoom, closestZoom);
1951+
return DPIUtil.scaleImageData(device, getImageMetadata(new ZoomContext(closestZoom)).getImageData(), zoom, closestZoom);
19361952
}
19371953

1938-
protected ImageHandle newImageHandle(int zoom) {
1939-
ImageData resizedData = getImageData(zoom);
1940-
return newImageHandle(resizedData, zoom);
1954+
protected ImageHandle newImageHandle(ZoomContext zoomContext) {
1955+
ImageData resizedData = getImageData(zoomContext.targetZoom());
1956+
return newImageHandle(resizedData, zoomContext);
19411957
}
19421958

1943-
protected final ImageHandle newImageHandle(ImageData data, int zoom) {
1959+
protected final ImageHandle newImageHandle(ImageData data, ZoomContext zoomContext) {
19441960
if (type == SWT.ICON && data.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
19451961
// If the original type was an icon with transparency mask and re-scaling leads
19461962
// to image data without transparency mask, this will create invalid images
19471963
// so this fallback will "repair" the image data by explicitly passing
19481964
// the transparency mask created from the scaled image data
1949-
return initIconHandle(device, data, data.getTransparencyMask(), zoom);
1965+
return initIconHandle(device, data, data.getTransparencyMask(), zoomContext.targetZoom());
19501966
} else {
1951-
return init(data, zoom);
1967+
return init(data, zoomContext.targetZoom());
19521968
}
19531969
}
19541970
}
@@ -1977,8 +1993,8 @@ protected Rectangle getBounds(int zoom) {
19771993
}
19781994

19791995
@Override
1980-
ImageData newImageData(int zoom) {
1981-
return getScaledImageData(zoom);
1996+
ImageData newImageData(ZoomContext zoomContext) {
1997+
return getScaledImageData(zoomContext.targetZoom());
19821998
}
19831999

19842000
@Override
@@ -2000,34 +2016,34 @@ private abstract class ImageFromImageDataProviderWrapper extends AbstractImagePr
20002016
void initImage() {
20012017
// As the init call configured some Image attributes (e.g. type)
20022018
// it must be called
2003-
newImageData(100);
2019+
newImageData(new ZoomContext(100));
20042020
}
20052021

20062022
@Override
2007-
ImageData newImageData(int zoom) {
2023+
ImageData newImageData(ZoomContext zoomContext) {
20082024
Function<Integer, ImageData> imageDataRetrieval = zoomToRetrieve -> {
2009-
ImageHandle handle = initializeHandleFromSource(zoomToRetrieve);
2025+
ImageHandle handle = initializeHandleFromSource(zoomContext);
20102026
ImageData data = handle.getImageData();
20112027
handle.destroy();
20122028
return data;
20132029
};
2014-
return cachedImageData.computeIfAbsent(zoom, imageDataRetrieval);
2030+
return cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrieval);
20152031
}
20162032

20172033
@Override
2018-
protected ImageHandle newImageHandle(int zoom) {
2019-
ImageData cachedData = cachedImageData.remove(zoom);
2034+
protected ImageHandle newImageHandle(ZoomContext zoomContext) {
2035+
ImageData cachedData = cachedImageData.remove(zoomContext.targetZoom());
20202036
if (cachedData != null) {
2021-
return newImageHandle(cachedData, zoom);
2037+
return newImageHandle(cachedData, zoomContext);
20222038
}
2023-
return initializeHandleFromSource(zoom);
2039+
return initializeHandleFromSource(zoomContext);
20242040
}
20252041

2026-
private ImageHandle initializeHandleFromSource(int zoom) {
2027-
ElementAtZoom<ImageData> imageDataAtZoom = loadImageData(zoom);
2028-
ImageData imageData = DPIUtil.scaleImageData(device, imageDataAtZoom.element(), zoom, imageDataAtZoom.zoom());
2042+
private ImageHandle initializeHandleFromSource(ZoomContext zoomContext) {
2043+
ElementAtZoom<ImageData> imageDataAtZoom = loadImageData(zoomContext.targetZoom());
2044+
ImageData imageData = DPIUtil.scaleImageData(device, imageDataAtZoom.element(), zoomContext.targetZoom(), imageDataAtZoom.zoom());
20292045
imageData = adaptImageDataIfDisabledOrGray(imageData);
2030-
return newImageHandle(imageData, zoom);
2046+
return newImageHandle(imageData, zoomContext);
20312047
}
20322048

20332049
}
@@ -2149,7 +2165,7 @@ public Collection<Integer> getPreservedZoomLevels() {
21492165

21502166
@Override
21512167
protected long configureGCData(GCData data) {
2152-
return configureGC(data, DPIUtil.getDeviceZoom());
2168+
return configureGC(data, new ZoomContext(DPIUtil.getDeviceZoom()));
21532169
}
21542170

21552171
@Override
@@ -2159,33 +2175,35 @@ protected Rectangle getBounds(int zoom) {
21592175
}
21602176

21612177
@Override
2162-
ImageData newImageData(int zoom) {
2178+
ImageData newImageData(ZoomContext zoomContext) {
2179+
int targetZoom = zoomContext.targetZoom();
21632180
if (zoomLevelToImageHandle.isEmpty()) {
2164-
return createBaseHandle(zoom).getImageData();
2181+
return createBaseHandle(targetZoom).getImageData();
21652182
}
21662183
// if a GC is initialized with an Image (memGC != null), the image data must not be resized, because it would
21672184
// be a destructive operation. Therefor, a new handle is created for the requested zoom
21682185
if (memGC != null) {
2169-
return newImageHandle(zoom).getImageData();
2186+
return newImageHandle(zoomContext).getImageData();
21702187
}
2171-
return getScaledImageData(zoom);
2188+
return getScaledImageData(targetZoom);
21722189
}
21732190

21742191
@Override
2175-
protected ImageHandle newImageHandle(int zoom) {
2192+
protected ImageHandle newImageHandle(ZoomContext zoomContext) {
2193+
int targetZoom = zoomContext.targetZoom();
21762194
if (zoomLevelToImageHandle.isEmpty()) {
2177-
return createBaseHandle(zoom);
2195+
return createBaseHandle(targetZoom);
21782196
}
21792197
if (memGC != null) {
2180-
if (memGC.getZoom() != zoom) {
2198+
if (memGC.getZoom() != targetZoom) {
21812199
GC currentGC = memGC;
21822200
memGC = null;
2183-
createHandle(zoom);
2184-
currentGC.refreshFor(new DrawableWrapper(Image.this, zoom));
2201+
createHandle(targetZoom);
2202+
currentGC.refreshFor(new DrawableWrapper(Image.this, zoomContext));
21852203
}
2186-
return zoomLevelToImageHandle.get(zoom);
2204+
return zoomLevelToImageHandle.get(targetZoom);
21872205
}
2188-
return super.newImageHandle(zoom);
2206+
return super.newImageHandle(zoomContext);
21892207
}
21902208
private ImageHandle createBaseHandle(int zoom) {
21912209
baseZoom = zoom;
@@ -2274,29 +2292,30 @@ Object getProvider() {
22742292
}
22752293

22762294
@Override
2277-
ImageData newImageData(int zoom) {
2295+
ImageData newImageData(ZoomContext zoomContext) {
22782296
Function<Integer, ImageData> imageDataRetrival = zoomToRetrieve -> {
22792297
ImageHandle handle = initializeHandleFromSource(zoomToRetrieve);
22802298
ImageData data = handle.getImageData();
22812299
handle.destroy();
22822300
return data;
22832301
};
2284-
return cachedImageData.computeIfAbsent(zoom, imageDataRetrival);
2302+
return cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrival);
22852303
}
22862304

22872305

22882306
@Override
2289-
protected ImageHandle newImageHandle(int zoom) {
2290-
ImageData cachedData = cachedImageData.remove(zoom);
2307+
protected ImageHandle newImageHandle(ZoomContext zoomContext) {
2308+
int targetZoom = zoomContext.targetZoom();
2309+
ImageData cachedData = cachedImageData.remove(targetZoom);
22912310
if (cachedData != null) {
2292-
return init(cachedData, zoom);
2311+
return init(cachedData, targetZoom);
22932312
}
2294-
return initializeHandleFromSource(zoom);
2313+
return initializeHandleFromSource(targetZoom);
22952314
}
22962315

22972316
private ImageHandle initializeHandleFromSource(int zoom) {
22982317
ElementAtZoom<ImageData> imageDataAtZoom = loadImageData(zoom);
2299-
ImageData imageData = DPIUtil.scaleImageData (device,imageDataAtZoom.element(), zoom, imageDataAtZoom.zoom());
2318+
ImageData imageData = DPIUtil.scaleImageData (device, imageDataAtZoom.element(), zoom, imageDataAtZoom.zoom());
23002319
imageData = adaptImageDataIfDisabledOrGray(imageData);
23012320
return init(imageData, zoom);
23022321
}
@@ -2315,7 +2334,7 @@ private class ImageFileNameProviderWrapper extends BaseImageProviderWrapper<Imag
23152334
super(provider, ImageFileNameProvider.class);
23162335
// Checks for the contract of the passed provider require
23172336
// checking for valid image data creation
2318-
newImageData(DPIUtil.getDeviceZoom());
2337+
newImageData(new ZoomContext(DPIUtil.getDeviceZoom()));
23192338
}
23202339

23212340
@Override
@@ -2569,7 +2588,7 @@ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
25692588
private ImageGcDrawer drawer;
25702589
private int width;
25712590
private int height;
2572-
private int currentZoom = 100;
2591+
private ZoomContext currentZoom = new ZoomContext(100);
25732592

25742593
ImageGcDrawerWrapper(ImageGcDrawer imageGcDrawer, int width, int height) {
25752594
checkProvider(imageGcDrawer, ImageGcDrawer.class);
@@ -2590,32 +2609,33 @@ protected long configureGCData(GCData data) {
25902609
}
25912610

25922611
@Override
2593-
ImageData newImageData(int zoom) {
2594-
return getImageMetadata(zoom).getImageData();
2612+
ImageData newImageData(ZoomContext zoomContext) {
2613+
return getImageMetadata(zoomContext).getImageData();
25952614
}
25962615

25972616
@Override
2598-
protected ImageHandle newImageHandle(int zoom) {
2599-
currentZoom = zoom;
2617+
protected ImageHandle newImageHandle(ZoomContext zoomContext) {
2618+
currentZoom = zoomContext;
2619+
int targetZoom = zoomContext.targetZoom();
26002620
int gcStyle = drawer.getGcStyle();
26012621
Image image;
26022622
if ((gcStyle & SWT.TRANSPARENT) != 0) {
2603-
int scaledHeight = Win32DPIUtils.pointToPixel(height, zoom);
2604-
int scaledWidth = Win32DPIUtils.pointToPixel(width, zoom);
2623+
int scaledHeight = Win32DPIUtils.pointToPixel(height, targetZoom);
2624+
int scaledWidth = Win32DPIUtils.pointToPixel(width, targetZoom);
26052625
/* Create a 24 bit image data with alpha channel */
26062626
final ImageData resultData = new ImageData (scaledWidth, scaledHeight, 24, new PaletteData (0xFF, 0xFF00, 0xFF0000));
26072627
resultData.alphaData = new byte [scaledWidth * scaledHeight];
2608-
image = new Image(device, resultData, zoom);
2628+
image = new Image(device, resultData, targetZoom);
26092629
} else {
26102630
image = new Image(device, width, height);
26112631
}
2612-
GC gc = new GC(new DrawableWrapper(image, zoom), gcStyle);
2632+
GC gc = new GC(new DrawableWrapper(image, zoomContext), gcStyle);
26132633
try {
26142634
drawer.drawOn(gc, width, height);
2615-
ImageData imageData = image.getImageMetadata(zoom).getImageData();
2635+
ImageData imageData = image.getImageData(targetZoom);
26162636
drawer.postProcess(imageData);
26172637
ImageData newData = adaptImageDataIfDisabledOrGray(imageData);
2618-
return init(newData, zoom);
2638+
return init(newData, targetZoom);
26192639
} finally {
26202640
gc.dispose();
26212641
image.dispose();
@@ -2646,16 +2666,16 @@ public boolean equals(Object otherProvider) {
26462666

26472667
private static class DrawableWrapper implements Drawable {
26482668
private final Image image;
2649-
private final int zoom;
2669+
private final ZoomContext zoomContext;
26502670

2651-
public DrawableWrapper(Image image, int zoom) {
2671+
public DrawableWrapper(Image image, ZoomContext zoomContext) {
26522672
this.image = image;
2653-
this.zoom = zoom;
2673+
this.zoomContext = zoomContext;
26542674
}
26552675

26562676
@Override
26572677
public long internal_new_GC(GCData data) {
2658-
return this.image.configureGC(data, zoom);
2678+
return this.image.configureGC(data, zoomContext);
26592679
}
26602680

26612681
@Override

0 commit comments

Comments
 (0)