Statistics
| Revision:

gvsig-raster / libjni-potrace / trunk / libjni-potrace / resources / potrace-1.8 / src / potrace_raster.c @ 1780

History | View | Annotate | Download (26.3 KB)

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
#define UNDEF ((double)(1e30))   /* a value to represent "undefined" */
41
#define INFTY ((double)(1e30))   /* a value to represent +infinity */
42

    
43
/* backends and their characteristics */
44
struct backend_s {
45
        char *name; /* name of this backend */
46
        char *ext; /* file extension */
47
        int fixed; /* fixed page size backend? */
48
        int pixel; /* pixel-based backend? */
49
        int multi; /* multi-page backend? */
50
        int (*init_f)(FILE *fout); /* initialization function */
51
        int (*page_f)(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
52
        /* per-bitmap function */
53
        int (*term_f)(FILE *fout); /* finalization function */
54
        int opticurve; /* opticurve capable (true Bezier curves?) */
55
};
56
typedef struct backend_s backend_t;
57

    
58
static backend_t backend[] = { {"eps", ".eps", 0, 0, 0, NULL, page_eps, NULL, 1}, {"postscript", ".ps", 1, 0, 1,
59
                init_ps, page_ps, term_ps, 1}, {"ps", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1}, {"pdf", ".pdf", 0, 0, 1,
60
                init_pdf, page_pdf, term_pdf, 1}, {"svg", ".svg", 0, 0, 0, NULL, page_svg, NULL, 1}, {"pgm", ".pgm", 0, 1, 1, NULL,
61
                page_pgm, NULL, 1}, {"gimppath", ".gimppath", 0, 1, 0, NULL, page_gimp, NULL, 1}, {"xfig", ".fig", 1, 0, 0, NULL,
62
                page_xfig, NULL, 0}, {NULL, NULL, 0, 0, 0, NULL, NULL, NULL}, };
63

    
64
struct info_s info;
65

    
66
#define COL0 "\033[G"  /* reset cursor to column 0 */
67

    
68
/* ---------------------------------------------------------------------- */
69
/* callback function for progress bar */
70

    
71
struct simple_progress_s {
72
        char name[22]; /* filename for status bar */
73
        double dnext; /* threshold value for next tick */
74
};
75
typedef struct simple_progress_s simple_progress_t;
76

    
77
static inline double double_of_dim(dim_t d, double def) {
78
        if (d.d) {
79
                return d.x * d.d;
80
        } else {
81
                return d.x * def;
82
        }
83
}
84

    
85
/* ---------------------------------------------------------------------- */
86
/* calculations with bitmap dimensions, positioning etc */
87

    
88
/* consider a rectangle spanned by the vectors (w,0) and (0,h). Rotate
89
 it counterclockwise by angle alpha. Then set the rect_t structure
90
 to the resulting rectangle, setting its bounding box, origin,
91
 x-basis and y-basis. */
92

    
93
static void rotate_dim(double alpha, double w, double h, rect_t *r) {
94
        double s, c, x0, x1, y0, y1;
95

    
96
        s = sin(alpha / 180 * M_PI);
97
        c = cos(alpha / 180 * M_PI);
98

    
99
        /* apply the transformation matrix to the basis vectors */
100
        x0 = c * w;
101
        x1 = s * w;
102
        y0 = -s * h;
103
        y1 = c * h;
104

    
105
        /* determine bounding box and origin relative to bounding box */
106
        r->bb[0] = fabs(x0) + fabs(y0);
107
        r->bb[1] = fabs(x1) + fabs(y1);
108
        r->orig[0] = -min(x0, 0) - min(y0, 0);
109
        r->orig[1] = -min(x1, 0) - min(y1, 0);
110
}
111

    
112
/* determine the dimensions of the output based on command line and
113
 image dimensions */
114
static void calc_dimensions(imginfo_t *imginfo) {
115
        double dim_def;
116
        double maxwidth, maxheight, sc;
117
        rect_t r;
118

    
119
        /* we take care of a special case: if one of the image dimensions is
120
         0, we change it to 1. Such an image is empty anyway, so there
121
         will be 0 paths in it. Changing the dimensions avoids division by
122
         0 error in calculating scaling factors, bounding boxes and
123
         such. This doesn't quite do the right thing in all cases, but it
124
         is better than causing overflow errors or "nan" output in
125
         backends.  Human users don't tend to process images of size 0
126
         anyway; they might occur in some pipelines. */
127
        if (imginfo->pixwidth == 0) {
128
                imginfo->pixwidth = 1;
129
        }
130
        if (imginfo->pixheight == 0) {
131
                imginfo->pixheight = 1;
132
        }
133

    
134
        /* set the default dimension for width, height, margins */
135
        if (info.backend->pixel) {
136
                dim_def = DIM_PT;
137
        } else {
138
                dim_def = DEFAULT_DIM;
139
        }
140

    
141
        /* apply default dimension to width, height, margins */
142
        imginfo->width = info.width_d.x == UNDEF ? UNDEF : double_of_dim(info.width_d, dim_def);
143
        imginfo->height = info.height_d.x == UNDEF ? UNDEF : double_of_dim(info.height_d, dim_def);
144
        imginfo->lmar = info.lmar_d.x == UNDEF ? UNDEF : double_of_dim(info.lmar_d, dim_def);
145
        imginfo->rmar = info.rmar_d.x == UNDEF ? UNDEF : double_of_dim(info.rmar_d, dim_def);
146
        imginfo->tmar = info.tmar_d.x == UNDEF ? UNDEF : double_of_dim(info.tmar_d, dim_def);
147
        imginfo->bmar = info.bmar_d.x == UNDEF ? UNDEF : double_of_dim(info.bmar_d, dim_def);
148

    
149
        /* determine width and height from desired resolution / scaling
150
         factor, if given */
151
        if (info.backend->pixel) {
152
                if (imginfo->width == UNDEF && info.sx != UNDEF) {
153
                        imginfo->width = imginfo->pixwidth * info.sx;
154
                }
155
                if (imginfo->height == UNDEF && info.sy != UNDEF) {
156
                        imginfo->height = imginfo->pixheight * info.sy;
157
                }
158
        } else {
159
                if (imginfo->width == UNDEF && info.rx != UNDEF) {
160
                        imginfo->width = imginfo->pixwidth / info.rx * 72;
161
                }
162
                if (imginfo->height == UNDEF && info.ry != UNDEF) {
163
                        imginfo->height = imginfo->pixheight / info.ry * 72;
164
                }
165
        }
166

    
167
        /* if one of width/height is specified, determine the other */
168
        if (imginfo->width == UNDEF && imginfo->height != UNDEF) {
169
                imginfo->width = imginfo->height / imginfo->pixheight * imginfo->pixwidth / info.stretch;
170
        } else
171
                if (imginfo->width != UNDEF && imginfo->height == UNDEF) {
172
                        imginfo->height = imginfo->width / imginfo->pixwidth * imginfo->pixheight * info.stretch;
173
                }
174

    
175
        /* if width and height are still variable, figure them out */
176
        if (imginfo->width == UNDEF && imginfo->height == UNDEF) {
177

    
178
                if (info.backend->fixed) {
179

    
180
                        /* in fixed-size backends, try to squeeze it between margins */
181
                        maxwidth = UNDEF;
182
                        maxheight = UNDEF;
183

    
184
                        if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
185
                                maxwidth = info.paperwidth - imginfo->lmar - imginfo->rmar;
186
                        }
187
                        if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
188
                                maxheight = info.paperheight - imginfo->bmar - imginfo->tmar;
189
                        }
190
                        if (maxwidth == UNDEF && maxheight == UNDEF) {
191
                                maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
192
                                maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
193
                        }
194

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

    
197
                        sc = min(maxwidth == UNDEF ? INFTY : maxwidth / r.bb[0], maxheight == UNDEF ? INFTY : maxheight / r.bb[1]);
198
                        imginfo->width = imginfo->pixwidth * sc;
199
                        imginfo->height = imginfo->pixheight * info.stretch * sc;
200

    
201
                } else
202
                        if (info.backend->pixel) {
203

    
204
                                /* in pixel-based backends, assume default scaling factor of 1 */
205

    
206
                                imginfo->width = imginfo->pixwidth;
207
                                imginfo->height = imginfo->pixheight * info.stretch;
208
                        } else {
209

    
210
                                /* otherwise, choose a default size based on the default paper format */
211

    
212
                                maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
213
                                maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
214

    
215
                                sc = min(maxwidth / imginfo->pixwidth, maxheight / imginfo->pixheight / info.stretch);
216
                                imginfo->width = imginfo->pixwidth * sc;
217
                                imginfo->height = imginfo->pixheight * info.stretch * sc;
218
                        }
219
        }
