gimpdrawable.c 18.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
#include "gimpdrawableP.h"
#include "gimpsignal.h"
#include "gimage.h"
#include "gimage_mask.h"
Manish Singh's avatar
Manish Singh committed
31
#include "gimpparasite.h"
32
#include "parasitelist.h"
33
#include "undo.h"
34

35
#include "libgimp/gimpmath.h"
36
#include "libgimp/gimpparasite.h"
37

38
#include "libgimp/gimpintl.h"
39

40
41
42

enum
{
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  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
57
gimp_drawable_get_type (void)
58
59
{
  static GtkType type;
60
61
62
63
64
65
  GIMP_TYPE_INIT (type,
		  GimpDrawable,
		  GimpDrawableClass,
		  gimp_drawable_init,
		  gimp_drawable_class_init,
		  GIMP_TYPE_OBJECT);
66
67
68
69
70
71
72
  return type;
}

static void
gimp_drawable_class_init (GimpDrawableClass *class)
{
  GtkObjectClass *object_class;
73
74
  GtkType type = GIMP_TYPE_DRAWABLE;

75
  object_class = GTK_OBJECT_CLASS (class);
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  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
 */
93
static gint        global_drawable_ID  = 1;
94
95
96
97
98
99
static GHashTable *gimp_drawable_table = NULL;

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

GimpDrawable*
100
gimp_drawable_get_ID (gint drawable_id)
101
102
103
104
105
106
107
108
109
{
  if (gimp_drawable_table == NULL)
    return NULL;

  return (GimpDrawable*) g_hash_table_lookup (gimp_drawable_table, 
					      (gpointer) drawable_id);
}

void
110
111
gimp_drawable_merge_shadow (GimpDrawable *drawable,
			    gint          undo)
112
113
114
115
116
{
  GImage *gimage;
  PixelRegion shadowPR;
  int x1, y1, x2, y2;

Manish Singh's avatar
Manish Singh committed
117
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
118

Manish Singh's avatar
Manish Singh committed
119
120
121
  gimage = gimp_drawable_gimage (drawable);
  g_return_if_fail (gimage != NULL);
  g_return_if_fail (gimage->shadow != NULL);
122

123
124
125
126
127
128
129
130
131
132
133
134
  /*  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
135
136
137
138
139
gimp_drawable_fill (GimpDrawable *drawable,
		    guchar        r,
		    guchar        g,
		    guchar        b,
		    guchar        a)
140
141
142
143
144
145
{
  GImage *gimage;
  PixelRegion destPR;
  guchar c[MAX_CHANNELS];
  guchar i;

Manish Singh's avatar
Manish Singh committed
146
147
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

148
  gimage = gimp_drawable_gimage (drawable);
Manish Singh's avatar
Manish Singh committed
149
  g_return_if_fail (gimage != NULL);
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

  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:
175
      g_message (_("Can't fill unknown image type."));
176
177
178
179
180
181
      break;
    }

  pixel_region_init (&destPR,
		     gimp_drawable_data (drawable),
		     0, 0,
182
		     gimp_drawable_width  (drawable),
183
184
185
186
187
188
		     gimp_drawable_height (drawable),
		     TRUE);
  color_region (&destPR, c);

}

189
gboolean
190
gimp_drawable_mask_bounds (GimpDrawable *drawable, 
191
192
193
194
			   gint         *x1,
			   gint         *y1,
			   gint         *x2,
			   gint         *y2)
195
{
Manish Singh's avatar
Manish Singh committed
196
  GimpImage *gimage;
197
  gint off_x, off_y;
198

Manish Singh's avatar
Manish Singh committed
199
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
200

Manish Singh's avatar
Manish Singh committed
201
202
  gimage = gimp_drawable_gimage (drawable);
  g_return_val_if_fail (gimage != NULL, FALSE);
203
204
205
206

  if (gimage_mask_bounds (gimage, x1, y1, x2, y2))
    {
      gimp_drawable_offsets (drawable, &off_x, &off_y);
207
      *x1 = CLAMP (*x1 - off_x, 0, gimp_drawable_width  (drawable));
208
      *y1 = CLAMP (*y1 - off_y, 0, gimp_drawable_height (drawable));
209
      *x2 = CLAMP (*x2 - off_x, 0, gimp_drawable_width  (drawable));
210
211
212
213
214
      *y2 = CLAMP (*y2 - off_y, 0, gimp_drawable_height (drawable));
      return TRUE;
    }
  else
    {
215
      *x2 = gimp_drawable_width  (drawable);
216
217
218
219
220
221
      *y2 = gimp_drawable_height (drawable);
      return FALSE;
    }
}

void
222
223
gimp_drawable_invalidate_preview (GimpDrawable *drawable,
				  gboolean      emit_signal)
224
{
Manish Singh's avatar
Manish Singh committed
225
  GimpImage *gimage;
226

Manish Singh's avatar
Manish Singh committed
227
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
228
229

  drawable->preview_valid = FALSE;
230
231
232
233
234

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

235
236
237
238
239
240
241
242
243
244
245
246
247
  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 *
gimp_drawable_gimage (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
248
249
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

250
251
252
  return drawable->gimage;
}

253
void
254
255
gimp_drawable_set_gimage (GimpDrawable *drawable,
			  GimpImage    *gimage)
256
{
Manish Singh's avatar
Manish Singh committed
257
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
258

259
260
  if (gimage == NULL)
    drawable->tattoo = 0;
261
  else if (drawable->tattoo == 0 || drawable->gimage != gimage )
262
263
    drawable->tattoo = gimp_image_get_new_tattoo (gimage);

264
  drawable->gimage = gimage;
265
266
}

267
268
269
gboolean
gimp_drawable_has_alpha (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
270
271
272
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

  return drawable->has_alpha;
273
}
274

275
GimpImageType
276
277
gimp_drawable_type (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
278
279
280
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->type;
281
282
}

283
284
GimpImageType
gimp_drawable_type_with_alpha (GimpDrawable *drawable)
285
{
286
287
288
  GimpImageType type;
  gboolean has_alpha;
  
Manish Singh's avatar
Manish Singh committed
289
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
290

291
292
  type = gimp_drawable_type (drawable);
  has_alpha = gimp_drawable_has_alpha (drawable);
293
294
295

  if (has_alpha)
    return type;
296
  else
297
298
299
300
301
302
303
304
    switch (type)
      {
      case RGB_GIMAGE:
	return RGBA_GIMAGE; break;
      case GRAY_GIMAGE:
	return GRAYA_GIMAGE; break;
      case INDEXED_GIMAGE:
	return INDEXEDA_GIMAGE; break;
305
306
307
      default:
	  g_assert_not_reached ();
	  break;
308
309
      }
  return 0;
310
311
}

312
gboolean
313
314
gimp_drawable_visible (GimpDrawable *drawable)
{
315
316
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

317
318
319
  return drawable->visible;
}

320
gchar *
321
gimp_drawable_get_name (GimpDrawable *drawable)
322
{
323
324
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

325
326
327
  return drawable->name;
}

328
void
329
330
gimp_drawable_set_name (GimpDrawable *drawable,
			gchar        *name)
331
{
332
  GSList       *list, *listb, *base_list;
333
  GimpDrawable *drawableb;
334
335
336
337
  gint          number = 1;
  gchar        *newname;
  gchar        *ext;
  gchar         numberbuf[20];
338
339

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
340
  g_return_if_fail (name != NULL);
341
342

  if (drawable->name)
343
344
345
346
347
    {
      g_free (drawable->name);
      drawable->name = NULL;
    }

348
  if (drawable->gimage == NULL || drawable->gimage->layers == NULL)
349
350
351
352
353
354
355
    {
      /* no other layers to check name against */
      drawable->name = g_strdup (name);
      return;
    }

  if (GIMP_IS_LAYER (drawable))
356
    base_list = drawable->gimage->layers;
357
  else if (GIMP_IS_CHANNEL (drawable))
358
359
360
361
    base_list = drawable->gimage->channels;
  else
    base_list = NULL;

362
  for (list = base_list; list; list = g_slist_next (list))
363
364
365
366
367
368
369
370
371
372
373
374
    {
      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 # */
375
	      g_snprintf (numberbuf, sizeof (numberbuf), "#%d", number);
376
377
378
379
380
381
382
383
384
385
386
387
	      if (strcmp (ext, numberbuf) != 0)
		{
		  /* No, so just ignore the # */
		  number = 1;
		  ext = &newname[strlen (newname)];
		}
	    }
	  else
	    {
	      number = 1;
	      ext = &newname[strlen (newname)];
	    }
388
	  sprintf (ext, "#%d", number + 1);
389
	  listb = base_list;
390
391
392
	  while (listb) /* make sure the new name is unique */
	    {
	      drawableb = GIMP_DRAWABLE (listb->data);
393
394
395

	      if (drawable != drawableb &&
		  strcmp (newname, gimp_drawable_get_name (drawableb)) == 0)
396
397
398
399
400
401
402
403
404
405
406
407
		{
		  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;
408
409
	}
    }
410

411
  drawable->name = g_strdup (name);
412
413
}

414
415
416
417
guchar *
gimp_drawable_get_color_at (GimpDrawable *drawable,
			    gint          x,
			    gint          y)
418
{
419
  Tile   *tile;
420
421
  guchar *src;
  guchar *dest;
422

Manish Singh's avatar
Manish Singh committed
423
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
424
425
  g_return_val_if_fail (gimp_drawable_gimage (drawable) ||
			!gimp_drawable_is_indexed (drawable), NULL);
426
427
428
429

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

431
  dest = g_new (guchar, 5);
Manish Singh's avatar
Manish Singh committed
432

433
434
435
  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
436

437
  gimp_image_get_color (gimp_drawable_gimage (drawable),
438
			gimp_drawable_type (drawable), dest, src);
Manish Singh's avatar
Manish Singh committed
439

440
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_drawable_type (drawable)))
441
442
443
    dest[3] = src[gimp_drawable_bytes (drawable) - 1];
  else
    dest[3] = 255;
