gimpdrawable.c 19.8 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
34
35
#include "gimpsignal.h"
#include "gimage.h"
#include "gimage_mask.h"
Manish Singh's avatar
Manish Singh committed
36
#include "gimpparasite.h"
37
#include "paint_funcs.h"
38
#include "parasitelist.h"
39
40
41
#include "pixel_region.h"
#include "tile.h"
#include "tile_manager.h"
42
#include "undo.h"
43

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

47
#include "libgimp/gimpintl.h"
48

49
50
51

enum
{
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  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
Manish Singh's avatar
Manish Singh committed
66
gimp_drawable_get_type (void)
67
{
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  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;
88
89
90
}

static void
91
gimp_drawable_class_init (GimpDrawableClass *klass)
92
93
{
  GtkObjectClass *object_class;
94
95
  GtkType type = GIMP_TYPE_DRAWABLE;

96
  object_class = GTK_OBJECT_CLASS (klass);
97
  parent_class = gtk_type_class (GIMP_TYPE_OBJECT);
98

99
  gimp_drawable_signals[INVALIDATE_PREVIEW] =
100
101
102
103
    gimp_signal_new ("invalidate_pr", GTK_RUN_LAST, type,
		     GTK_SIGNAL_OFFSET (GimpDrawableClass,
					invalidate_preview),
		     gimp_sigtype_void);
104

105
106
  gtk_object_class_add_signals (object_class, gimp_drawable_signals,
				LAST_SIGNAL);
107
108

  object_class->destroy = gimp_drawable_destroy;
109
110

  klass->invalidate_preview = NULL;
111
112
113
114
115
116
}


/*
 *  Static variables
 */
117
static gint        global_drawable_ID  = 1;
118
119
120
121
122
static GHashTable *gimp_drawable_table = NULL;

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

123
GimpDrawable *
124
gimp_drawable_get_ID (gint drawable_id)
125
126
127
128
{
  if (gimp_drawable_table == NULL)
    return NULL;

129
130
  return (GimpDrawable *) g_hash_table_lookup (gimp_drawable_table, 
					       (gpointer) drawable_id);
131
132
133
}

void
134
135
gimp_drawable_merge_shadow (GimpDrawable *drawable,
			    gint          undo)
136
{
137
138
139
  GImage      *gimage;
  PixelRegion  shadowPR;
  gint         x1, y1, x2, y2;
140

141
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
142
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
143

Manish Singh's avatar
Manish Singh committed
144
  gimage = gimp_drawable_gimage (drawable);
145

Manish Singh's avatar
Manish Singh committed
146
147
  g_return_if_fail (gimage != NULL);
  g_return_if_fail (gimage->shadow != NULL);
148

149
150
151
152
153
154
155
156
157
158
159
160
  /*  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
161
162
163
164
165
gimp_drawable_fill (GimpDrawable *drawable,
		    guchar        r,
		    guchar        g,
		    guchar        b,
		    guchar        a)
166
{
167
168
169
170
  GImage      *gimage;
  PixelRegion  destPR;
  guchar       c[MAX_CHANNELS];
  guchar       i;
171

172
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
173
174
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

175
  gimage = gimp_drawable_gimage (drawable);
176

Manish Singh's avatar
Manish Singh committed
177
  g_return_if_fail (gimage != NULL);
178
179
180
181

  switch (gimp_drawable_type (drawable))
    {
    case RGB_GIMAGE: case RGBA_GIMAGE:
182
      c[RED_PIX]   = r;
183
      c[GREEN_PIX] = g;
184
      c[BLUE_PIX]  = b;
185
186
187
      if (gimp_drawable_type (drawable) == RGBA_GIMAGE)
	c[ALPHA_PIX] = a;
      break;
188

189
190
191
192
193
    case GRAY_GIMAGE: case GRAYA_GIMAGE:
      c[GRAY_PIX] = r;
      if (gimp_drawable_type (drawable) == GRAYA_GIMAGE)
	c[ALPHA_G_PIX] = a;
      break;
194

195
    case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
196
      c[RED_PIX]   = r;
197
      c[GREEN_PIX] = g;
198
      c[BLUE_PIX]  = b;
199
200
201
202
203
      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;
204

205
    default:
206
      g_message (_("Can't fill unknown image type."));
207
208
209
210
211
212
      break;
    }

  pixel_region_init (&destPR,
		     gimp_drawable_data (drawable),
		     0, 0,
213
		     gimp_drawable_width  (drawable),
214
215
216
217
218
		     gimp_drawable_height (drawable),
		     TRUE);
  color_region (&destPR, c);
}

219
gboolean
220
gimp_drawable_mask_bounds (GimpDrawable *drawable, 
221
222
223
224
			   gint         *x1,
			   gint         *y1,
			   gint         *x2,
			   gint         *y2)
225
{
Manish Singh's avatar
Manish Singh committed
226
  GimpImage *gimage;
227
  gint off_x, off_y;
228

229
  g_return_val_if_fail (drawable != NULL, FALSE);
Manish Singh's avatar
Manish Singh committed
230
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
231

Manish Singh's avatar
Manish Singh committed
232
  gimage = gimp_drawable_gimage (drawable);
233

Manish Singh's avatar
Manish Singh committed
234
  g_return_val_if_fail (gimage != NULL, FALSE);
235
236
237
238

  if (gimage_mask_bounds (gimage, x1, y1, x2, y2))
    {
      gimp_drawable_offsets (drawable, &off_x, &off_y);
239
      *x1 = CLAMP (*x1 - off_x, 0, gimp_drawable_width  (drawable));
240
      *y1 = CLAMP (*y1 - off_y, 0, gimp_drawable_height (drawable));
241
      *x2 = CLAMP (*x2 - off_x, 0, gimp_drawable_width  (drawable));
242
243
244
245
246
      *y2 = CLAMP (*y2 - off_y, 0, gimp_drawable_height (drawable));
      return TRUE;
    }
  else
    {
247
      *x2 = gimp_drawable_width  (drawable);
248
249
250
251
252
253
      *y2 = gimp_drawable_height (drawable);
      return FALSE;
    }
}

void
254
255
gimp_drawable_invalidate_preview (GimpDrawable *drawable,
				  gboolean      emit_signal)
256
{
Manish Singh's avatar
Manish Singh committed
257
  GimpImage *gimage;
258

259
  g_return_if_fail (drawable != NULL);
Manish Singh's avatar
Manish Singh committed
260
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
261
262

  drawable->preview_valid = FALSE;
263
264
265
266
267

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

268
269
270
271
272
273
274
275
276
277
278
  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 *
279
gimp_drawable_gimage (const GimpDrawable *drawable)
280
{
Manish Singh's avatar
Manish Singh committed
281
282
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

283
284
285
  return drawable->gimage;
}

286
void
287
288
gimp_drawable_set_gimage (GimpDrawable *drawable,
			  GimpImage    *gimage)
289
{
Manish Singh's avatar
Manish Singh committed
290
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
291

292
293
  if (gimage == NULL)
    drawable->tattoo = 0;
294
  else if (drawable->tattoo == 0 || drawable->gimage != gimage )
295
296
    drawable->tattoo = gimp_image_get_new_tattoo (gimage);

297
  drawable->gimage = gimage;
298
299
}

300
gboolean
301
gimp_drawable_has_alpha (const GimpDrawable *drawable)
302
{
Manish Singh's avatar
Manish Singh committed
303
304
305
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

  return drawable->has_alpha;
306
}
307

308
GimpImageType
309
gimp_drawable_type (const GimpDrawable *drawable)
310
{
Manish Singh's avatar
Manish Singh committed
311
312
313
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->type;
314
315
}

316
GimpImageType
317
gimp_drawable_type_with_alpha (const GimpDrawable *drawable)
318
{
319
  GimpImageType type;
320
321
  gboolean      has_alpha;

Manish Singh's avatar
Manish Singh committed
322
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
323

324
325
  type = gimp_drawable_type (drawable);
  has_alpha = gimp_drawable_has_alpha (drawable);
326
327

  if (has_alpha)
328
329
330
    {
      return type;
    }
331
  else
332
333
334
335
336
337
338
339
340
341
    {
      switch (type)
	{
	case RGB_GIMAGE:
	  return RGBA_GIMAGE; break;
	case GRAY_GIMAGE:
	  return GRAYA_GIMAGE; break;
	case INDEXED_GIMAGE:
	  return INDEXEDA_GIMAGE; break;
	default:
342
343
	  g_assert_not_reached ();
	  break;
344
345
346
	}
    }

347
  return 0;
348
349
}

350
gboolean
351
gimp_drawable_visible (const GimpDrawable *drawable)
352
{
353
354
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

355
356
357
  return drawable->visible;
}

358
359
const gchar *
gimp_drawable_get_name (const GimpDrawable *drawable)
360
{
361
362
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

363
364
365
  return drawable->name;
}

366
void
367
gimp_drawable_set_name (GimpDrawable *drawable,
368
			const gchar  *name)
369
{
370
  GSList       *list, *listb, *base_list;
371
  GimpDrawable *drawableb;
372
373
374
375
  gint          number = 1;
  gchar        *newname;
  gchar        *ext;
  gchar         numberbuf[20];
376
377

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
378
  g_return_if_fail (name != NULL);
379
380

  if (drawable->name)
381
382
383
384
385
    {
      g_free (drawable->name);
      drawable->name = NULL;
    }

386
  if (drawable->gimage == NULL || drawable->gimage->layers == NULL)
387
388
389
390
391
392
393
    {
      /* no other layers to check name against */
      drawable->name = g_strdup (name);
      return;
    }

  if (GIMP_IS_LAYER (drawable))
394
    base_list = drawable->gimage->layers;
395
  else if (GIMP_IS_CHANNEL (drawable))
396
397
398
399
    base_list = drawable->gimage->channels;
  else
    base_list = NULL;

400
  for (list = base_list; list; list = g_slist_next (list))
401
402
403
404
405
406
407
408
409
410
411
412
    {
      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 # */
413
	      g_snprintf (numberbuf, sizeof (numberbuf), "#%d", number);
414
415
416
417
418
419
420
421
422
423
424
425
	      if (strcmp (ext, numberbuf) != 0)
		{
		  /* No, so just ignore the # */
		  number = 1;
		  ext = &newname[strlen (newname)];
		}
	    }
	  else
	    {
	      number = 1;
	      ext = &newname[strlen (newname)];
	    }
426
	  sprintf (ext, "#%d", number + 1);
427
	  listb = base_list;
428
429
430
	  while (listb) /* make sure the new name is unique */
	    {
	      drawableb = GIMP_DRAWABLE (listb->data);
431
432
433

	      if (drawable != drawableb &&
		  strcmp (newname, gimp_drawable_get_name (drawableb)) == 0)
434
435
436
437
438
439
440
441
442
443
444
445
		{
		  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;
446
447
	}
    }
448

449
  drawable->name = g_strdup (name);
450
451
}

