2005-01-19 Libor Pechacek

This patch teaches Potrace to work with open paths (common pattern in contour
line tracing) and exposes its internal API to CoVe.

diff -ruN potrace-1.6-orig/config.h potrace/config.h
--- potrace-1.6-orig/config.h	1970-01-01 01:00:00.000000000 +0100
+++ potrace/config.h	2017-01-27 14:20:08.034239529 +0100
@@ -0,0 +1,80 @@
+/* config.h.  Generated by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* does the C compiler have gcc bug 12243? */
+#define HAVE_GCC_LOOP_BUG 
+
+/* can we use Intel 386 optimizations? */
+#define HAVE_I386 
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* do we have the zlib library? */
+#define HAVE_ZLIB 
+
+/* Name of the mkbitmap binary */
+#define MKBITMAP "mkbitmap"
+
+/* Name of package */
+#define PACKAGE "potrace"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "selinger at users.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "potrace"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "potrace 1.6"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "potrace"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.6"
+
+/* Name of the potrace binary */
+#define POTRACE "potrace"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* do we use a4 papersize by default? */
+/* #undef USE_A4 */
+
+/* do we use metric units by default? */
+/* #undef USE_METRIC */
+
+/* Version number of package */
+#define VERSION "1.6"
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
diff -ruN potrace-1.6-orig/curve.h potrace/curve.h
--- potrace-1.6-orig/curve.h	2005-02-20 23:55:31.000000000 +0100
+++ potrace/curve.h	2017-01-27 14:20:08.034239529 +0100
@@ -16,6 +16,7 @@
 */
 
 struct privcurve_s {
+  int closed;
   int n;            /* number of segments */
   int *tag;         /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
   dpoint_t (*c)[3]; /* c[n][i]: control points. 
@@ -42,6 +43,7 @@
    fields of this data structure, but debugging backends may read
    other fields. */
 struct potrace_privpath_s {
+  int closed;
   int len;
   point_t *pt;     /* pt[len]: path as extracted from bitmap */
   int *lon;        /* lon[len]: (i,lon[i]) = longest straight line from i */
diff -ruN potrace-1.6-orig/potracelib.c potrace/potracelib.c
--- potrace-1.6-orig/potracelib.c	2005-02-27 02:47:04.000000000 +0100
+++ potrace/potracelib.c	2017-02-01 09:16:32.629755860 +0100
@@ -7,7 +7,6 @@
 
 #include "potracelib.h"
 #include "curve.h"
-#include "decompose.h"
 #include "trace.h"
 #include "progress.h"
 
@@ -42,71 +41,3 @@
   memcpy(p, &param_default, sizeof(potrace_param_t));
   return p;
 }
-
-/* On success, returns a potrace state st with st->status ==
-   POTRACE_STATUS_OK. On failure, returns NULL if no potrace state
-   could be created (with errno set), or returns an incomplete potrace
-   state (with st->status == POTRACE_STATUS_INCOMPLETE). Complete or
-   incomplete potrace state can be freed with potrace_state_free(). */
-potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) {
-  int r;
-  path_t *plist = NULL;
-  potrace_state_t *st;
-  progress_t prog;
-  progress_t subprog;
-  
-  /* prepare private progress bar state */
-  prog.callback = param->progress.callback;
-  prog.data = param->progress.data;
-  prog.min = param->progress.min;
-  prog.max = param->progress.max;
-  prog.epsilon = param->progress.epsilon;
-  prog.d_prev = param->progress.min;
-
-  /* allocate state object */
-  st = (potrace_state_t *)malloc(sizeof(potrace_state_t *));
-  if (!st) {
-    return NULL;
-  }
-
-  progress_subrange_start(0.0, 0.1, &prog, &subprog);
-
-  /* process the image */
-  r = bm_to_pathlist(bm, &plist, param, &subprog);
-  if (r) {
-    free(st);
-    return NULL;
-  }
-
-  st->status = POTRACE_STATUS_OK;
-  st->plist = plist;
-
-  progress_subrange_end(&prog, &subprog);
-
-  progress_subrange_start(0.1, 1.0, &prog, &subprog);
-
-  /* partial success. */
-  r = process_path(plist, param, &subprog);
-  if (r) {
-    st->status = POTRACE_STATUS_INCOMPLETE;
-  }
-
-  progress_subrange_end(&prog, &subprog);
-
-  return st;
-}
-
-/* free a potrace state, without disturbing errno. */
-void potrace_state_free(potrace_state_t *st) {
-  pathlist_free(st->plist);
-  free(st);
-}
-
-/* free a parameter list, without disturbing errno. */
-void potrace_param_free(potrace_param_t *p) {
-  free(p);
-}
-
-char *potrace_version() {
-  return "potracelib "VERSION"";
-}
diff -ruN potrace-1.6-orig/potrace.pro potrace/potrace.pro
--- potrace-1.6-orig/potrace.pro	1970-01-01 01:00:00.000000000 +0100
+++ potrace/potrace.pro	2017-01-27 14:20:08.034239529 +0100
@@ -0,0 +1,27 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2016-12-29T20:11:49
+#
+#-------------------------------------------------
+
+QT       -= core gui
+
+TARGET = potrace
+TEMPLATE = lib
+CONFIG += staticlib
+
+DEFINES += POTRACE_LIBRARY
+
+SOURCES += \
+    curve.c \
+    potracelib.c \
+    trace.c
+
+HEADERS += \
+    auxiliary.h \
+    config.h \
+    curve.h \
+    lists.h \
+    potracelib.h \
+    progress.h \
+    trace.h
diff -ruN potrace-1.6-orig/trace.c potrace/trace.c
--- potrace-1.6-orig/trace.c	2005-02-27 02:54:08.000000000 +0100
+++ potrace/trace.c	2017-02-01 09:17:17.881731826 +0100
@@ -270,7 +270,7 @@
 /* Preparation: fill in the sum* fields of a path (used for later
    rapid summing). Return 0 on success, 1 with errno set on
    failure. */
