gimpdrawable.c 19.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* 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.
 */
Sven Neumann's avatar
Sven Neumann committed
18

19 20
#include "config.h"

21
#include <stdlib.h>
Sven Neumann's avatar
Sven Neumann committed
22
#include <stdio.h>
23
#include <string.h>
24

Sven Neumann's avatar
Sven Neumann committed
25 26
#include <gtk/gtk.h>

27 28 29 30 31
#include "apptypes.h"

#include "channel.h"
#include "gimpdrawable.h"
#include "layer.h"
32
#include "gimppreviewcache.h"
33
#include "gimage_mask.h"
34
#include "gimpimage.h"
Manish Singh's avatar
Manish Singh committed
35
#include "gimpparasite.h"
36
#include "paint_funcs.h"
37
#include "parasitelist.h"
38 39 40
#include "pixel_region.h"
#include "tile.h"
#include "tile_manager.h"
41
#include "undo.h"
42

43
#include "libgimp/gimpmath.h"
44
#include "libgimp/gimpparasite.h"
45

46
#include "libgimp/gimpintl.h"
47

48 49 50

enum
{
51 52 53 54
  INVALIDATE_PREVIEW,
  LAST_SIGNAL
};

55 56 57 58
static void gimp_drawable_class_init   (GimpDrawableClass *klass);
static void gimp_drawable_init	       (GimpDrawable      *drawable);
static void gimp_drawable_destroy      (GtkObject         *object);
static void gimp_drawable_name_changed (GimpObject        *drawable);
59

60

61 62 63 64 65 66
static guint gimp_drawable_signals[LAST_SIGNAL] = { 0 };

static GimpDrawableClass *parent_class = NULL;


GtkType
Manish Singh's avatar
Manish Singh committed
67
gimp_drawable_get_type (void)
68
{
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
  static GtkType drawable_type = 0;

  if (! drawable_type)
    {
      GtkTypeInfo drawable_info =
      {
	"GimpDrawable",
	sizeof (GimpDrawable),
	sizeof (GimpDrawableClass),
	(GtkClassInitFunc) gimp_drawable_class_init,
	(GtkObjectInitFunc) gimp_drawable_init,
        /* reserved_1 */ NULL,
	/* reserved_2 */ NULL,
	(GtkClassInitFunc) NULL,
      };

      drawable_type = gtk_type_unique (GIMP_TYPE_OBJECT, &drawable_info);
    }

  return drawable_type;
89 90 91
}

static void
92
gimp_drawable_class_init (GimpDrawableClass *klass)
93
{
94 95
  GtkObjectClass  *object_class;
  GimpObjectClass *gimp_object_class;
96

97 98
  object_class      = (GtkObjectClass *) klass;
  gimp_object_class = (GimpObjectClass *) klass;
99

100
  parent_class = gtk_type_class (GIMP_TYPE_OBJECT);
101

102
  gimp_drawable_signals[INVALIDATE_PREVIEW] =
103 104 105 106 107 108 109
    gtk_signal_new ("invalidate_preview",
                    GTK_RUN_FIRST,
                    object_class->type,
                    GTK_SIGNAL_OFFSET (GimpDrawableClass,
				       invalidate_preview),
                    gtk_signal_default_marshaller,
                    GTK_TYPE_NONE, 0);
110

111 112
  gtk_object_class_add_signals (object_class, gimp_drawable_signals,
				LAST_SIGNAL);
113 114

  object_class->destroy = gimp_drawable_destroy;
115

116 117
  gimp_object_class->name_changed = gimp_drawable_name_changed;

118
  klass->invalidate_preview = NULL;
119 120
}

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
static void
gimp_drawable_name_changed (GimpObject *object)
{
  GimpDrawable *drawable;
  GimpDrawable *drawable2;
  GSList       *list, *list2, *base_list;
  gint          unique_ext = 0;
  gchar        *ext;
  gchar        *new_name = NULL;

  g_return_if_fail (GIMP_IS_DRAWABLE (object));

  drawable = GIMP_DRAWABLE (object);

  /*  if no other layers to check name against  */
  if (drawable->gimage == NULL || drawable->gimage->layers == NULL)
    return;

  if (GIMP_IS_LAYER (drawable))
    base_list = drawable->gimage->layers;
  else if (GIMP_IS_CHANNEL (drawable))
    base_list = drawable->gimage->channels;
  else
    base_list = NULL;

  for (list = base_list; list; list = g_slist_next (list))
    {
      drawable2 = GIMP_DRAWABLE (list->data);

      if (drawable != drawable2 &&
	  strcmp (gimp_object_get_name (GIMP_OBJECT (drawable)),
		  gimp_object_get_name (GIMP_OBJECT (drawable2))) == 0)
	{
          ext = strrchr (GIMP_OBJECT (drawable)->name, '#');

          if (ext)
            {
	      gchar *ext_str;

	      unique_ext = atoi (ext + 1);

	      ext_str = g_strdup_printf ("%d", unique_ext);

	      /*  check if the extension really is of the form "#<n>"  */
	      if (! strcmp (ext_str, ext + 1))
		{
		  *ext = '\0';
		}
	      else
                {
                  unique_ext = 0;
                }

              g_free (ext_str);
            }
          else
            {
              unique_ext = 0;
            }

	  do
	    {
	      unique_ext++;

	      g_free (new_name);

	      new_name = g_strdup_printf ("%s#%d",
					  GIMP_OBJECT (drawable)->name,
					  unique_ext);

              for (list2 = base_list; list2; list2 = g_slist_next (list2))
                {
		  drawable2 = GIMP_DRAWABLE (list2->data);

		  if (drawable == drawable2)
		    continue;

                  if (! strcmp (GIMP_OBJECT (drawable2)->name, new_name))
                    {
                      break;
                    }
                }
            }
          while (list2);

          g_free (GIMP_OBJECT (drawable)->name);

          GIMP_OBJECT (drawable)->name = new_name;

          break;
        }
    }
}