452
453
454
455
guchar *
gimp_drawable_get_color_at (GimpDrawable *drawable,
			    gint          x,
			    gint          y)
456
{
457
  Tile   *tile;
458
459
  guchar *src;
  guchar *dest;
460

Manish Singh's avatar
Manish Singh committed
461
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
462
463
  g_return_val_if_fail (gimp_drawable_gimage (drawable) ||
			!gimp_drawable_is_indexed (drawable), NULL);
464
465
466
467

  /* 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
468

469
  dest = g_new (guchar, 5);
Manish Singh's avatar
Manish Singh committed
470

471
472
473
  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
474

475
  gimp_image_get_color (gimp_drawable_gimage (drawable),
476
			gimp_drawable_type (drawable), dest, src);
Manish Singh's avatar
Manish Singh committed
477

478
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_drawable_type (drawable)))
479
480
481
    dest[3] = src[gimp_drawable_bytes (drawable) - 1];
  else
    dest[3] = 255;
Manish Singh's avatar
Manish Singh committed
482

Marc Lehmann's avatar
Marc Lehmann committed
483
  if (gimp_drawable_is_indexed (drawable))
484
485
486
    dest[4] = src[0];
  else
    dest[4] = 0;
Manish Singh's avatar
Manish Singh committed
487

488
  tile_release (tile, FALSE);
Manish Singh's avatar
Manish Singh committed
489

490
491
492
  return dest;
}

493
GimpParasite *
Marc Lehmann's avatar
Marc Lehmann committed
494
gimp_drawable_parasite_find (const GimpDrawable *drawable,
495
			     const gchar        *name)
496
{
497
498
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

499
  return parasite_list_find (drawable->parasites, name);
500
501
}

502
static void
503
504
505
list_func (gchar          *key,
	   GimpParasite   *p,
	   gchar        ***cur)
Marc Lehmann's avatar
Marc Lehmann committed
506
{
507
  *(*cur)++ = (gchar *) g_strdup (key);
Marc Lehmann's avatar
Marc Lehmann committed
508
509
}

510
gchar **
511
512
gimp_drawable_parasite_list (const GimpDrawable *drawable,
			     gint               *count)
Marc Lehmann's avatar
Marc Lehmann committed
513
{
514
515
516
  gchar **list;
  gchar **cur;

517
  g_return_val_if_fail (drawable != NULL, NULL);
518
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
519
  g_return_val_if_fail (count != NULL, NULL);
Marc Lehmann's avatar
Marc Lehmann committed
520
521

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

524
  parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
525

Marc Lehmann's avatar
Marc Lehmann committed
526
527
528
  return list;
}

529
void
Marc Lehmann's avatar
Marc Lehmann committed
530
gimp_drawable_parasite_attach (GimpDrawable *drawable,
531
			       GimpParasite *parasite)
532
{
533
534
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

jaycox's avatar
jaycox committed
535
536
  /* 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 */
537
  if (gimp_parasite_is_undoable (parasite))
538
    {
539
540
541
      /* do a group in case we have attach_parent set */
      undo_push_group_start (drawable->gimage, PARASITE_ATTACH_UNDO);

542
543
      undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
    }
544
  else if (gimp_parasite_is_persistent (parasite) &&
545
546
547
548
549
550
	   ! gimp_parasite_compare (parasite,
				    gimp_drawable_parasite_find
				    (drawable, gimp_parasite_name (parasite))))
    {
      undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
    }
551
552

  parasite_list_add (drawable->parasites, parasite);
553

554
  if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_PARENT))
