[gimp] Bug 681968 - Disabling 'Dot for Dot' glitches display



commit 051a3e4af48b04dca113b08eb510b7b2fa2d5db9
Author: Michael Natterer <mitch gimp org>
Date:   Sun Apr 20 18:06:52 2014 +0200

    Bug 681968 - Disabling 'Dot for Dot' glitches display
    
    Enhance the existing but unused display scaling (hidpi/retina) support
    to work independently in x and y direction, and adjust the scaling
    factors accordingly when dot-for-dot is off and xres != yres.
    
    Increase GIMP_DISPLAY_RENDER_MAX_SCALE from 2.0 to 4.0 and adjust the
    rendering chunk size dynamically so we never render chunks that do
    not fit into the GimpDisplayXfer buffers.

 app/display/gimpdisplayshell-draw.c   |   24 +++++++--
 app/display/gimpdisplayshell-render.c |   94 +++++++++++++++++++++------------
 app/display/gimpdisplayxfer.h         |    8 +---
 3 files changed, 82 insertions(+), 44 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 408f2ab..643a673 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -137,6 +137,8 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
 {
   gint x1, y1, x2, y2;
   gint i, j;
+  gint chunk_width;
+  gint chunk_height;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (gimp_display_get_image (shell->display));
@@ -180,14 +182,28 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
   /*  display the image in RENDER_BUF_WIDTH x RENDER_BUF_HEIGHT
    *  sized chunks
    */
-  for (i = y1; i < y2; i += GIMP_DISPLAY_RENDER_BUF_HEIGHT)
+  chunk_width  = GIMP_DISPLAY_RENDER_BUF_WIDTH;
+  chunk_height = GIMP_DISPLAY_RENDER_BUF_HEIGHT;
+
+  if ((shell->scale_x / shell->scale_y) > 2.0)
+    {
+      while ((chunk_width / chunk_height) < (shell->scale_x / shell->scale_y))
+        chunk_height /= 2;
+    }
+  else if ((shell->scale_y / shell->scale_x) > 2.0)
+    {
+      while ((chunk_height / chunk_width) < (shell->scale_y / shell->scale_x))
+        chunk_width /= 2;
+    }
+
+  for (i = y1; i < y2; i += chunk_height)
     {
-      for (j = x1; j < x2; j += GIMP_DISPLAY_RENDER_BUF_WIDTH)
+      for (j = x1; j < x2; j += chunk_width)
         {
           gint dx, dy;
 
-          dx = MIN (x2 - j, GIMP_DISPLAY_RENDER_BUF_WIDTH);
-          dy = MIN (y2 - i, GIMP_DISPLAY_RENDER_BUF_HEIGHT);
+          dx = MIN (x2 - j, chunk_width);
+          dy = MIN (y2 - i, chunk_height);
 
           gimp_display_shell_render (shell, cr, j, i, dx, dy);
         }
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 158422c..8956f28 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -20,6 +20,7 @@
 #include <gegl.h>
 #include <gtk/gtk.h>
 
+#include "libgimpmath/gimpmath.h"
 #include "libgimpcolor/gimpcolor.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
@@ -44,6 +45,9 @@
 #include "gimpdisplayxfer.h"
 
 
+/* #define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1 */
+
+
 void
 gimp_display_shell_render (GimpDisplayShell *shell,
                            cairo_t          *cr,
@@ -55,11 +59,17 @@ gimp_display_shell_render (GimpDisplayShell *shell,
   GimpImage       *image;
   GimpProjection  *projection;
   GeglBuffer      *buffer;
-  gdouble          window_scale = 1.0;
+  gdouble          scale_x      = 1.0;
+  gdouble          scale_y      = 1.0;
+  gdouble          buffer_scale = 1.0;
   gint             viewport_offset_x;
   gint             viewport_offset_y;
   gint             viewport_width;
   gint             viewport_height;
+  gint             scaled_x;
+  gint             scaled_y;
+  gint             scaled_width;
+  gint             scaled_height;
   cairo_surface_t *xfer;
   gint             xfer_src_x;
   gint             xfer_src_y;
@@ -78,22 +88,46 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 
 #ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
   /* if we had this future API, things would look pretty on hires (retina) */
-  window_scale = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET 
(shell))));
+  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET 
(shell))));
 #endif
 
-  window_scale = MIN (window_scale, GIMP_DISPLAY_RENDER_MAX_SCALE);
+  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
+  scale_y = scale_x;
+
+  if (shell->scale_x > shell->scale_y)
+    {
+      scale_y *= (shell->scale_x / shell->scale_y);
+
+      buffer_scale = shell->scale_y * scale_y;
+    }
+  else if (shell->scale_y > shell->scale_x)
+    {
+      scale_x *= (shell->scale_y / shell->scale_x);
+
+      buffer_scale = shell->scale_x * scale_x;
+    }
+  else
+    {
+      buffer_scale = shell->scale_x * scale_x;
+    }
 
   gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                  &viewport_offset_x,
                                                  &viewport_offset_y,
                                                  &viewport_width,
                                                  &viewport_height);
