Ticket #4034: 0001-Zoom-Gesture-zooms-through-the-gesture-s-center.patch

File 0001-Zoom-Gesture-zooms-through-the-gesture-s-center.patch, 5.0 KB (added by humitos, 11 years ago)

An intersting approach to the "zoom to fixed point" feature

  • ImageView.py

    From d1b8d74cf63748c074d2fa853e0b2132a8e862b1 Mon Sep 17 00:00:00 2001
    From: Manuel Kaufmann <humitos@gmail.com>
    Date: Mon, 29 Oct 2012 17:13:15 -0300
    Subject: [PATCH ImageViewer] Zoom Gesture zooms through the gesture's center
    
    When two fingers are used to zoom in/out the image, the center of the
    gesture is used to zoom the image through it.
    
    Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
    ---
     ImageView.py           | 86 +++++++++++++++++++++++++++++++++++++++++---------
     ImageViewerActivity.py |  1 +
     2 files changed, 72 insertions(+), 15 deletions(-)
    
    diff --git a/ImageView.py b/ImageView.py
    index cbc5516..f20910c 100644
    a b class ImageViewer(Gtk.DrawingArea): 
    7171        self._angle_ori = 0.0
    7272        self._fast = True
    7373        self._redraw_id = None
    74         self._is_touching = False
    7574        self._switched = False
    7675
     76        # zoom with fixed point
     77        self._is_touching = False
     78        self._touch_center = False
     79        self._old_zoom = None
     80        self._xofs = 0
     81        self._yofs = 0
     82
    7783    def do_get_property(self, pspec):
    7884        if pspec.name == 'zoom':
    7985            return self.zoom
    class ImageViewer(Gtk.DrawingArea): 
    167173                y = int((rect.height - h) / 2)
    168174        ctx.translate(x, y)
    169175
    170         if self._is_touching:
    171             if self._switched:
    172                 w, h = h, w
    173 
    174             if rect.height < h:
    175                 vadj = int((h - rect.height) / 2)
    176                 vadjustment = scrolled_window.get_vadjustment()
    177                 vadjustment.set_value(vadj)
    178 
    179             if rect.width < w:
    180                 hadj = int((w - rect.width) / 2)
    181                 hadjustment = scrolled_window.get_hadjustment()
    182                 hadjustment.set_value(hadj)
    183 
    184176        if self.zoom != 1:
    185177            logging.error('Scaling: %s', self.zoom)
    186178            ctx.scale(self.zoom, self.zoom)
    class ImageViewer(Gtk.DrawingArea): 
    218210            self._switched = True
    219211
    220212        self.set_size_request(w, h)
     213        self._scroll_image()
     214
     215    def _scroll_image(self):
     216        # based on Eye Of GNOME code
     217
     218        w = int(self.surface.get_width() * self.zoom)
     219        h = int(self.surface.get_height() * self.zoom)
     220
     221        old_width = int(self.surface.get_width() * self._old_zoom)
     222        old_height = int(self.surface.get_height() * self._old_zoom)
     223
     224        scrolled_window = self.get_parent()
     225        rect = scrolled_window.get_allocation()
     226
     227        if self._switched:
     228            # TODO: zoom with fixed point does not work properly when
     229            # the image is rotated
     230            return
     231
     232        if self._is_touching:
     233            zoom_x_anchor = self._touch_center[1] / rect.width
     234            zoom_y_anchor = self._touch_center[2] / rect.height
     235        else:
     236            zoom_x_anchor = 0.5
     237            zoom_y_anchor = 0.5
     238
     239        vadjustment = scrolled_window.get_vadjustment()
     240        step_inc = vadjustment.get_step_increment()
     241        page_inc = vadjustment.get_page_increment()
     242
     243        if old_height < rect.height:
     244            cy = zoom_y_anchor * old_height / self._old_zoom
     245        else:
     246            cy = (self._yofs + zoom_y_anchor * rect.height) / self._old_zoom
     247
     248        if h < rect.height:
     249            self._yofs = 0
     250        else:
     251            self._yofs = math.floor(cy * self.zoom - \
     252                    zoom_y_anchor * rect.height + 0.5)
     253
     254        vadj = max(0, min(self._yofs, h - rect.height))
     255        vadjustment.configure(vadj, 0, h, step_inc, page_inc,
     256                              rect.height)
     257
     258        hadjustment = scrolled_window.get_hadjustment()
     259        step_inc = hadjustment.get_step_increment()
     260        page_inc = hadjustment.get_page_increment()
     261
     262        if old_width < rect.width:
     263            cx = zoom_x_anchor * old_width / self._old_zoom
     264        else:
     265            cx = (self._xofs + zoom_x_anchor * rect.width) / self._old_zoom
     266
     267        if w < rect.width:
     268            self._xofs = 0
     269        else:
     270            self._xofs = math.floor(cx * self.zoom - \
     271                    zoom_x_anchor * rect.width + 0.5)
     272
     273        hadj = max(0, min(self._xofs, w - rect.width))
     274        hadjustment.configure(hadj, 0, w, step_inc, page_inc,
     275                              rect.width)
    221276
    222277    def set_zoom(self, zoom):
    223278        self._optimal_zoom_flag = False
    class ImageViewer(Gtk.DrawingArea): 
    302357        return zoom
    303358
    304359    def _set_zoom(self, zoom):
     360        self._old_zoom = self.zoom
    305361        self.zoom = zoom
    306362        self._redraw()
    307363        self.emit('zoom-changed')
  • ImageViewerActivity.py

    diff --git a/ImageViewerActivity.py b/ImageViewerActivity.py
    index 0c51699..b33e46c 100644
    a b class ImageViewerActivity(activity.Activity): 
    214214            logging.error('Scale changed %f', scale)
    215215
    216216            self.view._is_touching = True
     217            self.view._touch_center = controller.get_center()
    217218            self.view.set_zoom_relative(scale)
    218219
    219220    def handle_view_source(self):