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:
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user