+
+  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
+  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
+  scaled_width  = ceil (w * scale_x);
+  scaled_height = ceil (h * scale_y);
+
   if (shell->rotate_transform)
     {
       xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                  CAIRO_FORMAT_ARGB32,
-                                                 w * window_scale,
-                                                 h * window_scale);
+                                                 scaled_width,
+                                                 scaled_height);
       cairo_surface_mark_dirty (xfer);
       xfer_src_x = 0;
       xfer_src_y = 0;
@@ -101,8 +135,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
   else
     {
       xfer = gimp_display_xfer_get_surface (shell->xfer,
-                                            w * window_scale,
-                                            h * window_scale,
+                                            scaled_width,
+                                            scaled_height,
                                             &xfer_src_x,
                                             &xfer_src_y);
     }
@@ -136,11 +170,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
         }
 
       gegl_buffer_get (buffer,
-                       GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale,
-                                       (y + viewport_offset_y) * window_scale,
-                                       w * window_scale,
-                                       h * window_scale),
-                       shell->scale_x * window_scale,
+                       GEGL_RECTANGLE (scaled_x, scaled_y,
+                                       scaled_width, scaled_height),
+                       buffer_scale,
                        filter_format, shell->filter_data,
                        shell->filter_stride, GEGL_ABYSS_CLAMP);
 
@@ -148,13 +180,13 @@ gimp_display_shell_render (GimpDisplayShell *shell,
       gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                                shell->filter_buffer,
                                                GEGL_RECTANGLE (0, 0,
-                                                               w * window_scale,
-                                                               h * window_scale));
+                                                               scaled_width,
+                                                               scaled_height));
 
       gegl_buffer_get (shell->filter_buffer,
                        GEGL_RECTANGLE (0, 0,
-                                       w * window_scale,
-                                       h * window_scale),
+                                       scaled_width,
+                                       scaled_height),
                        1.0,
                        babl_format ("cairo-ARGB32"),
                        data, stride,
@@ -163,11 +195,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
   else
     {
       gegl_buffer_get (buffer,
-                       GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale,
-                                       (y + viewport_offset_y) * window_scale,
-                                       w * window_scale,
-                                       h * window_scale),
-                       shell->scale_x * window_scale,
+                       GEGL_RECTANGLE (scaled_x, scaled_y,
+                                       scaled_width, scaled_height),
+                       buffer_scale,
                        babl_format ("cairo-ARGB32"),
                        data, stride,
                        GEGL_ABYSS_CLAMP);
@@ -194,20 +224,18 @@ gimp_display_shell_render (GimpDisplayShell *shell,
       data += mask_src_y * stride + mask_src_x * 4;
 
       gegl_buffer_get (shell->mask,
-                       GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale,
-                                       (y + viewport_offset_y) * window_scale,
-                                       w * window_scale,
-                                       h * window_scale),
-                       shell->scale_x * window_scale,
+                       GEGL_RECTANGLE (scaled_x, scaled_y,
+                                       scaled_width, scaled_height),
+                       buffer_scale,
                        babl_format ("Y u8"),
                        data, stride,
                        GEGL_ABYSS_CLAMP);
 
       /* invert the mask so what is *not* the foreground object is masked */
-      mask_height = h * window_scale;
+      mask_height = scaled_height;
       while (mask_height--)
         {
-          gint    mask_width = w * window_scale;
+          gint    mask_width = scaled_width;
           guchar *d          = data;
 
           while (mask_width--)
@@ -226,11 +254,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
 
   cairo_rectangle (cr, x, y, w, h);
 
-  cairo_scale (cr, 1.0 / window_scale, 1.0 / window_scale);
+  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);
 
   cairo_set_source_surface (cr, xfer,
-                            (x - xfer_src_x) * window_scale,
-                            (y - xfer_src_y) * window_scale);
+                            x * scale_x - xfer_src_x,
+                            y * scale_y - xfer_src_y);
 
   if (shell->rotate_transform)
     {
@@ -252,8 +280,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
     {
       gimp_cairo_set_source_rgba (cr, &shell->mask_color);
       cairo_mask_surface (cr, shell->mask_surface,
-                          (x - mask_src_x) * window_scale,
-                          (y - mask_src_y) * window_scale);
+                          (x - mask_src_x) * scale_x,
+                          (y - mask_src_y) * scale_y);
     }
 
   cairo_restore (cr);
diff --git a/app/display/gimpdisplayxfer.h b/app/display/gimpdisplayxfer.h
index beb0b91..df1b890 100644
--- a/app/display/gimpdisplayxfer.h
+++ b/app/display/gimpdisplayxfer.h
@@ -19,16 +19,10 @@
 #define __GIMP_DISPLAY_XFER_H__
 
 
-/* #define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1 */
-
 #define GIMP_DISPLAY_RENDER_BUF_WIDTH  256
 #define GIMP_DISPLAY_RENDER_BUF_HEIGHT 256
 
-#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
-#define GIMP_DISPLAY_RENDER_MAX_SCALE 2.0
-#else
-#define GIMP_DISPLAY_RENDER_MAX_SCALE 1.0
-#endif
+#define GIMP_DISPLAY_RENDER_MAX_SCALE  4.0
 
 
 GimpDisplayXfer * gimp_display_xfer_realize     (GtkWidget       *widget);


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