@@ -151,6 +151,11 @@ public final class Image extends Resource implements Drawable {
151151 */
152152 private ImageDataProvider imageDataProvider ;
153153
154+ /**
155+ * ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
156+ */
157+ private ImageGcDrawer imageGcDrawer ;
158+
154159 /**
155160 * Style flag used to differentiate normal, gray-scale and disabled images based
156161 * 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) {
263268 this .type = srcImage .type ;
264269 this .imageDataProvider = srcImage .imageDataProvider ;
265270 this .imageFileNameProvider = srcImage .imageFileNameProvider ;
271+ this .imageGcDrawer = srcImage .imageGcDrawer ;
266272 this .styleFlag = srcImage .styleFlag | flag ;
267273 this .currentDeviceZoom = srcImage .currentDeviceZoom ;
268274
@@ -661,6 +667,34 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
661667 init ();
662668}
663669
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+ this .imageGcDrawer = imageGcDrawer ;
692+ currentDeviceZoom = DPIUtil .getDeviceZoom ();
693+ ImageData imageData = drawWithImageGcDrawer (currentDeviceZoom );
694+ init (imageData );
695+ init ();
696+ }
697+
664698/**
665699 * Refreshes the image for the current device scale factor.
666700 * <p>
@@ -722,6 +756,17 @@ boolean refreshImageForZoom () {
722756 refreshed = true ;
723757 currentDeviceZoom = deviceZoomLevel ;
724758 }
759+ } else if (imageGcDrawer != null ) {
760+ int deviceZoomLevel = deviceZoom ;
761+ if (deviceZoomLevel != currentDeviceZoom ) {
762+ ImageData data = drawWithImageGcDrawer (deviceZoomLevel );
763+ /* Release current native resources */
764+ destroy ();
765+ init (data );
766+ init ();
767+ refreshed = true ;
768+ currentDeviceZoom = deviceZoomLevel ;
769+ }
725770 } else {
726771 if (!DPIUtil .useCairoAutoScale ()) {
727772 int deviceZoomLevel = deviceZoom ;
@@ -904,6 +949,8 @@ public boolean equals (Object object) {
904949 return (styleFlag == image .styleFlag ) && imageDataProvider .equals (image .imageDataProvider );
905950 } else if (imageFileNameProvider != null && image .imageFileNameProvider != null ) {
906951 return (styleFlag == image .styleFlag ) && imageFileNameProvider .equals (image .imageFileNameProvider );
952+ } else if (imageGcDrawer != null && image .imageGcDrawer != null ) {
953+ return styleFlag == image .styleFlag && imageGcDrawer .equals (image .imageGcDrawer );
907954 } else {
908955 return surface == image .surface ;
909956 }
@@ -1110,11 +1157,33 @@ public ImageData getImageData (int zoom) {
11101157 } else if (imageFileNameProvider != null ) {
11111158 ElementAtZoom <String > fileName = DPIUtil .validateAndGetImagePathAtZoom (imageFileNameProvider , zoom );
11121159 return DPIUtil .scaleImageData (device , new ImageData (fileName .element ()), zoom , fileName .zoom ());
1160+ } else if (imageGcDrawer != null ) {
1161+ return drawWithImageGcDrawer (zoom );
11131162 } else {
11141163 return DPIUtil .scaleImageData (device , getImageDataAtCurrentZoom (), zoom , currentDeviceZoom );
11151164 }
11161165}
11171166
1167+
1168+
1169+ private ImageData drawWithImageGcDrawer (int zoom ) {
1170+ if (this .imageGcDrawer != null ) {
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+ SWT .error (SWT .ERROR_INVALID_ARGUMENT , null , ": ImageGcDrawer [" + imageGcDrawer + "] is null." );
1184+ return null ;
1185+ }
1186+
11181187/**
11191188 * Invokes platform specific functionality to allocate a new image.
11201189 * <p>
@@ -1179,6 +1248,8 @@ public int hashCode () {
11791248 return imageDataProvider .hashCode ();
11801249 } else if (imageFileNameProvider != null ) {
11811250 return imageFileNameProvider .hashCode ();
1251+ } else if (imageGcDrawer != null ) {
1252+ return imageGcDrawer .hashCode ();
11821253 } else {
11831254 return (int )surface ;
11841255 }
0 commit comments