app: add "show all" mode to GimpImage

Add a "show all" mode to GimpImage, which, when active, causes the
image projection's bounding box to be adjusted dynamically to the
combined bounding box of all layers and the canvas.  This mode is
controlled through the new gimp_image_{inc,dec}_show_all()
functions, which should be called by the display; a corresponding
display toggle will be added in the following commits.

Note that from the user's perspective, "show all" is a display
mode, rather than an image mode.  The GimpImage "show all" mode is
therefore merely an implementation detail, and shouldn't have any
effect on displays that don't use "show all" mode, or the PDB.
The ability to use the image with or without taking its "show all"
mode into account will be facilitated by the next commits.
This commit is contained in:
Ell 2019-09-04 14:31:52 +03:00
parent bcf2b937d9
commit 7f629a630c
3 changed files with 139 additions and 4 deletions

View File

@ -49,6 +49,9 @@ struct _GimpImagePrivate
GimpPrecision precision; /* image's precision */
GimpLayerMode new_layer_mode; /* default mode of new layers */
gint show_all; /* render full image content */
GeglRectangle bounding_box; /* image content bounding box */
guchar *colormap; /* colormap (for indexed) */
gint n_colors; /* # of colors (for indexed) */
GimpPalette *palette; /* palette of colormap */
@ -104,6 +107,9 @@ struct _GimpImagePrivate
GimpItemTree *vectors; /* the tree of vectors */
GSList *layer_stack; /* the layers in MRU order */
GQuark layer_offset_x_handler;
GQuark layer_offset_y_handler;
GQuark layer_bounding_box_handler;
GQuark layer_alpha_handler;
GQuark channel_name_changed_handler;
GQuark channel_color_changed_handler;

View File