Manish Singh's avatar
Manish Singh committed
444

Marc Lehmann's avatar
Marc Lehmann committed
445
  if (gimp_drawable_is_indexed (drawable))
446
447
448
    dest[4] = src[0];
  else
    dest[4] = 0;
Manish Singh's avatar
Manish Singh committed
449

450
  tile_release (tile, FALSE);
Manish Singh's avatar
Manish Singh committed
451

452
453
454
  return dest;
}

455
GimpParasite *
Marc Lehmann's avatar
Marc Lehmann committed
456
gimp_drawable_parasite_find (const GimpDrawable *drawable,
457
			     const gchar        *name)
458
{
459
460
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

461
  return parasite_list_find (drawable->parasites, name);
462
463
}

464
static void
465
466
467
list_func (gchar          *key,
	   GimpParasite   *p,
	   gchar        ***cur)
Marc Lehmann's avatar
Marc Lehmann committed
468
{
469
  *(*cur)++ = (gchar *) g_strdup (key);
Marc Lehmann's avatar
Marc Lehmann committed
470
471
}

472
473
474
gchar **
gimp_drawable_parasite_list (GimpDrawable *drawable,
			     gint         *count)
Marc Lehmann's avatar
Marc Lehmann committed
475
{
476
477
478
479
  gchar **list;
  gchar **cur;

  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
Marc Lehmann's avatar
Marc Lehmann committed
480
481

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

484
  parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
Marc Lehmann's avatar
Marc Lehmann committed
485
486
487
488
  
  return list;
}

