File o_circle_basic.c
*********************

File header
===========

     <<o_circle_basic.c : *>>=
     <<o_circle_basic.c : copyright and license -- o_circle_basic.c - copyright and license>>

     /* DO NOT read or edit this file ! Use ../noweb/o_circle_basic.nw instead */

     <<o_circle_basic.c : include directives -- o_circle_basic.c - include directives>>

     <<o_circle_basic.c : dist() -- o_circle_basic.c - dist()>>

     <<o_circle_basic.c : o_circle_add() -- o_circle_basic.c - o_circle_add()>>

     <<o_circle_basic.c : o_circle_copy() -- o_circle_basic.c - o_circle_copy()>>

     <<o_circle_basic.c : o_circle_modify() -- o_circle_basic.c - o_circle_modify()>>

     <<o_circle_basic.c : o_circle_read() -- o_circle_basic.c - o_circle_read()>>
     <<o_circle_basic.c : o_circle_save() -- o_circle_basic.c - o_circle_save()>>

     <<o_circle_basic.c : o_circle_translate() -- o_circle_basic.c - o_circle_translate()>>
     <<o_circle_basic.c : o_circle_translate_world() -- o_circle_basic.c - o_circle_translate_world()>>

     <<o_circle_basic.c : o_circle_rotate() -- o_circle_basic.c - o_circle_rotate()>>
     <<o_circle_basic.c : o_circle_rotate_world() -- o_circle_basic.c - o_circle_rotate_world()>>

     <<o_circle_basic.c : o_circle_mirror() -- o_circle_basic.c - o_circle_mirror()>>
     <<o_circle_basic.c : o_circle_mirror_world() -- o_circle_basic.c - o_circle_mirror_world()>>

     <<o_circle_basic.c : o_circle_recalc() -- o_circle_basic.c - o_circle_recalc()>>

     <<o_circle_basic.c : get_circle_bounds() -- o_circle_basic.c - get_circle_bounds()>>
     <<o_circle_basic.c : world_get_circle_bounds() -- o_circle_basic.c - world_get_circle_bounds()>>

     <<o_circle_basic.c : o_circle_print() -- o_circle_basic.c - o_circle_print()>>
     <<o_circle_basic.c : o_circle_print_solid() -- o_circle_basic.c - o_circle_print_solid()>>
     <<o_circle_basic.c : o_circle_print_dotted() -- o_circle_basic.c - o_circle_print_dotted()>>
     <<o_circle_basic.c : o_circle_print_dashed() -- o_circle_basic.c - o_circle_print_dashed()>>
     <<o_circle_basic.c : o_circle_print_center() -- o_circle_basic.c - o_circle_print_center()>>
     <<o_circle_basic.c : o_circle_print_phantom() -- o_circle_basic.c - o_circle_print_phantom()>>
     <<o_circle_basic.c : o_circle_print_filled() -- o_circle_basic.c - o_circle_print_filled()>>
     <<o_circle_basic.c : o_circle_print_mesh() -- o_circle_basic.c - o_circle_print_mesh()>>
     <<o_circle_basic.c : o_circle_print_hatch() -- o_circle_basic.c - o_circle_print_hatch()>>

     #if 0 /* original way of printing circle, no longer used */
     <<o_circle_basic.c : o_circle_print_old() -- o_circle_basic.c - o_circle_print_old()>>
     #endif

     <<o_circle_basic.c : o_circle_image_write() -- o_circle_basic.c - o_circle_image_write()>>

     <<o_circle_basic.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_circle_basic.c : include directives>>=
     #include <config.h>
     #include <stdio.h>
     #include <math.h>

     #include <gtk/gtk.h>
     #include <libguile.h>

     #ifdef HAS_LIBGDGEDA
     #include <gdgeda/gd.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"

     #ifdef HAVE_LIBDMALLOC
     #include <dmalloc.h>
     #endif

Function dist()
===============

 -- Function: dist x1 y1 x2 y2

     <<o_circle_basic.c : dist()>>=
     int
     dist(int x1, int y1, int x2, int y2)
     {
       int dx1, dy1;
       int dx2, dy2;
       int ret;

       dx1 = x1;
       dy1 = y1;
       dx2 = x2;
       dy2 = y2;

       ret =  sqrt(pow(dx1-dx2,2)+pow(dy1-dy2,2)) ;
       return( ret );
     }

          Defines :
          .

     }

Function o_circle_add()
=======================

 -- Function: o_circle_add w_current object_list type color x y radius
     This function creates a new object representing a circle. This object is added to the end of the list object_list pointed object belongs to. The circle is described by its center (x,y) and its radius radius. The type parameter must be equal to OBJ_CIRCLE. The color corresponds to the color the box will be drawn with.

The OBJECT structure is allocated with the s_basic_init_object() function. The structure describing the circle is allocated and initialized with the parameters given to the function.

Both the line type and the filling type are set to default values : solid line type with a width of 0, and no filling. It can be changed after with o_set_line_options() and o_set_fill_options().

The object is added to the end of the list described by the object_list parameter with s_basic_link_object().