220

    
221
        /* calculate coordinate system */
222
        rotate_dim(info.angle, imginfo->width, imginfo->height, &imginfo->trans);
223

    
224
        /* adjust margins */
225
        if (info.backend->fixed) {
226
                if (imginfo->lmar == UNDEF && imginfo->rmar == UNDEF) {
227
                        imginfo->lmar = (info.paperwidth - imginfo->trans.bb[0]) / 2;
228
                } else
229
                        if (imginfo->lmar == UNDEF) {
230
                                imginfo->lmar = (info.paperwidth - imginfo->trans.bb[0] - imginfo->rmar);
231
                        } else
232
                                if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
233
                                        imginfo->lmar += (info.paperwidth - imginfo->trans.bb[0] - imginfo->lmar - imginfo->rmar) / 2;
234
                                }
235
                if (imginfo->bmar == UNDEF && imginfo->tmar == UNDEF) {
236
                        imginfo->bmar = (info.paperheight - imginfo->trans.bb[1]) / 2;
237
                } else
238
                        if (imginfo->bmar == UNDEF) {
239
                                imginfo->bmar = (info.paperheight - imginfo->trans.bb[1] - imginfo->tmar);
240
                        } else
241
                                if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
242
                                        imginfo->bmar += (info.paperheight - imginfo->trans.bb[1] - imginfo->bmar - imginfo->tmar) / 2;
