changeset 460:b5e8e470f7f7

core (image): convert SVG images + better error handling: - when an SVG image is found, new backend `imageConvert` method is used to convert it to PNG - by default, 128x128 is used as dest size. - removed code to handle image without extension in filename, as it is now working with Kivy. - if texture is not updated after `texture_update` is called, an error is logged, a fallback image is used, and `on_error` event is dispatched
author Goffi <goffi@goffi.org>
date Sun, 19 Apr 2020 17:06:57 +0200
parents 72290ebfaa8b
children 3c9ba4a694ef
files cagou/core/image.py
diffstat 1 files changed, 43 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/cagou/core/image.py	Sun Apr 19 17:06:45 2020 +0200
+++ b/cagou/core/image.py	Sun Apr 19 17:06:57 2020 +0200
@@ -18,59 +18,57 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-from sat.core import log as logging
-log = logging.getLogger(__name__)
+import mimetypes
+from functools import partial
 from kivy.uix import image as kivy_img
-from kivy.core.image import Image as CoreImage
-from kivy.resources import resource_find
-import io
-import PIL
+from sat.core import log as logging
+from sat.tools.common import data_format
+from cagou import G
+
+log = logging.getLogger(__name__)
 
 
 class Image(kivy_img.Image):
     """Image widget which accept source without extension"""
+    SVG_CONVERT_EXTRA = {'width': 128, 'height': 128}
+
+    def __init__(self, **kwargs):
+        self.register_event_type('on_error')
+        super().__init__(**kwargs)
+
+    def _imageConvertCb(self, path):
+        self.source = path
 
     def texture_update(self, *largs):
-        if not self.source:
-            self.texture = None
-        else:
-            filename = resource_find(self.source)
-            self._loops = 0
-            if filename is None:
-                return log.error('Image: Error reading file {filename}'.
-                                    format(filename=self.source))
-            mipmap = self.mipmap
-            if self._coreimage is not None:
-                self._coreimage.unbind(on_texture=self._on_tex_change)
-            try:
-                self._coreimage = ci = CoreImage(filename, mipmap=mipmap,
-                                                 anim_delay=self.anim_delay,
-                                                 keep_data=self.keep_data,
-                                                 nocache=self.nocache)
-            except Exception:
-                # loading failed probably because of unmanaged extention,
-                # we try our luck with with PIL
-                try:
-                    im = PIL.Image.open(filename)
-                    ext = im.format.lower()
-                    del im
-                    # we can't use im.tobytes as it would use the
-                    # internal decompressed representation from pillow
-                    # and im.save would need processing to handle format
-                    data = io.BytesIO(open(filename, "rb").read())
-                    cache_filename = "{}.{}".format(filename,ext) # needed for kivy's Image to use cache
-                    self._coreimage = ci = CoreImage(data, ext=ext,
-                                                     filename=cache_filename, mipmap=mipmap,
-                                                     anim_delay=self.anim_delay,
-                                                     keep_data=self.keep_data,
-                                                     nocache=self.nocache)
-                except Exception as e:
-                    log.warning("Can't load image: {}".format(e))
-                    self._coreimage = ci = None
+        if self.source:
+            if mimetypes.guess_type(self.source, strict=False)[0] == 'image/svg+xml':
+                log.debug(f"Converting SVG image at {self.source} to PNG")
+                G.host.bridge.imageConvert(
+                    self.source,
+                    "",
+                    data_format.serialise(self.SVG_CONVERT_EXTRA),
+                    "",
+                    callback=self._imageConvertCb,
+                    errback=partial(
+                        G.host.errback,
+                        message=f"Can't load image at {self.source}: {{msg}}"
+                    )
+                )
+                return
 
-            if ci:
-                ci.bind(on_texture=self._on_tex_change)
-                self.texture = ci.texture
+        super().texture_update(*largs)
+        if self.source and self.texture is None:
+            log.warning(
+                f"Image {self.source} has not been imported correctly, replacing by "
+                f"empty one")
+            # FIXME: temporary image, to be replaced by something showing that something
+            #   went wrong
+            self.source = G.host.app.expand(
+                "{media}/misc/borders/border_hollow_black.png")
+            self.dispatch('on_error', Exception(f"Can't load source {self.source}"))
+
+    def on_error(self, err):
+        pass
 
 
 class AsyncImage(kivy_img.AsyncImage):