555
556
    {
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
557
      gimp_image_parasite_attach (drawable->gimage, parasite);
558
    }
559
  else if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_GRANDPARENT))
560
561
562
    {
      parasite_shift_parent (parasite);
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
563
      gimp_parasite_attach (parasite);
564
    }
565

566
  if (gimp_parasite_is_undoable (parasite))
567
568
569
    {
      undo_push_group_end (drawable->gimage);
    }
570
571
572
}

void
Marc Lehmann's avatar
Marc Lehmann committed
573
gimp_drawable_parasite_detach (GimpDrawable *drawable,
574
			       const gchar  *parasite)
575
{
576
  GimpParasite *p;
577

578
579
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

580
  if (! (p = parasite_list_find (drawable->parasites, parasite)))
581
    return;
582

583
  if (gimp_parasite_is_undoable (p))
jaycox's avatar
jaycox committed
584
    undo_push_drawable_parasite_remove (drawable->gimage, drawable,
585
586
					gimp_parasite_name (p));
  else if (gimp_parasite_is_persistent (p))
587
    undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
588
589

  parasite_list_remove (drawable->parasites, parasite);
590
591
}

592
Tattoo
593
gimp_drawable_get_tattoo (const GimpDrawable *drawable)
594
{
595
596
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); 

597
598
  return drawable->tattoo;
}
599

600
void
601
602
gimp_drawable_set_tattoo (GimpDrawable *drawable,
			  Tattoo        val)
603
604
605
606
607
608
{
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  drawable->tattoo = val;
}

609
gboolean
610
gimp_drawable_is_rgb (const GimpDrawable *drawable)
611
{
Manish Singh's avatar
Manish Singh committed
612
613
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

614
615
  if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
      gimp_drawable_type (drawable) == RGB_GIMAGE)
616
    return TRUE;
617
  else
618
    return FALSE;
619
620
}

621
gboolean
622
gimp_drawable_is_gray (const GimpDrawable *drawable)
623
{
Manish Singh's avatar
Manish Singh committed
624
625
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

626
627
  if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
      gimp_drawable_type (drawable) == GRAY_GIMAGE)
628
    return TRUE;
629
  else
630
    return FALSE;
631
632
}

633
gboolean
634
gimp_drawable_is_indexed (const GimpDrawable *drawable)
635
{
Manish Singh's avatar
Manish Singh committed
636
637
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

638
639
  if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
      gimp_drawable_type (drawable) == INDEXED_GIMAGE)
