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.
 */
18
19
#include "config.h"

20
#include <stdlib.h>
21
#include <string.h>
22

23
24
25
26
#include "gimpdrawableP.h"
#include "gimpsignal.h"
#include "gimage.h"
#include "gimage_mask.h"
Manish Singh's avatar
Manish Singh committed
27
#include "gimpparasite.h"
28
#include "parasitelist.h"
29
#include "undo.h"
30

31
#include "libgimp/gimpmath.h"
32
#include "libgimp/gimpparasite.h"
33

34
#include "libgimp/gimpintl.h"
35

36
37
38

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

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

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

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

GimpDrawable*
96
gimp_drawable_get_ID (gint drawable_id)
97
98
99
100
101
102
103
104
105
{
  if (gimp_drawable_table == NULL)
    return NULL;

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

void
106
107
gimp_drawable_merge_shadow (GimpDrawable *drawable,
			    gint          undo)
108
109
110
111
112
{
  GImage *gimage;
  PixelRegion shadowPR;
  int x1, y1, x2, y2;

Manish Singh's avatar
Manish Singh committed
113
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
114

Manish Singh's avatar
Manish Singh committed
115
116
117
  gimage = gimp_drawable_gimage (drawable);
  g_return_if_fail (gimage != NULL);
  g_return_if_fail (gimage->shadow != NULL);
118

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

Manish Singh's avatar
Manish Singh committed
142
143
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

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

  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:
171
      g_message (_("Can't fill unknown image type."));
172
173
174
175
176
177
      break;
    }

  pixel_region_init (&destPR,
		     gimp_drawable_data (drawable),
		     0, 0,
178
		     gimp_drawable_width  (drawable),
179
180
181
182
183
184
		     gimp_drawable_height (drawable),
		     TRUE);
  color_region (&destPR, c);

}

185
gboolean
186
gimp_drawable_mask_bounds (GimpDrawable *drawable, 
187
188
189
190
			   gint         *x1,
			   gint         *y1,
			   gint         *x2,
			   gint         *y2)
191
{
Manish Singh's avatar
Manish Singh committed
192
  GimpImage *gimage;
193
  gint off_x, off_y;
194

Manish Singh's avatar
Manish Singh committed
195
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
196

Manish Singh's avatar
Manish Singh committed
197
198
  gimage = gimp_drawable_gimage (drawable);
  g_return_val_if_fail (gimage != NULL, FALSE);
199
200
201
202

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

void
218
219
gimp_drawable_invalidate_preview (GimpDrawable *drawable,
				  gboolean      emit_signal)
220
{
Manish Singh's avatar
Manish Singh committed
221
  GimpImage *gimage;
222

Manish Singh's avatar
Manish Singh committed
223
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
224
225

  drawable->preview_valid = FALSE;
226
227
228
229
230

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

231
232
233
234
235
236
237
238
239
240
241
242
243
  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
244
245
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

246
247
248
  return drawable->gimage;
}

249
void
250
251
gimp_drawable_set_gimage (GimpDrawable *drawable,
			  GimpImage    *gimage)
252
{
Manish Singh's avatar
Manish Singh committed
253
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
254

255
256
  if (gimage == NULL)
    drawable->tattoo = 0;
257
  else if (drawable->tattoo == 0 || drawable->gimage != gimage )
258
259
    drawable->tattoo = gimp_image_get_new_tattoo (gimage);

260
  drawable->gimage = gimage;
261
262
}

263
264
265
gboolean
gimp_drawable_has_alpha (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
266
267
268
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

  return drawable->has_alpha;
269
}
270

271
GimpImageType
272
273
gimp_drawable_type (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
274
275
276
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->type;
277
278
}

279
280
GimpImageType
gimp_drawable_type_with_alpha (GimpDrawable *drawable)
281
{
282
283
284
  GimpImageType type;
  gboolean has_alpha;
  
Manish Singh's avatar
Manish Singh committed
285
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
286

287
288
  type = gimp_drawable_type (drawable);
  has_alpha = gimp_drawable_has_alpha (drawable);
289
290
291

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

308
gboolean
309
310
gimp_drawable_visible (GimpDrawable *drawable)
{
311
312
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

313
314
315
  return drawable->visible;
}

316
gchar *
317
gimp_drawable_get_name (GimpDrawable *drawable)
318
{
319
320
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

321
322
323
  return drawable->name;
}

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

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
336
  g_return_if_fail (name != NULL);
337
338

  if (drawable->name)
339
340
341
342
343
    {
      g_free (drawable->name);
      drawable->name = NULL;
    }

344
  if (drawable->gimage == NULL || drawable->gimage->layers == NULL)
345
346
347
348
349
350
351
    {
      /* no other layers to check name against */
      drawable->name = g_strdup (name);
      return;
    }

  if (GIMP_IS_LAYER (drawable))
352
    base_list = drawable->gimage->layers;
353
  else if (GIMP_IS_CHANNEL (drawable))
354
355
356
357
    base_list = drawable->gimage->channels;
  else
    base_list = NULL;

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

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

407
  drawable->name = g_strdup (name);
408
409
}

410
411
412
413
guchar *
gimp_drawable_get_color_at (GimpDrawable *drawable,
			    gint          x,
			    gint          y)
414
{
415
  Tile   *tile;
416
417
  guchar *src;
  guchar *dest;
418

Manish Singh's avatar
Manish Singh committed
419
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
420
421
  g_return_val_if_fail (gimp_drawable_gimage (drawable) ||
			!gimp_drawable_is_indexed (drawable), NULL);
422
423
424
425

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

427
  dest = g_new (guchar, 5);
Manish Singh's avatar
Manish Singh committed
428

429
430
431
  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
432

433
  gimp_image_get_color (gimp_drawable_gimage (drawable),
434
			gimp_drawable_type (drawable), dest, src);
Manish Singh's avatar
Manish Singh committed
435
436

  if (TYPE_HAS_ALPHA (gimp_drawable_type (drawable)))
437
438
439
    dest[3] = src[gimp_drawable_bytes (drawable) - 1];
  else
    dest[3] = 255;
Manish Singh's avatar
Manish Singh committed
440

Marc Lehmann's avatar
Marc Lehmann committed
441
  if (gimp_drawable_is_indexed (drawable))
442
443
444
    dest[4] = src[0];
  else
    dest[4] = 0;
Manish Singh's avatar
Manish Singh committed
445

446
  tile_release (tile, FALSE);
Manish Singh's avatar
Manish Singh committed
447

448
449
450
  return dest;
}

451
GimpParasite *
Marc Lehmann's avatar
Marc Lehmann committed
452
gimp_drawable_parasite_find (const GimpDrawable *drawable,
453
			     const gchar        *name)
454
{
455
456
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

457
  return parasite_list_find (drawable->parasites, name);
458
459
}

460
static void
461
462
463
list_func (gchar          *key,
	   GimpParasite   *p,
	   gchar        ***cur)
Marc Lehmann's avatar
Marc Lehmann committed
464
{
465
  *(*cur)++ = (gchar *) g_strdup (key);
Marc Lehmann's avatar
Marc Lehmann committed
466
467
}

468
469
470
gchar **
gimp_drawable_parasite_list (GimpDrawable *drawable,
			     gint         *count)
Marc Lehmann's avatar
Marc Lehmann committed
471
{
472
473
474
475
  gchar **list;
  gchar **cur;

  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
Marc Lehmann's avatar
Marc Lehmann committed
476
477

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

480
  parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
Marc Lehmann's avatar
Marc Lehmann committed
481
482
483
484
  
  return list;
}

485
void
Marc Lehmann's avatar
Marc Lehmann committed
486
gimp_drawable_parasite_attach (GimpDrawable *drawable,
487
			       GimpParasite *parasite)
488
{
489
490
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

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

498
499
      undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
    }
500
501
502
503
  else if (gimp_parasite_is_persistent (parasite) &&
	   !gimp_parasite_compare (parasite,
				   gimp_drawable_parasite_find
				   (drawable, gimp_parasite_name (parasite))))
504
    undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
505
506

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

void
Marc Lehmann's avatar
Marc Lehmann committed
525
gimp_drawable_parasite_detach (GimpDrawable *drawable,
526
			       const gchar  *parasite)
527
{
528
  GimpParasite *p;
529

530
531
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

532
  if (!(p = parasite_list_find (drawable->parasites, parasite)))
533
    return;
534

535
  if (gimp_parasite_is_undoable (p))
jaycox's avatar
jaycox committed
536
    undo_push_drawable_parasite_remove (drawable->gimage, drawable,
537
538
					gimp_parasite_name (p));
  else if (gimp_parasite_is_persistent (p))
539
    undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
540
541

  parasite_list_remove (drawable->parasites, parasite);
542
543
}

544
Tattoo
545
gimp_drawable_get_tattoo (const GimpDrawable *drawable)
546
{
547
548
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); 

549
550
  return drawable->tattoo;
}
551

552
void
553
554
gimp_drawable_set_tattoo (GimpDrawable *drawable,
			  Tattoo        val)
555
556
557
558
559
560
{
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  drawable->tattoo = val;
}

561
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
562
gimp_drawable_is_rgb (GimpDrawable *drawable)
563
{
Manish Singh's avatar
Manish Singh committed
564
565
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

566
567
  if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
      gimp_drawable_type (drawable) == RGB_GIMAGE)
568
    return TRUE;
569
  else
570
    return FALSE;
571
572
}

573
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
574
gimp_drawable_is_gray (GimpDrawable *drawable)
575
{
Manish Singh's avatar
Manish Singh committed
576
577
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

578
579
  if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
      gimp_drawable_type (drawable) == GRAY_GIMAGE)
580
    return TRUE;
581
  else
582
    return FALSE;
583
584
}

585
gboolean
Marc Lehmann's avatar
Marc Lehmann committed
586
gimp_drawable_is_indexed (GimpDrawable *drawable)
587
{
Manish Singh's avatar
Manish Singh committed
588
589
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);

590
591
  if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
      gimp_drawable_type (drawable) == INDEXED_GIMAGE)
592
    return TRUE;
593
  else
594
    return FALSE;
595
596
597
598
599
}

TileManager *
gimp_drawable_data (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
600
601
602
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  return drawable->tiles;
603
604
605
606
607
608
609
}

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

Manish Singh's avatar
Manish Singh committed
610
611
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

612
613
614
  if (! (gimage = gimp_drawable_gimage (drawable)))
    return NULL;

Manish Singh's avatar
Manish Singh committed
615
616
  return gimage_shadow (gimage, drawable->width, drawable->height, 
			drawable->bytes);
617
618
619
620
621
}

int
gimp_drawable_bytes (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
622
623
624
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->bytes;
625
626
}

627
gint
628
629
gimp_drawable_width (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
630
631
632
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->width;
633
634
}

635
gint
636
637
gimp_drawable_height (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
638
639
640
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);

  return drawable->height;
641
642
643
}

void
644
645
646
gimp_drawable_offsets (GimpDrawable *drawable,
		       gint         *off_x,
		       gint         *off_y)
647
{
Manish Singh's avatar
Manish Singh committed
648
649
650
651
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

  *off_x = drawable->offset_x;
  *off_y = drawable->offset_y;
652
653
}

654
guchar *
655
656
gimp_drawable_cmap (GimpDrawable *drawable)
{
Manish Singh's avatar
Manish Singh committed
657
  GimpImage *gimage;
658

Manish Singh's avatar
Manish Singh committed
659
660
661
662
663
664
  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;
665
666
667
668
669
}

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

672
673
674
675
676
677
678
  if (drawable->tiles)
    tile_manager_destroy (drawable->tiles);
}

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

698
699
  if (gimp_drawable_table == NULL)
    gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
700

Manish Singh's avatar
Manish Singh committed
701
  g_hash_table_insert (gimp_drawable_table,
702
		       GINT_TO_POINTER (drawable->ID),
703
704
705
706
707
708
709
		       (gpointer) drawable);
}

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

711
712
713
714
715
716
717
718
719
720
721
722
  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);

723
  if (drawable->preview_cache)
724
    gimp_preview_cache_invalidate (&drawable->preview_cache);
725

726
  if (drawable->parasites)
727
    gtk_object_unref (GTK_OBJECT (drawable->parasites));
728

729
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
730
    GTK_OBJECT_CLASS (parent_class)->destroy (object);
731
732
733
}

void
734
735
736
737
738
739
gimp_drawable_configure (GimpDrawable  *drawable,
			 GimpImage     *gimage,
			 gint           width,
			 gint           height, 
			 GimpImageType  type,
			 gchar         *name)
740
{
741
  gint     bpp;
742
  gboolean alpha;
743

Manish Singh's avatar
Manish Singh committed
744
745
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));

746
  if (!name)
747
    name = _("unnamed");
748
749
750
751

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

768
769
770
771
772
  drawable->name      = NULL;
  drawable->width     = width;
  drawable->height    = height;
  drawable->bytes     = bpp;
  drawable->type      = type;
773
  drawable->has_alpha = alpha;
774
775
  drawable->offset_x  = 0;
  drawable->offset_y  = 0;
776
777
778
779
780
781

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

782
  if (gimage)
783
    gimp_drawable_set_gimage (drawable, gimage);
784

785
  gimp_drawable_set_name (drawable, name);
786

787
  /*  preview variables  */
788
  drawable->preview_cache = NULL;
789
790
  drawable->preview_valid = FALSE;
}