[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: CVS update: Makefile.am



  User: cnieves 
  Date: 05/02/19 18:27:36

  Modified:    .        Makefile.am a_basic.nw f_image.nw f_print.nw
                        o_attrib.nw o_basic.nw o_complex_basic.nw o_list.nw
                        s_basic.nw s_toplevel.nw
  Added:       .        gdk-pixbuf-hacks.nw o_picture.nw
  Log:
  Added support for pictures within schematics and symbols.
  
  
  
  
  
  
  Revision  Changes    Path
  1.8       +2 -1      eda/geda/devel/libgeda/noweb/Makefile.am
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: Makefile.am
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/Makefile.am,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -b -r1.7 -r1.8
  --- Makefile.am	13 Feb 2005 21:46:43 -0000	1.7
  +++ Makefile.am	19 Feb 2005 23:27:32 -0000	1.8
  @@ -7,7 +7,8 @@
   	     s_attrib.nw s_basic.nw s_clib.nw s_color.nw s_conn.nw s_cue.nw \
   	     s_hierarchy.nw s_log.nw s_page.nw s_papersizes.nw \
   	     s_slib.nw s_stretch.nw s_tile.nw s_undo.nw s_menu.nw \
  -	     s_toplevel.nw u_basic.nw g_register.nw g_rc.nw i_vars.nw
  +	     s_toplevel.nw u_basic.nw g_register.nw g_rc.nw i_vars.nw \
  +	     o_picture.nw gdk-pixbuf-hacks.nw		
   
   MOSTLYCLEANFILES = *.log *~
   CLEANFILES = *.log *~
  
  
  
  1.18      +14 -0     eda/geda/devel/libgeda/noweb/a_basic.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: a_basic.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/a_basic.nw,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -b -r1.17 -r1.18
  --- a_basic.nw	14 Feb 2005 22:30:07 -0000	1.17
  +++ a_basic.nw	19 Feb 2005 23:27:32 -0000	1.18
  @@ -154,6 +154,10 @@
               out = (char *) o_arc_save(o_current);
               break;
   
  +  	  case(OBJ_PICTURE):
  +	    out = (char *) o_picture_save(o_current); 
  +	    break;
  +
             default:
               fprintf(stderr, "Error type!\n");
               exit(-1);
  @@ -290,6 +294,10 @@
               out = (char *) o_arc_save(o_current);
               break;
   
  +  	  case(OBJ_PICTURE):
  +	    out = (char *) o_picture_save(o_current); 
  +	    break;
  +
             default:
               fprintf(stderr, "Error type!\n");
               exit(-1);
  @@ -398,6 +406,12 @@
                                               release_ver, fileformat_ver);
           break;
   		
  +      case(OBJ_PICTURE):
  +        object_list = (OBJECT *) o_picture_read(w_current, object_list, buf,
  +						fp,
  +						release_ver, fileformat_ver);
  +        break;
  +		
         case(OBJ_CIRCLE):
           object_list = (OBJECT *) o_circle_read(w_current, object_list, buf,
                                                  release_ver, fileformat_ver);
  
  
  
  1.7       +8 -0      eda/geda/devel/libgeda/noweb/f_image.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: f_image.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/f_image.nw,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -b -r1.6 -r1.7
  --- f_image.nw	4 Feb 2005 04:39:28 -0000	1.6
  +++ f_image.nw	19 Feb 2005 23:27:32 -0000	1.7
  @@ -165,6 +165,14 @@
                               origin_x, origin_y, color_mode);
             break;
   			
  +	case(OBJ_PICTURE):
  +          /* FIXME: Implement this */
  +	  fprintf(stderr, "f_image_write_objects: o_picture_image_write not implemented yet\n");
  +	  out = NULL;
  +	  /* out = (char *) o_picture_image_write(w_current, o_current,
  +	     origin_x, origin_y, color_mode); */
  +	  break;
  +
           default:
             fprintf(stderr, "Error type!\n");
             exit(-1);
  
  
  
  1.12      +6 -0      eda/geda/devel/libgeda/noweb/f_print.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: f_print.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/f_print.nw,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -b -r1.11 -r1.12
  --- f_print.nw	4 Feb 2005 04:39:28 -0000	1.11
  +++ f_print.nw	19 Feb 2005 23:27:32 -0000	1.12
  @@ -482,6 +482,12 @@
                         origin_x, origin_y);
             break;
   
  +  	case(OBJ_PICTURE):
  +            /* FIXME: Implement this */
  +	  fprintf(stderr, "f_print_objects: o_picture_print not implemented yet\n");
  +	  /* o_picture_print(); */
  +	  break;
  +
           default:
             fprintf(stderr, "Error type!\n");
             exit(-1);
  
  
  
  1.21      +4 -0      eda/geda/devel/libgeda/noweb/o_attrib.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: o_attrib.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/o_attrib.nw,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -b -r1.20 -r1.21
  --- o_attrib.nw	4 Feb 2005 22:37:06 -0000	1.20
  +++ o_attrib.nw	19 Feb 2005 23:27:32 -0000	1.21
  @@ -963,6 +963,10 @@
             out = (char *) o_arc_save(o_current);
             break;
   
  +  	case(OBJ_PICTURE):
  +	  out = (char *) o_picture_save(o_current); 
  +	  break;
  +
           default:
             fprintf(stderr, "Error type!\n");
             exit(-1);
  
  
  
  1.7       +4 -0      eda/geda/devel/libgeda/noweb/o_basic.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: o_basic.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/o_basic.nw,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -b -r1.6 -r1.7
  --- o_basic.nw	4 Feb 2005 04:39:29 -0000	1.6
  +++ o_basic.nw	19 Feb 2005 23:27:32 -0000	1.7
  @@ -151,6 +151,10 @@
           o_box_recalc(w_current, o_current);
           break;
   
  +      case(OBJ_PICTURE):
  +        o_picture_recalc(w_current, o_current);
  +        break;
  +
         case(OBJ_CIRCLE):
           o_circle_recalc(w_current, o_current);
           break;
  
  
  
  1.24      +40 -0     eda/geda/devel/libgeda/noweb/o_complex_basic.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: o_complex_basic.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/o_complex_basic.nw,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -b -r1.23 -r1.24
  --- o_complex_basic.nw	14 Feb 2005 22:32:27 -0000	1.23
  +++ o_complex_basic.nw	19 Feb 2005 23:27:32 -0000	1.24
  @@ -141,6 +141,12 @@
           get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
           break;
   
  +      case(OBJ_PICTURE):
  +#ifndef HAS_GTK12
  +        get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
  +#endif
  +        break;
  +
         case(OBJ_CIRCLE):
           get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
           break;
  @@ -235,6 +241,12 @@
           get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
           break;
   
  +      case(OBJ_PICTURE):
  +#ifndef HAS_GTK12
  +        get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
  +#endif
  +        break;
  +
         case(OBJ_CIRCLE):
           get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
           break;
  @@ -321,6 +333,12 @@
           world_get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
           break;
   
  +      case(OBJ_PICTURE):
  +#ifndef HAS_GTK12
  +        world_get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
  +#endif
  +        break;
  +
         case(OBJ_CIRCLE):
           world_get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
           break;
  @@ -1087,6 +1105,10 @@
           o_box_translate_world(w_current, x1, y1, o_current);
           break;
   
  +      case(OBJ_PICTURE):
  +        o_picture_translate_world(w_current, x1, y1, o_current);
  +        break;
  +
         case(OBJ_CIRCLE):
           o_circle_translate_world(w_current, x1, y1, o_current);
           break;
  @@ -1322,6 +1344,7 @@
         case(OBJ_NET):
         case(OBJ_BUS):
         case(OBJ_BOX):
  +      case(OBJ_PICTURE):
         case(OBJ_CIRCLE):
         case(OBJ_PIN):
         case(OBJ_ARC):
  @@ -1361,6 +1384,7 @@
       case(OBJ_NET):
       case(OBJ_BUS):
       case(OBJ_BOX):
  +    case(OBJ_PICTURE):
       case(OBJ_CIRCLE):
       case(OBJ_PIN):
       case(OBJ_ARC):
  @@ -1404,6 +1428,7 @@
         case(OBJ_NET):
         case(OBJ_BUS):
         case(OBJ_BOX):
  +      case(OBJ_PICTURE):
         case(OBJ_CIRCLE):
         case(OBJ_PIN):
         case(OBJ_ARC):
  @@ -1455,6 +1480,7 @@
         case(OBJ_NET):
         case(OBJ_BUS):
         case(OBJ_BOX):
  +      case(OBJ_PICTURE):
         case(OBJ_CIRCLE):
         case(OBJ_PIN):
         case(OBJ_ARC):
  @@ -1499,6 +1525,7 @@
       case(OBJ_NET):
       case(OBJ_BUS):
       case(OBJ_BOX):
  +    case(OBJ_PICTURE):
       case(OBJ_CIRCLE):
       case(OBJ_PIN):
       case(OBJ_ARC):
  @@ -1544,6 +1571,7 @@
         case(OBJ_NET):
         case(OBJ_BUS):
         case(OBJ_BOX):
  +      case(OBJ_PICTURE):
         case(OBJ_CIRCLE):
         case(OBJ_PIN):
         case(OBJ_ARC):
  @@ -1644,6 +1672,12 @@
           o_box_rotate_world(w_current, 0, 0, angle_change, o_current);
           break;
   
  +      case(OBJ_PICTURE):
  +#ifndef HAS_GTK12
  +        o_picture_rotate_world(w_current, 0, 0, angle_change, o_current);
  +#endif
  +        break;
  +
         case(OBJ_CIRCLE):
           o_circle_rotate_world(w_current, 0, 0, angle_change, o_current);
           break;
  @@ -1708,6 +1742,12 @@
           o_box_mirror_world(w_current, 0, 0, o_current);
           break;
   
  +      case(OBJ_PICTURE):
  +#ifndef HAS_GTK12
  +        o_picture_mirror_world(w_current, 0, 0, o_current);
  +#endif
  +        break;
  +
         case(OBJ_CIRCLE):
           o_circle_mirror_world(w_current, 0, 0, o_current);
           break;
  
  
  
  1.6       +4 -0      eda/geda/devel/libgeda/noweb/o_list.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: o_list.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/o_list.nw,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -b -r1.5 -r1.6
  --- o_list.nw	4 Feb 2005 04:39:29 -0000	1.5
  +++ o_list.nw	19 Feb 2005 23:27:32 -0000	1.6
  @@ -118,6 +118,10 @@
         end = (OBJECT *) o_box_copy(w_current, end, selected);	
         break;
   
  +    case(OBJ_PICTURE):
  +      end = (OBJECT *) o_picture_copy(w_current, end, selected);	
  +      break;
  +
       case(OBJ_CIRCLE):
         end = (OBJECT *) o_circle_copy(w_current, end, selected);	
         break;
  
  
  
  1.12      +15 -0     eda/geda/devel/libgeda/noweb/s_basic.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: s_basic.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/s_basic.nw,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -b -r1.11 -r1.12
  --- s_basic.nw	4 Feb 2005 04:39:29 -0000	1.11
  +++ s_basic.nw	19 Feb 2005 23:27:32 -0000	1.12
  @@ -253,6 +253,7 @@
     new_node->circle = NULL;
     new_node->arc = NULL;
     new_node->box = NULL;
  +  new_node->picture = NULL;
     new_node->text = NULL;
     new_node->complex = NULL;
   
  @@ -533,6 +534,20 @@
       }
       o_current->box = NULL;
   
  +    if (o_current->picture) {
  +      /*	printf("sdeleting picture\n");*/
  +#ifndef HAS_GTK12
  +      if (o_current->picture->original_picture)
  +	free(o_current->picture->original_picture);
  +      if (o_current->picture->displayed_picture)
  +	free(o_current->picture->displayed_picture);
  +#endif
  +      if (o_current->picture->filename)
  +	free(o_current->picture->filename);
  +      free(o_current->picture);
  +    }
  +    o_current->picture = NULL;
  +
       if (o_current->text) {
         if (o_current->text->string) {
   				/*printf("sdeleting text->string\n");*/
  
  
  
  1.2       +8 -0      eda/geda/devel/libgeda/noweb/s_toplevel.nw
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: s_toplevel.nw
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/devel/libgeda/noweb/s_toplevel.nw,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- s_toplevel.nw	11 Feb 2005 18:18:42 -0000	1.1
  +++ s_toplevel.nw	19 Feb 2005 23:27:32 -0000	1.2
  @@ -290,6 +290,14 @@
     toplevel->coord_world = NULL;
     toplevel->coord_screen = NULL;
   
  +  toplevel->pfswindow = NULL;
  +  toplevel->pcfswindow = NULL;
  +#ifndef HAS_GTK12
  +  toplevel->current_pixbuf = NULL;
  +#endif
  +  toplevel->pixbuf_filename = NULL;
  +  toplevel->pixbuf_wh_ratio = 0;
  +
     toplevel->clwindow = NULL;
     toplevel->edit_color = 0;
   
  
  
  
  1.1                  eda/geda/devel/libgeda/noweb/gdk-pixbuf-hacks.nw
  
  Index: gdk-pixbuf-hacks.nw
  ===================================================================
  @c -*- mode: Noweb; noweb-doc-mode: texinfo-mode; noweb-code-mode: c-mode -*-
  
  @node File gdk-pixbuf-hacks.c,,,Top
  @chapter File @file{gdk-pixbuf-hacks.c}
  
  @section File header
  
  <<gdk-pixbuf-hacks.c : *>>=
  
  <<gdk-pixbuf-hacks.c : copyright and license>>
  
  /* Taken from gtkam's sources */
  
  /* DO NOT read or edit this file ! Use ../noweb/gdk-pixbuf-hacks.nw instead */
  
  <<gdk-pixbuf-hacks.c : include directives>>
  
  #ifndef HAS_GTK12
  <<gdk-pixbuf-hacks.c : macros>>
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_rotate()>>
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_add()>>
  
  <<gdk-pixbuf-hacks.c : copyright and license mirror flip>>
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_mirror_flip()>>
  
  #endif
  @
  
  <<gdk-pixbuf-hacks.c : copyright and license>>=
  /* Functions gdk_pixbuf_rotate and gdk_pixbuf_add are taken from gtkam,
     and is covered by this copyright. */
  /*
   * Copyright © 2001 Lutz Müller <lutz@xxxxxxxxxxxx>
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This library 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
   * Lesser General Public License for more details. 
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 02111-1307, USA.
   */
  
  @
  
  <<gdk-pixbuf-hacks.c : include directives>>=
  #include "config.h"
  #ifndef HAS_GTK12
  #include <gdk-pixbuf/gdk-pixbuf.h>
  #endif
  
  @
  
  <<gdk-pixbuf-hacks.c : macros>>=
  #define COPY90                                                          \
          if ((r2 < h1) && (c2 < w1)) {                                   \
            if ((w1 <= h1) && (r1 < h2))                                  \
              for (i = 0; i < c; i++)                                     \
                new_pixels[r1 * rs2 + c1 * c + i] =                      	\
                  pixels[r2 * rs1 + c2 * c + i];                  	\
            if ((w1 > h1) && (c1 > (w1 - h2)))                            \
              for (i = 0; i < c; i++)                                     \
                new_pixels[r1 * rs2 + (c1 - (w1 - h1)) * c + i] =        	\
                  pixels[r2 * rs1 + c2 * c + i];                  	\
          }
  
  #define COPY270                                                         \
          if ((r2 < h1) && (c2 < w1)) {                                   \
            if ((h1 > w1) && (r1 > (h1 - w1)))                            \
              for (i = 0; i < c; i++)                                     \
                new_pixels[(r1 - (h1 - w1)) * rs2 + c1 * c + i] =        	\
                  pixels[r2 * rs1 + c2 * c + i];                  	\
            if ((h1 <= w1) && (c1 < w2))                                  \
              for (i = 0; i < c; i++)                                     \
                new_pixels[r1 * rs2 + c1 * c + i] =               	\
                  pixels[r2 * rs1 + c2 * c + i];                  	\
          }
  
  @ %def COPY90 COPY270
  
  @section Function @code{gdk_pixbuf_rotate()}
  
  @defun gdk_pixbuf_rotate pixbuf angle
  @end defun
  
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_rotate()>>=
  GdkPixbuf *
  gdk_pixbuf_rotate (GdkPixbuf *pixbuf, guint angle)
  {
          GdkPixbuf *new = NULL;
          guint row, col, w1, h1, w2, h2;
          guint r1, r2, c1, c2;
          guint rs1, rs2;
          guint c;
          guint i;
  	guchar *pixels, *new_pixels;
  
  	if (pixbuf == NULL) {
  	  return NULL;
  	}	
          g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
  	
  	/* Swapped original definitions, so the picture turns counter-clockwise */
  	if (angle == 90)
  	  angle = 270;
  	else  if (angle == 270)
  	  angle = 90;
  
          switch (angle) {
          case 0:
                  return (gdk_pixbuf_copy (pixbuf));
          case 180:
                  new = gdk_pixbuf_new (
  			gdk_pixbuf_get_colorspace (pixbuf),
  			gdk_pixbuf_get_has_alpha (pixbuf),
  			gdk_pixbuf_get_bits_per_sample (pixbuf),
  			gdk_pixbuf_get_width (pixbuf),
  			gdk_pixbuf_get_height (pixbuf));
                  break;
          case 90:
          case 270:
                  new = gdk_pixbuf_new (
  			gdk_pixbuf_get_colorspace (pixbuf),
  			gdk_pixbuf_get_has_alpha (pixbuf),
  			gdk_pixbuf_get_bits_per_sample (pixbuf),
  			gdk_pixbuf_get_height (pixbuf),
  			gdk_pixbuf_get_width (pixbuf));
                  break;
          default:
                  g_warning ("Rotation by %i not implemented.", angle);
                  break;
          }
  
          rs1 = gdk_pixbuf_get_rowstride (pixbuf);
          rs2 = gdk_pixbuf_get_rowstride (new);
  
          c = gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3;
  
          w1 = gdk_pixbuf_get_width (pixbuf);
          h1 = gdk_pixbuf_get_height (pixbuf);
          w2 = gdk_pixbuf_get_width (new);
          h2 = gdk_pixbuf_get_height (new);
  
  	pixels = gdk_pixbuf_get_pixels (pixbuf);
  	new_pixels = gdk_pixbuf_get_pixels (new);
  
          /*
           * For rotation by 90 or 270, we assume the pixbuf to be a
           * square and move (r2,c2) to (r1,c1):
           */
          switch (angle) {
          case 90:
                  for (row = 0; row < MAX (w1, h1) / 2; row++) {
                          for (col = row; col < MAX (w1, h1) - row - 1; col++) {
                                  r1 = row;
                                  c1 = col;
                                  r2 = MAX (w1, h1) - col - 1;
                                  c2 = row;
                                  COPY90;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = MAX (w1, h1) - row - 1;
                                  c2 = MAX (w1, h1) - col - 1;
                                  COPY90;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = col;
                                  c2 = MAX (w1, h1) - row - 1;
                                  COPY90;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = row;
                                  c2 = col;
                                  COPY90;
                          }
                  }
                  break;
          case 270:
                  for (row = 0; row < MAX (w1, h1) / 2; row++) {
                          for (col = row; col < MAX (w1, h1) - row - 1; col++) {
                                  r1 = row;
                                  c1 = col;
                                  r2 = col;
                                  c2 = MAX (w1, h1) - row - 1;
                                  COPY270;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = MAX (w1, h1) - row - 1;
                                  c2 = MAX (w1, h1) - col - 1;
                                  COPY270;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = MAX (w1, h1) - col - 1;
                                  c2 = row;
                                  COPY270;
                                  r1 = r2;
                                  c1 = c2;
                                  r2 = row;
                                  c2 = col;
                                  COPY270;
                          }
                  }
                  break;
          case 180:
                  for (row = 0; row < h1; row++) {
                          for (col = 0; col < w1; col++) {
                                  r1 = row;
                                  c1 = col;
                                  r2 = h1 - row - 1;
                                  c2 = w1 - col - 1;
                                  for (i = 0; i < c; i++) {
                                    new_pixels[r2 * rs2 + c2 * c + i] =
                                      pixels[r1 * rs1 + c1 * c + i];
                                  }
                          }
                  }
                  break;
          default:
                  g_warning ("Rotation by %i not implemented.", angle);
                  break;
          }
  
          return (new);
  }
  
  @ %def gdk_pixbuf_rotate
  
  @section Function @code{gdk_pixbuf_add()}
  
  @defun gdk_pixbuf_add pixbuf offset_x offset_y pixbuf_to_add
  @end defun
  
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_add()>>=
  void
  gdk_pixbuf_add (GdkPixbuf *pixbuf, int offset_x, int offset_y,
  		GdkPixbuf *pixbuf_to_add)
  {
  	guchar *p1, *p2, a1, a2;
  	guint w1, h1, w2, h2, r1, r2;
  	guint row, col, i, pos1, pos2;
  
  	g_return_if_fail (pixbuf != NULL);
  	g_return_if_fail (pixbuf_to_add != NULL);
  
  	w1 = gdk_pixbuf_get_width (pixbuf);
  	h1 = gdk_pixbuf_get_height (pixbuf);
  	w2 = gdk_pixbuf_get_width (pixbuf_to_add);
  	h2 = gdk_pixbuf_get_height (pixbuf_to_add);
  	g_return_if_fail (w1 >= offset_x + w2);
  	g_return_if_fail (h1 >= offset_y + h2);
  
  	p1 = gdk_pixbuf_get_pixels (pixbuf);
  	p2 = gdk_pixbuf_get_pixels (pixbuf_to_add);
  	r1 = gdk_pixbuf_get_rowstride (pixbuf);
  	r2 = gdk_pixbuf_get_rowstride (pixbuf_to_add);
  	for (row = 0; row < h2; row++) {
  		for (col = 0; col < w2; col++) {
  			pos1 = (row + offset_y) * r1 + (col + offset_x) * 4;
  			pos2 = row * r2 + col * 4;
  			a1 = p1[pos1 + 3];
  			a2 = p2[pos2 + 3];
  
  			for (i = 0; i < 3; i++) {
  				p1[pos1 + i] *=
  					((gfloat) (0xff - a2) / (gfloat) 0xff);
  				p1[pos1 + i] += (p2[pos2 + i] * 
  					((gfloat) a2 / (gfloat) 0xff));
  			}
  			p1[pos1 + 3] = MAX (a1, a2);
  		}
  	}
  }
  @ %def gdk_pixbuf_add
  
  <<gdk-pixbuf-hacks.c : copyright and license mirror flip>>=
  /* The following function was taken from GQview, and is covered by this copyright. 
     The name of the function was changed from pixbuf_copy_mirror to 
     gdk_pixbuf_mirror_rotate. */
  /*
   * GQview
   * (C) 2002 John Ellis
   *
   * Author: John Ellis
   *
   * This software is released under the GNU General Public License (GNU GPL).
   * Please read the included file COPYING for more information.
   * This software comes with no warranty of any kind, use at your own risk!
   */
  
  @
  
  
  @section Function @code{gdk_pixbuf_mirror_flip()}
  
  @defun pixbuf_copy_mirror src, mirror, flip
  @end defun
  
  <<gdk-pixbuf-hacks.c : gdk_pixbuf_mirror_flip()>>=
  /*
   * Returns a copy of pixbuf mirrored and or flipped.
   * TO do a 180 degree rotations set both mirror and flipped TRUE
   * if mirror and flip are FALSE, result is a simple copy.
   */
  GdkPixbuf *gdk_pixbuf_mirror_flip(GdkPixbuf *src, gint mirror, gint flip)
  {
  	GdkPixbuf *dest;
  	gint has_alpha;
  	gint w, h, srs;
  	gint drs;
  	guchar *s_pix;
          guchar *d_pix;
  	guchar *sp;
          guchar *dp;
  	gint i, j;
  	gint a;
  
  	if (!src) return NULL;
  
  	w = gdk_pixbuf_get_width(src);
  	h = gdk_pixbuf_get_height(src);
  	has_alpha = gdk_pixbuf_get_has_alpha(src);
  	srs = gdk_pixbuf_get_rowstride(src);
  	s_pix = gdk_pixbuf_get_pixels(src);
  
  	dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, w, h);
  	drs = gdk_pixbuf_get_rowstride(dest);
  	d_pix = gdk_pixbuf_get_pixels(dest);
  
  	a = has_alpha ? 4 : 3;
  
  	for (i = 0; i < h; i++)
  		{
  		sp = s_pix + (i * srs);
  		if (flip)
  			{
  			dp = d_pix + ((h - i - 1) * drs);
  			}
  		else
  			{
  			dp = d_pix + (i * drs);
  			}
  		if (mirror)
  			{
  			dp += (w - 1) * a;
  			for (j = 0; j < w; j++)
  				{
  				*(dp++) = *(sp++);	/* r */
  				*(dp++) = *(sp++);	/* g */
  				*(dp++) = *(sp++);	/* b */
  				if (has_alpha) *(dp) = *(sp++);	/* a */
  				dp -= (a + 3);
  				}
  			}
  		else
  			{
  			for (j = 0; j < w; j++)
  				{
  				*(dp++) = *(sp++);	/* r */
  				*(dp++) = *(sp++);	/* g */
  				*(dp++) = *(sp++);	/* b */
  				if (has_alpha) *(dp++) = *(sp++);	/* a */
  				}
  			}
  		}
  
  	return dest;
  }
  
  @ %def gdk_pixbuf_mirror_flip
  
  
  1.1                  eda/geda/devel/libgeda/noweb/o_picture.nw
  
  Index: o_picture.nw
  ===================================================================
  @c -*- mode: Noweb; noweb-doc-mode: texinfo-mode; noweb-code-mode: c-mode -*-
  
  @node File o_picture.c,,,Top
  @chapter File @file{o_picture.c}
  
  @section File header
  <<o_picture.c : *>>=
  <<o_picture.c : copyright and license>>
  
  /* DO NOT read or edit this file ! Use ../noweb/o_picture.nw instead */
  
  <<o_picture.c : include directives>>
  #ifndef HAS_GTK12
  <<o_picture.c : o_picture_read()>>
  <<o_picture.c : o_picture_save()>>
  <<o_picture.c : o_picture_set_pixbuf()>>
  <<o_picture_basic.c : o_picture_add()>>
  <<o_picture_basic.c : o_picture_recalc()>>
  <<o_picture_basic.c : get_picture_bounds()>>
  <<o_picture_basic.c : world_get_picture_bounds()>>
  <<o_picture_basic.c : o_picture_modify()>>
  <<o_picture_basic.c : o_picture_rotate()>>
  <<o_picture_basic.c : o_picture_rotate_world()>>
  <<o_picture_basic.c : o_picture_mirror()>>
  <<o_picture_basic.c : o_picture_mirror_world()>>
  <<o_picture_basic.c : o_picture_translate()>>
  <<o_picture_basic.c : o_picture_translate_world()>>
  <<o_picture_basic.c : o_picture_copy()>>
  
  #endif
  
  @
  
  
  <<o_picture.c : copyright and license>>=
  /* gEDA - GPL Electronic Design Automation
   * libgeda - gEDA's library
   * Copyright (C) 1998-2000 Ales V. Hvezda
   *
   * 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 USA
   */
  
  
  @ 
  
  
  <<o_picture.c : include directives>>=
  #include <config.h>
  
  #include <stdio.h>
  #ifdef HAVE_STRING_H
  #include <string.h>
  #endif
  #include <math.h>
  
  #include <gtk/gtk.h>
  #include <guile/gh.h>
  #ifndef HAS_GTK12
  #include <gdk-pixbuf/gdk-pixbuf.h>
  #endif
  
  #include "defines.h"
  #include "struct.h"
  #include "globals.h"
  #include "o_types.h"
  #include "colors.h"
  #include "funcs.h"
  
  #include "../include/prototype.h"
  
  @ 
  
  @section Function [[o_picture_read()]]
  
  @defun o_picture_read w_current object_list buf version
  The function [[o_picture_read()]] get from the character string [[*buf]] the description of a picture. The new picture is then added to the list of object of which [[*object_list]] is the last element before the call.
  The function returns the new last element, that is the added picture object.
  @end defun
  
  <<o_picture.c : o_picture_read()>>=
  OBJECT *
  o_picture_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
              FILE *fp, unsigned int release_ver, unsigned int fileformat_ver)
  {
    int x1, y1;
    int width, height, angle;
    gchar mirrored, embedded;
    int num_conv;
    double ratio;
    gchar type;
    gchar buffer[MAX_TEXT_LINE_LENGTH]; 
    gchar *filename;
    GdkPixbuf *pixbuf;
  
    num_conv = sscanf(buf, "%c %d %d %d %d %d %d %d\n",
  	 &type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);
  
    if (num_conv != 8) {
      fprintf(stderr, "Error reading picture definition line: %s.\n", buf);
      s_log_message ("Error reading picture definition line: %s.\n", buf);
    }
  
    if (width == 0 || height == 0) {
      fprintf(stderr, "Found a zero width/height picture [ %c %d %d %d %d ]\n",
              type, x1, y1, width, height);
      s_log_message("Found a zero width/height picture [ %c %d %d %d %d ]\n",
                    type, x1, y1, width, height);
    }
  
    if ( (mirrored > 1) || (mirrored < 0)) {
      fprintf(stderr, "Found a picture with a wrong 'mirrored' parameter: %s.\n",
  	    mirrored);
      s_log_message("Found a picture with a wrong 'mirrored' parameter: %s.\n",
  	    mirrored);
      s_log_message("Setting mirrored to 0\n");
      mirrored = 0;
    }
  
    if ( (embedded > 1) || (embedded < 0)) {
      fprintf(stderr, "Found a picture with a wrong 'embedded' parameter: %s.\n",
  	    mirrored);
      s_log_message("Found a picture with a wrong 'embedded' parameter: %s.\n",
  	    mirrored);
      s_log_message("Setting mirrored to 0\n");
      mirrored = 0;
    }
    switch(angle) {
  	
      case(0):
      case(90):
      case(180):
      case(270):
      break;
  
      default:
      fprintf(stderr, "Found an unsupported picture angle [ %d ]\n", angle);
      s_log_message("Found an unsupported picture angle [ %d ]\n", angle);
      s_log_message("Setting angle to 0\n");
      angle=0;
      break;
  
    }
  
    fgets(buffer, 1024, fp);
    
    filename = g_strdup (buffer);
    filename = remove_last_nl(filename);	
      
    pixbuf = NULL;
  
    if (embedded == 0) {
  #ifndef HAS_GTK12
      pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
      if (pixbuf == NULL) {
        fprintf(stderr, "Error loading picture from file: %s.\n", filename);
        s_log_message( "Error loading picture from file: %s.\n", filename);
      }
  #endif  
    }
    else {
      fprintf(stderr, "Embedded pictures are not supported yet.\n");
      s_log_message ("Embedded pictures are not supported yet.\n");
    }
  
    if (pixbuf == NULL) {
      /* If the pixbuf couldn't be loaded, then try to load a warning picture */
      char *temp_filename;
  
      fprintf(stderr, "Loading warning picture.\n");
      s_log_message ("Loading warning picture.\n");
      
      temp_filename = g_strconcat(w_current->bitmap_directory, 
  			       G_DIR_SEPARATOR_S, "gschem-warning.png", NULL);
      pixbuf = gdk_pixbuf_new_from_file (temp_filename, NULL);
      if (pixbuf == NULL) {
        fprintf(stderr, "Error loading picture from file: %s.\n", temp_filename);
        s_log_message( "Error loading picture from file: %s.\n", temp_filename);
      }      
      free (temp_filename);
    }
    
    /* create and add the picture to the list */
    /* The picture is described by its upper left and lower right corner */
    object_list = (OBJECT *) o_picture_add(w_current, object_list,
  					 pixbuf, filename, 
  					 (double) (height/width),
  					 type, 
  					 x1, y1+height, x1+width, y1, 
  					 angle, mirrored, embedded);
    if (object_list->picture->filename) {
      free(object_list->picture->filename);
    }
    object_list->picture->filename = g_strdup(filename);
    
    free (filename);
    return(object_list);
  }
  
  @ %def o_picture_read
  
  
  @section Function [[o_picture_save()]]
  
  @defun o_picture_save buf object
  This function formats a string in the buffer [[*buff]] to describe the picture object [[*object]].
  A pointer to the new allocated and formated string is returned. The
  string must be freed at some point.
  @end defun
  
  <<o_picture.c : o_picture_save()>>=
  char *
  o_picture_save(OBJECT *object)
  {
    int width, height, x1, y1;
  
    /* calculate the width and height of the box */
    width  = abs(object->picture->lower_x - object->picture->upper_x); 
    height = abs(object->picture->upper_y - object->picture->lower_y);
  
    /* calculate the lower left corner of the box */
    x1 = object->picture->upper_x;
    y1 = object->picture->upper_y - height; /* move the origin to 0, 0*/
    
  #if DEBUG
    printf("picture: %d %d %d %d\n", x1, y1, width, height);
  #endif
  
    return(g_strdup_printf("%c %d %d %d %d %d %d %d\n%s", 
  			 object->type,
  			 x1, y1, width, height,
  			 object->picture->angle,
  			 object->picture->mirrored,
  			 0, /* No embedded pictures support yet */
  			 object->picture->filename));
  
  
  }
  
  @ %def o_picture_save
  
  
  @section Function @code{o_picture_set_string()}
  
  @defun o_picture_set_pixbuf w_current pixbuf filename
  @end defun
  
  <<o_picture.c : o_picture_set_pixbuf()>>=
  void
  o_picture_set_pixbuf(TOPLEVEL *w_current, GdkPixbuf *pixbuf, char *filename)
  {
  
    /* need to put an error messages here */
    if (pixbuf == NULL)  {
      fprintf(stderr, "error! picture in set pixbuf was NULL\n");
      return;
    }
  
    if (w_current->current_pixbuf != NULL) {
      free(w_current->current_pixbuf);
      w_current->current_pixbuf=NULL;
    }
  
    if (w_current->pixbuf_filename != NULL) {
      free(w_current->pixbuf_filename);
      w_current->pixbuf_filename=NULL;
    }
  
    w_current->current_pixbuf = pixbuf;
    w_current->pixbuf_filename = (char *) g_strdup(filename);
    
    w_current->pixbuf_wh_ratio = (double) gdk_pixbuf_get_width(pixbuf) / 
                                          gdk_pixbuf_get_height(pixbuf);
  
    /* be sure to free this pixbuf somewhere */
  }
  
  @ %def o_picture_set_pixbuf
  
  
  @section Function [[o_picture_add()]]
  
  @defun o_picture_add w_current object_list type color x1 y1 x2 y2
  This function creates a new object representing a picture. This object is added to the end of the list [[object_list]] pointed object belongs to.
  The picture is described by its upper left corner - [[x1]], [[y1]] - and its lower right corner - [[x2]], [[y2]].
  The [[type]] parameter must be equal to [[OBJ_PICTURE]]. 
  @end defun
  
  The [[OBJECT]] structure is allocated with the [[s_basic_init_object()]] function. The structure describing the picture is allocated and initialized with the parameters given to the function.
  
  The object is added to the end of the list described by the [[object_list]] parameter by the [[s_basic_link_object()]].
  
  The function returns a new pointer on the end of the object list.
  
  <<o_picture_basic.c : o_picture_add()>>=
  OBJECT *
  o_picture_add(TOPLEVEL *w_current, OBJECT *object_list,
  	      GdkPixbuf * pixbuf, char *filename, double ratio,
  	      char type, 
  	      int x1, int y1, int x2, int y2, int angle, char mirrored,
  	      char embedded)
  {
    OBJECT *new_node;
    PICTURE *picture;
  
    <<o_picture_add() : allocate memory for the new picture>>
  
    <<o_picture_add() : initialize the picture>>
  
    <<o_picture_add() : calculate the screen coords and the bounding picture>>
  
    <<o_picture_add() : add the object to the list>>
  
    return(object_list);
  }
  
  @ %def o_picture_add
  
  
  <<o_picture_add() : allocate memory for the new picture>>=
  /* create the object */
  new_node        = s_basic_init_object("picture");
  new_node->type  = type;
  
  picture = (PICTURE *) malloc(sizeof(PICTURE));
  new_node->picture   = picture;
  
  @ 
  
  
  <<o_picture_add() : initialize the picture>>=
  /* describe the picture with its upper left and lower right corner */
  picture->upper_x = x1;
  picture->upper_y = y1;
  picture->lower_x = x2;
  picture->lower_y = y2;
  
  /* Fill the picture data */
  	
     /* Create a copy of the pixbuf */
  picture->original_picture = gdk_pixbuf_rotate(pixbuf, 0);
  picture->filename = (char *) g_strdup(filename);
  picture->ratio = ratio;
  picture->displayed_picture = NULL;
  picture->angle = angle;
  picture->mirrored = mirrored;
  
  if (picture->original_picture == NULL) {
    fprintf(stderr, "new picture: Couldn't get enough memory for the new picture\n");
  }
  
  /* Clean w_current variables */
  /* FIXME: This should be done when canceling the action.
  /* Pixbuf filename is not freed because we want to remember the last directory */
  /*
  if (w_current->current_pixbuf != NULL) {
    free (w_current->current_pixbuf);
  }
  w_current->current_pixbuf = NULL;
  w_current->pixbuf_wh_ratio = 0;
  */
  
  /* TODO: questionable cast */     
  new_node->draw_func = (void *) picture_draw_func; 
  /* TODO: questionable cast */     
  new_node->sel_func  = (void *) select_func;  
  
  @ 
  
  
  <<o_picture_add() : calculate the screen coords and the bounding picture>>=
  /* compute the bounding picture */
  o_picture_recalc(w_current, new_node);
  
  @ 
  
  
  <<o_picture_add() : add the object to the list>>=
  /* add the object to the list */
  object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
  
  @ 
  
  @section Function [[o_picture_recalc()]]
  
  @defun o_picture_recalc w_current o_current
  This function recalculates the screen coords of the [[o_current]] pointed picture object from its world coords.
  @end defun
  
  The picture coordinates and its bounding are recalculated as well as the OBJECT specific fields (line width, filling ...).
  
  <<o_picture_basic.c : o_picture_recalc()>>=
  void
  o_picture_recalc(TOPLEVEL *w_current, OBJECT *o_current)
  {
    int left, top, right, bottom;
    int screen_x1, screen_y1;
    int screen_x2, screen_y2;
  
    if (o_current->picture == NULL) {
      return;
    }
  
    <<o_picture_recalc() : update the screen coords from world coords>>
  
    <<o_picture_recalc() : update the bounding picture in screen unit>>
  
    <<o_picture_recalc() : update the object general fields>>
  	
  }
  
  @ %def o_picture_recalc
  
  
  <<o_picture_recalc() : update the screen coords from world coords>>=
  /* update the screen coords of the upper left corner of the picture */
  WORLDtoSCREEN(w_current,
  			  o_current->picture->upper_x, o_current->picture->upper_y, 
  			  &screen_x1, &screen_y1);  
  o_current->picture->screen_upper_x = screen_x1;
  o_current->picture->screen_upper_y = screen_y1;
  
  /* update the screen coords of the lower right corner of the picture */
  WORLDtoSCREEN(w_current,
  			  o_current->picture->lower_x, o_current->picture->lower_y, 
  			  &screen_x2, &screen_y2);  
  o_current->picture->screen_lower_x = screen_x2;
  o_current->picture->screen_lower_y = screen_y2;
  
  @ 
  
  
  <<o_picture_recalc() : update the bounding picture in screen unit>>=
  /* update the bounding picture - screen unit */
  get_picture_bounds(w_current, o_current->picture, &left, &top, &right, &bottom);
  o_current->left   = left;
  o_current->top    = top;
  o_current->right  = right;
  o_current->bottom = bottom;
  
  @ 
  
  
  <<o_picture_recalc() : update the object general fields>>=
  /* recalc OBJECT specific parameters */
  o_object_recalc(w_current, o_current);
  
  @ 
  
  @section Function [[get_picture_bounds()]]
  
  @defun get_picture_bounds w_current object left top right bottom
  The [[get_picture_bounds()]] function set the [[left]], [[top]], [[right]] and [[bottom]] pointed variables to the boundings of the picture object described in [[*picture]] in screen unit.
  @end defun
  
  <<o_picture_basic.c : get_picture_bounds()>>=
  void
  get_picture_bounds(TOPLEVEL *w_current, PICTURE *picture,
  			   int *left, int *top, int *right, int *bottom)
  {
    *left   = picture->screen_upper_x;
    *top    = picture->screen_upper_y;
    *right  = picture->screen_lower_x;
    *bottom = picture->screen_lower_y;
  
  }
  
  @ %def get_picture_bounds
  
  
  @section Function [[world_get_picture_bounds()]]
  
  @defun world_get_picture_bounds w_current picture left top right bottom
  The [[world_get_picture_bounds()]] function sets the [[left]], [[top]], [[right]] and [[bottom]] pointed variables to the boundings of the picture object described in [[*picture]] in world unit.
  @end defun
  
  <<o_picture_basic.c : world_get_picture_bounds()>>=
  void
  world_get_picture_bounds(TOPLEVEL *w_current, PICTURE *picture,
  					 int *left, int *top, int *right, int *bottom)
  {
  	/* pb20011002 - why using min and max here and not above ? */
  	*left   = min(picture->upper_x, picture->lower_x);
  	*top    = min(picture->upper_y, picture->lower_y);
  	*right  = max(picture->upper_x, picture->lower_x);
  	*bottom = max(picture->upper_y, picture->lower_y);
  	
  	/* PB : same as above here for width of edges */	
  
  #if DEBUG 
  	printf("picture: %d %d %d %d\n", *left, *top, *right, *bottom);
  #endif
  	
  }
                   
  @ %def world_get_picture_bounds
  
  
  @section Function [[o_picture_modify()]]
  
  @defun o_picture_modify w_current object x y whichone
  This function modifies the coordinates of one of the four corner of the picture. The new coordinates of the corner identified by [[whichone]] are given by [[x]] and [[y]] in world unit.
  @end defun
  
  The coordinates of the corner is modified in the world coordinate system. Screen coordinates and boundings are then updated.
  
  <<o_picture_basic.c : o_picture_modify()>>=
  /* pb20011002 - rewritten : old one did not used x, y and whichone */
  void
  o_picture_modify(TOPLEVEL *w_current, OBJECT *object, 
  			 int x, int y, int whichone)
  {
  	int tmp;
  	
  	/* change the position of the selected corner */
  	switch(whichone) {
  		case PICTURE_UPPER_LEFT:
  			object->picture->upper_x = x;
   			tmp = abs(object->picture->upper_x - object->picture->lower_x) / 
  			  object->picture->ratio;
  			if (y < object->picture->lower_y) {
  			  tmp = -tmp;
  			}
  			object->picture->upper_y = object->picture->lower_y + tmp;
  			break;
  			
  		case PICTURE_LOWER_LEFT:
  			object->picture->upper_x = x;
   			tmp = abs(object->picture->upper_x - object->picture->lower_x) / 
  			  object->picture->ratio;
  			if (y > object->picture->upper_y) {
  			  tmp = -tmp;
  			}
  			object->picture->lower_y = object->picture->upper_y - tmp;
  			break;
  			
  		case PICTURE_UPPER_RIGHT:
  			object->picture->lower_x = x;
   			tmp = abs(object->picture->upper_x - object->picture->lower_x) / 
  			  object->picture->ratio;
  			if (y < object->picture->lower_y) {
  			  tmp = -tmp;
  			}
  			object->picture->upper_y = object->picture->lower_y + tmp;
  			break;
                          			
  		case PICTURE_LOWER_RIGHT:
  			object->picture->lower_x = x;
   			tmp = abs(object->picture->upper_x - object->picture->lower_x) / 
  			  object->picture->ratio;
  			if (y > object->picture->upper_y) {
  			  tmp = -tmp;
  			}
  			object->picture->lower_y = object->picture->upper_y - tmp;
  			break;
  			
  		default:
  			return;
  	}
  	
  	/* need to update the upper left and lower right corners */
  	if(object->picture->upper_x > object->picture->lower_x) {
  		tmp                  = object->picture->upper_x;
  		object->picture->upper_x = object->picture->lower_x;
  		object->picture->lower_x = tmp;
  	}
  	
  	if(object->picture->upper_y < object->picture->lower_y) {
  		tmp                  = object->picture->upper_y;
  		object->picture->upper_y = object->picture->lower_y;
  		object->picture->lower_y = tmp;
  	}
  	
  	/* recalculate the screen coords and the boundings */
  	o_picture_recalc(w_current, object);
    
  }
  
  @ %def o_picture_modify
  
  
  @section Function [[o_picture_rotate()]]
  
  @defun o_picture_rotate w_current centerx centery angle object
  This function applies a rotation of center ([[centerx]], [[centery]]) and angle [[angle]] to the picture object [[*object]].
  The coordinates of the rotation center are in screen units. 
  [[angle]] must be a 90 degree multiple. If not, no rotation is applied.
  @end defun
  
  The rotation is made with the [[o_picture_rotate_world()]] function that perform a rotation of angle [[angle]] and center ([[world_centerx]], [[world_centery]]) in world unit.
  
  <<o_picture_basic.c : o_picture_rotate()>>=
  /* takes in screen coordinates for the centerx,y, and then does the rotate 
   * in world space */
  /* also ignores angle argument... for now, rotate only in 90 degree 
   * increments */
  /* fixed to 90 degrees... it's *not* general now */
  void
  o_picture_rotate(TOPLEVEL *w_current,
  		 int centerx, int centery, int angle,
                   OBJECT *object)
  {
    int world_centerx, world_centery;
  
    /* convert the center of rotation to world unit */
    SCREENtoWORLD(w_current,
  				centerx, centery, 
                  &world_centerx, &world_centery);  
  
    /* rotate the picture */
    /* the check of the rotation angle is in o_picture_rotate_world() */
    o_picture_rotate_world(w_current,
  					 world_centerx, world_centery, angle,
  					 object);
  
    /* screen coords and boundings are updated by _rotate_world() */
    
  }
  
  @ %def o_picture_rotate
  
  
  @section Function [[o_picture_rotate_world()]]
  
  @defun o_picture_rotate_world w_current world_centerx world_centery angle object
  The function [[o_picture_rotate_world()]] rotate the picture described by [[*object]] around the ([[world_centerx]], [[world_centery]]) point by [[angle]] degrees.
  The center of rotation is in world unit.
  @end defun
  
  <<o_picture_basic.c : o_picture_rotate_world()>>=
  void
  o_picture_rotate_world(TOPLEVEL *w_current, 
                     int world_centerx, int world_centery, int angle,
                     OBJECT *object)
  {
  	int newx1, newy1;
  	int newx2, newy2;
  
  	<<o_picture_rotate_world() : check the rotation angle>>
  
  	<<o_picture_rotate_world() : rotate the picture world coords>>
  
  	<<o_picture_rotate_world() : update the screen coords>>
  	
  }
  
  @ %def o_picture_rotate_world
  
  
  Only 90 degree multiple and positive angles are allowed.
  
  <<o_picture_rotate_world() : check the rotation angle>>=
  /* angle must be positive */
  if(angle < 0) angle = -angle;
  /* angle must be a 90 multiple or no rotation performed */
  if((angle % 90) != 0) return;
  
  object->picture->angle = ( object->picture->angle + angle ) % 360;
  
  @ 
  
  
  The center of rotation ([[world_centerx]], [[world_centery]]) is translated to the origin. The rotation of the upper left and lower right corner are then performed. Finally, the rotated picture is translated back to its previous location.
  
  <<o_picture_rotate_world() : rotate the picture world coords>>=
  /* translate object to origin */
  object->picture->upper_x -= world_centerx;
  object->picture->upper_y -= world_centery;
  object->picture->lower_x -= world_centerx;
  object->picture->lower_y -= world_centery;
  
  /* rotate the upper left corner of the picture */
  rotate_point_90(object->picture->upper_x, object->picture->upper_y, angle,
  				&newx1, &newy1);
  
  /* rotate the lower left corner of the picture */
  rotate_point_90(object->picture->lower_x, object->picture->lower_y, angle,
  				&newx2, &newy2);
  
  /* reorder the corners after rotation */
  object->picture->upper_x = min(newx1,newx2);
  object->picture->upper_y = max(newy1,newy2);
  object->picture->lower_x = max(newx1,newx2);
  object->picture->lower_y = min(newy1,newy2);
  
  /* translate object back to normal position */
  object->picture->upper_x += world_centerx;
  object->picture->upper_y += world_centery;
  object->picture->lower_x += world_centerx;
  object->picture->lower_y += world_centery;
  
  @ 
  
  
  <<o_picture_rotate_world() : update the screen coords>>=
  /* recalc boundings and screen coords */
  o_picture_recalc(w_current, object);
  
  @ 
  
  
  @section Function [[o_picture_mirror()]]
  
  @defun o_picture_mirror w_current centerx centery object
  This function mirrors the picture from the point ([[centerx]],[[centery]]) in screen unit.
  @end defun
  
  The origin of the mirror in screen unit is converted in world unit. The picture is mirrored with the function [[o_picture_mirror_world()]] for which the origin of the mirror must be given in world unit.
  
  <<o_picture_basic.c : o_picture_mirror()>>=
  void
  o_picture_mirror(TOPLEVEL *w_current,
  			 int centerx, int centery,
  			 OBJECT *object)
  {
    int world_centerx, world_centery;
  
    /* convert the origin of mirror */
    SCREENtoWORLD(w_current, centerx, centery, 
                  &world_centerx,
                  &world_centery);  
  
    /* apply the mirror in world coords */
    o_picture_mirror_world(w_current,
  					 world_centerx, world_centery,
  					 object);
  
    /* screen coords and boundings are updated by _mirror_world() */
    
  }
  
  @ %def o_picture_mirror
  
  
  @section Function [[o_picture_mirror_world()]]
  
  @defun o_picture_mirror_world w_current world_centerx world_centery object
  This function mirrors the picture from the point ([[world_centerx]],[[world_centery]]) in world unit.
  @end defun
  
  The picture is first translated to the origin, then mirrored and finally translated back at its previous position.
  
  <<o_picture_basic.c : o_picture_mirror_world()>>=
  void
  o_picture_mirror_world(TOPLEVEL *w_current,
  				   int world_centerx, int world_centery,
                     OBJECT *object)
  {
    int newx1, newy1;
    int newx2, newy2;
  
    
    /* Set info in object */
    object->picture->mirrored = (object->picture->mirrored ^ 1) & 1;
  
    /* translate object to origin */
    object->picture->upper_x -= world_centerx;
    object->picture->upper_y -= world_centery;
    object->picture->lower_x -= world_centerx;
    object->picture->lower_y -= world_centery;
  
    /* mirror the corners */
    newx1 = -object->picture->upper_x;
    newy1 = object->picture->upper_y;
    newx2 = -object->picture->lower_x;
    newy2 = object->picture->lower_y;
  
    /* reorder the corners */
    object->picture->upper_x = min(newx1,newx2);
    object->picture->upper_y = max(newy1,newy2);
    object->picture->lower_x = max(newx1,newx2);
    object->picture->lower_y = min(newy1,newy2);
  
    /* translate back in position */
    object->picture->upper_x += world_centerx;
    object->picture->upper_y += world_centery;
    object->picture->lower_x += world_centerx;
    object->picture->lower_y += world_centery;
  
    /* recalc boundings and screen coords */
    o_picture_recalc(w_current, object);
    
  }
  
  @ %def o_picture_mirror_world
  
  
  
  @section Function [[o_picture_translate()]]
  
  @defun o_picture_translate w_current dx dy object
  This function applies a translation of ([[dx]],[[dy]]) to the picture described by [[*object]]. [[dx]] and [[dy]] are in screen unit.
  @end defun
  
  The translation vector is converted in world unit. The translation is made with [[o_picture_translate_world()]].
  
  <<o_picture_basic.c : o_picture_translate()>>=
  void
  o_picture_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
  {
    int world_dx, world_dy;
  
    if (object == NULL) printf("bt NO!\n");
  
    /* convert the translation vector in world unit */
    world_dx = SCREENabs(w_current, dx);
    world_dy = SCREENabs(w_current, dy);
  
    /* translate the picture */
    o_picture_translate_world(w_current, world_dx, world_dy, object);
  
    /* screen coords and boundings are updated by _translate_world */
    
  }
  
  @ %def o_picture_translate
  
  
  @section Function [[o_picture_translate_world()]]
  
  @defun o_picture_translate_world w_current x1 y1 object
  This function applies a translation of ([[x1]],[[y1]]) to the picture described by [[*object]]. [[x1]] and [[y1]] are in world unit.
  @end defun
  
  <<o_picture_basic.c : o_picture_translate_world()>>=
  void
  o_picture_translate_world(TOPLEVEL *w_current, int x1, int y1, OBJECT *object)
  {
    if (object == NULL) printf("btw NO!\n");
  
    <<o_picture_translate_world() : translate the picture>>
  
    <<o_picture_translate_world() : update the screen coordinates>>
    
  }
  
  @ %def o_picture_translate_world
  
  
  <<o_picture_translate_world() : translate the picture>>=
  /* Do world coords */
  object->picture->upper_x = object->picture->upper_x + x1;
  object->picture->upper_y = object->picture->upper_y + y1;
  object->picture->lower_x = object->picture->lower_x + x1;
  object->picture->lower_y = object->picture->lower_y + y1;     
  
  @ 
  
  
  <<o_picture_translate_world() : update the screen coordinates>>=
  /* recalc the screen coords and the bounding picture */
  o_picture_recalc(w_current, object);
  
  @ 
  
  
  @section Function [[o_picture_copy()]]
  
  @defun o_picture_copy w_current list_tail o_current
  The function [[o_picture_copy()]] creates a verbatim copy of the object pointed by [[o_current]] describing a picture. The new object is added at the end of the list, following the [[list_tail]] pointed object.
  @end defun
  
  The function returns a new pointer on the end of the object list.
  
  <<o_picture_basic.c : o_picture_copy()>>=
  OBJECT *
  o_picture_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
  {
    OBJECT *new_obj;
    ATTRIB *a_current;
    int color;
  	
    if (o_current->saved_color == -1) {
      color = o_current->color;
    } else {
      color = o_current->saved_color;
    }
  
    <<o_picture_copy() : create and insert a new object in the list>>
  
    <<o_picture_copy() : modify the fields of the new object>>
  
    <<o_picture_copy() : copy the attributes>>
  
    /* return the new tail of the object list */
    return(new_obj);
  } 
  
  @ %def o_picture_copy
  
  
  A new picture object is added at the end of the object list with [[o_picture_add()]]. Values for its fields are default and need to be modified.
  
  <<o_picture_copy() : create and insert a new object in the list>>=
  /* create and link a new picture object */	
  new_obj = o_picture_add(w_current, list_tail,
  			w_current->current_pixbuf, 
  			w_current->pixbuf_filename, 
  			w_current->pixbuf_wh_ratio,
  			OBJ_PICTURE,
  			0, 0, 0, 0, 0, FALSE, FALSE);
  
  @ 
  
  
  The dimensions of the new picture are set with the ones of the original picture. The two picturees have the same line type and the same filling options.
  
  The coordinates and the values in screen unit are computed with [[o_picture_recalc()]].
  
  <<o_picture_copy() : modify the fields of the new object>>=
  /* modifying */
  /* pb20011002 - have to check if o_current is a picture object */
  new_obj->picture->upper_x = o_current->picture->upper_x;
  new_obj->picture->upper_y = o_current->picture->upper_y;
  new_obj->picture->lower_x = o_current->picture->lower_x;
  new_obj->picture->lower_y = o_current->picture->lower_y;
  	
  /* Copy the picture data */
  new_obj->picture->original_picture = gdk_pixbuf_scale_simple(o_current->picture->original_picture,
                                         gdk_pixbuf_get_width (o_current->picture->original_picture),
                                         gdk_pixbuf_get_height (o_current->picture->original_picture),
                                         GDK_INTERP_BILINEAR);
  new_obj->picture->displayed_picture = gdk_pixbuf_scale_simple(o_current->picture->displayed_picture,
                                         gdk_pixbuf_get_width (o_current->picture->displayed_picture),
                                         gdk_pixbuf_get_height (o_current->picture->displayed_picture),
                                         GDK_INTERP_BILINEAR);
  
  new_obj->picture->ratio = o_current->picture->ratio;
  new_obj->picture->filename = g_strdup(o_current->picture->filename);
  
  new_obj->picture->angle = o_current->picture->angle;
  new_obj->picture->mirrored = o_current->picture->mirrored;
  
  o_picture_recalc(w_current, new_obj);
  
  @ 
  
  
  <<o_picture_copy() : copy the attributes>>=
  /*	new_obj->attribute = 0;*/
  a_current = o_current->attribs;
  if (a_current) {
      while ( a_current ) {
  		
  		/* head attrib node has prev = NULL */
  		if (a_current->prev != NULL) {
  			a_current->copied_to = new_obj;
  		}
  		a_current = a_current->next;
      }
  }
  
  @