640
    return TRUE;
641
  else
642
    return FALSE;
643
644
645
}

TileManager *
646
gimp_drawable_data (const GimpDrawable *drawable)
647
{
Manish Singh's avatar
Manish Singh committed
648
649
650
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  return drawable->tiles;
651
652
653
654
655
656
657
}

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

Manish Singh's avatar
Manish Singh committed
658
659
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

660
661
662
  if (! (gimage = gimp_drawable_gimage (drawable)))
    return NULL;

Manish Singh's avatar
Manish Singh committed
663
664
  return gimage_shadow (gimage, drawable->width, drawable->height, 
			drawable->bytes);
665
666
667
668
669
}

int
gimp_drawable_bytes (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
670
671
672
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->bytes;
673
674
}

675
gint
676
677
gimp_drawable_width (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
678
679
680
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->width;
681
682
}

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

  return drawable->height;
689
690
691
}

void
692
693
694
gimp_drawable_offsets (GimpDrawable *drawable,
		       gint         *off_x,
		       gint         *off_y)
695
{
Manish Singh's avatar
Manish Singh committed
696
697
698
699
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  *off_x = drawable->offset_x;
  *off_y = drawable->offset_y;
700
701
}

702
guchar *
703
gimp_drawable_cmap (const GimpDrawable *drawable)
704
{
Manish Singh's avatar
Manish Singh committed
705
  GimpImage *gimage;
706

Manish Singh's avatar
Manish Singh committed
707
708
709
710
711
712
  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;
713
714
715
716
717
}

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

720
721
722
723
724
725
726
  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
}

static void
gimp_drawable_init (GimpDrawable *drawable)
{
727
728
729
730
731
732
733
734
  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;
Manish Singh's avatar
Manish Singh committed
735
736
  drawable->ID            = global_drawable_ID++;
  drawable->tattoo        = 0;
737
738
739
  drawable->gimage        = NULL;
  drawable->type          = -1;
  drawable->has_alpha     = FALSE;
740
  drawable->preview_cache = NULL;
741
  drawable->preview_valid = FALSE;
742
  drawable->parasites     = parasite_list_new ();
Manish Singh's avatar
Manish Singh committed
743
744
  drawable->preview_cache = NULL;
  drawable->preview_valid = FALSE;
745

746
747
  if (gimp_drawable_table == NULL)
    gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
748

Manish Singh's avatar
Manish Singh committed
749
  g_hash_table_insert (gimp_drawable_table,
750
		       GINT_TO_POINTER (drawable->ID),
751
752
753
754
755
756
757
		       (gpointer) drawable);
}

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

759
760
761
762
763
764
765
766
767
768
769
770
  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);

771
  if (drawable->preview_cache)
772
    gimp_preview_cache_invalidate (&drawable->preview_cache);
773

774
  if (drawable->parasites)
775
    gtk_object_unref (GTK_OBJECT (drawable->parasites));
776

777
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
778
    GTK_OBJECT_CLASS (parent_class)->destroy (object);
779
780
781
}

void
782
783
784
785
786
gimp_drawable_configure (GimpDrawable  *drawable,
			 GimpImage     *gimage,
			 gint           width,
			 gint           height, 
			 GimpImageType  type,
787
			 const gchar   *name)
788
{
789
  gint     bpp;
790
  gboolean alpha;
791

Manish Singh's avatar
Manish Singh committed
792
793
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

794
  if (!name)
795
    name = _("unnamed");
796
797
798
799

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

816
817
818
819
820
  drawable->name      = NULL;
  drawable->width     = width;
  drawable->height    = height;
  drawable->bytes     = bpp;
  drawable->type      = type;
821
  drawable->has_alpha = alpha;
822
823
  drawable->offset_x  = 0;
  drawable->offset_y  = 0;
824
825
826

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

  drawable->tiles   = tile_manager_new (width, height, bpp);
829
830
  drawable->visible = TRUE;

831
  if (gimage)
832
    gimp_drawable_set_gimage (drawable, gimage);
833

834
  gimp_drawable_set_name (drawable, name);
835

836
  /*  preview variables  */
837
  drawable->preview_cache = NULL;
838
839
  drawable->preview_valid = FALSE;
}