489
void
Marc Lehmann's avatar
Marc Lehmann committed
490
gimp_drawable_parasite_attach (GimpDrawable *drawable,
491
			       GimpParasite *parasite)
492
{
493
494
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

jaycox's avatar
jaycox committed
495
496
  /* 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 */
497
  if (gimp_parasite_is_undoable (parasite))
498
    {
499
500
501
      /* do a group in case we have attach_parent set */
      undo_push_group_start (drawable->gimage, PARASITE_ATTACH_UNDO);

502
503
      undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
    }
504
505
506
507
  else if (gimp_parasite_is_persistent (parasite) &&
	   !gimp_parasite_compare (parasite,
				   gimp_drawable_parasite_find
				   (drawable, gimp_parasite_name (parasite))))
508
    undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
509
510

  parasite_list_add (drawable->parasites, parasite);
511
  if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_PARENT))
512
513
    {
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
514
      gimp_image_parasite_attach (drawable->gimage, parasite);
515
    }
516
  else if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_GRANDPARENT))
517
518
519
    {
      parasite_shift_parent (parasite);
      parasite_shift_parent (parasite);
Marc Lehmann's avatar
Marc Lehmann committed
520
      gimp_parasite_attach (parasite);
521
    }
522
  if (gimp_parasite_is_undoable (parasite))
523
524
525
    {
      undo_push_group_end (drawable->gimage);
    }
526
527
528
}

void
Marc Lehmann's avatar
Marc Lehmann committed
529
gimp_drawable_parasite_detach (GimpDrawable *drawable,
530
			       const gchar  *parasite)
531
{
532
  GimpParasite *p;
533

534
535
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

536
  if (!(p = parasite_list_find (drawable->parasites, parasite)))
537
    return;
538

539
  if (gimp_parasite_is_undoable (p))
jaycox's avatar
jaycox committed
540
    undo_push_drawable_parasite_remove (drawable->gimage, drawable,
541
542
					gimp_parasite_name (p));
  else if (gimp_parasite_is_persistent (p))
543
    undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
544
545

  parasite_list_remove (drawable->parasites, parasite);
546
547
}

548
Tattoo
549
gimp_drawable_get_tattoo (const GimpDrawable *drawable)
550
{
551
552
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); 

553
554
  return drawable->tattoo;
}
555

556
void
557
558
gimp_drawable_set_tattoo (GimpDrawable *drawable,
			  Tattoo        val)
559
560
561
562
563
564
{
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  drawable->tattoo = val;
}

565
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
566
gimp_drawable_is_rgb (GimpDrawable *drawable)
567
{
Manish Singh's avatar
Manish Singh committed
568
569
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

570
571
  if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
      gimp_drawable_type (drawable) == RGB_GIMAGE)
572
    return TRUE;
573
  else
574
    return FALSE;
575
576
}

577
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
578
gimp_drawable_is_gray (GimpDrawable *drawable)
579
{
Manish Singh's avatar
Manish Singh committed
580
581
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

582
583
  if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
      gimp_drawable_type (drawable) == GRAY_GIMAGE)
584
    return TRUE;
585
  else
586
    return FALSE;
587
588
}

589
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
590
gimp_drawable_is_indexed (GimpDrawable *drawable)
591
{
Manish Singh's avatar
Manish Singh committed
592
593
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

594
595
  if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
      gimp_drawable_type (drawable) == INDEXED_GIMAGE)
596
    return TRUE;
597
  else
598
    return FALSE;
599
600
601
602
603
}

TileManager *
gimp_drawable_data (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
604
605
606
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  return drawable->tiles;
607
608
609
610
611
612
613
}

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

Manish Singh's avatar
Manish Singh committed
614
615
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

616
617
618
  if (! (gimage = gimp_drawable_gimage (drawable)))
    return NULL;

Manish Singh's avatar
Manish Singh committed
619
620
  return gimage_shadow (gimage, drawable->width, drawable->height, 
			drawable->bytes);
621
622
623
624
625
}

int
gimp_drawable_bytes (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
626
627
628
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->bytes;
629
630
}

631
gint
632
633
gimp_drawable_width (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
634
635
636
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->width;
637
638
}

