mirror of https://github.com/GNOME/gimp.git
app: new option "Use extents of layer contents" to Align tool.
Instead of using the layer borders, we use the bounding box for the contents. This is similar to first run "Crop to Content" on every selected layer except we don't actually need to crop. Therefore we can work on bigger layer than the actual content while still arranging them based on content bounds. So often the result of alignment/distribution feels wrong because it doesn't correspond to the content we are seeing. With this option, we'll have the option to choose the desired behavior.
This commit is contained in:
parent
9be6a6b711
commit
c8547d0a50
|
@ -30,15 +30,19 @@
|
|||
#include "gimpimage-undo.h"
|
||||
#include "gimpitem.h"
|
||||
#include "gimpguide.h"
|
||||
#include "gimppickable.h"
|
||||
#include "gimppickable-auto-shrink.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
static GList * sort_by_offset (GList *list);
|
||||
static void compute_offsets (GList *list,
|
||||
GimpAlignmentType alignment);
|
||||
GimpAlignmentType alignment,
|
||||
gboolean align_contents);
|
||||
static void compute_offset (GObject *object,
|
||||
GimpAlignmentType alignment);
|
||||
GimpAlignmentType alignment,
|
||||
gboolean align_contents);
|
||||
static gint offset_compare (gconstpointer a,
|
||||
gconstpointer b);
|
||||
|
||||
|
@ -50,6 +54,7 @@ static gint offset_compare (gconstpointer a,
|
|||
* @alignment: The point on each target object to bring into alignment.
|
||||
* @reference: The #GObject to align the targets with, or %NULL.
|
||||
* @reference_alignment: The point on the reference object to align the target item with..
|
||||
* @align_contents: Take into account non-empty contents rather than item borders.
|
||||
* @offset: How much to shift the target from perfect alignment..
|
||||
*
|
||||
* This function shifts the positions of a set of target objects,
|
||||
|
@ -75,6 +80,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
GimpAlignmentType alignment,
|
||||
GObject *reference,
|
||||
GimpAlignmentType reference_alignment,
|
||||
gboolean align_contents,
|
||||
gint offset)
|
||||
{
|
||||
gboolean do_x = FALSE;
|
||||
|
@ -93,7 +99,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
case GIMP_ALIGN_HCENTER:
|
||||
case GIMP_ALIGN_RIGHT:
|
||||
do_x = TRUE;
|
||||
compute_offsets (list, GIMP_ALIGN_TOP);
|
||||
compute_offsets (list, GIMP_ALIGN_TOP, align_contents);
|
||||
break;
|
||||
|
||||
/* order horizontally for horizontal arrangement */
|
||||
|
@ -102,7 +108,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
case GIMP_ARRANGE_RIGHT:
|
||||
case GIMP_ARRANGE_HFILL:
|
||||
do_x = TRUE;
|
||||
compute_offsets (list, alignment);
|
||||
compute_offsets (list, alignment, align_contents);
|
||||
break;
|
||||
|
||||
/* order horizontally for vertical alignment */
|
||||
|
@ -110,7 +116,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
case GIMP_ALIGN_VCENTER:
|
||||
case GIMP_ALIGN_BOTTOM:
|
||||
do_y = TRUE;
|
||||
compute_offsets (list, GIMP_ALIGN_LEFT);
|
||||
compute_offsets (list, GIMP_ALIGN_LEFT, align_contents);
|
||||
break;
|
||||
|
||||
/* order vertically for vertical arrangement */
|
||||
|
@ -119,7 +125,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
case GIMP_ARRANGE_BOTTOM:
|
||||
case GIMP_ARRANGE_VFILL:
|
||||
do_y = TRUE;
|
||||
compute_offsets (list, alignment);
|
||||
compute_offsets (list, alignment, align_contents);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -129,7 +135,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
object_list = sort_by_offset (list);
|
||||
|
||||
/* now get offsets used for aligning */
|
||||
compute_offsets (list, alignment);
|
||||
compute_offsets (list, alignment, align_contents);
|
||||
|
||||
if (reference == NULL)
|
||||
{
|
||||
|
@ -139,7 +145,7 @@ gimp_image_arrange_objects (GimpImage *image,
|
|||
}
|
||||
else
|
||||
{
|
||||
compute_offset (reference, reference_alignment);
|
||||
compute_offset (reference, reference_alignment, FALSE);
|
||||
}
|
||||
|
||||
z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));
|
||||
|
@ -266,17 +272,19 @@ offset_compare (gconstpointer a,
|
|||
*/
|
||||
static void
|
||||
compute_offsets (GList *list,
|
||||
GimpAlignmentType alignment)
|
||||
GimpAlignmentType alignment,
|
||||
gboolean align_contents)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = list; l; l = g_list_next (l))
|
||||
compute_offset (l->data, alignment);
|
||||
compute_offset (l->data, alignment, align_contents);
|
||||
}
|
||||
|
||||
static void
|
||||
compute_offset (GObject *object,
|
||||
GimpAlignmentType alignment)
|
||||
GimpAlignmentType alignment,
|
||||
gboolean align_contents)
|
||||
{
|
||||
gint object_offset_x = 0;
|
||||
gint object_offset_y = 0;
|
||||
|
@ -304,7 +312,28 @@ compute_offset (GObject *object,
|
|||
&object_width,
|
||||
&object_height);
|
||||
|
||||
if (align_contents && GIMP_IS_PICKABLE (object))
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
gint width;
|
||||
gint height;
|
||||
|
||||
if (gimp_pickable_auto_shrink (GIMP_PICKABLE (object),
|
||||
0, 0,
|
||||
gimp_item_get_width (GIMP_ITEM (object)),
|
||||
gimp_item_get_height (GIMP_ITEM (object)),
|
||||
&x, &y, &width, &height) == GIMP_AUTO_SHRINK_SHRINK)
|
||||
{
|
||||
object_offset_x += x;
|
||||
object_offset_y += y;
|
||||
object_width = width;
|
||||
object_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
gimp_item_get_offset (item, &off_x, &off_y);
|
||||
|
||||
object_offset_x += off_x;
|
||||
object_offset_y += off_y;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ void gimp_image_arrange_objects (GimpImage *image,
|
|||
GimpAlignmentType alignment,
|
||||
GObject *reference,
|
||||
GimpAlignmentType reference_alignment,
|
||||
gboolean align_contents,
|
||||
gint offset);
|
||||
|
||||
#endif /* __GIMP_IMAGE_ARRANGE_H__ */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "vectors/gimpvectors.h"
|
||||
|
||||
#include "widgets/gimppropwidgets.h"
|
||||
#include "widgets/gimpwidgets-utils.h"
|
||||
|
||||
#include "gimpalignoptions.h"
|
||||
|
@ -56,12 +57,14 @@ enum
|
|||
PROP_OFFSET_Y,
|
||||
PROP_ALIGN_LAYERS,
|
||||
PROP_ALIGN_VECTORS,
|
||||
PROP_ALIGN_CONTENTS,
|
||||
};
|
||||
|
||||
struct _GimpAlignOptionsPrivate
|
||||
{
|
||||
gboolean align_layers;
|
||||
gboolean align_vectors;
|
||||
gboolean align_contents;
|
||||
|
||||
GList *selected_guides;
|
||||
GObject *reference;
|
||||
|
@ -158,6 +161,12 @@ gimp_align_options_class_init (GimpAlignOptionsClass *klass)
|
|||
_("Selected paths will be aligned or distributed by the tool"),
|
||||
FALSE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_CONTENTS,
|
||||
"align-contents",
|
||||
_("Use extents of layer contents"),
|
||||
_("Instead of aligning or distributing on layer borders, use its content bounding box"),
|
||||
TRUE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -209,6 +218,10 @@ gimp_align_options_set_property (GObject *object,
|
|||
gimp_align_options_update_area (options);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_CONTENTS:
|
||||
options->priv->align_contents = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -243,6 +256,10 @@ gimp_align_options_get_property (GObject *object,
|
|||
g_value_set_boolean (value, options->priv->align_vectors);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_CONTENTS:
|
||||
g_value_set_boolean (value, options->priv->align_contents);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -360,14 +377,24 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
|
|||
gint n = 0;
|
||||
|
||||
/* Selected objects */
|
||||
widget = gimp_prop_check_button_new (config, "align-layers", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
|
||||
frame = gimp_frame_new (_("Objects to align or distribute"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
align_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), align_vbox);
|
||||
gtk_widget_show (align_vbox);
|
||||
|
||||
widget = gimp_prop_check_button_new (config, "align-contents", NULL);
|
||||
widget = gimp_prop_expanding_frame_new (config, "align-layers",
|
||||
NULL, widget, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (align_vbox), widget, FALSE, FALSE, 0);
|
||||
|
||||
widget = gimp_prop_check_button_new (config, "align-vectors", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (align_vbox), widget, FALSE, FALSE, 0);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
widget = gtk_image_new_from_icon_name (GIMP_ICON_CURSOR, GTK_ICON_SIZE_BUTTON);
|
||||
|
@ -387,7 +414,7 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
|
|||
gtk_widget_show (widget);
|
||||
|
||||
widget = gtk_label_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (align_vbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
options->priv->selected_guides_label = widget;
|
||||
|
||||
|
@ -643,6 +670,12 @@ gimp_align_options_get_reference (GimpAlignOptions *options,
|
|||
return reference;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_align_options_align_contents (GimpAlignOptions *options)
|
||||
{
|
||||
return options->priv->align_contents;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_align_options_pick_guide (GimpAlignOptions *options,
|
||||
GimpGuide *guide,
|
||||
|
|
|
@ -67,6 +67,7 @@ void gimp_align_options_pick_reference (GimpAlignOptions *options,
|
|||
GObject *object);
|
||||
GObject * gimp_align_options_get_reference (GimpAlignOptions *options,
|
||||
gboolean blink_if_none);
|
||||
gboolean gimp_align_options_align_contents (GimpAlignOptions *options);
|
||||
|
||||
void gimp_align_options_pick_guide (GimpAlignOptions *options,
|
||||
GimpGuide *guide,
|
||||
|
|
|
@ -179,9 +179,6 @@ gimp_align_tool_constructed (GObject *object)
|
|||
g_signal_connect_object (options, "align-button-clicked",
|
||||
G_CALLBACK (gimp_align_tool_align),
|
||||
align_tool, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (align_tool, "undo",
|
||||
G_CALLBACK (gimp_align_tool_undo),
|
||||
align_tool, G_CONNECT_AFTER);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -765,6 +762,7 @@ gimp_align_tool_align (GimpAlignTool *align_tool,
|
|||
align_type,
|
||||
reference_object,
|
||||
align_type,
|
||||
gimp_align_options_align_contents (options),
|
||||
offset);
|
||||
|
||||
gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
|
||||
|
|
Loading…
Reference in New Issue