|
15 | 15 |
|
16 | 16 |
|
17 | 17 | import java.io.*;
|
| 18 | +import java.util.*; |
18 | 19 |
|
19 | 20 | import org.eclipse.swt.*;
|
20 | 21 | import org.eclipse.swt.internal.*;
|
@@ -151,6 +152,11 @@ public final class Image extends Resource implements Drawable {
|
151 | 152 | */
|
152 | 153 | private ImageDataProvider imageDataProvider;
|
153 | 154 |
|
| 155 | + /** |
| 156 | + * ImageGcDrawer to provide a callback to draw on a GC for various zoom levels |
| 157 | + */ |
| 158 | + private ImageGcDrawer imageGcDrawer; |
| 159 | + |
154 | 160 | /**
|
155 | 161 | * Style flag used to differentiate normal, gray-scale and disabled images based
|
156 | 162 | * on image data providers. Without this, a normal and a disabled image of the
|
@@ -263,6 +269,7 @@ public Image(Device device, Image srcImage, int flag) {
|
263 | 269 | this.type = srcImage.type;
|
264 | 270 | this.imageDataProvider = srcImage.imageDataProvider;
|
265 | 271 | this.imageFileNameProvider = srcImage.imageFileNameProvider;
|
| 272 | + this.imageGcDrawer = srcImage.imageGcDrawer; |
266 | 273 | this.styleFlag = srcImage.styleFlag | flag;
|
267 | 274 | this.currentDeviceZoom = srcImage.currentDeviceZoom;
|
268 | 275 |
|
@@ -661,6 +668,36 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
|
661 | 668 | init ();
|
662 | 669 | }
|
663 | 670 |
|
| 671 | +/** |
| 672 | + * The provided ImageGcDrawer will be called on demand whenever a new variant of the |
| 673 | + * Image for an additional zoom is required. Depending on the OS specific implementation |
| 674 | + * these calls will be done during the instantiation or later when a new variant is |
| 675 | + * requested. |
| 676 | + * |
| 677 | + * @param device the device on which to create the image |
| 678 | + * @param imageGcDrawer the ImageGcDrawer object to be called when a new image variant |
| 679 | + * for another zoom is required. |
| 680 | + * @param width the width of the new image in points |
| 681 | + * @param height the height of the new image in points |
| 682 | + * |
| 683 | + * @exception IllegalArgumentException <ul> |
| 684 | + * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
| 685 | + * <li>ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null</li> |
| 686 | + * </ul> |
| 687 | + * @since 3.129 |
| 688 | + */ |
| 689 | +public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) { |
| 690 | + super(device); |
| 691 | + if (imageGcDrawer == null) { |
| 692 | + SWT.error(SWT.ERROR_NULL_ARGUMENT); |
| 693 | + } |
| 694 | + this.imageGcDrawer = imageGcDrawer; |
| 695 | + currentDeviceZoom = DPIUtil.getDeviceZoom(); |
| 696 | + ImageData imageData = drawWithImageGcDrawer(width, height, currentDeviceZoom); |
| 697 | + init (imageData); |
| 698 | + init (); |
| 699 | +} |
| 700 | + |
664 | 701 | /**
|
665 | 702 | * Refreshes the image for the current device scale factor.
|
666 | 703 | * <p>
|
@@ -722,6 +759,17 @@ boolean refreshImageForZoom () {
|
722 | 759 | refreshed = true;
|
723 | 760 | currentDeviceZoom = deviceZoomLevel;
|
724 | 761 | }
|
| 762 | + } else if (imageGcDrawer != null) { |
| 763 | + int deviceZoomLevel = deviceZoom; |
| 764 | + if (deviceZoomLevel != currentDeviceZoom) { |
| 765 | + ImageData data = drawWithImageGcDrawer(width, height, deviceZoomLevel); |
| 766 | + /* Release current native resources */ |
| 767 | + destroy (); |
| 768 | + init(data); |
| 769 | + init(); |
| 770 | + refreshed = true; |
| 771 | + currentDeviceZoom = deviceZoomLevel; |
| 772 | + } |
725 | 773 | } else {
|
726 | 774 | if (!DPIUtil.useCairoAutoScale()) {
|
727 | 775 | int deviceZoomLevel = deviceZoom;
|
@@ -904,6 +952,9 @@ public boolean equals (Object object) {
|
904 | 952 | return (styleFlag == image.styleFlag) && imageDataProvider.equals (image.imageDataProvider);
|
905 | 953 | } else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
|
906 | 954 | return (styleFlag == image.styleFlag) && imageFileNameProvider.equals (image.imageFileNameProvider);
|
| 955 | + } else if (imageGcDrawer != null && image.imageGcDrawer != null) { |
| 956 | + return styleFlag == image.styleFlag && imageGcDrawer.equals(image.imageGcDrawer) && width == image.width |
| 957 | + && height == image.height; |
907 | 958 | } else {
|
908 | 959 | return surface == image.surface;
|
909 | 960 | }
|
@@ -1110,11 +1161,27 @@ public ImageData getImageData (int zoom) {
|
1110 | 1161 | } else if (imageFileNameProvider != null) {
|
1111 | 1162 | ElementAtZoom<String> fileName = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, zoom);
|
1112 | 1163 | return DPIUtil.scaleImageData (device, new ImageData (fileName.element()), zoom, fileName.zoom());
|
| 1164 | + } else if (imageGcDrawer != null) { |
| 1165 | + return drawWithImageGcDrawer(width, height, zoom); |
1113 | 1166 | } else {
|
1114 | 1167 | return DPIUtil.scaleImageData (device, getImageDataAtCurrentZoom (), zoom, currentDeviceZoom);
|
1115 | 1168 | }
|
1116 | 1169 | }
|
1117 | 1170 |
|
| 1171 | +private ImageData drawWithImageGcDrawer(int width, int height, int zoom) { |
| 1172 | + Image image = new Image(device, width, height); |
| 1173 | + GC gc = new GC(image); |
| 1174 | + try { |
| 1175 | + imageGcDrawer.drawOn(gc, width, height); |
| 1176 | + ImageData imageData = image.getImageData(zoom); |
| 1177 | + imageGcDrawer.postProcess(imageData); |
| 1178 | + return imageData; |
| 1179 | + } finally { |
| 1180 | + gc.dispose(); |
| 1181 | + image.dispose(); |
| 1182 | + } |
| 1183 | +} |
| 1184 | + |
1118 | 1185 | /**
|
1119 | 1186 | * Invokes platform specific functionality to allocate a new image.
|
1120 | 1187 | * <p>
|
@@ -1179,6 +1246,8 @@ public int hashCode () {
|
1179 | 1246 | return imageDataProvider.hashCode();
|
1180 | 1247 | } else if (imageFileNameProvider != null) {
|
1181 | 1248 | return imageFileNameProvider.hashCode();
|
| 1249 | + } else if (imageGcDrawer != null) { |
| 1250 | + return Objects.hash(imageGcDrawer, width, height); |
1182 | 1251 | } else {
|
1183 | 1252 | return (int)surface;
|
1184 | 1253 | }
|
|
0 commit comments