The function returns a pointer on the new end of the object list.

     <<o_circle_basic.c : o_circle_add()>>=
     OBJECT *
     o_circle_add(TOPLEVEL *w_current, OBJECT *object_list,
                  char type, int color,
                  int x, int y, int radius)
     {
       OBJECT *new_node;

       <<o_circle_add() : allocate memory for the new circle -- o_circle_add() - allocate memory for the new circle>>

       <<o_circle_add() : initialize the circle -- o_circle_add() - initialize the circle>>

       <<o_circle_add() : calculate the screen coords and the bounding box -- o_circle_add() - calculate the screen coords and the bounding box>>

       <<o_circle_add() : add the object to the list -- o_circle_add() - add the object to the list>>

       return(object_list);
     }

          Defines :
          o_circle_add,
           -- o_circle_read() - add the new circle to the list of objects,
           -- o_circle_copy() - create and insert a new object in the list.

     }

     <<o_circle_add() : allocate memory for the new circle>>=
     /* create the object */
     new_node         = s_basic_init_object("circle");
     new_node->type   = type;
     new_node->color  = color;

     new_node->circle = (CIRCLE *) malloc(sizeof(CIRCLE));

     <<o_circle_add() : initialize the circle>>=
     /* describe the circle with its center and radius */
     new_node->circle->center_x = x;
     new_node->circle->center_y = y;
     new_node->circle->radius   = radius;

     /* line type and filling initialized to default */
     o_set_line_options(w_current, new_node,
                                        END_NONE, TYPE_SOLID, 0, -1, -1);
     o_set_fill_options(w_current, new_node,
                                        FILLING_HOLLOW, -1, -1, -1, -1, -1);

     /* TODO: questionable cast */
     new_node->draw_func = (void *) circle_draw_func;
     /* TODO: questionable cast */
     new_node->sel_func = (void *) select_func;

     <<o_circle_add() : calculate the screen coords and the bounding box>>=
     /* compute the bounding box and screen coords */
     o_circle_recalc(w_current, new_node);

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

     <<o_circle_add() : add the object to the list>>=
     /* add the object to the list */
     object_list = (OBJECT *) s_basic_link_object(new_node, object_list);

Function o_circle_copy()
========================

 -- Function: o_circle_copy w_current list_tail o_current
     The function o_circle_copy() creates a verbatim copy of the object pointed by o_current describing a circle. The new object is added at the end of the list, following the list_tail pointed object.

The function returns the new pointer on the end of the object list.

     <<o_circle_basic.c : o_circle_copy()>>=
     OBJECT *
     o_circle_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_circle_copy() : create and insert a new object in the list -- o_circle_copy() - create and insert a new object in the list>>

       <<o_circle_copy() : modify the fields of the new object -- o_circle_copy() - modify the fields of the new object>>

       <<o_circle_copy() : copy the attributes -- o_circle_copy() - copy the attributes>>

       return(new_obj);
     }

          Defines :
          .

     }

A new circle object is added at the end of the object list with o_circle_add(). Values for its fields are default and need to be modified.

     <<o_circle_copy() : create and insert a new object in the list>>=
     /* create and link a new circle object */
     new_obj = o_circle_add(w_current, list_tail, OBJ_CIRCLE,
                                                color,
                                                0, 0, 0);

          Uses :
          o_circle_add,  -- o_circle_basic.c - o_circle_add().

     }

The parameters of the new circle are set with the ones of the original circle. The two circle have the same line type and the same filling options.

The coordinates and the values in screen unit are computed with o_circle_recalc().

     <<o_circle_copy() : modify the fields of the new object>>=
     /* modify */
     new_obj->circle->center_x = o_current->circle->center_x;
     new_obj->circle->center_y = o_current->circle->center_y;
     new_obj->circle->radius   = o_current->circle->radius;

     o_set_line_options(w_current, new_obj, o_current->line_end,
                                        o_current->line_type, o_current->line_width,
                                        o_current->line_length, o_current->line_space);
     o_set_fill_options(w_current, new_obj,
                                        o_current->fill_type, o_current->fill_width,
                                        o_current->fill_pitch1, o_current->fill_angle1,
                                        o_current->fill_pitch2, o_current->fill_angle2);

     o_circle_recalc(w_current, new_obj);

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

     <<o_circle_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;
         }
     }

Function o_circle_modify()
==========================

 -- Function: o_circle_modify w_current object x y whichone
     This function modifies the description of the circle object *object depending on whichone that give the meaning of the x and y parameters.

     If whichone is equal to CIRCLE_CENTER, the new center of the circle is given by (x,y) where x and y are in world units.

     If whichone is equal to CIRCLE_RADIUS, the radius is given by x - in world units. y is ignored.

The screen coords and the bounding box of the circle object are updated after the modification of its parameters.

     <<o_circle_basic.c : o_circle_modify()>>=
     void
     o_circle_modify(TOPLEVEL *w_current, OBJECT *object,
                     int x, int y, int whichone)
     {
       switch(whichone) {
               case CIRCLE_CENTER:
                       /* modify the center of the circle */
                       object->circle->center_x = x;
                       object->circle->center_y = y;
                       break;
               case CIRCLE_RADIUS:
                       /* modify the radius of the circle */
                       if (x == 0) {
                               s_log_message("Null radius circles are not allowed\n");
                               return;
                       }
                       object->circle->radius = x;
                       break;
               default:

               break;
       }

       /* recalculate the screen coords and the boundings */
       o_circle_recalc(w_current, object);

     }

          Defines :
          .

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

Function o_circle_read()
========================

 -- Function: o_circle_read w_current object_list buf version
     The o_circle_read() function gets from the character string *buff the description of a circle. The new circle is then added to the list of objects of which *object_list is the last element before the call. The function returns the new last element, that is the added circle object.

Depending on *version, the right file format is considered. Currently two file format revisions are supported :

  * the file format used until 2000704 release ;

  * the file format used for the releases after 20000704.

     <<o_circle_basic.c : o_circle_read()>>=
     OBJECT *
     o_circle_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
                   unsigned int release_ver, unsigned int fileformat_ver)
     {
       char type;
       int x1, y1;
       int radius;
       int color;
       int circle_width, circle_space, circle_length;
       int fill_width, angle1, pitch1, angle2, pitch2;
       int circle_end;
       int circle_type;
       int circle_fill;

       if(release_ver <= VERSION_20000704) {
               <<o_circle_read() : old geda file format -- o_circle_read() - old geda file format>>

       } else {
               <<o_circle_read() : geda file format after release 20000704 -- o_circle_read() - geda file format after release 20000704>>

       }

       <<o_circle_read() : check the values of the parameters -- o_circle_read() - check the values of the parameters>>

       <<o_circle_read() : add the new circle to the list of objects -- o_circle_read() - add the new circle to the list of objects>>

       return(object_list);
     }

          Defines :
          .

     }

The old geda file format, i.e. releases 20000704 and older, does not handle the line type and the filling of the box object. They are set to default.

     <<o_circle_read() : old geda file format>>=
     sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color);

     circle_width = 0;
     circle_end   = END_NONE;
     circle_type  = TYPE_SOLID;
     circle_length= -1;
     circle_space = -1;

     circle_fill  = FILLING_HOLLOW;
     fill_width  = 0;
     angle1      = -1;
     pitch1      = -1;
     angle2      = -1;
     pitch2      = -1;

The current line format to describe a circle is a space separated list of characters and numbers in plain ASCII on a single line. The meaning of each item is described in the file format documentation.

     <<o_circle_read() : geda file format after release 20000704>>=
     sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
                &type, &x1, &y1, &radius, &color,
                &circle_width, &circle_end, &circle_type,
                &circle_length, &circle_space, &circle_fill,
                &fill_width, &angle1, &pitch1, &angle2, &pitch2);

     <<o_circle_read() : check the values of the parameters>>=
     if (radius == 0) {
         fprintf(stderr, "Found a zero radius circle [ %c %d %d %d %d ]\n",
                 type, x1, y1, radius, color);
         s_log_message("Found a zero radius circle [ %c %d %d %d %d ]\n",
                       type, x1, y1, radius, color);

     }

     if (color < 0 || color > MAX_COLORS) {
         fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
         s_log_message("Found an invalid color [ %s ]\n", buf);
         s_log_message("Setting color to WHITE\n");
         color = WHITE;
     }

A circle is internally described by its center and its radius.

A new object is allocated, initialized and added to the object list. Its filling and line type are set according to the values of the field on the line.

     <<o_circle_read() : add the new circle to the list of objects>>=
     object_list = (OBJECT *) o_circle_add(w_current, object_list,
                                                                               type, color, x1, y1, radius);
     o_set_line_options(w_current, object_list,
                                        circle_end, circle_type, circle_width,
                                        circle_length, circle_space);
     o_set_fill_options(w_current, object_list,
                                        circle_fill, fill_width, pitch1, angle1, pitch2, angle2);

          Uses :
          o_circle_add,  -- o_circle_basic.c - o_circle_add().

     }

Function o_circle_save()
========================

 -- Function: o_circle_save buf object
     This function formats a string in the buffer *buff to describe the circle object *object. It follows the post-20000704 release file format that handle the line type and fill options. A pointer to the new allocated and formated string is returned. The string must be freed at some point.

     <<o_circle_basic.c : o_circle_save()>>=
     char *
     o_circle_save(OBJECT *object)
     {
       int x,y;
       int radius;
       int color;
       int circle_width, circle_space, circle_length;
       int fill_width, angle1, pitch1, angle2, pitch2;
       char *buf;
       OBJECT_END circle_end;
       OBJECT_TYPE circle_type;
       OBJECT_FILLING circle_fill;

       <<o_circle_save() : prepare the description of the circle -- o_circle_save() - prepare the description of the circle>>

     #if 0 /* old system */
       radius = abs(x2 - x1)/2;
       if (radius == 0) {
         radius = abs(y2 - y1)/2;
       }

       x = x1 + radius;
       y = y1 - radius; /* careful */
     #endif

       <<o_circle_save() : describe a circle with post-20000704 file format -- o_circle_save() - describe a circle with post-20000704 file format>>

       return(buf);
     }

          Defines :
          .

     }

     <<o_circle_save() : prepare the description of the circle>>=
     /* circle center and radius */
     x = object->circle->center_x;
     y = object->circle->center_y;
     radius = object->circle->radius;

     /* line type parameters */
     circle_width = object->line_width;
     circle_end   = object->line_end;
     circle_type  = object->line_type;
     circle_length= object->line_length;
     circle_space = object->line_space;

     /* filling parameters */
     circle_fill  = object->fill_type;
     fill_width   = object->fill_width;
     angle1       = object->fill_angle1;
     pitch1       = object->fill_pitch1;
     angle2       = object->fill_angle2;
     pitch2       = object->fill_pitch2;

     /* Use the right color */
     if (object->saved_color == -1) {
         color = object->color;
     } else {
         color = object->saved_color;
     }

     <<o_circle_save() : describe a circle with post-20000704 file format>>=
     buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
                           object->type, x, y, radius, color,
                           circle_width, circle_end, circle_type, circle_length,
                           circle_space, circle_fill,
                           fill_width, angle1, pitch1, angle2, pitch2);

Function o_circle_translate()
=============================

 -- Function: o_circle_translate w_current dx dy object
     This function applies a translation of (dx,dy to the circle described by *object. dx and dy are in screen unit.

The translation vector is converted in world unit. The translation is made with o_circle_translate_world().

     <<o_circle_basic.c : o_circle_translate()>>=
     void
     o_circle_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
     {
             int world_dx, world_dy;

             if (object == NULL) printf("ct NO!\n");

             /* convert the translation vector in world unit */
             world_dx = SCREENabs(w_current, dx);
             world_dy = SCREENabs(w_current, dy);

             /* translate the circle */
             o_circle_translate_world(w_current, world_dx, world_dy, object);

             /* screen coords and boundings are updated by _translate_world() */

     }

          Defines :
          .

          Uses :
          o_circle_translate_world,  -- o_circle_basic.c - o_circle_translate_world().

     }

Function o_circle_translate_world()
===================================

 -- Function: o_circle_translate_world w_current x1 y1 object
     This function applies a translation of (x1,y1) to the circle described by *object. x1 and y1 are in world unit.

     <<o_circle_basic.c : o_circle_translate_world()>>=
     void
     o_circle_translate_world(TOPLEVEL *w_current, int x1, int y1, OBJECT *object)
     {
       if (object == NULL) printf("ctw NO!\n");

       <<o_circle_translate_world() : translate the circle -- o_circle_translate_world() - translate the circle>>

       <<o_circle_translate_world() : update the screen coordinates -- o_circle_translate_world() - update the screen coordinates>>

     }

          Defines :
          o_circle_translate_world,
           -- o_circle_basic.c - o_circle_translate().

     }

     <<o_circle_translate_world() : translate the circle>>=
     /* Do world coords */
     object->circle->center_x = object->circle->center_x + x1;
     object->circle->center_y = object->circle->center_y + y1;

     <<o_circle_translate_world() : update the screen coordinates>>=
     /* recalc the screen coords and the bounding box */
     o_circle_recalc(w_current, object);

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

