From 94cdbacca73c8a91a85567970c7f565884fab9e7 Mon Sep 17 00:00:00 2001 From: Ell Date: Wed, 4 Sep 2019 14:31:52 +0300 Subject: [PATCH] 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. --- app/core/gimpimage-private.h | 6 ++ app/core/gimpimage.c | 134 +++++++++++++++++++++++++++++++++-- app/core/gimpimage.h | 3 + 3 files changed, 139 insertions(+), 4 deletions(-) diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h index 8ffda57b2c..a8fdc2fb61 100644 --- a/app/core/gimpimage-private.h +++ b/app/core/gimpimage-private.h @@ -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 */ @@ -103,6 +106,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; diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 30875ef3f2..f4960197f5 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -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) @@ -721,6 +729,12 @@ gimp_image_init (GimpImage *image) private->precision = GIMP_PRECISION_U8_GAMMA; 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; @@ -774,6 +788,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), @@ -852,6 +878,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); @@ -1016,6 +1044,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); @@ -1237,7 +1271,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 * @@ -1499,9 +1533,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 * @@ -1563,6 +1595,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) @@ -1666,6 +1713,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 */ @@ -3472,6 +3564,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 */ @@ -4392,6 +4514,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; } @@ -4509,6 +4633,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); } diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index 35ffd87a41..caded196a4 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -304,6 +304,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 */