639
gint
640
641
gimp_drawable_height (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
642
643
644
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->height;
645
646
647
}

void
648
649
650
gimp_drawable_offsets (GimpDrawable *drawable,
		       gint         *off_x,
		       gint         *off_y)
651
{
Manish Singh's avatar
Manish Singh committed
652
653
654
655
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  *off_x = drawable->offset_x;
  *off_y = drawable->offset_y;
656
657
}

658
guchar *
659
660
gimp_drawable_cmap (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
661
  GimpImage *gimage;
662

Manish Singh's avatar
Manish Singh committed
663
664
665
666
667
668
  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;
669
670
671
672
673
}

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

676
677
678
679
680
681
682
  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
}

static void
gimp_drawable_init (GimpDrawable *drawable)
{
683
684
685
686
687
688
689
690
  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
691
692
  drawable->ID            = global_drawable_ID++;
  drawable->tattoo        = 0;
693
694
695
  drawable->gimage        = NULL;
  drawable->type          = -1;
  drawable->has_alpha     = FALSE;
696
  drawable->preview_cache = NULL;
697
  drawable->preview_valid = FALSE;
698
  drawable->parasites     = parasite_list_new ();
Manish Singh's avatar
Manish Singh committed
699
700
  drawable->preview_cache = NULL;
  drawable->preview_valid = FALSE;
701

702
703
  if (gimp_drawable_table == NULL)
    gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
704

Manish Singh's avatar
Manish Singh committed
705
  g_hash_table_insert (gimp_drawable_table,
706
		       GINT_TO_POINTER (drawable->ID),
707
708
709
710
711
712
713
		       (gpointer) drawable);
}

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

715
716
717
718
719
720
721
722
723
724
725
726
  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);

727
  if (drawable->preview_cache)
728
    gimp_preview_cache_invalidate (&drawable->preview_cache);
729

730
  if (drawable->parasites)
731
    gtk_object_unref (GTK_OBJECT (drawable->parasites));
732

733
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
734
    GTK_OBJECT_CLASS (parent_class)->destroy (object);
735
736
737
}

void
738
739
740
741
742
743
gimp_drawable_configure (GimpDrawable  *drawable,
			 GimpImage     *gimage,
			 gint           width,
			 gint           height, 
			 GimpImageType  type,
			 gchar         *name)
744
{
745
  gint     bpp;
746
  gboolean alpha;
747

Manish Singh's avatar
Manish Singh committed
748
749
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

750
  if (!name)
751
    name = _("unnamed");
752
753
754
755

  switch (type)
    {
    case RGB_GIMAGE:
756
      bpp = 3; alpha = FALSE; break;
757
    case GRAY_GIMAGE:
758
      bpp = 1; alpha = FALSE; break;
759
    case RGBA_GIMAGE:
760
      bpp = 4; alpha = TRUE; break;
761
    case GRAYA_GIMAGE:
762
      bpp = 2; alpha = TRUE; break;
763
    case INDEXED_GIMAGE:
764
      bpp = 1; alpha = FALSE; break;
765
    case INDEXEDA_GIMAGE:
766
      bpp = 2; alpha = TRUE; break;
767
    default:
768
      g_message (_("Layer type %d not supported."), type);
769
770
771
      return;
    }

772
773
774
775
776
  drawable->name      = NULL;
  drawable->width     = width;
  drawable->height    = height;
  drawable->bytes     = bpp;
  drawable->type      = type;
777
  drawable->has_alpha = alpha;
778
779
  drawable->offset_x  = 0;
  drawable->offset_y  = 0;
780
781
782
783
784
785

  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
  drawable->tiles = tile_manager_new (width, height, bpp);
  drawable->visible = TRUE;

786
  if (gimage)
787
    gimp_drawable_set_gimage (drawable, gimage);
788

789
  gimp_drawable_set_name (drawable, name);
790

791
  /*  preview variables  */
792
  drawable->preview_cache = NULL;
793
794
  drawable->preview_valid = FALSE;
}