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

gEDA-cvs: gaf.git: branch: master updated (1.5.1-20081221-139-g21ad139)



The branch, master has been updated
       via  21ad139e3bc59d796a2a54f1cb35b71060848687 (commit)
       via  d9daf573f87edf46f2b74235db1e66bf669a2986 (commit)
      from  95432ccffdbb39434981f87050433c00f40125da (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gschem/src/o_arc.c    |  167 ++++++++++------------
 gschem/src/o_circle.c |  150 ++++++++------------
 gschem/src/o_path.c   |  380 ++++++++++++++++++-------------------------------
 3 files changed, 274 insertions(+), 423 deletions(-)


=================
 Commit Messages
=================

commit 21ad139e3bc59d796a2a54f1cb35b71060848687
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Jan 4 21:16:08 2009 +0000

    gschem: Compute the bounding box of a rubberbanded path analytically
    
    For now, actualy just take a big bounding box which includes the
    control points.

:100644 100644 e9ef0d1... d5ebeb2... M	gschem/src/o_path.c

commit d9daf573f87edf46f2b74235db1e66bf669a2986
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Jan 4 20:06:36 2009 +0000

    gschem: Refactor partially duplicated drawing code in various files.
    
    For each object type, there is drawing code for the normal object
    on the page, an object being placed, and objects being rubberbanded.
    
    In many cases (arc, circle and path being good examples), each of these
    functions repeat non-trivial amounts of very similar setup and drawing
    code. Only the line-width, stroke style need to be specific to each.
    
    Refactor the code such that the place and rubberbanding routines (which
    adjust the rendered geometry based on state variables) construct a
    temporary object with the modified geometry. Common parts of the cairo
    setup and path generation can be combined and shared between routines.

:100644 100644 ba2dedf... 295caa3... M	gschem/src/o_arc.c
:100644 100644 05171bb... 4145d26... M	gschem/src/o_circle.c
:100644 100644 50b78f3... e9ef0d1... M	gschem/src/o_path.c

=========
 Changes
=========

commit 21ad139e3bc59d796a2a54f1cb35b71060848687
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Jan 4 21:16:08 2009 +0000

    gschem: Compute the bounding box of a rubberbanded path analytically
    
    For now, actualy just take a big bounding box which includes the
    control points.

diff --git a/gschem/src/o_path.c b/gschem/src/o_path.c
index e9ef0d1..d5ebeb2 100644
--- a/gschem/src/o_path.c
+++ b/gschem/src/o_path.c
@@ -103,91 +103,6 @@ static void path_path (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
 }
 
 
-static void path_to_points_modify (GSCHEM_TOPLEVEL *w_current, PATH *path,
-                                   int dx, int dy, int new_x, int new_y, int whichone,
-                                   GdkPoint **points, int *num_points)
-
-{
-  PATH_SECTION *section;
-  int x1, y1, x2, y2, x3, y3;
-  int i;
-  int grip_no = 0;
-
-  sPOINT point = { 0, 0 };
-  GArray *polygon_points;
-  BEZIER bezier;
-
-  polygon_points = g_array_new (FALSE, FALSE, sizeof (sPOINT));
-
-
-  for (i = 0; i <  path->num_sections; i++) {
-    section = &path->sections[i];
-
-    x1 = section->x1 + dx; y1 = section->y1 + dy;
-    x2 = section->x2 + dx; y2 = section->y2 + dy;
-    x3 = section->x3 + dx; y3 = section->y3 + dy;
-
-    switch (section->code) {
-      case PATH_CURVETO:
-        /* Two control point grips */
-        if (whichone == grip_no++) {
-          x1 = new_x; y1 = new_y;
-        }
-        if (whichone == grip_no++) {
-          x2 = new_x; y2 = new_y;
-        }
-        WORLDtoSCREEN (w_current, x1, y1, &x1, &y1);
-        WORLDtoSCREEN (w_current, x2, y2, &x2, &y2);
-        /* Fall through */
-      case PATH_MOVETO:
-      case PATH_MOVETO_OPEN:
-      case PATH_LINETO:
-        /* Destination point grip */
-        if (whichone == grip_no++) {
-          x3 = new_x; y3 = new_y;
-        }
-        WORLDtoSCREEN (w_current, x3, y3, &x3, &y3);
-      case PATH_END:
-        break;
-    }
-
-    switch (section->code) {
-      case PATH_CURVETO:
-        bezier.x[0] = point.x;
-        bezier.y[0] = point.y;
-        bezier.x[1] = x1;
-        bezier.y[1] = y1;
-        bezier.x[2] = x2;
-        bezier.y[2] = y2;
-        point.x = bezier.x[3] = x3;
-        point.y = bezier.y[3] = y3;
-        m_polygon_append_bezier (polygon_points, &bezier, NUM_BEZIER_SEGMENTS);
-        break;
-
-      case PATH_MOVETO_OPEN:
-        /* Unsupported, just fall through and draw a line */
-        /* Fall through */
-
-      case PATH_MOVETO:
-      case PATH_LINETO:
-        point.x = x3;
-        point.y = y3;
-        m_polygon_append_point (polygon_points, point.x, point.y);
-        break;
-
-      case PATH_END:
-        break;
-    }
-  }
-
-  /* WARNING:
-   * Relies on the fact that sPOINT and GdkPoint are compatible */
-
-  *num_points = polygon_points->len;
-  *points = (GdkPoint *)g_array_free (polygon_points, FALSE);
-}
-
-
 static PATH *path_copy_modify (PATH *path, int dx, int dy,
                                int new_x, int new_y, int whichone)
 {
@@ -497,22 +412,6 @@ void o_path_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 }
 
 
-static void find_points_bounds (GdkPoint *points, int num_points,
-                                int *min_x, int *min_y, int *max_x, int *max_y)
-{
-  int i;
-  int found_bound = FALSE;
-
-  for (i = 0; i < num_points; i++) {
-    *min_x = (found_bound) ? min (*min_x, points[i].x) : points[i].x;
-    *min_y = (found_bound) ? min (*min_y, points[i].y) : points[i].y;
-    *max_x = (found_bound) ? max (*max_x, points[i].x) : points[i].x;
-    *max_y = (found_bound) ? max (*max_y, points[i].y) : points[i].y;
-    found_bound = TRUE;
-  }
-}
-
-
 /*! \todo Finish function documentation
  *  \brief
  *  \par Function Description
@@ -520,22 +419,57 @@ static void find_points_bounds (GdkPoint *points, int num_points,
 void o_path_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
 {
   PATH *path = w_current->which_object->path;
-  int num_points;
-  GdkPoint *points;
-  int min_x = 0, min_y = 0, max_x = 0, max_y = 0;
-
-  path_to_points_modify (w_current, path, 0, 0,
-                         w_current->second_wx, w_current->second_wy,
-                         w_current->which_grip, &points, &num_points);
-  if (num_points == 0) {
-    g_free (points);
-    return;
-  }
+  int min_x, min_y, max_x, max_y;
+  int x1, y1, x2, y2, x3, y3;
+  int new_x, new_y, whichone;
+  int grip_no = 0;
+  int i;
+
+  min_x = G_MAXINT;  max_x = G_MININT;
+  min_y = G_MAXINT;  max_y = G_MININT;
 
-  find_points_bounds (points, num_points, &min_x, &min_y, &max_x, &max_y);
-  g_free (points);
+  new_x = w_current->second_wx;
+  new_y = w_current->second_wy;
+  whichone = w_current->which_grip;
+
+  for (i = 0; i <  path->num_sections; i++) {
+    PATH_SECTION *section = &path->sections[i];
+
+    x1 = section->x1; y1 = section->y1;
+    x2 = section->x2; y2 = section->y2;
+    x3 = section->x3; y3 = section->y3;
+
+    switch (section->code) {
+      case PATH_CURVETO:
+        /* Two control point grips */
+        if (whichone == grip_no++) {
+          x1 = new_x; y1 = new_y;
+        }
+        if (whichone == grip_no++) {
+          x2 = new_x; y2 = new_y;
+        }
+        min_x = MIN (min_x, x1);  min_y = MIN (min_y, y1);
+        max_x = MAX (max_x, x1);  max_y = MAX (max_y, y1);
+        min_x = MIN (min_x, x2);  min_y = MIN (min_y, y2);
+        max_x = MAX (max_x, x2);  max_y = MAX (max_y, y2);
+        /* Fall through */
+      case PATH_MOVETO:
+      case PATH_MOVETO_OPEN:
+      case PATH_LINETO:
+        /* Destination point grip */
+        if (whichone == grip_no++) {
+          x3 = new_x; y3 = new_y;
+        }
+        min_x = MIN (min_x, x3);  min_y = MIN (min_y, y3);
+        max_x = MAX (max_x, x3);  max_y = MAX (max_y, y3);
+      case PATH_END:
+        break;
+    }
+  }
 
