[gimp] app: make all pixbuf rendering in GimpViewRenderer HiDPI-aware



commit 6370147990799f2595696be4d95c3cb121543f93
Author: Michael Natterer <mitch gimp org>
Date:   Wed Jan 9 20:31:43 2019 +0100

    app: make all pixbuf rendering in GimpViewRenderer HiDPI-aware
    
    Request pixbufs in double size and cache the created surface instead
    of the pixbuf. This affects rendering icons and image thumbnails.
    
    All other rendering (which is most previews) is not ported yet, but
    just lacks HiDPI quality, there are no actual bugs.

 app/widgets/gimpviewrenderer.c          | 61 +++++++++++++++++++++++----------
 app/widgets/gimpviewrendererimagefile.c | 24 +++++++++----
 2 files changed, 59 insertions(+), 26 deletions(-)
---
diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c
index d67ea05b25..68ec9045ef 100644
--- a/app/widgets/gimpviewrenderer.c
+++ b/app/widgets/gimpviewrenderer.c
@@ -65,7 +65,7 @@ enum
 struct _GimpViewRendererPrivate
 {
   cairo_pattern_t    *pattern;
-  GdkPixbuf          *pixbuf;
+  cairo_surface_t    *icon_surface;
   gchar              *bg_icon_name;
 
   GimpColorConfig    *color_config;
@@ -206,7 +206,7 @@ gimp_view_renderer_finalize (GObject *object)
 
   g_clear_pointer (&renderer->priv->pattern, cairo_pattern_destroy);
   g_clear_pointer (&renderer->surface, cairo_surface_destroy);
-  g_clear_object (&renderer->priv->pixbuf);
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
   g_clear_pointer (&renderer->priv->bg_icon_name, g_free);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -328,7 +328,7 @@ gimp_view_renderer_set_viewable (GimpViewRenderer *renderer,
     return;
 
   g_clear_pointer (&renderer->surface, cairo_surface_destroy);
-  g_clear_object (&renderer->priv->pixbuf);
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
 
   gimp_view_renderer_free_color_transform (renderer);
 
@@ -728,12 +728,19 @@ gimp_view_renderer_real_draw (GimpViewRenderer *renderer,
       renderer->priv->needs_render = FALSE;
     }
 
-  if (renderer->priv->pixbuf)
+  if (renderer->priv->icon_surface)
     {
-      gint  width  = gdk_pixbuf_get_width  (renderer->priv->pixbuf);
-      gint  height = gdk_pixbuf_get_height (renderer->priv->pixbuf);
+      gint  scale_factor = gtk_widget_get_scale_factor (widget);
+      gint  width;
+      gint  height;
       gint  x, y;
 
+      width  = cairo_image_surface_get_width  (renderer->priv->icon_surface);
+      height = cairo_image_surface_get_height (renderer->priv->icon_surface);
+
+      width  /= scale_factor;
+      height /= scale_factor;
+
       if (renderer->priv->bg_icon_name)
         {
           if (! renderer->priv->pattern)
@@ -749,7 +756,7 @@ gimp_view_renderer_real_draw (GimpViewRenderer *renderer,
       x = (available_width  - width)  / 2;
       y = (available_height - height) / 2;
 
-      gdk_cairo_set_source_pixbuf (cr, renderer->priv->pixbuf, x, y);
+      cairo_set_source_surface (cr, renderer->priv->icon_surface, x, y);
       cairo_rectangle (cr, x, y, width, height);
       cairo_fill (cr);
     }
@@ -791,11 +798,12 @@ gimp_view_renderer_real_render (GimpViewRenderer *renderer,
   GdkPixbuf   *pixbuf;
   GimpTempBuf *temp_buf;
   const gchar *icon_name;
+  gint         scale_factor = gtk_widget_get_scale_factor (widget);
 
   pixbuf = gimp_viewable_get_pixbuf (renderer->viewable,
                                      renderer->context,
-                                     renderer->width,
-                                     renderer->height);
+                                     renderer->width  * scale_factor,
+                                     renderer->height * scale_factor);
   if (pixbuf)
     {
       gimp_view_renderer_render_pixbuf (renderer, widget, pixbuf);
@@ -884,7 +892,7 @@ gimp_view_renderer_render_temp_buf (GimpViewRenderer *renderer,
                                     GimpViewBG        inside_bg,
                                     GimpViewBG        outside_bg)
 {
-  g_clear_object (&renderer->priv->pixbuf);
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
 
   if (! renderer->surface)
     renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
@@ -912,6 +920,7 @@ gimp_view_renderer_render_pixbuf (GimpViewRenderer *renderer,
 {
   GimpColorTransform *transform;
   const Babl         *format;
+  gint                scale_factor;
 
   g_clear_pointer (&renderer->surface, cairo_surface_destroy);
 
@@ -949,13 +958,19 @@ gimp_view_renderer_render_pixbuf (GimpViewRenderer *renderer,
           dest += dest_stride;
         }
 
-      g_clear_object (&renderer->priv->pixbuf);
-      renderer->priv->pixbuf = new;
+      pixbuf = new;
     }
   else
     {
-      g_set_object (&renderer->priv->pixbuf, pixbuf);
+      g_object_ref (pixbuf);
     }
+
+  scale_factor = gtk_widget_get_scale_factor (widget);
+
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
+  renderer->priv->icon_surface =
+    gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
+  g_object_unref (pixbuf);
 }
 
 void
@@ -964,41 +979,49 @@ gimp_view_renderer_render_icon (GimpViewRenderer *renderer,
                                 const gchar      *icon_name)
 {
   GdkPixbuf *pixbuf;
+  gint       scale_factor;
   gint       width;
   gint       height;
 
-
   g_return_if_fail (GIMP_IS_VIEW_RENDERER (renderer));
   g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (icon_name != NULL);
 
-  g_clear_object (&renderer->priv->pixbuf);
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
   g_clear_pointer (&renderer->surface, cairo_surface_destroy);
 
+  scale_factor = gtk_widget_get_scale_factor (widget);
+
   pixbuf = gimp_widget_load_icon (widget, icon_name,
                                   MIN (renderer->width, renderer->height));
   width  = gdk_pixbuf_get_width (pixbuf);
   height = gdk_pixbuf_get_height (pixbuf);
 
-  if (width > renderer->width || height > renderer->height)
+  if (width  > renderer->width  * scale_factor ||
+      height > renderer->height * scale_factor)
     {
       GdkPixbuf *scaled_pixbuf;
 
       gimp_viewable_calc_preview_size (width, height,
-                                       renderer->width, renderer->height,
+                                       renderer->width  * scale_factor,
+                                       renderer->height * scale_factor,
                                        TRUE, 1.0, 1.0,
                                        &width, &height,
                                        NULL);
 
       scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
-                                               width, height,
+                                               width  * scale_factor,
+                                               height * scale_factor,
                                                GDK_INTERP_BILINEAR);
 
       g_object_unref (pixbuf);
       pixbuf = scaled_pixbuf;
     }
 
-  renderer->priv->pixbuf = pixbuf;
+  g_clear_pointer (&renderer->priv->icon_surface, cairo_surface_destroy);
+  renderer->priv->icon_surface =
+    gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
+  g_object_unref (pixbuf);
 }
 
 GimpColorTransform *
diff --git a/app/widgets/gimpviewrendererimagefile.c b/app/widgets/gimpviewrendererimagefile.c
index ba8ee94c20..ce3fb820c7 100644
--- a/app/widgets/gimpviewrendererimagefile.c
+++ b/app/widgets/gimpviewrendererimagefile.c
@@ -68,9 +68,13 @@ static void
 gimp_view_renderer_imagefile_render (GimpViewRenderer *renderer,
                                      GtkWidget        *widget)
 {
-  GdkPixbuf *pixbuf = gimp_view_renderer_get_frame_pixbuf (renderer, widget,
-                                                           renderer->width,
-                                                           renderer->height);
+  GdkPixbuf *pixbuf;
+  gint       scale_factor = gtk_widget_get_scale_factor (widget);
+  gint       width        = renderer->width  * scale_factor;
+  gint       height       = renderer->height * scale_factor;
+
+  pixbuf = gimp_view_renderer_get_frame_pixbuf (renderer, widget,
+                                                width, height);
 
   if (! pixbuf)
     {
@@ -78,8 +82,7 @@ gimp_view_renderer_imagefile_render (GimpViewRenderer *renderer,
 
       pixbuf = gimp_view_renderer_imagefile_get_icon (imagefile,
                                                       widget,
-                                                      MIN (renderer->width,
-                                                           renderer->height));
+                                                      MAX (width, height));
     }
 
   if (pixbuf)
@@ -179,9 +182,16 @@ gimp_view_renderer_imagefile_get_icon (GimpImagefile *imagefile,
         }
     }
 
-  if (! pixbuf && thumbnail->image_mimetype)
+  if (! pixbuf)
     {
-      pixbuf = get_icon_for_mime_type (thumbnail->image_mimetype, size);
+      if (thumbnail->image_mimetype)
+        {
+          pixbuf = get_icon_for_mime_type (thumbnail->image_mimetype, size);
+        }
+      else if (thumbnail->image_state == GIMP_THUMB_STATE_FOLDER)
+        {
+          pixbuf = get_icon_for_mime_type ("inode/directory", size);
+        }
     }
 
   if (! pixbuf)


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