243
                                }
244
        } else {
245
                if (imginfo->lmar == UNDEF) {
246
                        imginfo->lmar = 0;
247
                }
248
                if (imginfo->rmar == UNDEF) {
249
                        imginfo->rmar = 0;
250
                }
251
                if (imginfo->bmar == UNDEF) {
252
                        imginfo->bmar = 0;
253
                }
254
                if (imginfo->tmar == UNDEF) {
255
                        imginfo->tmar = 0;
256
                }
257
        }
258
}
259

    
260
static FILE *my_fopen_read(const char *filename) {
261
        if (filename == NULL || strcmp(filename, "-") == 0) {
262
                return stdin;
263
        }
264
        return fopen(filename, "rb");
265
}
266

    
267
static FILE *my_fopen_write(const char *filename) {
268
        if (filename == NULL || strcmp(filename, "-") == 0) {
269
                return stdout;
270
        }
271
        return fopen(filename, "wb");
272
}
273

    
274
/* close a file, but do nothing is filename is NULL or "-" */
275
static void my_fclose(FILE *f, const char *filename) {
276
        if (filename == NULL || strcmp(filename, "-") == 0) {
277
                return;
278
        }
279
        fclose(f);
280
}
281

    
282
/* print a simple progress bar. This is a callback function that is
283
 potentially called often; thus, it has been optimized for the
284
 typical case, which is when the progress bar does not need updating. */