-  o_invalidate_rect (w_current, min_x, min_y, max_x, max_y);
+  WORLDtoSCREEN (w_current, min_x, max_y, &x1, &y1);
+  WORLDtoSCREEN (w_current, max_x, min_y, &x2, &y2);
+  o_invalidate_rect (w_current, x1, y1, x2, y2);
 }
 
 

commit d9daf573f87edf46f2b74235db1e66bf669a2986
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Jan 4 20:06:36 2009 +0000

    gschem: Refactor partially duplicated drawing code in various files.
    
    For each object type, there is drawing code for the normal object
    on the page, an object being placed, and objects being rubberbanded.
    
    In many cases (arc, circle and path being good examples), each of these
    functions repeat non-trivial amounts of very similar setup and drawing
    code. Only the line-width, stroke style need to be specific to each.
    
    Refactor the code such that the place and rubberbanding routines (which
    adjust the rendered geometry based on state variables) construct a
    temporary object with the modified geometry. Common parts of the cairo
    setup and path generation can be combined and shared between routines.

diff --git a/gschem/src/o_arc.c b/gschem/src/o_arc.c
index ba2dedf..295caa3 100644
--- a/gschem/src/o_arc.c
+++ b/gschem/src/o_arc.c
@@ -28,6 +28,40 @@
 #endif
 
 