Function o_circle_rotate()
==========================

 -- Function: o_circle_rotate w_current centerx centery angle object
     This function applies a rotation of center (centerx,centery) and angle angle to the circle 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.

The rotation is made by the o_circle_rotate_world() function that perform a rotation of angle angle and center (world_centerx,world_centery) in world unit.

     <<o_circle_basic.c : o_circle_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 */
     void
     o_circle_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 circle */
       o_circle_rotate_world(w_current,
                                                     world_centerx, world_centery, angle,
                                                     object);

       /* screen coords and boundings are updated by _rotate_world() */

     }

          Defines :
          .

          Uses :
          o_circle_rotate_world,  -- o_circle_basic.c - o_circle_rotate_world().

     }

Function o_circle_rotate_world()
================================

 -- Function: o_circle_rotate_world w_current world_centerx world_centery angle object
     The function o_circle_rotate_world() rotate the circle described by *object around the (world_centerx,world_centery) point by angle angle degrees. The center of rotation is in world unit.

     <<o_circle_basic.c : o_circle_rotate_world()>>=
     void
     o_circle_rotate_world(TOPLEVEL *w_current,
                           int world_centerx, int world_centery, int angle,
                           OBJECT *object)
     {
       int newx, newy;
       int x, y;

       <<o_circle_rotate_world() : check the rotation angle -- o_circle_rotate_world() - check the rotation angle>>

       <<o_circle_rotate_world() : rotate the circle center in world coords -- o_circle_rotate_world() - rotate the circle center in world coords>>

       <<o_circle_rotate_world() : update the screen coords and boundings -- o_circle_rotate_world() - update the screen coords and boundings>>

     }

          Defines :
          o_circle_rotate_world,
           -- o_circle_basic.c - o_circle_rotate().

     }

Only 90 degree multiple and positive angles are allowed.

     <<o_circle_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;

The center of rotation (world_centerx,world_centery) is translated to the origin. The rotation of the center around the origin is then performed. Finally, the rotated circle is translated back to its previous location.

     <<o_circle_rotate_world() : rotate the circle center in world coords>>=
     /* translate object to origin */
     object->circle->center_x -= world_centerx;
     object->circle->center_y -= world_centery;

     /* rotate the center of the circle around the origin */
     x = object->circle->center_x;
     y = object->circle->center_y;
     rotate_point_90(x, y, angle, &newx, &newy);
     object->circle->center_x = newx;
     object->circle->center_y = newy;

     /* translate back in position */
     object->circle->center_x += world_centerx;
     object->circle->center_y += world_centery;

     <<o_circle_rotate_world() : update the screen coords and boundings>>=
     o_circle_recalc(w_current, object);

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

Function o_circle_mirror()
==========================

 -- Function: o_circle_mirror w_current centerx centery object
     This function mirrors the box from the point (centerx,centery) in screen unit.

The origin of the mirror in screen unit is converted in world unit. The circle is mirrored with the function o_circle_mirrir_world() for which the origin of the mirror must be given in world unit.

     <<o_circle_basic.c : o_circle_mirror()>>=
     void
     o_circle_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_circle_mirror_world(w_current,
                                                     world_centerx, world_centery,
                                                     object);

       /* screen coords and boundings are updated by _mirror_world() */

     }

          Defines :
          .

          Uses :
          o_circle_mirror_world,  -- o_circle_basic.c - o_circle_mirror_world().

     }

Function o_circle_mirror_world()
================================

 -- Function: o_circle_mirror_world w_current world_centerx world_centery object
     This function mirrors the circle from the point (world_centerx,world_centery) in world unit.

The circle is first translated to the origin, then mirrored and finally translated back at its previous location.

The bounding box and the screen coords of the circle are recalculated after mirroring.

     <<o_circle_basic.c : o_circle_mirror_world()>>=
     void
     o_circle_mirror_world(TOPLEVEL *w_current,
                                               int world_centerx, int world_centery,
                                               OBJECT *object)
     {
       /* translate object to origin */
       object->circle->center_x -= world_centerx;
       object->circle->center_y -= world_centery;

       /* mirror the center of the circle */
       object->circle->center_x = -object->circle->center_x;
       object->circle->center_y =  object->circle->center_y;

       /* translate back in position */
       object->circle->center_x += world_centerx;
       object->circle->center_y += world_centery;

       /* recalc boundings and screen coords */
       o_circle_recalc(w_current, object);

     }

          Defines :
          o_circle_mirror_world,
           -- o_circle_basic.c - o_circle_mirror().

          Uses :
          o_circle_recalc,  -- o_circle_basic.c - o_circle_recalc().

     }

Function o_circle_recalc()
==========================

 -- Function: o_circle_recalc w_current o_current
     This function recalculates the screen coords of the o_current pointed circle object from its world coords.

The box coordinates and its bounding are recalculated as well as the OBJECT specific (line width, filling ...).

     <<o_circle_basic.c : o_circle_recalc()>>=
     void
     o_circle_recalc(TOPLEVEL *w_current, OBJECT *o_current)
     {
       int screen_x1, screen_y1;
       int left, right, top, bottom;

       if (o_current->circle == NULL) {
         return;
       }

     #if DEBUG
       printf("drawing circle\n");
     #endif

       <<o_circle_recalc() : update the screen coords from world coords -- o_circle_recalc() - update the screen coords from world coords>>

       <<o_circle_recalc() : update the bounding box in screen unit -- o_circle_recalc() - update the bounding box in screen unit>>

       <<o_circle_recalc() : update the object general fields -- o_circle_recalc() - update the object general fields>>

     }

          Defines :
          o_circle_recalc,
           -- o_circle_basic.c - o_circle_modify(),
           -- o_circle_add() - calculate the screen coords and the bounding box,
           -- o_circle_translate_world() - update the screen coordinates,
           -- o_circle_copy() - modify the fields of the new object,
           -- o_circle_basic.c - o_circle_mirror_world(),
           -- o_circle_rotate_world() - update the screen coords and boundings.

     }

     <<o_circle_recalc() : update the screen coords from world coords>>=
     /* update the screen coords of the center of the circle */
     WORLDtoSCREEN(w_current,
                               o_current->circle->center_x, o_current->circle->center_y,
                               &screen_x1, &screen_y1);
     o_current->circle->screen_x = screen_x1;
     o_current->circle->screen_y = screen_y1;

     /* update the value of the radius in screen unit */
     o_current->circle->screen_radius = SCREENabs(w_current,
                                                                                              o_current->circle->radius);

     <<o_circle_recalc() : update the bounding box in screen unit>>=
     /* update the bounding box - screen unit */
     get_circle_bounds(w_current, o_current->circle, &left, &top, &right, &bottom);
     o_current->left   = left;
     o_current->top    = top;
     o_current->right  = right;
     o_current->bottom = bottom;

          Uses :
          get_circle_bounds,  -- o_circle_basic.c - get_circle_bounds().

     }

     <<o_circle_recalc() : update the object general fields>>=
     /* recalc OBJECT specific parameters */
     o_object_recalc(w_current, o_current);

Function get_circle_bounds()
============================

 -- Function: get_circle_bounds w_current circle left top right bottom
     The get_circle_bounds() function set the left, top, right and bottom pointed variables to the boundings of the circle object described in *circle in screen unit.

The function finds the smallest rectangle that cover this circle.

     <<o_circle_basic.c : get_circle_bounds()>>=
     void
     get_circle_bounds(TOPLEVEL *w_current, CIRCLE *circle, int *left, int *top,
                       int *right, int *bottom)
     {
             *left   = circle->screen_x - circle->screen_radius;
             *top    = circle->screen_y - circle->screen_radius;
             *right  = circle->screen_x + circle->screen_radius;
             *bottom = circle->screen_y + circle->screen_radius;

             /* PB : need to take into account the width of the line */

             /* out temp
              *left = *left - 4;
              *top = *top - 4;

              *right = *right + 4;
              *bottom = *bottom + 4;
              */

     }

          Defines :
          get_circle_bounds,
           -- o_circle_recalc() - update the bounding box in screen unit.

     }

Function world_get_circle_bounds()
==================================

 -- Function: o_world_get_circle_bounds w_current circle left top right bottom
     The world_get_circle_bounds() function sets the left, top, right and bottom pointed variables to the boundings of the circle object described in *circle in world unit.

     <<o_circle_basic.c : world_get_circle_bounds()>>=
     void
     world_get_circle_bounds(TOPLEVEL *w_current, CIRCLE *circle, int *left,
                             int *top, int *right, int *bottom)
     {

       *left   = w_current->init_right;
       *top    = w_current->init_bottom;
       *right  = 0;
       *bottom = 0;

       *left   = circle->center_x - circle->radius;
       *top    = circle->center_y - circle->radius;
       *right  = circle->center_x + circle->radius;
       *bottom = circle->center_y + circle->radius;

       /*
        *left = points->x1;
        *top = points->y1;
        *right = points->x1+(temp);
        *bottom = points->y1-(temp);
        */

       /*
        *left = min(circle->x1, circle->x1+temp);
        *top = min(circle->y1, circle->y1-temp);
        *right = max(circle->x1, circle->x1+temp);
        *bottom = max(circle->y1, circle->y1-temp);*/

     #if DEBUG
       printf("circle: %d %d %d %d\n", *left, *top, *right, *bottom);
     #endif

     }

          Defines :
          .

     }

Function o_circle_print()
=========================

 -- Function: o_circle_print w_current fp o_current origin_x origin_y
     This function write in a postscript file the circle described by the o_current pointed object. It takes into account its line type and fill type. The postscript resulting files is descibed by the file pointer fp.

The validity of the o_current pointer is checked : a null pointer causes an error message and a return.

The description of the circle is extracted from the o_current pointed object : the coordinates of the center of the circle, its radius, its line type, its fill type.

The outline and the inside of the circle are successively handled by two differend sets of functions.

     <<o_circle_basic.c : o_circle_print()>>=
     void
     o_circle_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
                    int origin_x, int origin_y)
     {
       int x, y, radius;
       int color;
       int circle_width, length, space;
       int fill_width, angle1, pitch1, angle2, pitch2;
       void (*outl_func)() = NULL;
       void (*fill_func)() = NULL;

       if (o_current == NULL) {
         printf("got null in o_circle_print\n");
         return;
       }

       x      = o_current->circle->center_x;
       y      = o_current->circle->center_y;
       radius = o_current->circle->radius;

       color  = o_current->color;

       <<o_circle_print() : printing outline -- o_circle_print() - printing outline>>
       <<o_circle_print() : printing the filling -- o_circle_print() - printing the filling>>

     }

          Defines :
          o_circle_print,
           -- o_circle_basic.c - o_circle_print_old().

     }

Depending on the type of the line for this particular circle, the appropriate function is chosen among o_circle_print_solid(), o_circle_print_dotted(), o_circle_print_dashed(), o_circle_print_center and o_circle_print_phantom().

The needed parameters for each of these type is extracted from the o_current object. Depending on the type, unused parameters are set to -1.

