app: when freezing a drawable's preview, freeze ancestors' previews

Add GimpViewable::preview_{freeze,thaw}() virtual functions, which
get called when the viewable's preview is frozen/thawed.  Implement
the functions in GimpDrawable, recursively freezing the parent
drawable's preview (or the image's preview, for top-level
drawables) while the drawable's preview is frozen.  For layer
masks, freeze the associated layer's parent.

This avoids updating layer-group/image previews while painting on,
or applying a filter to, a descendant layer.  This both reduces
lag, and fixes a discrepancy between the layer's preview, which
isn't updated, and its parents' previews.
This commit is contained in:
Ell 2019-03-28 12:03:49 -04:00
parent d821b088e2
commit e2ea2e4a82
4 changed files with 81 additions and 1 deletions

View file

@ -100,6 +100,8 @@ static gint64 gimp_drawable_get_memsize (GimpObject *object,
static gboolean gimp_drawable_get_size (GimpViewable *viewable,
gint *width,
gint *height);
static void gimp_drawable_preview_freeze (GimpViewable *viewable);
static void gimp_drawable_preview_thaw (GimpViewable *viewable);
static GeglNode * gimp_drawable_get_node (GimpFilter *filter);
@ -267,6 +269,8 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
viewable_class->get_size = gimp_drawable_get_size;
viewable_class->get_new_preview = gimp_drawable_get_new_preview;
viewable_class->get_new_pixbuf = gimp_drawable_get_new_pixbuf;
viewable_class->preview_freeze = gimp_drawable_preview_freeze;
viewable_class->preview_thaw = gimp_drawable_preview_thaw;
filter_class->get_node = gimp_drawable_get_node;
@ -418,6 +422,28 @@ gimp_drawable_get_size (GimpViewable *viewable,
return TRUE;
}
static void
gimp_drawable_preview_freeze (GimpViewable *viewable)
{
GimpViewable *parent = gimp_viewable_get_parent (viewable);
if (! parent)
parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable)));
gimp_viewable_preview_freeze (parent);
}
static void
gimp_drawable_preview_thaw (GimpViewable *viewable)
{
GimpViewable *parent = gimp_viewable_get_parent (viewable);
if (! parent)
parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable)));
gimp_viewable_preview_thaw (parent);
}
static GeglNode *
gimp_drawable_get_node (GimpFilter *filter)
{

View file

@ -32,6 +32,9 @@
#include "gimp-intl.h"
static void gimp_layer_mask_preview_freeze (GimpViewable *viewable);
static void gimp_layer_mask_preview_thaw (GimpViewable *viewable);
static gboolean gimp_layer_mask_is_attached (GimpItem *item);
static gboolean gimp_layer_mask_is_content_locked (GimpItem *item);
static gboolean gimp_layer_mask_is_position_locked (GimpItem *item);
@ -68,6 +71,9 @@ gimp_layer_mask_class_init (GimpLayerMaskClass *klass)
viewable_class->default_icon_name = "gimp-layer-mask";
viewable_class->preview_freeze = gimp_layer_mask_preview_freeze;
viewable_class->preview_thaw = gimp_layer_mask_preview_thaw;
item_class->is_attached = gimp_layer_mask_is_attached;
item_class->is_content_locked = gimp_layer_mask_is_content_locked;
item_class->is_position_locked = gimp_layer_mask_is_position_locked;
@ -86,6 +92,40 @@ gimp_layer_mask_init (GimpLayerMask *layer_mask)
layer_mask->layer = NULL;
}
static void
gimp_layer_mask_preview_freeze (GimpViewable *viewable)
{
GimpLayerMask *mask = GIMP_LAYER_MASK (viewable);
GimpLayer *layer = gimp_layer_mask_get_layer (mask);
if (layer)
{
GimpViewable *parent = gimp_viewable_get_parent (GIMP_VIEWABLE (layer));
if (! parent)
parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (layer)));
gimp_viewable_preview_freeze (parent);
}
}
static void
gimp_layer_mask_preview_thaw (GimpViewable *viewable)
{
GimpLayerMask *mask = GIMP_LAYER_MASK (viewable);
GimpLayer *layer = gimp_layer_mask_get_layer (mask);
if (layer)
{
GimpViewable *parent = gimp_viewable_get_parent (GIMP_VIEWABLE (layer));
if (! parent)
parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (layer)));
gimp_viewable_preview_thaw (parent);
}
}
static gboolean
gimp_layer_mask_is_content_locked (GimpItem *item)
{

View file

@ -204,6 +204,8 @@ gimp_viewable_class_init (GimpViewableClass *klass)
klass->get_new_pixbuf = gimp_viewable_real_get_new_pixbuf;
klass->get_description = gimp_viewable_real_get_description;
klass->is_name_editable = gimp_viewable_real_is_name_editable;
klass->preview_freeze = NULL;
klass->preview_thaw = NULL;
klass->get_children = gimp_viewable_real_get_children;
klass->set_expanded = NULL;
klass->get_expanded = NULL;
@ -1278,7 +1280,12 @@ gimp_viewable_preview_freeze (GimpViewable *viewable)
private->freeze_count++;
if (private->freeze_count == 1)
g_object_notify (G_OBJECT (viewable), "frozen");
{
if (GIMP_VIEWABLE_GET_CLASS (viewable)->preview_freeze)
GIMP_VIEWABLE_GET_CLASS (viewable)->preview_freeze (viewable);
g_object_notify (G_OBJECT (viewable), "frozen");
}
}
void
@ -1297,7 +1304,11 @@ gimp_viewable_preview_thaw (GimpViewable *viewable)
if (private->freeze_count == 0)
{
gimp_viewable_invalidate_preview (viewable);
g_object_notify (G_OBJECT (viewable), "frozen");
if (GIMP_VIEWABLE_GET_CLASS (viewable)->preview_thaw)
GIMP_VIEWABLE_GET_CLASS (viewable)->preview_thaw (viewable);
}
}

View file

@ -97,6 +97,9 @@ struct _GimpViewableClass
gboolean (* is_name_editable) (GimpViewable *viewable);
void (* preview_freeze) (GimpViewable *viewable);
void (* preview_thaw) (GimpViewable *viewable);
GimpContainer * (* get_children) (GimpViewable *viewable);
void (* set_expanded) (GimpViewable *viewable,