215 216 217 218

/*
 *  Static variables
 */
219
static gint        global_drawable_ID  = 1;
220 221 222 223 224
static GHashTable *gimp_drawable_table = NULL;

/**************************/
/*  Function definitions  */

225
GimpDrawable *
226
gimp_drawable_get_ID (gint drawable_id)
227 228 229 230
{
  if (gimp_drawable_table == NULL)
    return NULL;

231 232
  return (GimpDrawable *) g_hash_table_lookup (gimp_drawable_table, 
					       (gpointer) drawable_id);
233 234 235
}

void
236 237
gimp_drawable_merge_shadow (GimpDrawable *drawable,
			    gint          undo)
238
{
239 240 241
  GImage      *gimage;
  PixelRegion  shadowPR;
  gint         x1, y1, x2, y2;
242

243
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
244
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
245

Manish Singh's avatar
Manish Singh committed
246
  gimage = gimp_drawable_gimage (drawable);
247

Manish Singh's avatar
Manish Singh committed
248 249
  g_return_if_fail (gimage != NULL);
  g_return_if_fail (gimage->shadow != NULL);
250

251 252 253 254 255 256 257
  /*  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);
258 259
  gimp_image_apply_image (gimage, drawable, &shadowPR, undo, OPAQUE_OPACITY,
			  REPLACE_MODE, NULL, x1, y1);
260 261 262
}

void
263 264 265 266 267
gimp_drawable_fill (GimpDrawable *drawable,
		    guchar        r,
		    guchar        g,
		    guchar        b,
		    guchar        a)
268
{
269 270 271 272
  GImage      *gimage;
  PixelRegion  destPR;
  guchar       c[MAX_CHANNELS];
  guchar       i;
273

274
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
275 276
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

277
  gimage = gimp_drawable_gimage (drawable);
278

Manish Singh's avatar
Manish Singh committed
279
  g_return_if_fail (gimage != NULL);
280 281 282 283

  switch (gimp_drawable_type (drawable))
    {
    case RGB_GIMAGE: case RGBA_GIMAGE:
284
      c[RED_PIX]   = r;
285
      c[GREEN_PIX] = g;
286
      c[BLUE_PIX]  = b;
287 288 289
      if (gimp_drawable_type (drawable) == RGBA_GIMAGE)
	c[ALPHA_PIX] = a;
      break;
290

291 292 293 294 295
    case GRAY_GIMAGE: case GRAYA_GIMAGE:
      c[GRAY_PIX] = r;
      if (gimp_drawable_type (drawable) == GRAYA_GIMAGE)
	c[ALPHA_G_PIX] = a;
      break;
296

297
    case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
298
      c[RED_PIX]   = r;
299
      c[GREEN_PIX] = g;
300
      c[BLUE_PIX]  = b;
301
      gimp_image_transform_color (gimage, drawable, c, &i, RGB);
302 303 304 305
      c[INDEXED_PIX] = i;
      if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE)
	  c[ALPHA_I_PIX] = a;
      break;
306

307
    default:
308
      g_message (_("Can't fill unknown image type."));
309 310 311 312 313 314
      break;
    }

  pixel_region_init (&destPR,
		     gimp_drawable_data (drawable),
		     0, 0,
315
		     gimp_drawable_width  (drawable),
316 317 318 319 320
		     gimp_drawable_height (drawable),
		     TRUE);
  color_region (&destPR, c);
}

321
gboolean
322
gimp_drawable_mask_bounds (GimpDrawable *drawable, 
323 324 325 326
			   gint         *x1,
			   gint         *y1,
			   gint         *x2,
			   gint         *y2)
327
{
Manish Singh's avatar
Manish Singh committed
328
  GimpImage *gimage;
329
  gint off_x, off_y;
330

331
  g_return_val_if_fail (drawable != NULL, FALSE);
Manish Singh's avatar
Manish Singh committed
332
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
333

Manish Singh's avatar
Manish Singh committed
334
  gimage = gimp_drawable_gimage (drawable);
335

Manish Singh's avatar
Manish Singh committed
336
  g_return_val_if_fail (gimage != NULL, FALSE);
337 338 339 340

  if (gimage_mask_bounds (gimage, x1, y1, x2, y2))
    {
      gimp_drawable_offsets (drawable, &off_x, &off_y);
341
      *x1 = CLAMP (*x1 - off_x, 0, gimp_drawable_width  (drawable));
342
      *y1 = CLAMP (*y1 - off_y, 0, gimp_drawable_height (drawable));
343
      *x2 = CLAMP (*x2 - off_x, 0, gimp_drawable_width  (drawable));
344 345 346 347 348
      *y2 = CLAMP (*y2 - off_y, 0, gimp_drawable_height (drawable));
      return TRUE;
    }
  else
    {
349
      *x2 = gimp_drawable_width  (drawable);
350 351 352 353 354 355
      *y2 = gimp_drawable_height (drawable);
      return FALSE;
    }
}

void
356 357
gimp_drawable_invalidate_preview (GimpDrawable *drawable,
				  gboolean      emit_signal)
358
{
Manish Singh's avatar
Manish Singh committed
359
  GimpImage *gimage;
360

361
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
362
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
363 364

  drawable->preview_valid = FALSE;
365 366 367 368 369

  if (emit_signal)
    gtk_signal_emit (GTK_OBJECT (drawable),
		     gimp_drawable_signals[INVALIDATE_PREVIEW]);

370 371 372 373 374 375 376 377 378 379 380
  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;
    }
}


GimpImage *
381
gimp_drawable_gimage (const GimpDrawable *drawable)
382
{
Manish Singh's avatar
Manish Singh committed
383 384
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

385 386 387
  return drawable->gimage;
}

388
void
389 390
gimp_drawable_set_gimage (GimpDrawable *drawable,
			  GimpImage    *gimage)
391
{
Manish Singh's avatar
Manish Singh committed
392
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
393

394 395
  if (gimage == NULL)
    drawable->tattoo = 0;
396
  else if (drawable->tattoo == 0 || drawable->gimage != gimage )
397 398
    drawable->tattoo = gimp_image_get_new_tattoo (gimage);

399
  drawable->gimage = gimage;
400 401
}

402
gboolean
403
gimp_drawable_has_alpha (const GimpDrawable *drawable)
404
{
Manish Singh's avatar
Manish Singh committed
405 406 407
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

  return drawable->has_alpha;
408
}
409

410
GimpImageType
411
gimp_drawable_type (const GimpDrawable *drawable)
412
{
Manish Singh's avatar
Manish Singh committed
413 414 415
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->type;
416 417
}

418
GimpImageType
419
gimp_drawable_type_with_alpha (const GimpDrawable *drawable)
420
{
421
  GimpImageType type;
422 423
  gboolean      has_alpha;

Manish Singh's avatar
Manish Singh committed
424
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
425

426 427
  type = gimp_drawable_type (drawable);
  has_alpha = gimp_drawable_has_alpha (drawable);
428 429

  if (has_alpha)
430 431 432
    {
      return type;
    }
433
  else
434 435 436 437 438 439 440 441 442 443
    {
      switch (type)
	{
	case RGB_GIMAGE:
	  return RGBA_GIMAGE; break;
	case GRAY_GIMAGE:
	  return GRAYA_GIMAGE; break;
	case INDEXED_GIMAGE:
	  return INDEXEDA_GIMAGE; break;
	default:
444 445
	  g_assert_not_reached ();
	  break;
446 447 448
	}
    }

449
  return 0;
450 451
}

452
gboolean
453
gimp_drawable_visible (const GimpDrawable *drawable)
454
{
455 456
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

457 458 459
  return drawable->visible;
}

460 461 462 463
guchar *
gimp_drawable_get_color_at (GimpDrawable *drawable,
			    gint          x,
			    gint          y)
464
{
465
  Tile   *tile;
466 467
  guchar *src;
  guchar *dest;
468

Manish Singh's avatar
Manish Singh committed
469
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
470 471
  g_return_val_if_fail (gimp_drawable_gimage (drawable) ||
			!gimp_drawable_is_indexed (drawable), NULL);
472 473 474 475

  /* do not make this a g_return_if_fail() */
  if ( !(x >= 0 && x < drawable->width && y >= 0 && y < drawable->height))
    return NULL;
Manish Singh's avatar
Manish Singh committed
476

477
  dest = g_new (guchar, 5);
Manish Singh's avatar
Manish Singh committed
478

479 480 481
  tile = tile_manager_get_tile (gimp_drawable_data (drawable), x, y,
				TRUE, FALSE);
  src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
Manish Singh's avatar
Manish Singh committed
482

483
  gimp_image_get_color (gimp_drawable_gimage (drawable),
484
			gimp_drawable_type (drawable), dest, src);
Manish Singh's avatar
Manish Singh committed
485

486
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_drawable_type (drawable)))
487 488 489
    dest[3] = src[gimp_drawable_bytes (drawable) - 1];
  else
    dest[3] = 255;