In the eventuality of a length and/or space null, the line is printed solid to avoid and endless loop produced by other functions in such a case.

     <<o_circle_print() : printing outline>>=

       circle_width = o_current->line_width;
       length       = o_current->line_length;
       space        = o_current->line_space;

       switch(o_current->line_type) {
         case(TYPE_SOLID):
           length = -1; space  = -1;
           outl_func = (void *) o_circle_print_solid;
           break;

         case(TYPE_DOTTED):
           length = -1;
           outl_func = (void *) o_circle_print_dotted;
           break;

         case(TYPE_DASHED):
           outl_func = (void *) o_circle_print_dashed;
           break;

         case(TYPE_CENTER):
           outl_func = (void *) o_circle_print_center;
           break;

         case(TYPE_PHANTOM):
           outl_func = (void *) o_circle_print_phantom;
           break;

         case(TYPE_ERASE):
           /* Unused for now print it solid */
           length = -1; space  = -1;
           outl_func = (void *) o_circle_print_solid;
           break;
       }

       if((length == 0) || (space == 0)) {
         length = -1; space  = -1;
         outl_func = (void *) o_circle_print_solid;
       }

       (*outl_func)(w_current, fp,
                    x - origin_x, y - origin_y,
                    radius,
                    color,
                    circle_width, length, space,
                    origin_x, origin_y);

          Uses :
          o_circle_print_center,  -- o_circle_basic.c - o_circle_print_center().
          o_circle_print_dashed,  -- o_circle_basic.c - o_circle_print_dashed().
          o_circle_print_dotted,  -- o_circle_basic.c - o_circle_print_dotted().
          o_circle_print_phantom,  -- o_circle_basic.c - o_circle_print_phantom().
          o_circle_print_solid,  -- o_circle_basic.c - o_circle_print_solid().

     }

If the filling type of the circle is not HOLLOW, the appropriate function is chosen among o_circle_print_filled(), o_circle_print_mesh() and o_circle_print_hatch(). The corresponding parameters are extracted from the o_current object and corrected afterward.

The case where pitch1 and pitch2 are null or negative is avoided as it leads to an endless loop in most of the called functions. In such a case, the circle is printed filled. Unused parameters for each of these functions are set to -1 or any passive value.

     <<o_circle_print() : printing the filling>>=
       if(o_current->fill_type != FILLING_HOLLOW) {
         fill_width = o_current->fill_width;
         angle1     = o_current->fill_angle1;
         pitch1     = o_current->fill_pitch1;
         angle2     = o_current->fill_angle2;
         pitch2     = o_current->fill_pitch2;

         switch(o_current->fill_type) {
           case(FILLING_FILL):
             angle1 = -1; pitch1 = 1;
             angle2 = -1; pitch2 = 1;
             fill_width = -1;
             fill_func = (void *) o_circle_print_filled;
             break;

           case(FILLING_MESH):
             fill_func = (void *) o_circle_print_mesh;
             break;

           case(FILLING_HATCH):
             angle2 = -1; pitch2 = 1;
             fill_func = (void *) o_circle_print_hatch;
             break;

           case(FILLING_VOID):
                                     /* Unused for now, print it filled */
             angle1 = -1; pitch1 = 1;
             angle2 = -1; pitch2 = 1;
             fill_width = -1;
             fill_func = (void *) o_circle_print_filled;
             break;

           case(FILLING_HOLLOW):
             /* nop */
             break;
         }

         if((pitch1 <= 0) || (pitch2 <= 0)) {
           angle1 = -1; pitch1 = 1;
           angle2 = -1; pitch2 = 1;
           fill_func = (void *) o_circle_print_filled;
         }

         (*fill_func)(w_current, fp,
                      x, y, radius,
                      color,
                      fill_width,
                      angle1, pitch1, angle2, pitch2,
                      origin_x, origin_y);
       }

          Uses :
          o_circle_print_hatch,  -- o_circle_basic.c - o_circle_print_hatch().

     }

Function o_circle_print_solid()
===============================

 -- Function: o_circle_print_solid w_current fp x y radius color circle_width length space origin_x origin_y
     This function prints the outline of a circle when a solid line type is required. The circle is defined by its center in (x, y) and its radius in radius. It is printed with the color given in color. The parameters length and space are ignored.

It uses the function o_arc_print_solid() to print the outline. Therefore it acts as an interface between the way a circle is defined and the way an arc is defined.

All dimensions are in mils.

     <<o_circle_basic.c : o_circle_print_solid()>>=
     void
     o_circle_print_solid(TOPLEVEL *w_current, FILE *fp,
                          int x, int y, int radius,
                          int color,
                          int circle_width, int length, int space,
                          int origin_x, int origin_y)
     {

       o_arc_print_solid(w_current, fp,
                         x, y, radius,
                         0, FULL_CIRCLE / 64,
                         color,
                         circle_width, -1, -1,
                         origin_x, origin_y);

     }

          Defines :
          o_circle_print_solid,
           -- o_circle_print() - printing outline.

     }

Function o_circle_print_dotted()
================================

 -- Function: o_circle_print_dotted w_current fp x y radius color circle_width length space origin_x origin_y
     This function prints the outline of a circle when a dotted line type is required. The circle is defined by its center in (x, y) and its radius in radius. It is printed with the color given in color. The parameter length is ignored.

It uses the function o_arc_print_dotted() to print the outline. Therefore it acts as an interface between the way a circle is defined and the way an arc is defined.

All dimensions are in mils.

     <<o_circle_basic.c : o_circle_print_dotted()>>=
     void
     o_circle_print_dotted(TOPLEVEL *w_current, FILE *fp,
                           int x, int y, int radius,
                           int color,
                           int circle_width, int length, int space,
                           int origin_x, int origin_y)
     {

       o_arc_print_dotted(w_current, fp,
                          x, y, radius,
                          0, FULL_CIRCLE / 64,
                          color,
                          circle_width, -1, space,
                          origin_x, origin_y);

     }

          Defines :
          o_circle_print_dotted,
           -- o_circle_print() - printing outline.

     }

Function o_circle_print_dashed()
================================

 -- Function: o_circle_print_dashed w_current fp x y radius color circle_width length space origin_x origin_y
     This function prints the outline of a circle when a dashed line type is required. The circle is defined by its center in (x, y) and its radius in radius. It is printed with the color given in color.

