home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / rotate.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-01  |  19.2 KB  |  652 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  *  Rotate plug-in v1.0
  5.  *  Copyright 1997-2000 by Sven Neumann <sven@gimp.org> 
  6.  *                       & Adam D. Moss <adam@gimp.org>
  7.  * 
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  */
  22.  
  23. /* Revision history
  24.  *  (09/28/97)  v0.1   first development release 
  25.  *  (09/29/97)  v0.2   nicer dialog,
  26.  *                     changed the menu-location to Filters/Transforms
  27.  *  (10/01/97)  v0.3   now handles layered images and undo
  28.  *  (10/13/97)  v0.3a  small bugfix, no real changes
  29.  *  (10/17/97)  v0.4   now handles selections
  30.  *  (01/09/98)  v0.5   a few fixes to support portability
  31.  *  (01/15/98)  v0.6   fixed a line that caused rotate to crash on some 
  32.  *                     systems               
  33.  *  (05/28/98)  v0.7   use the new gimp_message function for error output
  34.  *  (10/09/99)  v0.8   rotate guides too
  35.  *  (11/13/99)  v0.9   merge rotators and rotate plug-ins 
  36.  *                     -> drop the dialog, register directly into menus instead
  37.  *  (06/18/00)  v1.0   speed up 180░ rotations, 
  38.  *                     declare version 1.0 for gimp-1.2 release
  39.  */
  40.  
  41. /* TODO List
  42.  *  - handle channels and masks
  43.  *  - rewrite the main function to make it work on tiles rather than
  44.  *    process the image row by row. This should result in a significant
  45.  *    speedup (thanks to quartic for this suggestion). 
  46.  *  - do something magical so that only one rotate can be occuring at a time!
  47.  */  
  48.  
  49. #include "config.h"
  50.  
  51. #include <stdlib.h>
  52. #include <string.h>
  53.  
  54. #include <libgimp/gimp.h>
  55.  
  56. #include "libgimp/stdplugins-intl.h"
  57.  
  58.  
  59. /* Defines */
  60. #define PLUG_IN_VERSION     "v1.0 (2000/06/18)"
  61. #define PLUG_IN_IMAGE_TYPES "RGB*, INDEXED*, GRAY*"
  62. #define PLUG_IN_AUTHOR      "Sven Neumann <sven@gimp.org>, Adam D. Moss <adam@gimp.org>"
  63. #define PLUG_IN_COPYRIGHT   "Sven Neumann, Adam D. Moss"
  64.  
  65.  
  66. typedef struct 
  67. {
  68.   gint angle;
  69.   gint everything;
  70. } RotateValues;
  71.  
  72. typedef struct 
  73. {
  74.   gint32 ID;
  75.   gint32 orientation;
  76.   gint32 position;
  77. } GuideInfo;
  78.  
  79. static RotateValues rotvals = 
  80.   1,        /* default to 90 degrees */
  81.   1         /* default to whole image */
  82. };
  83.  
  84.  
  85. static void  query   (void);
  86. static void  run     (gchar      *name,
  87.               gint        nparams,    
  88.               GimpParam  *param,    
  89.               gint       *nreturn_vals,  
  90.               GimpParam **return_vals);
  91.  
  92. static void  rotate                 (void);
  93. static void  rotate_drawable        (GimpDrawable *drawable);
  94. static void  rotate_compute_offsets (gint         *offsetx, 
  95.                      gint         *offsety, 
  96.                      gint          image_width, 
  97.                      gint          image_height,
  98.                      gint          width, 
  99.                      gint          height);
  100.  
  101. /* Global Variables */
  102. GimpPlugInInfo PLUG_IN_INFO =
  103. {
  104.   NULL,  /* init_proc  */
  105.   NULL,     /* quit_proc  */
  106.   query, /* query_proc */
  107.   run    /* run_proc   */
  108. };
  109.  
  110. /* the image and drawable that will be used later */
  111. static GimpDrawable *active_drawable = NULL;
  112. static gint32        image_ID = -1;
  113.  
  114. /* Functions */
  115.  
  116. MAIN ()
  117.  
  118. static void
  119. query (void)
  120. {
  121.   static GimpParamDef args[] =
  122.   {
  123.     { GIMP_PDB_INT32,    "run_mode",   "Interactive, non-interactive"},
  124.     { GIMP_PDB_IMAGE,    "image",      "Input image" },
  125.     { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable" },
  126.     { GIMP_PDB_INT32,    "angle",      "Angle { 90 (1), 180 (2), 270 (3) } degrees" },
  127.     { GIMP_PDB_INT32,    "everything", "Rotate the whole image? { TRUE, FALSE }" }
  128.   };
  129.   static gint nargs = sizeof (args) / sizeof (args[0]);
  130.  
  131.   static GimpParamDef menuargs[] =
  132.   {
  133.     { GIMP_PDB_INT32,    "run_mode",   "Interactive, non-interactive" },
  134.     { GIMP_PDB_IMAGE,    "image",      "Input image" },
  135.     { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable"}
  136.   };
  137.   static gint nmenuargs = sizeof (menuargs) / sizeof (menuargs[0]);
  138.  
  139.   gimp_install_procedure ("plug_in_rotate",
  140.               "Rotates a layer or the whole image by 90, 180 or 270 degrees",
  141.               "This plug-in does rotate the active layer or the "
  142.               "whole image clockwise by multiples of 90 degrees. "
  143.               "When the whole image is choosen, the image is "
  144.               "resized if necessary.",
  145.               PLUG_IN_AUTHOR,
  146.               PLUG_IN_COPYRIGHT,
  147.               PLUG_IN_VERSION,
  148.               NULL,
  149.               PLUG_IN_IMAGE_TYPES,
  150.               GIMP_PLUGIN,        
  151.               nargs, 0,
  152.               args, NULL);
  153.  
  154.   gimp_install_procedure ("plug_in_layer_rot90",
  155.               "Rotates the given layer 90 degrees clockwise.",
  156.               "Rotates the given layer 90 degrees clockwise.",
  157.               PLUG_IN_AUTHOR,
  158.               PLUG_IN_COPYRIGHT,
  159.               PLUG_IN_VERSION,
  160.               N_("<Image>/Layers/Rotate/90 degrees"),
  161.               PLUG_IN_IMAGE_TYPES,
  162.               GIMP_PLUGIN,
  163.               nmenuargs, 0,
  164.               menuargs, NULL);
  165.   gimp_install_procedure ("plug_in_layer_rot180",
  166.               "Rotates the given layer 180 degrees.",
  167.               "Rotates the given layer 180 degrees.",
  168.               PLUG_IN_AUTHOR,
  169.               PLUG_IN_COPYRIGHT,
  170.               PLUG_IN_VERSION,
  171.               N_("<Image>/Layers/Rotate/180 degrees"),
  172.               PLUG_IN_IMAGE_TYPES,
  173.               GIMP_PLUGIN,
  174.               nmenuargs, 0,
  175.               menuargs, NULL);
  176.   gimp_install_procedure ("plug_in_layer_rot270",
  177.               "Rotates the given layer 270 degrees clockwise.",
  178.               "Rotates the given layer 270 degrees clockwise.",
  179.               PLUG_IN_AUTHOR,
  180.               PLUG_IN_COPYRIGHT,
  181.               PLUG_IN_VERSION,
  182.               N_("<Image>/Layers/Rotate/270 degrees"),
  183.               PLUG_IN_IMAGE_TYPES,
  184.               GIMP_PLUGIN,
  185.               nmenuargs, 0,
  186.               menuargs, NULL);
  187.  
  188.   gimp_install_procedure ("plug_in_image_rot90",
  189.               "Rotates the given image 90 degrees clockwise.",
  190.               "Rotates the given image 90 degrees clockwise.",
  191.               PLUG_IN_AUTHOR,
  192.               PLUG_IN_COPYRIGHT,
  193.               PLUG_IN_VERSION,
  194.               N_("<Image>/Image/Transforms/Rotate/90 degrees"),
  195.               PLUG_IN_IMAGE_TYPES,
  196.               GIMP_PLUGIN,
  197.               nmenuargs, 0,
  198.               menuargs, NULL);
  199.   gimp_install_procedure ("plug_in_image_rot180",
  200.               "Rotates the given image 180 degrees.",
  201.               "Rotates the given image 180 degrees.",
  202.               PLUG_IN_AUTHOR,
  203.               PLUG_IN_COPYRIGHT,
  204.               PLUG_IN_VERSION,
  205.               N_("<Image>/Image/Transforms/Rotate/180 degrees"),
  206.               PLUG_IN_IMAGE_TYPES,
  207.               GIMP_PLUGIN,
  208.               nmenuargs, 0,
  209.               menuargs, NULL);
  210.   gimp_install_procedure ("plug_in_image_rot270",
  211.               "Rotates the given image 270 degrees clockwise.",
  212.               "Rotates the given image 270 degrees clockwise.",
  213.               PLUG_IN_AUTHOR,
  214.               PLUG_IN_COPYRIGHT,
  215.               PLUG_IN_VERSION,
  216.               N_("<Image>/Image/Transforms/Rotate/270 degrees"),
  217.               PLUG_IN_IMAGE_TYPES,
  218.               GIMP_PLUGIN,
  219.               nmenuargs, 0,
  220.               menuargs, NULL);
  221. }
  222.  
  223. static void 
  224. run (gchar      *name,
  225.      gint        nparams,
  226.      GimpParam  *param,
  227.      gint       *nreturn_vals,
  228.      GimpParam **return_vals)
  229. {
  230.   /* Get the runmode from the in-parameters */
  231.   GimpRunModeType run_mode = param[0].data.d_int32;    
  232.   
  233.   /* status variable, use it to check for errors in invocation usualy only 
  234.      during non-interactive calling */    
  235.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;     
  236.   
  237.   /*always return at least the status to the caller. */
  238.   static GimpParam values[1];
  239.   
  240.   /* initialize the return of the status */     
  241.   values[0].type = GIMP_PDB_STATUS;
  242.   values[0].data.d_status = status;
  243.   *nreturn_vals = 1;
  244.   *return_vals = values;
  245.  
  246.   INIT_I18N (); 
  247.  
  248.   /* get image and drawable */
  249.   image_ID = param[1].data.d_int32;
  250.   active_drawable = gimp_drawable_get (param[2].data.d_drawable);
  251.   
  252.   /* Check the procedure name we were called with, to decide
  253.      what needs to be done. */
  254.   if (strcmp (name, "plug_in_rotate") == 0)
  255.     {
  256.       switch (run_mode)
  257.     {
  258.     case GIMP_RUN_INTERACTIVE:
  259.     case GIMP_RUN_NONINTERACTIVE:
  260.       /* check to see if invoked with the correct number of parameters */
  261.       if (nparams == 5)
  262.         {
  263.           rotvals.angle = (gint) param[3].data.d_int32;
  264.           rotvals.angle = rotvals.angle % 4;
  265.           rotvals.everything = (gint) param[4].data.d_int32;
  266.           /* Store variable states for next run */
  267.           gimp_set_data ("plug_in_rotate", &rotvals, sizeof (RotateValues));
  268.         }
  269.       else
  270.         status = GIMP_PDB_CALLING_ERROR;
  271.       break;
  272.     case GIMP_RUN_WITH_LAST_VALS:
  273.       /* Possibly retrieve data from a previous run */
  274.       gimp_get_data ("plug_in_rotate", &rotvals);
  275.       rotvals.angle = rotvals.angle % 4;
  276.       break;
  277.     default:
  278.       break;
  279.     }
  280.     }
  281.   else if (strcmp (name, "plug_in_layer_rot90") == 0)
  282.     {
  283.       rotvals.angle      = 1;
  284.       rotvals.everything = FALSE;
  285.     }
  286.   else if (strcmp (name, "plug_in_layer_rot180") == 0)
  287.     {
  288.       rotvals.angle      = 2;
  289.       rotvals.everything = FALSE;
  290.     }
  291.   else if (strcmp (name, "plug_in_layer_rot270") == 0)
  292.     {
  293.       rotvals.angle      = 3;
  294.       rotvals.everything = FALSE;
  295.     }
  296.   else if (strcmp (name, "plug_in_image_rot90") == 0)
  297.     {
  298.       rotvals.angle      = 1;
  299.       rotvals.everything = TRUE;
  300.     }
  301.   else if (strcmp (name, "plug_in_image_rot180") == 0)
  302.     {
  303.       rotvals.angle      = 2;
  304.       rotvals.everything = TRUE;
  305.     }
  306.   else if (strcmp (name, "plug_in_image_rot270") == 0)
  307.     {
  308.       rotvals.angle      = 3;
  309.       rotvals.everything = TRUE;
  310.     }
  311.   else 
  312.     status = GIMP_PDB_CALLING_ERROR;
  313.  
  314.   if (status == GIMP_PDB_SUCCESS)
  315.     {
  316.       /* Run the main function */
  317.       rotate ();
  318.       
  319.       /* If run mode is interactive, flush displays, else (script) don't 
  320.      do it, as the screen updates would make the scripts slow */
  321.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  322.     gimp_displays_flush ();
  323.     }
  324.  
  325.   values[0].data.d_status = status; 
  326. }
  327.  
  328. static void
  329. rotate_compute_offsets (gint *offsetx,
  330.             gint *offsety,
  331.             gint  image_width, 
  332.             gint  image_height,
  333.             gint  width, 
  334.             gint  height)
  335. {
  336.   gint buffer;
  337.  
  338.   if (rotvals.everything)  /* rotate around the image center */
  339.     {
  340.       switch ( rotvals.angle )
  341.     {
  342.     case 1:   /* 90░ */
  343.       buffer   = *offsetx;
  344.       *offsetx = image_height - *offsety - height;
  345.       *offsety = buffer;
  346.       break;
  347.     case 2:   /* 180░ */
  348.       *offsetx = image_width - *offsetx - width;
  349.       *offsety = image_height - *offsety - height;
  350.       break;
  351.     case 3:   /* 270░ */
  352.       buffer   = *offsetx;
  353.       *offsetx = *offsety;
  354.       *offsety = image_width - buffer - width;
  355.     }
  356.     }
  357.   else  /* rotate around the drawable center */
  358.     {
  359.       if (rotvals.angle != 2)
  360.     {
  361.       *offsetx = *offsetx + (width-height)/2 ;
  362.       *offsety = *offsety + (height-width)/2 ;
  363.     }
  364.     }
  365.   return;
  366. }
  367.  
  368.  
  369. static void
  370. rotate_drawable (GimpDrawable *drawable)
  371. {
  372.   GimpPixelRgn  srcPR, destPR;
  373.   gint          width, height;
  374.   gint          longside;
  375.   gint          bytes;
  376.   gint          row, col;
  377.   gint          offsetx, offsety;
  378.   gboolean      was_preserve_transparency = FALSE;
  379.   guchar       *buffer;
  380.   guchar       *src_row, *dest_row;
  381.  
  382.   /* initialize */
  383.  
  384.   row = 0;
  385.  
  386.   /* Get the size of the input drawable. */
  387.   width = drawable->width;
  388.   height = drawable->height;
  389.   bytes = drawable->bpp;
  390.  
  391.   if (gimp_layer_get_preserve_transparency (drawable->id))
  392.     {
  393.     was_preserve_transparency = TRUE;
  394.     gimp_layer_set_preserve_transparency (drawable->id, FALSE);
  395.     }
  396.  
  397.   if (rotvals.angle == 2)  /* we're rotating by 180░ */
  398.     {
  399.       gimp_tile_cache_ntiles (2 * (width / gimp_tile_width() + 1));
  400.  
  401.       gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, 
  402.                FALSE, FALSE);
  403.       gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height,
  404.                TRUE, TRUE);
  405.       
  406.       src_row  = (guchar *) g_malloc (width * bytes);
  407.       dest_row = (guchar *) g_malloc (width * bytes);
  408.       
  409.       for (row = 0; row < height; row++)
  410.     {
  411.       gimp_pixel_rgn_get_row (&srcPR, src_row, 0, row, width); 
  412.       for (col = 0; col < width; col++) 
  413.         { 
  414.           memcpy (dest_row + col * bytes, 
  415.               src_row + (width - 1 - col) * bytes,
  416.               bytes);
  417.         }         
  418.       gimp_pixel_rgn_set_row (&destPR, dest_row, 0, (height - row - 1), 
  419.                   width);
  420.       
  421.       if ((row % 5) == 0)
  422.         gimp_progress_update ((double) row / (double) height);
  423.     }
  424.  
  425.       g_free (src_row);
  426.       g_free (dest_row);
  427.  
  428.       gimp_drawable_flush (drawable); 
  429.       gimp_drawable_merge_shadow (drawable->id, TRUE); 
  430.       gimp_drawable_update (drawable->id, 0, 0, width, height); 
  431.  
  432.     }
  433.   else                     /* we're rotating by 90░ or 270░ */
  434.     {  
  435.       (width > height) ? (longside = width) : (longside = height);
  436.  
  437.       gimp_layer_resize (drawable->id, longside, longside, 0, 0);
  438.       drawable = gimp_drawable_get (drawable->id);
  439.       gimp_drawable_flush (drawable);
  440.       
  441.       gimp_tile_cache_ntiles ( (longside / gimp_tile_width () + 1) + 
  442.                    (longside / gimp_tile_height () + 1) );
  443.  
  444.       gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, longside, longside, 
  445.                FALSE, FALSE);
  446.       gimp_pixel_rgn_init (&destPR, drawable, 0, 0, longside, longside,
  447.                TRUE, TRUE);
  448.       
  449.       buffer = g_malloc (longside * bytes);
  450.       
  451.       if (rotvals.angle == 1)     /* we're rotating by 90░ */
  452.     {
  453.       for (row = 0; row < height; row++)
  454.         {
  455.           gimp_pixel_rgn_get_row (&srcPR, buffer, 0, row, width); 
  456.           gimp_pixel_rgn_set_col (&destPR, buffer, (height - row - 1), 0,
  457.                       width);
  458.  
  459.           if ((row % 5) == 0)
  460.         gimp_progress_update ((double) row / (double) height);
  461.         }
  462.     }
  463.       else                        /* we're rotating by 270░ */
  464.     {
  465.       for (col = 0; col < width; col++)
  466.         {
  467.           gimp_pixel_rgn_get_col (&srcPR, buffer, col, 0, height); 
  468.           gimp_pixel_rgn_set_row (&destPR, buffer, 0, (width - col - 1), 
  469.                       height);
  470.  
  471.           if ((col % 5) == 0)
  472.         gimp_progress_update ((double) col / (double) width);
  473.         }
  474.     }
  475.  
  476.       g_free (buffer);
  477.  
  478.       gimp_progress_update ( 1.0 );
  479.  
  480.       gimp_drawable_flush (drawable); 
  481.       gimp_drawable_merge_shadow (drawable->id, TRUE);
  482.       gimp_drawable_update (drawable->id, 0, 0, height, width); 
  483.  
  484.       gimp_layer_resize (drawable->id, height, width, 0, 0);
  485.       drawable = gimp_drawable_get (drawable->id);
  486.       gimp_drawable_flush (drawable);
  487.       gimp_drawable_update (drawable->id, 0, 0, height, width);
  488.     }
  489.  
  490.   gimp_drawable_offsets (drawable->id, &offsetx, &offsety);
  491.   rotate_compute_offsets (&offsetx, &offsety, 
  492.               gimp_image_width (image_ID),
  493.               gimp_image_height (image_ID), 
  494.               width, height); 
  495.   gimp_layer_set_offsets (drawable->id, offsetx, offsety);
  496.  
  497.   if (was_preserve_transparency)
  498.     gimp_layer_set_preserve_transparency ( drawable->id, TRUE );
  499.  
  500.   return;
  501. }
  502.  
  503.  
  504. /* The main rotate function */
  505. static void 
  506. rotate (void)
  507. {
  508.   GimpDrawable *drawable;
  509.   gint32       *layers;
  510.   gint          i;
  511.   gint          nlayers;
  512.   gint32        guide_ID;
  513.   GuideInfo    *guide;
  514.   GList        *guides = NULL;
  515.   GList        *list;
  516.  
  517.   if (rotvals.angle == 0) return;  
  518.  
  519.   /* if there's a selection and we try to rotate the whole image */
  520.   /* create an error message and exit                            */     
  521.   if ( rotvals.everything )
  522.     {
  523.       if ( !gimp_selection_is_empty (image_ID) ) 
  524.     {
  525.       gimp_message (_("You can not rotate the whole image if there's a selection."));
  526.       gimp_drawable_detach (active_drawable);
  527.       return;
  528.     }
  529.       if ( gimp_layer_is_floating_selection (active_drawable->id) ) 
  530.     {
  531.       gimp_message (_("You can not rotate the whole image if there's a floating selection."));
  532.       gimp_drawable_detach (active_drawable);
  533.       return;
  534.     }
  535.     }
  536.   else
  537.     /* if we are trying to rotate a chennel or a mask, create an error message and exit */
  538.     {
  539.       if ( !gimp_drawable_is_layer (active_drawable->id) )
  540.     {
  541.       gimp_message (_("Sorry, channels and masks can not be rotated."));
  542.       gimp_drawable_detach (active_drawable);
  543.       return;
  544.     }
  545.     } 
  546.   
  547.   gimp_progress_init (_("Rotating..."));
  548.  
  549.   gimp_undo_push_group_start (image_ID);
  550.  
  551.   if (rotvals.everything)  /* rotate the whole image */ 
  552.     {
  553.       gint32 width = gimp_image_width (image_ID);
  554.       gint32 height = gimp_image_height (image_ID);
  555.  
  556.       gimp_drawable_detach (active_drawable);
  557.       layers = gimp_image_get_layers (image_ID, &nlayers);
  558.       for ( i=0; i<nlayers; i++ )
  559.     {
  560.       drawable = gimp_drawable_get (layers[i]);
  561.       rotate_drawable (drawable);
  562.       gimp_drawable_detach (drawable);
  563.     }
  564.       g_free(layers);      
  565.  
  566.       /* build a list of all guides and remove them */
  567.       guide_ID = 0;
  568.       while ((guide_ID = gimp_image_find_next_guide (image_ID, guide_ID)) != 0)
  569.     {
  570.       guide = g_new (GuideInfo, 1);
  571.       guide->ID = guide_ID;
  572.       guide->orientation = gimp_image_get_guide_orientation (image_ID, guide_ID);
  573.       guide->position = gimp_image_get_guide_position (image_ID, guide_ID);
  574.       guides = g_list_prepend (guides, guide);
  575.     }
  576.       for (list = guides; list; list = list->next)  
  577.     {
  578.       guide = (GuideInfo *)list->data;
  579.       gimp_image_delete_guide (image_ID, guide->ID);
  580.     }
  581.  
  582.       /* if rotation is not 180 degrees, resize the image */
  583.       /*    Do it now after the guides are removed, since */ 
  584.       /*    gimp_image_resize() moves the guides.         */ 
  585.       if (rotvals.angle != 2)
  586.     gimp_image_resize (image_ID, height, width, 0, 0);
  587.  
  588.       /* add the guides back to the image */
  589.       if (guides)
  590.     {
  591.       switch (rotvals.angle)
  592.         {
  593.         case 1:
  594.           for (list = guides; list; list = list->next)  
  595.         {
  596.           guide = (GuideInfo *)list->data;
  597.           if (guide->orientation == GIMP_HORIZONTAL)
  598.             gimp_image_add_vguide (image_ID, height - guide->position);
  599.           else
  600.             gimp_image_add_hguide (image_ID, guide->position);
  601.           g_free (guide);
  602.         }     
  603.           break;
  604.         case 2:
  605.           for (list = guides; list; list = list->next)  
  606.         {
  607.           guide = (GuideInfo *)list->data;
  608.           if (guide->orientation == GIMP_HORIZONTAL)
  609.             gimp_image_add_hguide (image_ID, height - guide->position);
  610.           else
  611.             gimp_image_add_vguide (image_ID, width - guide->position);
  612.           g_free (guide);
  613.         }     
  614.           break;
  615.         case 3:
  616.           for (list = guides; list; list = list->next)  
  617.         {
  618.           guide = (GuideInfo *)list->data;
  619.           if (guide->orientation == GIMP_HORIZONTAL)
  620.             gimp_image_add_vguide (image_ID, guide->position);
  621.           else
  622.             gimp_image_add_hguide (image_ID, width - guide->position);
  623.           g_free (guide);
  624.         }     
  625.           break;
  626.         default: 
  627.           break;
  628.         }
  629.       g_list_free (guides);
  630.     }
  631.     }
  632.   else  /* rotate only the active layer */
  633.     {
  634.  
  635.       /* check for active selection and float it */
  636.       if ( !gimp_selection_is_empty (image_ID) &&
  637.        !gimp_layer_is_floating_selection (active_drawable->id) )
  638.     active_drawable = 
  639.       gimp_drawable_get (gimp_selection_float (image_ID, 
  640.                            active_drawable->id,  
  641.                            0, 0));
  642.                 
  643.       rotate_drawable (active_drawable);
  644.       gimp_drawable_detach (active_drawable);
  645.     }
  646.  
  647.   gimp_undo_push_group_end (image_ID);
  648.  
  649.   return;
  650. }
  651.