Manish Singh's avatar
Manish Singh committed
490

Marc Lehmann's avatar
Marc Lehmann committed
491
  if (gimp_drawable_is_indexed (drawable))
492 493 494
    dest[4] = src[0];
  else
    dest[4] = 0;
Manish Singh's avatar
Manish Singh committed
495

496
  tile_release (tile, FALSE);
Manish Singh's avatar
Manish Singh committed
497

498 499 500
  return dest;
}

501
GimpParasite *
Marc Lehmann's avatar
Marc Lehmann committed
502
gimp_drawable_parasite_find (const GimpDrawable *drawable,
503
			     const gchar        *name)
504
{
505 506
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

507
  return parasite_list_find (drawable->parasites, name);
508 509
}

510
static void
511 512 513
list_func (gchar          *key,
	   GimpParasite   *p,
	   gchar        ***cur)
Marc Lehmann's avatar
Marc Lehmann committed
514
{
515
  *(*cur)++ = (gchar *) g_strdup (key);
Marc Lehmann's avatar
Marc Lehmann committed
516 517
}

518
gchar **
519 520
gimp_drawable_parasite_list (const GimpDrawable *drawable,
			     gint               *count)
Marc Lehmann's avatar
Marc Lehmann committed
521
{
522 523 524
  gchar **list;
  gchar **cur;

525
  g_return_val_if_fail (drawable != NULL, NULL);
526
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
527
  g_return_val_if_fail (count != NULL, NULL);
Marc Lehmann's avatar
Marc Lehmann committed
528 529

  *count = parasite_list_length (drawable->parasites);
Manish Singh's avatar
Manish Singh committed
530
  cur = list = g_new (gchar *, *count);
Marc Lehmann's avatar
Marc Lehmann committed
531

532
  parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
533

Marc Lehmann's avatar
Marc Lehmann committed
534 535 536
  return list;
}