+static void arc_path (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
+{
+  ARC *arc = object->arc;
+  int line_width;
+  int sx1, sy1, sx2, sy2;
+  double cx, cy;
+  double radius;
+
+  WORLDtoSCREEN (w_current, arc->x - arc->width  / 2,
+                            arc->y + arc->height / 2, &sx1, &sy1);
+  WORLDtoSCREEN (w_current, arc->x + arc->width  / 2,
+                            arc->y - arc->height / 2, &sx2, &sy2);
+  line_width = SCREENabs (w_current, object->line_width);
+  if (line_width <= 0) {
+    line_width = 1;
+  }
+
+  cx = (double)(sx1 + sx2) / 2.;
+  cy = (double)(sy1 + sy2) / 2.;
+  radius = (double)(sy2 - sy1) / 2.;
+
+  cairo_translate (w_current->cr, cx, cy);
+
+  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
+     allows for the case where sx2 == sx1 or sy2 == sy1 */
+  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
+                              (double)(sy2 - sy1 + 1), 1.);
+
+  gschem_cairo_arc (w_current->cr, line_width, 0., 0., radius,
+                    arc->start_angle, arc->end_angle);
+  cairo_identity_matrix (w_current->cr);
+}
+
+
 /*! \brief Draw an arc on the screen.
  *  \par Function Description
  *  This function is used to draw an arc on screen. The arc is described
@@ -44,7 +78,6 @@
 void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int sx1, sy1, sx2, sy2;
   int line_width;
   COLOR *color;
   int length, space;
@@ -56,28 +89,6 @@ void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   if (toplevel->DONT_REDRAW == 1)
     return;
 
-  /*
-   * As an arc is definetely not a closed shape there is no need to
-   * define and call any filling function. Another way to say that is
-   * that an arc can not be filled. It simply draws the arc according
-   * to the type line.
-   *
-   * The values describing the line type are extracted from the
-   * <B>o_current</B> pointed structure. These are the width of the line,
-   * the field called length and the field called space and the desired
-   * end type for the arc.
-   *
-   * Depending on the type of line desired the appropriate function is
-   * called. Values of space and length are adapted to the type of line.
-   * The possible functions are the following : #o_arc_draw_solid(),
-   * #o_arc_draw_dotted(), #o_arc_draw_dashed() and #o_arc_draw_phantom().
-   *
-   * The combination <B>length</B> == 0 and <B>space</B> == 0 is avoided as it
-   * leads to an endless loop in function called after. If such a case is
-   * encountered the arc is drawn as a solid arc independently of its
-   * initial type.
-   */
-
   if (toplevel->override_color != -1 )
     color = x_color_lookup (toplevel->override_color);
   else
@@ -91,24 +102,7 @@ void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   length = SCREENabs (w_current, o_current->line_length);
   space = SCREENabs (w_current, o_current->line_space);
 
