[sushi/wip/cosimoc/no-clutter: 14/66] image: port to use a custom GtkWidget



commit 6015dd2b4dd9668e4bac1ef56724ad4e6c1bba0e
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Mon Apr 3 12:39:51 2017 -0700

    image: port to use a custom GtkWidget
    
    The Image class will draw an image at the right scale, while preserving
    the aspect ratio.

 flatpak/org.gnome.NautilusPreviewer.json |   3 +-
 src/js/viewers/image.js                  | 102 ++++++++++++++++++++++++++++---
 2 files changed, 96 insertions(+), 9 deletions(-)
---
diff --git a/flatpak/org.gnome.NautilusPreviewer.json b/flatpak/org.gnome.NautilusPreviewer.json
index 696c8e4..b82d260 100644
--- a/flatpak/org.gnome.NautilusPreviewer.json
+++ b/flatpak/org.gnome.NautilusPreviewer.json
@@ -27,7 +27,8 @@
         "--filesystem=~/.config/dconf:ro",
         "--filesystem=host:ro",
         "--filesystem=home",
-        "--env=DCONF_USER_CONFIG_DIR=.config/dconf"
+        "--env=DCONF_USER_CONFIG_DIR=.config/dconf",
+        "--env=GST_DEBUG=2,Sushi*:6"
     ],
     "modules": [
         {
diff --git a/src/js/viewers/image.js b/src/js/viewers/image.js
index dea3dc5..8144769 100644
--- a/src/js/viewers/image.js
+++ b/src/js/viewers/image.js
@@ -23,10 +23,11 @@
  *
  */
 
+const Gdk = imports.gi.Gdk;
 const GdkPixbuf = imports.gi.GdkPixbuf;
-const GtkClutter = imports.gi.GtkClutter;
-const Gtk = imports.gi.Gtk;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
 
 const Gettext = imports.gettext.domain('sushi');
 const _ = Gettext.gettext;
@@ -36,6 +37,90 @@ const Mainloop = imports.mainloop;
 const MimeHandler = imports.ui.mimeHandler;
 const Utils = imports.ui.utils;
 
+const Image = new Lang.Class({
+    Name: 'Image',
+    Extends: Gtk.DrawingArea,
+    Properties: {
+        'pix': GObject.ParamSpec.object('pix', '', '',
+                                        GObject.ParamFlags.READWRITE,
+                                        GdkPixbuf.Pixbuf)
+    },
+
+    _init: function() {
+        this._pix = null;
+        this._scaledSurface = null;
+
+        this.parent();
+    },
+
+    _ensureScaledPix: function() {
+        let scaleFactor = this.get_scale_factor();
+        let width = this.get_allocated_width() * scaleFactor;
+        let height = this.get_allocated_height() * scaleFactor;
+
+        // Downscale original to fit, if necessary
+        let origWidth = this._pix.get_width();
+        let origHeight = this._pix.get_height();
+
+        let scaleX = width / origWidth;
+        let scaleY = height / origHeight;
+        let scale = Math.min(scaleX, scaleY);
+
+        let newWidth = Math.floor(origWidth * scale);
+        let newHeight = Math.floor(origHeight * scale);
+
+        let scaledWidth = this._scaledSurface ? this._scaledSurface.getWidth() : 0;
+        let scaledHeight = this._scaledSurface ? this._scaledSurface.getHeight() : 0;
+
+        if (newWidth != scaledWidth || newHeight != scaledHeight) {
+            let scaledPixbuf = this._pix.scale_simple(newWidth, newHeight,
+                                                      GdkPixbuf.InterpType.BILINEAR);
+            this._scaledSurface = Gdk.cairo_surface_create_from_pixbuf(scaledPixbuf,
+                                                                       scaleFactor,
+                                                                       this.get_window());
+        }
+    },
+
+    vfunc_get_preferred_width: function() {
+        return [1, this._pix ? this.pix.get_width() : 1];
+    },
+
+    vfunc_get_preferred_height: function() {
+        return [1, this._pix ? this.pix.get_height() : 1];
+    },
+
+    vfunc_size_allocate: function(allocation) {
+        this.parent(allocation);
+        this._ensureScaledPix();
+    },
+
+    vfunc_draw: function(context) {
+        if (!this._scaledSurface)
+            return false;
+
+        let width = this.get_allocated_width();
+        let height = this.get_allocated_height();
+
+        let scaleFactor = this.get_scale_factor();
+        let offsetX = (width - this._scaledSurface.getWidth() / scaleFactor) / 2;
+        let offsetY = (height - this._scaledSurface.getHeight() / scaleFactor) / 2;
+
+        context.setSourceSurface(this._scaledSurface, offsetX, offsetY);
+        context.paint();
+        return false;
+    },
+
+    set pix(p) {
+        this._pix = p;
+        this._scaledSurface = null;
+        this.queue_resize();
+    },
+
+    get pix() {
+        return this._pix;
+    }
+});
+
 const ImageRenderer = new Lang.Class({
     Name: 'ImageRenderer',
 
@@ -58,6 +143,8 @@ const ImageRenderer = new Lang.Class({
     },
 
     _createImageTexture : function(file) {
+        this._texture = new Image();
+
         file.read_async
         (GLib.PRIORITY_DEFAULT, null,
          Lang.bind(this,
@@ -78,9 +165,7 @@ const ImageRenderer = new Lang.Class({
 
              this._iter = anim.get_iter(null);
              let pix = this._iter.get_pixbuf().apply_embedded_orientation();
-
-             this._texture = new GtkClutter.Texture({ keep_aspect_ratio: true });
-             this._texture.set_from_pixbuf(pix);
+             this._texture.pix = pix;
 
              if (!anim.is_static_image())
                  this._startTimeout();
@@ -99,9 +184,10 @@ const ImageRenderer = new Lang.Class({
          }));
     },
 
-    getSizeForAllocation : function(allocation, fullScreen) {
-        let baseSize = this._texture.get_base_size();
-        return Utils.getScaledSize(baseSize, allocation, fullScreen);
+    getSizeForAllocation : function(allocation) {
+        let width = this._texture.pix.get_width();
+        let height = this._texture.pix.get_height();
+        return Utils.getScaledSize([width, height], allocation, false);
     },
 
     _startTimeout : function() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]