537
void
Marc Lehmann's avatar
Marc Lehmann committed
538
gimp_drawable_parasite_attach (GimpDrawable *drawable,
539
			       GimpParasite *parasite)
540
{
541 542
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

jaycox's avatar
jaycox committed
543 544
  /* 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 */
545
  if (gimp_parasite_is_undoable (parasite))
546
    {
547 548 549
      /* do a group in case we have attach_parent set */
      undo_push_group_start (drawable->gimage, PARASITE_ATTACH_UNDO);

550 551
      undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
    }
552
  else if (gimp_parasite_is_persistent (parasite) &&
553 554 555 556 557 558
	   ! gimp_parasite_compare (parasite,
				    gimp_drawable_parasite_find
				    (drawable, gimp_parasite_name (parasite))))
    {
      undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
    }
559 560

  parasite_list_add (drawable->parasites, parasite);
561

562
  if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_PARENT))
563 564
    {
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
565
      gimp_image_parasite_attach (drawable->gimage, parasite);
566
    }
567
  else if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_GRANDPARENT))
568 569 570
    {
      parasite_shift_parent (parasite);
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
571
      gimp_parasite_attach (parasite);
572
    }
573

574
  if (gimp_parasite_is_undoable (parasite))
575 576 577
    {
      undo_push_group_end (drawable->gimage);
    }