-  WORLDtoSCREEN (w_current, o_current->arc->x - o_current->arc->width / 2,
-                           o_current->arc->y + o_current->arc->height / 2,
-                           &sx1, &sy1);
-  WORLDtoSCREEN (w_current, o_current->arc->x + o_current->arc->width / 2,
-                           o_current->arc->y - o_current->arc->height / 2,
-                           &sx2, &sy2);
-
-  cairo_translate (w_current->cr, (double)(sx1 + sx2) / 2.,
-                                  (double)(sy1 + sy2) / 2.);
-
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-  gschem_cairo_arc (w_current->cr, line_width,
-                    0., 0., (double)(sy2 - sy1) / 2.,
-                    o_current->arc->start_angle, o_current->arc->end_angle);
-  cairo_identity_matrix (w_current->cr);
+  arc_path (w_current, o_current);
 
   gschem_cairo_set_source_color (w_current->cr, color);
   gschem_cairo_stroke (w_current->cr, o_current->line_type,
@@ -117,10 +111,6 @@ void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   if (o_current->selected && w_current->draw_grips == TRUE) {
     o_arc_draw_grips (w_current, o_current);
   }
-
-#if DEBUG
-  printf("drawing arc\n");
-#endif
 }
 
 /*! \todo Finish function documentation!!!
@@ -155,13 +145,21 @@ void o_arc_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
  */
 void o_arc_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
 {
-  int sx1, sy1, sx2, sy2;
-  int line_width = 1;
+  OBJECT object;
+  ARC arc;
   int color;
 
-  if (o_current->arc == NULL) {
-    return;
-  }
+  g_return_if_fail (o_current->arc != NULL);
+
+  /* Setup a fake object to pass the drawing routine */
+  object.arc = &arc;
+  object.line_width = 0; /* clamped to 1 pixel in arc_path */
+  arc.x = o_current->arc->x + dx;
+  arc.y = o_current->arc->y + dy;
+  arc.width  = o_current->arc->width;
+  arc.height = o_current->arc->height;
+  arc.start_angle = o_current->arc->start_angle;
+  arc.end_angle   = o_current->arc->end_angle;
 
   if (o_current->saved_color != -1) {
     color = o_current->saved_color;
@@ -169,24 +167,7 @@ void o_arc_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_cur
     color = o_current->color;
   }
 
-  WORLDtoSCREEN (w_current, o_current->arc->x + dx - o_current->arc->width / 2,
-                           o_current->arc->y + dy + o_current->arc->height / 2,
-                           &sx1, &sy1);
-  WORLDtoSCREEN (w_current, o_current->arc->x + dx + o_current->arc->width / 2,
-                           o_current->arc->y + dy- o_current->arc->height / 2,
-                           &sx2, &sy2);
-
-  cairo_translate (w_current->cr, (double)(sx1 + sx2) / 2.,
-                                  (double)(sy1 + sy2) / 2.);
-
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-  gschem_cairo_arc (w_current->cr, line_width,
-                    0., 0., (double)(sy2 - sy1) / 2.,
-                    o_current->arc->start_angle, o_current->arc->end_angle);
-  cairo_identity_matrix (w_current->cr);
+  arc_path (w_current, &object);
 
   gschem_cairo_set_source_color (w_current->cr, x_color_lookup_dark (color));
   gschem_cairo_stroke (w_current->cr, TYPE_SOLID, END_NONE, 1, -1, -1);
@@ -397,40 +378,38 @@ void o_arc_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int whichone)
  */
 void o_arc_draw_rubber (GSCHEM_TOPLEVEL *w_current)
 {
+  OBJECT object;
+  ARC arc;
   double rad_angle;
-  double radius;
-  double cx, cy;
-  int sx1, sy1, sx2, sy2, rx, ry;
-
-  WORLDtoSCREEN (w_current, w_current->first_wx - w_current->distance,
-                            w_current->first_wy + w_current->distance,
-                            &sx1, &sy1);
-  WORLDtoSCREEN (w_current, w_current->first_wx + w_current->distance,
-                            w_current->first_wy - w_current->distance,
-                            &sx2, &sy2);
-
-  radius = (double)(sy2 - sy1) / 2.;
-  cx = (double)(sx1 + sx2) / 2.;
-  cy = (double)(sy1 + sy2) / 2.;
+  int rdx, rdy;
+  int x1, y1, x2, y2;
 
-  cairo_translate (w_current->cr, cx, cy);
+  /* Setup a fake object to pass the drawing routine */
+  object.arc = &arc;
+  object.line_width = 0; /* clamped to 1 pixel in arc_path */
+  arc.x = w_current->first_wx;
+  arc.y = w_current->first_wy;
+  arc.width  = w_current->distance * 2;
+  arc.height = w_current->distance * 2;
+  arc.start_angle = w_current->second_wx;
+  arc.end_angle   = w_current->second_wy;
 
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-  gschem_cairo_arc (w_current->cr, 1, 0., 0., radius,
-                    w_current->second_wx, w_current->second_wy);
-  cairo_identity_matrix (w_current->cr);
+  arc_path (w_current, &object);
 
   gschem_cairo_set_source_color (w_current->cr,
                                  x_color_lookup_dark (SELECT_COLOR));
 
-  /* draw the radius segment from the w_current variables */
+  /* draw the radius line */
   rad_angle = ((double) w_current->second_wx) * M_PI / 180;
-  rx = cx + radius * cos (rad_angle);
-  ry = cy - radius * sin (rad_angle);
-  gschem_cairo_line (w_current->cr, END_NONE, 1, cx, cy, rx, ry);
+  rdx = (double) w_current->distance * cos (rad_angle);
+  rdy = (double) w_current->distance * sin (rad_angle);
+
+  WORLDtoSCREEN (w_current, w_current->first_wx,
+                            w_current->first_wy, &x1, &y1);
+  WORLDtoSCREEN (w_current, w_current->first_wx + rdx,
+                            w_current->first_wy + rdy, &x2, &y2);
+
+  gschem_cairo_line (w_current->cr, END_NONE, 1, x1, y1, x2, y2);
 
   gschem_cairo_stroke (w_current->cr, TYPE_SOLID, END_NONE, 1, -1, -1);
 }
diff --git a/gschem/src/o_circle.c b/gschem/src/o_circle.c
index 05171bb..4145d26 100644
--- a/gschem/src/o_circle.c
+++ b/gschem/src/o_circle.c
@@ -33,6 +33,40 @@ typedef void (*FILL_FUNC)( GdkDrawable *w, GdkGC *gc, COLOR *color,
                            gint fill_width, gint angle1, gint pitch1,
                            gint angle2, gint pitch2 );
 
