Statistics
| Revision:

gvsig-raster / libjni-potrace / trunk / libjni-potrace / src / main / native / jpotrace / potrace_raster.c @ 1780

History | View | Annotate | Download (26.5 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
#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
                                break;
778
                        case 'O':
779
                                info.param->opttolerance = strtod(optarg, &p);
780
                                break;
781
                        case 'o':
782
                                free(info.outfile);
783
                                info.outfile = strdup(optarg);
784
                                break;
785
                        case 'k':
786
                                info.blacklevel = strtod(optarg, &p);
787
                                break;
788
                        case 'i':
789
                                info.invert = 1;
790
                                break;
791
                        case OPT_OPAQUE:
792
                                info.opaque = 1;
793
                                break;
794
                        case OPT_GROUP:
795
                                info.group = 1;
796
                                break;
797
                        case '?':
798
                                fprintf(stderr, "Try --help for more info\n");
799
                                exit(1);
800
                                break;
801
                        default:
802
                                fprintf(stderr, "\"POTRACE\": Unimplemented option -- %c\n", c);
803
                                exit(1);
804
                }
805
        }
806
        info.infiles = &av[optind];
807
        info.infilecount = ac-optind;
808
}
809

    
810
static double* showList(potrace_path_t *plist) {
811
        int i;
812
        int count;
813
        potrace_path_t *p;
814
        int n, *tag;
815
        potrace_dpoint_t (*c)[3];
816
        double *memory;
817

    
818
        p = plist;
819
        count = 0;
820

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

    
845
        // Creamos la zona de memoria que devolveremos a Java
846
        memory = (double *) malloc(sizeof(double) * count);
847

    
848
        // Rellenamos la memoria con la lista de operaciones a realizar
849
        p = plist;
850
        count = 1;
851
        while (p != NULL) {
852
                n = p->curve.n;
853
                tag = p->curve.tag;
854
                c = p->curve.c;
855

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

    
892
static double* process_buffer(const long *inbuffer, int width, int height) {
893
        int r;
894
        double *memory;
895
        potrace_bitmap_t *bm = NULL;
896
        imginfo_t imginfo;
897
        int eof_flag = 0; /* to indicate premature eof */
898
        potrace_state_t *st;
899
        simple_progress_t progress_data;
900
        int dy;
901

    
902
        bm = (potrace_bitmap_t *) malloc (sizeof(potrace_bitmap_t));
903
        bm->w = width;
904
        bm->h = height;
905
        dy = (width + 32 - 1) / 32;
906
        bm->dy = dy;
907

    
908
        bm->map = (potrace_word *) inbuffer;
909

    
910
        /* prepare progress bar, if requested */
911
        info.param->progress.callback = NULL;
912

    
913
        // Invertir colores, el negro es blanco y el blanco es negro
914
        if (info.invert)
915
                bm_invert(bm);
916

    
917
        /* process the image */
918

    
919
        st = potrace_trace(info.param, bm);
920
        if (!st || st->status != POTRACE_STATUS_OK) {
921
                fprintf(stderr, "\"POTRACE\": %s\n", strerror(errno));
922
                exit(2);
923
        }
924
        /* calculate image dimensions */
925
        imginfo.pixwidth = bm->w;
926
        imginfo.pixheight = bm->h;
927
        calc_dimensions(&imginfo);
928
        
929
        // rgaitan: We cannot use here bm_free (becouse it
930
        // frees also the bm->map (that is a inbuffer, that in this
931
        // case comes from java so, FAIL!.
932
        //bm_free(bm);
933

    
934
        memory = showList(st->plist);
935

    
936
        potrace_state_free(st);
937

    
938
        if (info.progress) {
939
                fprintf(stderr, "\n");
940
        }
941

    
942
        return memory;
943
}
944

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

    
949
        // Reiniciar el contador externo de los parametros
950
        optind = 1;
951

    
952
        /* process options */
953
        dopts(argc, argv);
954

    
955
        return process_buffer(bufferIn, width, height);
956
}