578 579 580
}

void
Marc Lehmann's avatar
Marc Lehmann committed
581
gimp_drawable_parasite_detach (GimpDrawable *drawable,
582
			       const gchar  *parasite)
583
{
584
  GimpParasite *p;
585

586 587
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

588
  if (! (p = parasite_list_find (drawable->parasites, parasite)))
589
    return;
590

591
  if (gimp_parasite_is_undoable (p))
jaycox's avatar
jaycox committed
592
    undo_push_drawable_parasite_remove (drawable->gimage, drawable,
593 594
					gimp_parasite_name (p));
  else if (gimp_parasite_is_persistent (p))
595
    undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
596 597

  parasite_list_remove (drawable->parasites, parasite);
598 599
}

600
Tattoo
601
gimp_drawable_get_tattoo (const GimpDrawable *drawable)
602
{
603 604
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); 

605 606
  return drawable->tattoo;
}
607

608
void
609 610
gimp_drawable_set_tattoo (GimpDrawable *drawable,
			  Tattoo        val)
611 612 613 614 615 616
{
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  drawable->tattoo = val;
}

617
gboolean
618
gimp_drawable_is_rgb (const GimpDrawable *drawable)
619
{
Manish Singh's avatar
Manish Singh committed
620 621
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

622 623
  if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
      gimp_drawable_type (drawable) == RGB_GIMAGE)
624
    return TRUE;
625
  else
626
    return FALSE;
627 628
}

629
gboolean
630
gimp_drawable_is_gray (const GimpDrawable *drawable)
631
{
Manish Singh's avatar
Manish Singh committed
632 633
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

634 635
  if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
      gimp_drawable_type (drawable) == GRAY_GIMAGE)
636
    return TRUE;
637
  else
638
    return FALSE;
639 640
}

641
gboolean
642
gimp_drawable_is_indexed (const GimpDrawable *drawable)
643
{
Manish Singh's avatar
Manish Singh committed
644 645
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

646 647
  if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
      gimp_drawable_type (drawable) == INDEXED_GIMAGE)
648
    return TRUE;
649
  else
650
    return FALSE;
651 652 653
}

TileManager *
654
gimp_drawable_data (const GimpDrawable *drawable)
655
{
Manish Singh's avatar
Manish Singh committed
656 657 658
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  return drawable->tiles;
659 660 661 662 663 664 665
}

TileManager *
gimp_drawable_shadow (GimpDrawable *drawable)
{
  GImage *gimage;

Manish Singh's avatar
Manish Singh committed
666 667
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

668 669 670
  if (! (gimage = gimp_drawable_gimage (drawable)))
    return NULL;

671 672
  return gimp_image_shadow (gimage, drawable->width, drawable->height, 
			    drawable->bytes);
673 674 675 676 677
}

int
gimp_drawable_bytes (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
678 679 680
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->bytes;
681 682
}

683
gint
684 685
gimp_drawable_width (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
686 687 688
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->width;
689 690
}

691
gint
692 693
gimp_drawable_height (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
694 695 696
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->height;
697 698 699
}

void
700 701 702
gimp_drawable_offsets (GimpDrawable *drawable,
		       gint         *off_x,
		       gint         *off_y)
703
{
Manish Singh's avatar
Manish Singh committed
704 705 706 707
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  *off_x = drawable->offset_x;
  *off_y = drawable->offset_y;
708 709
}

