Bill Skaggs <weskaggs@primate.ucdavis.edu>

* app/core/core-enums.[ch]: add GIMP_ARRANGE_FOO values
	to GimpAlignmentType, and change CENTER to HCENTER,
	MIDDLE to VCENTER.

	* app/core/gimpimage-arrange.c: extensively rewritten
	to handle arrangement of objects, and to do the
	required sorting of lists by offset.

	* app/tools/gimpaligntool.[ch]: added ability to arrange
	groups of layers etc with constant spacing.  Also try
	to change things so that the tool aligns with the
	object that users expect intuitively.
This commit is contained in:
William Skaggs 2006-06-08 22:15:45 +00:00
parent 16cda2d4cd
commit 9dbc0ee193
8 changed files with 733 additions and 384 deletions

View file

@ -1,3 +1,18 @@
2006-06-08 Bill Skaggs <weskaggs@primate.ucdavis.edu>
* app/core/core-enums.[ch]: add GIMP_ARRANGE_FOO values
to GimpAlignmentType, and change CENTER to HCENTER,
MIDDLE to VCENTER.
* app/core/gimpimage-arrange.c: extensively rewritten
to handle arrangement of objects, and to do the
required sorting of lists by offset.
* app/tools/gimpaligntool.[ch]: added ability to arrange
groups of layers etc with constant spacing. Also try
to change things so that the tool aligns with the
object that users expect intuitively.
2006-06-08 Simon Budig <simon@gimp.org>
* plug-ins/common/sel_gauss.c: fix the EXPAND macro to make

View file

