mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
f1d89f712d
commit
58db8a3ef0
|
@ -565,6 +565,69 @@ gimp_display_shell_draw_layer_boundary (GimpDisplayShell *shell,
|
|||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
gint 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]);
|
||||
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]);
|
||||
|
||||
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]);
|
||||
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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue