home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gimpdrawable.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  19.7 KB  |  796 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24.  
  25. #include <gtk/gtk.h>
  26.  
  27. #include "gimpdrawableP.h"
  28. #include "gimppreviewcache.h"
  29. #include "gimpsignal.h"
  30. #include "gimage.h"
  31. #include "gimage_mask.h"
  32. #include "gimpparasite.h"
  33. #include "parasitelist.h"
  34. #include "undo.h"
  35.  
  36. #include "libgimp/gimpmath.h"
  37. #include "libgimp/gimpparasite.h"
  38.  
  39. #include "libgimp/gimpintl.h"
  40.  
  41.  
  42. enum
  43. {
  44.   INVALIDATE_PREVIEW,
  45.   LAST_SIGNAL
  46. };
  47.  
  48. static void gimp_drawable_class_init (GimpDrawableClass *klass);
  49. static void gimp_drawable_init         (GimpDrawable      *drawable);
  50. static void gimp_drawable_destroy    (GtkObject        *object);
  51.  
  52. static guint gimp_drawable_signals[LAST_SIGNAL] = { 0 };
  53.  
  54. static GimpDrawableClass *parent_class = NULL;
  55.  
  56.  
  57. GtkType
  58. gimp_drawable_get_type (void)
  59. {
  60.   static GtkType type;
  61.   GIMP_TYPE_INIT (type,
  62.           GimpDrawable,
  63.           GimpDrawableClass,
  64.           gimp_drawable_init,
  65.           gimp_drawable_class_init,
  66.           GIMP_TYPE_OBJECT);
  67.   return type;
  68. }
  69.  
  70. static void
  71. gimp_drawable_class_init (GimpDrawableClass *class)
  72. {
  73.   GtkObjectClass *object_class;
  74.   GtkType type = GIMP_TYPE_DRAWABLE;
  75.  
  76.   object_class = GTK_OBJECT_CLASS (class);
  77.   parent_class = gtk_type_class (GIMP_TYPE_OBJECT);
  78.   
  79.   gimp_drawable_signals[INVALIDATE_PREVIEW] =
  80.       gimp_signal_new ("invalidate_pr", GTK_RUN_LAST, type,
  81.                GTK_SIGNAL_OFFSET(GimpDrawableClass,
  82.                          invalidate_preview),
  83.                gimp_sigtype_void);
  84.  
  85.   gtk_object_class_add_signals (object_class, gimp_drawable_signals, LAST_SIGNAL);
  86.  
  87.   object_class->destroy = gimp_drawable_destroy;
  88. }
  89.  
  90.  
  91. /*
  92.  *  Static variables
  93.  */
  94. static gint        global_drawable_ID  = 1;
  95. static GHashTable *gimp_drawable_table = NULL;
  96.  
  97. /**************************/
  98. /*  Function definitions  */
  99.  
  100. GimpDrawable*
  101. gimp_drawable_get_ID (gint drawable_id)
  102. {
  103.   if (gimp_drawable_table == NULL)
  104.     return NULL;
  105.  
  106.   return (GimpDrawable*) g_hash_table_lookup (gimp_drawable_table, 
  107.                           (gpointer) drawable_id);
  108. }
  109.  
  110. void
  111. gimp_drawable_merge_shadow (GimpDrawable *drawable,
  112.                 gint          undo)
  113. {
  114.   GImage *gimage;
  115.   PixelRegion shadowPR;
  116.   int x1, y1, x2, y2;
  117.  
  118.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  119.  
  120.   gimage = gimp_drawable_gimage (drawable);
  121.   g_return_if_fail (gimage != NULL);
  122.   g_return_if_fail (gimage->shadow != NULL);
  123.  
  124.   /*  A useful optimization here is to limit the update to the
  125.    *  extents of the selection mask, as it cannot extend beyond
  126.    *  them.
  127.    */
  128.   gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  129.   pixel_region_init (&shadowPR, gimage->shadow, x1, y1,
  130.              (x2 - x1), (y2 - y1), FALSE);
  131.   gimage_apply_image (gimage, drawable, &shadowPR, undo, OPAQUE_OPACITY,
  132.               REPLACE_MODE, NULL, x1, y1);
  133. }
  134.  
  135. void
  136. gimp_drawable_fill (GimpDrawable *drawable,
  137.             guchar        r,
  138.             guchar        g,
  139.             guchar        b,
  140.             guchar        a)
  141. {
  142.   GImage *gimage;
  143.   PixelRegion destPR;
  144.   guchar c[MAX_CHANNELS];
  145.   guchar i;
  146.  
  147.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  148.  
  149.   gimage = gimp_drawable_gimage (drawable);
  150.   g_return_if_fail (gimage != NULL);
  151.  
  152.   switch (gimp_drawable_type (drawable))
  153.     {
  154.     case RGB_GIMAGE: case RGBA_GIMAGE:
  155.       c[RED_PIX] = r;
  156.       c[GREEN_PIX] = g;
  157.       c[BLUE_PIX] = b;
  158.       if (gimp_drawable_type (drawable) == RGBA_GIMAGE)
  159.     c[ALPHA_PIX] = a;
  160.       break;
  161.     case GRAY_GIMAGE: case GRAYA_GIMAGE:
  162.       c[GRAY_PIX] = r;
  163.       if (gimp_drawable_type (drawable) == GRAYA_GIMAGE)
  164.     c[ALPHA_G_PIX] = a;
  165.       break;
  166.     case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
  167.       c[RED_PIX] = r;
  168.       c[GREEN_PIX] = g;
  169.       c[BLUE_PIX] = b;
  170.       gimage_transform_color (gimage, drawable, c, &i, RGB);
  171.       c[INDEXED_PIX] = i;
  172.       if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE)
  173.       c[ALPHA_I_PIX] = a;
  174.       break;
  175.     default:
  176.       g_message (_("Can't fill unknown image type."));
  177.       break;
  178.     }
  179.  
  180.   pixel_region_init (&destPR,
  181.              gimp_drawable_data (drawable),
  182.              0, 0,
  183.              gimp_drawable_width  (drawable),
  184.              gimp_drawable_height (drawable),
  185.              TRUE);
  186.   color_region (&destPR, c);
  187.  
  188. }
  189.  
  190. gboolean
  191. gimp_drawable_mask_bounds (GimpDrawable *drawable, 
  192.                gint         *x1,
  193.                gint         *y1,
  194.                gint         *x2,
  195.                gint         *y2)
  196. {
  197.   GimpImage *gimage;
  198.   gint off_x, off_y;
  199.  
  200.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  201.  
  202.   gimage = gimp_drawable_gimage (drawable);
  203.   g_return_val_if_fail (gimage != NULL, FALSE);
  204.  
  205.   if (gimage_mask_bounds (gimage, x1, y1, x2, y2))
  206.     {
  207.       gimp_drawable_offsets (drawable, &off_x, &off_y);
  208.       *x1 = CLAMP (*x1 - off_x, 0, gimp_drawable_width  (drawable));
  209.       *y1 = CLAMP (*y1 - off_y, 0, gimp_drawable_height (drawable));
  210.       *x2 = CLAMP (*x2 - off_x, 0, gimp_drawable_width  (drawable));
  211.       *y2 = CLAMP (*y2 - off_y, 0, gimp_drawable_height (drawable));
  212.       return TRUE;
  213.     }
  214.   else
  215.     {
  216.       *x2 = gimp_drawable_width  (drawable);
  217.       *y2 = gimp_drawable_height (drawable);
  218.       return FALSE;
  219.     }
  220. }
  221.  
  222. void
  223. gimp_drawable_invalidate_preview (GimpDrawable *drawable,
  224.                   gboolean      emit_signal)
  225. {
  226.   GimpImage *gimage;
  227.  
  228.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  229.  
  230.   drawable->preview_valid = FALSE;
  231.  
  232.   if (emit_signal)
  233.     gtk_signal_emit (GTK_OBJECT (drawable),
  234.              gimp_drawable_signals[INVALIDATE_PREVIEW]);
  235.  
  236.   gimage = gimp_drawable_gimage (drawable);
  237.   if (gimage)
  238.     {
  239.       gimage->comp_preview_valid[0] = FALSE;
  240.       gimage->comp_preview_valid[1] = FALSE;
  241.       gimage->comp_preview_valid[2] = FALSE;
  242.     }
  243. }
  244.  
  245.  
  246. GimpImage *
  247. gimp_drawable_gimage (GimpDrawable *drawable)
  248. {
  249.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  250.  
  251.   return drawable->gimage;
  252. }
  253.  
  254. void
  255. gimp_drawable_set_gimage (GimpDrawable *drawable,
  256.               GimpImage    *gimage)
  257. {
  258.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  259.  
  260.   if (gimage == NULL)
  261.     drawable->tattoo = 0;
  262.   else if (drawable->tattoo == 0 || drawable->gimage != gimage )
  263.     drawable->tattoo = gimp_image_get_new_tattoo (gimage);
  264.  
  265.   drawable->gimage = gimage;
  266. }
  267.  
  268. gboolean
  269. gimp_drawable_has_alpha (GimpDrawable *drawable)
  270. {
  271.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  272.  
  273.   return drawable->has_alpha;
  274. }
  275.  
  276. GimpImageType
  277. gimp_drawable_type (GimpDrawable *drawable)
  278. {
  279.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
  280.  
  281.   return drawable->type;
  282. }
  283.  
  284. GimpImageType
  285. gimp_drawable_type_with_alpha (GimpDrawable *drawable)
  286. {
  287.   GimpImageType type;
  288.   gboolean has_alpha;
  289.   
  290.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
  291.  
  292.   type = gimp_drawable_type (drawable);
  293.   has_alpha = gimp_drawable_has_alpha (drawable);
  294.  
  295.   if (has_alpha)
  296.     return type;
  297.   else
  298.     switch (type)
  299.       {
  300.       case RGB_GIMAGE:
  301.     return RGBA_GIMAGE; break;
  302.       case GRAY_GIMAGE:
  303.     return GRAYA_GIMAGE; break;
  304.       case INDEXED_GIMAGE:
  305.     return INDEXEDA_GIMAGE; break;
  306.       default:
  307.       g_assert_not_reached ();
  308.       break;
  309.       }
  310.   return 0;
  311. }
  312.  
  313. gboolean
  314. gimp_drawable_visible (GimpDrawable *drawable)
  315. {
  316.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  317.  
  318.   return drawable->visible;
  319. }
  320.  
  321. gchar *
  322. gimp_drawable_get_name (GimpDrawable *drawable)
  323. {
  324.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  325.  
  326.   return drawable->name;
  327. }
  328.  
  329. void
  330. gimp_drawable_set_name (GimpDrawable *drawable,
  331.             gchar        *name)
  332. {
  333.   GSList       *list, *listb, *base_list;
  334.   GimpDrawable *drawableb;
  335.   gint          number = 1;
  336.   gchar        *newname;
  337.   gchar        *ext;
  338.   gchar         numberbuf[20];
  339.  
  340.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  341.   g_return_if_fail (name != NULL);
  342.  
  343.   if (drawable->name)
  344.     {
  345.       g_free (drawable->name);
  346.       drawable->name = NULL;
  347.     }
  348.  
  349.   if (drawable->gimage == NULL || drawable->gimage->layers == NULL)
  350.     {
  351.       /* no other layers to check name against */
  352.       drawable->name = g_strdup (name);
  353.       return;
  354.     }
  355.  
  356.   if (GIMP_IS_LAYER (drawable))
  357.     base_list = drawable->gimage->layers;
  358.   else if (GIMP_IS_CHANNEL (drawable))
  359.     base_list = drawable->gimage->channels;
  360.   else
  361.     base_list = NULL;
  362.  
  363.   for (list = base_list; list; list = g_slist_next (list))
  364.     {
  365.       drawableb = GIMP_DRAWABLE (list->data);
  366.       if (drawable != drawableb &&
  367.       strcmp (name, gimp_drawable_get_name (drawableb)) == 0)
  368.     { /* names conflict */
  369.       newname = g_malloc (strlen (name) + 10); /* if this aint enough 
  370.                               yer screwed */
  371.       strcpy (newname, name);
  372.       if ((ext = strrchr (newname, '#')))
  373.         {
  374.           number = atoi(ext+1);
  375.           /* Check if there really was the number we think after the # */
  376.           g_snprintf (numberbuf, sizeof (numberbuf), "#%d", number);
  377.           if (strcmp (ext, numberbuf) != 0)
  378.         {
  379.           /* No, so just ignore the # */
  380.           number = 1;
  381.           ext = &newname[strlen (newname)];
  382.         }
  383.         }
  384.       else
  385.         {
  386.           number = 1;
  387.           ext = &newname[strlen (newname)];
  388.         }
  389.       sprintf (ext, "#%d", number + 1);
  390.       listb = base_list;
  391.       while (listb) /* make sure the new name is unique */
  392.         {
  393.           drawableb = GIMP_DRAWABLE (listb->data);
  394.  
  395.           if (drawable != drawableb &&
  396.           strcmp (newname, gimp_drawable_get_name (drawableb)) == 0)
  397.         {
  398.           number++;
  399.           sprintf (ext, "#%d", number+1);
  400.           /* Rescan from beginning */
  401.           listb = base_list;
  402.           continue;
  403.         }
  404.           listb = listb->next;
  405.         }
  406.       drawable->name = g_strdup (newname);
  407.       g_free (newname);
  408.       return;
  409.     }
  410.     }
  411.  
  412.   drawable->name = g_strdup (name);
  413. }
  414.  
  415. guchar *
  416. gimp_drawable_get_color_at (GimpDrawable *drawable,
  417.                 gint          x,
  418.                 gint          y)
  419. {
  420.   Tile   *tile;
  421.   guchar *src;
  422.   guchar *dest;
  423.  
  424.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  425.   g_return_val_if_fail (gimp_drawable_gimage (drawable) ||
  426.             !gimp_drawable_is_indexed (drawable), NULL);
  427.  
  428.   /* do not make this a g_return_if_fail() */
  429.   if ( !(x >= 0 && x < drawable->width && y >= 0 && y < drawable->height))
  430.     return NULL;
  431.  
  432.   dest = g_new (guchar, 5);
  433.  
  434.   tile = tile_manager_get_tile (gimp_drawable_data (drawable), x, y,
  435.                 TRUE, FALSE);
  436.   src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
  437.  
  438.   gimp_image_get_color (gimp_drawable_gimage (drawable),
  439.             gimp_drawable_type (drawable), dest, src);
  440.  
  441.   if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_drawable_type (drawable)))
  442.     dest[3] = src[gimp_drawable_bytes (drawable) - 1];
  443.   else
  444.     dest[3] = 255;
  445.  
  446.   if (gimp_drawable_is_indexed (drawable))
  447.     dest[4] = src[0];
  448.   else
  449.     dest[4] = 0;
  450.  
  451.   tile_release (tile, FALSE);
  452.  
  453.   return dest;
  454. }
  455.  
  456. GimpParasite *
  457. gimp_drawable_parasite_find (const GimpDrawable *drawable,
  458.                  const gchar        *name)
  459. {
  460.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  461.  
  462.   return parasite_list_find (drawable->parasites, name);
  463. }
  464.  
  465. static void
  466. list_func (gchar          *key,
  467.        GimpParasite   *p,
  468.        gchar        ***cur)
  469. {
  470.   *(*cur)++ = (gchar *) g_strdup (key);
  471. }
  472.  
  473. gchar **
  474. gimp_drawable_parasite_list (GimpDrawable *drawable,
  475.                  gint         *count)
  476. {
  477.   gchar **list;
  478.   gchar **cur;
  479.  
  480.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  481.  
  482.   *count = parasite_list_length (drawable->parasites);
  483.   cur = list = g_new (gchar *, *count);
  484.  
  485.   parasite_list_foreach (drawable->parasites, (GHFunc) list_func, &cur);
  486.   
  487.   return list;
  488. }
  489.  
  490. void
  491. gimp_drawable_parasite_attach (GimpDrawable *drawable,
  492.                    GimpParasite *parasite)
  493. {
  494.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  495.  
  496.   /* only set the dirty bit manually if we can be saved and the new
  497.      parasite differs from the current one and we arn't undoable */
  498.   if (gimp_parasite_is_undoable (parasite))
  499.     {
  500.       /* do a group in case we have attach_parent set */
  501.       undo_push_group_start (drawable->gimage, PARASITE_ATTACH_UNDO);
  502.  
  503.       undo_push_drawable_parasite (drawable->gimage, drawable, parasite);
  504.     }
  505.   else if (gimp_parasite_is_persistent (parasite) &&
  506.        !gimp_parasite_compare (parasite,
  507.                    gimp_drawable_parasite_find
  508.                    (drawable, gimp_parasite_name (parasite))))
  509.     undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
  510.  
  511.   parasite_list_add (drawable->parasites, parasite);
  512.   if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_PARENT))
  513.     {
  514.       parasite_shift_parent (parasite);
  515.       gimp_image_parasite_attach (drawable->gimage, parasite);
  516.     }
  517.   else if (gimp_parasite_has_flag (parasite, GIMP_PARASITE_ATTACH_GRANDPARENT))
  518.     {
  519.       parasite_shift_parent (parasite);
  520.       parasite_shift_parent (parasite);
  521.       gimp_parasite_attach (parasite);
  522.     }
  523.   if (gimp_parasite_is_undoable (parasite))
  524.     {
  525.       undo_push_group_end (drawable->gimage);
  526.     }
  527. }
  528.  
  529. void
  530. gimp_drawable_parasite_detach (GimpDrawable *drawable,
  531.                    const gchar  *parasite)
  532. {
  533.   GimpParasite *p;
  534.  
  535.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  536.  
  537.   if (!(p = parasite_list_find (drawable->parasites, parasite)))
  538.     return;
  539.  
  540.   if (gimp_parasite_is_undoable (p))
  541.     undo_push_drawable_parasite_remove (drawable->gimage, drawable,
  542.                     gimp_parasite_name (p));
  543.   else if (gimp_parasite_is_persistent (p))
  544.     undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
  545.  
  546.   parasite_list_remove (drawable->parasites, parasite);
  547. }
  548.  
  549. Tattoo
  550. gimp_drawable_get_tattoo (const GimpDrawable *drawable)
  551. {
  552.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); 
  553.  
  554.   return drawable->tattoo;
  555. }
  556.  
  557. void
  558. gimp_drawable_set_tattoo (GimpDrawable *drawable,
  559.               Tattoo        val)
  560. {
  561.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  562.  
  563.   drawable->tattoo = val;
  564. }
  565.  
  566. gboolean
  567. gimp_drawable_is_rgb (GimpDrawable *drawable)
  568. {
  569.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  570.  
  571.   if (gimp_drawable_type (drawable) == RGBA_GIMAGE ||
  572.       gimp_drawable_type (drawable) == RGB_GIMAGE)
  573.     return TRUE;
  574.   else
  575.     return FALSE;
  576. }
  577.  
  578. gboolean
  579. gimp_drawable_is_gray (GimpDrawable *drawable)
  580. {
  581.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  582.  
  583.   if (gimp_drawable_type (drawable) == GRAYA_GIMAGE ||
  584.       gimp_drawable_type (drawable) == GRAY_GIMAGE)
  585.     return TRUE;
  586.   else
  587.     return FALSE;
  588. }
  589.  
  590. gboolean
  591. gimp_drawable_is_indexed (GimpDrawable *drawable)
  592. {
  593.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  594.  
  595.   if (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE ||
  596.       gimp_drawable_type (drawable) == INDEXED_GIMAGE)
  597.     return TRUE;
  598.   else
  599.     return FALSE;
  600. }
  601.  
  602. TileManager *
  603. gimp_drawable_data (GimpDrawable *drawable)
  604. {
  605.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  606.  
  607.   return drawable->tiles;
  608. }
  609.  
  610. TileManager *
  611. gimp_drawable_shadow (GimpDrawable *drawable)
  612. {
  613.   GImage *gimage;
  614.  
  615.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  616.  
  617.   if (! (gimage = gimp_drawable_gimage (drawable)))
  618.     return NULL;
  619.  
  620.   return gimage_shadow (gimage, drawable->width, drawable->height, 
  621.             drawable->bytes);
  622. }
  623.  
  624. int
  625. gimp_drawable_bytes (GimpDrawable *drawable)
  626. {
  627.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
  628.  
  629.   return drawable->bytes;
  630. }
  631.  
  632. gint
  633. gimp_drawable_width (GimpDrawable *drawable)
  634. {
  635.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
  636.  
  637.   return drawable->width;
  638. }
  639.  
  640. gint
  641. gimp_drawable_height (GimpDrawable *drawable)
  642. {
  643.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
  644.  
  645.   return drawable->height;
  646. }
  647.  
  648. void
  649. gimp_drawable_offsets (GimpDrawable *drawable,
  650.                gint         *off_x,
  651.                gint         *off_y)
  652. {
  653.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  654.  
  655.   *off_x = drawable->offset_x;
  656.   *off_y = drawable->offset_y;
  657. }
  658.  
  659. guchar *
  660. gimp_drawable_cmap (GimpDrawable *drawable)
  661. {
  662.   GimpImage *gimage;
  663.  
  664.   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  665.  
  666.   gimage = gimp_drawable_gimage (drawable);
  667.   g_return_val_if_fail (gimage != NULL, NULL);
  668.  
  669.   return gimage->cmap;
  670. }
  671.  
  672. void
  673. gimp_drawable_deallocate (GimpDrawable *drawable)
  674. {
  675.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  676.  
  677.   if (drawable->tiles)
  678.     tile_manager_destroy (drawable->tiles);
  679. }
  680.  
  681. static void
  682. gimp_drawable_init (GimpDrawable *drawable)
  683. {
  684.   drawable->name          = NULL;
  685.   drawable->tiles         = NULL;
  686.   drawable->visible       = FALSE;
  687.   drawable->width         = 0;
  688.   drawable->height        = 0;
  689.   drawable->offset_x      = 0;
  690.   drawable->offset_y      = 0;
  691.   drawable->bytes         = 0;
  692.   drawable->ID            = global_drawable_ID++;
  693.   drawable->tattoo        = 0;
  694.   drawable->gimage        = NULL;
  695.   drawable->type          = -1;
  696.   drawable->has_alpha     = FALSE;
  697.   drawable->preview_cache = NULL;
  698.   drawable->preview_valid = FALSE;
  699.   drawable->parasites     = parasite_list_new ();
  700.   drawable->preview_cache = NULL;
  701.   drawable->preview_valid = FALSE;
  702.  
  703.   if (gimp_drawable_table == NULL)
  704.     gimp_drawable_table = g_hash_table_new (g_direct_hash, NULL);
  705.  
  706.   g_hash_table_insert (gimp_drawable_table,
  707.                GINT_TO_POINTER (drawable->ID),
  708.                (gpointer) drawable);
  709. }
  710.  
  711. static void
  712. gimp_drawable_destroy (GtkObject *object)
  713. {
  714.   GimpDrawable *drawable;
  715.  
  716.   g_return_if_fail (GIMP_IS_DRAWABLE (object));
  717.  
  718.   drawable = GIMP_DRAWABLE (object);
  719.  
  720.   g_hash_table_remove (gimp_drawable_table, (gpointer) drawable->ID);
  721.   
  722.   if (drawable->name)
  723.     g_free (drawable->name);
  724.  
  725.   if (drawable->tiles)
  726.     tile_manager_destroy (drawable->tiles);
  727.  
  728.   if (drawable->preview_cache)
  729.     gimp_preview_cache_invalidate (&drawable->preview_cache);
  730.  
  731.   if (drawable->parasites)
  732.     gtk_object_unref (GTK_OBJECT (drawable->parasites));
  733.  
  734.   if (GTK_OBJECT_CLASS (parent_class)->destroy)
  735.     GTK_OBJECT_CLASS (parent_class)->destroy (object);
  736. }
  737.  
  738. void
  739. gimp_drawable_configure (GimpDrawable  *drawable,
  740.              GimpImage     *gimage,
  741.              gint           width,
  742.              gint           height, 
  743.              GimpImageType  type,
  744.              gchar         *name)
  745. {
  746.   gint     bpp;
  747.   gboolean alpha;
  748.  
  749.   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  750.  
  751.   if (!name)
  752.     name = _("unnamed");
  753.  
  754.   switch (type)
  755.     {
  756.     case RGB_GIMAGE:
  757.       bpp = 3; alpha = FALSE; break;
  758.     case GRAY_GIMAGE:
  759.       bpp = 1; alpha = FALSE; break;
  760.     case RGBA_GIMAGE:
  761.       bpp = 4; alpha = TRUE; break;
  762.     case GRAYA_GIMAGE:
  763.       bpp = 2; alpha = TRUE; break;
  764.     case INDEXED_GIMAGE:
  765.       bpp = 1; alpha = FALSE; break;
  766.     case INDEXEDA_GIMAGE:
  767.       bpp = 2; alpha = TRUE; break;
  768.     default:
  769.       g_message (_("Layer type %d not supported."), type);
  770.       return;
  771.     }
  772.  
  773.   drawable->name      = NULL;
  774.   drawable->width     = width;
  775.   drawable->height    = height;
  776.   drawable->bytes     = bpp;
  777.   drawable->type      = type;
  778.   drawable->has_alpha = alpha;
  779.   drawable->offset_x  = 0;
  780.   drawable->offset_y  = 0;
  781.  
  782.   if (drawable->tiles)
  783.     tile_manager_destroy (drawable->tiles);
  784.   drawable->tiles = tile_manager_new (width, height, bpp);
  785.   drawable->visible = TRUE;
  786.  
  787.   if (gimage)
  788.     gimp_drawable_set_gimage (drawable, gimage);
  789.  
  790.   gimp_drawable_set_name (drawable, name);
  791.  
  792.   /*  preview variables  */
  793.   drawable->preview_cache = NULL;
  794.   drawable->preview_valid = FALSE;
  795. }
  796.