-static int calc_sums(privpath_t *pp) {
+int calc_sums(privpath_t *pp) {
   int i, x, y;
   int n = pp->len;
 
@@ -327,7 +327,7 @@
    substantial. */
 
 /* returns 0 on success, 1 on error with errno set */
-static int calc_lon(privpath_t *pp) {
+int calc_lon(privpath_t *pp) {
   point_t *pt = pp->pt;
   int n = pp->len;
   int i, j, k, k1;
@@ -350,20 +350,29 @@
      algorithm). But even if this were not so, there is no harm, as
      in practice, correctness does not depend on the word "furthest"
      above.  */
-  k = 0;
+  k = pp->closed?0:(n-1);
   for (i=n-1; i>=0; i--) {
     if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
       k = i+1;  /* necessarily i<n-1 in this case */
     }
     nc[i] = k;
   }
+#ifdef DEBUG
+  printf("nc[%d] = ", n);
+  for (i=0; i<n; i++)
+    printf("%d, ", nc[i]);
+  printf("\n");
+#endif /* DEBUG */
 
   SAFE_MALLOC(pp->lon, n, int);
 
   /* determine pivot points: for each i, let pivk[i] be the furthest k
      such that all j with i<j<k lie on a line connecting i,k. */
   
-  for (i=n-1; i>=0; i--) {
+  if (!pp->closed)
+    pivk[n-1] = n-1;
+
+  for (i=pp->closed?(n-1):(n-2); i>=0; i--) {
     ct[0] = ct[1] = ct[2] = ct[3] = 0;
 
     /* keep track of "directions" that have occurred */
@@ -414,8 +423,11 @@
       }	
       k1 = k;
       k = nc[k1];
-      if (!cyclic(k,i,k1)) {
+      if (pp->closed && !cyclic(k,i,k1))
 	break;
+      if (!pp->closed && k == k1) {
+	pivk[i] = k1;
+	goto foundk;
       }
     }
   constraint_viol:
@@ -459,10 +471,19 @@
     pp->lon[i]=j;
   }
 
-  for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
-    pp->lon[i] = j;
+  if (pp->closed) {
+    for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
+      pp->lon[i] = j;
+    }
   }
 
+#ifdef DEBUG
+  printf("lon[%d] = ", n);
+  for (i=0; i<n; i++)
+    printf("%d, ", pp->lon[i]);
+  printf("\n");
+#endif /* DEBUG */
+
   free(pivk);
   free(nc);
   return 0;
@@ -522,7 +543,7 @@
 /* find the optimal polygon. Fill in the m and po components. Return 1
    on failure with errno set, else 0. Non-cyclic version: assumes i=0
    is in the polygon. Fixme: ### implement cyclic version. */
-static int bestpolygon(privpath_t *pp)
+int bestpolygon(privpath_t *pp)
 {
   int i, j, m, k;     
   int n = pp->len;
@@ -544,16 +565,32 @@
   SAFE_MALLOC(seg1, n+1, int);
 
   /* calculate clipped paths */
-  for (i=0; i<n; i++) {
-    c = mod(pp->lon[mod(i-1,n)]-1,n);
-    if (c == i) {
-      c = mod(i+1,n);
+  if(pp->closed) {
+    for (i=0; i<n; i++) {
+      c = mod(pp->lon[mod(i-1,n)]-1,n);
+      if (c == i) {
+	c = mod(i+1,n);
+      }
+      if (c < i) {
+	clip0[i] = n;
+      } else {
+	clip0[i] = c;
+      }
     }
-    if (c < i) {
-      clip0[i] = n;
-    } else {
-      clip0[i] = c;
+  } else {
+    for (i=1; i<n-1; i++) {
+      c = pp->lon[i-1]-1;
+      if (c == i) {
+	c = i+1;
+      }
+      if (c < i) {
+	clip0[i] = n-1;
+      } else {
+	clip0[i] = c;
+      }
     }
+    clip0[0] = clip0[1]-1;
+    clip0[n-1] = n-1;
   }
 
   /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
@@ -568,15 +605,15 @@
 
   /* calculate seg0[j] = longest path from 0 with j segments */
   i = 0;
-  for (j=0; i<n; j++) {
+  for (j=0; i<(pp->closed?n:(n-1)); j++) {
     seg0[j] = i;
     i = clip0[i];
   }
-  seg0[j] = n;
+  seg0[j] = (pp->closed?n:(n-1));
   m = j;
 
   /* calculate seg1[j] = longest path to n with m-j segments */
-  i = n;
+  i = (pp->closed?n:(n-1));
   for (j=m; j>0; j--) {
     seg1[j] = i;
     i = clip1[i];
@@ -606,10 +643,12 @@
   SAFE_MALLOC(pp->po, m, int);
 
   /* read off shortest path */
-  for (i=n, j=m-1; i>0; j--) {
+  for (i=(pp->closed?n:(n-1)), j=m-1; i>0; j--) {
     i = prev[i];
     pp->po[j] = i;
   }
+  if(!pp->closed)
+    pp->po[m-1] = n-1;
 
   free(pen);
   free(prev);
@@ -637,7 +676,7 @@
    if it lies outside. Return 1 with errno set on error; 0 on
    success. */
 
-static int adjust_vertices(privpath_t *pp) {
+int adjust_vertices(privpath_t *pp) {
   int m = pp->m;
   int *po = pp->po;
   int n = pp->len;
@@ -698,7 +737,7 @@
      Instead of using the actual intersection, we find the point
      within a given unit square which minimizes the square distance to
      the two lines. */
-  for (i=0; i<m; i++) {
+  for (i=(pp->closed?0:1); i<(pp->closed?m:(m-1)); i++) {
     quadform_t Q;
     dpoint_t w;
     double dx, dy;
@@ -821,6 +860,14 @@
     continue;
   }
 
+  if(!pp->closed) {
+    pp->curve.vertex[0].x = pp->pt[po[0]].x;
+    pp->curve.vertex[0].y = pp->pt[po[0]].y;
+    pp->curve.vertex[m-1].x = pp->pt[po[m-1]].x;
+    pp->curve.vertex[m-1].y = pp->pt[po[m-1]].y;
+  }
+  pp->curve.closed = pp->closed;
+
   free(ctr);
   free(dir);
   free(q);
@@ -837,7 +884,7 @@
 /* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
 
 /* Always succeeds and returns 0 */
-static int smooth(privcurve_t *curve, int sign, double alphamax) {
+int smooth(privcurve_t *curve, int sign, double alphamax) {
   int m = curve->n;
 
   int i, j, k;
@@ -855,7 +902,7 @@
   }
 
   /* examine each vertex and find its best fit */
-  for (i=0; i<m; i++) {
+  for (i=0; i<(curve->closed?m:(m-2)); i++) {
     j = mod(i+1, m);
     k = mod(i+2, m);
     p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
@@ -892,6 +939,15 @@
     curve->beta[j] = 0.5;
   }
 
+  if(!curve->closed) {
+    curve->tag[0] = POTRACE_CORNER;
+    curve->c[0][1].x = 0; curve->c[0][1].y = 0;
+    curve->c[0][2] = curve->vertex[0];
+    curve->tag[m-1] = POTRACE_CORNER;
+    curve->c[m-1][1] = curve->vertex[m-1];
+    curve->c[m-1][2].x = 0; curve->c[m-1][2].y = 0;
+  }
+
   return 0;
 }
 
@@ -1051,7 +1107,7 @@
 /* optimize the path p, replacing sequences of Bezier segments by a
    single segment when possible. Return 0 on success, 1 with errno set
    on failure. */
-static int opticurve(privpath_t *pp, double opttolerance) {
+int opticurve(privpath_t *pp, double opttolerance) {
   int m = pp->curve.n;
   int *pt = NULL;     /* pt[m+1] */
   double *pen = NULL; /* pen[m+1] */
diff -ruN potrace-1.6-orig/trace.h potrace/trace.h
--- potrace-1.6-orig/trace.h	2005-02-22 22:31:23.000000000 +0100
+++ potrace/trace.h	2017-02-01 09:17:28.089726427 +0100
@@ -11,5 +11,11 @@
 #include "progress.h"
 
 int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress);
+int calc_sums(privpath_t *pp);
+int calc_lon(privpath_t *pp);
+int bestpolygon(privpath_t *pp);
+int adjust_vertices(privpath_t *pp);
+int smooth(privcurve_t *curve, int sign, double alphamax);
+int opticurve(privpath_t *pp, double opttolerance);
 
 #endif /* TRACE_H */