+
+static void circle_path (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
+{
+  CIRCLE *circle = object->circle;
+  int line_width;
+  int sx1, sy1, sx2, sy2;
+  double cx, cy;
+  double radius;
+
+  WORLDtoSCREEN (w_current, circle->center_x - circle->radius,
+                            circle->center_y + circle->radius, &sx1, &sy1);
+  WORLDtoSCREEN (w_current, circle->center_x + circle->radius,
+                            circle->center_y - circle->radius, &sx2, &sy2);
+  line_width = SCREENabs (w_current, object->line_width);
+  if (line_width <= 0) {
+    line_width = 1;
+  }
+
+  cx = (double)(sx1 + sx2) / 2.;
+  cy = (double)(sy1 + sy2) / 2.;
+  radius = (double)(sy2 - sy1) / 2.;
+
+  cairo_translate (w_current->cr, cx, cy);
+
+  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
+     allows for the case where sx2 == sx1 or sy2 == sy1 */
+  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
+                              (double)(sy2 - sy1 + 1), 1.);
+
+  gschem_cairo_arc (w_current->cr, line_width, 0., 0., radius, 0., 360);
+  cairo_identity_matrix (w_current->cr);
+}
+
+
 /*! \brief Draw a circle on the screen.
  *  \par Function Description
  *  This function is used to draw a circle on screen. The circle is described
@@ -49,9 +83,6 @@ typedef void (*FILL_FUNC)( GdkDrawable *w, GdkGC *gc, COLOR *color,
 void o_circle_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int sx1, sy1, sx2, sy2;
-  double cx, cy;
-  double radius;
   int line_width, length, space;
   int fill_width, angle1, pitch1, angle2, pitch2;
   COLOR *color;
@@ -80,22 +111,6 @@ void o_circle_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
     color = x_color_lookup (o_current->color);
   }
 
-  /*
-   * The values describing the line type are extracted from the
-   * <B>o_current</B> pointed structure. These are the width of the line, the
-   * field called length and the field called space and the desired end type
-   * for the line.
-   *
-   * Depending on the type of the line that has to be used to draw the circle
-   * the appropriate function is called. Values of space and length are
-   * adapted to the type of line. The possible functions are the following :
-   * #o_arc_draw_solid(), #o_arc_draw_dotted(), #o_arc_draw_dashed() and
-   * #o_arc_draw_phantom(). Therefore it reuses the code from arc primitive.
-   *
-   * The combination <B>length</B> == 0 and <B>space</B> == 0 is avoided as it lead
-   * to an endless loop in function called after. If such a case is encountered
-   * the circle is drawn as a solid circle independently of its initial type.
-   */
   line_width = SCREENabs (w_current, o_current->line_width);
   if (line_width <= 0) {
     line_width = 1;
@@ -179,26 +194,7 @@ void o_circle_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
                 color, w_current, o_current->circle,
                 fill_width, angle1, pitch1, angle2, pitch2);
 
-  WORLDtoSCREEN (w_current, o_current->circle->center_x - o_current->circle->radius,
-                            o_current->circle->center_y + o_current->circle->radius,
-                            &sx1, &sy1);
-  WORLDtoSCREEN (w_current, o_current->circle->center_x + o_current->circle->radius,
-                            o_current->circle->center_y - o_current->circle->radius,
-                            &sx2, &sy2);
-
-  cx = (double)(sx1 + sx2) / 2.;
-  cy = (double)(sy1 + sy2) / 2.;
-  radius = (double)(sy2 - sy1) / 2.;
-
-  cairo_translate (w_current->cr, cx, cy);
-
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-
-  gschem_cairo_arc (w_current->cr, line_width, 0., 0., radius, 0., 360);
-  cairo_identity_matrix (w_current->cr);
+  circle_path (w_current, o_current);
 
   gschem_cairo_set_source_color (w_current->cr, color);
   if (o_current->fill_type == FILLING_FILL)