@ -228,6 +228,12 @@ static void gimp_image_mask_update (GimpDrawable *drawable,
gint width,
gint height,
GimpImage *image);
static void gimp_image_layer_offset_changed (GimpDrawable *drawable,
const GParamSpec *pspec,
GimpImage *image);
static void gimp_image_layer_bounding_box_changed
(GimpDrawable *drawable,
GimpImage *image);
static void gimp_image_layer_alpha_changed (GimpDrawable *drawable,
GimpImage *image);
static void gimp_image_channel_add (GimpContainer *container,
@ -250,6 +256,8 @@ static void gimp_image_active_vectors_notify (GimpItemTree *tree,
const GParamSpec *pspec,
GimpImage *image);
static void gimp_image_update_bounding_box (GimpImage *image);
G_DEFINE_TYPE_WITH_CODE (GimpImage, gimp_image, GIMP_TYPE_VIEWABLE,
G_ADD_PRIVATE (GimpImage)
@ -710,6 +718,12 @@ gimp_image_init (GimpImage *image)
private->precision = GIMP_PRECISION_U8_NON_LINEAR;
private->new_layer_mode = -1;
private->show_all = 0;
private->bounding_box.x = 0;
private->bounding_box.y = 0;
private->bounding_box.width = 0;
private->bounding_box.height = 0;
private->colormap = NULL;
private->n_colors = 0;
private->palette = NULL;
@ -761,6 +775,18 @@ gimp_image_init (GimpImage *image)
G_CALLBACK (gimp_image_invalidate),
image);
private->layer_offset_x_handler =
gimp_container_add_handler (private->layers->container, "notify::offset-x",
G_CALLBACK (gimp_image_layer_offset_changed),
image);
private->layer_offset_y_handler =
gimp_container_add_handler (private->layers->container, "notify::offset-y",
G_CALLBACK (gimp_image_layer_offset_changed),
image);
private->layer_bounding_box_handler =
gimp_container_add_handler (private->layers->container, "bounding-box-changed",
G_CALLBACK (gimp_image_layer_bounding_box_changed),
image);
private->layer_alpha_handler =
gimp_container_add_handler (private->layers->container, "alpha-changed",
G_CALLBACK (gimp_image_layer_alpha_changed),
@ -839,6 +865,8 @@ gimp_image_constructed (GObject *object)
private->quick_mask_color = config->quick_mask_color;
gimp_image_update_bounding_box (image);
if (private->base_type == GIMP_INDEXED)
gimp_image_colormap_init (image);
@ -1003,6 +1031,12 @@ gimp_image_dispose (GObject *object)
gimp_image_invalidate,
image);
gimp_container_remove_handler (private->layers->container,
private->layer_offset_x_handler);
gimp_container_remove_handler (private->layers->container,
private->layer_offset_y_handler);
gimp_container_remove_handler (private->layers->container,
private->layer_bounding_box_handler);
gimp_container_remove_handler (private->layers->container,
private->layer_alpha_handler);
@ -1223,7 +1257,7 @@ gimp_image_size_changed (GimpViewable *viewable)
gimp_image_metadata_update_pixel_size (image);
gimp_projectable_structure_changed (GIMP_PROJECTABLE (image));
gimp_image_update_bounding_box (image);
}
static gchar *
@ -1474,9 +1508,7 @@ gimp_image_get_bounding_box (GimpProjectable *projectable)
{
GimpImage *image = GIMP_IMAGE (projectable);
return *GEGL_RECTANGLE (0, 0,
gimp_image_get_width (image),
gimp_image_get_height (image));
return GIMP_IMAGE_GET_PRIVATE (image)->bounding_box;
}
static GeglNode *
@ -1538,6 +1570,21 @@ gimp_image_mask_update (GimpDrawable *drawable,
GIMP_IMAGE_GET_PRIVATE (image)->flush_accum.mask_changed = TRUE;
}
static void
gimp_image_layer_offset_changed (GimpDrawable *drawable,
const GParamSpec *pspec,
GimpImage *image)
{
gimp_image_update_bounding_box (image);
}
static void
gimp_image_layer_bounding_box_changed (GimpDrawable *drawable,
GimpImage *image)
{
gimp_image_update_bounding_box (image);
}
static void
gimp_image_layer_alpha_changed (GimpDrawable *drawable,
GimpImage *image)
@ -1641,6 +1688,51 @@ gimp_image_active_vectors_notify (GimpItemTree *tree,
g_signal_emit (image, gimp_image_signals[ACTIVE_VECTORS_CHANGED], 0);
}
static void
gimp_image_update_bounding_box (GimpImage *image)
{
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
GeglRectangle bounding_box;
bounding_box.x = 0;
bounding_box.y = 0;
bounding_box.width = gimp_image_get_width (image);
bounding_box.height = gimp_image_get_height (image);
if (private->show_all)
{
GList *iter;
for (iter = gimp_image_get_layer_iter (image);
iter;
iter = g_list_next (iter))
{
GimpLayer *layer = iter->data;
GeglRectangle layer_bounding_box;
gint offset_x;
gint offset_y;
gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
layer_bounding_box = gimp_drawable_get_bounding_box (
GIMP_DRAWABLE (layer));
layer_bounding_box.x += offset_x;
layer_bounding_box.y += offset_y;
gegl_rectangle_bounding_box (&bounding_box,
&bounding_box, &layer_bounding_box);
}
}
if (! gegl_rectangle_equal (&bounding_box, &private->bounding_box))
{
private->bounding_box = bounding_box;
gimp_projectable_bounds_changed (GIMP_PROJECTABLE (image), 0, 0);
}
}
/* public functions */
@ -3461,6 +3553,36 @@ gimp_image_inc_instance_count (GimpImage *image)
GIMP_IMAGE_GET_PRIVATE (image)->instance_count++;
}
void
gimp_image_inc_show_all_count (GimpImage *image)
{
g_return_if_fail (GIMP_IS_IMAGE (image));
GIMP_IMAGE_GET_PRIVATE (image)->show_all++;
if (GIMP_IMAGE_GET_PRIVATE (image)->show_all == 1)
{
g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer);
gimp_image_update_bounding_box (image);
}
}
void
gimp_image_dec_show_all_count (GimpImage *image)
{
g_return_if_fail (GIMP_IS_IMAGE (image));
GIMP_IMAGE_GET_PRIVATE (image)->show_all--;
if (GIMP_IMAGE_GET_PRIVATE (image)->show_all == 0)
{
g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer);
gimp_image_update_bounding_box (image);
}
}
/* parasites */
@ -4381,6 +4503,8 @@ gimp_image_add_layer (GimpImage *image,
if (old_has_alpha != gimp_image_has_alpha (image))
private->flush_accum.alpha_changed = TRUE;
gimp_image_update_bounding_box (image);
return TRUE;
}
@ -4498,6 +4622,8 @@ gimp_image_remove_layer (GimpImage *image,
if (old_has_alpha != gimp_image_has_alpha (image))
private->flush_accum.alpha_changed = TRUE;
gimp_image_update_bounding_box (image);
if (push_undo)
gimp_image_undo_group_end (image);
}

View File

@ -307,6 +307,9 @@ void gimp_image_dec_display_count (GimpImage *image);
gint gimp_image_get_instance_count (GimpImage *image);
void gimp_image_inc_instance_count (GimpImage *image);
void gimp_image_inc_show_all_count (GimpImage *image);
void gimp_image_dec_show_all_count (GimpImage *image);
/* parasites */