mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
CRE/ImageViewer: get scaled blitbuffer when long-press on SVG
Get a Lua userdata wrapping a crengine LVSvgImageSource object when long-press on a SVG image, and have crengine/LunaSVG render it smoothly scaled to the requested size by ImageViewer.
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user