710
guchar *
711
gimp_drawable_cmap (const GimpDrawable *drawable)
712
{
Manish Singh's avatar
Manish Singh committed
713
  GimpImage *gimage;
714

Manish Singh's avatar
Manish Singh committed
715 716 717 718 719 720
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  gimage = gimp_drawable_gimage (drawable);
  g_return_val_if_fail (gimage != NULL, NULL);

  return gimage->cmap;
721 722 723 724 725
}

void
gimp_drawable_deallocate (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
726 727
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

728 729 730 731 732 733 734
  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
}

static void
gimp_drawable_init (GimpDrawable *drawable)
{
735 736 737 738 739 740 741
  drawable->tiles         = NULL;
  drawable->visible       = FALSE;
  drawable->width         = 0;
  drawable->height        = 0;
  drawable->offset_x      = 0;
  drawable->offset_y      = 0;
  drawable->bytes         = 0;
Manish Singh's avatar
Manish Singh committed
742 743
  drawable->ID            = global_drawable_ID++;
  drawable->tattoo        = 0;
744 745 746
  drawable->gimage        = NULL;
  drawable->type          = -1;
  drawable->has_alpha     = FALSE;
747
  drawable->preview_cache = NULL;
748
  drawable->preview_valid = FALSE;
749
  drawable->parasites     = parasite_list_new ();
Manish Singh's avatar
Manish Singh committed
750 751
  drawable->preview_cache = NULL;
  drawable->preview_valid = FALSE;
752

753 754
  if (gimp_drawable_table == NULL)
    gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
755

Manish Singh's avatar
Manish Singh committed
756
  g_hash_table_insert (gimp_drawable_table,
757
		       GINT_TO_POINTER (drawable->ID),
758 759 760 761 762 763 764
		       (gpointer) drawable);
}

static void
gimp_drawable_destroy (GtkObject *object)
{
  GimpDrawable *drawable;
765

766 767 768 769 770 771 772 773 774
  g_return_if_fail (GIMP_IS_DRAWABLE (object));

  drawable = GIMP_DRAWABLE (object);

  g_hash_table_remove (gimp_drawable_table, (gpointer) drawable->ID);

  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);

775
  if (drawable->preview_cache)
776
    gimp_preview_cache_invalidate (&drawable->preview_cache);
777

778
  if (drawable->parasites)
779
    gtk_object_unref (GTK_OBJECT (drawable->parasites));
780

781
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
782
    GTK_OBJECT_CLASS (parent_class)->destroy (object);
783 784 785
}

void
786 787 788 789 790
gimp_drawable_configure (GimpDrawable  *drawable,
			 GimpImage     *gimage,
			 gint           width,
			 gint           height, 
			 GimpImageType  type,
791
			 const gchar   *name)
792
{
793
  gint     bpp;
794
  gboolean alpha;
795

Manish Singh's avatar
Manish Singh committed
796 797
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

798
  if (!name)
799
    name = _("unnamed");
800 801 802 803

  switch (type)
    {
    case RGB_GIMAGE:
804
      bpp = 3; alpha = FALSE; break;
805
    case GRAY_GIMAGE:
806
      bpp = 1; alpha = FALSE; break;
807
    case RGBA_GIMAGE:
808
      bpp = 4; alpha = TRUE; break;
809
    case GRAYA_GIMAGE:
810
      bpp = 2; alpha = TRUE; break;
811
    case INDEXED_GIMAGE:
812
      bpp = 1; alpha = FALSE; break;
813
    case INDEXEDA_GIMAGE:
814
      bpp = 2; alpha = TRUE; break;
815
    default:
816
      g_message (_("Layer type %d not supported."), type);
817 818 819
      return;
    }

820 821 822 823
  drawable->width     = width;
  drawable->height    = height;
  drawable->bytes     = bpp;
  drawable->type      = type;
824
  drawable->has_alpha = alpha;
825 826
  drawable->offset_x  = 0;
  drawable->offset_y  = 0;
827 828 829

  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
830 831

  drawable->tiles   = tile_manager_new (width, height, bpp);
832 833
  drawable->visible = TRUE;

834
  if (gimage)
835
    gimp_drawable_set_gimage (drawable, gimage);
836

837
  gimp_object_set_name (GIMP_OBJECT (drawable), name);
838

839
  /*  preview variables  */
840
  drawable->preview_cache = NULL;
841 842
  drawable->preview_valid = FALSE;
}