diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 7f0789a8b..faddf6844 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -1008,7 +1008,9 @@ function ReaderHighlight:onHold(arg, ges) -- check if we were holding on an image -- we provide want_frames=true, so we get a list of images for -- animated GIFs (supported by ImageViewer) - local image = self.ui.document:getImageFromPosition(self.hold_pos, true) + -- We provide accept_cre_scalable_image=true to get, if the image is a SVG image, + -- a function that ImageViewer can use to get a perfect bb at any scale factor. + local image = self.ui.document:getImageFromPosition(self.hold_pos, true, true) if image then logger.dbg("hold on image") local ImageViewer = require("ui/widget/imageviewer") diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index f471d5a93..320cec82f 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -539,14 +539,40 @@ function CreDocument:getCoverPageImage() end end -function CreDocument:getImageFromPosition(pos, want_frames) - local data, size = self._document:getImageDataFromPosition(pos.x, pos.y) +function CreDocument:getImageFromPosition(pos, want_frames, accept_cre_scalable_image) + local data, size, cre_img = self._document:getImageDataFromPosition(pos.x, pos.y, accept_cre_scalable_image) if data and size then logger.dbg("CreDocument: got image data from position", data, size) local image = RenderImage:renderImageData(data, size, want_frames) C.free(data) -- free the userdata we got from crengine return image end + if cre_img then + -- The image is a scalable image (SVG), and we got an image object from crengine, that + -- can draw itself at any requested scale factor: returns a function, that will be used + -- by ImageViewer to get the perfect bb. + return function(scale, w, h) + logger.dbg("CreImage: scaling for", scale, w, h) + if not cre_img then + return + end + if scale == false then -- used to signal we are done with the object + cre_img:free() + cre_img = false + return + end + -- scale will be used if non-0, otherwise the bb will be made to fit in w/h, + -- keeping the original aspect ratio + local image_data, image_w, image_h, image_scale = cre_img:renderScaled(scale, w, h) + if image_data then + -- This data is held in the cre_img object, so this bb is only + -- valid as long as this object is alive, and until the next + -- call to this function that will replace this data. + local bb = Blitbuffer.new(image_w, image_h, Blitbuffer.TYPE_BBRGB32, image_data) + return bb, image_scale + end + end + end end function CreDocument:getWordFromPosition(pos) diff --git a/frontend/ui/widget/imageviewer.lua b/frontend/ui/widget/imageviewer.lua index 15e8e6909..1c13cea8d 100644 --- a/frontend/ui/widget/imageviewer.lua +++ b/frontend/ui/widget/imageviewer.lua @@ -75,6 +75,7 @@ local ImageViewer = InputContainer:new{ _image_wg = nil, _images_list = nil, _images_list_disposable = nil, + _scaled_image_func = nil, } @@ -147,6 +148,12 @@ function ImageViewer:init() self._images_list_disposable = self.image_disposable self.image_disposable = self._images_list.image_disposable end + -- If self.image is a function (scalable SVG image object provided by crengine), + -- it can be used to get the perfect bb for any scale_factor + if type(self.image) == "function" then + self._scaled_image_func = self.image + self.image = self._scaled_image_func(1) -- native image size, that we need to know + end -- Widget layout if self._scale_to_fit == nil then -- initialize our toggle @@ -410,6 +417,16 @@ function ImageViewer:_new_image_wg() rotation_angle = rotate_clockwise and 90 or 270 end + if self._scaled_image_func then + local scale_factor_used + self.image, scale_factor_used = self._scaled_image_func(self.scale_factor, max_image_w, max_image_h) + if self.scale_factor == 0 then + -- onZoomIn/Out need to know the current scale factor, that they won't be + -- able to fetch from _image_wg as we force it to be 1. So, remember it. + self._scale_factor_0 = scale_factor_used + end + end + self._image_wg = ImageWidget:new{ file = self.file, image = self.image, @@ -418,7 +435,7 @@ function ImageViewer:_new_image_wg() width = max_image_w, height = max_image_h, rotation_angle = rotation_angle, - scale_factor = self.scale_factor, + scale_factor = self._scaled_image_func and 1 or self.scale_factor, center_x_ratio = self._center_x_ratio, center_y_ratio = self._center_y_ratio, } @@ -621,7 +638,7 @@ end function ImageViewer:onZoomIn(inc) if self.scale_factor == 0 then -- Get the scale_factor made out for best fit - self.scale_factor = self._image_wg:getScaleFactor() + self.scale_factor = self._scale_factor_0 or self._image_wg:getScaleFactor() end if not inc then inc = 0.2 end -- default for key zoom event self.scale_factor = self.scale_factor + inc @@ -636,7 +653,7 @@ end function ImageViewer:onZoomOut(dec) if self.scale_factor == 0 then -- Get the scale_factor made out for best fit - self.scale_factor = self._image_wg:getScaleFactor() + self.scale_factor = self._scale_factor_0 or self._image_wg:getScaleFactor() end if not dec then dec = 0.2 end -- default for key zoom event self.scale_factor = self.scale_factor - dec @@ -725,6 +742,10 @@ function ImageViewer:onCloseWidget() logger.dbg("ImageViewer:onCloseWidget: free self._images_list", self._images_list) self._images_list:free() end + if self._scaled_image_func then + self._scaled_image_func(false) -- invoke :free() on the creimage object + self._scaled_image_func = nil + end -- Those, on the other hand, are always initialized, but may not actually be in our widget tree right now, -- depending on what we needed to show, so they might not get sent a CloseWidget event.