Commit ccee0ec4 authored by Sven Neumann's avatar Sven Neumann
Browse files

app/display: let cairo render the checkerboard

Instead of blending the scaled image data onto the checkerboard and
then painting this image to the screen, render the image data into
an ARGB cairo image surface. Then paint a checkerboard on the canvas
and the image on top of it.
parent ebeb9333
......@@ -2285,6 +2285,14 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
if (! gdk_region_empty (image_region))
{
cairo_save (cr);
gimp_display_shell_draw_checkerboard (shell, cr,
image_rect.x,
image_rect.y,
image_rect.width,
image_rect.height);
cairo_restore (cr);
gdk_region_get_rectangles (image_region, &rects, &n_rects);
cairo_save (cr);
......
......@@ -21,6 +21,7 @@
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
......@@ -750,3 +751,48 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
}
}
}
static cairo_pattern_t *
gimp_display_shell_create_checkerboard (GimpDisplayShell *shell,
cairo_t *cr)
{
GimpCheckSize check_size;
GimpCheckType check_type;
guchar check_light;
guchar check_dark;
GimpRGB light;
GimpRGB dark;
g_object_get (shell->display->config,
"transparency-size", &check_size,
"transparency-type", &check_type,
NULL);
gimp_checks_get_shades (check_type, &check_light, &check_dark);
gimp_rgb_set_uchar (&light, check_light, check_light, check_light);
gimp_rgb_set_uchar (&dark, check_dark, check_dark, check_dark);
return gimp_cairo_checkerboard_create (cr,
1 << (check_size + 2), &light, &dark);
}
void
gimp_display_shell_draw_checkerboard (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h)
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (cr != NULL);
if (G_UNLIKELY (! shell->checkerboard))
shell->checkerboard = gimp_display_shell_create_checkerboard (shell, cr);
cairo_rectangle (cr, x, y, w, h);
cairo_clip (cr);
cairo_translate (cr, - shell->offset_x, - shell->offset_y);
cairo_set_source (cr, shell->checkerboard);
cairo_paint (cr);
}
......@@ -71,6 +71,12 @@ void gimp_display_shell_draw_area (GimpDisplayShell *shell,
gint y,
gint w,
gint h);
void gimp_display_shell_draw_checkerboard (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h);
#endif /* __GIMP_DISPLAY_SHELL_DRAW_H__ */
......@@ -592,6 +592,12 @@ gimp_display_shell_check_notify_handler (GObject *config,
GimpCanvasPaddingMode padding_mode;
GimpRGB padding_color;
if (shell->checkerboard)
{
cairo_pattern_destroy (shell->checkerboard);
shell->checkerboard = NULL;
}
gimp_display_shell_get_padding (shell, &padding_mode, &padding_color);
switch (padding_mode)
......
......@@ -74,7 +74,6 @@ struct _RenderInfo
gdouble scaley;
gint src_x;
gint src_y;
gint dest_bpp;
gint dest_bpl;
gint zoom_quality;
......@@ -102,17 +101,7 @@ static void gimp_display_shell_render_info_scale (RenderInfo *info,
gint level,
gboolean is_premult);
static void gimp_display_shell_render_setup_notify (GObject *config,
GParamSpec *param_spec,
Gimp *gimp);
static guchar *tile_buf = NULL;
static guint check_mod = 0;
static guint check_shift = 0;
static guchar check_dark = 0;
static guchar check_light = 0;
static guchar *tile_buf = NULL;
void
......@@ -121,17 +110,8 @@ gimp_display_shell_render_init (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
g_return_if_fail (tile_buf == NULL);
g_signal_connect (gimp->config, "notify::transparency-size",
G_CALLBACK (gimp_display_shell_render_setup_notify),
gimp);
g_signal_connect (gimp->config, "notify::transparency-type",
G_CALLBACK (gimp_display_shell_render_setup_notify),
gimp);
/* allocate a buffer for arranging information from a row of tiles */
tile_buf = g_new (guchar, GIMP_DISPLAY_RENDER_BUF_WIDTH * MAX_CHANNELS);
gimp_display_shell_render_setup_notify (G_OBJECT (gimp->config), NULL, gimp);
}
void
......@@ -139,10 +119,6 @@ gimp_display_shell_render_exit (Gimp *gimp)
{
g_return_if_fail (GIMP_IS_GIMP (gimp));
g_signal_handlers_disconnect_by_func (gimp->config,
gimp_display_shell_render_setup_notify,
gimp);
if (tile_buf)
{
g_free (tile_buf);
......@@ -150,40 +126,6 @@ gimp_display_shell_render_exit (Gimp *gimp)
}
}
static void
gimp_display_shell_render_setup_notify (GObject *config,
GParamSpec *param_spec,
Gimp *gimp)
{
GimpCheckSize check_size;
GimpCheckType check_type;
g_object_get (config,
"transparency-size", &check_size,
"transparency-type", &check_type,
NULL);
gimp_checks_get_shades (check_type, &check_light, &check_dark);
switch (check_size)
{
case GIMP_CHECK_SIZE_SMALL_CHECKS:
check_mod = 0x3;
check_shift = 2;
break;
case GIMP_CHECK_SIZE_MEDIUM_CHECKS:
check_mod = 0x7;
check_shift = 3;
break;
case GIMP_CHECK_SIZE_LARGE_CHECKS:
check_mod = 0xf;
check_shift = 4;
break;
}
}
/* Render Image functions */
......@@ -248,7 +190,6 @@ gimp_display_shell_render (GimpDisplayShell *shell,
info.w = w;
info.h = h;
info.dest_bpp = 4;
info.dest_bpl = cairo_image_surface_get_stride (shell->render_surface);
switch (shell->display->config->zoom_quality)
......@@ -303,6 +244,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH);
#endif
#if 0
/* dim pixels outside the highlighted rectangle */
if (highlight)
{
......@@ -317,6 +259,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gimp_display_shell_render_mask (shell, &info);
}
#endif
cairo_surface_mark_dirty (shell->render_surface);
......@@ -325,11 +268,11 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gint disp_xoffset, disp_yoffset;
gimp_display_shell_scroll_get_disp_offset (shell,
&disp_xoffset, &disp_yoffset);
&disp_xoffset, &disp_yoffset);
cairo_rectangle (cr, x + disp_xoffset, y + disp_yoffset, w, h);
cairo_set_source_surface (cr, shell->render_surface,
x + disp_xoffset, y + disp_yoffset);
cairo_rectangle (cr, x + disp_xoffset, y + disp_yoffset, w, h);
cairo_fill (cr);
}
}
......@@ -437,12 +380,12 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
while (TRUE)
{
const guchar *src = info->src;
guchar *dest = info->dest;
guint32 *dest = (guint32 *) info->dest;
switch (shell->mask_color)
{
case GIMP_RED_CHANNEL:
for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
for (x = info->x; x < xe; x++, src++, dest += 4)
{
if (*src & 0x80)
continue;
......@@ -453,7 +396,7 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
break;
case GIMP_GREEN_CHANNEL:
for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
for (x = info->x; x < xe; x++, src++, dest += 4)
{
if (*src & 0x80)
continue;
......@@ -464,7 +407,7 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
break;
case GIMP_BLUE_CHANNEL:
for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
for (x = info->x; x < xe; x++, src++, dest += 4)
{
if (*src & 0x80)
continue;
......@@ -512,24 +455,12 @@ render_image_gray_a (RenderInfo *info)
while (TRUE)
{
const guchar *src = info->src;
guchar *dest = info->dest;
guint dark_light;
guint32 *dest = (guint32 *) info->dest;
dark_light = (y >> check_shift) + (info->x >> check_shift);
for (x = info->x; x < xe; x++, src += 2, dest += info->dest_bpp)
for (x = info->x; x < xe; x++, src += 2, dest++)
{
guint v;
if (dark_light & 0x1)
v = ((src[0] << 8) + check_dark * (256 - src[1])) >> 8;
else
v = ((src[0] << 8) + check_light * (256 - src[1])) >> 8;
GIMP_CAIRO_RGB24_SET_PIXEL (dest, v, v, v);
if (((x + 1) & check_mod) == 0)
dark_light += 1;
/* data in src is premultiplied already */
*dest = (src[1] << 24) | (src[0] << 16) | (src[0] << 8) | src[0];
}
if (++y == ye)
......@@ -561,32 +492,12 @@ render_image_rgb_a (RenderInfo *info)
while (TRUE)
{
const guchar *src = info->src;
guchar *dest = info->dest;
guint dark_light;
guint32 *dest = (guint32 *) info->dest;
dark_light = (y >> check_shift) + (info->x >> check_shift);
for (x = info->x; x < xe; x++, src += 4, dest += info->dest_bpp)
for (x = info->x; x < xe; x++, src += 4, dest++)
{
guint r, g, b;
if (dark_light & 0x1)
{
r = ((src[0] << 8) + check_dark * (256 - src[3])) >> 8;
g = ((src[1] << 8) + check_dark * (256 - src[3])) >> 8;
b = ((src[2] << 8) + check_dark * (256 - src[3])) >> 8;
}
else
{
r = ((src[0] << 8) + check_light * (256 - src[3])) >> 8;
g = ((src[1] << 8) + check_light * (256 - src[3])) >> 8;
b = ((src[2] << 8) + check_light * (256 - src[3])) >> 8;
}
GIMP_CAIRO_RGB24_SET_PIXEL (dest, r, g, b);
if (((x + 1) & check_mod) == 0)
dark_light += 1;
/* data in src is premultiplied already */
*dest = (src[3] << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
}
if (++y == ye)
......
......@@ -286,7 +286,7 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->x_src_dec = 1;
shell->y_src_dec = 1;
shell->render_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
shell->render_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
GIMP_DISPLAY_RENDER_BUF_WIDTH,
GIMP_DISPLAY_RENDER_BUF_HEIGHT);
......@@ -769,6 +769,12 @@ gimp_display_shell_dispose (GObject *object)
shell->render_surface = NULL;
}
if (shell->checkerboard)
{
cairo_pattern_destroy (shell->checkerboard);
shell->checkerboard = NULL;
}
if (shell->highlight)
{
g_slice_free (GdkRectangle, shell->highlight);
......
......@@ -132,6 +132,7 @@ struct _GimpDisplayShell
GtkWidget *statusbar; /* statusbar */
cairo_surface_t *render_surface; /* buffer for rendering the image */
cairo_pattern_t *checkerboard; /* checkerboard pattern */
guint title_idle_id; /* title update idle ID */
gchar *title; /* current title */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment