1998-06-30 23:31:32 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
1998-09-24 09:19:57 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
1999-02-21 07:20:54 +08:00
|
|
|
#include <string.h>
|
1998-06-30 23:31:32 +08:00
|
|
|
#include "gimpdrawableP.h"
|
|
|
|
#include "gimpsignal.h"
|
|
|
|
#include "gimage.h"
|
|
|
|
#include "gimage_mask.h"
|
1998-12-22 14:03:53 +08:00
|
|
|
#include "gimpparasite.h"
|
1998-10-30 18:21:33 +08:00
|
|
|
#include "parasitelist.h"
|
gave parasite undo a MISC_UNDO class for now so it compiles
* app/gimpdrawable.c: gave parasite undo a MISC_UNDO class for now
so it compiles
* app/tools_cmds.c: fix crop invoker to give correct args to
crop_image
* app/color_cmds.c: s/GRAY/GRAY_LUT/g;
* app/brush_select.[ch]: removed PDB procs, export brush_active_dialogs,
brush_select_dialog, s/active_dialogs/brush_active_dialogs/
* app/gimage_cmds.[ch]
* app/channel_ops.[ch]: removed channel ops PDB procs, moved duplicate
function from gimage_cmds to channel_ops, export offset and duplicate
* app/gimpbrushlist.[ch]: removed PDB procs
* app/gradient.[ch]: removed PDB procs,
* app/gradient_header.h: exported G_SAMPLE, GradSelect, num_gradients,
grad_active_dialogs, gradient_select_dialog
* app/gradient_select.c: removed PDB procs,
s/active_dialogs/grad_active_dialogs/
* app/patterns.[ch]: removed PDB procs
* app/pattern_select.[ch]: removed PDB procs,
s/active_dialogs/pattern_active_dialogs/
* app/procedural_db.c: removed PDB procs and supporting functions
* app/procedrual_db.h: fiddled with enums
* app/channel_cmds.[ch]
* app/drawable_cmds.[ch]
* app/parasite_cmds.[ch]: pdbgenned now, removed header files
* app/gimpparasite.c: minor cleanup
* app/internal_procs.c: use pdbgen stuff
* app/tools_cmds.c
* app/text_tool_cmds.c: updated from pdbgen
* app/brushes_cmds.c
* app/brush_select_cmds.c
* app/gradient_cmds.c
* app/gradient_select_cmds.c
* app/patterns_cmds.c
* app/pattern_select_cmds.c
* app/procedural_db_cmds.c: new pdbgen files
* app/Makefile.am: file shuffle (see above)
-Yosh
1999-04-24 04:54:02 +08:00
|
|
|
#include "undo.h"
|
1998-06-30 23:31:32 +08:00
|
|
|
|
1998-12-16 19:23:30 +08:00
|
|
|
#include "libgimp/parasite.h"
|
1998-11-23 22:47:09 +08:00
|
|
|
#include "libgimp/gimpintl.h"
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
enum {
|
|
|
|
INVALIDATE_PREVIEW,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
static void gimp_drawable_class_init (GimpDrawableClass *klass);
|
|
|
|
static void gimp_drawable_init (GimpDrawable *drawable);
|
|
|
|
static void gimp_drawable_destroy (GtkObject *object);
|
|
|
|
|
|
|
|
static guint gimp_drawable_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
static GimpDrawableClass *parent_class = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
GtkType
|
|
|
|
gimp_drawable_get_type ()
|
|
|
|
{
|
|
|
|
static GtkType type;
|
|
|
|
GIMP_TYPE_INIT(type,
|
|
|
|
GimpDrawable,
|
|
|
|
GimpDrawableClass,
|
|
|
|
gimp_drawable_init,
|
|
|
|
gimp_drawable_class_init,
|
|
|
|
GIMP_TYPE_OBJECT);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_drawable_class_init (GimpDrawableClass *class)
|
|
|
|
{
|
|
|
|
GtkObjectClass *object_class;
|
1999-08-22 19:45:31 +08:00
|
|
|
GtkType type = GIMP_TYPE_DRAWABLE;
|
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
object_class = GTK_OBJECT_CLASS(class);
|
|
|
|
parent_class = gtk_type_class (GIMP_TYPE_OBJECT);
|
|
|
|
|
|
|
|
gimp_drawable_signals[INVALIDATE_PREVIEW] =
|
|
|
|
gimp_signal_new ("invalidate_pr", GTK_RUN_LAST, type,
|
|
|
|
GTK_SIGNAL_OFFSET(GimpDrawableClass,
|
|
|
|
invalidate_preview),
|
|
|
|
gimp_sigtype_void);
|
|
|
|
|
|
|
|
gtk_object_class_add_signals (object_class, gimp_drawable_signals, LAST_SIGNAL);
|
|
|
|
|
|
|
|
object_class->destroy = gimp_drawable_destroy;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Static variables
|
|
|
|
*/
|
1999-08-22 19:45:31 +08:00
|
|
|
static gint global_drawable_ID = 1;
|
1998-06-30 23:31:32 +08:00
|
|
|
static GHashTable *gimp_drawable_table = NULL;
|
|
|
|
|
|
|
|
/**************************/
|
|
|
|
/* Function definitions */
|
|
|
|
|
|
|
|
GimpDrawable*
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_get_ID (gint drawable_id)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
if (gimp_drawable_table == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return (GimpDrawable*) g_hash_table_lookup (gimp_drawable_table,
|
|
|
|
(gpointer) drawable_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_merge_shadow (GimpDrawable *drawable,
|
|
|
|
gint undo)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
GImage *gimage;
|
|
|
|
PixelRegion shadowPR;
|
|
|
|
int x1, y1, x2, y2;
|
|
|
|
|
|
|
|
if (! drawable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
|
|
|
return;
|
|
|
|
|
1999-01-28 06:00:44 +08:00
|
|
|
if (! gimage->shadow)
|
|
|
|
return;
|
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
/* A useful optimization here is to limit the update to the
|
|
|
|
* extents of the selection mask, as it cannot extend beyond
|
|
|
|
* them.
|
|
|
|
*/
|
|
|
|
gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
|
|
|
|
pixel_region_init (&shadowPR, gimage->shadow, x1, y1,
|
|
|
|
(x2 - x1), (y2 - y1), FALSE);
|
|
|
|
gimage_apply_image (gimage, drawable, &shadowPR, undo, OPAQUE_OPACITY,
|
|
|
|
REPLACE_MODE, NULL, x1, y1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_fill (GimpDrawable *drawable,
|
|
|
|
guchar r,
|
|
|
|
guchar g,
|
|
|
|
guchar b,
|
|
|
|
guchar a)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
GImage *gimage;
|
|
|
|
PixelRegion destPR;
|
|
|
|
guchar c[MAX_CHANNELS];
|
|
|
|
guchar i;
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
g_assert (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
gimage = gimp_drawable_gimage (drawable);
|
|
|
|
g_assert (gimage);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
switch (gimp_drawable_type (drawable))
|
|
|
|
{
|
|
|
|
case RGB_GIMAGE: case RGBA_GIMAGE:
|
|
|
|
c[RED_PIX] = r;
|
|
|
|
c[GREEN_PIX] = g;
|
|
|
|
c[BLUE_PIX] = b;
|
|
|
|
if (gimp_drawable_type (drawable) == RGBA_GIMAGE)
|
|
|
|
c[ALPHA_PIX] = a;
|
|
|
|
break;
|
|
|
|
case GRAY_GIMAGE: case GRAYA_GIMAGE:
|
|
|
|
c[GRAY_PIX] = r;
|
|
|
|
if (gimp_drawable_type (drawable) == GRAYA_GIMAGE)
|
|
|
|
c[ALPHA_G_PIX] = a;
|
|
|
|
break;
|
|
|
|
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
|
|
|
|
c[RED_PIX] = r;
|
|
|
|
c[GREEN_PIX] = g;
|
|
|
|
c[BLUE_PIX] = b;
|
|
|
|
gimage_transform_color (gimage, drawable, c, &i, RGB);
|
|
|
|
c[INDEXED_PIX] = i;
|
|
|
|
if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE)
|
|
|
|
c[ALPHA_I_PIX] = a;
|
|
|
|
break;
|
|
|
|
default:
|
1998-11-23 22:47:09 +08:00
|
|
|
g_message (_("Can't fill unknown image type."));
|
1998-06-30 23:31:32 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixel_region_init (&destPR,
|
|
|
|
gimp_drawable_data (drawable),
|
|
|
|
0, 0,
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_width (drawable),
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_height (drawable),
|
|
|
|
TRUE);
|
|
|
|
color_region (&destPR, c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_mask_bounds (GimpDrawable *drawable,
|
1999-08-22 19:45:31 +08:00
|
|
|
gint *x1,
|
|
|
|
gint *y1,
|
|
|
|
gint *x2,
|
|
|
|
gint *y2)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
GImage *gimage;
|
1999-08-22 19:45:31 +08:00
|
|
|
gint off_x, off_y;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
if (! drawable)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (gimage_mask_bounds (gimage, x1, y1, x2, y2))
|
|
|
|
{
|
|
|
|
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
1999-08-22 19:45:31 +08:00
|
|
|
*x1 = CLAMP (*x1 - off_x, 0, gimp_drawable_width (drawable));
|
1998-06-30 23:31:32 +08:00
|
|
|
*y1 = CLAMP (*y1 - off_y, 0, gimp_drawable_height (drawable));
|
1999-08-22 19:45:31 +08:00
|
|
|
*x2 = CLAMP (*x2 - off_x, 0, gimp_drawable_width (drawable));
|
1998-06-30 23:31:32 +08:00
|
|
|
*y2 = CLAMP (*y2 - off_y, 0, gimp_drawable_height (drawable));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
*x2 = gimp_drawable_width (drawable);
|
1998-06-30 23:31:32 +08:00
|
|
|
*y2 = gimp_drawable_height (drawable);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_invalidate_preview (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
GImage *gimage;
|
|
|
|
|
|
|
|
if (! drawable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
drawable->preview_valid = FALSE;
|
|
|
|
#if 0
|
1999-08-22 19:45:31 +08:00
|
|
|
gtk_signal_emit (GTK_OBJECT (drawable),
|
|
|
|
gimp_drawable_signals[INVALIDATE_PREVIEW]);
|
1998-06-30 23:31:32 +08:00
|
|
|
#endif
|
|
|
|
gimage = gimp_drawable_gimage (drawable);
|
|
|
|
if (gimage)
|
|
|
|
{
|
|
|
|
gimage->comp_preview_valid[0] = FALSE;
|
|
|
|
gimage->comp_preview_valid[1] = FALSE;
|
|
|
|
gimage->comp_preview_valid[2] = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gint
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_dirty (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->dirty = (drawable->dirty < 0) ? 2 : drawable->dirty + 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gint
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_clean (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->dirty = (drawable->dirty <= 0) ? 0 : drawable->dirty - 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
GimpImage *
|
|
|
|
gimp_drawable_gimage (GimpDrawable *drawable)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
g_assert (GIMP_IS_DRAWABLE (drawable));
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
return drawable->gimage;
|
|
|
|
}
|
|
|
|
|
1998-10-14 10:54:02 +08:00
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_set_gimage (GimpDrawable *drawable,
|
|
|
|
GimpImage *gimage)
|
1998-10-14 10:54:02 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
g_assert (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
1998-10-14 10:54:02 +08:00
|
|
|
if (gimage == NULL)
|
|
|
|
drawable->tattoo = 0;
|
1998-12-16 19:23:30 +08:00
|
|
|
else if (drawable->tattoo == 0 || drawable->gimage != gimage )
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->tattoo = gimp_image_get_new_tattoo (gimage);
|
|
|
|
|
1998-12-16 19:23:30 +08:00
|
|
|
drawable->gimage = gimage;
|
1998-10-14 10:54:02 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
|
|
|
gimp_drawable_has_alpha (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->has_alpha;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
1998-10-14 10:54:02 +08:00
|
|
|
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
GimpImageType
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_type (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->type;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
GimpImageType
|
|
|
|
gimp_drawable_type_with_alpha (GimpDrawable *drawable)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
GimpImageType type = gimp_drawable_type (drawable);
|
|
|
|
|
|
|
|
gboolean has_alpha = gimp_drawable_has_alpha (drawable);
|
|
|
|
|
|
|
|
if (has_alpha)
|
|
|
|
return type;
|
1998-06-30 23:31:32 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RGB_GIMAGE:
|
|
|
|
return RGBA_GIMAGE; break;
|
|
|
|
case GRAY_GIMAGE:
|
|
|
|
return GRAYA_GIMAGE; break;
|
|
|
|
case INDEXED_GIMAGE:
|
|
|
|
return INDEXEDA_GIMAGE; break;
|
|
|
|
}
|
|
|
|
return 0;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_visible (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
return drawable->visible;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gchar *
|
1998-09-24 09:19:57 +08:00
|
|
|
gimp_drawable_get_name (GimpDrawable *drawable)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
return drawable->name;
|
|
|
|
}
|
|
|
|
|
1998-09-24 09:19:57 +08:00
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_set_name (GimpDrawable *drawable,
|
|
|
|
gchar *name)
|
1998-09-24 09:19:57 +08:00
|
|
|
{
|
|
|
|
GSList *list, *listb, *base_list;
|
|
|
|
GimpDrawable *drawableb;
|
1999-08-22 19:45:31 +08:00
|
|
|
gint number = 1;
|
|
|
|
gchar *newname;
|
|
|
|
gchar *ext;
|
|
|
|
gchar numberbuf[20];
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
1998-09-24 09:19:57 +08:00
|
|
|
|
|
|
|
if (drawable->name)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
|
|
|
g_free (drawable->name);
|
|
|
|
drawable->name = NULL;
|
|
|
|
}
|
|
|
|
|
1998-09-24 09:19:57 +08:00
|
|
|
if (drawable->gimage == 0 || drawable->gimage->layers == 0)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
|
|
|
/* no other layers to check name against */
|
|
|
|
drawable->name = g_strdup (name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (drawable))
|
1998-09-24 09:19:57 +08:00
|
|
|
base_list = drawable->gimage->layers;
|
1999-08-22 19:45:31 +08:00
|
|
|
else if (GIMP_IS_CHANNEL (drawable))
|
1998-09-24 09:19:57 +08:00
|
|
|
base_list = drawable->gimage->channels;
|
|
|
|
else
|
|
|
|
base_list = NULL;
|
|
|
|
|
|
|
|
list = base_list;
|
|
|
|
while (list)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
|
|
|
drawableb = GIMP_DRAWABLE (list->data);
|
|
|
|
if (drawable != drawableb &&
|
|
|
|
strcmp (name, gimp_drawable_get_name (drawableb)) == 0)
|
|
|
|
{ /* names conflict */
|
|
|
|
newname = g_malloc (strlen (name) + 10); /* if this aint enough
|
|
|
|
yer screwed */
|
|
|
|
strcpy (newname, name);
|
|
|
|
if ((ext = strrchr (newname, '#')))
|
|
|
|
{
|
|
|
|
number = atoi(ext+1);
|
|
|
|
/* Check if there really was the number we think after the # */
|
|
|
|
sprintf (numberbuf, "#%d", number);
|
|
|
|
if (strcmp (ext, numberbuf) != 0)
|
|
|
|
{
|
|
|
|
/* No, so just ignore the # */
|
|
|
|
number = 1;
|
|
|
|
ext = &newname[strlen (newname)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
number = 1;
|
|
|
|
ext = &newname[strlen (newname)];
|
|
|
|
}
|
|
|
|
sprintf (ext, "#%d", number+1);
|
1998-09-24 09:19:57 +08:00
|
|
|
listb = base_list;
|
1999-08-22 19:45:31 +08:00
|
|
|
while (listb) /* make sure the new name is unique */
|
|
|
|
{
|
|
|
|
drawableb = GIMP_DRAWABLE (listb->data);
|
|
|
|
if (drawable !=
|
|
|
|
drawableb && strcmp (newname,
|
|
|
|
gimp_drawable_get_name(drawableb)) == 0)
|
|
|
|
{
|
|
|
|
number++;
|
|
|
|
sprintf (ext, "#%d", number+1);
|
|
|
|
/* Rescan from beginning */
|
|
|
|
listb = base_list;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
listb = listb->next;
|
|
|
|
}
|
|
|
|
drawable->name = g_strdup (newname);
|
|
|
|
g_free (newname);
|
|
|
|
return;
|
1998-09-24 09:19:57 +08:00
|
|
|
}
|
1999-08-22 19:45:31 +08:00
|
|
|
list = list->next;
|
1998-09-24 09:19:57 +08:00
|
|
|
}
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->name = g_strdup (name);
|
1998-09-24 09:19:57 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *
|
|
|
|
gimp_drawable_get_color_at (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
1999-02-16 16:53:54 +08:00
|
|
|
{
|
|
|
|
Tile *tile;
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *src;
|
|
|
|
guchar *dest;
|
1999-02-16 16:53:54 +08:00
|
|
|
|
|
|
|
if (!drawable ||
|
1999-08-22 19:45:31 +08:00
|
|
|
(!gimp_drawable_gimage (drawable) && gimp_drawable_indexed (drawable))
|
1999-02-16 16:53:54 +08:00
|
|
|
|| x < 0 || y < 0 ||
|
|
|
|
x >= drawable->width || y >= drawable->height)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
dest = g_new (guchar, 5);
|
1999-02-16 16:53:54 +08:00
|
|
|
tile = tile_manager_get_tile (gimp_drawable_data (drawable), x, y,
|
|
|
|
TRUE, FALSE);
|
|
|
|
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_image_get_color (gimp_drawable_gimage (drawable),
|
1999-02-16 16:53:54 +08:00
|
|
|
gimp_drawable_type (drawable), dest, src);
|
|
|
|
if(TYPE_HAS_ALPHA(gimp_drawable_type (drawable)))
|
|
|
|
dest[3] = src[gimp_drawable_bytes (drawable) - 1];
|
|
|
|
else
|
|
|
|
dest[3] = 255;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (gimp_drawable_indexed (drawable))
|
1999-02-16 16:53:54 +08:00
|
|
|
dest[4] = src[0];
|
|
|
|
else
|
|
|
|
dest[4] = 0;
|
|
|
|
tile_release (tile, FALSE);
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
1998-10-08 16:15:21 +08:00
|
|
|
Parasite *
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_find_parasite (const GimpDrawable *drawable,
|
|
|
|
const gchar *name)
|
1998-10-08 16:15:21 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
return parasite_list_find (drawable->parasites, name);
|
1998-10-08 16:15:21 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
static void
|
|
|
|
list_func (gchar *key,
|
|
|
|
Parasite *p,
|
|
|
|
gchar ***cur)
|
1999-02-14 02:19:44 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
*(*cur)++ = (gchar *) g_strdup (key);
|
1999-02-14 02:19:44 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gchar **
|
|
|
|
gimp_drawable_parasite_list (GimpDrawable *drawable,
|
|
|
|
gint *count)
|
1999-02-14 02:19:44 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
gchar **list, **cur;
|
1999-02-14 02:19:44 +08:00
|
|
|
|
|
|
|
*count = parasite_list_length (drawable->parasites);
|
1999-08-22 19:45:31 +08:00
|
|
|
cur = list = (gchar **) g_malloc (sizeof (gchar *) * *count);
|
1999-02-14 02:19:44 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
|
1999-02-14 02:19:44 +08:00
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
1998-10-08 16:15:21 +08:00
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_attach_parasite (GimpDrawable *drawable,
|
|
|
|
Parasite *parasite)
|
1998-10-08 16:15:21 +08:00
|
|
|
{
|
1999-04-23 14:07:09 +08:00
|
|
|
/* only set the dirty bit manually if we can be saved and the new
|
|
|
|
parasite differs from the current one and we arn't undoable */
|
1999-08-22 19:45:31 +08:00
|
|
|
if (parasite_is_undoable (parasite))
|
|
|
|
{
|
|
|
|
undo_push_group_start (drawable->gimage, MISC_UNDO); /* do a group in case we have
|
|
|
|
attach_parrent set */
|
|
|
|
undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
|
|
|
|
}
|
1999-04-23 14:07:09 +08:00
|
|
|
else if (parasite_is_persistent(parasite) &&
|
1999-08-22 19:45:31 +08:00
|
|
|
!parasite_compare( parasite,
|
|
|
|
gimp_drawable_find_parasite
|
|
|
|
(drawable, parasite_name (parasite))))
|
|
|
|
gimp_image_dirty (drawable->gimage);
|
|
|
|
|
|
|
|
parasite_list_add (drawable->parasites, parasite);
|
|
|
|
if (parasite_has_flag (parasite, PARASITE_ATTACH_PARENT))
|
|
|
|
{
|
|
|
|
parasite_shift_parent (parasite);
|
|
|
|
gimp_image_attach_parasite (drawable->gimage, parasite);
|
|
|
|
}
|
|
|
|
else if (parasite_has_flag (parasite, PARASITE_ATTACH_GRANDPARENT))
|
|
|
|
{
|
|
|
|
parasite_shift_parent (parasite);
|
|
|
|
parasite_shift_parent (parasite);
|
|
|
|
gimp_attach_parasite (parasite);
|
|
|
|
}
|
|
|
|
if (parasite_is_undoable (parasite))
|
|
|
|
{
|
|
|
|
undo_push_group_end (drawable->gimage);
|
|
|
|
}
|
1998-10-08 16:15:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_detach_parasite (GimpDrawable *drawable,
|
|
|
|
const gchar *parasite)
|
1998-10-08 16:15:21 +08:00
|
|
|
{
|
1998-12-16 19:23:30 +08:00
|
|
|
Parasite *p;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
|
|
|
if (!(p = parasite_list_find (drawable->parasites, parasite)))
|
1998-12-16 19:23:30 +08:00
|
|
|
return;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
|
|
|
if (parasite_is_undoable (p))
|
1999-04-23 14:07:09 +08:00
|
|
|
undo_push_drawable_parasite_remove (drawable->gimage, drawable,
|
1999-08-22 19:45:31 +08:00
|
|
|
parasite_name (p));
|
|
|
|
else if (parasite_is_persistent (p))
|
|
|
|
gimp_image_dirty (drawable->gimage);
|
|
|
|
|
|
|
|
parasite_list_remove (drawable->parasites, parasite);
|
1998-10-08 16:15:21 +08:00
|
|
|
}
|
|
|
|
|
1998-10-30 18:21:33 +08:00
|
|
|
Tattoo
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_get_tattoo (const GimpDrawable *drawable)
|
1998-10-14 10:54:02 +08:00
|
|
|
{
|
|
|
|
return drawable->tattoo;
|
|
|
|
}
|
1998-10-08 16:15:21 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_color (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
|
|
|
|
gimp_drawable_type (drawable) == RGB_GIMAGE)
|
1999-08-22 19:45:31 +08:00
|
|
|
return TRUE;
|
1998-06-30 23:31:32 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
return FALSE;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_gray (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
|
|
|
|
gimp_drawable_type (drawable) == GRAY_GIMAGE)
|
1999-08-22 19:45:31 +08:00
|
|
|
return TRUE;
|
1998-06-30 23:31:32 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
return FALSE;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_indexed (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
|
|
|
|
gimp_drawable_type (drawable) == INDEXED_GIMAGE)
|
1999-08-22 19:45:31 +08:00
|
|
|
return TRUE;
|
1998-06-30 23:31:32 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
return FALSE;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TileManager *
|
|
|
|
gimp_drawable_data (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->tiles;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TileManager *
|
|
|
|
gimp_drawable_shadow (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
GImage *gimage;
|
|
|
|
|
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (drawable)
|
|
|
|
return gimage_shadow (gimage, drawable->width, drawable->height,
|
|
|
|
drawable->bytes);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
gimp_drawable_bytes (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->bytes;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gint
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_width (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->width;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gint
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_height (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
return drawable->height;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_offsets (GimpDrawable *drawable,
|
|
|
|
gint *off_x,
|
|
|
|
gint *off_y)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
|
|
|
if (drawable)
|
|
|
|
{
|
|
|
|
*off_x = drawable->offset_x;
|
|
|
|
*off_y = drawable->offset_y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*off_x = *off_y = 0;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *
|
1998-06-30 23:31:32 +08:00
|
|
|
gimp_drawable_cmap (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
GImage *gimage;
|
|
|
|
|
|
|
|
if ((gimage = gimp_drawable_gimage (drawable)))
|
|
|
|
return gimage->cmap;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_deallocate (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
if (drawable->tiles)
|
|
|
|
tile_manager_destroy (drawable->tiles);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_drawable_init (GimpDrawable *drawable)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->name = NULL;
|
|
|
|
drawable->tiles = NULL;
|
|
|
|
drawable->visible = FALSE;
|
|
|
|
drawable->width = 0;
|
|
|
|
drawable->height = 0;
|
|
|
|
drawable->offset_x = 0;
|
|
|
|
drawable->offset_y = 0;
|
|
|
|
drawable->bytes = 0;
|
|
|
|
drawable->dirty = FALSE;
|
|
|
|
drawable->gimage = NULL;
|
|
|
|
drawable->type = -1;
|
|
|
|
drawable->has_alpha = FALSE;
|
1999-06-24 07:01:14 +08:00
|
|
|
drawable->preview_cache = NULL;
|
1998-06-30 23:31:32 +08:00
|
|
|
drawable->preview_valid = FALSE;
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->parasites = parasite_list_new ();
|
|
|
|
drawable->tattoo = 0;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
drawable->ID = global_drawable_ID++;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
if (gimp_drawable_table == NULL)
|
|
|
|
gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
g_hash_table_insert (gimp_drawable_table, (gpointer) drawable->ID,
|
|
|
|
(gpointer) drawable);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_drawable_destroy (GtkObject *object)
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
g_return_if_fail (object != NULL);
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (object));
|
|
|
|
|
|
|
|
drawable = GIMP_DRAWABLE (object);
|
|
|
|
|
|
|
|
g_hash_table_remove (gimp_drawable_table, (gpointer) drawable->ID);
|
|
|
|
|
|
|
|
if (drawable->name)
|
|
|
|
g_free (drawable->name);
|
|
|
|
|
|
|
|
if (drawable->tiles)
|
|
|
|
tile_manager_destroy (drawable->tiles);
|
|
|
|
|
1999-06-24 07:01:14 +08:00
|
|
|
if (drawable->preview_cache)
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_preview_cache_invalidate (&drawable->preview_cache);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
1998-10-08 16:15:21 +08:00
|
|
|
if (drawable->parasites)
|
1999-08-22 19:45:31 +08:00
|
|
|
gtk_object_unref (GTK_OBJECT (drawable->parasites));
|
1998-10-08 16:15:21 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
1999-08-22 19:45:31 +08:00
|
|
|
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_configure (GimpDrawable *drawable,
|
|
|
|
GimpImage *gimage,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
GimpImageType type,
|
|
|
|
gchar *name)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
gint bpp;
|
|
|
|
gboolean alpha;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
if (!name)
|
1998-11-23 22:47:09 +08:00
|
|
|
name = _("unnamed");
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RGB_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 3; alpha = FALSE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
case GRAY_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 1; alpha = FALSE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
case RGBA_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 4; alpha = TRUE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
case GRAYA_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 2; alpha = TRUE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
case INDEXED_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 1; alpha = FALSE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
case INDEXEDA_GIMAGE:
|
1999-08-22 19:45:31 +08:00
|
|
|
bpp = 2; alpha = TRUE; break;
|
1998-06-30 23:31:32 +08:00
|
|
|
default:
|
1998-11-23 22:47:09 +08:00
|
|
|
g_message (_("Layer type %d not supported."), type);
|
1998-06-30 23:31:32 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->name = NULL;
|
|
|
|
drawable->width = width;
|
|
|
|
drawable->height = height;
|
|
|
|
drawable->bytes = bpp;
|
|
|
|
drawable->type = type;
|
1998-06-30 23:31:32 +08:00
|
|
|
drawable->has_alpha = alpha;
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->offset_x = 0;
|
|
|
|
drawable->offset_y = 0;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
if (drawable->tiles)
|
|
|
|
tile_manager_destroy (drawable->tiles);
|
|
|
|
drawable->tiles = tile_manager_new (width, height, bpp);
|
1999-08-22 19:45:31 +08:00
|
|
|
drawable->dirty = FALSE;
|
1998-06-30 23:31:32 +08:00
|
|
|
drawable->visible = TRUE;
|
|
|
|
|
1998-10-14 10:54:02 +08:00
|
|
|
if (gimage)
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_set_gimage (drawable, gimage);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_set_name (drawable, name);
|
1998-09-24 09:19:57 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
/* preview variables */
|
1999-06-24 07:01:14 +08:00
|
|
|
drawable->preview_cache = NULL;
|
1998-06-30 23:31:32 +08:00
|
|
|
drawable->preview_valid = FALSE;
|
|
|
|
}
|