Bug 735810 - performance shrinkage of Paths tool
Use a GQueue instead of a GList in GimpCanvasGroup, so adding items takes constant time instead of O(n). Also, removing items was traversing the list twice. This should generally speed up tools with lots of canvas items. Also, add a private pointer to the instance struct instead of using a GET_PRIVATE() macro.
This commit is contained in:
@ -40,20 +40,13 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct _GimpCanvasGroupPrivate GimpCanvasGroupPrivate;
|
|
||||||
|
|
||||||
struct _GimpCanvasGroupPrivate
|
struct _GimpCanvasGroupPrivate
|
||||||
{
|
{
|
||||||
GList *items;
|
GQueue *items;
|
||||||
gboolean group_stroking;
|
gboolean group_stroking;
|
||||||
gboolean group_filling;
|
gboolean group_filling;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_PRIVATE(group) \
|
|
||||||
G_TYPE_INSTANCE_GET_PRIVATE (group, \
|
|
||||||
GIMP_TYPE_CANVAS_GROUP, \
|
|
||||||
GimpCanvasGroupPrivate)
|
|
||||||
|
|
||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
|
|
||||||
@ -115,17 +108,22 @@ gimp_canvas_group_class_init (GimpCanvasGroupClass *klass)
|
|||||||
static void
|
static void
|
||||||
gimp_canvas_group_init (GimpCanvasGroup *group)
|
gimp_canvas_group_init (GimpCanvasGroup *group)
|
||||||
{
|
{
|
||||||
|
group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
|
||||||
|
GIMP_TYPE_CANVAS_GROUP,
|
||||||
|
GimpCanvasGroupPrivate);
|
||||||
|
|
||||||
|
group->priv->items = g_queue_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_canvas_group_dispose (GObject *object)
|
gimp_canvas_group_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (object);
|
||||||
|
|
||||||
if (private->items)
|
if (group->priv->items)
|
||||||
{
|
{
|
||||||
g_list_free_full (private->items, (GDestroyNotify) g_object_unref);
|
g_queue_free_full (group->priv->items, (GDestroyNotify) g_object_unref);
|
||||||
private->items = NULL;
|
group->priv->items = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
@ -137,15 +135,15 @@ gimp_canvas_group_set_property (GObject *object,
|
|||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (object);
|
||||||
|
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case PROP_GROUP_STROKING:
|
case PROP_GROUP_STROKING:
|
||||||
private->group_stroking = g_value_get_boolean (value);
|
group->priv->group_stroking = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_GROUP_FILLING:
|
case PROP_GROUP_FILLING:
|
||||||
private->group_filling = g_value_get_boolean (value);
|
group->priv->group_filling = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -160,15 +158,15 @@ gimp_canvas_group_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (object);
|
||||||
|
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case PROP_GROUP_STROKING:
|
case PROP_GROUP_STROKING:
|
||||||
g_value_set_boolean (value, private->group_stroking);
|
g_value_set_boolean (value, group->priv->group_stroking);
|
||||||
break;
|
break;
|
||||||
case PROP_GROUP_FILLING:
|
case PROP_GROUP_FILLING:
|
||||||
g_value_set_boolean (value, private->group_filling);
|
g_value_set_boolean (value, group->priv->group_filling);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -181,31 +179,31 @@ static void
|
|||||||
gimp_canvas_group_draw (GimpCanvasItem *item,
|
gimp_canvas_group_draw (GimpCanvasItem *item,
|
||||||
cairo_t *cr)
|
cairo_t *cr)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (item);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (item);
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
for (list = private->items; list; list = g_list_next (list))
|
for (list = group->priv->items->head; list; list = g_list_next (list))
|
||||||
{
|
{
|
||||||
GimpCanvasItem *sub_item = list->data;
|
GimpCanvasItem *sub_item = list->data;
|
||||||
|
|
||||||
gimp_canvas_item_draw (sub_item, cr);
|
gimp_canvas_item_draw (sub_item, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (private->group_stroking)
|
if (group->priv->group_stroking)
|
||||||
_gimp_canvas_item_stroke (item, cr);
|
_gimp_canvas_item_stroke (item, cr);
|
||||||
|
|
||||||
if (private->group_filling)
|
if (group->priv->group_filling)
|
||||||
_gimp_canvas_item_fill (item, cr);
|
_gimp_canvas_item_fill (item, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_region_t *
|
static cairo_region_t *
|
||||||
gimp_canvas_group_get_extents (GimpCanvasItem *item)
|
gimp_canvas_group_get_extents (GimpCanvasItem *item)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (item);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (item);
|
||||||
cairo_region_t *region = NULL;
|
cairo_region_t *region = NULL;
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
for (list = private->items; list; list = g_list_next (list))
|
for (list = group->priv->items->head; list; list = g_list_next (list))
|
||||||
{
|
{
|
||||||
GimpCanvasItem *sub_item = list->data;
|
GimpCanvasItem *sub_item = list->data;
|
||||||
cairo_region_t *sub_region = gimp_canvas_item_get_extents (sub_item);
|
cairo_region_t *sub_region = gimp_canvas_item_get_extents (sub_item);
|
||||||
@ -229,10 +227,10 @@ gimp_canvas_group_hit (GimpCanvasItem *item,
|
|||||||
gdouble x,
|
gdouble x,
|
||||||
gdouble y)
|
gdouble y)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private = GET_PRIVATE (item);
|
GimpCanvasGroup *group = GIMP_CANVAS_GROUP (item);
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
for (list = private->items; list; list = g_list_next (list))
|
for (list = group->priv->items->head; list; list = g_list_next (list))
|
||||||
{
|
{
|
||||||
if (gimp_canvas_item_hit (list->data, x, y))
|
if (gimp_canvas_item_hit (list->data, x, y))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -267,21 +265,17 @@ void
|
|||||||
gimp_canvas_group_add_item (GimpCanvasGroup *group,
|
gimp_canvas_group_add_item (GimpCanvasGroup *group,
|
||||||
GimpCanvasItem *item)
|
GimpCanvasItem *item)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
|
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
|
||||||
g_return_if_fail (GIMP_CANVAS_ITEM (group) != item);
|
g_return_if_fail (GIMP_CANVAS_ITEM (group) != item);
|
||||||
|
|
||||||
private = GET_PRIVATE (group);
|
if (group->priv->group_stroking)
|
||||||
|
|
||||||
if (private->group_stroking)
|
|
||||||
gimp_canvas_item_suspend_stroking (item);
|
gimp_canvas_item_suspend_stroking (item);
|
||||||
|
|
||||||
if (private->group_filling)
|
if (group->priv->group_filling)
|
||||||
gimp_canvas_item_suspend_filling (item);
|
gimp_canvas_item_suspend_filling (item);
|
||||||
|
|
||||||
private->items = g_list_append (private->items, g_object_ref (item));
|
g_queue_push_tail (group->priv->items, g_object_ref (item));
|
||||||
|
|
||||||
if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
|
if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
|
||||||
{
|
{
|
||||||
@ -303,21 +297,21 @@ void
|
|||||||
gimp_canvas_group_remove_item (GimpCanvasGroup *group,
|
gimp_canvas_group_remove_item (GimpCanvasGroup *group,
|
||||||
GimpCanvasItem *item)
|
GimpCanvasItem *item)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private;
|
GList *list;
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
|
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
|
||||||
|
|
||||||
private = GET_PRIVATE (group);
|
list = g_queue_find (group->priv->items, item);
|
||||||
|
|
||||||
g_return_if_fail (g_list_find (private->items, item));
|
g_return_if_fail (list != NULL);
|
||||||
|
|
||||||
private->items = g_list_remove (private->items, item);
|
g_queue_delete_link (group->priv->items, list);
|
||||||
|
|
||||||
if (private->group_stroking)
|
if (group->priv->group_stroking)
|
||||||
gimp_canvas_item_resume_stroking (item);
|
gimp_canvas_item_resume_stroking (item);
|
||||||
|
|
||||||
if (private->group_filling)
|
if (group->priv->group_filling)
|
||||||
gimp_canvas_item_resume_filling (item);
|
gimp_canvas_item_resume_filling (item);
|
||||||
|
|
||||||
if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
|
if (_gimp_canvas_item_needs_update (GIMP_CANVAS_ITEM (group)))
|
||||||
@ -342,13 +336,9 @@ void
|
|||||||
gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
|
gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
|
||||||
gboolean group_stroking)
|
gboolean group_stroking)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
||||||
|
|
||||||
private = GET_PRIVATE (group);
|
if (group->priv->group_stroking != group_stroking)
|
||||||
|
|
||||||
if (private->group_stroking != group_stroking)
|
|
||||||
{
|
{
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
@ -358,9 +348,9 @@ gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
|
|||||||
"group-stroking", group_stroking ? TRUE : FALSE,
|
"group-stroking", group_stroking ? TRUE : FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
for (list = private->items; list; list = g_list_next (list))
|
for (list = group->priv->items->head; list; list = g_list_next (list))
|
||||||
{
|
{
|
||||||
if (private->group_stroking)
|
if (group->priv->group_stroking)
|
||||||
gimp_canvas_item_suspend_stroking (list->data);
|
gimp_canvas_item_suspend_stroking (list->data);
|
||||||
else
|
else
|
||||||
gimp_canvas_item_resume_stroking (list->data);
|
gimp_canvas_item_resume_stroking (list->data);
|
||||||
@ -374,13 +364,9 @@ void
|
|||||||
gimp_canvas_group_set_group_filling (GimpCanvasGroup *group,
|
gimp_canvas_group_set_group_filling (GimpCanvasGroup *group,
|
||||||
gboolean group_filling)
|
gboolean group_filling)
|
||||||
{
|
{
|
||||||
GimpCanvasGroupPrivate *private;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
|
||||||
|
|
||||||
private = GET_PRIVATE (group);
|
if (group->priv->group_filling != group_filling)
|
||||||
|
|
||||||
if (private->group_filling != group_filling)
|
|
||||||
{
|
{
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
@ -390,9 +376,9 @@ gimp_canvas_group_set_group_filling (GimpCanvasGroup *group,
|
|||||||
"group-filling", group_filling ? TRUE : FALSE,
|
"group-filling", group_filling ? TRUE : FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
for (list = private->items; list; list = g_list_next (list))
|
for (list = group->priv->items->head; list; list = g_list_next (list))
|
||||||
{
|
{
|
||||||
if (private->group_filling)
|
if (group->priv->group_filling)
|
||||||
gimp_canvas_item_suspend_filling (list->data);
|
gimp_canvas_item_suspend_filling (list->data);
|
||||||
else
|
else
|
||||||
gimp_canvas_item_resume_filling (list->data);
|
gimp_canvas_item_resume_filling (list->data);
|
||||||
|
@ -33,11 +33,15 @@
|
|||||||
#define GIMP_CANVAS_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_GROUP, GimpCanvasGroupClass))
|
#define GIMP_CANVAS_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_GROUP, GimpCanvasGroupClass))
|
||||||
|
|
||||||
|
|
||||||
typedef struct _GimpCanvasGroupClass GimpCanvasGroupClass;
|
typedef struct _GimpCanvasGroupPrivate GimpCanvasGroupPrivate;
|
||||||
|
typedef struct _GimpCanvasGroupClass GimpCanvasGroupClass;
|
||||||
|
|
||||||
struct _GimpCanvasGroup
|
struct _GimpCanvasGroup
|
||||||
{
|
{
|
||||||
GimpCanvasItem parent_instance;
|
GimpCanvasItem parent_instance;
|
||||||
|
|
||||||
|
GimpCanvasGroupPrivate *priv;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GimpCanvasGroupClass
|
struct _GimpCanvasGroupClass
|
||||||
|
Reference in New Issue
Block a user