@ -149,23 +149,35 @@ gimp_alignment_type_get_type (void)
{
static const GEnumValue values[] =
{
{ GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", "left" },
{ GIMP_ALIGN_CENTER, "GIMP_ALIGN_CENTER", "center" },
{ GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", "right" },
{ GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", "top" },
{ GIMP_ALIGN_MIDDLE, "GIMP_ALIGN_MIDDLE", "middle" },
{ GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", "bottom" },
{ GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", "align-left" },
{ GIMP_ALIGN_HCENTER, "GIMP_ALIGN_HCENTER", "align-hcenter" },
{ GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", "align-right" },
{ GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", "align-top" },
{ GIMP_ALIGN_VCENTER, "GIMP_ALIGN_VCENTER", "align-vcenter" },
{ GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", "align-bottom" },
{ GIMP_ARRANGE_LEFT, "GIMP_ARRANGE_LEFT", "arrange-left" },
{ GIMP_ARRANGE_HCENTER, "GIMP_ARRANGE_HCENTER", "arrange-hcenter" },
{ GIMP_ARRANGE_RIGHT, "GIMP_ARRANGE_RIGHT", "arrange-right" },
{ GIMP_ARRANGE_TOP, "GIMP_ARRANGE_TOP", "arrange-top" },
{ GIMP_ARRANGE_VCENTER, "GIMP_ARRANGE_VCENTER", "arrange-vcenter" },
{ GIMP_ARRANGE_BOTTOM, "GIMP_ARRANGE_BOTTOM", "arrange-bottom" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
{ GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", NULL },
{ GIMP_ALIGN_CENTER, "GIMP_ALIGN_CENTER", NULL },
{ GIMP_ALIGN_HCENTER, "GIMP_ALIGN_HCENTER", NULL },
{ GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", NULL },
{ GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", NULL },
{ GIMP_ALIGN_MIDDLE, "GIMP_ALIGN_MIDDLE", NULL },
{ GIMP_ALIGN_VCENTER, "GIMP_ALIGN_VCENTER", NULL },
{ GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", NULL },
{ GIMP_ARRANGE_LEFT, "GIMP_ARRANGE_LEFT", NULL },
{ GIMP_ARRANGE_HCENTER, "GIMP_ARRANGE_HCENTER", NULL },
{ GIMP_ARRANGE_RIGHT, "GIMP_ARRANGE_RIGHT", NULL },
{ GIMP_ARRANGE_TOP, "GIMP_ARRANGE_TOP", NULL },
{ GIMP_ARRANGE_VCENTER, "GIMP_ARRANGE_VCENTER", NULL },
{ GIMP_ARRANGE_BOTTOM, "GIMP_ARRANGE_BOTTOM", NULL },
{ 0, NULL, NULL }
};

View file

@ -102,11 +102,17 @@ GType gimp_alignment_type_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_ALIGN_LEFT,
GIMP_ALIGN_CENTER,
GIMP_ALIGN_HCENTER,
GIMP_ALIGN_RIGHT,
GIMP_ALIGN_TOP,
GIMP_ALIGN_MIDDLE,
GIMP_ALIGN_BOTTOM
GIMP_ALIGN_VCENTER,
GIMP_ALIGN_BOTTOM,
GIMP_ARRANGE_LEFT,
GIMP_ARRANGE_HCENTER,
GIMP_ARRANGE_RIGHT,
GIMP_ARRANGE_TOP,
GIMP_ARRANGE_VCENTER,
GIMP_ARRANGE_BOTTOM
} GimpAlignmentType;

View file

@ -31,12 +31,21 @@
#include "gimp-intl.h"
static GList * sort_by_offset (GList *list);
static void compute_offsets (GList *list,
GimpAlignmentType alignment);
static void compute_offset (GObject *object,
GimpAlignmentType alignment);
static gint offset_compare (gconstpointer a,
gconstpointer b);
/**
* gimp_image_arrange_objects:
* @image: The #GimpImage to which the objects belong.
* @list: A #GList of objects to be aligned.
* @alignment: The point on each target object to bring into alignment.
* @reference: The #GObject to align the targets with.
* @reference: The #GObject to align the targets with, or #NULL.
* @reference_alignment: The point on the reference object to align the target item with..
* @offset: How much to shift the target from perfect alignment..
*
@ -46,6 +55,11 @@
* alignment does not make sense (i.e., trying to align a vertical guide vertically),
* nothing happens and no error message is generated.
*
* The objects in the list are sorted into increasing order before
* being arranged, where the order is defined by the type of alignment
* being requested. If the @reference argument is #NULL, then the first
* object in the sorted list is used as reference.
*
* When there are multiple target objects, they are arranged so that the spacing
* between consecutive ones is given by the argument @offset.
*/
@ -59,107 +73,61 @@ gimp_image_arrange_objects (GimpImage *image,
{
gboolean do_x = FALSE;
gboolean do_y = FALSE;
gint reference_offset_x = 0;
gint reference_offset_y = 0;
gint reference_height = 0;
gint reference_width = 0;
gint x0 = 0;
gint y0 = 0;
gint z0 = 0;
GList *object_list;
g_return_if_fail (GIMP_IS_IMAGE (image));
g_return_if_fail (G_IS_OBJECT (reference));
g_return_if_fail (G_IS_OBJECT (reference) || reference == NULL);
/* figure out whether we are aligning horizontally or vertically */
switch (reference_alignment)
/* get offsets used for sorting */
switch (alignment)
{
/* order vertically for horizontal alignment */
case GIMP_ALIGN_LEFT:
case GIMP_ALIGN_CENTER:
case GIMP_ALIGN_HCENTER:
case GIMP_ALIGN_RIGHT:
do_x = TRUE;
compute_offsets (list, GIMP_ALIGN_TOP);
break;
/* order horizontally for horizontal arrangement */
case GIMP_ARRANGE_LEFT:
case GIMP_ARRANGE_HCENTER:
case GIMP_ARRANGE_RIGHT:
do_x = TRUE;
compute_offsets (list, alignment);
break;
/* order horizontally for vertical alignment */
case GIMP_ALIGN_TOP:
case GIMP_ALIGN_MIDDLE:
case GIMP_ALIGN_VCENTER:
case GIMP_ALIGN_BOTTOM:
do_y = TRUE;
compute_offsets (list, GIMP_ALIGN_LEFT);
break;
/* order vertically for vertical arrangement */
case GIMP_ARRANGE_TOP:
case GIMP_ARRANGE_VCENTER:
case GIMP_ARRANGE_BOTTOM:
do_y = TRUE;
compute_offsets (list, alignment);
break;
default:
g_assert_not_reached ();
}
/* get dimensions of the reference object */
if (GIMP_IS_IMAGE (reference))
object_list = sort_by_offset (list);
/* now get offsets used for aligning */
compute_offsets (list, alignment);
if (reference == NULL)
{
reference_offset_x = 0;
reference_offset_y = 0;
reference_width = gimp_image_get_width (image);
reference_height = gimp_image_get_height (image);
}
else if (GIMP_IS_ITEM (reference))
{
GimpItem *item = GIMP_ITEM (reference);
reference_offset_x = item->offset_x;
reference_offset_y = item->offset_y;
reference_height = item->height;
reference_width = item->width;
}
else if (GIMP_IS_GUIDE (reference))
{
GimpGuide *guide = GIMP_GUIDE (reference);
switch (gimp_guide_get_orientation (guide))
{
case GIMP_ORIENTATION_VERTICAL:
if (do_y)
return;
reference_offset_x = gimp_guide_get_position (guide);
reference_width = 0;
break;
case GIMP_ORIENTATION_HORIZONTAL:
if (do_x)
return;
reference_offset_y = gimp_guide_get_position (guide);
reference_height = 0;
break;
default:
break;
}
reference = G_OBJECT (object_list->data);
object_list = g_list_next (object_list);
}
else
{
g_printerr ("Reference object is not an image, item, or guide.\n");
return;
}
compute_offset (reference, reference_alignment);
/* compute alignment pos for reference object */
switch (reference_alignment)
{
case GIMP_ALIGN_LEFT:
x0 = reference_offset_x;
break;
case GIMP_ALIGN_CENTER:
x0 = reference_offset_x + reference_width/2;
break;
case GIMP_ALIGN_RIGHT:
x0 = reference_offset_x + reference_width;
break;
case GIMP_ALIGN_TOP:
y0 = reference_offset_y;
break;
case GIMP_ALIGN_MIDDLE:
y0 = reference_offset_y + reference_height/2;
break;
case GIMP_ALIGN_BOTTOM:
y0 = reference_offset_y + reference_height;
break;
default:
g_assert_not_reached ();
}
z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));
if (list)
if (object_list)
{
GList *l;
gint n;
@ -168,96 +136,21 @@ gimp_image_arrange_objects (GimpImage *image,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_DISPLACE,
_("Arrange Objects"));
for (l = list, n = 1; l; l = g_list_next (l), n++)
for (l = object_list, n = 1; l; l = g_list_next (l), n++)
{
GObject *target = G_OBJECT (l->data);
gint xtranslate = 0;
gint ytranslate = 0;
gint target_offset_x = 0;
gint target_offset_y = 0;
gint target_height = 0;
gint target_width = 0;
gint x1 = 0;
gint y1 = 0;
gint z1;
/* compute dimensions of target object */
if (GIMP_IS_ITEM (target))
{
GimpItem *item = GIMP_ITEM (target);
target_offset_x = item->offset_x;
target_offset_y = item->offset_y;
target_height = item->height;
target_width = item->width;
}
else if (GIMP_IS_GUIDE (target))
{
GimpGuide *guide = GIMP_GUIDE (target);
switch (gimp_guide_get_orientation (guide))
{
case GIMP_ORIENTATION_VERTICAL:
if (do_y)
return;
target_offset_x = gimp_guide_get_position (guide);
target_width = 0;
break;
case GIMP_ORIENTATION_HORIZONTAL:
if (do_x)
return;
target_offset_y = gimp_guide_get_position (guide);
target_height = 0;
break;
default:
break;
}
}
else
{
g_printerr ("Alignment target is not an item or guide.\n");
}
z1 = GPOINTER_TO_INT (g_object_get_data (target,
"align-offset"));
if (do_x)
{
switch (alignment)
{
case GIMP_ALIGN_LEFT:
x1 = target_offset_x;
break;
case GIMP_ALIGN_CENTER:
x1 = target_offset_x + target_width/2;
break;
case GIMP_ALIGN_RIGHT:
x1 = target_offset_x + target_width;
break;
default:
g_assert_not_reached ();
}
xtranslate = x0 - x1 + n * offset;
}
xtranslate = z0 - z1 + n * offset;
if (do_y)
{
switch (alignment)
{
case GIMP_ALIGN_TOP:
y1 = target_offset_y;
break;
case GIMP_ALIGN_MIDDLE:
y1 = target_offset_y + target_height/2;
break;
case GIMP_ALIGN_BOTTOM:
y1 = target_offset_y + target_height;
break;
default:
g_assert_not_reached ();
}
ytranslate = y0 - y1 + n * offset;
}
ytranslate = z0 - z1 + n * offset;
/* now actually align the target object */
if (GIMP_IS_ITEM (target))
@ -272,12 +165,12 @@ gimp_image_arrange_objects (GimpImage *image,
switch (gimp_guide_get_orientation (guide))
{
case GIMP_ORIENTATION_VERTICAL:
gimp_image_move_guide (image, guide, x1 + xtranslate, TRUE);
gimp_image_move_guide (image, guide, z1 + xtranslate, TRUE);
gimp_image_update_guide (image, guide);
break;
case GIMP_ORIENTATION_HORIZONTAL:
gimp_image_move_guide (image, guide, y1 + ytranslate, TRUE);
gimp_image_move_guide (image, guide, z1 + ytranslate, TRUE);
gimp_image_update_guide (image, guide);
break;
@ -288,7 +181,130 @@ gimp_image_arrange_objects (GimpImage *image,
}
gimp_image_undo_group_end (image);
gimp_image_flush (image);
}
g_list_free (object_list);
}
static GList *
sort_by_offset (GList *list)
{
return g_list_sort (g_list_copy (list),
offset_compare);
}
static gint
offset_compare (gconstpointer a,
gconstpointer b)
{
gint offset1 = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a),
"align-offset"));
gint offset2 = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b),
"align-offset"));
return offset1 - offset2;
}
/*
* this function computes the position of the alignment point
* for each object in the list, and attaches it to the
* object as object data.
*/
static void
compute_offsets (GList *list,
GimpAlignmentType alignment)
{
GList *l;
for (l = list; l; l = g_list_next (l))
compute_offset (G_OBJECT (l->data), alignment);
}
static void
compute_offset (GObject *object,
GimpAlignmentType alignment)
{
gint object_offset_x = 0;
gint object_offset_y = 0;
gint object_height = 0;
gint object_width = 0;
gint offset = 0;
if (GIMP_IS_IMAGE (object))
{
GimpImage *image = GIMP_IMAGE (object);
object_offset_x = 0;
object_offset_y = 0;
object_height = gimp_image_get_height (image);
object_width = gimp_image_get_width (image);
}
else if (GIMP_IS_ITEM (object))
{
GimpItem *item = GIMP_ITEM (object);
object_offset_x = item->offset_x;
object_offset_y = item->offset_y;
object_height = item->height;
object_width = item->width;
}
else if (GIMP_IS_GUIDE (object))
{
GimpGuide *guide = GIMP_GUIDE (object);
switch (gimp_guide_get_orientation (guide))
{
case GIMP_ORIENTATION_VERTICAL:
object_offset_x = gimp_guide_get_position (guide);
object_width = 0;
break;
case GIMP_ORIENTATION_HORIZONTAL:
object_offset_y = gimp_guide_get_position (guide);
object_height = 0;
break;
default:
break;
}
}
else
{
g_printerr ("Alignment object is not an image, item or guide.\n");
}
switch (alignment)
{
case GIMP_ALIGN_LEFT:
case GIMP_ARRANGE_LEFT:
offset = object_offset_x;
break;
case GIMP_ALIGN_HCENTER:
case GIMP_ARRANGE_HCENTER:
offset = object_offset_x + object_width/2;
break;
case GIMP_ALIGN_RIGHT:
case GIMP_ARRANGE_RIGHT:
offset = object_offset_x + object_width;
break;
case GIMP_ALIGN_TOP:
case GIMP_ARRANGE_TOP:
offset = object_offset_y;
break;
case GIMP_ALIGN_VCENTER:
case GIMP_ARRANGE_VCENTER:
offset = object_offset_y + object_height/2;
break;
case GIMP_ALIGN_BOTTOM:
case GIMP_ARRANGE_BOTTOM:
offset = object_offset_y + object_height;
break;
default:
g_assert_not_reached ();
}
g_object_set_data (object, "align-offset",
GINT_TO_POINTER (offset));
}

View file

@ -86,11 +86,7 @@ static void gimp_align_tool_draw (GimpDrawTool *draw_tool);
static GtkWidget *button_with_stock (GimpAlignmentType action,
GimpAlignTool *align_tool);
static GtkWidget *gimp_align_tool_controls (GimpAlignTool *align_tool);
static void set_action (GtkWidget *widget,
gpointer data);
static void do_horizontal_alignment (GtkWidget *widget,
gpointer data);
static void do_vertical_alignment (GtkWidget *widget,
static void do_alignment (GtkWidget *widget,
gpointer data);
static void clear_selected_object (GObject *object,
GimpAlignTool *align_tool);
@ -119,7 +115,7 @@ gimp_align_tool_register (GimpToolRegisterCallback callback,
gimp_align_options_gui,
0,
"gimp-align-tool",
_("Align"),
_("Alignment Tool"),
_("Align or arrange layers and other items"),
N_("_Align"), "Q",
NULL, GIMP_HELP_TOOL_MOVE,
@ -156,8 +152,7 @@ gimp_align_tool_init (GimpAlignTool *align_tool)
align_tool->selected_objects = NULL;
align_tool->horz_align_type = GIMP_ALIGN_LEFT;
align_tool->vert_align_type = GIMP_ALIGN_TOP;
align_tool->align_type = GIMP_ALIGN_LEFT;
align_tool->horz_offset = 0;
align_tool->vert_offset = 0;
@ -285,6 +280,13 @@ gimp_align_tool_button_press (GimpTool *tool,
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
/*
* some rather complex logic here. If the user clicks without modifiers,
* then we start a new list, and use the first object in it as reference.
* If the user clicks using Shift, or draws a rubber-band box, then
* we add objects to the list, but do not specify which one should
* be used as reference.
*/
static void
gimp_align_tool_button_release (GimpTool *tool,
GimpCoords *coords,
@ -300,8 +302,20 @@ gimp_align_tool_button_release (GimpTool *tool,
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
if (! (state & GDK_SHIFT_MASK))
clear_all_selected_objects (align_tool);
if (state & GDK_BUTTON3_MASK) /* cancel this action */
{
align_tool->x1 = align_tool->x0;
align_tool->y1 = align_tool->y0;
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
return;
}
if (! (state & GDK_SHIFT_MASK)) /* start a new list */
{
clear_all_selected_objects (align_tool);
align_tool->set_reference = FALSE;
}
#define EPSILON 3
@ -350,6 +364,12 @@ gimp_align_tool_button_release (GimpTool *tool,
g_signal_connect (object, "removed",
G_CALLBACK (clear_selected_object),
(gpointer) align_tool);
/* if an object has been selected using unmodified click,
* it should be used as the reference
*/
if (! (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)))
align_tool->set_reference = TRUE;
}
}
}
@ -552,6 +572,7 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
GtkWidget *table;
GtkWidget *label;
GtkWidget *button;
GtkWidget *spinbutton;
gint row, col, n;
hbox = gtk_hbox_new (FALSE, 0);
@ -574,13 +595,13 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_table_attach_defaults (GTK_TABLE (table), hbox2, 0, 8, row, row + 1);
gtk_widget_show (hbox2);
label = gtk_label_new (_("Horizontal"));
label = gtk_label_new (_("Align"));
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
gtk_widget_show (label);
row++;
/* second row */
/* horizontal align row */
col = 1;
n = 0;
@ -592,7 +613,7 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
++col;
++col;
button = button_with_stock (GIMP_ALIGN_CENTER, align_tool);
button = button_with_stock (GIMP_ALIGN_HCENTER, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Align center of target"), NULL);
align_tool->button[n++] = button;
@ -608,34 +629,7 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
row++;
/* next row */
/* label = gtk_label_new (_("Offset:")); */
/* gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 3, row, row + 1); */
/* gtk_widget_show (label); */
/* spinbutton = gimp_spin_button_new (&align_tool->horz_offset_adjustment, */
/* 0, */
/* -100000., */
/* 100000., */
/* 1., 20., 20., 1., 0); */
/* gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 3, 7, row, row + 1); */
/* g_signal_connect (align_tool->horz_offset_adjustment, "value-changed", */
/* G_CALLBACK (gimp_double_adjustment_update), */
/* &align_tool->horz_offset); */
/* gtk_widget_show (spinbutton); */
/* row++; */
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_table_attach_defaults (GTK_TABLE (table), hbox2, 0, 8, row, row + 1);
gtk_widget_show (hbox2);
label = gtk_label_new (_("Vertical"));
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
gtk_widget_show (label);
row++;
/* second row */
/* vertical align row */
col = 1;
@ -646,7 +640,7 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
++col;
++col;
button = button_with_stock (GIMP_ALIGN_MIDDLE, align_tool);
button = button_with_stock (GIMP_ALIGN_VCENTER, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Align middle of target"), NULL);
align_tool->button[n++] = button;
@ -662,21 +656,85 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
row++;
/* next row */
/* label = gtk_label_new (_("Offset:")); */
/* gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 3, row, row + 1); */
/* gtk_widget_show (label); */
/* label row */
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_table_attach_defaults (GTK_TABLE (table), hbox2, 0, 8, row, row + 1);
gtk_widget_show (hbox2);
label = gtk_label_new (_("Arrange"));
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
gtk_widget_show (label);
/* spinbutton = gimp_spin_button_new (&align_tool->vert_offset_adjustment, */
/* 0, */
/* -100000., */
/* 100000., */
/* 1., 20., 20., 1., 0); */
/* gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 3, 7, row, row + 1); */
/* g_signal_connect (align_tool->vert_offset_adjustment, "value-changed", */
/* G_CALLBACK (gimp_double_adjustment_update), */
/* &align_tool->vert_offset); */
/* gtk_widget_show (spinbutton); */
row++;
/* horizontal arrange row */
col = 1;
button = button_with_stock (GIMP_ARRANGE_LEFT, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange left edges of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
button = button_with_stock (GIMP_ARRANGE_HCENTER, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange horiz centers of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
button = button_with_stock (GIMP_ARRANGE_RIGHT, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange right edges of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
row++;
/* vertical arrange row */
col = 1;
button = button_with_stock (GIMP_ARRANGE_TOP, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange top edges of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
button = button_with_stock (GIMP_ARRANGE_VCENTER, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange vertical centers of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
button = button_with_stock (GIMP_ARRANGE_BOTTOM, align_tool);
gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 2, row, row + 1);
gimp_help_set_help_data (button, _("Arrange bottoms of targets"), NULL);
align_tool->button[n++] = button;
++col;
++col;
row++;
/* offset row */
label = gtk_label_new (_("Offset:"));
gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 3, row, row + 1);
gtk_widget_show (label);
spinbutton = gimp_spin_button_new (&align_tool->horz_offset_adjustment,
0,
-100000.,
100000.,
1., 20., 20., 1., 0);
gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 3, 7, row, row + 1);
g_signal_connect (align_tool->horz_offset_adjustment, "value-changed",
G_CALLBACK (gimp_double_adjustment_update),
&align_tool->horz_offset);
gtk_widget_show (spinbutton);
gtk_widget_show (hbox);
return hbox;
@ -684,33 +742,73 @@ gimp_align_tool_controls (GimpAlignTool *align_tool)
static void
do_horizontal_alignment (GtkWidget *widget,
gpointer data)
do_alignment (GtkWidget *widget,
gpointer data)
{
GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (data);
GimpImage *image;
GObject *reference_object;
GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (data);
GimpAlignmentType action;
GimpImage *image;
GObject *reference_object;
GList *list;
gint offset;
image = GIMP_TOOL (align_tool)->display->image;
action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "action"));
offset = align_tool->horz_offset;
switch (action)
{
case GIMP_ALIGN_LEFT:
case GIMP_ALIGN_HCENTER:
case GIMP_ALIGN_RIGHT:
case GIMP_ALIGN_TOP:
case GIMP_ALIGN_VCENTER:
case GIMP_ALIGN_BOTTOM:
offset = 0;
break;
case GIMP_ARRANGE_LEFT:
case GIMP_ARRANGE_HCENTER:
case GIMP_ARRANGE_RIGHT:
case GIMP_ARRANGE_TOP:
case GIMP_ARRANGE_VCENTER:
case GIMP_ARRANGE_BOTTOM:
offset = align_tool->horz_offset;
break;
}
/* if nothing is selected, just return
* if only one object is selected, use the image as reference
* if multiple objects are selected, use the first one as reference
* if multiple objects are selected, use the first one as reference if
* "set_reference" is TRUE, otherwise use NULL.
*/
if (g_list_length (align_tool->selected_objects) == 0)
return;
else if (g_list_length (align_tool->selected_objects) == 1)
reference_object = G_OBJECT (image);
{
reference_object = G_OBJECT (image);
list = align_tool->selected_objects;
}
else
reference_object = G_OBJECT (align_tool->selected_objects->data);
{
if (align_tool->set_reference)
{
reference_object = G_OBJECT (align_tool->selected_objects->data);
list = g_list_next (align_tool->selected_objects);
}
else
{
reference_object = NULL;
list = align_tool->selected_objects;
}
}
gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
gimp_image_arrange_objects (image, align_tool->selected_objects,
align_tool->horz_align_type,
gimp_image_arrange_objects (image, list,
action,
reference_object,
align_tool->horz_align_type,
align_tool->horz_offset);
action,
offset);
gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
@ -718,40 +816,6 @@ do_horizontal_alignment (GtkWidget *widget,
}
static void
do_vertical_alignment (GtkWidget *widget,
gpointer data)
{
GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (data);
GimpImage *image;
GObject *reference_object;
image = GIMP_TOOL (align_tool)->display->image;
/* if nothing is selected, just return
* if only one object is selected, use the image as reference
* if multiple objects are selected, use the first one as reference
*/
if (g_list_length (align_tool->selected_objects) == 0)
return;
else if (g_list_length (align_tool->selected_objects) == 1)
reference_object = G_OBJECT (image);
else
reference_object = G_OBJECT (align_tool->selected_objects->data);
gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
gimp_image_arrange_objects (image, align_tool->selected_objects,
align_tool->vert_align_type,
reference_object,
align_tool->vert_align_type,
align_tool->vert_offset);
gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
gimp_image_flush (image);
}
static GtkWidget *
@ -766,7 +830,7 @@ button_with_stock (GimpAlignmentType action,
case GIMP_ALIGN_LEFT:
stock_id = GIMP_STOCK_GRAVITY_WEST;
break;
case GIMP_ALIGN_CENTER:
case GIMP_ALIGN_HCENTER:
stock_id = GIMP_STOCK_HCENTER;
break;
case GIMP_ALIGN_RIGHT:
@ -775,12 +839,30 @@ button_with_stock (GimpAlignmentType action,
case GIMP_ALIGN_TOP:
stock_id = GIMP_STOCK_GRAVITY_NORTH;
break;
case GIMP_ALIGN_MIDDLE:
case GIMP_ALIGN_VCENTER:
stock_id = GIMP_STOCK_VCENTER;
break;
case GIMP_ALIGN_BOTTOM:
stock_id = GIMP_STOCK_GRAVITY_SOUTH;
break;
case GIMP_ARRANGE_LEFT:
stock_id = GIMP_STOCK_GRAVITY_WEST;
break;
case GIMP_ARRANGE_HCENTER:
stock_id = GIMP_STOCK_HCENTER;
break;
case GIMP_ARRANGE_RIGHT:
stock_id = GIMP_STOCK_GRAVITY_EAST;
break;
case GIMP_ARRANGE_TOP:
stock_id = GIMP_STOCK_GRAVITY_NORTH;
break;
case GIMP_ARRANGE_VCENTER:
stock_id = GIMP_STOCK_VCENTER;
break;
case GIMP_ARRANGE_BOTTOM:
stock_id = GIMP_STOCK_GRAVITY_SOUTH;
break;
default:
stock_id = "?";
break;
@ -791,7 +873,7 @@ button_with_stock (GimpAlignmentType action,
g_object_set_data (G_OBJECT (button), "action", GINT_TO_POINTER (action));
g_signal_connect (button, "clicked",
G_CALLBACK (set_action),
G_CALLBACK (do_alignment),
align_tool);
gtk_widget_set_sensitive (button, FALSE);
@ -800,34 +882,6 @@ button_with_stock (GimpAlignmentType action,
return button;
}
static void
set_action (GtkWidget *widget,
gpointer data)
{
GimpAlignTool *align_tool = data;
GimpAlignmentType action;
action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "action"));
switch (action)
{
case GIMP_ALIGN_LEFT:
case GIMP_ALIGN_CENTER:
case GIMP_ALIGN_RIGHT:
align_tool->horz_align_type = action;
do_horizontal_alignment (widget, data);
break;
case GIMP_ALIGN_TOP:
case GIMP_ALIGN_MIDDLE:
case GIMP_ALIGN_BOTTOM:
align_tool->vert_align_type = action;
do_vertical_alignment (widget, data);
break;
default:
break;
}
}
static void
clear_selected_object (GObject *object,
GimpAlignTool *align_tool)

View file

@ -30,7 +30,7 @@
#define GIMP_IS_ALIGN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_ALIGN_TOOL))
#define GIMP_ALIGN_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ALIGN_TOOL, GimpAlignToolClass))
#define ALIGN_TOOL_NUM_BUTTONS 6
#define ALIGN_TOOL_NUM_BUTTONS 12
typedef struct _GimpAlignTool GimpAlignTool;
typedef struct _GimpAlignToolClass GimpAlignToolClass;
@ -44,8 +44,7 @@ struct _GimpAlignTool
GList *selected_objects;
GimpAlignmentType horz_align_type;
GimpAlignmentType vert_align_type;
GimpAlignmentType align_type;
gdouble horz_offset;
gdouble vert_offset;
@ -54,6 +53,8 @@ struct _GimpAlignTool
GtkObject *vert_offset_adjustment;
gint x0, y0, x1, y1; /* rubber-band rectangle */
gboolean set_reference;
};
struct _GimpAlignToolClass

View file

@ -149,6 +149,11 @@ static gint find_unused_ia_color (const guchar *pixels,
static gboolean load_defaults (void);
static void save_defaults (void);
static void load_gui_defaults (PngSaveGui *pg);
static guchar *fill_bit2byte (void);
static void byte2bit (const guchar *byteline,
gint width,
guchar *bitline,
gboolean invert);
/*
* Globals...
@ -672,8 +677,16 @@ load_image (const gchar *filename,
GimpPixelRgn pixel_rgn; /* Pixel region for layer */
png_structp pp; /* PNG read pointer */
png_infop info; /* PNG info pointers */
guchar **pixels, /* Pixel rows */
*pixel; /* Pixel data */
gboolean is_bw = FALSE;
guchar **pixels = NULL; /* Pixel rows */
guchar *pixel = NULL; /* Pixel data */
/* b&w needs this for bits*/
guchar *bits = NULL; /* rows of bits */
guchar **bit_line = NULL; /* pointers to BOR */
gint bit_line_len = 0; /* number of bytes to keep the bits */
guchar *bit2byte = NULL;
guchar alpha[256], /* Index -> Alpha */
*alpha_ptr; /* Temporary pointer */
@ -685,6 +698,20 @@ load_image (const gchar *filename,
if (setjmp (pp->jmpbuf))
{
/* this is a (maybe useless) attempt to recover cleanly from errors. */
#if PNG_LIBPNG_VER > 88
png_destroy_read_struct(&pp, &info, (png_infopp) NULL);
#endif
g_free (pixel);
g_free (pixels);
if (is_bw)
{
g_free (bit2byte);
g_free (bits);
g_free (bit_line);
};
g_message (_("Error while reading '%s'. File corrupted?"),
gimp_filename_to_utf8 (filename));
return image;
@ -744,8 +771,19 @@ load_image (const gchar *filename,
if (info->color_type != PNG_COLOR_TYPE_PALETTE &&
(info->valid & PNG_INFO_tRNS))
{
png_set_expand (pp);
}
if (info->bit_depth == 1)
{
/* b&w, load this as an indexed image */
is_bw = TRUE;
bits = NULL;
bit_line = NULL;
bit2byte = NULL;
}
else
{
png_set_expand (pp);
}
}
/*
* Turn on interlace handling... libpng returns just 1 (ie single pass)
@ -781,6 +819,7 @@ load_image (const gchar *filename,
png_read_update_info (pp, info);
/* mmc: this means, that png_set_expand & png_set_packing may change info->color_type? */
switch (info->color_type)
{
case PNG_COLOR_TYPE_RGB: /* RGB */
@ -796,9 +835,22 @@ load_image (const gchar *filename,
break;
case PNG_COLOR_TYPE_GRAY: /* Grayscale */
bpp = 1;
image_type = GIMP_GRAY;
layer_type = GIMP_GRAY_IMAGE;
/* g_print("opening a grayscale png. bit depth: %d\n", info->bit_depth); */
if (is_bw)
{
/* Have to construct the white&black palette, see below. */
image_type = GIMP_INDEXED;
layer_type = GIMP_INDEXED_IMAGE;
bpp = 1; /* This is fake, we disable the expansion (by libpng)!
* But, after our conversion the rows will indeed be 1 byte-per-pixel. */
bit2byte = fill_bit2byte ();
}
else
{
bpp = 1;
image_type = GIMP_GRAY;
layer_type = GIMP_GRAY_IMAGE;
}
break;
case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */
@ -938,6 +990,12 @@ load_image (const gchar *filename,
info->num_palette);
}
}
else if (is_bw)
{
/* we are converting grayscale image to a b&w palette: this is the palette then: */
guchar bw_map[] = { 0, 0, 0, 255, 255, 255 };
gimp_image_set_colormap (image, bw_map,2);
}
/*
* Get the drawable and set the pixel region for our load...
@ -956,6 +1014,21 @@ load_image (const gchar *filename,
pixel = g_new (guchar, tile_height * info->width * bpp);
pixels = g_new (guchar *, tile_height);
if (is_bw)
{
bit_line_len = ((info->width +7 ) / 8);
/* >> 3 */
/* bits_per_byte! */
bits = g_new (guchar, tile_height * bit_line_len);
bit_line = g_new (guchar *, tile_height);
for (i = 0; i < tile_height; i++)
bit_line[i] = bits + bit_line_len * i;
/* g_print("bit_line_len =%d\n", bit_line_len); */
}
for (i = 0; i < tile_height; i++)
pixels[i] = pixel + info->width * info->channels * i;
@ -977,7 +1050,49 @@ load_image (const gchar *filename,
gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
png_read_rows (pp, pixels, NULL, num);
/* mmc: interlacing not handled now? */
/* if we used the libpng builtin expansion, we would have to
* convert values 255 (black) into 1 (palette index)
* I think this approach is faster:
*/
if (is_bw)
{
int i, j;
guchar *source, *dest;
png_read_rows (pp, bit_line, NULL, num);
/* FIXME: we must not memcpy after the boundary!
* So, if the line is not a multiple of 8 (bits per byte),
* we should do it out of the cycle!*/
#define BITS_PER_BYTE 8
for (j=0; j< tile_height; j++)
{
dest = pixels[j];
source = bit_line[j];
for (i=0; i < (info->width / BITS_PER_BYTE) ; i++)
{
memcpy (dest,
bit2byte + *source * BITS_PER_BYTE,
BITS_PER_BYTE);
dest += BITS_PER_BYTE;
source++;
}
if (info->width / BITS_PER_BYTE < bit_line_len)
{
memcpy (dest,
bit2byte + *source * BITS_PER_BYTE,
info->width % BITS_PER_BYTE);
}
}
}
else
{
png_read_rows (pp, pixels, NULL, num);
}
gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
@ -1119,7 +1234,23 @@ load_image (const gchar *filename,
}
/*
static guchar *
fill_bit2byte (void)
{
guchar *bit2byte = g_new (guchar, 256 * 8);
guchar *dest;
gint i, j;
dest = bit2byte;
for (j = 0; j < 256; j++)
for (i = 7; i >= 0; i--)
*(dest++) = ((j & (1 << i)) != 0);
return bit2byte;
}
/*
* 'save_image ()' - Save the specified image to a PNG file.
*/
@ -1138,16 +1269,16 @@ save_image (const gchar *filename,
begin, /* Beginning tile row */
end, /* Ending tile row */
num; /* Number of rows to load */
FILE *fp; /* File pointer */
FILE *fp = NULL; /* File pointer */
GimpDrawable *drawable; /* Drawable for layer */
GimpPixelRgn pixel_rgn; /* Pixel region for layer */
png_structp pp; /* PNG read pointer */
png_infop info; /* PNG info pointer */
gint num_colors; /* Number of colors in colormap */
gint offx, offy; /* Drawable offsets from origin */
guchar **pixels, /* Pixel rows */
*fixed, /* Fixed-up pixel data */
*pixel; /* Pixel data */
guchar **pixels = NULL; /* Pixel rows */
guchar *fixed = NULL; /* Fixed-up pixel data */
guchar *pixel = NULL; /* Pixel data */
gdouble xres, yres; /* GIMP resolution (dpi) */
png_color_16 background; /* Background color */
png_time mod_time; /* Modification time (ie NOW) */
@ -1157,7 +1288,10 @@ save_image (const gchar *filename,
guchar remap[256]; /* Re-mapping for the palette */
png_textp text = NULL;
/* indexed b/w -> save as 1bit grayscale to save space! */
gboolean is_bw = FALSE, invert = FALSE;
png_textp text = NULL;
if (pngvals.comment)
{
@ -1203,7 +1337,18 @@ save_image (const gchar *filename,
if (setjmp (pp->jmpbuf))
{
g_message (_("Error while saving '%s'. Could not save image."),
/* mmc: fixme: neo says, on failure a saving process exits, so this might be done implicitely
* I do it explicitely for case someone reuses the code. */
#if PNG_LIBPNG_VER > 88
png_destroy_write_struct(&pp, &info);
#endif
if (fp)
fclose (fp);
g_free (pixels);
g_free (pixel);
g_message (_("Error while saving '%s'. Could not save image."),
gimp_filename_to_utf8 (filename));
return FALSE;
}
@ -1279,12 +1424,42 @@ save_image (const gchar *filename,
break;
case GIMP_INDEXED_IMAGE:
bpp = 1;
info->color_type = PNG_COLOR_TYPE_PALETTE;
info->valid |= PNG_INFO_PLTE;
info->palette =
(png_colorp) gimp_image_get_colormap (image_ID, &num_colors);
info->num_palette = num_colors;
{
/* copied from tiff.c ! */
guchar *cmap = gimp_image_get_colormap (image_ID, &num_colors);
if (num_colors == 2)
{
const guchar bw_map[] = { 0, 0, 0, 255, 255, 255 };
const guchar wb_map[] = { 255, 255, 255, 0, 0, 0 };
is_bw = (memcmp (cmap, bw_map, 6) == 0);
if (!is_bw)
{
is_bw = (memcmp (cmap, wb_map, 6) == 0);
if (is_bw)
invert = TRUE;
}
}
if (is_bw)
{
bpp = 1;
info->color_type = PNG_COLOR_TYPE_GRAY;
info->bit_depth = 1;
g_free (cmap);
}
else
{
bpp = 1;
info->color_type = PNG_COLOR_TYPE_PALETTE;
info->valid |= PNG_INFO_PLTE;
info->palette = (png_colorp) cmap;
info->num_palette = num_colors;
}
}
break;
case GIMP_INDEXEDA_IMAGE:
@ -1506,6 +1681,17 @@ save_image (const gchar *filename,
}
}
}
else if (is_bw)
{
/* indexed b/w -> 1-grayscale: at this stage, */
/* we have to convert the 0/1 indexes(bytes) into 0/1 bits */
/* pixel is the array of several lines of the image: indexes
* pixels is an array of pointers at the beginnings of the lines */
for (i = 0; i < num; ++i)
{
byte2bit (pixels[i], info->width, pixels[i], invert);
}
}
png_write_rows (pp, pixels, num);
@ -1539,6 +1725,53 @@ save_image (const gchar *filename,
return TRUE;
}
/* Convert n bytes of 0/1 to a line of bits */
static void
byte2bit (const guchar *byteline,
gint width,
guchar *bitline,
gboolean invert)
{
guchar bitval;
guchar rest[8];
while (width >= 8)
{
bitval = 0;
if (*(byteline++)) bitval |= 0x80;
if (*(byteline++)) bitval |= 0x40;
if (*(byteline++)) bitval |= 0x20;
if (*(byteline++)) bitval |= 0x10;
if (*(byteline++)) bitval |= 0x08;
if (*(byteline++)) bitval |= 0x04;
if (*(byteline++)) bitval |= 0x02;
if (*(byteline++)) bitval |= 0x01;
*(bitline++) = invert ? ~bitval : bitval;
width -= 8;
}
if (width > 0)
{
memset (rest, 0, 8);
memcpy (rest, byteline, width);
bitval = 0;
byteline = rest;
if (*(byteline++)) bitval |= 0x80;
if (*(byteline++)) bitval |= 0x40;
if (*(byteline++)) bitval |= 0x20;
if (*(byteline++)) bitval |= 0x10;
if (*(byteline++)) bitval |= 0x08;
if (*(byteline++)) bitval |= 0x04;
if (*(byteline++)) bitval |= 0x02;
*bitline = invert ? ~bitval & (0xff << (8 - width)) : bitval;
}
}
static gboolean
ia_has_transparent_pixels (const guchar *pixels,
gint numpixels)

View file

@ -11,11 +11,6 @@
#
# - Modified by jacob berkman <jacob@ximian.com> to install
# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
#
# - Modified by Rodney Dawes <dobey@novell.com> for use with intltool
#
# We have the following line for use by intltoolize:
# INTLTOOL_MAKEFILE
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
PACKAGE = @PACKAGE@
@ -32,21 +27,20 @@ VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
datadir = @datadir@
datarootdir = @datarootdir@
libdir = @libdir@
localedir = $(libdir)/locale
gnulocaledir = $(datadir)/locale
gettextsrcdir = $(datadir)/glib-2.0/gettext/po
subdir = po
install_sh = @install_sh@
# Automake >= 1.8 provides @mkdir_p@.
# Until it can be supposed, use the safe fallback:
mkdir_p = $(install_sh) -d
mkdir_p = @mkdir_p@
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
CC = @CC@
GENCAT = @GENCAT@
GMSGFMT = @GMSGFMT@
MSGFMT = @MSGFMT@
XGETTEXT = @XGETTEXT@
@ -67,13 +61,13 @@ SOURCES =
POFILES = @POFILES@
GMOFILES = @GMOFILES@
DISTFILES = ChangeLog Makefile.in.in POTFILES.in \
$(POFILES) $(SOURCES)
EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS
$(POFILES) $(GMOFILES) $(SOURCES)
POTFILES = \
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
INSTOBJEXT = @INSTOBJEXT@
.SUFFIXES:
.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
@ -83,7 +77,7 @@ CATOBJEXT = @CATOBJEXT@
.po.pox:
$(MAKE) $(GETTEXT_PACKAGE).pot
$(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox
$(MSGMERGE) $< $(top_builddir)/po/$(GETTEXT_PACKAGE).pot -o $*pox
.po.mo:
$(MSGFMT) -o $@ $<
@ -94,7 +88,7 @@ CATOBJEXT = @CATOBJEXT@
.po.cat:
sed -f ../intl/po2msg.sed < $< > $*.msg \
&& rm -f $@ && gencat $@ $*.msg
&& rm -f $@ && $(GENCAT) $@ $*.msg
all: all-@USE_NLS@
@ -110,7 +104,11 @@ install-exec:
install-data: install-data-@USE_NLS@
install-data-no: all
install-data-yes: all
$(mkdir_p) $(DESTDIR)$(datadir)
if test -n "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $(DESTDIR)$(datadir); \
else \
$(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \
fi
@catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
@ -120,31 +118,39 @@ install-data-yes: all
esac; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \
$(mkdir_p) $$dir; \
if test -r $$cat; then \
$(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE).mo; \
echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE).mo"; \
if test -n "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $$dir; \
else \
$(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE).mo; \
$(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \
fi; \
if test -r $$cat; then \
$(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
else \
$(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(GETTEXT_PACKAGE).mo"; \
"$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
fi; \
if test -r $$cat.m; then \
$(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE).mo.m; \
echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \
$(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
else \
if test -r $(srcdir)/$$cat.m ; then \
$(INSTALL_DATA) $(srcdir)/$$cat.m \
$$dir/$(GETTEXT_PACKAGE).mo.m; \
$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(GETTEXT_PACKAGE).mo.m"; \
"$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
else \
true; \
fi; \
fi; \
done
if test "$(PACKAGE)" = "glib"; then \
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
if test -n "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \
else \
$(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \
fi; \
$(INSTALL_DATA) $(srcdir)/Makefile.in.in \
$(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
else \
@ -159,16 +165,16 @@ uninstall:
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
done
if test "$(PACKAGE)" = "glib"; then \
rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
fi
check: all $(GETTEXT_PACKAGE).pot
check: all
dvi info tags TAGS ID:
@ -180,25 +186,19 @@ mostlyclean:
clean: mostlyclean
distclean: clean
rm -f Makefile Makefile.in POTFILES stamp-it
rm -f *.mo *.msg *.cat *.cat.m *.gmo
rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
maintainer-clean: distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f Makefile.in.in
rm -f $(GMOFILES)
distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir)
dist distdir: $(DISTFILES)
dist distdir: $(DISTFILES) $(GETTEXT_PACKAGE).pot
dists="$(DISTFILES)"; \
extra_dists="$(EXTRA_DISTFILES)"; \
for file in $$extra_dists; do \
test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \
done; \
for file in $$dists; do \
test -f $$file || file="$(srcdir)/$$file"; \
ln $$file $(distdir) 2> /dev/null \
|| cp -p $$file $(distdir); \
ln $(srcdir)/$$file $(distdir) 2> /dev/null \
|| cp -p $(srcdir)/$$file $(distdir); \
done
update-po: Makefile
@ -228,15 +228,27 @@ update-po: Makefile
fi; \
done
Makefile POTFILES: stamp-it
@if test ! -f $@; then \
rm -f stamp-it; \
$(MAKE) stamp-it; \
fi
# POTFILES is created from POTFILES.in by stripping comments, empty lines
# and Intltool tags (enclosed in square brackets), and appending a full
# relative path to them
POTFILES: POTFILES.in
( if test 'x$(srcdir)' != 'x.'; then \
posrcprefix='$(top_srcdir)/'; \
else \
posrcprefix="../"; \
fi; \
rm -f $@-t $@ \
&& (sed -e '/^#/d' \
-e "s/^\[.*\] +//" \
-e '/^[ ]*$$/d' \
-e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
| sed -e '$$s/\\$$//') > $@-t \
&& chmod a-w $@-t \
&& mv $@-t $@ )
stamp-it: Makefile.in.in ../config.status POTFILES.in
Makefile: Makefile.in.in ../config.status POTFILES
cd .. \
&& CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \
&& CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
$(SHELL) ./config.status
# Tell versions [3.59,3.63) of GNU make not to export all variables.