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.
This commit is contained in:
Michael Natterer
2014-04-20 18:06:52 +02:00
parent 1a674374d3
commit 051a3e4af4
3 changed files with 82 additions and 44 deletions

View File

@ -137,6 +137,8 @@ gimp_display_shell_draw_image (GimpDisplayShell *shell,
{ {
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
gint i, j; gint i, j;
gint chunk_width;
gint chunk_height;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (gimp_display_get_image (shell->display)); 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 /* display the image in RENDER_BUF_WIDTH x RENDER_BUF_HEIGHT
* sized chunks * 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)
{ {
for (j = x1; j < x2; j += GIMP_DISPLAY_RENDER_BUF_WIDTH) 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 += chunk_width)
{ {
gint dx, dy; gint dx, dy;
dx = MIN (x2 - j, GIMP_DISPLAY_RENDER_BUF_WIDTH); dx = MIN (x2 - j, chunk_width);
dy = MIN (y2 - i, GIMP_DISPLAY_RENDER_BUF_HEIGHT); dy = MIN (y2 - i, chunk_height);
gimp_display_shell_render (shell, cr, j, i, dx, dy); gimp_display_shell_render (shell, cr, j, i, dx, dy);
} }

View File

@ -20,6 +20,7 @@
#include <gegl.h> #include <gegl.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "libgimpmath/gimpmath.h"
#include "libgimpcolor/gimpcolor.h" #include "libgimpcolor/gimpcolor.h"
#include "libgimpwidgets/gimpwidgets.h" #include "libgimpwidgets/gimpwidgets.h"
@ -44,6 +45,9 @@
#include "gimpdisplayxfer.h" #include "gimpdisplayxfer.h"
/* #define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1 */
void void
gimp_display_shell_render (GimpDisplayShell *shell, gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr, cairo_t *cr,
@ -55,11 +59,17 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GimpImage *image; GimpImage *image;
GimpProjection *projection; GimpProjection *projection;
GeglBuffer *buffer; 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_x;
gint viewport_offset_y; gint viewport_offset_y;
gint viewport_width; gint viewport_width;
gint viewport_height; gint viewport_height;
gint scaled_x;
gint scaled_y;
gint scaled_width;
gint scaled_height;
cairo_surface_t *xfer; cairo_surface_t *xfer;
gint xfer_src_x; gint xfer_src_x;
gint xfer_src_y; gint xfer_src_y;
@ -78,22 +88,46 @@ gimp_display_shell_render (GimpDisplayShell *shell,
#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING #ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
/* if we had this future API, things would look pretty on hires (retina) */ /* 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 #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, gimp_display_shell_scroll_get_scaled_viewport (shell,
&viewport_offset_x, &viewport_offset_x,
&viewport_offset_y, &viewport_offset_y,
&viewport_width, &viewport_width,
&viewport_height); &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) if (shell->rotate_transform)
{ {
xfer = cairo_surface_create_similar_image (cairo_get_target (cr), xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_ARGB32,
w * window_scale, scaled_width,
h * window_scale); scaled_height);
cairo_surface_mark_dirty (xfer); cairo_surface_mark_dirty (xfer);
xfer_src_x = 0; xfer_src_x = 0;
xfer_src_y = 0; xfer_src_y = 0;
@ -101,8 +135,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
else else
{ {
xfer = gimp_display_xfer_get_surface (shell->xfer, xfer = gimp_display_xfer_get_surface (shell->xfer,
w * window_scale, scaled_width,
h * window_scale, scaled_height,
&xfer_src_x, &xfer_src_x,
&xfer_src_y); &xfer_src_y);
} }
@ -136,11 +170,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
} }
gegl_buffer_get (buffer, gegl_buffer_get (buffer,
GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale, GEGL_RECTANGLE (scaled_x, scaled_y,
(y + viewport_offset_y) * window_scale, scaled_width, scaled_height),
w * window_scale, buffer_scale,
h * window_scale),
shell->scale_x * window_scale,
filter_format, shell->filter_data, filter_format, shell->filter_data,
shell->filter_stride, GEGL_ABYSS_CLAMP); 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, gimp_color_display_stack_convert_buffer (shell->filter_stack,
shell->filter_buffer, shell->filter_buffer,
GEGL_RECTANGLE (0, 0, GEGL_RECTANGLE (0, 0,
w * window_scale, scaled_width,
h * window_scale)); scaled_height));
gegl_buffer_get (shell->filter_buffer, gegl_buffer_get (shell->filter_buffer,
GEGL_RECTANGLE (0, 0, GEGL_RECTANGLE (0, 0,
w * window_scale, scaled_width,
h * window_scale), scaled_height),
1.0, 1.0,
babl_format ("cairo-ARGB32"), babl_format ("cairo-ARGB32"),
data, stride, data, stride,
@ -163,11 +195,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
else else
{ {
gegl_buffer_get (buffer, gegl_buffer_get (buffer,
GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale, GEGL_RECTANGLE (scaled_x, scaled_y,
(y + viewport_offset_y) * window_scale, scaled_width, scaled_height),
w * window_scale, buffer_scale,
h * window_scale),
shell->scale_x * window_scale,
babl_format ("cairo-ARGB32"), babl_format ("cairo-ARGB32"),
data, stride, data, stride,
GEGL_ABYSS_CLAMP); GEGL_ABYSS_CLAMP);
@ -194,20 +224,18 @@ gimp_display_shell_render (GimpDisplayShell *shell,
data += mask_src_y * stride + mask_src_x * 4; data += mask_src_y * stride + mask_src_x * 4;
gegl_buffer_get (shell->mask, gegl_buffer_get (shell->mask,
GEGL_RECTANGLE ((x + viewport_offset_x) * window_scale, GEGL_RECTANGLE (scaled_x, scaled_y,
(y + viewport_offset_y) * window_scale, scaled_width, scaled_height),
w * window_scale, buffer_scale,
h * window_scale),
shell->scale_x * window_scale,
babl_format ("Y u8"), babl_format ("Y u8"),
data, stride, data, stride,
GEGL_ABYSS_CLAMP); GEGL_ABYSS_CLAMP);
/* invert the mask so what is *not* the foreground object is masked */ /* invert the mask so what is *not* the foreground object is masked */
mask_height = h * window_scale; mask_height = scaled_height;
while (mask_height--) while (mask_height--)
{ {
gint mask_width = w * window_scale; gint mask_width = scaled_width;
guchar *d = data; guchar *d = data;
while (mask_width--) while (mask_width--)
@ -226,11 +254,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
cairo_rectangle (cr, x, y, w, h); 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, cairo_set_source_surface (cr, xfer,
(x - xfer_src_x) * window_scale, x * scale_x - xfer_src_x,
(y - xfer_src_y) * window_scale); y * scale_y - xfer_src_y);
if (shell->rotate_transform) if (shell->rotate_transform)
{ {
@ -252,8 +280,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
{ {
gimp_cairo_set_source_rgba (cr, &shell->mask_color); gimp_cairo_set_source_rgba (cr, &shell->mask_color);
cairo_mask_surface (cr, shell->mask_surface, cairo_mask_surface (cr, shell->mask_surface,
(x - mask_src_x) * window_scale, (x - mask_src_x) * scale_x,
(y - mask_src_y) * window_scale); (y - mask_src_y) * scale_y);
} }
cairo_restore (cr); cairo_restore (cr);

View File

@ -19,16 +19,10 @@
#define __GIMP_DISPLAY_XFER_H__ #define __GIMP_DISPLAY_XFER_H__
/* #define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1 */
#define GIMP_DISPLAY_RENDER_BUF_WIDTH 256 #define GIMP_DISPLAY_RENDER_BUF_WIDTH 256
#define GIMP_DISPLAY_RENDER_BUF_HEIGHT 256 #define GIMP_DISPLAY_RENDER_BUF_HEIGHT 256
#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING #define GIMP_DISPLAY_RENDER_MAX_SCALE 4.0
#define GIMP_DISPLAY_RENDER_MAX_SCALE 2.0
#else
#define GIMP_DISPLAY_RENDER_MAX_SCALE 1.0
#endif
GimpDisplayXfer * gimp_display_xfer_realize (GtkWidget *widget); GimpDisplayXfer * gimp_display_xfer_realize (GtkWidget *widget);