It uses the function o_arc_print_dashed() to print the outline. Therefore it acts as an interface between the way a circle is defined and the way an arc is defined.

All dimensions are in mils.

     <<o_circle_basic.c : o_circle_print_dashed()>>=
     void
     o_circle_print_dashed(TOPLEVEL *w_current, FILE *fp,
                           int x, int y,
                           int radius,
                           int color,
                           int circle_width, int length, int space,
                           int origin_x, int origin_y)
     {

       o_arc_print_dashed(w_current, fp,
                          x, y, radius,
                          0, FULL_CIRCLE / 64,
                          color,
                          circle_width, length, space,
                          origin_x, origin_y);

     }

          Defines :
          o_circle_print_dashed,
           -- o_circle_print() - printing outline.

     }

Function o_circle_print_center()
================================

 -- Function: o_circle_print_center w_current fp x y radius color circle_width length space origin_x origin_y
     This function prints the outline of a circle when a centered line type is required. The circle is defined by its center in (x, y) and its radius in radius. It is printed with the color given in color.

It uses the function o_arc_print_center() to print the outline. Therefore it acts as an interface between the way a circle is defined and the way an arc is defined.

All dimensions are in mils.

     <<o_circle_basic.c : o_circle_print_center()>>=
     void
     o_circle_print_center(TOPLEVEL *w_current, FILE *fp,
                           int x, int y,
                           int radius,
                           int color,
                           int circle_width, int length, int space,
                           int origin_x, int origin_y)
     {

       o_arc_print_center(w_current, fp,
                          x, y, radius,
                          0, FULL_CIRCLE / 64,
                          color,
                          circle_width, length, space,
                          origin_x, origin_y);

     }

          Defines :
          o_circle_print_center,
           -- o_circle_print() - printing outline.

     }

Function o_circle_print_phantom()
=================================

 -- Function: o_circle_print_phantom w_current fp x y radius color circle_width length space origin_x origin_y
     This function prints the outline of a circle when a phantom line type is required. The circle is defined by its center in (x, y) and its radius in radius. It is printed with the color given in color.

It uses the function o_arc_print_phantom() to print the outline. Therefore it acts as an interface between the way a circle is defined and the way an arc is defined.

All dimensions are in mils.

     <<o_circle_basic.c : o_circle_print_phantom()>>=
     void
     o_circle_print_phantom(TOPLEVEL *w_current, FILE *fp,
                            int x, int y,
                            int radius,
                            int color,
                            int circle_width, int length, int space,
                            int origin_x, int origin_y)
     {

       o_arc_print_phantom(w_current, fp,
                           x, y, radius,
                           0, FULL_CIRCLE / 64,
                           color,
                           circle_width, length, space,
                           origin_x, origin_y);

     }

          Defines :
          o_circle_print_phantom,
           -- o_circle_print() - printing outline.

     }

Function o_circle_print_filled()
================================

 -- Function: o_circle_print_filled w_current fp x y radius color circle_width length space origin_x origin_y
     The function prints a filled circle with a solid pattern. No outline is printed. The circle is defined by the coordinates of its center in (x,y) and its radius given by the radius parameter. The postscript file is defined by the file pointer fp. fill_width, angle1 and pitch1, angle2 and pitch2 parameters are ignored in this functions but kept for compatibility with other fill functions.

All dimensions are in mils (except angle1 and angle2 in degree).

     <<o_circle_basic.c : o_circle_print_filled()>>=
     void
     o_circle_print_filled(TOPLEVEL *w_current, FILE *fp,
                           int x, int y, int radius,
                           int color,
                           int fill_width,
                           int angle1, int pitch1,
                           int angle2, int pitch2,
                           int origin_x, int origin_y)
     {
       fprintf(fp, "gsave\n");
       if (w_current->print_color) {
         f_print_set_color(fp, color);
       }

       f_print_set_line_width(fp, 1);

       fprintf(fp, "newpath\n");
       fprintf(fp, "%d mils %d mils\n", x-origin_x, y-origin_y);
       fprintf(fp, "%d mils\n", radius);
       fprintf(fp, "0 360 arc\n");
       fprintf(fp, "fill\n");
       fprintf(fp, "grestore\n");

     }

Function o_circle_print_mesh()
==============================

 -- Function: o_circle_print_mesh w_current fp x y radius color fill_width angle1 pitch1 angle2 pitch2 origin_x origin_y
     The function prints a meshed circle. No outline is printed. The circle is defined by the coordinates of its center in (x,y) and its radius by the radius parameter. The postscript file is defined by the file pointer fp.

The inside mesh is achieved by two successive call to the o_circle_print_hatch() function, given angle1 and pitch1 the first time and angle2 and pitch2 the second time.

Negative or null values for pitch1 and/or pitch2 are not allowed as it leads to an endless loop in o_circle_print_hatch.

All dimensions are in mils (except angle1 and angle2 in degree).

     <<o_circle_basic.c : o_circle_print_mesh()>>=
     void
     o_circle_print_mesh(TOPLEVEL *w_current, FILE *fp,
                         int x, int y, int radius,
                         int color,
                         int fill_width,
                         int angle1, int pitch1,
                         int angle2, int pitch2,
                         int origin_x, int origin_y)
     {
       o_circle_print_hatch(w_current, fp,
                            x, y, radius,
                            color,
                            fill_width,
                            angle1, pitch1,
                            -1, -1,
                            origin_x, origin_y);
       o_circle_print_hatch(w_current, fp,
                            x, y, radius,
                            color,
                            fill_width,
                            angle2, pitch2,
                            -1, -1,
                            origin_x, origin_y);

     }

          Uses :
          o_circle_print_hatch,  -- o_circle_basic.c - o_circle_print_hatch().

     }