@@ -414,14 +410,18 @@ void o_circle_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
  */
 void o_circle_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
 {
-  int sx1, sy1, sx2, sy2;
-  double cx, cy;
-  double radius;
+  OBJECT object;
+  CIRCLE circle;
   int color;
 
-  if (o_current->circle == NULL) {
-    return;
-  }
+  g_return_if_fail (o_current->circle != NULL);
+
+  /* Setup a fake object to pass the drawing routine */
+  object.circle = &circle;
+  object.line_width = 0; /* clamped to 1 pixel in circle_path */
+  circle.center_x = o_current->circle->center_x + dx;
+  circle.center_y = o_current->circle->center_y + dy;
+  circle.radius = o_current->circle->radius;
 
   if (o_current->saved_color != -1) {
     color = o_current->saved_color;
@@ -429,26 +429,7 @@ void o_circle_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_
     color = o_current->color;
   }
 
-  WORLDtoSCREEN (w_current, o_current->circle->center_x + dx - o_current->circle->radius,
-                            o_current->circle->center_y + dy + o_current->circle->radius,
-                            &sx1, &sy1);
-  WORLDtoSCREEN (w_current, o_current->circle->center_x + dx + o_current->circle->radius,
-                            o_current->circle->center_y + dy - o_current->circle->radius,
-                            &sx2, &sy2);
-
-  cx = (double)(sx1 + sx2) / 2.;
-  cy = (double)(sy1 + sy2) / 2.;
-  radius = (double)(sy2 - sy1) / 2.;
-
-  cairo_translate (w_current->cr, cx, cy);
-
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-
-  gschem_cairo_arc (w_current->cr, 1, 0., 0., radius, 0., 360);
-  cairo_identity_matrix (w_current->cr);
+  circle_path (w_current, &object);
 
   gschem_cairo_set_source_color (w_current->cr, x_color_lookup_dark (color));
   gschem_cairo_stroke (w_current->cr, TYPE_SOLID, END_NONE, 1, -1, -1);
@@ -591,33 +572,24 @@ void o_circle_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_circle_draw_rubber (GSCHEM_TOPLEVEL *w_current)
 {
-  int sx1, sy1, sx2, sy2;
-  double cx, cy;
-  double radius;
+  OBJECT object;
+  CIRCLE circle;
+  int x1, y1, x2, y2;
 
-  /* draw the circle from the w_current variables */
+  /* Setup a fake object to pass the drawing routine */
+  object.circle = &circle;
+  object.line_width = 0; /* clamped to 1 pixel in circle_path */
+  circle.center_x = w_current->first_wx;
+  circle.center_y = w_current->first_wy;
+  circle.radius   = w_current->distance;
 
-  WORLDtoSCREEN (w_current, w_current->first_wx - w_current->distance,
-                            w_current->first_wy + w_current->distance,
-                            &sx1, &sy1);
-  WORLDtoSCREEN (w_current, w_current->first_wx + w_current->distance,
-                            w_current->first_wy - w_current->distance,
-                            &sx2, &sy2);
+  circle_path (w_current, &object);
 
-  cx = (double)(sx1 + sx2) / 2.;
-  cy = (double)(sy1 + sy2) / 2.;
-  radius = (double)(sy2 - sy1) / 2.;
-
-  cairo_translate (w_current->cr, cx, cy);
-
-  /* Adjust for non-uniform X/Y scale factor. Note that the + 1
-     allows for the case where sx2 == sx1 or sy2 == sy1 */
-  cairo_scale (w_current->cr, (double)(sx2 - sx1 + 1) /
-                              (double)(sy2 - sy1 + 1), 1.);
-
-  gschem_cairo_arc (w_current->cr, 1, 0., 0., radius, 0., 360);
-  cairo_identity_matrix (w_current->cr);
-  gschem_cairo_line (w_current->cr, END_NONE, 1, cx, cy, cx + radius, cy);
+  WORLDtoSCREEN (w_current, w_current->first_wx,
+                            w_current->first_wy, &x1, &y1);
+  WORLDtoSCREEN (w_current, w_current->first_wx + w_current->distance,
+                            w_current->first_wy, &x2, &y2);
+  gschem_cairo_line (w_current->cr, END_NONE, 1, x1, y1, x2, y2);
 
   gschem_cairo_set_source_color (w_current->cr,
                                  x_color_lookup_dark (SELECT_COLOR));
diff --git a/gschem/src/o_path.c b/gschem/src/o_path.c
index 50b78f3..e9ef0d1 100644
--- a/gschem/src/o_path.c
+++ b/gschem/src/o_path.c
@@ -46,6 +46,63 @@ static void hint_coordinates (int x, int y, double *fx, double *fy, int width)
 }
 
 
+static void path_path (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
+{
+  PATH *path = object->path;
+  int line_width;
+  int i;
+  int x1, y1, x2, y2, x3, y3;
+  double fx1 = 0.0, fy1 = 0.0;
+  double fx2 = 0.0, fy2 = 0.0;
+  double fx3 = 0.0, fy3 = 0.0;
+
+  line_width = SCREENabs (w_current, object->line_width);
+  if (line_width <= 0) {
+    line_width = 1;
+  }
+
+  for (i = 0; i <  path->num_sections; i++) {
+    PATH_SECTION *section = &path->sections[i];
+
+    switch (section->code) {
+      case PATH_CURVETO:
+        /* Two control point grips */
+        WORLDtoSCREEN (w_current, section->x1, section->y1, &x1, &y1);
+        WORLDtoSCREEN (w_current, section->x2, section->y2, &x2, &y2);
+        hint_coordinates (x1, y1, &fx1, &fy1, line_width);
+        hint_coordinates (x2, y2, &fx2, &fy2, line_width);
+        /* Fall through */
+      case PATH_MOVETO:
+      case PATH_MOVETO_OPEN:
+      case PATH_LINETO:
+        /* Destination point grip */
+        WORLDtoSCREEN (w_current, section->x3, section->y3, &x3, &y3);
+        hint_coordinates (x3, y3, &fx3, &fy3, line_width);
+      case PATH_END:
+        break;
+    }
+
+    switch (section->code) {
+      case PATH_MOVETO:
+        cairo_close_path (w_current->cr);
+        /* fall-through */
+      case PATH_MOVETO_OPEN:
+        cairo_move_to (w_current->cr, fx3, fy3);
+        break;
+      case PATH_CURVETO:
+        cairo_curve_to (w_current->cr, fx1, fy1, fx2, fy2, fx3, fy3);
+        break;
+      case PATH_LINETO:
+        cairo_line_to (w_current->cr, fx3, fy3);
+        break;
+      case PATH_END:
+        cairo_close_path (w_current->cr);
+        break;
+    }
+  }
+}
+
+
 static void path_to_points_modify (GSCHEM_TOPLEVEL *w_current, PATH *path,
                                    int dx, int dy, int new_x, int new_y, int whichone,
                                    GdkPoint **points, int *num_points)
@@ -131,6 +188,57 @@ static void path_to_points_modify (GSCHEM_TOPLEVEL *w_current, PATH *path,
 }
 
 
+static PATH *path_copy_modify (PATH *path, int dx, int dy,
+                               int new_x, int new_y, int whichone)
+{
+  PATH *new_path;
+  int x1, y1, x2, y2, x3, y3;
+  int i;
+  int grip_no = 0;
+
+  new_path = g_malloc (sizeof (PATH));
+  new_path->sections = g_malloc (path->num_sections * sizeof (PATH_SECTION));
+  new_path->num_sections = path->num_sections;
+  new_path->num_sections_max = path->num_sections;
+
+  for (i = 0; i <  path->num_sections; i++) {
+    PATH_SECTION *section     = &path->sections[i];
+    PATH_SECTION *new_section = &new_path->sections[i];
+
+    x1 = section->x1 + dx; y1 = section->y1 + dy;
+    x2 = section->x2 + dx; y2 = section->y2 + dy;
+    x3 = section->x3 + dx; y3 = section->y3 + dy;
+
+    switch (section->code) {
+      case PATH_CURVETO:
+        /* Two control point grips */
+        if (whichone == grip_no++) {
+          x1 = new_x; y1 = new_y;
+        }
+        if (whichone == grip_no++) {
+          x2 = new_x; y2 = new_y;
+        }
+        /* Fall through */
+      case PATH_MOVETO:
+      case PATH_MOVETO_OPEN:
+      case PATH_LINETO:
+        /* Destination point grip */
+        if (whichone == grip_no++) {
+          x3 = new_x; y3 = new_y;
+        }
+      case PATH_END:
+        break;
+    }
+
+    new_section->code = section->code;
+    new_section->x1 = x1;  new_section->y1 = y1;
+    new_section->x2 = x2;  new_section->y2 = y2;
+    new_section->x3 = x3;  new_section->y3 = y3;
+  }
+  return new_path;
+}
+
+
 /*! \brief Placeholder filling function.
  *  \par Function Description
  *  This function does nothing. It has the same prototype as all the
@@ -280,12 +388,6 @@ void o_path_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   int line_width, length, space;
   int fill_width, angle1, pitch1, angle2, pitch2;
   FILL_FUNC fill_func;
-  PATH_SECTION *section;
-  int i;
-  int x1, y1, x2, y2, x3, y3;
-  double fx1 = 0.0, fy1 = 0.0;
-  double fx2 = 0.0, fy2 = 0.0;
-  double fx3 = 0.0, fy3 = 0.0;
 
   COLOR *color;
 
@@ -379,45 +481,7 @@ void o_path_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
   (*fill_func) (w_current->drawable, w_current->gc, color,
                 w_current, path, fill_width, angle1, pitch1, angle2, pitch2);
 
-  for (i = 0; i <  path->num_sections; i++) {
-    section = &path->sections[i];
-
-    switch (section->code) {
-      case PATH_CURVETO:
-        /* Two control point grips */
-        WORLDtoSCREEN (w_current, section->x1, section->y1, &x1, &y1);
-        WORLDtoSCREEN (w_current, section->x2, section->y2, &x2, &y2);
-        hint_coordinates (x1, y1, &fx1, &fy1, line_width);
-        hint_coordinates (x2, y2, &fx2, &fy2, line_width);
-        /* Fall through */
-      case PATH_MOVETO:
-      case PATH_MOVETO_OPEN:
-      case PATH_LINETO:
-        /* Destination point grip */
-        WORLDtoSCREEN (w_current, section->x3, section->y3, &x3, &y3);
-        hint_coordinates (x3, y3, &fx3, &fy3, line_width);
-      case PATH_END:
-        break;
-    }
-
-    switch (section->code) {
-      case PATH_MOVETO:
-        cairo_close_path (w_current->cr);
-        /* fall-through */
-      case PATH_MOVETO_OPEN:
-        cairo_move_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_CURVETO:
-        cairo_curve_to (w_current->cr, fx1, fy1, fx2, fy2, fx3, fy3);
-        break;
-      case PATH_LINETO:
-        cairo_line_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_END:
-        cairo_close_path (w_current->cr);
-        break;
-    }
-  }
+  path_path (w_current, o_current);
 
   gschem_cairo_set_source_color (w_current->cr, color);
 
