[gimp] app/display: let cairo render the checkerboard
- From: Sven Neumann <neo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app/display: let cairo render the checkerboard
- Date: Wed, 29 Sep 2010 18:38:18 +0000 (UTC)
commit ccee0ec41a37727115e73d919e0c2a34ffae8f20
Author: Sven Neumann <sven gimp org>
Date: Tue Sep 28 21:10:03 2010 +0200
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.
app/display/gimpdisplayshell-callbacks.c | 8 ++
app/display/gimpdisplayshell-draw.c | 46 +++++++++++
app/display/gimpdisplayshell-draw.h | 6 ++
app/display/gimpdisplayshell-handlers.c | 6 ++
app/display/gimpdisplayshell-render.c | 123 ++++-------------------------
app/display/gimpdisplayshell.c | 8 ++-
app/display/gimpdisplayshell.h | 1 +
7 files changed, 91 insertions(+), 107 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index dbd1dc3..6192689 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -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);
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 5c67580..8131898 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -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);
+}
diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h
index 0baff69..8561458 100644
--- a/app/display/gimpdisplayshell-draw.h
+++ b/app/display/gimpdisplayshell-draw.h
@@ -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__ */
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index f080b74..ff65d8b 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -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)
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index b229ed0..26c8d66 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -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)
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 8b283dc..0ceeb7f 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -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);
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 3b3d313..e990352 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -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 */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]