Function o_circle_print_hatch()
===============================

 -- Function: o_circle_print_hatch w_current fp x y radius color fill_width angle1 pitch1 angle2 pitch2 origin_x origin_y
     The function prints a hatched circle. No outline is printed. The circle is defined by the coordinates of its center in (x,y) and its radius by the radius parameter. The postscript file is defined by the file pointer fp. angle2 and pitch2 parameters are ignored in this functions but kept for compatibility with other fill functions.

The only attribute of line here is its width from the parameter width.

Negative or null values for pitch1 are not allowed as it leads to an endless loop.

All dimensions are in mils (except angle1 and angle2 in degree).

     <<o_circle_basic.c : o_circle_print_hatch()>>=
     void
     o_circle_print_hatch(TOPLEVEL *w_current, FILE *fp,
                          int x, int y, int radius,
                          int color,
                          int fill_width,
                          int angle1, int pitch1,
                          int angle2, int pitch2,
                          int origin_x, int origin_y)
     {
       double x0, y0, x1, y1, x2, y2;
       double cos_a_, sin_a_;

       fprintf(fp, "gsave\n");
       if (w_current->print_color) {
         f_print_set_color(fp, color);
       }

       f_print_set_line_width(fp, fill_width);

          Defines :
          o_circle_print_hatch,
           -- o_circle_basic.c - o_circle_print_mesh(),
           -- o_circle_print() - printing the filling.

     }

The values of the cosinus and sinus of the angle angle1 are calculated for future usage (repetitive).

     <<o_circle_basic.c : o_circle_print_hatch()>>+=
       cos_a_ = cos(((double) angle1) * M_PI/180);
       sin_a_ = sin(((double) angle1) * M_PI/180);

       <<o_circle_print_hatch() : calculating and printing the lines -- o_circle_print_hatch() - calculating and printing the lines>>

       fprintf(fp, "grestore\n");

     }

When printing a line in a circle there is two intersections. It looks for the coordinates of one of these points when the line is horizontal. The second one can be easily obtained by symmetry in relation to the vertical axis going through the centre of the circle.

These two points are therefore rotated of angle angle1 using the elements previously computed.

The corresponding line can be printed providing that the coordinates are rounded.

These operations are repeated for every horizontal line that can fit in the upper half of the circle (using and incrementing the variable Y0).

     <<o_circle_print_hatch() : calculating and printing the lines>>=
       y0 = 0;
       while(y0 < (double) radius) {
         x0 = pow((double) radius, 2) - pow(y0, 2);
         x0 = sqrt(x0);

         x1 = (x0*cos_a_ - y0*sin_a_) + x;
         y1 = y + (x0*sin_a_ + y0*cos_a_);
         x2 = ((-x0)*cos_a_ - y0*sin_a_) + x;
         y2 = y + ((-x0)*sin_a_ + y0*cos_a_);

         fprintf(fp, "newpath\n");
         fprintf(fp, "%d mils %d mils moveto\n", (int) x1, (int) y1);
         fprintf(fp, "%d mils %d mils lineto\n", (int) x2, (int) y2);
         fprintf(fp, "stroke\n");

The function uses the symetry in relation to the centre of the circle. It avoid repetitive computation for the second half of the surface of the circle.

     <<o_circle_print_hatch() : calculating and printing the lines>>+=

                     x1 = x + (x0*cos_a_ - (-y0)*sin_a_);
                     y1 = y + (x0*sin_a_ + (-y0)*cos_a_);
                     x2 = x + ((-x0)*cos_a_ - (-y0)*sin_a_);
                     y2 = y + ((-x0)*sin_a_ + (-y0)*cos_a_);

                     fprintf(fp, "newpath\n");
                     fprintf(fp, "%d mils %d mils moveto\n", (int) x1, (int) y1);
                     fprintf(fp, "%d mils %d mils lineto\n", (int) x2, (int) y2);
                     fprintf(fp, "stroke\n");

                     y0 = y0 + pitch1;
             }

Function o_circle_print_old()
=============================

 -- Function: o_circle_print_old w_current fp o_current origin_x origin_y
     This function is the old function to print a circle. It does not handle line type and filling of a circle.

     <<o_circle_basic.c : o_circle_print_old()>>=
     void
     o_circle_print_old(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
             int origin_x, int origin_y)
     {
       if (o_current == NULL) {
         printf("got null in o_circle_print\n");
         return;
       }

       fprintf(fp, "gsave\n");
       if (w_current->print_color) {
         f_print_set_color(fp, o_current->color);
       }

       f_print_set_line_width(fp, o_current->line_width);

       fprintf(fp, "newpath\n");
       fprintf(fp, "%d mils %d mils\n", o_current->circle->center_x-origin_x,
               o_current->circle->center_y-origin_y);
       fprintf(fp, "%d mils\n", o_current->circle->radius);
       fprintf(fp, "0 360 arc\n");
       fprintf(fp, "stroke\n");
       fprintf(fp, "grestore\n");
     }

          Defines :
          .

          Uses :
          o_circle_print,  -- o_circle_basic.c - o_circle_print().

     }

Function o_circle_image_write()
===============================

 -- Function: o_circle_image_write w_current o_current origin_x origin_y color_mode
     This function draws a circle in an image with the libgdgeda function gdImage Arc().

     <<o_circle_basic.c : o_circle_image_write()>>=
     void
     o_circle_image_write(TOPLEVEL *w_current, OBJECT *o_current,
                          int origin_x, int origin_y, int color_mode)
     {
       int color;

       if (o_current == NULL) {
         printf("got null in o_circle_image_write\n");
         return;
       }

       if (color_mode == TRUE) {
         color = o_image_geda2gd_color(o_current->color);
       } else {
         color = image_black;
       }

     #ifdef HAS_LIBGDGEDA

       gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
                                                     o_current->line_width));

       gdImageArc(current_im_ptr,
                  o_current->circle->screen_x,
                  o_current->circle->screen_y,
                  SCREENabs(w_current, o_current->circle->radius)*2,
                  SCREENabs(w_current, o_current->circle->radius)*2,
                  0, 360,
                  color);
     #endif

     }

          Defines :
          .

     }