@@ -151,6 +151,11 @@ public final class Image extends Resource implements Drawable {
151
151
*/
152
152
private ImageDataProvider imageDataProvider ;
153
153
154
+ /**
155
+ * ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
156
+ */
157
+ private ImageGcDrawer imageGcDrawer ;
158
+
154
159
/**
155
160
* Style flag used to differentiate normal, gray-scale and disabled images based
156
161
* on image data providers. Without this, a normal and a disabled image of the
@@ -263,6 +268,7 @@ public Image(Device device, Image srcImage, int flag) {
263
268
this .type = srcImage .type ;
264
269
this .imageDataProvider = srcImage .imageDataProvider ;
265
270
this .imageFileNameProvider = srcImage .imageFileNameProvider ;
271
+ this .imageGcDrawer = srcImage .imageGcDrawer ;
266
272
this .styleFlag = srcImage .styleFlag | flag ;
267
273
this .currentDeviceZoom = srcImage .currentDeviceZoom ;
268
274
@@ -661,6 +667,37 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
661
667
init ();
662
668
}
663
669
670
+ /**
671
+ * The provided ImageGcDrawer will be called on demand whenever a new variant of the
672
+ * Image for an additional zoom is required. Depending on the OS specific implementation
673
+ * these calls will be done during the instantiation or later when a new variant is
674
+ * requested
675
+ * <p>
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,8 @@ 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 );
907
957
} else {
908
958
return surface == image .surface ;
909
959
}
@@ -1110,11 +1160,27 @@ public ImageData getImageData (int zoom) {
1110
1160
} else if (imageFileNameProvider != null ) {
1111
1161
ElementAtZoom <String > fileName = DPIUtil .validateAndGetImagePathAtZoom (imageFileNameProvider , zoom );
1112
1162
return DPIUtil .scaleImageData (device , new ImageData (fileName .element ()), zoom , fileName .zoom ());
1163
+ } else if (imageGcDrawer != null ) {
1164
+ return drawWithImageGcDrawer (width , height , zoom );
1113
1165
} else {
1114
1166
return DPIUtil .scaleImageData (device , getImageDataAtCurrentZoom (), zoom , currentDeviceZoom );
1115
1167
}
1116
1168
}
1117
1169
1170
+ private ImageData drawWithImageGcDrawer (int width , int height , int zoom ) {
1171
+ Image image = new Image (device , width , height );
1172
+ GC gc = new GC (image );
1173
+ try {
1174
+ imageGcDrawer .drawOn (gc );
1175
+ ImageData imageData = image .getImageData (zoom );
1176
+ imageGcDrawer .postProcess (imageData );
1177
+ return imageData ;
1178
+ } finally {
1179
+ gc .dispose ();
1180
+ image .dispose ();
1181
+ }
1182
+ }
1183
+
1118
1184
/**
1119
1185
* Invokes platform specific functionality to allocate a new image.
1120
1186
* <p>
@@ -1179,6 +1245,8 @@ public int hashCode () {
1179
1245
return imageDataProvider .hashCode ();
1180
1246
} else if (imageFileNameProvider != null ) {
1181
1247
return imageFileNameProvider .hashCode ();
1248
+ } else if (imageGcDrawer != null ) {
1249
+ return imageGcDrawer .hashCode ();
1182
1250
} else {
1183
1251
return (int )surface ;
1184
1252
}
0 commit comments