summaryrefslogtreecommitdiff
path: root/Build/source/libs/potrace/potrace-src/src/main.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-08-31 23:11:41 +0000
committerKarl Berry <karl@freefriends.org>2018-08-31 23:11:41 +0000
commit8ba2cf02688200d56e4fe0839a451ef832ce15b6 (patch)
treefcec1a50903a6e5b939859a1f92e15342636f290 /Build/source/libs/potrace/potrace-src/src/main.c
parent5d0960aa5419651a9c9b6503e44be2f098831ef1 (diff)
dvisvgm 2.5, including potrace now bundled with dvisvgm instead of under libs/
git-svn-id: svn://tug.org/texlive/trunk@48527 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/potrace/potrace-src/src/main.c')
-rw-r--r--Build/source/libs/potrace/potrace-src/src/main.c1274
1 files changed, 0 insertions, 1274 deletions
diff --git a/Build/source/libs/potrace/potrace-src/src/main.c b/Build/source/libs/potrace/potrace-src/src/main.c
deleted file mode 100644
index 1722e69af19..00000000000
--- a/Build/source/libs/potrace/potrace-src/src/main.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/* Copyright (C) 2001-2017 Peter Selinger.
- This file is part of Potrace. It is free software and it is covered
- by the GNU General Public License. See the file COPYING for details. */
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-#ifndef _NETBSD_SOURCE
-#define _NETBSD_SOURCE 1
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <strings.h>
-#include <getopt.h>
-#include <math.h>
-
-#include "main.h"
-#include "potracelib.h"
-#include "backend_pdf.h"
-#include "backend_eps.h"
-#include "backend_pgm.h"
-#include "backend_svg.h"
-#include "backend_xfig.h"
-#include "backend_dxf.h"
-#include "backend_geojson.h"
-#include "potracelib.h"
-#include "bitmap_io.h"
-#include "bitmap.h"
-#include "platform.h"
-#include "auxiliary.h"
-#include "progress_bar.h"
-#include "trans.h"
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#define UNDEF ((double)(1e30)) /* a value to represent "undefined" */
-
-struct info_s info;
-
-/* ---------------------------------------------------------------------- */
-/* some data structures for option processing */
-
-struct pageformat_s {
- const char *name;
- int w, h;
-};
-typedef struct pageformat_s pageformat_t;
-
-/* dimensions of the various page formats, in postscript points */
-static pageformat_t pageformat[] = {
- { "a4", 595, 842 },
- { "a3", 842, 1191 },
- { "a5", 421, 595 },
- { "b5", 516, 729 },
- { "letter", 612, 792 },
- { "legal", 612, 1008 },
- { "tabloid", 792, 1224 },
- { "statement", 396, 612 },
- { "executive", 540, 720 },
- { "folio", 612, 936 },
- { "quarto", 610, 780 },
- { "10x14", 720, 1008 },
- { NULL, 0, 0 },
-};
-
-struct turnpolicy_s {
- const char *name;
- int n;
-};
-typedef struct turnpolicy_s turnpolicy_t;
-
-/* names of turn policies */
-static turnpolicy_t turnpolicy[] = {
- {"black", POTRACE_TURNPOLICY_BLACK},
- {"white", POTRACE_TURNPOLICY_WHITE},
- {"left", POTRACE_TURNPOLICY_LEFT},
- {"right", POTRACE_TURNPOLICY_RIGHT},
- {"minority", POTRACE_TURNPOLICY_MINORITY},
- {"majority", POTRACE_TURNPOLICY_MAJORITY},
- {"random", POTRACE_TURNPOLICY_RANDOM},
- {NULL, 0},
-};
-
-/* backends and their characteristics */
-struct backend_s {
- const char *name; /* name of this backend */
- const char *ext; /* file extension */
- int fixed; /* fixed page size backend? */
- int pixel; /* pixel-based backend? */
- int multi; /* multi-page backend? */
- int (*init_f)(FILE *fout); /* initialization function */
- int (*page_f)(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
- /* per-bitmap function */
- int (*term_f)(FILE *fout); /* finalization function */
- int opticurve; /* opticurve capable (true Bezier curves?) */
-};
-typedef struct backend_s backend_t;
-
-static backend_t backend[] = {
- { "svg", ".svg", 0, 0, 0, NULL, page_svg, NULL, 1 },
- { "pdf", ".pdf", 0, 0, 1, init_pdf, page_pdf, term_pdf, 1 },
- { "pdfpage", ".pdf", 1, 0, 1, init_pdf, page_pdfpage, term_pdf, 1 },
- { "eps", ".eps", 0, 0, 0, NULL, page_eps, NULL, 1 },
- { "postscript", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1 },
- { "ps", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1 },
- { "dxf", ".dxf", 0, 1, 0, NULL, page_dxf, NULL, 1 },
- { "geojson", ".json",0, 1, 0, NULL, page_geojson, NULL, 1 },
- { "pgm", ".pgm", 0, 1, 1, NULL, page_pgm, NULL, 1 },
- { "gimppath", ".svg", 0, 1, 0, NULL, page_gimp, NULL, 1 },
- { "xfig", ".fig", 1, 0, 0, NULL, page_xfig, NULL, 0 },
- { NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0 },
-};
-
-/* look up a backend by name. If found, return 0 and set *bp. If not
- found leave *bp unchanged and return 1, or 2 on ambiguous
- prefix. */
-static int backend_lookup(const char *name, backend_t **bp) {
- int i;
- int m=0; /* prefix matches */
- backend_t *b = NULL;
-
- for (i=0; backend[i].name; i++) {
- if (strcasecmp(backend[i].name, name)==0) {
- *bp = &backend[i];
- return 0;
- } else if (strncasecmp(backend[i].name, name, strlen(name))==0) {
- m++;
- b = &backend[i];
- }
- }
- /* if there was no exact match, and exactly one prefix match, use that */
- if (m==1) {
- *bp = b;
- return 0;
- } else if (m) {
- return 2;
- } else {
- return 1;
- }
-}
-
-/* list all available backends by name, in a comma separated list.
- Assume the cursor starts in column j, and break lines at length
- linelen. Do not output any trailing punctuation. Return the column
- the cursor is in. */
-static int backend_list(FILE *fout, int j, int linelen) {
- int i;
-
- for (i=0; backend[i].name; i++) {
- if (j + (int)strlen(backend[i].name) > linelen) {
- fprintf(fout, "\n");
- j = 0;
- }
- j += fprintf(fout, "%s", backend[i].name);
- if (backend[i+1].name) {
- j += fprintf(fout, ", ");
- }
- }
- return j;
-}
-
-/* ---------------------------------------------------------------------- */
-/* some info functions */
-
-static void license(FILE *f) {
- fprintf(f,
- "This program is free software; you can redistribute it and/or modify\n"
- "it under the terms of the GNU General Public License as published by\n"
- "the Free Software Foundation; either version 2 of the License, or\n"
- "(at your option) any later version.\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software Foundation\n"
- "Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
- );
-}
-
-static void show_defaults(FILE *f) {
- fprintf(f, "Default unit: " DEFAULT_DIM_NAME "\n");
- fprintf(f, "Default page size: " DEFAULT_PAPERFORMAT "\n");
-}
-
-static void usage(FILE *f) {
- int j;
-
- fprintf(f, "Usage: " POTRACE " [options] [filename...]\n");
- fprintf(f, "General options:\n");
- fprintf(f, " -h, --help - print this help message and exit\n");
- fprintf(f, " -v, --version - print version info and exit\n");
- fprintf(f, " -l, --license - print license info and exit\n");
- fprintf(f, "File selection:\n");
- fprintf(f, " <filename> - an input file\n");
- fprintf(f, " -o, --output <filename> - write all output to this file\n");
- fprintf(f, " -- - end of options; 0 or more input filenames follow\n");
- fprintf(f, "Backend selection:\n");
- fprintf(f, " -b, --backend <name> - select backend by name\n");
- fprintf(f, " -b svg, -s, --svg - SVG backend (scalable vector graphics)\n");
- fprintf(f, " -b pdf - PDF backend (portable document format)\n");
- fprintf(f, " -b pdfpage - fixed page-size PDF backend\n");
- fprintf(f, " -b eps, -e, --eps - EPS backend (encapsulated PostScript) (default)\n");
- fprintf(f, " -b ps, -p, --postscript - PostScript backend\n");
- fprintf(f, " -b pgm, -g, --pgm - PGM backend (portable greymap)\n");
- fprintf(f, " -b dxf - DXF backend (drawing interchange format)\n");
- fprintf(f, " -b geojson - GeoJSON backend\n");
- fprintf(f, " -b gimppath - Gimppath backend (GNU Gimp)\n");
- fprintf(f, " -b xfig - XFig backend\n");
- fprintf(f, "Algorithm options:\n");
- fprintf(f, " -z, --turnpolicy <policy> - how to resolve ambiguities in path decomposition\n");
- fprintf(f, " -t, --turdsize <n> - suppress speckles of up to this size (default 2)\n");
- fprintf(f, " -a, --alphamax <n> - corner threshold parameter (default 1)\n");
- fprintf(f, " -n, --longcurve - turn off curve optimization\n");
- fprintf(f, " -O, --opttolerance <n> - curve optimization tolerance (default 0.2)\n");
- fprintf(f, " -u, --unit <n> - quantize output to 1/unit pixels (default 10)\n");
- fprintf(f, " -d, --debug <n> - produce debugging output of type n (n=1,2,3)\n");
- fprintf(f, "Scaling and placement options:\n");
- fprintf(f, " -P, --pagesize <format> - page size (default is " DEFAULT_PAPERFORMAT ")\n");
- fprintf(f, " -W, --width <dim> - width of output image\n");
- fprintf(f, " -H, --height <dim> - height of output image\n");
- fprintf(f, " -r, --resolution <n>[x<n>] - resolution (in dpi) (dimension-based backends)\n");
- fprintf(f, " -x, --scale <n>[x<n>] - scaling factor (pixel-based backends)\n");
- fprintf(f, " -S, --stretch <n> - yresolution/xresolution\n");
- fprintf(f, " -A, --rotate <angle> - rotate counterclockwise by angle\n");
- fprintf(f, " -M, --margin <dim> - margin\n");
- fprintf(f, " -L, --leftmargin <dim> - left margin\n");
- fprintf(f, " -R, --rightmargin <dim> - right margin\n");
- fprintf(f, " -T, --topmargin <dim> - top margin\n");
- fprintf(f, " -B, --bottommargin <dim> - bottom margin\n");
- fprintf(f, " --tight - remove whitespace around the input image\n");
- fprintf(f, "Color options, supported by some backends:\n");
- fprintf(f, " -C, --color #rrggbb - set foreground color (default black)\n");
- fprintf(f, " --fillcolor #rrggbb - set fill color (default transparent)\n");
- fprintf(f, " --opaque - make white shapes opaque\n");
- fprintf(f, "SVG options:\n");
- fprintf(f, " --group - group related paths together\n");
- fprintf(f, " --flat - whole image as a single path\n");
- fprintf(f, "Postscript/EPS/PDF options:\n");
- fprintf(f, " -c, --cleartext - do not compress the output\n");
- fprintf(f, " -2, --level2 - use postscript level 2 compression (default)\n");
-#ifdef HAVE_ZLIB
- fprintf(f, " -3, --level3 - use postscript level 3 compression\n");
-#endif
- fprintf(f, " -q, --longcoding - do not optimize for file size\n");
- fprintf(f, "PGM options:\n");
- fprintf(f, " -G, --gamma <n> - gamma value for anti-aliasing (default 2.2)\n");
- fprintf(f, "Frontend options:\n");
- fprintf(f, " -k, --blacklevel <n> - black/white cutoff in input file (default 0.5)\n");
- fprintf(f, " -i, --invert - invert bitmap\n");
- fprintf(f, "Progress bar options:\n");
- fprintf(f, " --progress - show progress bar\n");
- fprintf(f, " --tty <mode> - progress bar rendering: vt100 or dumb\n");
- fprintf(f, "\n");
- fprintf(f, "Dimensions can have optional units, e.g. 6.5in, 15cm, 100pt.\n");
- fprintf(f, "Default is " DEFAULT_DIM_NAME " (or pixels for pgm, dxf, and gimppath backends).\n");
- fprintf(f, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
- j = fprintf(f, "Backends are: ");
- backend_list(f, j, 78);
- fprintf(f, ".\n");
-}
-
-/* ---------------------------------------------------------------------- */
-/* auxiliary functions for parameter parsing */
-
-/* parse a dimension of the kind "1.5in", "7cm", etc. Return result in
- postscript points (=1/72 in). If endptr!=NULL, store pointer to
- next character in *endptr in the manner of strtod(3). */
-static dim_t parse_dimension(char *s, char **endptr) {
- char *p;
- dim_t res;
-
- res.x = strtod(s, &p);
- res.d = 0;
- if (p!=s) {
- if (!strncasecmp(p, "in", 2)) {
- res.d = DIM_IN;
- p += 2;
- } else if (!strncasecmp(p, "cm", 2)) {
- res.d = DIM_CM;
- p += 2;
- } else if (!strncasecmp(p, "mm", 2)) {
- res.d = DIM_MM;
- p += 2;
- } else if (!strncasecmp(p, "pt", 2)) {
- res.d = DIM_PT;
- p += 2;
- }
- }
- if (endptr!=NULL) {
- *endptr = p;
- }
- return res;
-}
-
-/* parse a pair of dimensions, such as "8.5x11in", "30mmx4cm" */
-static void parse_dimensions(char *s, char **endptr, dim_t *dxp, dim_t *dyp) {
- char *p, *q;
- dim_t dx, dy;
-
- dx = parse_dimension(s, &p);
- if (p==s) {
- goto fail;
- }
- if (*p != 'x') {
- goto fail;
- }
- p++;
- dy = parse_dimension(p, &q);
- if (q==p) {
- goto fail;
- }
- if (dx.d && !dy.d) {
- dy.d = dx.d;
- } else if (!dx.d && dy.d) {
- dx.d = dy.d;
- }
- *dxp = dx;
- *dyp = dy;
- if (endptr != NULL) {
- *endptr = q;
- }
- return;
-
- fail:
- dx.x = dx.d = dy.x = dy.d = 0;
- *dxp = dx;
- *dyp = dy;
- if (endptr != NULL) {
- *endptr = s;
- }
- return;
-}
-
-static inline double double_of_dim(dim_t d, double def) {
- if (d.d) {
- return d.x * d.d;
- } else {
- return d.x * def;
- }
-}
-
-static int parse_color(char *s) {
- int i, d;
- int col = 0;
-
- if (s[0] != '#' || strlen(s) != 7) {
- return -1;
- }
- for (i=0; i<6; i++) {
- d = s[6-i];
- if (d >= '0' && d <= '9') {
- col |= (d-'0') << (4*i);
- } else if (d >= 'a' && d <= 'f') {
- col |= (d-'a'+10) << (4*i);
- } else if (d >= 'A' && d <= 'F') {
- col |= (d-'A'+10) << (4*i);
- } else {
- return -1;
- }
- }
- return col;
-}
-
-/* ---------------------------------------------------------------------- */
-/* option processing */
-
-/* codes for options that don't have short form */
-enum {
- OPT_TIGHT = 300,
- OPT_FILLCOLOR,
- OPT_OPAQUE,
- OPT_GROUP,
- OPT_FLAT,
- OPT_PROGRESS,
- OPT_TTY
-};
-
-static struct option longopts[] = {
- {"help", 0, 0, 'h'},
- {"version", 0, 0, 'v'},
- {"show-defaults", 0, 0, 'V'}, /* undocumented option for compatibility */
- {"license", 0, 0, 'l'},
- {"width", 1, 0, 'W'},
- {"height", 1, 0, 'H'},
- {"resolution", 1, 0, 'r'},
- {"scale", 1, 0, 'x'},
- {"stretch", 1, 0, 'S'},
- {"margin", 1, 0, 'M'},
- {"leftmargin", 1, 0, 'L'},
- {"rightmargin", 1, 0, 'R'},
- {"topmargin", 1, 0, 'T'},
- {"bottommargin", 1, 0, 'B'},
- {"tight", 0, 0, OPT_TIGHT},
- {"rotate", 1, 0, 'A'},
- {"pagesize", 1, 0, 'P'},
- {"turdsize", 1, 0, 't'},
- {"unit", 1, 0, 'u'},
- {"cleartext", 0, 0, 'c'},
- {"level2", 0, 0, '2'},
- {"level3", 0, 0, '3'},
- {"eps", 0, 0, 'e'},
- {"postscript", 0, 0, 'p'},
- {"svg", 0, 0, 's'},
- {"pgm", 0, 0, 'g'},
- {"backend", 1, 0, 'b'},
- {"debug", 1, 0, 'd'},
- {"color", 1, 0, 'C'},
- {"fillcolor", 1, 0, OPT_FILLCOLOR},
- {"turnpolicy", 1, 0, 'z'},
- {"gamma", 1, 0, 'G'},
- {"longcurve", 0, 0, 'n'},
- {"longcoding", 0, 0, 'q'},
- {"alphamax", 1, 0, 'a'},
- {"opttolerance", 1, 0, 'O'},
- {"output", 1, 0, 'o'},
- {"blacklevel", 1, 0, 'k'},
- {"invert", 0, 0, 'i'},
- {"opaque", 0, 0, OPT_OPAQUE},
- {"group", 0, 0, OPT_GROUP},
- {"flat", 0, 0, OPT_FLAT},
- {"progress", 0, 0, OPT_PROGRESS},
- {"tty", 1, 0, OPT_TTY},
-
- {0, 0, 0, 0}
-};
-
-static const char *shortopts = "hvVlW:H:r:x:S:M:L:R:T:B:A:P:t:u:c23epsgb:d:C:z:G:nqa:O:o:k:i";
-
-static void dopts(int ac, char *av[]) {
- int c;
- char *p;
- int i, j, r;
- dim_t dim, dimx, dimy;
- int matches, bestmatch;
-
- /* defaults */
- backend_lookup("eps", &info.backend);
- info.debug = 0;
- info.width_d.x = UNDEF;
- info.height_d.x = UNDEF;
- info.rx = UNDEF;
- info.ry = UNDEF;
- info.sx = UNDEF;
- info.sy = UNDEF;
- info.stretch = 1;
- info.lmar_d.x = UNDEF;
- info.rmar_d.x = UNDEF;
- info.tmar_d.x = UNDEF;
- info.bmar_d.x = UNDEF;
- info.angle = 0;
- info.paperwidth = DEFAULT_PAPERWIDTH;
- info.paperheight = DEFAULT_PAPERHEIGHT;
- info.tight = 0;
- info.unit = 10;
- info.compress = 1;
- info.pslevel = 2;
- info.color = 0x000000;
- info.gamma = 2.2;
- info.param = potrace_param_default();
- if (!info.param) {
- fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
- exit(2);
- }
- info.longcoding = 0;
- info.outfile = NULL;
- info.blacklevel = 0.5;
- info.invert = 0;
- info.opaque = 0;
- info.grouping = 1;
- info.fillcolor = 0xffffff;
- info.progress = 0;
- info.progress_bar = DEFAULT_PROGRESS_BAR;
-
- while ((c = getopt_long(ac, av, shortopts, longopts, NULL)) != -1) {
- switch (c) {
- case 'h':
- fprintf(stdout, "" POTRACE " " VERSION ". Transforms bitmaps into vector graphics.\n\n");
- usage(stdout);
- exit(0);
- break;
- case 'v':
- case 'V':
- fprintf(stdout, "" POTRACE " " VERSION ". Copyright (C) 2001-2017 Peter Selinger.\n");
- fprintf(stdout, "Library version: %s\n", potrace_version());
- show_defaults(stdout);
- exit(0);
- break;
- case 'l':
- fprintf(stdout, "" POTRACE " " VERSION ". Copyright (C) 2001-2017 Peter Selinger.\n\n");
- license(stdout);
- exit(0);
- break;
- case 'W':
- info.width_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'H':
- info.height_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'r':
- parse_dimensions(optarg, &p, &dimx, &dimy);
- if (*p == 0 && dimx.d == 0 && dimy.d == 0 && dimx.x != 0.0 && dimy.x != 0.0) {
- info.rx = dimx.x;
- info.ry = dimy.x;
- break;
- }
- dim = parse_dimension(optarg, &p);
- if (*p == 0 && dim.d == 0 && dim.x != 0.0) {
- info.rx = info.ry = dim.x;
- break;
- }
- fprintf(stderr, "" POTRACE ": invalid resolution -- %s\n", optarg);
- exit(1);
- break;
- case 'x':
- parse_dimensions(optarg, &p, &dimx, &dimy);
- if (*p == 0 && dimx.d == 0 && dimy.d == 0) {
- info.sx = dimx.x;
- info.sy = dimy.x;
- break;
- }
- dim = parse_dimension(optarg, &p);
- if (*p == 0 && dim.d == 0) {
- info.sx = info.sy = dim.x;
- break;
- }
- fprintf(stderr, "" POTRACE ": invalid scaling factor -- %s\n", optarg);
- exit(1);
- break;
- case 'S':
- info.stretch = atof(optarg);
- break;
- case 'M':
- info.lmar_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- info.rmar_d = info.tmar_d = info.bmar_d = info.lmar_d;
- break;
- case 'L':
- info.lmar_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'R':
- info.rmar_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'T':
- info.tmar_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'B':
- info.bmar_d = parse_dimension(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
- exit(1);
- }
- break;
- case OPT_TIGHT:
- info.tight = 1;
- break;
- case 'A':
- info.angle = strtod(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid angle -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'P':
- matches = 0;
- bestmatch = 0;
- for (i=0; pageformat[i].name!=NULL; i++) {
- if (strcasecmp(pageformat[i].name, optarg)==0) {
- matches = 1;
- bestmatch = i;
- break;
- } else if (strncasecmp(pageformat[i].name, optarg, strlen(optarg))==0) {
- /* don't allow partial match on "10x14" */
- if (optarg[0] != '1') {
- matches++;
- bestmatch = i;
- }
- }
- }
- if (matches == 1) {
- info.paperwidth = pageformat[bestmatch].w;
- info.paperheight = pageformat[bestmatch].h;
- break;
- }
- parse_dimensions(optarg, &p, &dimx, &dimy);
- if (*p == 0) {
- info.paperwidth = (int)round(double_of_dim(dimx, DEFAULT_DIM));
- info.paperheight = (int)round(double_of_dim(dimy, DEFAULT_DIM));
- break;
- }
- if (matches == 0) {
- fprintf(stderr, "" POTRACE ": unrecognized page format -- %s\n", optarg);
- } else {
- fprintf(stderr, "" POTRACE ": ambiguous page format -- %s\n", optarg);
- }
- j = fprintf(stderr, "Use one of: ");
- for (i=0; pageformat[i].name!=NULL; i++) {
- if (j + strlen(pageformat[i].name) > 75) {
- fprintf(stderr, "\n");
- j = 0;
- }
- j += fprintf(stderr, "%s, ", pageformat[i].name);
- }
- fprintf(stderr, "or specify <dim>x<dim>.\n");
- exit(1);
- break;
- case 't':
- info.param->turdsize = atoi(optarg);
- break;
- case 'u':
- info.unit = strtod(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid unit -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'c':
- info.pslevel = 2;
- info.compress = 0;
- break;
- case '2':
- info.pslevel = 2;
- info.compress = 1;
- break;
- case '3':
-#ifdef HAVE_ZLIB
- info.pslevel = 3;
- info.compress = 1;
-#else
- fprintf(stderr, "" POTRACE ": option -3 not supported, using -2 instead.\n");
- fflush(stderr);
- info.pslevel = 2;
- info.compress = 1;
-#endif
- break;
- case 'e':
- backend_lookup("eps", &info.backend);
- break;
- case 'p':
- backend_lookup("postscript", &info.backend);
- break;
- case 's':
- backend_lookup("svg", &info.backend);
- break;
- case 'g':
- backend_lookup("pgm", &info.backend);
- break;
- case 'b':
- r = backend_lookup(optarg, &info.backend);
- if (r==1 || r==2) {
- if (r==1) {
- fprintf(stderr, "" POTRACE ": unrecognized backend -- %s\n", optarg);
- } else {
- fprintf(stderr, "" POTRACE ": ambiguous backend -- %s\n", optarg);
- }
- j = fprintf(stderr, "Use one of: ");
- backend_list(stderr, j, 70);
- fprintf(stderr, ".\n");
- exit(1);
- }
- break;
- case 'd':
- info.debug = atoi(optarg);
- break;
- case 'C':
- info.color = parse_color(optarg);
- if (info.color == -1) {
- fprintf(stderr, "" POTRACE ": invalid color -- %s\n", optarg);
- exit(1);
- }
- break;
- case OPT_FILLCOLOR:
- info.fillcolor = parse_color(optarg);
- if (info.fillcolor == -1) {
- fprintf(stderr, "" POTRACE ": invalid color -- %s\n", optarg);
- exit(1);
- }
- info.opaque = 1;
- break;
- case 'z':
- matches = 0;
- bestmatch = 0;
- for (i=0; turnpolicy[i].name!=NULL; i++) {
- if (strcasecmp(turnpolicy[i].name, optarg)==0) {
- matches = 1;
- bestmatch = i;
- break;
- } else if (strncasecmp(turnpolicy[i].name, optarg, strlen(optarg))==0) {
- matches++;
- bestmatch = i;
- }
- }
- if (matches == 1) {
- info.param->turnpolicy = turnpolicy[bestmatch].n;
- break;
- }
- if (matches == 0) {
- fprintf(stderr, "" POTRACE ": unrecognized turnpolicy -- %s\n", optarg);
- } else {
- fprintf(stderr, "" POTRACE ": ambiguous turnpolicy -- %s\n", optarg);
- }
- j = fprintf(stderr, "Use one of: ");
- for (i=0; turnpolicy[i].name!=NULL; i++) {
- if (j + strlen(turnpolicy[i].name) > 75) {
- fprintf(stderr, "\n");
- j = 0;
- }
- j += fprintf(stderr, "%s%s", turnpolicy[i].name, turnpolicy[i+1].name ? ", " : "");
- }
- fprintf(stderr, ".\n");
- exit(1);
- break;
- case 'G':
- info.gamma = atof(optarg);
- break;
- case 'n':
- info.param->opticurve = 0;
- break;
- case 'q':
- info.longcoding = 1;
- break;
- case 'a':
- info.param->alphamax = strtod(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid alphamax -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'O':
- info.param->opttolerance = strtod(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid opttolerance -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'o':
- free(info.outfile);
- info.outfile = strdup(optarg);
- if (!info.outfile) {
- fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
- exit(2);
- }
- break;
- case 'k':
- info.blacklevel = strtod(optarg, &p);
- if (*p) {
- fprintf(stderr, "" POTRACE ": invalid blacklevel -- %s\n", optarg);
- exit(1);
- }
- break;
- case 'i':
- info.invert = 1;
- break;
- case OPT_OPAQUE:
- info.opaque = 1;
- break;
- case OPT_GROUP:
- info.grouping = 2;
- break;
- case OPT_FLAT:
- info.grouping = 0;
- break;
- case OPT_PROGRESS:
- info.progress = 1;
- break;
- case OPT_TTY:
- if (strcmp(optarg, "dumb") == 0) {
- info.progress_bar = progress_bar_simplified;
- } else if (strcmp(optarg, "vt100") == 0) {
- info.progress_bar = progress_bar_vt100;
- } else {
- fprintf(stderr, "" POTRACE ": invalid tty mode -- %s. Try --help for more info\n", optarg);
- exit(1);
- }
- break;
- case '?':
- fprintf(stderr, "Try --help for more info\n");
- exit(1);
- break;
- default:
- fprintf(stderr, "" POTRACE ": Unimplemented option -- %c\n", c);
- exit(1);
- }
- }
- info.infiles = &av[optind];
- info.infilecount = ac-optind;
- info.some_infiles = info.infilecount ? 1 : 0;
-
- /* if "--" was used, even an empty list of filenames is considered
- "some" filenames. */
- if (strcmp(av[optind-1], "--") == 0) {
- info.some_infiles = 1;
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/* calculations with bitmap dimensions, positioning etc */
-
-/* determine the dimensions of the output based on command line and
- image dimensions, and optionally, based on the actual image outline. */
-static void calc_dimensions(imginfo_t *imginfo, potrace_path_t *plist) {
- double dim_def;
- double maxwidth, maxheight, sc;
- int default_scaling = 0;
-
- /* we take care of a special case: if one of the image dimensions is
- 0, we change it to 1. Such an image is empty anyway, so there
- will be 0 paths in it. Changing the dimensions avoids division by
- 0 error in calculating scaling factors, bounding boxes and
- such. This doesn't quite do the right thing in all cases, but it
- is better than causing overflow errors or "nan" output in
- backends. Human users don't tend to process images of size 0
- anyway; they might occur in some pipelines. */
- if (imginfo->pixwidth == 0) {
- imginfo->pixwidth = 1;
- }
- if (imginfo->pixheight == 0) {
- imginfo->pixheight = 1;
- }
-
- /* set the default dimension for width, height, margins */
- if (info.backend->pixel) {
- dim_def = DIM_PT;
- } else {
- dim_def = DEFAULT_DIM;
- }
-
- /* apply default dimension to width, height, margins */
- imginfo->width = info.width_d.x == UNDEF ? UNDEF : double_of_dim(info.width_d, dim_def);
- imginfo->height = info.height_d.x == UNDEF ? UNDEF : double_of_dim(info.height_d, dim_def);
- imginfo->lmar = info.lmar_d.x == UNDEF ? UNDEF : double_of_dim(info.lmar_d, dim_def);
- imginfo->rmar = info.rmar_d.x == UNDEF ? UNDEF : double_of_dim(info.rmar_d, dim_def);
- imginfo->tmar = info.tmar_d.x == UNDEF ? UNDEF : double_of_dim(info.tmar_d, dim_def);
- imginfo->bmar = info.bmar_d.x == UNDEF ? UNDEF : double_of_dim(info.bmar_d, dim_def);
-
- /* start with a standard rectangle */
- trans_from_rect(&imginfo->trans, imginfo->pixwidth, imginfo->pixheight);
-
- /* if info.tight is set, tighten the bounding box */
- if (info.tight) {
- trans_tighten(&imginfo->trans, plist);
- }
-
- /* sx/rx is just an alternate way to specify width; sy/ry is just an
- alternate way to specify height. */
- if (info.backend->pixel) {
- if (imginfo->width == UNDEF && info.sx != UNDEF) {
- imginfo->width = imginfo->trans.bb[0] * info.sx;
- }
- if (imginfo->height == UNDEF && info.sy != UNDEF) {
- imginfo->height = imginfo->trans.bb[1] * info.sy;
- }
- } else {
- if (imginfo->width == UNDEF && info.rx != UNDEF) {
- imginfo->width = imginfo->trans.bb[0] / info.rx * 72;
- }
- if (imginfo->height == UNDEF && info.ry != UNDEF) {
- imginfo->height = imginfo->trans.bb[1] / info.ry * 72;
- }
- }
-
- /* if one of width/height is specified, use stretch to determine the
- other */
- if (imginfo->width == UNDEF && imginfo->height != UNDEF) {
- imginfo->width = imginfo->height / imginfo->trans.bb[1] * imginfo->trans.bb[0] / info.stretch;
- } else if (imginfo->width != UNDEF && imginfo->height == UNDEF) {
- imginfo->height = imginfo->width / imginfo->trans.bb[0] * imginfo->trans.bb[1] * info.stretch;
- }
-
- /* if width and height are still variable, tenatively use the
- default scaling factor of 72dpi (for dimension-based backends) or
- 1 (for pixel-based backends). For fixed-size backends, this will
- be adjusted later to fit the page. */
- if (imginfo->width == UNDEF && imginfo->height == UNDEF) {
- imginfo->width = imginfo->trans.bb[0];
- imginfo->height = imginfo->trans.bb[1] * info.stretch;
- default_scaling = 1;
- }
-
- /* apply scaling */
- trans_scale_to_size(&imginfo->trans, imginfo->width, imginfo->height);
-
- /* apply rotation, and tighten the bounding box again, if necessary */
- if (info.angle != 0.0) {
- trans_rotate(&imginfo->trans, info.angle);
- if (info.tight) {
- trans_tighten(&imginfo->trans, plist);
- }
- }
-
- /* for fixed-size backends, if default scaling was in effect,
- further adjust the scaling to be the "best fit" for the given
- page size and margins. */
- if (default_scaling && info.backend->fixed) {
-
- /* try to squeeze it between margins */
- maxwidth = UNDEF;
- maxheight = UNDEF;
-
- if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
- maxwidth = info.paperwidth - imginfo->lmar - imginfo->rmar;
- }
- if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
- maxheight = info.paperheight - imginfo->bmar - imginfo->tmar;
- }
- if (maxwidth == UNDEF && maxheight == UNDEF) {
- maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
- maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
- }
-
- if (maxwidth == UNDEF) {
- sc = maxheight / imginfo->trans.bb[1];
- } else if (maxheight == UNDEF) {
- sc = maxwidth / imginfo->trans.bb[0];
- } else {
- sc = min(maxwidth / imginfo->trans.bb[0], maxheight / imginfo->trans.bb[1]);
- }
-
- /* re-scale coordinate system */
- imginfo->width *= sc;
- imginfo->height *= sc;
- trans_rescale(&imginfo->trans, sc);
- }
-
- /* adjust margins */
- if (info.backend->fixed) {
- if (imginfo->lmar == UNDEF && imginfo->rmar == UNDEF) {
- imginfo->lmar = (info.paperwidth-imginfo->trans.bb[0])/2;
- } else if (imginfo->lmar == UNDEF) {
- imginfo->lmar = (info.paperwidth-imginfo->trans.bb[0]-imginfo->rmar);
- } else if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
- imginfo->lmar += (info.paperwidth-imginfo->trans.bb[0]-imginfo->lmar-imginfo->rmar)/2;
- }
- if (imginfo->bmar == UNDEF && imginfo->tmar == UNDEF) {
- imginfo->bmar = (info.paperheight-imginfo->trans.bb[1])/2;
- } else if (imginfo->bmar == UNDEF) {
- imginfo->bmar = (info.paperheight-imginfo->trans.bb[1]-imginfo->tmar);
- } else if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
- imginfo->bmar += (info.paperheight-imginfo->trans.bb[1]-imginfo->bmar-imginfo->tmar)/2;
- }
- } else {
- if (imginfo->lmar == UNDEF) {
- imginfo->lmar = 0;
- }
- if (imginfo->rmar == UNDEF) {
- imginfo->rmar = 0;
- }
- if (imginfo->bmar == UNDEF) {
- imginfo->bmar = 0;
- }
- if (imginfo->tmar == UNDEF) {
- imginfo->tmar = 0;
- }
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/* auxiliary functions for file handling */
-
-/* open a file for reading. Return stdin if filename is NULL or "-" */
-static FILE *my_fopen_read(const char *filename) {
- if (filename == NULL || strcmp(filename, "-") == 0) {
- return stdin;
- }
- return fopen(filename, "rb");
-}
-
-/* open a file for writing. Return stdout if filename is NULL or "-" */
-static FILE *my_fopen_write(const char *filename) {
- if (filename == NULL || strcmp(filename, "-") == 0) {
- return stdout;
- }
- return fopen(filename, "wb");
-}
-
-/* close a file, but do nothing is filename is NULL or "-" */
-static void my_fclose(FILE *f, const char *filename) {
- if (filename == NULL || strcmp(filename, "-") == 0) {
- return;
- }
- fclose(f);
-}
-
-/* make output filename from input filename. Return an allocated value. */
-static char *make_outfilename(const char *infile, const char *ext) {
- char *outfile;
- char *p;
-
- if (strcmp(infile, "-") == 0) {
- return strdup("-");
- }
-
- outfile = (char *) malloc(strlen(infile)+strlen(ext)+5);
- if (!outfile) {
- return NULL;
- }
- strcpy(outfile, infile);
- p = strrchr(outfile, '.');
- if (p) {
- *p = 0;
- }
- strcat(outfile, ext);
-
- /* check that input and output filenames are different */
- if (strcmp(infile, outfile) == 0) {
- strcpy(outfile, infile);
- strcat(outfile, "-out");
- }
-
- return outfile;
-}
-
-/* ---------------------------------------------------------------------- */
-/* Process one infile */
-
-/* Process one or more bitmaps from fin, and write the results to fout
- using the page_f function of the appropriate backend. */
-
-static void process_file(backend_t *b, const char *infile, const char *outfile, FILE *fin, FILE *fout) {
- int r;
- potrace_bitmap_t *bm = NULL;
- imginfo_t imginfo;
- int eof_flag = 0; /* to indicate premature eof */
- int count; /* number of bitmaps successfully processed, this file */
- potrace_state_t *st;
-
- for (count=0; ; count++) {
- /* read a bitmap */
- r = bm_read(fin, info.blacklevel, &bm);
- switch (r) {
- case -1: /* system error */
- fprintf(stderr, "" POTRACE ": %s: %s\n", infile, strerror(errno));
- exit(2);
- case -2: /* corrupt file format */
- fprintf(stderr, "" POTRACE ": %s: file format error: %s\n", infile, bm_read_error);
- exit(2);
- case -3: /* empty file */
- if (count>0) { /* end of file */
- return;
- }
- fprintf(stderr, "" POTRACE ": %s: empty file\n", infile);
- exit(2);
- case -4: /* wrong magic */
- if (count>0) {
- fprintf(stderr, "" POTRACE ": %s: warning: junk at end of file\n", infile);
- return;
- }
- fprintf(stderr, "" POTRACE ": %s: file format not recognized\n", infile);
- fprintf(stderr, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
- exit(2);
- case 1: /* unexpected end of file */
- fprintf(stderr, "" POTRACE ": warning: %s: premature end of file\n", infile);
- eof_flag = 1;
- break;
- }
-
- /* prepare progress bar, if requested */
- if (info.progress) {
- r = info.progress_bar->init(&info.param->progress, infile, count);
- if (r) {
- fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
- exit(2);
- }
- } else {
- info.param->progress.callback = NULL;
- }
-
- if (info.invert) {
- bm_invert(bm);
- }
-
- /* process the image */
- st = potrace_trace(info.param, bm);
- if (!st || st->status != POTRACE_STATUS_OK) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", infile, strerror(errno));
- exit(2);
- }
-
- /* calculate image dimensions */
- imginfo.pixwidth = bm->w;
- imginfo.pixheight = bm->h;
- bm_free(bm);
-
- calc_dimensions(&imginfo, st->plist);
-
- r = b->page_f(fout, st->plist, &imginfo);
- if (r) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", outfile, strerror(errno));
- exit(2);
- }
-
- potrace_state_free(st);
-
- if (info.progress) {
- info.progress_bar->term(&info.param->progress);
- }
-
- if (eof_flag || !b->multi) {
- return;
- }
- }
- /* not reached */
-}
-
-/* ---------------------------------------------------------------------- */
-/* main: handle file i/o */
-
-#define TRY(x) if (x) goto try_error
-
-int main(int ac, char *av[]) {
- backend_t *b; /* backend info */
- FILE *fin, *fout;
- int i;
- char *outfile;
-
- /* platform-specific initializations, e.g., set file i/o to binary */
- platform_init();
-
- /* process options */
- dopts(ac, av);
-
- b = info.backend;
- if (b==NULL) {
- fprintf(stderr, "" POTRACE ": internal error: selected backend not found\n");
- exit(1);
- }
-
- /* fix some parameters */
- /* if backend cannot handle opticurve, disable it */
- if (b->opticurve == 0) {
- info.param->opticurve = 0;
- }
-
- /* there are several ways to call us:
- potrace -- stdin to stdout
- potrace -o outfile -- stdin to outfile
- potrace file... -- encode each file and generate outfile names
- potrace -o outfile file... -- concatenate files and write to outfile
-
- The latter form is only allowed one file for single-page
- backends. For multi-page backends, each file must contain 0 or
- more complete bitmaps.
- */
-
- if (!info.some_infiles) { /* read from stdin */
-
- fout = my_fopen_write(info.outfile);
- if (!fout) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", info.outfile ? info.outfile : "stdout", strerror(errno));
- exit(2);
- }
- if (b->init_f) {
- TRY(b->init_f(fout));
- }
- process_file(b, "stdin", info.outfile ? info.outfile : "stdout", stdin, fout);
- if (b->term_f) {
- TRY(b->term_f(fout));
- }
- my_fclose(fout, info.outfile);
- free(info.outfile);
- potrace_param_free(info.param);
- return 0;
-
- } else if (!info.outfile) { /* infiles -> multiple outfiles */
-
- for (i=0; i<info.infilecount; i++) {
- outfile = make_outfilename(info.infiles[i], b->ext);
- if (!outfile) {
- fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
- exit(2);
- }
- fin = my_fopen_read(info.infiles[i]);
- if (!fin) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", info.infiles[i], strerror(errno));
- exit(2);
- }
- fout = my_fopen_write(outfile);
- if (!fout) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", outfile, strerror(errno));
- exit(2);
- }
- if (b->init_f) {
- TRY(b->init_f(fout));
- }
- process_file(b, info.infiles[i], outfile, fin, fout);
- if (b->term_f) {
- TRY(b->term_f(fout));
- }
- my_fclose(fin, info.infiles[i]);
- my_fclose(fout, outfile);
- free(outfile);
- }
- potrace_param_free(info.param);
- return 0;
-
- } else { /* infiles to single outfile */
-
- if (!b->multi && info.infilecount >= 2) {
- fprintf(stderr, "" POTRACE ": cannot use multiple input files with -o in %s mode\n", b->name);
- exit(1);
- }
- if (info.infilecount == 0) {
- fprintf(stderr, "" POTRACE ": cannot use empty list of input files with -o\n");
- exit(1);
- }
-
- fout = my_fopen_write(info.outfile);
- if (!fout) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", info.outfile, strerror(errno));
- exit(2);
- }
- if (b->init_f) {
- TRY(b->init_f(fout));
- }
- for (i=0; i<info.infilecount; i++) {
- fin = my_fopen_read(info.infiles[i]);
- if (!fin) {
- fprintf(stderr, "" POTRACE ": %s: %s\n", info.infiles[i], strerror(errno));
- exit(2);
- }
- process_file(b, info.infiles[i], info.outfile, fin, fout);
- my_fclose(fin, info.infiles[i]);
- }
- if (b->term_f) {
- TRY(b->term_f(fout));
- }
- my_fclose(fout, info.outfile);
- free(info.outfile);
- potrace_param_free(info.param);
- return 0;
-
- }
-
- /* not reached */
-
- try_error:
- fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
- exit(2);
-}