app: completely switch to cairo-drawing the selection
and remove all old selection drawing code. Thanks to Benjamin Otte for pointing out the right optimization. Also fixes bug #479875 - performance problem drawing a complex selection.
This commit is contained in:
@ -56,7 +56,6 @@ static void gimp_canvas_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
|
|
||||||
static void gimp_canvas_realize (GtkWidget *widget);
|
|
||||||
static void gimp_canvas_unrealize (GtkWidget *widget);
|
static void gimp_canvas_unrealize (GtkWidget *widget);
|
||||||
static void gimp_canvas_style_set (GtkWidget *widget,
|
static void gimp_canvas_style_set (GtkWidget *widget,
|
||||||
GtkStyle *prev_style);
|
GtkStyle *prev_style);
|
||||||
@ -76,91 +75,6 @@ G_DEFINE_TYPE (GimpCanvas, gimp_canvas, GIMP_TYPE_OVERLAY_BOX)
|
|||||||
#define parent_class gimp_canvas_parent_class
|
#define parent_class gimp_canvas_parent_class
|
||||||
|
|
||||||
|
|
||||||
static const guchar stipples[GIMP_CANVAS_NUM_STIPPLES][8] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x78, /* -####--- */
|
|
||||||
0xF0, /* ####---- */
|
|
||||||
0xE1, /* ###----# */
|
|
||||||
0xC3, /* ##----## */
|
|
||||||
0x87, /* #----### */
|
|
||||||
0x0F, /* ----#### */
|
|
||||||
0x1E, /* ---####- */
|
|
||||||
0x3C, /* --####-- */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_canvas_class_init (GimpCanvasClass *klass)
|
gimp_canvas_class_init (GimpCanvasClass *klass)
|
||||||
{
|
{
|
||||||
@ -170,7 +84,6 @@ gimp_canvas_class_init (GimpCanvasClass *klass)
|
|||||||
object_class->set_property = gimp_canvas_set_property;
|
object_class->set_property = gimp_canvas_set_property;
|
||||||
object_class->get_property = gimp_canvas_get_property;
|
object_class->get_property = gimp_canvas_get_property;
|
||||||
|
|
||||||
widget_class->realize = gimp_canvas_realize;
|
|
||||||
widget_class->unrealize = gimp_canvas_unrealize;
|
widget_class->unrealize = gimp_canvas_unrealize;
|
||||||
widget_class->style_set = gimp_canvas_style_set;
|
widget_class->style_set = gimp_canvas_style_set;
|
||||||
widget_class->focus_in_event = gimp_canvas_focus_in_event;
|
widget_class->focus_in_event = gimp_canvas_focus_in_event;
|
||||||
@ -197,9 +110,6 @@ gimp_canvas_init (GimpCanvas *canvas)
|
|||||||
|
|
||||||
for (i = 0; i < GIMP_CANVAS_NUM_STYLES; i++)
|
for (i = 0; i < GIMP_CANVAS_NUM_STYLES; i++)
|
||||||
canvas->gc[i] = NULL;
|
canvas->gc[i] = NULL;
|
||||||
|
|
||||||
for (i = 0; i < GIMP_CANVAS_NUM_STIPPLES; i++)
|
|
||||||
canvas->stipple[i] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -240,18 +150,6 @@ gimp_canvas_get_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gimp_canvas_realize (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
GimpCanvas *canvas = GIMP_CANVAS (widget);
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (parent_class)->realize (widget);
|
|
||||||
|
|
||||||
canvas->stipple[0] =
|
|
||||||
gdk_bitmap_create_from_data (gtk_widget_get_window (widget),
|
|
||||||
(const gchar *) stipples[0], 8, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_canvas_unrealize (GtkWidget *widget)
|
gimp_canvas_unrealize (GtkWidget *widget)
|
||||||
{
|
{
|
||||||
@ -267,15 +165,6 @@ gimp_canvas_unrealize (GtkWidget *widget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < GIMP_CANVAS_NUM_STIPPLES; i++)
|
|
||||||
{
|
|
||||||
if (canvas->stipple[i])
|
|
||||||
{
|
|
||||||
g_object_unref (canvas->stipple[i]);
|
|
||||||
canvas->stipple[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas->layout)
|
if (canvas->layout)
|
||||||
{
|
{
|
||||||
g_object_unref (canvas->layout);
|
g_object_unref (canvas->layout);
|
||||||
@ -369,10 +258,6 @@ gimp_canvas_gc_new (GimpCanvas *canvas,
|
|||||||
|
|
||||||
switch (style)
|
switch (style)
|
||||||
{
|
{
|
||||||
case GIMP_CANVAS_STYLE_BLACK:
|
|
||||||
case GIMP_CANVAS_STYLE_WHITE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GIMP_CANVAS_STYLE_RENDER:
|
case GIMP_CANVAS_STYLE_RENDER:
|
||||||
mask |= GDK_GC_EXPOSURES;
|
mask |= GDK_GC_EXPOSURES;
|
||||||
values.graphics_exposures = TRUE;
|
values.graphics_exposures = TRUE;
|
||||||
@ -396,14 +281,6 @@ gimp_canvas_gc_new (GimpCanvas *canvas,
|
|||||||
values.join_style = GDK_JOIN_MITER;
|
values.join_style = GDK_JOIN_MITER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_CANVAS_STYLE_SELECTION_IN:
|
|
||||||
case GIMP_CANVAS_STYLE_SELECTION_OUT:
|
|
||||||
mask |= GDK_GC_CAP_STYLE | GDK_GC_FILL | GDK_GC_STIPPLE;
|
|
||||||
values.cap_style = GDK_CAP_NOT_LAST;
|
|
||||||
values.fill = GDK_OPAQUE_STIPPLED;
|
|
||||||
values.stipple = canvas->stipple[0];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -426,33 +303,6 @@ gimp_canvas_gc_new (GimpCanvas *canvas,
|
|||||||
case GIMP_CANVAS_STYLE_XOR_DASHED:
|
case GIMP_CANVAS_STYLE_XOR_DASHED:
|
||||||
case GIMP_CANVAS_STYLE_XOR:
|
case GIMP_CANVAS_STYLE_XOR:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_CANVAS_STYLE_WHITE:
|
|
||||||
fg.red = 0xffff;
|
|
||||||
fg.green = 0xffff;
|
|
||||||
fg.blue = 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GIMP_CANVAS_STYLE_BLACK:
|
|
||||||
case GIMP_CANVAS_STYLE_SELECTION_IN:
|
|
||||||
fg.red = 0x0;
|
|
||||||
fg.green = 0x0;
|
|
||||||
fg.blue = 0x0;
|
|
||||||
|
|
||||||
bg.red = 0xffff;
|
|
||||||
bg.green = 0xffff;
|
|
||||||
bg.blue = 0xffff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GIMP_CANVAS_STYLE_SELECTION_OUT:
|
|
||||||
fg.red = 0xffff;
|
|
||||||
fg.green = 0xffff;
|
|
||||||
fg.blue = 0xffff;
|
|
||||||
|
|
||||||
bg.red = 0x7f7f;
|
|
||||||
bg.green = 0x7f7f;
|
|
||||||
bg.blue = 0x7f7f;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gdk_gc_set_rgb_fg_color (gc, &fg);
|
gdk_gc_set_rgb_fg_color (gc, &fg);
|
||||||
@ -885,40 +735,6 @@ gimp_canvas_set_clip_region (GimpCanvas *canvas,
|
|||||||
gdk_gc_set_clip_region (canvas->gc[style], region);
|
gdk_gc_set_clip_region (canvas->gc[style], region);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gimp_canvas_set_stipple_index:
|
|
||||||
* @canvas: a #GimpCanvas widget
|
|
||||||
* @style: the #GimpCanvasStyle to alter
|
|
||||||
* @index: the new stipple index
|
|
||||||
*
|
|
||||||
* Some styles of the #GimpCanvas do a stipple fill. #GimpCanvas has a
|
|
||||||
* set of %GIMP_CANVAS_NUM_STIPPLES stipple bitmaps. This function
|
|
||||||
* allows you to change the bitmap being used. This can be used to
|
|
||||||
* implement a marching ants effect. An older implementation used to
|
|
||||||
* use this feature and so it is included since it might be useful in
|
|
||||||
* the future. All stipple bitmaps but the default one are created on
|
|
||||||
* the fly.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
gimp_canvas_set_stipple_index (GimpCanvas *canvas,
|
|
||||||
GimpCanvasStyle style,
|
|
||||||
guint index)
|
|
||||||
{
|
|
||||||
if (! gimp_canvas_ensure_style (canvas, style))
|
|
||||||
return;
|
|
||||||
|
|
||||||
index = index % GIMP_CANVAS_NUM_STIPPLES;
|
|
||||||
|
|
||||||
if (! canvas->stipple[index])
|
|
||||||
{
|
|
||||||
canvas->stipple[index] =
|
|
||||||
gdk_bitmap_create_from_data (gtk_widget_get_window (GTK_WIDGET (canvas)),
|
|
||||||
(const gchar *) stipples[index], 8, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
gdk_gc_set_stipple (canvas->gc[style], canvas->stipple[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gimp_canvas_set_bg_color:
|
* gimp_canvas_set_bg_color:
|
||||||
* @canvas: a #GimpCanvas widget
|
* @canvas: a #GimpCanvas widget
|
||||||
|
@ -24,14 +24,10 @@
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GIMP_CANVAS_STYLE_BLACK,
|
|
||||||
GIMP_CANVAS_STYLE_WHITE,
|
|
||||||
GIMP_CANVAS_STYLE_RENDER,
|
GIMP_CANVAS_STYLE_RENDER,
|
||||||
GIMP_CANVAS_STYLE_XOR,
|
GIMP_CANVAS_STYLE_XOR,
|
||||||
GIMP_CANVAS_STYLE_XOR_DASHED,
|
GIMP_CANVAS_STYLE_XOR_DASHED,
|
||||||
GIMP_CANVAS_STYLE_XOR_DOTTED,
|
GIMP_CANVAS_STYLE_XOR_DOTTED,
|
||||||
GIMP_CANVAS_STYLE_SELECTION_IN,
|
|
||||||
GIMP_CANVAS_STYLE_SELECTION_OUT,
|
|
||||||
GIMP_CANVAS_NUM_STYLES
|
GIMP_CANVAS_NUM_STYLES
|
||||||
} GimpCanvasStyle;
|
} GimpCanvasStyle;
|
||||||
|
|
||||||
@ -147,9 +143,6 @@ void gimp_canvas_set_clip_rect (GimpCanvas *canvas,
|
|||||||
void gimp_canvas_set_clip_region (GimpCanvas *canvas,
|
void gimp_canvas_set_clip_region (GimpCanvas *canvas,
|
||||||
GimpCanvasStyle style,
|
GimpCanvasStyle style,
|
||||||
const GdkRegion *region);
|
const GdkRegion *region);
|
||||||
void gimp_canvas_set_stipple_index (GimpCanvas *canvas,
|
|
||||||
GimpCanvasStyle style,
|
|
||||||
guint index);
|
|
||||||
void gimp_canvas_set_bg_color (GimpCanvas *canvas,
|
void gimp_canvas_set_bg_color (GimpCanvas *canvas,
|
||||||
GimpRGB *color);
|
GimpRGB *color);
|
||||||
|
|
||||||
|
@ -598,11 +598,10 @@ gimp_display_shell_draw_selection_out (GimpDisplayShell *shell,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
|
gimp_display_shell_draw_selection_segments (GimpDisplayShell *shell,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
GdkSegment *segs,
|
GdkSegment *segs,
|
||||||
gint n_segs,
|
gint n_segs)
|
||||||
gint index)
|
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
@ -610,7 +609,7 @@ gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
|
|||||||
g_return_if_fail (cr != NULL);
|
g_return_if_fail (cr != NULL);
|
||||||
g_return_if_fail (segs != NULL && n_segs > 0);
|
g_return_if_fail (segs != NULL && n_segs > 0);
|
||||||
|
|
||||||
gimp_display_shell_set_selection_in_style (shell, cr, index);
|
cairo_set_line_width (cr, 1.0);
|
||||||
|
|
||||||
for (i = 0; i < n_segs; i++)
|
for (i = 0; i < n_segs; i++)
|
||||||
{
|
{
|
||||||
@ -629,6 +628,21 @@ gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
|
|||||||
cairo_stroke (cr);
|
cairo_stroke (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_display_shell_draw_selection_in_mask (GimpDisplayShell *shell,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_pattern_t *mask,
|
||||||
|
gint index)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||||
|
g_return_if_fail (cr != NULL);
|
||||||
|
g_return_if_fail (mask != NULL);
|
||||||
|
|
||||||
|
gimp_display_shell_set_selection_in_style (shell, cr, index);
|
||||||
|
|
||||||
|
cairo_mask (cr, mask);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_display_shell_draw_vector (GimpDisplayShell *shell,
|
gimp_display_shell_draw_vector (GimpDisplayShell *shell,
|
||||||
GimpVectors *vectors)
|
GimpVectors *vectors)
|
||||||
|
@ -57,10 +57,13 @@ void gimp_display_shell_draw_selection_out (GimpDisplayShell *shell,
|
|||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
GdkSegment *segs,
|
GdkSegment *segs,
|
||||||
gint n_segs);
|
gint n_segs);
|
||||||
void gimp_display_shell_draw_selection_in (GimpDisplayShell *shell,
|
void gimp_display_shell_draw_selection_segments (GimpDisplayShell *shell,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
GdkSegment *segs,
|
GdkSegment *segs,
|
||||||
gint n_segs,
|
gint n_segs);
|
||||||
|
void gimp_display_shell_draw_selection_in_mask (GimpDisplayShell *shell,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_pattern_t *mask,
|
||||||
gint index);
|
gint index);
|
||||||
void gimp_display_shell_draw_vector (GimpDisplayShell *shell,
|
void gimp_display_shell_draw_vector (GimpDisplayShell *shell,
|
||||||
GimpVectors *vectors);
|
GimpVectors *vectors);
|
||||||
|
@ -41,18 +41,10 @@
|
|||||||
#include "gimpdisplayshell-transform.h"
|
#include "gimpdisplayshell-transform.h"
|
||||||
|
|
||||||
|
|
||||||
#undef VERBOSE
|
|
||||||
|
|
||||||
#define MAX_POINTS_INC 2048
|
|
||||||
#define USE_DRAWPOINTS TRUE
|
|
||||||
|
|
||||||
|
|
||||||
struct _Selection
|
struct _Selection
|
||||||
{
|
{
|
||||||
GimpDisplayShell *shell; /* shell that owns the selection */
|
GimpDisplayShell *shell; /* shell that owns the selection */
|
||||||
|
|
||||||
gboolean use_cairo; /* temp hack */
|
|
||||||
|
|
||||||
GdkSegment *segs_in; /* gdk segments of area boundary */
|
GdkSegment *segs_in; /* gdk segments of area boundary */
|
||||||
gint n_segs_in; /* number of segments in segs_in */
|
gint n_segs_in; /* number of segments in segs_in */
|
||||||
|
|
||||||
@ -68,8 +60,7 @@ struct _Selection
|
|||||||
gboolean hidden; /* is the selection hidden? */
|
gboolean hidden; /* is the selection hidden? */
|
||||||
gboolean layer_hidden; /* is the layer boundary hidden? */
|
gboolean layer_hidden; /* is the layer boundary hidden? */
|
||||||
guint timeout; /* timer for successive draws */
|
guint timeout; /* timer for successive draws */
|
||||||
GdkPoint *points_in[8]; /* points of segs_in for fast ants */
|
cairo_pattern_t *segs_in_mask; /* cache for rendered segments */
|
||||||
gint num_points_in[8]; /* number of points in points_in */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -86,12 +77,7 @@ static void selection_undraw (Selection *selection);
|
|||||||
static void selection_layer_undraw (Selection *selection);
|
static void selection_layer_undraw (Selection *selection);
|
||||||
static void selection_layer_draw (Selection *selection);
|
static void selection_layer_draw (Selection *selection);
|
||||||
|
|
||||||
static void selection_add_point (GdkPoint *points[8],
|
static void selection_render_mask (Selection *selection);
|
||||||
gint max_npoints[8],
|
|
||||||
gint npoints[8],
|
|
||||||
gint x,
|
|
||||||
gint y);
|
|
||||||
static void selection_render_points (Selection *selection);
|
|
||||||
|
|
||||||
static void selection_transform_segs (Selection *selection,
|
static void selection_transform_segs (Selection *selection,
|
||||||
const BoundSeg *src_segs,
|
const BoundSeg *src_segs,
|
||||||
@ -124,7 +110,6 @@ gimp_display_shell_selection_init (GimpDisplayShell *shell)
|
|||||||
selection = g_slice_new0 (Selection);
|
selection = g_slice_new0 (Selection);
|
||||||
|
|
||||||
selection->shell = shell;
|
selection->shell = shell;
|
||||||
selection->use_cairo = g_getenv ("CAIRO_SELECTION") != NULL;
|
|
||||||
selection->visible = TRUE;
|
selection->visible = TRUE;
|
||||||
selection->hidden = ! gimp_display_shell_get_show_selection (shell);
|
selection->hidden = ! gimp_display_shell_get_show_selection (shell);
|
||||||
selection->layer_hidden = ! gimp_display_shell_get_show_layer (shell);
|
selection->layer_hidden = ! gimp_display_shell_get_show_layer (shell);
|
||||||
@ -298,105 +283,21 @@ selection_resume (Selection *selection)
|
|||||||
selection_start (selection);
|
selection_start (selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #define BENCHMARK 1 */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
selection_draw (Selection *selection)
|
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)
|
if (selection->segs_in)
|
||||||
{
|
{
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|
||||||
cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));
|
cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));
|
||||||
|
|
||||||
gimp_display_shell_draw_selection_in (selection->shell, cr,
|
gimp_display_shell_draw_selection_in_mask (selection->shell, cr,
|
||||||
selection->segs_in,
|
selection->segs_in_mask,
|
||||||
selection->n_segs_in,
|
|
||||||
selection->index % 8);
|
selection->index % 8);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef USE_DRAWPOINTS
|
|
||||||
|
|
||||||
#ifdef VERBOSE
|
|
||||||
{
|
|
||||||
gint j, sum;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (selection->segs_in)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
#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
|
static void
|
||||||
@ -474,137 +375,21 @@ selection_layer_undraw (Selection *selection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
selection_add_point (GdkPoint *points[8],
|
selection_render_mask (Selection *selection)
|
||||||
gint max_npoints[8],
|
|
||||||
gint npoints[8],
|
|
||||||
gint x,
|
|
||||||
gint y)
|
|
||||||
{
|
{
|
||||||
gint i, j;
|
cairo_t *cr;
|
||||||
|
|
||||||
j = (x - y) & 7;
|
cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));
|
||||||
|
|
||||||
i = npoints[j]++;
|
cairo_push_group_with_content (cr, CAIRO_CONTENT_ALPHA);
|
||||||
if (i == max_npoints[j])
|
|
||||||
{
|
|
||||||
max_npoints[j] += 2048;
|
|
||||||
points[j] = g_realloc (points[j], sizeof (GdkPoint) * max_npoints[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
points[j][i].x = x;
|
gimp_display_shell_draw_selection_segments (selection->shell, cr,
|
||||||
points[j][i].y = y;
|
selection->segs_in,
|
||||||
}
|
selection->n_segs_in);
|
||||||
|
|
||||||
|
selection->segs_in_mask = cairo_pop_group (cr);
|
||||||
|
|
||||||
/* Render the segs_in array into points_in */
|
cairo_destroy (cr);
|
||||||
|
|
||||||
static void
|
|
||||||
selection_render_points (Selection *selection)
|
|
||||||
{
|
|
||||||
gint max_npoints[8];
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
if (selection->segs_in == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
max_npoints[i] = MAX_POINTS_INC;
|
|
||||||
selection->points_in[i] = g_new (GdkPoint, max_npoints[i]);
|
|
||||||
selection->num_points_in[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < selection->n_segs_in; i++)
|
|
||||||
{
|
|
||||||
gint x, y;
|
|
||||||
gint dx, dy;
|
|
||||||
gint dxa, dya;
|
|
||||||
gint r;
|
|
||||||
|
|
||||||
#ifdef VERBOSE
|
|
||||||
g_print ("%2d: (%d, %d) - (%d, %d)\n", i,
|
|
||||||
selection->segs_in[i].x1,
|
|
||||||
selection->segs_in[i].y1,
|
|
||||||
selection->segs_in[i].x2,
|
|
||||||
selection->segs_in[i].y2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
x = selection->segs_in[i].x1;
|
|
||||||
dxa = selection->segs_in[i].x2 - x;
|
|
||||||
|
|
||||||
if (dxa > 0)
|
|
||||||
{
|
|
||||||
dx = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dxa = -dxa;
|
|
||||||
dx = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
y = selection->segs_in[i].y1;
|
|
||||||
dya = selection->segs_in[i].y2 - y;
|
|
||||||
|
|
||||||
if (dya > 0)
|
|
||||||
{
|
|
||||||
dy = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dya = -dya;
|
|
||||||
dy = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dxa > dya)
|
|
||||||
{
|
|
||||||
r = dya;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
selection_add_point (selection->points_in,
|
|
||||||
max_npoints,
|
|
||||||
selection->num_points_in,
|
|
||||||
x, y);
|
|
||||||
x += dx;
|
|
||||||
r += dya;
|
|
||||||
|
|
||||||
if (r >= (dxa << 1))
|
|
||||||
{
|
|
||||||
y += dy;
|
|
||||||
r -= (dxa << 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (x != selection->segs_in[i].x2);
|
|
||||||
}
|
|
||||||
else if (dxa < dya)
|
|
||||||
{
|
|
||||||
r = dxa;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
selection_add_point (selection->points_in,
|
|
||||||
max_npoints,
|
|
||||||
selection->num_points_in,
|
|
||||||
x, y);
|
|
||||||
y += dy;
|
|
||||||
r += dxa;
|
|
||||||
|
|
||||||
if (r >= (dya << 1))
|
|
||||||
{
|
|
||||||
x += dx;
|
|
||||||
r -= (dya << 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (y != selection->segs_in[i].y2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
selection_add_point (selection->points_in,
|
|
||||||
max_npoints,
|
|
||||||
selection->num_points_in,
|
|
||||||
x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -672,9 +457,7 @@ selection_generate_segs (Selection *selection)
|
|||||||
selection_transform_segs (selection, segs_in,
|
selection_transform_segs (selection, segs_in,
|
||||||
selection->segs_in, selection->n_segs_in);
|
selection->segs_in, selection->n_segs_in);
|
||||||
|
|
||||||
#ifdef USE_DRAWPOINTS
|
selection_render_mask (selection);
|
||||||
selection_render_points (selection);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -718,8 +501,6 @@ selection_generate_segs (Selection *selection)
|
|||||||
static void
|
static void
|
||||||
selection_free_segs (Selection *selection)
|
selection_free_segs (Selection *selection)
|
||||||
{
|
{
|
||||||
gint j;
|
|
||||||
|
|
||||||
if (selection->segs_in)
|
if (selection->segs_in)
|
||||||
{
|
{
|
||||||
g_free (selection->segs_in);
|
g_free (selection->segs_in);
|
||||||
@ -741,14 +522,10 @@ selection_free_segs (Selection *selection)
|
|||||||
selection->n_segs_layer = 0;
|
selection->n_segs_layer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 8; j++)
|
if (selection->segs_in_mask)
|
||||||
{
|
{
|
||||||
if (selection->points_in[j])
|
cairo_pattern_destroy (selection->segs_in_mask);
|
||||||
{
|
selection->segs_in_mask = NULL;
|
||||||
g_free (selection->points_in[j]);
|
|
||||||
selection->points_in[j] = NULL;
|
|
||||||
selection->num_points_in[j] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,14 +548,11 @@ selection_start_timeout (Selection *selection)
|
|||||||
/* Draw the ants */
|
/* Draw the ants */
|
||||||
if (! selection->hidden)
|
if (! selection->hidden)
|
||||||
{
|
{
|
||||||
GimpCanvas *canvas = GIMP_CANVAS (selection->shell->canvas);
|
|
||||||
GimpDisplayConfig *config = selection->shell->display->config;
|
GimpDisplayConfig *config = selection->shell->display->config;
|
||||||
|
|
||||||
selection_draw (selection);
|
selection_draw (selection);
|
||||||
|
|
||||||
if (selection->segs_out)
|
if (selection->segs_out)
|
||||||
{
|
|
||||||
if (selection->use_cairo)
|
|
||||||
{
|
{
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|
||||||
@ -790,13 +564,6 @@ selection_start_timeout (Selection *selection)
|
|||||||
|
|
||||||
cairo_destroy (cr);
|
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)
|
if (selection->segs_in && selection->visible)
|
||||||
selection->timeout = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
|
selection->timeout = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
|
||||||
|
Reference in New Issue
Block a user