285
static void simple_progress(double d, void *data) {
286
        simple_progress_t *p = (simple_progress_t *) data;
287
        static char b[] = "========================================";
288
        int tick; /* number of visible tickmarks, 0..40 */
289
        int perc; /* visible percentage, 0..100 */
290

    
291
        /* note: the 0.01 and 0.025 ensure that we always end on 40
292
         tickmarks and 100%, despite any rounding errors. The 0.995
293
         ensures that tick always increases when d >= p->dnext. */
294
        if (d >= p->dnext) {
295
                tick = (int) floor(d * 40 + 0.01);
296
                perc = (int) floor(d * 100 + 0.025);
297
                fprintf(stderr, "%-21s |%-40s| %d%% "COL0"", p->name, b + 40 - tick, perc);
298
                p->dnext = (tick + 0.995) / 40.0;
299
        }
300
}
301

    
302
/* Initialize parameters for simple progress bar. The caller passes an
303
 allocated simple_progress_t structure to avoid having to malloc it
304
 here and free it later. */
305
static inline void init_progress(potrace_progress_t *prog, simple_progress_t *p, const char *filename, int count) {
306
        const char *q, *s;
307
        int len;
308

    
309
        /* initialize callback function's data */
310
        p->dnext = 0;
311

    
312
        if (count != 0) {
313
                sprintf(p->name, " (p.%d):", count + 1);
314
        } else {
315
                s = filename;
316
                if ((q = strrchr(s, '/')) != NULL) {
317
                        s = q + 1;
318
                }
319
                len = strlen(s);
320
                strncpy(p->name, s, 21);
321
                p->name[20] = 0;
322
                if (len > 20) {
323
                        p->name[17] = '.';
324
                        p->name[18] = '.';
325
                        p->name[19] = '.';
326
                }
327
                strcat(p->name, ":");
328
        }
329

    
330
        /* initialize progress parameters */
331
        prog->callback = &simple_progress;
332
        prog->data = (void *) p;
333
        prog->min = 0.0;
334
        prog->max = 1.0;
335
        prog->epsilon = 0.0;
336

    
337
        /* draw first progress bar */
338
        simple_progress(0.0, prog->data);
339
        return;
340
}
341

    
342
struct pageformat_s {
343
        char *name;
344
        int w, h;
345
};
346
typedef struct pageformat_s pageformat_t;
347

    
348
/* dimensions of the various page formats, in postscript points */
349
static pageformat_t pageformat[] = {
350
        { "a4",        595,  842 },
351
        { "a3",        842, 1191 },
352
        { "a5",        421,  595 },
353
        { "b5",        516,  729 },
354
        { "letter",    612,  792 },
355
        { "legal",     612, 1008 },
356
        { "tabloid",   792, 1224 },
357
        { "statement", 396,  612 },
358
        { "executive", 540,  720 },
359
        { "folio",     612,  936 },
360
        { "quarto",    610,  780 },
361
        { "10x14",     720, 1008 },
362
        { NULL, 0, 0 },
363
};
364

    
365
struct turnpolicy_s {
366
        char *name;
367
        int n;
368
};
369
typedef struct turnpolicy_s turnpolicy_t;
370

    
371
/* names of turn policies */
372
static turnpolicy_t turnpolicy[] = {
373
        {"black",    POTRACE_TURNPOLICY_BLACK},
374
        {"white",    POTRACE_TURNPOLICY_WHITE},
375
        {"left",     POTRACE_TURNPOLICY_LEFT},
376
        {"right",    POTRACE_TURNPOLICY_RIGHT},
377
        {"minority", POTRACE_TURNPOLICY_MINORITY},
378
        {"majority", POTRACE_TURNPOLICY_MAJORITY},
379
        {"random",   POTRACE_TURNPOLICY_RANDOM},
380
        {NULL, 0},
381
};
382

    
383
static dim_t parse_dimension(char *s, char **endptr) {
384
        char *p;
385
        dim_t res;
386

    
387
        res.x = strtod(s, &p);
388
        res.d = 0;
389
        if (p!=s) {
390
                if (!strncasecmp(p, "in", 2)) {
391
                        res.d = DIM_IN;
392
                        p += 2;
393
                } else if (!strncasecmp(p, "cm", 2)) {
394
                        res.d = DIM_CM;
395
                        p += 2;
396
                } else if (!strncasecmp(p, "mm", 2)) {
397
                        res.d = DIM_MM;
398
                        p += 2;
399
                } else if (!strncasecmp(p, "pt", 2)) {
400
                        res.d = DIM_PT;
401
                        p += 2;
402
                }
403
        }
404
        if (endptr!=NULL) {
405
                *endptr = p;
406
        }
407
        return res;
408
}
409

    
410
/* parse a pair of dimensions, such as "8.5x11in", "30mmx4cm" */
411
static void parse_dimensions(char *s, char **endptr, dim_t *dxp, dim_t *dyp) {
412
        char *p, *q;
413
        dim_t dx, dy;
414

    
415
        dx = parse_dimension(s, &p);
416
        if (p==s) {
417
                goto fail;
418
        }
419
        if (*p != 'x') {
420
                goto fail;
421
        }
422
        p++;
423
        dy = parse_dimension(p, &q);
424
        if (q==p) {
425
                goto fail;
426
        }
427
        if (dx.d && !dy.d) {
428
                dy.d = dx.d;
429
        } else if (!dx.d && dy.d) {
430
                dx.d = dy.d;
431
        }
432
        *dxp = dx;
433
        *dyp = dy;
434
        if (endptr != NULL) {
435
                *endptr = q;
436
        }
437
        return;
438

    
439
 fail:
440
        dx.x = dx.d = dy.x = dy.d = 0;
441
        *dxp = dx;
442
        *dyp = dy;
443
        if (endptr != NULL) {
444
                *endptr = s;
445
        }
446
        return;
447
}
448

    
449
#define OPT_GROUP     300
450
#define OPT_OPAQUE    301
451
#define OPT_FILLCOLOR 302
452
#define OPT_PROGRESS  303
453

    
454
static struct option longopts[] = {
455
        {"help",          0, 0, 'h'},
456
        {"version",       0, 0, 'v'},
457
        {"license",       0, 0, 'l'},
458
        {"show-defaults", 0, 0, 'V'},
459
        {"progress",      0, 0, OPT_PROGRESS},
460
        {"width",         1, 0, 'W'},
461
        {"height",        1, 0, 'H'},
462
        {"resolution",    1, 0, 'r'},
463
        {"scale",         1, 0, 'x'},
464
        {"stretch",       1, 0, 'S'},
465
        {"margin",        1, 0, 'M'},
466
        {"leftmargin",    1, 0, 'L'},
467
        {"rightmargin",   1, 0, 'R'},
468
        {"topmargin",     1, 0, 'T'},
469
        {"bottommargin",  1, 0, 'B'},
470
        {"rotate",        1, 0, 'A'},
471
        {"pagesize",      1, 0, 'P'},
472
        {"turdsize",      1, 0, 't'},
473
        {"unit",          1, 0, 'u'},
474
        {"cleartext",     0, 0, 'c'},
475
        {"level2",        0, 0, '2'},
476
        {"level3",        0, 0, '3'},
477
        {"eps",           0, 0, 'e'},
478
        {"postscript",    0, 0, 'p'},
479
        {"svg",           0, 0, 's'},
480
        {"pgm",           0, 0, 'g'},
481
        {"backend",       1, 0, 'b'},
482
        {"debug",         1, 0, 'd'},
483
        {"color",         1, 0, 'C'},
484
        {"fillcolor",     1, 0, OPT_FILLCOLOR},
485
        {"turnpolicy",    1, 0, 'z'},
486
        {"gamma",         1, 0, 'G'},
487
        {"longcurve",     0, 0, 'n'},
488
        {"longcoding",    0, 0, 'q'},
489
        {"alphamax",      1, 0, 'a'},
490
        {"opttolerance",  1, 0, 'O'},
491
        {"output",        1, 0, 'o'},
492
        {"blacklevel",    1, 0, 'k'},
493
        {"invert",        0, 0, 'i'},
494
        {"opaque",        0, 0, OPT_OPAQUE},
495
        {"group",         0, 0, OPT_GROUP},
496

    
497
        {0, 0, 0, 0}
498
};
499

    
500
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";
501

    
502
static void dopts(int ac, char *av[]) {
503
        int c;
504
        char *p;
505
        int i, j, r;
506
        dim_t dim, dimx, dimy;
507
        int matches, bestmatch;
508

    
509
        /* defaults */
510
        info.backend = &backend[0];
511

    
512
        info.debug = 0;
513
        info.width_d.x = UNDEF;
514
        info.height_d.x = UNDEF;
515
        info.rx = UNDEF;
516
        info.ry = UNDEF;
517
        info.sx = UNDEF;
518
        info.sy = UNDEF;
519
        info.stretch = 1;
520
        info.lmar_d.x = UNDEF;
521
        info.rmar_d.x = UNDEF;
522
        info.tmar_d.x = UNDEF;
523
        info.bmar_d.x = UNDEF;
524
        info.angle = 0;
525
        info.paperwidth = DEFAULT_PAPERWIDTH;
526
        info.paperheight = DEFAULT_PAPERHEIGHT;
527
        info.unit = 10;
528
        info.compress = 1;
529
        info.pslevel = 2;
530
        info.color = 0x000000;
531
        info.gamma = 2.2;
532
        info.param = potrace_param_default();
533
        if (!info.param) {
534
                fprintf(stderr, ""POTRACE": %s\n", strerror(errno));
535
                exit(1);
536
        }
537
        info.longcoding = 0;
538
        info.outfile = NULL;
539
        info.blacklevel = 0.5;
540
        info.invert = 0;
541
        info.opaque = 0;
542
        info.group = 0;
543
        info.fillcolor = 0xffffff;
544
        info.progress = 0;
545

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

    
760
                                if (*p) {
761
                                        fprintf(stderr, ""POTRACE": invalid alphamax -- %s\n", optarg);
762
                                        exit(1);
763
                                }
764
                                break;
765
                        case 'O':
766
                                info.param->opttolerance = strtod(optarg, &p);
767
                                if (*p) {
768
                                        fprintf(stderr, ""POTRACE": invalid opttolerance -- %s\n", optarg);
769
                                        exit(1);
770
                                }
771
                                break;
772
                        case 'o':
773
                                free(info.outfile);
774
                                info.outfile = strdup(optarg);
775
                                break;
776
                        case 'k':
777
                                info.blacklevel = strtod(optarg, &p);
778
                                if (*p) {
779
                                        fprintf(stderr, ""POTRACE": invalid blacklevel -- %s\n", optarg);
780
                                        exit(1);
781
                                }
782
                                break;
783
                        case 'i':
784
                                info.invert = 1;
785
                                break;
786
                        case OPT_OPAQUE:
787
                                info.opaque = 1;
788
                                break;
789
                        case OPT_GROUP:
790
                                info.group = 1;
791
                                break;
792
                        case '?':
793
                                fprintf(stderr, "Try --help for more info\n");
794
                                exit(1);
795
                                break;
796
                        default:
797
                                fprintf(stderr, ""POTRACE": Unimplemented option -- %c\n", c);
798
                                exit(1);
799
                }
800
        }
801
        info.infiles = &av[optind];
802
        info.infilecount = ac-optind;
803
}
804

    
805
static double* showList(potrace_path_t *plist) {
806
        int i;
807
        int count;
808
        potrace_path_t *p;
809
        int n, *tag;
810
        potrace_dpoint_t (*c)[3];
811
        double *memory;
812

    
813
        p = plist;
814
        count = 0;
815

    
816
        // Comprobamos cuanto va a ocupar la memoria a rellenar
817
        while (p != NULL) {
818
                n = p->curve.n;
819
                tag = p->curve.tag;
820
                c = p->curve.c;
821
                count += 3; // moveTo(x, y)
822
                for (i = 0; i < n; i++) {
823
                        switch (tag[i]) {
824
                                case POTRACE_CORNER:
825
                                        count += 3; // lineTo(x, y)
826
                                        count += 3; // lineTo(x, y)
827
                                        break;
828
                                case POTRACE_CURVETO:
829
                                        count += 7; // curveTo(x1, y1, x2, y2, x3, y3)
830
                                        break;
831
                        }
832
                }
833
                // at the end of a group of a positive path and its negative children, fill
834
                if (p->next == NULL || p->next->sign == '+')
835
                        count++; // closePath()
836
                p = p->next;
837
        }
838
        count++;
839

    
840
        // Creamos la zona de memoria que devolveremos a Java
841
        memory = (double *) malloc(sizeof(double) * count);
842

    
843
        // Rellenamos la memoria con la lista de operaciones a realizar
844
        p = plist;
845
        count = 1;
846
        while (p != NULL) {
847
                n = p->curve.n;
848
                tag = p->curve.tag;
849
                c = p->curve.c;
850

    
851
                // moveTo(x, y);
852
                memory[count++] = 0;
853
                memory[count++] = c[n - 1][2].x;
854
                memory[count++] = c[n - 1][2].y;
855
                for (i = 0; i < n; i++) {
856
                        switch (tag[i]) {
857
                                case POTRACE_CORNER:
858
                                        // lineTo(x, y);
859
                                        memory[count++] = 1;
860
                                        memory[count++] = c[i][1].x;
861
                                        memory[count++] = c[i][1].y;
862
                                        // lineTo(x, y);
863
                                        memory[count++] = 1;
864
                                        memory[count++] = c[i][2].x;
865
                                        memory[count++] = c[i][2].y;
866
                                        break;
867
                                case POTRACE_CURVETO:
868
                                        // curveTo(x1, y1, x2, y2, x3, y3);
869
                                        memory[count++] = 2;
870
                                        memory[count++] = c[i][0].x;
871
                                        memory[count++] = c[i][0].y;
872
                                        memory[count++] = c[i][1].x;
873
                                        memory[count++] = c[i][1].y;
874
                                        memory[count++] = c[i][2].x;
875
                                        memory[count++] = c[i][2].y;
876
                                        break;
877
                        }
878
                }
879
                if (p->next == NULL || p->next->sign == '+')
880
                        memory[count++] = 3;
881
                p = p->next;
882
        }
883
        memory[0] = count;
884
        return memory;
885
}
886

    
887
static double* process_buffer(const long *inbuffer, int width, int height) {
888
        int r;
889
        double *memory;
890
        potrace_bitmap_t *bm = NULL;
891
        imginfo_t imginfo;
892
        int eof_flag = 0; /* to indicate premature eof */
893
        potrace_state_t *st;
894
        simple_progress_t progress_data;
895

    
896
        bm = (potrace_bitmap_t *) malloc (sizeof(potrace_bitmap_t));
897
        bm->w = width;
898
        bm->h = height;
899
        int dy = (width + 32 - 1) / 32;
900
        bm->dy = dy;
901

    
902
        bm->map = (potrace_word *) inbuffer;
903

    
904
        /* prepare progress bar, if requested */
905
        info.param->progress.callback = NULL;
906

    
907
        // Invertir colores, el negro es blanco y el blanco es negro
908
        if (info.invert)
909
                bm_invert(bm);
910

    
911
        /* process the image */
912

    
913
        st = potrace_trace(info.param, bm);
914
        if (!st || st->status != POTRACE_STATUS_OK) {
915
                fprintf(stderr, ""POTRACE": %s\n", strerror(errno));
916
                exit(2);
917
        }
918
        /* calculate image dimensions */
919
        imginfo.pixwidth = bm->w;
920
        imginfo.pixheight = bm->h;
921
        calc_dimensions(&imginfo);
922

    
923
        bm_free(bm);
924

    
925
        memory = showList(st->plist);
926

    
927
        potrace_state_free(st);
928

    
929
        if (info.progress) {
930
                fprintf(stderr, "\n");
931
        }
932

    
933
        return memory;
934
}
935

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

    
940
        // Reiniciar el contador externo de los parametros
941
        optind = 1;
942

    
943
        /* process options */
944
        dopts(argc, argv);
945

    
946
        return process_buffer(bufferIn, width, height);
947
}