[gimp] app: port GimpDisplayShell selection drawing to cairo
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: port GimpDisplayShell selection drawing to cairo
- Date: Thu, 26 Aug 2010 16:10:52 +0000 (UTC)
commit 58db8a3ef0f87e83869604ec45c2f966b90f493e
Author: Michael Natterer <mitch gimp org>
Date: Thu Aug 26 18:09:33 2010 +0200
app: port GimpDisplayShell selection drawing to cairo
but keep the old code around because it's much faster. The new code is
enabled by defining the CAIRO_SELECTION environment variable.
app/display/gimpdisplayshell-draw.c | 63 +++++++++++++
app/display/gimpdisplayshell-draw.h | 9 ++
app/display/gimpdisplayshell-selection.c | 150 ++++++++++++++++++++----------
app/display/gimpdisplayshell-style.c | 78 ++++++++++++++--
app/display/gimpdisplayshell-style.h | 43 +++++----
5 files changed, 266 insertions(+), 77 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index cfd9f88..df3d99c 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -566,6 +566,69 @@ gimp_display_shell_draw_layer_boundary (GimpDisplayShell *shell,
}
void
+gimp_display_shell_draw_selection_out (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GdkSegment *segs,
+ gint n_segs)
+{
+ gint i;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (segs != NULL && n_segs > 0);
+
+ gimp_display_shell_set_selection_out_style (shell, cr);
+
+ for (i = 0; i < n_segs; i++)
+ {
+ if (segs[i].x1 == segs[i].x2)
+ {
+ cairo_move_to (cr, segs[i].x1 + 0.5, segs[i].y1);
+ cairo_line_to (cr, segs[i].x2 + 0.5, segs[i].y2);
+ }
+ else
+ {
+ cairo_move_to (cr, segs[i].x1, segs[i].y1 + 0.5);
+ cairo_line_to (cr, segs[i].x2, segs[i].y2 + 0.5);
+ }
+ }
+
+ cairo_stroke (cr);
+}
+
+void
+gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GdkSegment *segs,
+ gint n_segs,
+ gint index)
+{
+ gint i;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (segs != NULL && n_segs > 0);
+
+ gimp_display_shell_set_selection_in_style (shell, cr, index);
+
+ for (i = 0; i < n_segs; i++)
+ {
+ if (segs[i].x1 == segs[i].x2)
+ {
+ cairo_move_to (cr, segs[i].x1 + 0.5, segs[i].y1);
+ cairo_line_to (cr, segs[i].x2 + 0.5, segs[i].y2);
+ }
+ else
+ {
+ cairo_move_to (cr, segs[i].x1, segs[i].y1 + 0.5);
+ cairo_line_to (cr, segs[i].x2, segs[i].y2 + 0.5);
+ }
+ }
+
+ cairo_stroke (cr);
+}
+
+void
gimp_display_shell_draw_vector (GimpDisplayShell *shell,
GimpVectors *vectors)
{
diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h
index d9d8199..8fed497 100644
--- a/app/display/gimpdisplayshell-draw.h
+++ b/app/display/gimpdisplayshell-draw.h
@@ -53,6 +53,15 @@ void gimp_display_shell_draw_layer_boundary (GimpDisplayShell *shell,
GimpDrawable *drawable,
GdkSegment *segs,
gint n_segs);
+void gimp_display_shell_draw_selection_out (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GdkSegment *segs,
+ gint n_segs);
+void gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GdkSegment *segs,
+ gint n_segs,
+ gint index);
void gimp_display_shell_draw_vector (GimpDisplayShell *shell,
GimpVectors *vectors);
void gimp_display_shell_draw_vectors (GimpDisplayShell *shell);
diff --git a/app/display/gimpdisplayshell-selection.c b/app/display/gimpdisplayshell-selection.c
index 4741040..28b8cfd 100644
--- a/app/display/gimpdisplayshell-selection.c
+++ b/app/display/gimpdisplayshell-selection.c
@@ -51,6 +51,8 @@ struct _Selection
{
GimpDisplayShell *shell; /* shell that owns the selection */
+ gboolean use_cairo; /* temp hack */
+
GdkSegment *segs_in; /* gdk segments of area boundary */
gint n_segs_in; /* number of segments in segs_in */
@@ -122,6 +124,7 @@ gimp_display_shell_selection_init (GimpDisplayShell *shell)
selection = g_slice_new0 (Selection);
selection->shell = shell;
+ selection->use_cairo = g_getenv ("CAIRO_SELECTION") != NULL;
selection->visible = TRUE;
selection->hidden = ! gimp_display_shell_get_show_selection (shell);
selection->layer_hidden = ! gimp_display_shell_get_show_layer (shell);
@@ -295,70 +298,105 @@ selection_resume (Selection *selection)
selection_start (selection);
}
+/* #define BENCHMARK 1 */
+
static void
selection_draw (Selection *selection)
{
GimpCanvas *canvas = GIMP_CANVAS (selection->shell->canvas);
+#ifdef BENCHMARK
+ GTimer *timer = g_timer_new ();
+ gint test;
+
+ for (test = 0; test < 20; test++)
+ {
+#endif /* BENCHMARK */
+ if (selection->use_cairo)
+ {
+ if (selection->segs_in)
+ {
+ cairo_t *cr;
+
+ cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));
+
+ gimp_display_shell_draw_selection_in (selection->shell, cr,
+ selection->segs_in,
+ selection->n_segs_in,
+ selection->index % 8);
+ cairo_destroy (cr);
+ }
+ }
+ else
+ {
#ifdef USE_DRAWPOINTS
#ifdef VERBOSE
- {
- gint j, sum;
+ {
+ gint j, sum;
- sum = 0;
- for (j = 0; j < 8; j++)
- sum += selection->num_points_in[j];
+ sum = 0;
+ for (j = 0; j < 8; j++)
+ sum += selection->num_points_in[j];
- g_print ("%d segments, %d points\n", selection->n_segs_in, sum);
- }
+ g_print ("%d segments, %d points\n", selection->n_segs_in, sum);
+ }
#endif
- if (selection->segs_in)
- {
- gint i;
-
- if (selection->index == 0)
+ if (selection->segs_in)
{
- for (i = 0; i < 4; i++)
- if (selection->num_points_in[i])
- gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_WHITE,
- selection->points_in[i],
- selection->num_points_in[i]);
-
- for (i = 4; i < 8; i++)
- if (selection->num_points_in[i])
- gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_BLACK,
- selection->points_in[i],
- selection->num_points_in[i]);
- }
- else
- {
- i = ((selection->index + 3) & 7);
- if (selection->num_points_in[i])
- gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_WHITE,
- selection->points_in[i],
- selection->num_points_in[i]);
-
- i = ((selection->index + 7) & 7);
- if (selection->num_points_in[i])
- gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_BLACK,
- selection->points_in[i],
- selection->num_points_in[i]);
+ gint i;
+
+ if (selection->index == 0)
+ {
+ for (i = 0; i < 4; i++)
+ if (selection->num_points_in[i])
+ gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_WHITE,
+ selection->points_in[i],
+ selection->num_points_in[i]);
+
+ for (i = 4; i < 8; i++)
+ if (selection->num_points_in[i])
+ gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_BLACK,
+ selection->points_in[i],
+ selection->num_points_in[i]);
+ }
+ else
+ {
+ i = ((selection->index + 3) & 7);
+ if (selection->num_points_in[i])
+ gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_WHITE,
+ selection->points_in[i],
+ selection->num_points_in[i]);
+
+ i = ((selection->index + 7) & 7);
+ if (selection->num_points_in[i])
+ gimp_canvas_draw_points (canvas, GIMP_CANVAS_STYLE_BLACK,
+ selection->points_in[i],
+ selection->num_points_in[i]);
+ }
}
- }
#else /* ! USE_DRAWPOINTS */
- gimp_canvas_set_stipple_index (canvas,
- GIMP_CANVAS_STYLE_SELECTION_IN,
- selection->index);
- if (selection->segs_in)
- gimp_canvas_draw_segments (canvas, GIMP_CANVAS_STYLE_SELECTION_IN,
- selection->segs_in,
- selection->n_segs_in);
+ gimp_canvas_set_stipple_index (canvas,
+ GIMP_CANVAS_STYLE_SELECTION_IN,
+ selection->index);
+ if (selection->segs_in)
+ gimp_canvas_draw_segments (canvas, GIMP_CANVAS_STYLE_SELECTION_IN,
+ selection->segs_in,
+ selection->n_segs_in);
#endif /* USE_DRAWPOINTS */
+ }
+#ifdef BENCHMARK
+ }
+
+ g_printerr ("drawing 20 selections took %f seconds\n",
+ g_timer_elapsed (timer, NULL));
+
+ g_timer_destroy (timer);
+#endif /* BENCHMARK */
}
static void
@@ -739,10 +777,26 @@ selection_start_timeout (Selection *selection)
selection_draw (selection);
if (selection->segs_out)
- gimp_canvas_draw_segments (canvas, GIMP_CANVAS_STYLE_SELECTION_OUT,
- selection->segs_out,
- selection->n_segs_out);
+ {
+ if (selection->use_cairo)
+ {
+ cairo_t *cr;
+
+ cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));
+ gimp_display_shell_draw_selection_out (selection->shell, cr,
+ selection->segs_out,
+ selection->n_segs_out);
+
+ cairo_destroy (cr);
+ }
+ else
+ {
+ gimp_canvas_draw_segments (canvas, GIMP_CANVAS_STYLE_SELECTION_OUT,
+ selection->segs_out,
+ selection->n_segs_out);
+ }
+ }
if (selection->segs_in && selection->visible)
selection->timeout = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
diff --git a/app/display/gimpdisplayshell-style.c b/app/display/gimpdisplayshell-style.c
index 777f9b1..85366d1 100644
--- a/app/display/gimpdisplayshell-style.c
+++ b/app/display/gimpdisplayshell-style.c
@@ -20,6 +20,8 @@
#include "config.h"
+#include <string.h>
+
#include <gegl.h>
#include <gtk/gtk.h>
@@ -53,12 +55,19 @@ static const GimpRGB layer_group_bg = { 0.0, 1.0, 1.0, 1.0 };
static const GimpRGB layer_mask_fg = { 0.0, 0.0, 0.0, 1.0 };
static const GimpRGB layer_mask_bg = { 0.0, 1.0, 0.0, 1.0 };
+static const GimpRGB selection_out_fg = { 1.0, 1.0, 1.0, 1.0 };
+static const GimpRGB selection_out_bg = { 0.5, 0.5, 0.5, 1.0 };
+
+static const GimpRGB selection_in_fg = { 0.0, 0.0, 0.0, 1.0 };
+static const GimpRGB selection_in_bg = { 1.0, 1.0, 1.0, 1.0 };
+
/* local function prototypes */
static void gimp_display_shell_set_stipple_style (cairo_t *cr,
const GimpRGB *fg,
- const GimpRGB *bg);
+ const GimpRGB *bg,
+ gint index);
/* public functions */
@@ -76,11 +85,13 @@ gimp_display_shell_set_guide_style (GimpDisplayShell *shell,
if (active)
gimp_display_shell_set_stipple_style (cr,
&guide_active_fg,
- &guide_active_bg);
+ &guide_active_bg,
+ 0);
else
gimp_display_shell_set_stipple_style (cr,
&guide_normal_fg,
- &guide_normal_bg);
+ &guide_normal_bg,
+ 0);
}
void
@@ -124,7 +135,8 @@ gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
{
gimp_display_shell_set_stipple_style (cr,
&grid->fgcolor,
- &grid->bgcolor);
+ &grid->bgcolor,
+ 0);
}
else
{
@@ -132,7 +144,8 @@ gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
gimp_display_shell_set_stipple_style (cr,
&grid->fgcolor,
- &bg);
+ &bg,
+ 0);
}
break;
@@ -205,22 +218,56 @@ gimp_display_shell_set_layer_style (GimpDisplayShell *shell,
{
gimp_display_shell_set_stipple_style (cr,
&layer_mask_fg,
- &layer_mask_bg);
+ &layer_mask_bg,
+ 0);
}
else if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
{
gimp_display_shell_set_stipple_style (cr,
&layer_group_fg,
- &layer_group_bg);
+ &layer_group_bg,
+ 0);
}
else
{
gimp_display_shell_set_stipple_style (cr,
&layer_fg,
- &layer_bg);
+ &layer_bg,
+ 0);
}
}
+void
+gimp_display_shell_set_selection_out_style (GimpDisplayShell *shell,
+ cairo_t *cr)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (cr != NULL);
+
+ cairo_set_line_width (cr, 1.0);
+
+ gimp_display_shell_set_stipple_style (cr,
+ &selection_out_fg,
+ &selection_out_bg,
+ 0);
+}
+
+void
+gimp_display_shell_set_selection_in_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gint index)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+ g_return_if_fail (cr != NULL);
+
+ cairo_set_line_width (cr, 1.0);
+
+ gimp_display_shell_set_stipple_style (cr,
+ &selection_in_fg,
+ &selection_in_bg,
+ index);
+}
+
/* private functions */
@@ -229,7 +276,8 @@ static cairo_user_data_key_t surface_data_key = { 0, };
static void
gimp_display_shell_set_stipple_style (cairo_t *cr,
const GimpRGB *fg,
- const GimpRGB *bg)
+ const GimpRGB *bg,
+ gint index)
{
cairo_surface_t *surface;
guchar *data = g_malloc0 (8 * 8 * 4);
@@ -247,7 +295,7 @@ gimp_display_shell_set_stipple_style (cairo_t *cr,
{
for (x = 0; x < 8; x++)
{
- if ((y < 4 && x < 4) || (y >= 4 && x >= 4))
+ if ((x + y + index) % 8 >= 4)
GIMP_CAIRO_ARGB32_SET_PIXEL (d, fg_r, fg_g, fg_b, fg_a);
else
GIMP_CAIRO_ARGB32_SET_PIXEL (d, bg_r, bg_g, bg_b, bg_a);
@@ -256,6 +304,16 @@ gimp_display_shell_set_stipple_style (cairo_t *cr,
}
}
+ if (FALSE)//index > 0)
+ {
+ gint move = index * 4;
+ guchar *buf = g_alloca (8 * 8 * 4);
+
+ memcpy (buf, data, 8 * 8 * 4);
+ memcpy (data, buf + 8 * 8 * 4 - move, move);
+ memcpy (data + move, buf, 8 * 8 * 4 - move);
+ }
+
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
8, 8, 8 * 4);
diff --git a/app/display/gimpdisplayshell-style.h b/app/display/gimpdisplayshell-style.h
index 2717da4..8be7eea 100644
--- a/app/display/gimpdisplayshell-style.h
+++ b/app/display/gimpdisplayshell-style.h
@@ -22,25 +22,30 @@
#define __GIMP_DISPLAY_SHELL_STYLE_H__
-void gimp_display_shell_set_guide_style (GimpDisplayShell *shell,
- cairo_t *cr,
- gboolean active);
-void gimp_display_shell_set_sample_point_style (GimpDisplayShell *shell,
- cairo_t *cr,
- gboolean active);
-void gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
- cairo_t *cr,
- GimpGrid *grid);
-void gimp_display_shell_set_cursor_style (GimpDisplayShell *shell,
- cairo_t *cr);
-void gimp_display_shell_set_pen_style (GimpDisplayShell *shell,
- cairo_t *cr,
- GimpContext *context,
- GimpActiveColor active,
- gint width);
-void gimp_display_shell_set_layer_style (GimpDisplayShell *shell,
- cairo_t *cr,
- GimpDrawable *drawable);
+void gimp_display_shell_set_guide_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gboolean active);
+void gimp_display_shell_set_sample_point_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gboolean active);
+void gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GimpGrid *grid);
+void gimp_display_shell_set_cursor_style (GimpDisplayShell *shell,
+ cairo_t *cr);
+void gimp_display_shell_set_pen_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GimpContext *context,
+ GimpActiveColor active,
+ gint width);
+void gimp_display_shell_set_layer_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ GimpDrawable *drawable);
+void gimp_display_shell_set_selection_out_style (GimpDisplayShell *shell,
+ cairo_t *cr);
+void gimp_display_shell_set_selection_in_style (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gint index);
#endif /* __GIMP_DISPLAY_SHELL_STYLE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]