@@ -488,66 +552,25 @@ void o_path_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
  */
 void o_path_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
-  PATH *path = o_current->path;
+  OBJECT object;
   int color;
   int line_width = 1;
-  PATH_SECTION *section;
-  int i;
-  int x1, y1, x2, y2, x3, y3;
-  double fx1 = 0.0, fy1 = 0.0;
-  double fx2 = 0.0, fy2 = 0.0;
-  double fx3 = 0.0, fy3 = 0.0;
 
-  if (path == NULL) {
-    return;
-  }
+  g_return_if_fail (o_current->path != NULL);
 
-  if (toplevel->override_color != -1 ) {
-    color = toplevel->override_color;
+  /* Setup a fake object to pass the drawing routine */
+  object.line_width = 0; /* clamped to 1 pixel in circle_path */
+  object.path = path_copy_modify (o_current->path, dx, dy, 0, 0, -1);
+
+  if (w_current->toplevel->override_color != -1 ) {
+    color = w_current->toplevel->override_color;
   } else {
     color = o_current->color;
   }
 
-  for (i = 0; i <  path->num_sections; i++) {
-    section = &path->sections[i];
-
-    switch (section->code) {
-      case PATH_CURVETO:
-        /* Two control point grips */
-        WORLDtoSCREEN (w_current, section->x1 + dx, section->y1 + dy, &x1, &y1);
-        WORLDtoSCREEN (w_current, section->x2 + dx, section->y2 + dy, &x2, &y2);
-        hint_coordinates (x1, y1, &fx1, &fy1, line_width);
-        hint_coordinates (x2, y2, &fx2, &fy2, line_width);
-        /* Fall through */
-      case PATH_MOVETO:
-      case PATH_MOVETO_OPEN:
-      case PATH_LINETO:
-        /* Destination point grip */
-        WORLDtoSCREEN (w_current, section->x3 + dx, section->y3 + dy, &x3, &y3);
-        hint_coordinates (x3, y3, &fx3, &fy3, line_width);
-      case PATH_END:
-        break;
-    }
-
-    switch (section->code) {
-      case PATH_MOVETO:
-        cairo_close_path (w_current->cr);
-        /* fall-through */
-      case PATH_MOVETO_OPEN:
-        cairo_move_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_CURVETO:
-        cairo_curve_to (w_current->cr, fx1, fy1, fx2, fy2, fx3, fy3);
-        break;
-      case PATH_LINETO:
-        cairo_line_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_END:
-        cairo_close_path (w_current->cr);
-        break;
-    }
-  }
+  path_path (w_current, &object);
+  g_free (object.path->sections);
+  g_free (object.path);
 
   gschem_cairo_set_source_color (w_current->cr, x_color_lookup_dark (color));
   gschem_cairo_stroke (w_current->cr, TYPE_SOLID, END_NONE, line_width, -1, -1);
@@ -629,75 +652,18 @@ void o_path_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_path_draw_rubber (GSCHEM_TOPLEVEL *w_current)
 {
-  int whichone = w_current->which_grip;
-  PATH *path = w_current->which_object->path;
-  PATH_SECTION *section;
-  int i;
-  int grip_no = 0;
+  OBJECT object;
   int line_width = 1;
-  int x, y;
-  int x1, y1, x2, y2, x3, y3;
-  double fx1 = 0.0, fy1 = 0.0;
-  double fx2 = 0.0, fy2 = 0.0;
-  double fx3 = 0.0, fy3 = 0.0;
-
-  x = w_current->second_wx;
-  y = w_current->second_wy;
 
-  for (i = 0; i <  path->num_sections; i++) {
-    section = &path->sections[i];
+  /* Setup a fake object to pass the drawing routine */
+  object.line_width = 0; /* clamped to 1 pixel in circle_path */
+  object.path = path_copy_modify (w_current->which_object->path, 0, 0,
+                                  w_current->second_wx,
+                                  w_current->second_wy, w_current->which_grip);
 
-    x1 = section->x1;
-    y1 = section->y1;
-    x2 = section->x2;
-    y2 = section->y2;
-    x3 = section->x3;
-    y3 = section->y3;
-
-    switch (section->code) {
-      case PATH_CURVETO:
-        /* Two control point grips */
-        if (whichone == grip_no++) {
-          x1 = x; y1 = y;
-        }
-        if (whichone == grip_no++) {
-          x2 = x; y2 = y;
-        }
-        WORLDtoSCREEN (w_current, x1, y1, &x1, &y1);
-        WORLDtoSCREEN (w_current, x2, y2, &x2, &y2);
-        hint_coordinates (x1, y1, &fx1, &fy1, line_width);
-        hint_coordinates (x2, y2, &fx2, &fy2, line_width);
-        /* Fall through */
-      case PATH_MOVETO:
-      case PATH_MOVETO_OPEN:
-      case PATH_LINETO:
-        /* Destination point grip */
-        if (whichone == grip_no++) {
-          x3 = x; y3 = y;
-        }
-        WORLDtoSCREEN (w_current, x3, y3, &x3, &y3);
-        hint_coordinates (x3, y3, &fx3, &fy3, line_width);
-      case PATH_END:
-        break;
-    }
-
-    switch (section->code) {
-      case PATH_MOVETO:
-        cairo_close_path (w_current->cr);
-        /* fall-through */
-      case PATH_MOVETO_OPEN:
-        cairo_move_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_CURVETO:
-        cairo_curve_to (w_current->cr, fx1, fy1, fx2, fy2, fx3, fy3);
-        break;
-      case PATH_LINETO:
-        cairo_line_to (w_current->cr, fx3, fy3);
-        break;
-      case PATH_END:
-        break;
-    }
-  }
+  path_path (w_current, &object);
+  g_free (object.path->sections);
+  g_free (object.path);
 
   gschem_cairo_set_source_color (w_current->cr, x_color_lookup (SELECT_COLOR));
   gschem_cairo_stroke (w_current->cr, TYPE_SOLID, END_SQUARE, line_width, -1, -1);




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs