Revision 31929

View differences:

tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/.project
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
3
	<name>libjni-potrace</name>
4
	<comment></comment>
5
	<projects>
6
	</projects>
7
	<buildSpec>
8
		<buildCommand>
9
			<name>org.eclipse.jdt.core.javabuilder</name>
10
			<arguments>
11
			</arguments>
12
		</buildCommand>
13
	</buildSpec>
14
	<natures>
15
		<nature>org.eclipse.jdt.core.javanature</nature>
16
	</natures>
17
</projectDescription>
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/java/org/gvsig/jpotrace/JNIBase.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.jpotrace;
20
/**
21
 * La clase <code>JNIBase</code> sirve para cargar la libreria de jpotrace
22
 * 
23
 * @version 31/07/2008
24
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
25
 */
26
public class JNIBase {
27
	static {
28
		String os = System.getProperty("os.name");
29
		if (os.toLowerCase().startsWith("windows"))
30
			System.loadLibrary("jpotrace001");
31
		else
32
			System.loadLibrary("jpotrace");
33
	}
34
}
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/java/org/gvsig/jpotrace/PotraceException.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.jpotrace;
20
/**
21
 * La clase <code>PotraceException</code> es una forma de expresar que un
22
 * parametro ha sido mal usado en la libreria de jpotrace
23

  
24
 * @version 31/07/2008
25
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
26
 */
27
public class PotraceException extends Exception {
28
	private static final long serialVersionUID = -5761750440639572006L;
29

  
30
	public PotraceException(String msg) {
31
		super(msg);
32
	}
33
}
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/java/org/gvsig/jpotrace/Potrace.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.jpotrace;
20
/**
21
 * La clase <code>Potrace</code> contiene los metodos que comunican la libreria
22
 * nativa con Java
23
 *  
24
 * @version 31/07/2008
25
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
26
 */
27
public class Potrace extends JNIBase {
28
	private static native double[] vectorizeBufferRasterNat(int[] bufferIn, int width, int height, String[] params);
29

  
30
	/**
31
	 * Vectoriza un buffer pasado por parametro y es devuelto en forma de array
32
	 * de doubles. Hay que especificar el ancho y alto del buffer y el buffer ha
33
	 * de ser pasado en el formato que soporta potrace, que es en forma de bits.
34
	 * 
35
	 * El parametro params es un array de Strings como se usaria en el tipico
36
	 * main(char[]) para expresar los parametros de potrace, es una forma de poder
37
	 * aprovechar todos los parametros del comando potrace desde Java. Algunos 
38
	 * no funcionan, como especificar el fichero origen o destino
39
	 * 
40
	 * @param bufferIn
41
	 * @param width
42
	 * @param height
43
	 * @param params
44
	 * @return
45
	 * @throws PotraceException
46
	 */
47
	public static double[] vectorizeBufferRaster(int[] bufferIn, int width, int height, String[] params) throws PotraceException {
48
		if (bufferIn == null)
49
			throw new PotraceException("El parametro Buffer no puede estar vacio");
50

  
51
		if (width <= 0)
52
			throw new PotraceException("El ancho del buffer ha de ser mayor a 0");
53

  
54
		if (height <= 0)
55
			throw new PotraceException("El alto del buffer ha de ser mayor a 0");
56

  
57
		return vectorizeBufferRasterNat(bufferIn, width, height, params);
58
	}
59
}
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/bitops.h
1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

  
5
/* $Id: bitops.h 147 2007-04-09 00:44:09Z selinger $ */
6

  
7
/* bits.h: this file defines some macros for bit manipulations. We
8
   provide a generic implementation, as well as machine- and
9
   compiler-specific fast implementations */
10

  
11
/* lobit: return the position of the rightmost "1" bit of an int, or
12
   32 if none. hibit: return 1 + the position of the leftmost "1" bit
13
   of an int, or 0 if none. Note: these functions work on 32-bit
14
   integers. */
15

  
16
#ifndef BITOPS_H
17
#define BITOPS_H
18

  
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22

  
23
/* ---------------------------------------------------------------------- */
24
/* machine specific macros */
25

  
26
#if defined(HAVE_I386)
27

  
28
static inline unsigned int lobit(unsigned int x) {
29
  unsigned int res;
30
  asm ("bsf	%1,%0\n\t"
31
       "jnz	0f\n\t"
32
       "movl	$32,%0\n"
33
       "0:"
34
       : "=r" (res)
35
       : "r" (x));
36
  return res;
37
}
38

  
39
static inline unsigned int hibit(unsigned int x) {
40
  unsigned int res;					
41

  
42
  asm ("bsr	%1,%0\n\t"
43
       "jnz	0f\n\t"
44
       "movl	$-1,%0\n"
45
       "0:"
46
       : "=r" (res)
47
       : "r" (x));
48
  return res+1;
49
}
50

  
51
/* ---------------------------------------------------------------------- */
52
#else /* generic macros */
53

  
54
static inline unsigned int lobit(unsigned int x) {
55
  unsigned int res = 32;
56
  while (x & 0xffffff) {
57
    x <<= 8;
58
    res -= 8;
59
  }
60
  while (x) {
61
    x <<= 1;
62
    res -= 1;
63
  }
64
  return res;
65
}
66

  
67
static inline unsigned int hibit(unsigned int x) {
68
  unsigned int res = 0;
69
  while (x > 0xff) {
70
    x >>= 8;
71
    res += 8;
72
  }
73
  while (x) {
74
    x >>= 1;
75
    res += 1;
76
  }
77
  return res;
78
}
79

  
80
#endif 
81

  
82
#endif /* BITOPS_H */
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/backend_gimp.h
1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

  
5
/* $Id: backend_gimp.h 147 2007-04-09 00:44:09Z selinger $ */
6

  
7
#ifndef BACKEND_GIMPPATH_H
8
#define BACKEND_GIMPPATH_H
9

  
10
#include "potracelib.h"
11
#include "main.h"
12

  
13
int page_gimp(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
14

  
15
#endif /* BACKEND_GIMPPATH_H */
16

  
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/greymap.h
1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

  
5
/* $Id: greymap.h 147 2007-04-09 00:44:09Z selinger $ */
6

  
7
#ifndef PGM_H
8
#define PGM_H
9

  
10
#include <stdio.h>
11

  
12
/* internal format for greymaps. Note: in this format, rows are
13
   ordered from bottom to top. The pixels in each row are given from
14
   left to right. */
15

  
16
struct greymap_s {
17
  int w;                 /* width, in pixels */
18
  int h;                 /* height, in pixels */
19
  signed short int *map;    /* raw data, w*h values */
20
};
21
typedef struct greymap_s greymap_t;
22

  
23
/* macros for accessing pixel at index (x,y). Note that the origin is
24
   in the *lower* left corner. U* macros omit the bounds check. */
25

  
26
#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(gm)->w])
27
#define gm_safe(gm, x, y) ((int)(x)>=0 && (int)(x)<(gm)->w && (int)(y)>=0 && (int)(y)<(gm)->h)
28
#define gm_bound(x, m) ((x)<0 ? 0 : (x)>=(m) ? (m)-1 : (x))
29
#define GM_UGET(gm, x, y) (*gm_index(gm, x, y))
30
#define GM_UINC(gm, x, y, b) (*gm_index(gm, x, y) += (short int)(b))
31
#define GM_UINV(gm, x, y) (*gm_index(gm, x, y) = 255 - *gm_index(gm, x, y))
32
#define GM_UPUT(gm, x, y, b) (*gm_index(gm, x, y) = (short int)(b))
33
#define GM_GET(gm, x, y) (gm_safe(gm, x, y) ? GM_UGET(gm, x, y) : 0)
34
#define GM_INC(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UINC(gm, x, y, b) : 0)
35
#define GM_INV(gm, x, y) (gm_safe(gm, x, y) ? GM_UINV(gm, x, y) : 0)
36
#define GM_PUT(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UPUT(gm, x, y, b) : 0)
37
#define GM_BGET(gm, x, y) GM_UGET(gm, gm_bound(x, gm->w), gm_bound(y, gm->h))
38

  
39
/* modes for cutting off out-of-range values. The following names
40
   refer to winding numbers. I.e., make a pixel black if winding
41
   number is nonzero, odd, or positive, respectively. We assume that 0
42
   winding number corresponds to white (255). */
43
#define GM_MODE_NONZERO 1
44
#define GM_MODE_ODD 2
45
#define GM_MODE_POSITIVE 3
46
#define GM_MODE_NEGATIVE 4
47

  
48
extern char *gm_read_error;
49

  
50
greymap_t *gm_new(int w, int h);
51
greymap_t *gm_dup(greymap_t *gm);
52
void gm_free(greymap_t *gm);
53
void gm_clear(greymap_t *gm, int b);
54
int gm_read(FILE *f, greymap_t **gmp);
55
int gm_writepgm(FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma);
56
int gm_print(FILE *f, greymap_t *gm);
57

  
58
#endif /* PGM_H */
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/auxiliary.h
1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

  
5
/* This header file collects some general-purpose macros (and static
6
   inline functions) that are used in various places. */
7

  
8
#ifndef AUXILIARY_H
9
#define AUXILIARY_H
10

  
11
#ifdef HAVE_CONFIG_H
12
#include "config.h"
13
#endif
14

  
15
/* ---------------------------------------------------------------------- */
16
/* point arithmetic */
17

  
18
#include "potracelib.h"
19

  
20
struct point_s {
21
  long x;
22
  long y;
23
};
24
typedef struct point_s point_t;
25

  
26
typedef potrace_dpoint_t dpoint_t;
27

  
28
/* convert point_t to dpoint_t */
29
static inline dpoint_t dpoint(point_t p) {
30
  dpoint_t res;
31
  res.x = p.x;
32
  res.y = p.y;
33
  return res;
34
}
35

  
36
/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
37
static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
38
  dpoint_t res;
39

  
40
  res.x = a.x + lambda * (b.x - a.x);
41
  res.y = a.y + lambda * (b.y - a.y);
42
  return res;
43
}
44

  
45
/* ---------------------------------------------------------------------- */
46
/* some useful macros. Note: the "mod" macro works correctly for
47
   negative a. Also note that the test for a>=n, while redundant,
48
   speeds up the mod function by 70% in the average case (significant
49
   since the program spends about 16% of its time here - or 40%
50
   without the test). The "floordiv" macro returns the largest integer
51
   <= a/n, and again this works correctly for negative a, as long as
52
   a,n are integers and n>0. */
53

  
54
/* integer arithmetic */
55

  
56
static inline int mod(int a, int n) {
57
  return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
58
}
59

  
60
static inline int floordiv(int a, int n) {
61
  return a>=0 ? a/n : -1-(-1-a)/n;
62
}
63

  
64
/* Note: the following work for integers and other numeric types. */
65
#undef sign
66
#undef abs
67
#undef min
68
#undef max
69
#undef sq
70
#undef cu
71
#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0)
72
#define abs(a) ((a)>0 ? (a) : -(a))
73
#define min(a,b) ((a)<(b) ? (a) : (b))
74
#define max(a,b) ((a)>(b) ? (a) : (b))
75
#define sq(a) ((a)*(a))
76
#define cu(a) ((a)*(a)*(a))
77

  
78
#endif /* AUXILIARY_H */
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/potrace_raster.c
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
#include <stdio.h>
20
#include <errno.h>
21
#include <math.h>
22
#include "getopt.h"
23

  
24
#include "main.h"
25
#include "platform.h"
26

  
27
#include "backend_pdf.h"
28
#include "backend_eps.h"
29
#include "backend_pgm.h"
30
#include "backend_svg.h"
31
#include "backend_gimp.h"
32
#include "backend_xfig.h"
33
#include "bitmap_io.h"
34
#include "auxiliary.h"
35

  
36
#ifndef M_PI
37
#define M_PI 3.14159265358979323846
38
#endif
39

  
40
#if defined(_MSC_VER)
41
	/* replacement of Unix rint() for Windows */
42
	static int rint (double x)
43
	{
44
	char *buf;
45
	int i,dec,sig;
46

  
47
	buf = _fcvt(x, 0, &dec, &sig);
48
	i = atoi(buf);
49
	if(sig == 1) {
50
	i = i * -1;
51
	}
52
	return(i);
53
	}
54
	#define strcasecmp  stricmp
55
	#define strncasecmp  strnicmp
56
#endif
57

  
58
#define UNDEF ((double)(1e30))   /* a value to represent "undefined" */
59
#define INFTY ((double)(1e30))   /* a value to represent +infinity */
60

  
61
/* backends and their characteristics */
62
struct backend_s {
63
	char *name; /* name of this backend */
64
	char *ext; /* file extension */
65
	int fixed; /* fixed page size backend? */
66
	int pixel; /* pixel-based backend? */
67
	int multi; /* multi-page backend? */
68
	int (*init_f)(FILE *fout); /* initialization function */
69
	int (*page_f)(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
70
	/* per-bitmap function */
71
	int (*term_f)(FILE *fout); /* finalization function */
72
	int opticurve; /* opticurve capable (true Bezier curves?) */
73
};
74
typedef struct backend_s backend_t;
75

  
76
static backend_t backend[] = { {"eps", ".eps", 0, 0, 0, NULL, page_eps, NULL, 1}, {"postscript", ".ps", 1, 0, 1,
77
		init_ps, page_ps, term_ps, 1}, {"ps", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1}, {"pdf", ".pdf", 0, 0, 1,
78
		init_pdf, page_pdf, term_pdf, 1}, {"svg", ".svg", 0, 0, 0, NULL, page_svg, NULL, 1}, {"pgm", ".pgm", 0, 1, 1, NULL,
79
		page_pgm, NULL, 1}, {"gimppath", ".gimppath", 0, 1, 0, NULL, page_gimp, NULL, 1}, {"xfig", ".fig", 1, 0, 0, NULL,
80
		page_xfig, NULL, 0}, {NULL, NULL, 0, 0, 0, NULL, NULL, NULL}, };
81

  
82
struct info_s info;
83

  
84
#define COL0 "\033[G"  /* reset cursor to column 0 */
85

  
86
/* ---------------------------------------------------------------------- */
87
/* callback function for progress bar */
88

  
89
struct simple_progress_s {
90
	char name[22]; /* filename for status bar */
91
	double dnext; /* threshold value for next tick */
92
};
93
typedef struct simple_progress_s simple_progress_t;
94

  
95
static inline double double_of_dim(dim_t d, double def) {
96
	if (d.d) {
97
		return d.x * d.d;
98
	} else {
99
		return d.x * def;
100
	}
101
}
102

  
103
/* ---------------------------------------------------------------------- */
104
/* calculations with bitmap dimensions, positioning etc */
105

  
106
/* consider a rectangle spanned by the vectors (w,0) and (0,h). Rotate
107
 it counterclockwise by angle alpha. Then set the rect_t structure
108
 to the resulting rectangle, setting its bounding box, origin,
109
 x-basis and y-basis. */
110

  
111
static void rotate_dim(double alpha, double w, double h, rect_t *r) {
112
	double s, c, x0, x1, y0, y1;
113

  
114
	s = sin(alpha / 180 * M_PI);
115
	c = cos(alpha / 180 * M_PI);
116

  
117
	/* apply the transformation matrix to the basis vectors */
118
	x0 = c * w;
119
	x1 = s * w;
120
	y0 = -s * h;
121
	y1 = c * h;
122

  
123
	/* determine bounding box and origin relative to bounding box */
124
	r->bb[0] = fabs(x0) + fabs(y0);
125
	r->bb[1] = fabs(x1) + fabs(y1);
126
	r->orig[0] = -min(x0, 0) - min(y0, 0);
127
	r->orig[1] = -min(x1, 0) - min(y1, 0);
128
}
129

  
130
/* determine the dimensions of the output based on command line and
131
 image dimensions */
132
static void calc_dimensions(imginfo_t *imginfo) {
133
	double dim_def;
134
	double maxwidth, maxheight, sc;
135
	rect_t r;
136

  
137
	/* we take care of a special case: if one of the image dimensions is
138
	 0, we change it to 1. Such an image is empty anyway, so there
139
	 will be 0 paths in it. Changing the dimensions avoids division by
140
	 0 error in calculating scaling factors, bounding boxes and
141
	 such. This doesn't quite do the right thing in all cases, but it
142
	 is better than causing overflow errors or "nan" output in
143
	 backends.  Human users don't tend to process images of size 0
144
	 anyway; they might occur in some pipelines. */
145
	if (imginfo->pixwidth == 0) {
146
		imginfo->pixwidth = 1;
147
	}
148
	if (imginfo->pixheight == 0) {
149
		imginfo->pixheight = 1;
150
	}
151

  
152
	/* set the default dimension for width, height, margins */
153
	if (info.backend->pixel) {
154
		dim_def = DIM_PT;
155
	} else {
156
		dim_def = DEFAULT_DIM;
157
	}
158

  
159
	/* apply default dimension to width, height, margins */
160
	imginfo->width = info.width_d.x == UNDEF ? UNDEF : double_of_dim(info.width_d, dim_def);
161
	imginfo->height = info.height_d.x == UNDEF ? UNDEF : double_of_dim(info.height_d, dim_def);
162
	imginfo->lmar = info.lmar_d.x == UNDEF ? UNDEF : double_of_dim(info.lmar_d, dim_def);
163
	imginfo->rmar = info.rmar_d.x == UNDEF ? UNDEF : double_of_dim(info.rmar_d, dim_def);
164
	imginfo->tmar = info.tmar_d.x == UNDEF ? UNDEF : double_of_dim(info.tmar_d, dim_def);
165
	imginfo->bmar = info.bmar_d.x == UNDEF ? UNDEF : double_of_dim(info.bmar_d, dim_def);
166

  
167
	/* determine width and height from desired resolution / scaling
168
	 factor, if given */
169
	if (info.backend->pixel) {
170
		if (imginfo->width == UNDEF && info.sx != UNDEF) {
171
			imginfo->width = imginfo->pixwidth * info.sx;
172
		}
173
		if (imginfo->height == UNDEF && info.sy != UNDEF) {
174
			imginfo->height = imginfo->pixheight * info.sy;
175
		}
176
	} else {
177
		if (imginfo->width == UNDEF && info.rx != UNDEF) {
178
			imginfo->width = imginfo->pixwidth / info.rx * 72;
179
		}
180
		if (imginfo->height == UNDEF && info.ry != UNDEF) {
181
			imginfo->height = imginfo->pixheight / info.ry * 72;
182
		}
183
	}
184

  
185
	/* if one of width/height is specified, determine the other */
186
	if (imginfo->width == UNDEF && imginfo->height != UNDEF) {
187
		imginfo->width = imginfo->height / imginfo->pixheight * imginfo->pixwidth / info.stretch;
188
	} else
189
		if (imginfo->width != UNDEF && imginfo->height == UNDEF) {
190
			imginfo->height = imginfo->width / imginfo->pixwidth * imginfo->pixheight * info.stretch;
191
		}
192

  
193
	/* if width and height are still variable, figure them out */
194
	if (imginfo->width == UNDEF && imginfo->height == UNDEF) {
195

  
196
		if (info.backend->fixed) {
197

  
198
			/* in fixed-size backends, try to squeeze it between margins */
199
			maxwidth = UNDEF;
200
			maxheight = UNDEF;
201

  
202
			if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
203
				maxwidth = info.paperwidth - imginfo->lmar - imginfo->rmar;
204
			}
205
			if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
206
				maxheight = info.paperheight - imginfo->bmar - imginfo->tmar;
207
			}
208
			if (maxwidth == UNDEF && maxheight == UNDEF) {
209
				maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
210
				maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
211
			}
212

  
213
			rotate_dim(info.angle, imginfo->pixwidth, imginfo->pixheight * info.stretch, &r);
214

  
215
			sc = min(maxwidth == UNDEF ? INFTY : maxwidth / r.bb[0], maxheight == UNDEF ? INFTY : maxheight / r.bb[1]);
216
			imginfo->width = imginfo->pixwidth * sc;
217
			imginfo->height = imginfo->pixheight * info.stretch * sc;
218

  
219
		} else
220
			if (info.backend->pixel) {
221

  
222
				/* in pixel-based backends, assume default scaling factor of 1 */
223

  
224
				imginfo->width = imginfo->pixwidth;
225
				imginfo->height = imginfo->pixheight * info.stretch;
226
			} else {
227

  
228
				/* otherwise, choose a default size based on the default paper format */
229

  
230
				maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
231
				maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
232

  
233
				sc = min(maxwidth / imginfo->pixwidth, maxheight / imginfo->pixheight / info.stretch);
234
				imginfo->width = imginfo->pixwidth * sc;
235
				imginfo->height = imginfo->pixheight * info.stretch * sc;
236
			}
237
	}
238

  
239
	/* calculate coordinate system */
240
	rotate_dim(info.angle, imginfo->width, imginfo->height, &imginfo->trans);
241

  
242
	/* adjust margins */
243
	if (info.backend->fixed) {
244
		if (imginfo->lmar == UNDEF && imginfo->rmar == UNDEF) {
245
			imginfo->lmar = (info.paperwidth - imginfo->trans.bb[0]) / 2;
246
		} else
247
			if (imginfo->lmar == UNDEF) {
248
				imginfo->lmar = (info.paperwidth - imginfo->trans.bb[0] - imginfo->rmar);
249
			} else
250
				if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
251
					imginfo->lmar += (info.paperwidth - imginfo->trans.bb[0] - imginfo->lmar - imginfo->rmar) / 2;
252
				}
253
		if (imginfo->bmar == UNDEF && imginfo->tmar == UNDEF) {
254
			imginfo->bmar = (info.paperheight - imginfo->trans.bb[1]) / 2;
255
		} else
256
			if (imginfo->bmar == UNDEF) {
257
				imginfo->bmar = (info.paperheight - imginfo->trans.bb[1] - imginfo->tmar);
258
			} else
259
				if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
260
					imginfo->bmar += (info.paperheight - imginfo->trans.bb[1] - imginfo->bmar - imginfo->tmar) / 2;
261
				}
262
	} else {
263
		if (imginfo->lmar == UNDEF) {
264
			imginfo->lmar = 0;
265
		}
266
		if (imginfo->rmar == UNDEF) {
267
			imginfo->rmar = 0;
268
		}
269
		if (imginfo->bmar == UNDEF) {
270
			imginfo->bmar = 0;
271
		}
272
		if (imginfo->tmar == UNDEF) {
273
			imginfo->tmar = 0;
274
		}
275
	}
276
}
277

  
278
static FILE *my_fopen_read(const char *filename) {
279
	if (filename == NULL || strcmp(filename, "-") == 0) {
280
		return stdin;
281
	}
282
	return fopen(filename, "rb");
283
}
284

  
285
static FILE *my_fopen_write(const char *filename) {
286
	if (filename == NULL || strcmp(filename, "-") == 0) {
287
		return stdout;
288
	}
289
	return fopen(filename, "wb");
290
}
291

  
292
/* close a file, but do nothing is filename is NULL or "-" */
293
static void my_fclose(FILE *f, const char *filename) {
294
	if (filename == NULL || strcmp(filename, "-") == 0) {
295
		return;
296
	}
297
	fclose(f);
298
}
299

  
300
/* print a simple progress bar. This is a callback function that is
301
 potentially called often; thus, it has been optimized for the
302
 typical case, which is when the progress bar does not need updating. */
303
static void simple_progress(double d, void *data) {
304
	simple_progress_t *p = (simple_progress_t *) data;
305
	static char b[] = "========================================";
306
	int tick; /* number of visible tickmarks, 0..40 */
307
	int perc; /* visible percentage, 0..100 */
308

  
309
	/* note: the 0.01 and 0.025 ensure that we always end on 40
310
	 tickmarks and 100%, despite any rounding errors. The 0.995
311
	 ensures that tick always increases when d >= p->dnext. */
312
	if (d >= p->dnext) {
313
		tick = (int) floor(d * 40 + 0.01);
314
		perc = (int) floor(d * 100 + 0.025);
315
		fprintf(stderr, "%-21s |%-40s| %d%% "COL0"", p->name, b + 40 - tick, perc);
316
		p->dnext = (tick + 0.995) / 40.0;
317
	}
318
}
319

  
320
/* Initialize parameters for simple progress bar. The caller passes an
321
 allocated simple_progress_t structure to avoid having to malloc it
322
 here and free it later. */
323
static inline void init_progress(potrace_progress_t *prog, simple_progress_t *p, const char *filename, int count) {
324
	const char *q, *s;
325
	int len;
326

  
327
	/* initialize callback function's data */
328
	p->dnext = 0;
329

  
330
	if (count != 0) {
331
		sprintf(p->name, " (p.%d):", count + 1);
332
	} else {
333
		s = filename;
334
		if ((q = strrchr(s, '/')) != NULL) {
335
			s = q + 1;
336
		}
337
		len = strlen(s);
338
		strncpy(p->name, s, 21);
339
		p->name[20] = 0;
340
		if (len > 20) {
341
			p->name[17] = '.';
342
			p->name[18] = '.';
343
			p->name[19] = '.';
344
		}
345
		strcat(p->name, ":");
346
	}
347

  
348
	/* initialize progress parameters */
349
	prog->callback = &simple_progress;
350
	prog->data = (void *) p;
351
	prog->min = 0.0;
352
	prog->max = 1.0;
353
	prog->epsilon = 0.0;
354

  
355
	/* draw first progress bar */
356
	simple_progress(0.0, prog->data);
357
	return;
358
}
359

  
360
struct pageformat_s {
361
	char *name;
362
	int w, h;
363
};
364
typedef struct pageformat_s pageformat_t;
365

  
366
/* dimensions of the various page formats, in postscript points */
367
static pageformat_t pageformat[] = {
368
	{ "a4",        595,  842 },
369
	{ "a3",        842, 1191 },
370
	{ "a5",        421,  595 },
371
	{ "b5",        516,  729 },
372
	{ "letter",    612,  792 },
373
	{ "legal",     612, 1008 },
374
	{ "tabloid",   792, 1224 },
375
	{ "statement", 396,  612 },
376
	{ "executive", 540,  720 },
377
	{ "folio",     612,  936 },
378
	{ "quarto",    610,  780 },
379
	{ "10x14",     720, 1008 },
380
	{ NULL, 0, 0 },
381
};
382

  
383
struct turnpolicy_s {
384
	char *name;
385
	int n;
386
};
387
typedef struct turnpolicy_s turnpolicy_t;
388

  
389
/* names of turn policies */
390
static turnpolicy_t turnpolicy[] = {
391
	{"black",    POTRACE_TURNPOLICY_BLACK},
392
	{"white",    POTRACE_TURNPOLICY_WHITE},
393
	{"left",     POTRACE_TURNPOLICY_LEFT},
394
	{"right",    POTRACE_TURNPOLICY_RIGHT},
395
	{"minority", POTRACE_TURNPOLICY_MINORITY},
396
	{"majority", POTRACE_TURNPOLICY_MAJORITY},
397
	{"random",   POTRACE_TURNPOLICY_RANDOM},
398
	{NULL, 0},
399
};
400

  
401
static dim_t parse_dimension(char *s, char **endptr) {
402
	char *p;
403
	dim_t res;
404

  
405
	res.x = strtod(s, &p);
406
	res.d = 0;
407
	if (p!=s) {
408
		if (!strncasecmp(p, "in", 2)) {
409
			res.d = DIM_IN;
410
			p += 2;
411
		} else if (!strncasecmp(p, "cm", 2)) {
412
			res.d = DIM_CM;
413
			p += 2;
414
		} else if (!strncasecmp(p, "mm", 2)) {
415
			res.d = DIM_MM;
416
			p += 2;
417
		} else if (!strncasecmp(p, "pt", 2)) {
418
			res.d = DIM_PT;
419
			p += 2;
420
		}
421
	}
422
	if (endptr!=NULL) {
423
		*endptr = p;
424
	}
425
	return res;
426
}
427

  
428
/* parse a pair of dimensions, such as "8.5x11in", "30mmx4cm" */
429
static void parse_dimensions(char *s, char **endptr, dim_t *dxp, dim_t *dyp) {
430
	char *p, *q;
431
	dim_t dx, dy;
432

  
433
	dx = parse_dimension(s, &p);
434
	if (p==s) {
435
		goto fail;
436
	}
437
	if (*p != 'x') {
438
		goto fail;
439
	}
440
	p++;
441
	dy = parse_dimension(p, &q);
442
	if (q==p) {
443
		goto fail;
444
	}
445
	if (dx.d && !dy.d) {
446
		dy.d = dx.d;
447
	} else if (!dx.d && dy.d) {
448
		dx.d = dy.d;
449
	}
450
	*dxp = dx;
451
	*dyp = dy;
452
	if (endptr != NULL) {
453
		*endptr = q;
454
	}
455
	return;
456

  
457
 fail:
458
	dx.x = dx.d = dy.x = dy.d = 0;
459
	*dxp = dx;
460
	*dyp = dy;
461
	if (endptr != NULL) {
462
		*endptr = s;
463
	}
464
	return;
465
}
466

  
467
#define OPT_GROUP     300
468
#define OPT_OPAQUE    301
469
#define OPT_FILLCOLOR 302
470
#define OPT_PROGRESS  303
471

  
472
static struct option longopts[] = {
473
	{"help",          0, 0, 'h'},
474
	{"version",       0, 0, 'v'},
475
	{"license",       0, 0, 'l'},
476
	{"show-defaults", 0, 0, 'V'},
477
	{"progress",      0, 0, OPT_PROGRESS},
478
	{"width",         1, 0, 'W'},
479
	{"height",        1, 0, 'H'},
480
	{"resolution",    1, 0, 'r'},
481
	{"scale",         1, 0, 'x'},
482
	{"stretch",       1, 0, 'S'},
483
	{"margin",        1, 0, 'M'},
484
	{"leftmargin",    1, 0, 'L'},
485
	{"rightmargin",   1, 0, 'R'},
486
	{"topmargin",     1, 0, 'T'},
487
	{"bottommargin",  1, 0, 'B'},
488
	{"rotate",        1, 0, 'A'},
489
	{"pagesize",      1, 0, 'P'},
490
	{"turdsize",      1, 0, 't'},
491
	{"unit",          1, 0, 'u'},
492
	{"cleartext",     0, 0, 'c'},
493
	{"level2",        0, 0, '2'},
494
	{"level3",        0, 0, '3'},
495
	{"eps",           0, 0, 'e'},
496
	{"postscript",    0, 0, 'p'},
497
	{"svg",           0, 0, 's'},
498
	{"pgm",           0, 0, 'g'},
499
	{"backend",       1, 0, 'b'},
500
	{"debug",         1, 0, 'd'},
501
	{"color",         1, 0, 'C'},
502
	{"fillcolor",     1, 0, OPT_FILLCOLOR},
503
	{"turnpolicy",    1, 0, 'z'},
504
	{"gamma",         1, 0, 'G'},
505
	{"longcurve",     0, 0, 'n'},
506
	{"longcoding",    0, 0, 'q'},
507
	{"alphamax",      1, 0, 'a'},
508
	{"opttolerance",  1, 0, 'O'},
509
	{"output",        1, 0, 'o'},
510
	{"blacklevel",    1, 0, 'k'},
511
	{"invert",        0, 0, 'i'},
512
	{"opaque",        0, 0, OPT_OPAQUE},
513
	{"group",         0, 0, OPT_GROUP},
514

  
515
	{0, 0, 0, 0}
516
};
517

  
518
static char *shortopts = "hvlVW:H:r:x:S:M:L:R:T:B:A:P:t:u:c23epsgb:d:C:z:G:nqa:O:o:k:i";
519

  
520
static void dopts(int ac, char *av[]) {
521
	int c;
522
	char *p;
523
	int i, j, r;
524
	dim_t dim, dimx, dimy;
525
	int matches, bestmatch;
526

  
527
	/* defaults */
528
	info.backend = &backend[0];
529

  
530
	info.debug = 0;
531
	info.width_d.x = UNDEF;
532
	info.height_d.x = UNDEF;
533
	info.rx = UNDEF;
534
	info.ry = UNDEF;
535
	info.sx = UNDEF;
536
	info.sy = UNDEF;
537
	info.stretch = 1;
538
	info.lmar_d.x = UNDEF;
539
	info.rmar_d.x = UNDEF;
540
	info.tmar_d.x = UNDEF;
541
	info.bmar_d.x = UNDEF;
542
	info.angle = 0;
543
	info.paperwidth = DEFAULT_PAPERWIDTH;
544
	info.paperheight = DEFAULT_PAPERHEIGHT;
545
	info.unit = 10;
546
	info.compress = 1;
547
	info.pslevel = 2;
548
	info.color = 0x000000;
549
	info.gamma = 2.2;
550
	info.param = potrace_param_default();
551
	if (!info.param) {
552
		fprintf(stderr, ""POTRACE": %s\n", strerror(errno));
553
		exit(1);
554
	}
555
	info.longcoding = 0;
556
	info.outfile = NULL;
557
	info.blacklevel = 0.5;
558
	info.invert = 0;
559
	info.opaque = 0;
560
	info.group = 0;
561
	info.fillcolor = 0xffffff;
562
	info.progress = 0;
563

  
564
	while ((c = getopt_long(ac, av, shortopts, longopts, NULL)) != -1) {
565
		switch (c) {
566
			case OPT_PROGRESS:
567
				info.progress = 1;
568
				break;
569
			case 'W':
570
				info.width_d = parse_dimension(optarg, &p);
571
				if (*p) {
572
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
573
					exit(1);
574
				}
575
				break;
576
			case 'H':
577
				info.height_d = parse_dimension(optarg, &p);
578
				if (*p) {
579
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
580
					exit(1);
581
				}
582
				break;
583
			case 'r':
584
				parse_dimensions(optarg, &p, &dimx, &dimy);
585
				if (*p == 0 && dimx.d == 0 && dimy.d == 0) {
586
					info.rx = dimx.x;
587
					info.ry = dimy.x;
588
					break;
589
				}
590
				dim = parse_dimension(optarg, &p);
591
				if (*p == 0 && dim.d == 0) {
592
					info.rx = info.ry = dim.x;
593
					break;
594
				}
595
				fprintf(stderr, ""POTRACE": invalid resolution -- %s\n", optarg);
596
				exit(1);
597
				break;
598
			case 'x':
599
				parse_dimensions(optarg, &p, &dimx, &dimy);
600
				if (*p == 0 && dimx.d == 0 && dimy.d == 0) {
601
					info.sx = dimx.x;
602
					info.sy = dimy.x;
603
					break;
604
				}
605
				dim = parse_dimension(optarg, &p);
606
				if (*p == 0 && dim.d == 0) {
607
					info.sx = info.sy = dim.x;
608
					break;
609
				}
610
				fprintf(stderr, ""POTRACE": invalid scaling factor -- %s\n", optarg);
611
				exit(1);
612
				break;
613
			case 'S':
614
				info.stretch = atof(optarg);
615
				break;
616
			case 'M':
617
				info.lmar_d = parse_dimension(optarg, &p);
618
				if (*p) {
619
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
620
					exit(1);
621
				}
622
				info.rmar_d = info.tmar_d = info.bmar_d = info.lmar_d;
623
				break;
624
			case 'L':
625
				info.lmar_d = parse_dimension(optarg, &p);
626
				if (*p) {
627
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
628
					exit(1);
629
				}
630
				break;
631
			case 'R':
632
				info.rmar_d = parse_dimension(optarg, &p);
633
				if (*p) {
634
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
635
					exit(1);
636
				}
637
				break;
638
			case 'T':
639
				info.tmar_d = parse_dimension(optarg, &p);
640
				if (*p) {
641
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
642
					exit(1);
643
				}
644
				break;
645
			case 'B':
646
				info.bmar_d = parse_dimension(optarg, &p);
647
				if (*p) {
648
					fprintf(stderr, ""POTRACE": invalid dimension -- %s\n", optarg);
649
					exit(1);
650
				}
651
				break;
652
			case 'A':
653
				info.angle = strtod(optarg, &p);
654
				if (*p) {
655
					fprintf(stderr, ""POTRACE": invalid angle -- %s\n", optarg);
656
					exit(1);
657
				}
658
				break;
659
			case 'P':
660
				matches = 0;
661
				bestmatch = 0;
662
				for (i=0; pageformat[i].name!=NULL; i++) {
663
					if (strcasecmp(pageformat[i].name, optarg)==0) {
664
						matches = 1;
665
						bestmatch = i;
666
						break;
667
					} else if (strncasecmp(pageformat[i].name, optarg, strlen(optarg))==0) {
668
						/* don't allow partial match on "10x14" */
669
						if (optarg[0] != '1') {
670
							matches++;
671
							bestmatch = i;
672
						}
673
					}
674
				}
675
				if (matches == 1) {
676
					info.paperwidth = pageformat[bestmatch].w;
677
					info.paperheight = pageformat[bestmatch].h;
678
					break;
679
				}
680
				parse_dimensions(optarg, &p, &dimx, &dimy);
681
				if (*p == 0) {
682
					info.paperwidth = (int)rint(double_of_dim(dimx, DEFAULT_DIM));
683
					info.paperheight = (int)rint(double_of_dim(dimy, DEFAULT_DIM));
684
					break;
685
				}
686
				if (matches == 0) {
687
					fprintf(stderr, ""POTRACE": unrecognized page format -- %s\n", optarg);
688
				} else {
689
					fprintf(stderr, ""POTRACE": ambiguous page format -- %s\n", optarg);
690
				}
691
				j = fprintf(stderr, "Use one of: ");
692
				for (i=0; pageformat[i].name!=NULL; i++) {
693
					if (j + strlen(pageformat[i].name) > 75) {
694
						fprintf(stderr, "\n");
695
						j = 0;
696
					}
697
					j += fprintf(stderr, "%s, ", pageformat[i].name);
698
				}
699
				fprintf(stderr, "or specify <dim>x<dim>.\n");
700
				exit(1);
701
				break;
702
			case 't':
703
				info.param->turdsize = atoi(optarg);
704
				break;
705
			case 'u':
706
				info.unit = strtod(optarg, &p);
707
				if (*p) {
708
					fprintf(stderr, ""POTRACE": invalid unit -- %s\n", optarg);
709
					exit(1);
710
				}
711
				break;
712
			case 'c':
713
				info.pslevel = 2;
714
				info.compress = 0;
715
				break;
716
			case '2':
717
				info.pslevel = 2;
718
				info.compress = 1;
719
				break;
720
			case '3':
721
#ifdef HAVE_ZLIB
722
				info.pslevel = 3;
723
				info.compress = 1;
724
#else
725
				fprintf(stderr, ""POTRACE": option -3 not supported, using -2 instead.\n");
726
				info.pslevel = 2;
727
				info.compress = 1;
728
#endif
729
				break;
730
			case 'd':
731
				info.debug = atoi(optarg);
732
				break;
733
			case 'z':
734
				matches = 0;
735
				bestmatch = 0;
736
				for (i=0; turnpolicy[i].name!=NULL; i++) {
737
					if (strcasecmp(turnpolicy[i].name, optarg)==0) {
738
						matches = 1;
739
						bestmatch = i;
740
						break;
741
					} else if (strncasecmp(turnpolicy[i].name, optarg, strlen(optarg))==0) {
742
						matches++;
743
						bestmatch = i;
744
					}
745
				}
746
				if (matches == 1) {
747
					info.param->turnpolicy = turnpolicy[bestmatch].n;
748
					break;
749
				}
750
				if (matches == 0) {
751
					fprintf(stderr, ""POTRACE": unrecognized turnpolicy -- %s\n", optarg);
752
				} else {
753
					fprintf(stderr, ""POTRACE": ambiguous turnpolicy -- %s\n", optarg);
754
				}
755
				j = fprintf(stderr, "Use one of: ");
756
				for (i=0; turnpolicy[i].name!=NULL; i++) {
757
					if (j + strlen(turnpolicy[i].name) > 75) {
758
						fprintf(stderr, "\n");
759
						j = 0;
760
					}
761
					j += fprintf(stderr, "%s%s", turnpolicy[i].name, turnpolicy[i+1].name ? ", " : "");
762
				}
763
				fprintf(stderr, ".\n");
764
				exit(1);
765
				break;
766
			case 'G':
767
				info.gamma = atof(optarg);
768
				break;
769
			case 'n':
770
				info.param->opticurve = 0;
771
				break;
772
			case 'q':
773
				info.longcoding = 1;
774
				break;
775
			case 'a':
776
				info.param->alphamax = strtod(optarg, &p);
777

  
778
				if (*p) {
779
					fprintf(stderr, ""POTRACE": invalid alphamax -- %s\n", optarg);
780
					exit(1);
781
				}
782
				break;
783
			case 'O':
784
				info.param->opttolerance = strtod(optarg, &p);
785
				if (*p) {
786
					fprintf(stderr, ""POTRACE": invalid opttolerance -- %s\n", optarg);
787
					exit(1);
788
				}
789
				break;
790
			case 'o':
791
				free(info.outfile);
792
				info.outfile = strdup(optarg);
793
				break;
794
			case 'k':
795
				info.blacklevel = strtod(optarg, &p);
796
				if (*p) {
797
					fprintf(stderr, ""POTRACE": invalid blacklevel -- %s\n", optarg);
798
					exit(1);
799
				}
800
				break;
801
			case 'i':
802
				info.invert = 1;
803
				break;
804
			case OPT_OPAQUE:
805
				info.opaque = 1;
806
				break;
807
			case OPT_GROUP:
808
				info.group = 1;
809
				break;
810
			case '?':
811
				fprintf(stderr, "Try --help for more info\n");
812
				exit(1);
813
				break;
814
			default:
815
				fprintf(stderr, ""POTRACE": Unimplemented option -- %c\n", c);
816
				exit(1);
817
		}
818
	}
819
	info.infiles = &av[optind];
820
	info.infilecount = ac-optind;
821
}
822

  
823
static double* showList(potrace_path_t *plist) {
824
	int i;
825
	int count;
826
	potrace_path_t *p;
827
	int n, *tag;
828
	potrace_dpoint_t (*c)[3];
829
	double *memory;
830

  
831
	p = plist;
832
	count = 0;
833

  
834
	// Comprobamos cuanto va a ocupar la memoria a rellenar
835
	while (p != NULL) {
836
		n = p->curve.n;
837
		tag = p->curve.tag;
838
		c = p->curve.c;
839
		count += 3; // moveTo(x, y)
840
		for (i = 0; i < n; i++) {
841
			switch (tag[i]) {
842
				case POTRACE_CORNER:
843
					count += 3; // lineTo(x, y)
844
					count += 3; // lineTo(x, y)
845
					break;
846
				case POTRACE_CURVETO:
847
					count += 7; // curveTo(x1, y1, x2, y2, x3, y3)
848
					break;
849
			}
850
		}
851
		// at the end of a group of a positive path and its negative children, fill
852
		if (p->next == NULL || p->next->sign == '+')
853
			count++; // closePath()
854
		p = p->next;
855
	}
856
	count++;
857

  
858
	// Creamos la zona de memoria que devolveremos a Java
859
	memory = (double *) malloc(sizeof(double) * count);
860

  
861
	// Rellenamos la memoria con la lista de operaciones a realizar
862
	p = plist;
863
	count = 1;
864
	while (p != NULL) {
865
		n = p->curve.n;
866
		tag = p->curve.tag;
867
		c = p->curve.c;
868

  
869
		// moveTo(x, y);
870
		memory[count++] = 0;
871
		memory[count++] = c[n - 1][2].x;
872
		memory[count++] = c[n - 1][2].y;
873
		for (i = 0; i < n; i++) {
874
			switch (tag[i]) {
875
				case POTRACE_CORNER:
876
					// lineTo(x, y);
877
					memory[count++] = 1;
878
					memory[count++] = c[i][1].x;
879
					memory[count++] = c[i][1].y;
880
					// lineTo(x, y);
881
					memory[count++] = 1;
882
					memory[count++] = c[i][2].x;
883
					memory[count++] = c[i][2].y;
884
					break;
885
				case POTRACE_CURVETO:
886
					// curveTo(x1, y1, x2, y2, x3, y3);
887
					memory[count++] = 2;
888
					memory[count++] = c[i][0].x;
889
					memory[count++] = c[i][0].y;
890
					memory[count++] = c[i][1].x;
891
					memory[count++] = c[i][1].y;
892
					memory[count++] = c[i][2].x;
893
					memory[count++] = c[i][2].y;
894
					break;
895
			}
896
		}
897
		if (p->next == NULL || p->next->sign == '+')
898
			memory[count++] = 3;
899
		p = p->next;
900
	}
901
	memory[0] = count;
902
	return memory;
903
}
904

  
905
static double* process_buffer(const long *inbuffer, int width, int height) {
906
	int r;
907
	double *memory;
908
	potrace_bitmap_t *bm = NULL;
909
	imginfo_t imginfo;
910
	int eof_flag = 0; /* to indicate premature eof */
911
	potrace_state_t *st;
912
	simple_progress_t progress_data;
913
	int dy;
914

  
915
	bm = (potrace_bitmap_t *) malloc (sizeof(potrace_bitmap_t));
916
	bm->w = width;
917
	bm->h = height;
918
	dy = (width + 32 - 1) / 32;
919
	bm->dy = dy;
920

  
921
	bm->map = (potrace_word *) inbuffer;
922

  
923
	/* prepare progress bar, if requested */
924
	info.param->progress.callback = NULL;
925

  
926
	// Invertir colores, el negro es blanco y el blanco es negro
927
	if (info.invert)
928
		bm_invert(bm);
929

  
930
	/* process the image */
931

  
932
	st = potrace_trace(info.param, bm);
933
	if (!st || st->status != POTRACE_STATUS_OK) {
934
		fprintf(stderr, ""POTRACE": %s\n", strerror(errno));
935
		exit(2);
936
	}
937
	/* calculate image dimensions */
938
	imginfo.pixwidth = bm->w;
939
	imginfo.pixheight = bm->h;
940
	calc_dimensions(&imginfo);
941
	
942
	// rgaitan: We cannot use here bm_free (becouse it
943
	// frees also the bm->map (that is a inbuffer, that in this
944
	// case comes from java so, FAIL!.
945
	//bm_free(bm);
946

  
947
	memory = showList(st->plist);
948

  
949
	potrace_state_free(st);
950

  
951
	if (info.progress) {
952
		fprintf(stderr, "\n");
953
	}
954

  
955
	return memory;
956
}
957

  
958
double* vectorizarBuffer(const long *bufferIn, int width, int height, int argc, char *argv[]) {
959
	/* platform-specific initializations, e.g., set file i/o to binary */
960
	platform_init();
961

  
962
	// Reiniciar el contador externo de los parametros
963
	optind = 1;
964

  
965
	/* process options */
966
	dopts(argc, argv);
967

  
968
	return process_buffer(bufferIn, width, height);
969
}
tags/gvSIG_3D_Animation_1_9_SNAPSHOT_build_11/libraries/libjni-potrace/src/main/native/jpotrace/render.c
1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

  
5
/* $Id: render.c 147 2007-04-09 00:44:09Z selinger $ */
6

  
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <math.h>
10
#include <string.h>
11

  
12
#include "render.h"
13
#include "greymap.h"
14
#include "auxiliary.h"
15

  
16
/* ---------------------------------------------------------------------- */
17
/* routines for anti-aliased rendering of curves */
18

  
19
/* we use the following method. Given a point (x,y) (with real-valued
20
   coordinates) in the plane, let (xi,yi) be the integer part of the
21
   coordinates, i.e., xi=floor(x), yi=floor(y). Define a path from
22
   (x,y) to infinity as follows: path(x,y) =
23
   (x,y)--(xi+1,y)--(xi+1,yi)--(+infty,yi).  Now as the point (x,y)
24
   moves smoothly across the plane, the path path(x,y) sweeps
25
   (non-smoothly) across a certain area. We proportionately blacken
26
   the area as the path moves "downward", and we whiten the area as
27
   the path moves "upward". This way, after the point has traversed a
28
   closed curve, the interior of the curve has been darkened
29
   (counterclockwise movement) or lightened (clockwise movement). (The
30
   "grey shift" is actually proportional to the winding number). By
31
   choosing the above path with mostly integer coordinates, we achieve
32
   that only pixels close to (x,y) receive grey values and are subject
33
   to round-off errors. The grey value of pixels far away from (x,y)
34
   is always in "integer" (where 0=black, 1=white).  As a special
35
   trick, we keep an accumulator rm->a1, which holds a double value to
36
   be added to the grey value to be added to the current pixel
37
   (xi,yi).  Only when changing "current" pixels, we convert this
38
   double value to an integer. This way we avoid round-off errors at
39
   the meeting points of line segments. Another speedup measure is
40
   that we sometimes use the rm->incrow_buf array to postpone
41
   incrementing or decrementing an entire row. If incrow_buf[y]=x+1!=0,
42
   then all the pixels (x,y),(x+1,y),(x+2,y),... are scheduled to be
43
   incremented/decremented (which one is the case will be clear from 
44
   context). This keeps the greymap operations reasonably local. */
45

  
46
/* allocate a new rendering state */
47
render_t *render_new(greymap_t *gm) {
48
  render_t *rm;
49

  
50
  rm = (render_t *) malloc(sizeof(render_t));
51
  if (!rm) {
52
    return NULL;
53
  }
54
  memset(rm, 0, sizeof(render_t));
55
  rm->gm = gm;
56
  rm->incrow_buf = (int *) malloc(gm->h * sizeof(int));
57
  if (!rm->incrow_buf) {
58
    free(rm);
59
    return NULL;
60
  }
61
  memset(rm->incrow_buf, 0, gm->h * sizeof(int));
62
  return rm;
63
}
64

  
65
/* free a given rendering state. Note: this does not free the
66
   underlying greymap. */
67
void render_free(render_t *rm) {
68
  free(rm->incrow_buf);
69
  free(rm);
70
}
71

  
72
/* close path */
73
void render_close(render_t *rm) {
74
  if (rm->x0 != rm->x1 || rm->y0 != rm->y1) {
75
    render_lineto(rm, rm->x0, rm->y0);
76
  }
77
  GM_INC(rm->gm, rm->x0i, rm->y0i, (rm->a0+rm->a1)*255);
78

  
79
  /* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
80
  
81
  /* the persistent state is now undefined */
82
}
83

  
84
/* move point */
85
void render_moveto(render_t *rm, double x, double y) {
86
  /* close the previous path */
87
  render_close(rm);
88

  
89
  rm->x0 = rm->x1 = x;
90
  rm->y0 = rm->y1 = y;
91
  rm->x0i = (int)floor(rm->x0);
92
  rm->x1i = (int)floor(rm->x1);
93
  rm->y0i = (int)floor(rm->y0);
94
  rm->y1i = (int)floor(rm->y1);
95
  rm->a0 = rm->a1 = 0;
96
}
97

  
98
/* add b to pixels (x,y) and all pixels to the right of it. However,
99
   use rm->incrow_buf as a buffer to economize on multiple calls */
100
static void incrow(render_t *rm, int x, int y, int b) {
101
  int i, x0;
102

  
103
  if (y < 0 || y >= rm->gm->h) {
104
    return;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff