about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-02-17 17:01:46 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-02-17 17:01:46 +0000
commit48fcca1c8d1cf815774e6168042a54aa5ebd0849 (patch)
tree22aee86d75444c78d2ec5791ee5cfeee89c423b9
parentc3f6dbb9e9c68644f87b328650ef3f05359608b2 (diff)
downloadnetpbm-mirror-48fcca1c8d1cf815774e6168042a54aa5ebd0849.tar.gz
netpbm-mirror-48fcca1c8d1cf815774e6168042a54aa5ebd0849.tar.xz
netpbm-mirror-48fcca1c8d1cf815774e6168042a54aa5ebd0849.zip
Various pamtosvg fixes, cleanup
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@580 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/other/pamtosvg/curve.c214
-rw-r--r--converter/other/pamtosvg/curve.h56
-rw-r--r--converter/other/pamtosvg/fit.c1049
-rw-r--r--converter/other/pamtosvg/pamtosvg.c3
-rw-r--r--converter/other/pamtosvg/spline.c10
-rw-r--r--doc/HISTORY2
6 files changed, 752 insertions, 582 deletions
diff --git a/converter/other/pamtosvg/curve.c b/converter/other/pamtosvg/curve.c
index cc8aeb59..6cfe8ead 100644
--- a/converter/other/pamtosvg/curve.c
+++ b/converter/other/pamtosvg/curve.c
@@ -42,18 +42,21 @@ int_to_real_coord(pm_pixelcoord const int_coord) {
 
 /* Return an entirely empty curve.  */
 
-curve_type
-new_curve (void)
-{
-  curve_type curve;
-  MALLOCVAR_NOFAIL(curve);
-  curve->point_list = NULL;
-  CURVE_LENGTH (curve) = 0;
-  CURVE_CYCLIC (curve) = false;
-  CURVE_START_TANGENT (curve) = CURVE_END_TANGENT (curve) = NULL;
-  PREVIOUS_CURVE (curve) = NEXT_CURVE (curve) = NULL;
+curve *
+new_curve(void) {
+  curve * curveP;
 
-  return curve;
+  MALLOCVAR_NOFAIL(curveP);
+
+  curveP->point_list = NULL;
+  CURVE_LENGTH(curveP) = 0;
+  CURVE_CYCLIC(curveP) = false;
+  CURVE_BEG_SLOPE(curveP) = curve_slope_none();
+  CURVE_END_SLOPE(curveP) = curve_slope_none();
+  PREVIOUS_CURVE(curveP)  = NULL;
+  NEXT_CURVE(curveP)      = NULL;
+
+  return curveP;
 }
 
 
@@ -71,23 +74,39 @@ copy_most_of_curve (curve_type old_curve)
   return curve;
 }
 
+void
+move_curve(curve * const dstP,
+           curve * const srcP) {
+
+    /* Move ownership of dynamically allocated memory from source 
+       to destination; destroy source.
+    */
+
+   if (CURVE_LENGTH(dstP) > 0)
+       free(dstP->point_list);
+    
+   *dstP = *srcP;
+
+   free(srcP);
+}
+
+
 
 /* The length of CURVE will be zero if we ended up not being able to fit
    it (which in turn implies a problem elsewhere in the program, but at
    any rate, we shouldn't try here to free the nonexistent curve).  */
 
 void
-free_curve (curve_type curve)
-{
-  if (CURVE_LENGTH (curve) > 0)
-    free (curve->point_list);
-  if (CURVE_START_TANGENT (curve))
-    free (CURVE_START_TANGENT (curve));
-  if (CURVE_END_TANGENT (curve))
-    free (CURVE_END_TANGENT (curve));
+free_curve(curve * const curveP) {
+
+   if (CURVE_LENGTH(curveP) > 0)
+       free(curveP->point_list);
+
+   free(curveP);
 }
 
 
+
 void
 append_point(curve_type  const curve,
              float_coord const coord) {
@@ -123,99 +142,99 @@ append_pixel(curve_type    const curve,
     }									\
   while (0)
 
+
+
 void
-log_curve (curve_type curve, bool print_t)
-{
-  unsigned this_point;
-
-  if (!log_file) return;
-
-  LOG1 ("curve id = %lx:\n", (unsigned long) curve);
-  LOG1 ("  length = %u.\n", CURVE_LENGTH (curve));
-  if (CURVE_CYCLIC (curve))
-    LOG ("  cyclic.\n");
-
-  /* It should suffice to check just one of the tangents for being null
-     -- either they both should be, or neither should be.  */
-  if (CURVE_START_TANGENT (curve) != NULL)
-    LOG4 ("  tangents = (%.3f,%.3f) & (%.3f,%.3f).\n",
-          CURVE_START_TANGENT (curve)->dx, CURVE_START_TANGENT (curve)->dy,
-          CURVE_END_TANGENT (curve)->dx, CURVE_END_TANGENT (curve)->dy);
-
-  LOG ("  ");
-
-  /* If the curve is short enough, don't use ellipses.  */
-  if (CURVE_LENGTH (curve) <= NUM_TO_PRINT * 2)
-    {
-      for (this_point = 0; this_point < CURVE_LENGTH (curve); this_point++)
-        {
-          LOG_CURVE_POINT (curve, this_point, print_t);
-          LOG (" ");
-
-          if (this_point != CURVE_LENGTH (curve) - 1
-              && (this_point + 1) % NUM_TO_PRINT == 0)
-            LOG ("\n  ");
+log_curve(curve * const curveP,
+          bool    const print_t) {
+
+    if (!log_file)
+        return;
+
+    LOG1("curve id = %lx:\n", (unsigned long) curveP);
+    LOG1("  length = %u.\n", CURVE_LENGTH(curveP));
+    if (CURVE_CYCLIC(curveP))
+        LOG("  cyclic.\n");
+
+    /* It should suffice to check just one of the tangents for being present
+       -- either they both should be, or neither should be.
+    */
+    if (curve_slope_is_present(CURVE_BEG_SLOPE(curveP)))
+        LOG4("  tangents = (%.3f,%.3f) & (%.3f,%.3f).\n",
+             CURVE_BEG_SLOPE(curveP).dx, CURVE_BEG_SLOPE(curveP).dy,
+             CURVE_END_SLOPE(curveP).dx, CURVE_END_SLOPE(curveP).dy);
+
+    LOG("  ");
+
+    /* If the curve is short enough, don't use ellipses.  */
+    if (CURVE_LENGTH(curveP) <= NUM_TO_PRINT * 2) {
+        unsigned int thisPoint;
+    
+        for (thisPoint = 0; thisPoint < CURVE_LENGTH(curveP); ++thisPoint) {
+            LOG_CURVE_POINT(curveP, thisPoint, print_t);
+            LOG(" ");
+
+            if (thisPoint != CURVE_LENGTH(curveP) - 1
+                && (thisPoint + 1) % NUM_TO_PRINT == 0)
+                LOG("\n  ");
         }
-    }
-  else
-    {
-      for (this_point = 0;
-           this_point < NUM_TO_PRINT && this_point < CURVE_LENGTH (curve);
-           this_point++)
-        {
-          LOG_CURVE_POINT (curve, this_point, print_t);
-          LOG (" ");
+    } else {
+        unsigned int thisPoint;
+        for (thisPoint = 0;
+             thisPoint < NUM_TO_PRINT && thisPoint < CURVE_LENGTH(curveP);
+             ++thisPoint) {
+            LOG_CURVE_POINT(curveP, thisPoint, print_t);
+            LOG(" ");
         }
 
-      LOG ("...\n   ...");
+        LOG("...\n   ...");
 
-      for (this_point = CURVE_LENGTH (curve) - NUM_TO_PRINT;
-           this_point < CURVE_LENGTH (curve);
-           this_point++)
-        {
-          LOG (" ");
-          LOG_CURVE_POINT (curve, this_point, print_t);
+        for (thisPoint = CURVE_LENGTH(curveP) - NUM_TO_PRINT;
+             thisPoint < CURVE_LENGTH(curveP);
+             ++thisPoint) {
+            LOG(" ");
+            LOG_CURVE_POINT(curveP, thisPoint, print_t);
         }
     }
-
-  LOG (".\n");
+    LOG(".\n");
 }
 
 
 /* Like `log_curve', but write the whole thing.  */
 
 void
-log_entire_curve (curve_type curve)
-{
-  unsigned this_point;
+log_entire_curve(curve * const curveP) {
 
-  if (!log_file) return;
+    unsigned int thisPoint;
 
-  LOG1 ("curve id = %lx:\n", (unsigned long) curve);
-  LOG1 ("  length = %u.\n", CURVE_LENGTH (curve));
-  if (CURVE_CYCLIC (curve))
-    LOG ("  cyclic.\n");
+    if (!log_file)
+        return;
 
-  /* It should suffice to check just one of the tangents for being null
-     -- either they both should be, or neither should be.  */
-  if (CURVE_START_TANGENT (curve) != NULL)
-    LOG4 ("  tangents = (%.3f,%.3f) & (%.3f,%.3f).\n",
-          CURVE_START_TANGENT (curve)->dx, CURVE_START_TANGENT (curve)->dy,
-          CURVE_END_TANGENT (curve)->dx, CURVE_END_TANGENT (curve)->dy);
+    LOG1("curve id = %lx:\n", (unsigned long) curveP);
+    LOG1("  length = %u.\n", CURVE_LENGTH(curveP));
+    if (CURVE_CYCLIC(curveP))
+        LOG("  cyclic.\n");
 
-  LOG (" ");
+    /* It should suffice to check just one of the tangents for being present
+       -- either they both should be, or neither should be.  */
+    if (curve_slope_is_present(CURVE_BEG_SLOPE(curveP)))
+        LOG4("  tangents = (%.3f,%.3f) & (%.3f,%.3f).\n",
+             CURVE_BEG_SLOPE(curveP).dx, CURVE_BEG_SLOPE(curveP).dy,
+             CURVE_END_SLOPE(curveP).dx, CURVE_END_SLOPE(curveP).dy);
+    
+    LOG(" ");
 
-  for (this_point = 0; this_point < CURVE_LENGTH (curve); this_point++)
-    {
-      LOG (" ");
-      LOG_CURVE_POINT (curve, this_point, true);
-      /* Compiler warning `Condition is always true' can be ignored */
+    for (thisPoint = 0; thisPoint < CURVE_LENGTH(curveP); ++thisPoint) {
+        LOG(" ");
+        LOG_CURVE_POINT(curveP, thisPoint, true);
+        /* Compiler warning `Condition is always true' can be ignored */
     }
 
-  LOG (".\n");
+    LOG(".\n");
 }
 
 
+
 /* Return an initialized but empty curve list.  */
 
 curve_list_type
@@ -233,19 +252,16 @@ new_curve_list (void)
 /* Free a curve list and all the curves it contains.  */
 
 void
-free_curve_list(curve_list_type * const curve_list) {
+free_curve_list(curve_list_type * const curveListP) {
 
-  unsigned this_curve;
+    unsigned int thisCurve;
 
-  for (this_curve = 0; this_curve < curve_list->length; this_curve++)
-    {
-      free_curve (curve_list->data[this_curve]);
-      free (curve_list->data[this_curve]);
-    }
+    for (thisCurve = 0; thisCurve < curveListP->length; ++thisCurve)
+        free_curve(curveListP->data[thisCurve]);
 
-  /* If the character was empty, it won't have any curves.  */
-  if (curve_list->data != NULL)
-    free (curve_list->data);
+    /* If the character was empty, it won't have any curves.  */
+    if (curveListP->data != NULL)
+        free (curveListP->data);
 }
 
 
diff --git a/converter/other/pamtosvg/curve.h b/converter/other/pamtosvg/curve.h
index 2f010d45..5c499950 100644
--- a/converter/other/pamtosvg/curve.h
+++ b/converter/other/pamtosvg/curve.h
@@ -20,19 +20,31 @@ typedef struct {
 
 
 
-struct curve {
+typedef struct curve {
 /*----------------------------------------------------------------------------
   An ordered list of contiguous points in the raster, with no corners
   in it.  I.e. something that could reasonably be fit to a spline.
 -----------------------------------------------------------------------------*/
     point_type *   point_list;
+        /* Array of the points in the curve.  Malloc'ed.  Size is 'length'.
+           if 'length' is zero, this is meaningless and no memory is
+           allocated.
+        */
     unsigned       length;
+        /* Number of points in the curve */
     bool           cyclic;
-    vector_type *  start_tangent;
-    vector_type *  end_tangent;
+    vector_type    begSlope;
+        /* Slope of the curve (i.e. of tangent line) at its end point */
+    vector_type    endSlope;
+        /* Slope of the curve (i.e. of tangent line) at its start point */
+
+    /* 'previous' and 'next' links are for the doubly linked list which is
+       a chain of all curves in an outline.  The chain is a cycle for a
+       closed outline and linear for an open outline.
+    */
     struct curve * previous;
     struct curve * next;
-};
+} curve;
 
 typedef struct curve * curve_type;
 
@@ -61,9 +73,20 @@ typedef struct curve * curve_type;
   ? CURVE_CYCLIC (c) ? (signed int) CURVE_LENGTH (c) + (signed int) (n) - 1 : -1\
   : (signed int) (n) - 1)
 
-/* The tangents at the endpoints are computed using the neighboring curves.  */
-#define CURVE_START_TANGENT(c) ((c)->start_tangent)
-#define CURVE_END_TANGENT(c) ((c)->end_tangent)
+#define CURVE_BEG_SLOPE(c) ((c)->begSlope)
+#define CURVE_END_SLOPE(c) ((c)->endSlope)
+
+static __inline__ vector_type
+curve_slope_none(void) {
+    vector_type const retval = {0.0, 0.0, 0.0};
+    return retval;
+}
+
+static bool
+curve_slope_is_present(vector_type const slope) {
+    return slope.dx != 0.0 || slope.dy != 0.0;
+}
+
 #define PREVIOUS_CURVE(c) ((c)->previous)
 #define NEXT_CURVE(c) ((c)->next)
 
@@ -74,8 +97,12 @@ extern curve_type new_curve (void);
 /* Return a curve the same as C, except without any points.  */
 extern curve_type copy_most_of_curve (curve_type c);
 
-/* Free the memory C uses.  */
-extern void free_curve (curve_type c);
+void
+move_curve(curve * const dstP,
+           curve * const srcP);
+
+void
+free_curve(curve * const curveP);
 
 /* Like `append_pixel', for a point in real coordinates.  */
 void
@@ -101,11 +128,12 @@ typedef struct {
 /*----------------------------------------------------------------------------
    An ordered list of contiguous curves of a particular color.
 -----------------------------------------------------------------------------*/
-    curve_type * data;
-    unsigned     length;
-    bool         clockwise;
-    pixel        color;
-    bool         open;
+    curve ** data;
+        /* data[i] is the handle of the ith curve in the list */
+    unsigned length;
+    bool     clockwise;
+    pixel    color;
+    bool     open;
         /* The curve list does not form a closed shape;  i.e. the last
            curve doesn't end where the first one starts.
         */
diff --git a/converter/other/pamtosvg/fit.c b/converter/other/pamtosvg/fit.c
index 2fa64500..56b0bbda 100644
--- a/converter/other/pamtosvg/fit.c
+++ b/converter/other/pamtosvg/fit.c
@@ -56,6 +56,7 @@ typedef struct index_list
 
 
 
+
 static pm_pixelcoord
 real_to_int_coord(float_coord const real_coord) {
 /*----------------------------------------------------------------------------
@@ -360,7 +361,8 @@ remove_adjacent_corners(index_list_type *   const list,
    We should never find two consecutive knees.
 
    Since the first and last points are corners (unless the curve is
-   cyclic), it doesn't make sense to remove those.  */
+   cyclic), it doesn't make sense to remove those.
+*/
 
 /* This evaluates to true if the vector V is zero in one direction and
    nonzero in the other.  */
@@ -388,172 +390,171 @@ remove_adjacent_corners(index_list_type *   const list,
 
 
 static void
-remove_knee_points(curve_type const curve,
-                   bool       const clockwise) {
-
-      unsigned const offset = (CURVE_CYCLIC(curve) == true) ? 0 : 1;
-      curve_type const trimmed_curve = copy_most_of_curve(curve);
-
-      pm_pixelcoord previous;
-      unsigned i;
-
-      if (!CURVE_CYCLIC(curve))
-          append_pixel(trimmed_curve,
-                       real_to_int_coord(CURVE_POINT(curve, 0)));
-
-      previous = real_to_int_coord(CURVE_POINT(curve,
-                                               CURVE_PREV(curve, offset)));
-
-      for (i = offset; i < CURVE_LENGTH (curve) - offset; ++i) {
-          pm_pixelcoord const current =
-              real_to_int_coord(CURVE_POINT(curve, i));
-          pm_pixelcoord const next =
-              real_to_int_coord(CURVE_POINT(curve, CURVE_NEXT(curve, i)));
-          vector_type const prev_delta = IPsubtract(previous, current);
-          vector_type const next_delta = IPsubtract(next, current);
-
-          if (ONLY_ONE_ZERO(prev_delta) && ONLY_ONE_ZERO(next_delta)
-              && ((clockwise && CLOCKWISE_KNEE(prev_delta, next_delta))
-                  || (!clockwise
-                      && COUNTERCLOCKWISE_KNEE(prev_delta, next_delta))))
-              LOG2(" (%d,%d)", current.col, current.row);
-          else {
-              previous = current;
-              append_pixel(trimmed_curve, current);
-          }
-      }
+remove_knee_points(curve * const curveP,
+                   bool    const clockwise) {
 
-      if (!CURVE_CYCLIC(curve))
-          append_pixel(trimmed_curve,
-                       real_to_int_coord(LAST_CURVE_POINT(curve)));
+    unsigned int const offset = CURVE_CYCLIC(curveP) ? 0 : 1;
+    curve * const trimmedCurveP = copy_most_of_curve(curveP);
+
+    pm_pixelcoord previous;
+    unsigned int i;
 
-      if (CURVE_LENGTH(trimmed_curve) == CURVE_LENGTH(curve))
-          LOG(" (none)");
+    if (!CURVE_CYCLIC(curveP))
+        append_pixel(trimmedCurveP,
+                     real_to_int_coord(CURVE_POINT(curveP, 0)));
+
+    previous = real_to_int_coord(CURVE_POINT(curveP,
+                                             CURVE_PREV(curveP, offset)));
+
+    for (i = offset; i < CURVE_LENGTH(curveP) - offset; ++i) {
+        pm_pixelcoord const current =
+            real_to_int_coord(CURVE_POINT(curveP, i));
+        pm_pixelcoord const next =
+            real_to_int_coord(CURVE_POINT(curveP, CURVE_NEXT(curveP, i)));
+        vector_type const prev_delta = IPsubtract(previous, current);
+        vector_type const next_delta = IPsubtract(next, current);
+
+        if (ONLY_ONE_ZERO(prev_delta) && ONLY_ONE_ZERO(next_delta)
+            && ((clockwise && CLOCKWISE_KNEE(prev_delta, next_delta))
+                || (!clockwise
+                    && COUNTERCLOCKWISE_KNEE(prev_delta, next_delta))))
+            LOG2(" (%d,%d)", current.col, current.row);
+        else {
+            previous = current;
+            append_pixel(trimmedCurveP, current);
+        }
+    }
 
-      LOG(".\n");
+    if (!CURVE_CYCLIC(curveP))
+        append_pixel(trimmedCurveP,
+                     real_to_int_coord(LAST_CURVE_POINT(curveP)));
 
-      free_curve(curve);
-      *curve = *trimmed_curve;
-      free(trimmed_curve);      /* free_curve? --- Masatake */
-}
+    if (CURVE_LENGTH(trimmedCurveP) == CURVE_LENGTH(curveP))
+        LOG(" (none)");
 
+    LOG(".\n");
+
+    move_curve(curveP, trimmedCurveP);
+}
 
 
-/* Smooth the curve by adding in neighboring points.  Do this
-   `filter_iterations' times.  But don't change the corners.  */
 
 static void
-filter(curve_type          const curve,
-       fitting_opts_type * const fitting_opts) {
+filter(curve *             const curveP,
+       fitting_opts_type * const fittingOptsP) {
+/*----------------------------------------------------------------------------
+  Smooth the curve by adding in neighboring points.  Do this
+  fittingOptsP->filter_iterations times.  But don't change the corners.
+-----------------------------------------------------------------------------*/
+    unsigned int const offset = CURVE_CYCLIC(curveP) ? 0 : 1;
 
-    unsigned iteration, this_point;
-    unsigned offset = (CURVE_CYCLIC (curve) == true) ? 0 : 1;
-    float_coord prev_new_point;
+    unsigned int iteration, thisPoint;
+    float_coord prevNewPoint;
     
-    /* We must have at least three points---the previous one, the current
+    /* We must have at least three points -- the previous one, the current
        one, and the next one.  But if we don't have at least five, we will
        probably collapse the curve down onto a single point, which means
        we won't be able to fit it with a spline.
     */
-    if (CURVE_LENGTH (curve) < 5) {
-        LOG1 ("Length is %u, not enough to filter.\n", CURVE_LENGTH (curve));
+    if (CURVE_LENGTH(curveP) < 5) {
+        LOG1("Length is %u, not enough to filter.\n", CURVE_LENGTH(curveP));
         return;
     }
 
-    prev_new_point.x = FLT_MAX;
-    prev_new_point.y = FLT_MAX;
-    prev_new_point.z = FLT_MAX;
+    prevNewPoint.x = FLT_MAX;
+    prevNewPoint.y = FLT_MAX;
+    prevNewPoint.z = FLT_MAX;
     
     for (iteration = 0;
-         iteration < fitting_opts->filter_iterations;
+         iteration < fittingOptsP->filter_iterations;
          ++iteration) {
-        curve_type newcurve = copy_most_of_curve (curve);
-        bool collapsed = false;
+        curve * const newcurveP = copy_most_of_curve(curveP);
+
+        bool collapsed;
         
+        collapsed = false;  /* initial value */
+
         /* Keep the first point on the curve.  */
         if (offset)
-            append_point (newcurve, CURVE_POINT (curve, 0));
+            append_point(newcurveP, CURVE_POINT(curveP, 0));
         
-        for (this_point = offset;
-             this_point < CURVE_LENGTH (curve) - offset;
-             ++this_point) {
+        for (thisPoint = offset;
+             thisPoint < CURVE_LENGTH(curveP) - offset;
+             ++thisPoint) {
             vector_type in, out, sum;
-            float_coord new_point;
+            float_coord newPoint;
             
             /* Calculate the vectors in and out, computed by looking
-               at n points on either side of this_point. Experimental
+               at n points on either side of this_point.  Experimental
                it was found that 2 is optimal.
             */
 
             signed int prev, prevprev; /* have to be signed */
             unsigned int next, nextnext;
-            float_coord candidate = CURVE_POINT (curve, this_point);
+            float_coord candidate = CURVE_POINT(curveP, thisPoint);
             
-            prev = CURVE_PREV (curve, this_point);
-            prevprev = CURVE_PREV (curve, prev);
-            next = CURVE_NEXT (curve, this_point);
-            nextnext = CURVE_NEXT (curve, next);
+            prev = CURVE_PREV(curveP, thisPoint);
+            prevprev = CURVE_PREV(curveP, prev);
+            next = CURVE_NEXT(curveP, thisPoint);
+            nextnext = CURVE_NEXT(curveP, next);
             
             /* Add up the differences from p of the `surround' points
                before p.
             */
             in.dx = in.dy = in.dz = 0.0;
 
-            in = Vadd (in, Psubtract (CURVE_POINT (curve, prev), candidate));
+            in = Vadd(in, Psubtract(CURVE_POINT(curveP, prev), candidate));
             if (prevprev >= 0)
                 in = Vadd(in,
-                          Psubtract(CURVE_POINT (curve, prevprev), candidate));
+                          Psubtract(CURVE_POINT(curveP, prevprev), candidate));
             
             /* And the points after p.  Don't use more points after p than we
                ended up with before it.
             */
             out.dx = out.dy = out.dz = 0.0;
             
-            out = Vadd (out, Psubtract (CURVE_POINT (curve, next), candidate));
-            if (nextnext < CURVE_LENGTH (curve))
+            out = Vadd(out, Psubtract(CURVE_POINT(curveP, next), candidate));
+            if (nextnext < CURVE_LENGTH(curveP))
                 out = Vadd(out,
-                           Psubtract(CURVE_POINT (curve, nextnext),
+                           Psubtract(CURVE_POINT(curveP, nextnext),
                                      candidate));
             
             /* Start with the old point.  */
-            new_point = candidate;
-            sum = Vadd (in, out);
+            newPoint = candidate;
+            sum = Vadd(in, out);
             /* We added 2*n+2 points, so we have to divide the sum by 2*n+2 */
-            new_point.x += sum.dx / 6;
-            new_point.y += sum.dy / 6;
-            new_point.z += sum.dz / 6;
-            if (fabs (prev_new_point.x - new_point.x) < 0.3
-                && fabs (prev_new_point.y - new_point.y) < 0.3
-                && fabs (prev_new_point.z - new_point.z) < 0.3) {
+            newPoint.x += sum.dx / 6;
+            newPoint.y += sum.dy / 6;
+            newPoint.z += sum.dz / 6;
+            if (fabs(prevNewPoint.x - newPoint.x) < 0.3
+                && fabs (prevNewPoint.y - newPoint.y) < 0.3
+                && fabs (prevNewPoint.z - newPoint.z) < 0.3) {
                 collapsed = true;
                 break;
             }
             
-            
             /* Put the newly computed point into a separate curve, so it
                doesn't affect future computation (on this iteration).
             */
-            append_point (newcurve, prev_new_point = new_point);
+            append_point(newcurveP, prevNewPoint = newPoint);
         }
         
         if (collapsed)
-            free_curve (newcurve);
+            free_curve(newcurveP);
         else {
             /* Just as with the first point, we have to keep the last
                point.
             */
             if (offset)
-                append_point (newcurve, LAST_CURVE_POINT (curve));
+                append_point(newcurveP, LAST_CURVE_POINT(curveP));
             
             /* Set the original curve to the newly filtered one, and go
                again.
             */
-            free_curve (curve);
-            *curve = *newcurve;
+            move_curve(curveP, newcurveP);
         }
-        free (newcurve);
     }
-    log_curve (curve, false);
+    log_curve(curveP, false);
 }
 
 
@@ -690,24 +691,24 @@ makeOutlineOneCurve(pixel_outline_type const outline,
 /*----------------------------------------------------------------------------
    Add to *curveListP a single curve that represents the outline 'outline'.
 -----------------------------------------------------------------------------*/
-    curve_type curve;
+    curve * curveP;
     unsigned int pixelSeq;
 
-    curve = new_curve();
-    
+    curveP = new_curve();
+
     for (pixelSeq = 0; pixelSeq < O_LENGTH(outline); ++pixelSeq)
-        append_pixel(curve, O_COORDINATE(outline, pixelSeq));
+        append_pixel(curveP, O_COORDINATE(outline, pixelSeq));
     
-    if (curveListP->open)
-        CURVE_CYCLIC(curve) = false;
+    if (outline.open)
+        CURVE_CYCLIC(curveP) = false;
     else
-        CURVE_CYCLIC(curve) = true;
+        CURVE_CYCLIC(curveP) = true;
     
     /* Make it a one-curve cycle */
-    NEXT_CURVE(curve)     = curve;
-    PREVIOUS_CURVE(curve) = curve;
+    NEXT_CURVE(curveP)     = curveP;
+    PREVIOUS_CURVE(curveP) = curveP;
 
-    append_curve(curveListP, curve);
+    append_curve(curveListP, curveP);
 }
 
 
@@ -716,12 +717,20 @@ static void
 addCurveStartingAtCorner(pixel_outline_type const outline,
                          index_list_type    const cornerList,
                          unsigned int       const cornerSeq,
-                         curve_list_type *  const curveListP) {
+                         curve_list_type *  const curveListP,
+                         curve **           const curCurvePP) {
+/*----------------------------------------------------------------------------
+   Add to the list *curveListP a new curve that starts at the cornerSeq'th
+   corner in outline 'outline' (whose corners are 'cornerList') and
+   goes to the next corner (or the end of the outline if no next corner).
 
+   Furthermore, add that curve to the curve chain whose end is pointed
+   to by *curCurvePP (NULL means chain is empty).
+-----------------------------------------------------------------------------*/
     unsigned int const cornerPixelSeq = GET_INDEX(cornerList, cornerSeq);
     
     unsigned int lastPixelSeq;
-    curve_type curve;
+    curve * curveP;
     unsigned int pixelSeq;
     
     if (cornerSeq + 1 >= cornerList.length)
@@ -731,20 +740,23 @@ addCurveStartingAtCorner(pixel_outline_type const outline,
         /* Go through the next corner */
         lastPixelSeq = GET_INDEX(cornerList, cornerSeq + 1);
     
-    curve = new_curve();
+    curveP = new_curve();
 
     for (pixelSeq = cornerPixelSeq; pixelSeq <= lastPixelSeq; ++pixelSeq)
-        append_pixel(curve, O_COORDINATE(outline, pixelSeq));
+        append_pixel(curveP, O_COORDINATE(outline, pixelSeq));
     
+    append_curve(curveListP, curveP);
     {
-        /* Add curve to end of chain */
-        if (!CURVE_LIST_EMPTY(*curveListP)) {
-            curve_type const previousCurve = LAST_CURVE_LIST_ELT(*curveListP);
-            NEXT_CURVE(previousCurve) = curve;
-            PREVIOUS_CURVE(curve)     = previousCurve;
+        /* Add the new curve to the outline chain */
+
+        curve * const oldCurCurveP = *curCurvePP;
+
+        if (oldCurCurveP) {
+            NEXT_CURVE(oldCurCurveP) = curveP;
+            PREVIOUS_CURVE(curveP)   = oldCurCurveP;
         }
+        *curCurvePP = curveP;
     }
-    append_curve(curveListP, curve);
 }
 
 
@@ -774,49 +786,54 @@ divideOutlineWithCorners(pixel_outline_type const outline,
     unsigned int const firstCurveSeq = CURVE_LIST_LENGTH(*curveListP);
         /* Index in curve list of the first curve we add */
     unsigned int cornerSeq;
+    curve * curCurveP;
+        /* Pointer to the curve we most recently added for this outline.
+           Null if none
+        */
 
     assert(cornerList.length > 0);
 
+    curCurveP = NULL;  /* No curves in outline chain yet */
+
     if (outline.open) {
-        /* Start with a curve that contains the point up to the first
+        /* Start with a curve that contains the points up to the first
            corner
         */
-        curve_type curve;
+        curve * curveP;
         unsigned int pixelSeq;
         
-        curve = new_curve();
+        curveP = new_curve();
 
         for (pixelSeq = 0; pixelSeq <= GET_INDEX(cornerList, 0); ++pixelSeq)
-            append_pixel(curve, O_COORDINATE(outline, pixelSeq));
+            append_pixel(curveP, O_COORDINATE(outline, pixelSeq));
 
-        append_curve(curveListP, curve);
-    } else
+        append_curve(curveListP, curveP);
+        curCurveP = curveP;  /* Only curve in outline chain now */
+    } else {
         /* We'll pick up the pixels before the first corner at the end */
-
+    }
     /* Add to the list a curve that starts at each corner and goes
        through the following corner, or the end of the outline if
        there is no following corner.  Do it in order of the corners.
     */
     for (cornerSeq = 0; cornerSeq < cornerList.length; ++cornerSeq)
-        addCurveStartingAtCorner(outline, cornerList, cornerSeq, curveListP);
+        addCurveStartingAtCorner(outline, cornerList, cornerSeq, curveListP,
+                                 &curCurveP);
 
     if (!outline.open) {
         /* Come around to the start of the curve list -- add the pixels
            before the first corner to the last curve, and chain the last
            curve to the first one.
         */
-        curve_type const firstCurve =
-            CURVE_LIST_ELT(*curveListP, firstCurveSeq);
-        curve_type const lastCurve  =
-            LAST_CURVE_LIST_ELT(*curveListP);
+        curve * const firstCurveP = CURVE_LIST_ELT(*curveListP, firstCurveSeq);
 
         unsigned int pixelSeq;
 
         for (pixelSeq = 0; pixelSeq <= GET_INDEX(cornerList, 0); ++pixelSeq)
-            append_pixel(lastCurve, O_COORDINATE(outline, pixelSeq));
+            append_pixel(curCurveP, O_COORDINATE(outline, pixelSeq));
 
-        NEXT_CURVE(lastCurve)      = firstCurve;
-        PREVIOUS_CURVE(firstCurve) = lastCurve;
+        NEXT_CURVE(curCurveP)       = firstCurveP;
+        PREVIOUS_CURVE(firstCurveP) = curCurveP;
     }
 }
 
@@ -1146,27 +1163,30 @@ spline_linear_enough(spline_type *             const spline,
 /* Forward declaration for recursion */
 
 static spline_list_type *
-fitCurve(curve_type                const curve,
-         const fitting_opts_type * const fitting_opts,
-         at_exception_type *       const exception);
+fitCurve(curve *                   const curveP,
+         const fitting_opts_type * const fittingOptsP,
+         curve *                   const prevCurveP,
+         curve *                   const nextCurveP,
+         at_exception_type *       const exceptionP);
 
 
 
 static spline_list_type *
-fit_with_line(curve_type const curve) {
+fitWithLine(curve * const curveP) {
 /*----------------------------------------------------------------------------
-  This routine returns the curve fitted to a straight line in a very
-  simple way: make the first and last points on the curve be the
-  endpoints of the line.  This simplicity is justified because we are
-  called only on very short curves.
+  Return a list of splines that fit curve *curveP in a very simple way:
+  a single spline which is a straight line through the first and last
+  points on the curve.
+
+  This simplicity is useful only on a very short curve.
 -----------------------------------------------------------------------------*/
     spline_type line;
 
     LOG("Fitting with straight line:\n");
 
     SPLINE_DEGREE(line) = LINEARTYPE;
-    START_POINT(line) = CONTROL1(line) = CURVE_POINT(curve, 0);
-    END_POINT(line) = CONTROL2(line) = LAST_CURVE_POINT(curve);
+    START_POINT(line)   = CONTROL1(line) = CURVE_POINT(curveP, 0);
+    END_POINT(line)     = CONTROL2(line) = LAST_CURVE_POINT(curveP);
 
     /* Make sure that this line is never changed to a cubic.  */
     SPLINE_LINEARITY(line) = 0;
@@ -1187,11 +1207,11 @@ fit_with_line(curve_type const curve) {
 #define B3(t) CUBE (t)
 
 static spline_type
-fit_one_spline(curve_type          const curve, 
-               at_exception_type * const exception) {
+fit_one_spline(curve *             const curveP, 
+               at_exception_type * const exceptionP) {
 /*----------------------------------------------------------------------------
    Our job here is to find alpha1 (and alpha2), where t1_hat (t2_hat) is
-   the tangent to CURVE at the starting (ending) point, such that:
+   the slope of *curveP at the starting (ending) point, such that:
 
    control1 = alpha1 * t1_hat + starting point
    control2 = alpha2 * t2_hat + ending_point
@@ -1219,22 +1239,22 @@ fit_one_spline(curve_type          const curve,
     float C[2][2] = { { 0.0, 0.0 }, { 0.0, 0.0 } };
     float X[2] = { 0.0, 0.0 };
 
-    t1_hat = *CURVE_START_TANGENT(curve);  /* initial value */
-    t2_hat = *CURVE_END_TANGENT(curve);    /* initial value */
+    t1_hat = CURVE_BEG_SLOPE(curveP);  /* initial value */
+    t2_hat = CURVE_END_SLOPE(curveP);  /* initial value */
 
-    MALLOCARRAY_NOFAIL(A, CURVE_LENGTH(curve) * 2);
+    MALLOCARRAY_NOFAIL(A, CURVE_LENGTH(curveP) * 2);
 
-    START_POINT(spline) = CURVE_POINT(curve, 0);
-    END_POINT(spline)   = LAST_CURVE_POINT(curve);
+    START_POINT(spline) = CURVE_POINT(curveP, 0);
+    END_POINT(spline)   = LAST_CURVE_POINT(curveP);
     start_vector = make_vector(START_POINT(spline));
     end_vector   = make_vector(END_POINT(spline));
 
-    for (i = 0; i < CURVE_LENGTH(curve); ++i) {
-        A[(i << 1) + 0] = Vmult_scalar(t1_hat, B1(CURVE_T(curve, i)));
-        A[(i << 1) + 1] = Vmult_scalar(t2_hat, B2(CURVE_T(curve, i)));
+    for (i = 0; i < CURVE_LENGTH(curveP); ++i) {
+        A[(i << 1) + 0] = Vmult_scalar(t1_hat, B1(CURVE_T(curveP, i)));
+        A[(i << 1) + 1] = Vmult_scalar(t2_hat, B2(CURVE_T(curveP, i)));
     }
 
-    for (i = 0; i < CURVE_LENGTH(curve); ++i) {
+    for (i = 0; i < CURVE_LENGTH(curveP); ++i) {
         vector_type temp, temp0, temp1, temp2, temp3;
         vector_type * Ai = A + (i << 1);
 
@@ -1244,13 +1264,13 @@ fit_one_spline(curve_type          const curve,
         C[1][1] += Vdot(Ai[1], Ai[1]);
 
         /* Now the right-hand side of the equation in the paper.  */
-        temp0 = Vmult_scalar(start_vector, B0(CURVE_T(curve, i)));
-        temp1 = Vmult_scalar(start_vector, B1(CURVE_T(curve, i)));
-        temp2 = Vmult_scalar(end_vector, B2(CURVE_T(curve, i)));
-        temp3 = Vmult_scalar(end_vector, B3(CURVE_T(curve, i)));
+        temp0 = Vmult_scalar(start_vector, B0(CURVE_T(curveP, i)));
+        temp1 = Vmult_scalar(start_vector, B1(CURVE_T(curveP, i)));
+        temp2 = Vmult_scalar(end_vector, B2(CURVE_T(curveP, i)));
+        temp3 = Vmult_scalar(end_vector, B3(CURVE_T(curveP, i)));
 
         temp = make_vector(
-            Vsubtract_point(CURVE_POINT(curve, i),
+            Vsubtract_point(CURVE_POINT(curveP, i),
                             Vadd(temp0, Vadd(temp1, Vadd(temp2, temp3)))));
 
         X[0] += Vdot(temp, Ai[0]);
@@ -1265,7 +1285,7 @@ fit_one_spline(curve_type          const curve,
     C0_C1_det = C[0][0] * C[1][1] - C[1][0] * C[0][1];
     if (C0_C1_det == 0.0) {
         LOG ("zero determinant of C0*C1");
-        at_exception_fatal(exception, "zero determinant of C0*C1");
+        at_exception_fatal(exceptionP, "zero determinant of C0*C1");
         goto cleanup;
     }
 
@@ -1301,235 +1321,422 @@ logSplineFit(spline_type const spline) {
 
 
 static vector_type
-find_half_tangent(curve_type     const c,
-                  bool           const to_start_point,
-                  unsigned int * const n_points,
-                  unsigned int   const tangent_surround) {
+findHalfTangent(curve *        const curveP,
+                bool           const toStartPoint,
+                unsigned int * const nPointsP,
+                unsigned int   const tangentSurround) {
 /*----------------------------------------------------------------------------
-  Find the change in y and change in x for `tangent_surround' (a global)
-  points along CURVE.  Increment N_POINTS by the number of points we
-  actually look at.
+  Find the change in y and change in x for 'tangentSurround'
+  points along *curveP.  Increment *nPointsP by the number of points at
+  which we actually look.
 -----------------------------------------------------------------------------*/
+    int const factor = toStartPoint ? 1 : -1;
+    unsigned int const tangentIndex = toStartPoint ? 0 : curveP->length - 1;
+    float_coord const tangentPoint = CURVE_POINT(curveP, tangentIndex);
+    vector_type const zeroZero = { 0.0, 0.0 };
+    unsigned int const surround =
+        MIN(CURVE_LENGTH(curveP) / 2, tangentSurround);
+
     unsigned int p;
-    int factor = to_start_point ? 1 : -1;
-    unsigned tangent_index = to_start_point ? 0 : c->length - 1;
-    float_coord tangent_point = CURVE_POINT (c, tangent_index);
-    vector_type tangent = { 0.0, 0.0 };
-    unsigned int surround;
-
-    if ((surround = CURVE_LENGTH(c) / 2) > tangent_surround)
-        surround = tangent_surround;
-    
-    for (p = 1; p <= surround; ++p) {
-        int const this_index = p * factor + tangent_index;
-        float_coord this_point;
+    vector_type slope;
+    unsigned int nPoints;
+
+    for (p = 1, nPoints = 0, slope = zeroZero; p <= surround; ++p) {
+        int const thisIndex = p * factor + tangentIndex;
+        float_coord thisPoint;
         
-        if (this_index < 0 || this_index >= (int) c->length)
+        if (thisIndex < 0 || thisIndex >= (int) curveP->length)
             break;
 
-        this_point = CURVE_POINT(c, p * factor + tangent_index);
+        thisPoint = CURVE_POINT(curveP, p * factor + tangentIndex);
 
-        /* Perhaps we should weight the tangent from `this_point' by some
+        /* Perhaps we should weight the tangent from `thisPoint' by some
            factor dependent on the distance from the tangent point.
         */
-        tangent = Vadd (tangent,
-                        Vmult_scalar(Psubtract(this_point, tangent_point),
-                                     (float) factor));
-        ++*n_points;
+        slope = Vadd(slope, Vmult_scalar(Psubtract(thisPoint, tangentPoint),
+                                         (float) factor));
+        ++nPoints;
     }
-
-    return tangent;
+    *nPointsP += nPoints;
+    return slope;
 }
 
 
 
 static void
-find_tangent(curve_type   const curve,
-             bool         const to_start_point,
-             bool         const cross_curve,
-             unsigned int const tangent_surround_arg) {
+findTangent(curve *      const curveP,
+            bool         const toStartPoint,
+            bool         const crossCurve,
+            curve *      const adjacentCurveP,
+            unsigned int const tangentSurroundArg) {
 /*----------------------------------------------------------------------------
-  Find an approximation to the tangent to an endpoint of CURVE (to the
-  first point if TO_START_POINT is true, else the last).  If
-  CROSS_CURVE is true, consider points on the adjacent curve to CURVE.
+  Find an approximation to the slope of *curveP (i.e. slope of tangent
+  line) at an endpoint (the first point if 'toStartPoint' is true,
+  else the last).
+
+  If 'adjacentCurveP' is non-null, consider points on the adjacent
+  curve to *curveP.  The adjacent curve is *adjacentCurveP.  Adjacent
+  means the previous curve in the outline chain for the slope at the
+  start point ('toStartPoint' == true), the next curve otherwise.
+  If *curveP is cyclic, then it is its own adjacent curve.
   
   It is important to compute an accurate approximation, because the
   control points that we eventually decide upon to fit the curve will
-  be placed on the half-lines defined by the tangents and
-  endpoints...and we never recompute the tangent after this.
+  be placed on the half-lines defined by the slopes and endpoints, and
+  we never recompute the tangent after this.
 -----------------------------------------------------------------------------*/
-    vector_type ** curve_tangent;
-    vector_type tangent;
-    unsigned n_points;
-    
-    LOG1("  tangent to %s: ", (to_start_point == true) ? "start" : "end");
+    vector_type * curveSlopeP;
+        /* Pointer to one of the slope members of *curveP: the one for
+           the point at which we're asked to find the tangent (according
+           to 'toStartPoint')
+        */
+    unsigned nPoints;
+
+    LOG2("  tangent to %s of curve %lx: ",
+         toStartPoint ? "start" : "end", (unsigned long)curveP);
 
-    n_points = 0;  /* initial value */
+    nPoints = 0;  /* initial value */
 
-    curve_tangent = to_start_point ?
-        &(CURVE_START_TANGENT(curve)) : &(CURVE_END_TANGENT(curve));
+    curveSlopeP = toStartPoint ?
+        &CURVE_BEG_SLOPE(curveP) : &CURVE_END_SLOPE(curveP);
 
-    if (*curve_tangent == NULL) {
-        unsigned int tangent_surround;
+    if (!curve_slope_is_present(*curveSlopeP)) {
+        vector_type slope;
+        vector_type normalizedSlope;
+        unsigned int tangentSurround;
 
-        tangent_surround = tangent_surround_arg;  /* initial value */
-        MALLOCVAR_NOFAIL(*curve_tangent);
+        tangentSurround = tangentSurroundArg;  /* initial value */
         do {
-            tangent = find_half_tangent(curve, to_start_point, &n_points,
-                                        tangent_surround);
-
-            if (cross_curve || CURVE_CYCLIC(curve)) {
-                curve_type const adjacent_curve = to_start_point ?
-                    PREVIOUS_CURVE(curve) : NEXT_CURVE(curve);
-                vector_type const tangent2 = !to_start_point ?
-                    find_half_tangent(adjacent_curve, true, &n_points,
-                                      tangent_surround) :
-                    find_half_tangent(adjacent_curve, true, &n_points,
-                                      tangent_surround);
-                
+            slope = findHalfTangent(curveP, toStartPoint, &nPoints,
+                                    tangentSurround);
+
+            if (adjacentCurveP) {
+                vector_type const slope2 =
+                    findHalfTangent(adjacentCurveP, !toStartPoint, &nPoints,
+                                    tangentSurround);
+               
                 LOG3("(adjacent curve half tangent (%.3f,%.3f,%.3f)) ",
-                     tangent2.dx, tangent2.dy, tangent2.dz);
-                tangent = Vadd (tangent, tangent2);
+                     slope2.dx, slope2.dy, slope2.dz);
+                slope = Vadd(slope, slope2);
             }
-            --tangent_surround;
-        } while (tangent.dx == 0.0 && tangent.dy == 0.0);
-
-        assert(n_points > 0);
-        **curve_tangent = Vmult_scalar (tangent, (float)(1.0 / n_points));
-        if (CURVE_CYCLIC(curve) && CURVE_START_TANGENT(curve))
-            *CURVE_START_TANGENT(curve) = **curve_tangent;
-        if (CURVE_CYCLIC(curve) && CURVE_END_TANGENT(curve))
-            *CURVE_END_TANGENT(curve) = **curve_tangent;
+            --tangentSurround;
+        } while (slope.dx == 0.0 && slope.dy == 0.0);
+
+        assert(nPoints > 0);
+
+        normalizedSlope = Vmult_scalar(slope, (float)(1.0 / nPoints));
+        if (CURVE_CYCLIC(curveP)) {
+            /* I have no idea what this is */
+            if (curve_slope_is_present(CURVE_BEG_SLOPE(curveP)))
+                CURVE_BEG_SLOPE(curveP) = normalizedSlope;
+            if (curve_slope_is_present(CURVE_END_SLOPE(curveP)))
+                CURVE_END_SLOPE(curveP) = normalizedSlope;
+        }
+        *curveSlopeP = normalizedSlope;
     } else
         LOG("(already computed) ");
     
-    LOG3("(%.3f,%.3f,%.3f).\n", (*curve_tangent)->dx,
-         (*curve_tangent)->dy, (*curve_tangent)->dz);
+    LOG3("(%.3f,%.3f,%.3f).\n",
+         curveSlopeP->dx, curveSlopeP->dy, curveSlopeP->dz);
 }
 
 
 
-static float
-find_error(curve_type          const curve,
-           spline_type         const spline,
-           unsigned int *      const worst_point,
-           at_exception_type * const exception) {
+static void
+findError(curve *             const curveP,
+          spline_type         const spline,
+          float *             const errorP,
+          unsigned int *      const worstPointP,
+          at_exception_type * const exceptionP) {
 /*----------------------------------------------------------------------------
-  When this routine is called, we have computed a spline representation
-  for the digitized curve.  The question is, how good is it?  If the
-  fit is very good indeed, we might have an error of zero on each
-  point, and then WORST_POINT becomes irrelevant.  But normally, we
-  return the error at the worst point, and the index of that point in
-  WORST_POINT.  The error computation itself is the Euclidean distance
-  from the original curve CURVE to the fitted spline SPLINE.
+  Tell how good a fit 'spline' is for *curveP.
+  
+  Return the error (maximum Euclidian distance between a point on
+  *curveP and the corresponding point on 'spline') as *errorP and the
+  sequence number of the point on the curve where the error is
+  greatest as *worstPointP.
+
+  If there are multiple equally bad points, return an arbitrary one of
+  them as *worstPointP.
 -----------------------------------------------------------------------------*/
-    unsigned int this_point;
-    float total_error;
-    float worst_error;
+    unsigned int thisPoint;
+    float totalError;
+    float worstError;
+    unsigned int worstPoint;
 
-    total_error = 0.0;  /* initial value */
-    worst_error = FLT_MIN; /* initial value */
+    assert(CURVE_LENGTH(curveP) > 0);
 
-    *worst_point = CURVE_LENGTH(curve) + 1;   /* A sentinel value.  */
+    totalError = 0.0;  /* initial value */
+    worstError = FLT_MIN; /* initial value */
+    worstPoint = 0;
         
-    for (this_point = 0; this_point < CURVE_LENGTH(curve); ++this_point) {
-        float_coord const curve_point = CURVE_POINT(curve, this_point);
-        float const t = CURVE_T(curve, this_point);
-        float_coord const spline_point = evaluate_spline(spline, t);
-        float const this_error = distance(curve_point, spline_point);
-        if (this_error >= worst_error) {
-            *worst_point = this_point;
-            worst_error = this_error;
+    for (thisPoint = 0; thisPoint < CURVE_LENGTH(curveP); ++thisPoint) {
+        float_coord const curvePoint = CURVE_POINT(curveP, thisPoint);
+        float const t = CURVE_T(curveP, thisPoint);
+        float_coord const splinePoint = evaluate_spline(spline, t);
+        float const thisError = distance(curvePoint, splinePoint);
+        if (thisError >= worstError) {
+            worstPoint = thisPoint;
+            worstError = thisError;
         }
-        total_error += this_error;
+        totalError += thisError;
     }
 
-    if (*worst_point == CURVE_LENGTH(curve) + 1) {
-        /* Didn't have any ``worst point''; the error should be zero.  */
-        if (epsilon_equal(total_error, 0.0))
-            LOG ("  Every point fit perfectly.\n");
-        else {
-            LOG("No worst point found; something is wrong");
-            at_exception_warning(exception,
-                                 "No worst point found; something is wrong");
-        }
-    } else {
-        if (epsilon_equal(total_error, 0.0))
-            LOG ("  Every point fit perfectly.\n");
-        else {
-            LOG5("  Worst error (at (%.3f,%.3f,%.3f), point #%u) was %.3f.\n",
-                 CURVE_POINT(curve, *worst_point).x,
-                 CURVE_POINT(curve, *worst_point).y,
-                 CURVE_POINT(curve, *worst_point).z,
-                 *worst_point, worst_error);
-            LOG1("  Total error was %.3f.\n", total_error);
-            LOG2("  Average error (over %u points) was %.3f.\n",
-                 CURVE_LENGTH(curve), total_error / CURVE_LENGTH(curve));
-        }
+    if (epsilon_equal(totalError, 0.0))
+        LOG("  Every point fits perfectly.\n");
+    else {
+        LOG5("  Worst error (at (%.3f,%.3f,%.3f), point #%u) was %.3f.\n",
+             CURVE_POINT(curveP, worstPoint).x,
+             CURVE_POINT(curveP, worstPoint).y,
+             CURVE_POINT(curveP, worstPoint).z,
+             worstPoint, worstError);
+        LOG1("  Total error was %.3f.\n", totalError);
+        LOG2("  Average error (over %u points) was %.3f.\n",
+                 CURVE_LENGTH(curveP), totalError / CURVE_LENGTH(curveP));
     }
-    return worst_error;
+    assert(worstPoint < CURVE_LENGTH(curveP));
+    *errorP      = worstError;
+    *worstPointP = worstPoint;
 }
 
 
 
 static void
-set_initial_parameter_values(curve_type const curve) {
+setInitialParameterValues(curve * const curveP) {
 /*----------------------------------------------------------------------------
-   Find reasonable values for t for each point on CURVE.  The method is
-   called chord-length parameterization, which is described in Plass &
-   Stone.  The basic idea is just to use the distance from one point to
-   the next as the t value, normalized to produce values that increase
-   from zero for the first point to one for the last point.
+   Fill in the 't' values in *curveP.
+
+   To find reasonable values for t for each point on *curveP, we use
+   the "chord-length parameterization" method, which is described in
+   Plass & Stone.  The basic idea is just to use the distance from one
+   point to the next as the t value, normalized to produce values that
+   increase from zero for the first point to one for the last point.
 -----------------------------------------------------------------------------*/
     unsigned int p;
 
     LOG("\nAssigning initial t values:\n  ");
 
-    CURVE_T(curve, 0) = 0.0;
+    CURVE_T(curveP, 0) = 0.0;
 
-    for (p = 1; p < CURVE_LENGTH (curve); ++p) {
-        float_coord const point = CURVE_POINT(curve, p);
-        float_coord const previous_p = CURVE_POINT(curve, p - 1);
-        float const d = distance (point, previous_p);
-        CURVE_T (curve, p) = CURVE_T (curve, p - 1) + d;
+    for (p = 1; p < CURVE_LENGTH(curveP); ++p) {
+        float_coord const point      = CURVE_POINT(curveP, p);
+        float_coord const previous_p = CURVE_POINT(curveP, p - 1);
+        float const d = distance(point, previous_p);
+        CURVE_T(curveP, p) = CURVE_T(curveP, p - 1) + d;
     }
 
-    assert(LAST_CURVE_T (curve) != 0.0);
+    assert(LAST_CURVE_T(curveP) != 0.0);
+
+    for (p = 1; p < CURVE_LENGTH(curveP); ++p)
+        CURVE_T(curveP, p) = CURVE_T(curveP, p) / LAST_CURVE_T(curveP);
+
+    log_entire_curve(curveP);
+}
+
+
+
+static void
+subdivideCurve(curve *                   const curveP,
+               unsigned int              const subdivisionIndex,
+               const fitting_opts_type * const fittingOptsP,
+               curve **                  const leftCurvePP,
+               curve **                  const rghtCurvePP) {
+/*----------------------------------------------------------------------------
+  Split curve *curveP into two, at 'subdivisionIndex'.  (Actually,
+  leave *curveP alone, but return as *leftCurvePP and *rghtCurvePP
+  two new curves that are the pieces).
+
+  To be precise, the point with sequence number 'subdivisionIndex'
+  becomes the first pixel of the right-hand curve.
+-----------------------------------------------------------------------------*/
+    curve * leftCurveP;
+    curve * rghtCurveP;
 
-    for (p = 1; p < CURVE_LENGTH(curve); ++p)
-        CURVE_T(curve, p) = CURVE_T(curve, p) / LAST_CURVE_T(curve);
+    leftCurveP = new_curve();
+    rghtCurveP = new_curve();
 
-    log_entire_curve(curve);
+    LOG3("  Final point: (%.3f,%.3f), #%u.\n",
+         CURVE_POINT(curveP, subdivisionIndex).x,
+         CURVE_POINT(curveP, subdivisionIndex).y, subdivisionIndex);
+
+    /* The last point of the left-hand curve will also be the first
+       point of the right-hand curve.
+    */
+    assert(subdivisionIndex < CURVE_LENGTH(curveP));
+    CURVE_LENGTH(leftCurveP) = subdivisionIndex + 1;
+    CURVE_LENGTH(rghtCurveP) = CURVE_LENGTH(curveP) - subdivisionIndex;
+
+    MALLOCARRAY_NOFAIL(leftCurveP->point_list, CURVE_LENGTH(leftCurveP));
+    memcpy(leftCurveP->point_list, &curveP->point_list[0],
+           CURVE_LENGTH(leftCurveP) * sizeof(curveP->point_list[0]));
+
+    MALLOCARRAY_NOFAIL(rghtCurveP->point_list, CURVE_LENGTH(rghtCurveP));
+    memcpy(rghtCurveP->point_list, &curveP->point_list[subdivisionIndex],
+           CURVE_LENGTH(rghtCurveP) * sizeof(curveP->point_list[0]));
+
+    /* We want to use the tangents of the curve which we are
+       subdividing for the start tangent for *leftCurveP and the
+       end tangent for rightCurveP.
+    */
+    CURVE_BEG_SLOPE(leftCurveP) = CURVE_BEG_SLOPE(curveP);
+    CURVE_END_SLOPE(rghtCurveP) = CURVE_END_SLOPE(curveP);
+
+    /* We have to set up the two curves before finding the slope at
+       the subdivision point.  The slope at that point must be the
+       same for both curves, or noticeable bumps will occur in the
+       character.  But we want to use information on both sides of the
+       point to compute the slope, hence cross_curve = true.
+    */
+    findTangent(leftCurveP,
+                /* toStartPoint: */   false,
+                /* crossCurve: */     true,
+                /* adjacentCurveP: */ rghtCurveP,
+                fittingOptsP->tangent_surround);
+
+    CURVE_BEG_SLOPE(rghtCurveP) = CURVE_END_SLOPE(leftCurveP);
+
+    *leftCurvePP = leftCurveP;
+    *rghtCurvePP = rghtCurveP;
 }
 
 
 
 static spline_list_type *
-fit_with_least_squares(curve_type                const curve,
-                       const fitting_opts_type * const fitting_opts,
-                       at_exception_type *       const exception) {
+leftRightConcat(const spline_list_type *  const leftSplineListP,
+                const spline_list_type *  const rghtSplineListP,
+                at_exception_type *       const exceptionP) {
+/*----------------------------------------------------------------------------
+   Return a spline list which is the concatenation of the spline lists
+   obtained by splitting a curve in two and fitting each independently.
+   NULL for a spline list pointer means Caller was unable to fit a list
+   of splines to that side of the curve.
+-----------------------------------------------------------------------------*/
+    spline_list_type * retval;
+                
+    retval = new_spline_list();
+
+    if (leftSplineListP == NULL) {
+        LOG("Could not fit spline to left curve.\n");
+        at_exception_warning(exceptionP, "Could not fit left spline list");
+    } else
+        concat_spline_lists(retval, *leftSplineListP);
+    
+    if (rghtSplineListP == NULL) {
+        LOG("Could not fit spline to right curve.\n");
+        at_exception_warning(exceptionP, "Could not fit right spline list");
+    } else
+        concat_spline_lists(retval, *rghtSplineListP);
+
+    return retval;
+}
+
+
+
+static unsigned int
+divisionPoint(curve *      const curveP,
+              unsigned int const worstFitPoint) {
+/*----------------------------------------------------------------------------
+   Return the sequence number of the point at which we should divide
+   curve *curveP for the purpose of doing a separate fit of each side,
+   assuming the point which least matches a single spline is sequence
+   number 'worstFitPoint'.
+
+   We get as close as we can to that while still having at least two
+   points on each side.
+
+   Assume the curve is at least 4 points long.
+
+   The return value is the sequence number of the first point of the
+   second (right-hand) subcurve.
+-----------------------------------------------------------------------------*/
+    assert(CURVE_LENGTH(curveP) >= 4);
+
+    return MAX(2, MIN(worstFitPoint, CURVE_LENGTH(curveP) - 2));
+}
+
+
+
+static spline_list_type *
+divideAndFit(curve *                   const curveP,
+             unsigned int              const subdivisionIndex,
+             const fitting_opts_type * const fittingOptsP,
+             curve *                   const prevCurveP,
+             curve *                   const nextCurveP,
+             at_exception_type *       const exceptionP) {
+/*----------------------------------------------------------------------------
+  Same as fitWithLeastSquares() (i.e. return a list of splines that fit
+  the curve *curveP), except assuming no single spline will fit the
+  entire curve.
+
+  Divide it into two curves at 'subdivisionIndex' and fit each
+  separately to a list of splines.  Return the concatenation of those
+  spline lists.
+
+  Assume 'subdivisionIndex' leaves at least two pixels on each side.
+-----------------------------------------------------------------------------*/
+    spline_list_type * retval;
+    spline_list_type * leftSplineListP;
+    curve * leftCurveP;
+    curve * rghtCurveP;
+
+    assert(subdivisionIndex > 1);
+    assert(subdivisionIndex < CURVE_LENGTH(curveP)-1);
+    subdivideCurve(curveP, subdivisionIndex, fittingOptsP,
+                   &leftCurveP, &rghtCurveP);
+
+    leftSplineListP = fitCurve(leftCurveP, fittingOptsP,
+                               prevCurveP, rghtCurveP, exceptionP);
+
+    if (!at_exception_got_fatal(exceptionP)) {
+        spline_list_type * rghtSplineListP;
+
+        rghtSplineListP = fitCurve(rghtCurveP, fittingOptsP,
+                                   leftCurveP, nextCurveP, exceptionP);
+
+        if (!at_exception_got_fatal(exceptionP)) {
+            if (leftSplineListP == NULL && rghtSplineListP == NULL)
+                retval = NULL;
+            else
+                retval = leftRightConcat(leftSplineListP, rghtSplineListP,
+                                         exceptionP);
+
+            if (rghtSplineListP) {
+                free_spline_list(*rghtSplineListP);
+                free(rghtSplineListP);
+            }
+        }
+        if (leftSplineListP) {
+            free_spline_list(*leftSplineListP);
+            free(leftSplineListP);
+        }
+    }
+
+    free_curve(leftCurveP);
+    free_curve(rghtCurveP);
+
+    return retval;
+}
+
+
+
+static spline_list_type *
+fitWithLeastSquares(curve *                   const curveP,
+                    const fitting_opts_type * const fittingOptsP,
+                    curve *                   const prevCurveP,
+                    curve *                   const nextCurveP,
+                    at_exception_type *       const exceptionP) {
 /*----------------------------------------------------------------------------
   The least squares method is well described in Schneider's thesis.
   Briefly, we try to fit the entire curve with one spline.  If that
   fails, we subdivide the curve. 
 -----------------------------------------------------------------------------*/
-    float error;
-    float best_error;
+    spline_list_type * retval;
     spline_type spline;
-    spline_type best_spline;
-    spline_list_type * spline_list;
-    unsigned int worst_point;
-    float previous_error;
     
-    best_error = FLT_MAX;  /* initial value */
-    previous_error = FLT_MAX;  /* initial value */
-    spline_list = NULL;  /* initial value */
-    worst_point = 0;  /* initial value */
-
-    LOG ("\nFitting with least squares:\n");
+    LOG("\nFitting with least squares:\n");
     
-    /* Phoenix reduces the number of points with a ``linear spline
-       technique''.  But for fitting letterforms, that is
+    /* Phoenix reduces the number of points with a "linear spline
+       technique."  But for fitting letterforms, that is
        inappropriate.  We want all the points we can get.
     */
     
@@ -1539,179 +1746,92 @@ fit_with_least_squares(curve_type                const curve,
     */
 
     LOG("Finding tangents:\n");
-    find_tangent(curve, /* to_start */ true,  /* cross_curve */ false,
-                 fitting_opts->tangent_surround);
-    find_tangent(curve, /* to_start */ false, /* cross_curve */ false,
-                 fitting_opts->tangent_surround);
-
-    set_initial_parameter_values(curve);
-
-    /* Now we loop, subdividing, until CURVE has been fit.  */
-    while (true) {
-        float error;
-
-        spline = fit_one_spline(curve, exception);
-        best_spline = spline;
-        if (at_exception_got_fatal(exception))
-            goto cleanup;
-
-        logSplineFit(spline);
-        
-        if (SPLINE_DEGREE(spline) == LINEARTYPE)
-            break;
-
-        error = find_error(curve, spline, &worst_point, exception);
-        if (error <= previous_error) {
-            best_error  = error;
-            best_spline = spline;
+    findTangent(curveP, /* toStart */ true,  /* crossCurve */ false,
+                CURVE_CYCLIC(curveP) ? curveP : NULL,
+                fittingOptsP->tangent_surround);
+    findTangent(curveP, /* toStart */ false, /* crossCurve */ false,
+                CURVE_CYCLIC(curveP) ? curveP : NULL,
+                fittingOptsP->tangent_surround);
+
+    setInitialParameterValues(curveP);
+
+    if (CURVE_CYCLIC(curveP) && CURVE_LENGTH(curveP) < 4) {
+        unsigned i;
+        for (i = 0; i < CURVE_LENGTH(curveP); ++i) {
+            float_coord const point = CURVE_POINT(curveP, i);
+            fprintf(stderr, "point %u = (%f, %f)\n", i, point.x, point.y);
         }
-        break;
     }
 
-    if (SPLINE_DEGREE(spline) == LINEARTYPE) {
-        spline_list = new_spline_list_with_spline(spline);
-        LOG1("Accepted error of %.3f.\n", error);
-        return spline_list;
-    }
-
-    /* Go back to the best fit.  */
-    spline = best_spline;
-    error = best_error;
+    /* Try a single spline over whole curve */
 
-    if (error < fitting_opts->error_threshold && !CURVE_CYCLIC(curve)) {
-        /* The points were fitted with a spline.  We end up here
-           whenever a fit is accepted.  We have one more job: see if
-           the ``curve'' that was fit should really be a straight
-           line.
-        */
-        if (spline_linear_enough(&spline, curve, fitting_opts)) {
-            SPLINE_DEGREE(spline) = LINEARTYPE;
-            LOG("Changed to line.\n");
-        }
-        spline_list = new_spline_list_with_spline(spline);
-        LOG1("Accepted error of %.3f.\n", error);
-    } else {
-        /* We couldn't fit the curve acceptably, so subdivide.  */
-        unsigned subdivision_index;
-        spline_list_type * left_spline_list;
-        spline_list_type * right_spline_list;
-        curve_type left_curve, right_curve;
-
-        left_curve  = new_curve();
-        right_curve = new_curve();
-
-        /* Insert 'left_curve', then 'right_curve' after 'curve' in the list */
-        NEXT_CURVE(right_curve) = NEXT_CURVE(curve);
-        PREVIOUS_CURVE(right_curve) = left_curve;
-        NEXT_CURVE(left_curve) = right_curve;
-        PREVIOUS_CURVE(left_curve) = curve;
-        NEXT_CURVE(curve) = left_curve;
-
-        LOG1("\nSubdividing (error %.3f):\n", error);
-        LOG3("  Original point: (%.3f,%.3f), #%u.\n",
-             CURVE_POINT (curve, worst_point).x,
-             CURVE_POINT (curve, worst_point).y, worst_point);
-        subdivision_index = worst_point;
-        LOG3 ("  Final point: (%.3f,%.3f), #%u.\n",
-              CURVE_POINT (curve, subdivision_index).x,
-              CURVE_POINT (curve, subdivision_index).y, subdivision_index);
-
-        /* The last point of the left-hand curve will also be the first
-           point of the right-hand curve.  */
-        CURVE_LENGTH(left_curve)  = subdivision_index + 1;
-        CURVE_LENGTH(right_curve) = CURVE_LENGTH(curve) - subdivision_index;
-        left_curve->point_list = curve->point_list;
-        right_curve->point_list = curve->point_list + subdivision_index;
-
-        /* We want to use the tangents of the curve which we are
-           subdividing for the start tangent for left_curve and the
-           end tangent for right_curve.
-        */
-        CURVE_START_TANGENT(left_curve) = CURVE_START_TANGENT(curve);
-        CURVE_END_TANGENT(right_curve)  = CURVE_END_TANGENT(curve);
-
-        /* We have to set up the two curves before finding the tangent at
-           the subdivision point.  The tangent at that point must be the
-           same for both curves, or noticeable bumps will occur in the
-           character.  But we want to use information on both sides of the
-           point to compute the tangent, hence cross_curve = true.
-        */
-        find_tangent(left_curve, /* to_start_point: */ false,
-                     /* cross_curve: */ true, fitting_opts->tangent_surround);
-        CURVE_START_TANGENT(right_curve) = CURVE_END_TANGENT(left_curve);
-
-        /* Now that we've set up the curves, we can fit them.  */
-        left_spline_list = fitCurve(left_curve, fitting_opts, exception);
-        if (at_exception_got_fatal(exception))
-            /* TODO: Memory allocated for left_curve and right_curve
-               will leak.*/
-            goto cleanup;
+    spline = fit_one_spline(curveP, exceptionP);
+    if (!at_exception_got_fatal(exceptionP)) {
+        float error;
+        unsigned int worstPoint;
 
-        right_spline_list = fitCurve(right_curve, fitting_opts, exception);
-        /* TODO: Memory allocated for left_curve and right_curve
-           will leak.*/
-        if (at_exception_got_fatal(exception))
-            goto cleanup;
+        logSplineFit(spline);
         
-        /* Neither of the subdivided curves could be fit, so fail.  */
-        if (left_spline_list == NULL && right_spline_list == NULL)
-            return NULL;
+        findError(curveP, spline, &error, &worstPoint, exceptionP);
+        assert(worstPoint < CURVE_LENGTH(curveP));
 
-        /* Put the two together (or whichever of them exist).  */
-        spline_list = new_spline_list();
-
-        if (left_spline_list == NULL) {
-            LOG1("Could not fit spline to left curve (%lx).\n",
-                 (unsigned long) left_curve);
-            at_exception_warning(exception, "Could not fit left spline list");
-        } else {
-            concat_spline_lists(spline_list, *left_spline_list);
-            free_spline_list(*left_spline_list);
-            free(left_spline_list);
-        }
-        
-        if (right_spline_list == NULL) {
-            LOG1("Could not fit spline to right curve (%lx).\n",
-                 (unsigned long) right_curve);
-            at_exception_warning(exception, "Could not fit right spline list");
+        if (error < fittingOptsP->error_threshold && !CURVE_CYCLIC(curveP)) {
+            /* The points were fitted adequately with a spline.  But
+               see if the "curve" that was fit should really just be a
+               straight line.
+            */
+            if (spline_linear_enough(&spline, curveP, fittingOptsP)) {
+                SPLINE_DEGREE(spline) = LINEARTYPE;
+                LOG("Changed to line.\n");
+            }
+            retval = new_spline_list_with_spline(spline);
+            LOG1("Accepted error of %.3f.\n", error);
         } else {
-            concat_spline_lists(spline_list, *right_spline_list);
-            free_spline_list(*right_spline_list);
-            free(right_spline_list);
+            /* We couldn't fit the curve acceptably with a single spline,
+               so divide into two curves and try to fit each separately.
+            */
+            unsigned int const divIndex = divisionPoint(curveP, worstPoint);
+            LOG1("\nSubdividing at point #%u\n", divIndex);
+            LOG4("  Worst match point: (%.3f,%.3f), #%u.  Error %.3f\n",
+                 CURVE_POINT(curveP, worstPoint).x,
+                 CURVE_POINT(curveP, worstPoint).y, worstPoint, error);
+
+            retval = divideAndFit(curveP, divIndex, fittingOptsP,
+                                  prevCurveP, nextCurveP,
+                                  exceptionP);
         }
-        if (CURVE_END_TANGENT(left_curve))
-            free(CURVE_END_TANGENT(left_curve));
-        free(left_curve);
-        free(right_curve);
-    }
-cleanup:
+    } else
+        retval = NULL; /* quiet compiler warning */
 
-    return spline_list;
+    return retval;
 }
 
 
 
 static spline_list_type *
-fitCurve(curve_type                const curve,
+fitCurve(curve *                   const curveP,
          const fitting_opts_type * const fittingOptsP,
-         at_exception_type *       const exception) {
+         curve *                   const prevCurveP,
+         curve *                   const nextCurveP,
+         at_exception_type *       const exceptionP) {
 /*----------------------------------------------------------------------------
   Transform a set of locations to a list of splines (the fewer the
-  better).  We are guaranteed that CURVE does not contain any corners.
+  better).  We are guaranteed that *curveP does not contain any corners.
   We return NULL if we cannot fit the points at all.
 -----------------------------------------------------------------------------*/
     spline_list_type * fittedSplinesP;
 
-    if (CURVE_LENGTH(curve) < 2) {
-        LOG("Tried to fit curve with less than two points");
-        at_exception_warning(exception, 
+    if (CURVE_LENGTH(curveP) < 2) {
+        LOG("Tried to fit curve with fewer than two points");
+        at_exception_warning(exceptionP, 
                              "Tried to fit curve with less than two points");
         fittedSplinesP = NULL;
-    } else if (CURVE_LENGTH(curve) < 4)
-        fittedSplinesP = fit_with_line(curve);
+    } else if (CURVE_LENGTH(curveP) < 4)
+        fittedSplinesP = fitWithLine(curveP);
     else
         fittedSplinesP =
-            fit_with_least_squares(curve, fittingOptsP, exception);
+            fitWithLeastSquares(curveP, fittingOptsP, prevCurveP, nextCurveP,
+                                exceptionP);
 
     return fittedSplinesP;
 }
@@ -1738,13 +1858,15 @@ fitCurves(curve_list_type           const curveList,
          curveSeq < curveList.length && !at_exception_got_fatal(exceptionP);
          ++curveSeq) {
 
-        curve_type const currentCurve = CURVE_LIST_ELT(curveList, curveSeq);
+        curve * const curveP = CURVE_LIST_ELT(curveList, curveSeq);
 
         spline_list_type * curveSplinesP;
 
-        LOG1("\nFitting curve #%u:\n", curveSeq);
+        LOG2("\nFitting curve #%u (%lx):\n", curveSeq, (unsigned long)curveP);
 
-        curveSplinesP = fitCurve(currentCurve, fittingOptsP, exceptionP);
+        curveSplinesP = fitCurve(curveP, fittingOptsP,
+                                 PREVIOUS_CURVE(curveP),
+                                 NEXT_CURVE(curveP), exceptionP);
         if (!at_exception_got_fatal(exceptionP)) {
             if (curveSplinesP == NULL) {
                 LOG1("Could not fit curve #%u", curveSeq);
@@ -1922,7 +2044,6 @@ fit_outlines_to_splines(pixel_outline_list_type  const pixelOutlineList,
                        exception, notifyProgress, progressData,
                        testCancel, testcancelData, splineListArrayP);
 
-
     free_curve_list_array(&curveListArray, notifyProgress, progressData);
     
     flush_log_output();
diff --git a/converter/other/pamtosvg/pamtosvg.c b/converter/other/pamtosvg/pamtosvg.c
index 84d67948..c6fe2f4c 100644
--- a/converter/other/pamtosvg/pamtosvg.c
+++ b/converter/other/pamtosvg/pamtosvg.c
@@ -211,6 +211,7 @@ parseCommandLine(int argc,
             pm_error("Too many arguments (%u).  The only non-option argument "
                      "is the input file name.", argc-1);
     }
+    free(option_def);
 }
 
 
@@ -384,7 +385,7 @@ main(int argc, char * argv[]) {
     pm_close(ifP);
     if (cmdline.log)
         pm_close(log_file);
-    
+
     at_splines_free(splinesP);
     at_bitmap_free(bitmapP);
 
diff --git a/converter/other/pamtosvg/spline.c b/converter/other/pamtosvg/spline.c
index 5bdf0c0e..61167ec4 100644
--- a/converter/other/pamtosvg/spline.c
+++ b/converter/other/pamtosvg/spline.c
@@ -105,11 +105,13 @@ new_spline_list_with_spline (spline_type spline)
    elements, since they are arrays in automatic storage.  And we don't
    want to free the list if it was empty.  */
 
+
+
 void
-free_spline_list (spline_list_type spline_list)
-{
-  if (SPLINE_LIST_DATA (spline_list) != NULL)
-    free (SPLINE_LIST_DATA (spline_list));
+free_spline_list(spline_list_type spline_list) {
+
+    if (SPLINE_LIST_DATA(spline_list) != NULL)
+        free(SPLINE_LIST_DATA(spline_list));
 }
 
 
diff --git a/doc/HISTORY b/doc/HISTORY
index 44c012dc..7b5f692a 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -6,6 +6,8 @@ CHANGE HISTORY
 
 not yet  BJH  Release 10.42.00
 
+              pamtosvg: fix various bugs: crash, poor tracing, memory leaks.
+
               ppmtoarbtxt: fix array bounds violation with really large
               replacement sequence.