diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 408f2ab686..643a673c37 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) { - 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; - 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 158422c30c..8956f2883f 100644 --- a/app/display/gimpdisplayshell-render.c +++ b/app/display/gimpdisplayshell-render.c @@ -20,6 +20,7 @@ #include #include +#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 beb0b91b63..df1b890c34 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);