diff options
| author | Nicolas Dufour <nicoduf@yahoo.fr> | 2011-04-14 06:29:21 +0000 |
|---|---|---|
| committer | JazzyNico <nicoduf@yahoo.fr> | 2011-04-14 06:29:21 +0000 |
| commit | de76d854317e700b1f0297c83f6a1cacc2ffa533 (patch) | |
| tree | 097e2cafc1ee46bc4aa1b9694626273fc1a3fdae /src | |
| parent | add expression evaluator for spinbox input boxes. also knows a little about u... (diff) | |
| download | inkscape-de76d854317e700b1f0297c83f6a1cacc2ffa533.tar.gz inkscape-de76d854317e700b1f0297c83f6a1cacc2ffa533.zip | |
Tracing. Potrace 1.9 update (see http://potrace.sourceforge.net/ChangeLog).
(bzr r10163)
Diffstat (limited to 'src')
| -rw-r--r-- | src/trace/potrace/auxiliary.h | 29 | ||||
| -rw-r--r-- | src/trace/potrace/bitmap.h | 6 | ||||
| -rw-r--r-- | src/trace/potrace/curve.cpp | 4 | ||||
| -rw-r--r-- | src/trace/potrace/curve.h | 2 | ||||
| -rw-r--r-- | src/trace/potrace/decompose.cpp | 50 | ||||
| -rw-r--r-- | src/trace/potrace/decompose.h | 5 | ||||
| -rw-r--r-- | src/trace/potrace/greymap.cpp | 52 | ||||
| -rw-r--r-- | src/trace/potrace/greymap.h | 10 | ||||
| -rw-r--r-- | src/trace/potrace/lists.h | 4 | ||||
| -rw-r--r-- | src/trace/potrace/potracelib.cpp | 9 | ||||
| -rw-r--r-- | src/trace/potrace/potracelib.h | 12 | ||||
| -rw-r--r-- | src/trace/potrace/progress.h | 8 | ||||
| -rw-r--r-- | src/trace/potrace/render.cpp | 4 | ||||
| -rw-r--r-- | src/trace/potrace/render.h | 4 | ||||
| -rw-r--r-- | src/trace/potrace/trace.cpp | 90 | ||||
| -rw-r--r-- | src/trace/potrace/trace.h | 5 |
16 files changed, 166 insertions, 128 deletions
diff --git a/src/trace/potrace/auxiliary.h b/src/trace/potrace/auxiliary.h index 7baab851c..1c2765816 100644 --- a/src/trace/potrace/auxiliary.h +++ b/src/trace/potrace/auxiliary.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ @@ -75,4 +75,31 @@ static inline int floordiv(int a, int n) { #define sq(a) ((a)*(a)) #define cu(a) ((a)*(a)*(a)) +/* ---------------------------------------------------------------------- */ +/* deterministically and efficiently hash (x,y) into a pseudo-random bit */ +static inline int detrand(int x, int y) { + unsigned int z; + static const unsigned char t[256] = { + /* non-linear sequence: constant term of inverse in GF(8), + mod x^8+x^4+x^3+x+1 */ + 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, + 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + }; + + /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible + 5-bit sequence */ + z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93; + z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff]; + return z; +} + #endif /* AUXILIARY_H */ diff --git a/src/trace/potrace/bitmap.h b/src/trace/potrace/bitmap.h index 2a172b1ad..671382dc2 100644 --- a/src/trace/potrace/bitmap.h +++ b/src/trace/potrace/bitmap.h @@ -1,14 +1,10 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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 BITMAP_H #define BITMAP_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdlib.h> diff --git a/src/trace/potrace/curve.cpp b/src/trace/potrace/curve.cpp index c9a6fbe04..00d7bd2db 100644 --- a/src/trace/potrace/curve.cpp +++ b/src/trace/potrace/curve.cpp @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: curve.c 227 2010-12-16 05:47:19Z selinger $ */ /* private part of the path and curve data structures */ #include <stdio.h> diff --git a/src/trace/potrace/curve.h b/src/trace/potrace/curve.h index 45c0790be..bfde0af1a 100644 --- a/src/trace/potrace/curve.h +++ b/src/trace/potrace/curve.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ diff --git a/src/trace/potrace/decompose.cpp b/src/trace/potrace/decompose.cpp index 15c39825e..8219234c4 100644 --- a/src/trace/potrace/decompose.cpp +++ b/src/trace/potrace/decompose.cpp @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: decompose.c 227 2010-12-16 05:47:19Z selinger $ */ #include <stdio.h> #include <stdlib.h> @@ -55,32 +55,6 @@ static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) { /* ---------------------------------------------------------------------- */ /* auxiliary functions */ -/* deterministically and efficiently hash (x,y) into a pseudo-random bit */ -static inline int detrand(int x, int y) { - unsigned int z; - static const unsigned char t[256] = { - /* non-linear sequence: constant term of inverse in GF(8), - mod x^8+x^4+x^3+x+1 */ - 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, - 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, - 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, - 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, - 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, - 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - }; - - /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible - 5-bit sequence */ - z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93; - z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff]; - return z & 1; -} - /* return the "majority" value of bitmap bm at intersection (x,y). We assume that the bitmap is balanced at "radius" 1. */ static int majority(potrace_bitmap_t *bm, int x, int y) { @@ -304,7 +278,8 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) { path_t *heap, *heap1; path_t *cur; path_t *head; - path_t **hook, **hook_in, **hook_out; /* for fast appending to linked list */ + path_t **plist_hook; /* for fast appending to linked list */ + path_t **hook_in, **hook_out; /* for fast appending to linked list */ bbox_t bbox; bm_clear(bm, 0); @@ -391,18 +366,18 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) { heap->next = NULL; /* heap is a linked list of childlists */ } plist = NULL; - hook = &plist; + plist_hook = &plist; while (heap) { heap1 = heap->next; for (p=heap; p; p=p->sibling) { /* p is a positive path */ /* append to linked list */ - list_insert_beforehook(p, hook); + list_insert_beforehook(p, plist_hook); /* go through its children */ for (p1=p->childlist; p1; p1=p1->sibling) { /* append to linked list */ - list_insert_beforehook(p1, hook); + list_insert_beforehook(p1, plist_hook); /* append its childlist to heap, if non-empty */ if (p1->childlist) { list_append(path_t, heap1, p1->childlist); @@ -423,9 +398,12 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) { static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) { int x; int y; + int x0; + + x0 = (*xp) & ~(BM_WORDBITS-1); for (y=*yp; y>=0; y--) { - for (x=0; x<bm->w; x+=BM_WORDBITS) { + for (x=x0; x<bm->w; x+=BM_WORDBITS) { if (*bm_index(bm, x, y)) { while (!BM_GET(bm, x, y)) { x++; @@ -436,6 +414,7 @@ static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) { return 0; } } + x0 = 0; } /* not found */ return 1; @@ -451,7 +430,7 @@ int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_pa int y; path_t *p; path_t *plist = NULL; /* linked list of path objects */ - path_t **hook = &plist; /* used to speed up appending to linked list */ + path_t **plist_hook = &plist; /* used to speed up appending to linked list */ potrace_bitmap_t *bm1 = NULL; int sign; @@ -465,6 +444,7 @@ int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_pa bm_clearexcess(bm1); /* iterate through components */ + x = 0; y = bm1->h - 1; while (findnext(bm1, &x, &y) == 0) { /* calculate the sign by looking at the original */ @@ -483,7 +463,7 @@ int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_pa if (p->area <= param->turdsize) { path_free(p); } else { - list_insert_beforehook(p, hook); + list_insert_beforehook(p, plist_hook); } if (bm1->h > 0) { /* to be sure */ diff --git a/src/trace/potrace/decompose.h b/src/trace/potrace/decompose.h index 5552fa0a1..409439c62 100644 --- a/src/trace/potrace/decompose.h +++ b/src/trace/potrace/decompose.h @@ -1,14 +1,15 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: decompose.h 227 2010-12-16 05:47:19Z selinger $ */ #ifndef DECOMPOSE_H #define DECOMPOSE_H #include "potracelib.h" #include "progress.h" +#include "curve.h" int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress); diff --git a/src/trace/potrace/greymap.cpp b/src/trace/potrace/greymap.cpp index 646ecc3a5..770dd72e6 100644 --- a/src/trace/potrace/greymap.cpp +++ b/src/trace/potrace/greymap.cpp @@ -1,14 +1,13 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: greymap.c 227 2010-12-16 05:47:19Z selinger $ */ /* Routines for manipulating greymaps, including reading pgm files. We only deal with greymaps of depth 8 bits. */ #include <stdlib.h> -#include <errno.h> #include <string.h> #include <math.h> @@ -28,7 +27,6 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp); greymap_t *gm_new(int w, int h) { greymap_t *gm; - int errno_save; gm = (greymap_t *) malloc(sizeof(greymap_t)); if (!gm) { @@ -38,9 +36,7 @@ greymap_t *gm_new(int w, int h) { gm->h = h; gm->map = (signed short int *) malloc(w*h*sizeof(signed short int)); if (!gm->map) { - errno_save = errno; free(gm); - errno = errno_save; return NULL; } return gm; @@ -60,7 +56,7 @@ greymap_t *gm_dup(greymap_t *gm) { if (!gm1) { return NULL; } - memcpy(gm1->map, gm->map, gm->w*gm->h*2); + memcpy(gm1->map, gm->map, gm->w*gm->h*sizeof(signed short int)); return gm1; } @@ -69,7 +65,7 @@ void gm_clear(greymap_t *gm, int b) { int i; if (b==0) { - memset(gm->map, 0, gm->w*gm->h*2); + memset(gm->map, 0, gm->w*gm->h*sizeof(signed short int)); } else { for (i=0; i<gm->w*gm->h; i++) { gm->map[i] = b; @@ -161,16 +157,16 @@ static int readbit(FILE *f) { /* ---------------------------------------------------------------------- */ -char const *gm_read_error = NULL; - -/** Read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and +/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and convert the output to a greymap. Return greymap in *gmp. Return 0 on success, -1 on error with errno set, -2 on bad file format (with error message in gm_read_error), and 1 on premature end of file, -3 on empty file (including files with only whitespace and comments), -4 if wrong magic number. If the return value is >=0, *gmp is - valid. - */ + valid. */ + +char const *gm_read_error = NULL; + int gm_read(FILE *f, greymap_t **gmp) { int magic[2]; @@ -413,6 +409,7 @@ struct bmp_info_s { unsigned int ncolors; /* number of colors in palette */ unsigned int ColorsImportant; unsigned int ctbits; /* sample size for color table */ + int topdown; /* top-down mode? */ }; typedef struct bmp_info_s bmp_info_t; @@ -481,6 +478,9 @@ static int bmp_forward(FILE *f, int pos) { #define TRY(x) if (x) goto try_error #define TRY_EOF(x) if (x) goto eof +/* correct y-coordinate for top-down format */ +#define ycorr(y) (bmpinfo.topdown ? bmpinfo.h-1-y : y) + /* read BMP stream after magic number. Return values as for gm_read. We choose to be as permissive as possible, since there are many programs out there which produce BMP. For instance, ppmtobmp can @@ -512,7 +512,8 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { /* info header */ TRY(bmp_readint(f, 4, &bmpinfo.InfoSize)); - if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64) { + if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64 + || bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124) { /* Windows or new OS/2 format */ bmpinfo.ctbits = 32; /* sample size in color table */ TRY(bmp_readint(f, 4, &bmpinfo.w)); @@ -525,6 +526,12 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM)); TRY(bmp_readint(f, 4, &bmpinfo.ncolors)); TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant)); + if ((signed int)bmpinfo.h < 0) { + bmpinfo.h = -bmpinfo.h; + bmpinfo.topdown = 1; + } else { + bmpinfo.topdown = 0; + } } else if (bmpinfo.InfoSize == 12) { /* old OS/2 format */ bmpinfo.ctbits = 24; /* sample size in color table */ @@ -534,11 +541,12 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { TRY(bmp_readint(f, 2, &bmpinfo.bits)); bmpinfo.comp = 0; bmpinfo.ncolors = 0; + bmpinfo.topdown = 0; } else { goto format_error; } - /* forward to color table (i.e., if bmpinfo.InfoSize == 64) */ + /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */ TRY(bmp_forward(f, 14+bmpinfo.InfoSize)); if (bmpinfo.Planes != 1) { @@ -593,7 +601,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { for (i=0; 8*i<bmpinfo.w; i++) { TRY_EOF(bmp_readint(f, 1, &b)); for (j=0; j<8; j++) { - GM_PUT(gm, i*8+j, y, b & (0x80 >> j) ? coltable[1] : coltable[0]); + GM_PUT(gm, i*8+j, ycorr(y), b & (0x80 >> j) ? coltable[1] : coltable[0]); } } TRY(bmp_pad(f)); @@ -620,7 +628,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { b = bitbuf >> (INTBITS - bmpinfo.bits); bitbuf <<= bmpinfo.bits; n -= bmpinfo.bits; - GM_UPUT(gm, x, y, coltable[b]); + GM_UPUT(gm, x, ycorr(y), coltable[b]); } TRY(bmp_pad(f)); } @@ -640,7 +648,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { for (x=0; x<bmpinfo.w; x++) { TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c)); c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff); - GM_UPUT(gm, x, y, c/3); + GM_UPUT(gm, x, ycorr(y), c/3); } TRY(bmp_pad(f)); } @@ -664,7 +672,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { if (y>=bmpinfo.h) { break; } - GM_UPUT(gm, x, y, col[i&1]); + GM_UPUT(gm, x, ycorr(y), col[i&1]); x++; } } else if (c == 0) { @@ -693,7 +701,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { if (y>=bmpinfo.h) { break; } - GM_PUT(gm, x, y, coltable[(b>>(4-4*(i&1))) & 0xf]); + GM_PUT(gm, x, ycorr(y), coltable[(b>>(4-4*(i&1))) & 0xf]); x++; } if ((c+1) & 2) { @@ -720,7 +728,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { if (y>=bmpinfo.h) { break; } - GM_UPUT(gm, x, y, coltable[c]); + GM_UPUT(gm, x, ycorr(y), coltable[c]); x++; } } else if (c == 0) { @@ -747,7 +755,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) { if (y>=bmpinfo.h) { break; } - GM_PUT(gm, x, y, coltable[b]); + GM_PUT(gm, x, ycorr(y), coltable[b]); x++; } if (c & 1) { diff --git a/src/trace/potrace/greymap.h b/src/trace/potrace/greymap.h index 059fec4e4..0736232a7 100644 --- a/src/trace/potrace/greymap.h +++ b/src/trace/potrace/greymap.h @@ -1,11 +1,11 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: greymap.h 227 2010-12-16 05:47:19Z selinger $ */ -#ifndef PGM_H -#define PGM_H +#ifndef GREYMAP_H +#define GREYMAP_H #include <stdio.h> @@ -55,4 +55,4 @@ int gm_read(FILE *f, greymap_t **gmp); int gm_writepgm(FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma); int gm_print(FILE *f, greymap_t *gm); -#endif /* PGM_H */ +#endif /* GREYMAP_H */ diff --git a/src/trace/potrace/lists.h b/src/trace/potrace/lists.h index fc853398a..4f78bf20f 100644 --- a/src/trace/potrace/lists.h +++ b/src/trace/potrace/lists.h @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: lists.h 227 2010-12-16 05:47:19Z selinger $ */ #ifndef _PS_LISTS_H #define _PS_LISTS_H diff --git a/src/trace/potrace/potracelib.cpp b/src/trace/potrace/potracelib.cpp index 17e04cabb..3dbf3230b 100644 --- a/src/trace/potrace/potracelib.cpp +++ b/src/trace/potrace/potracelib.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ @@ -48,15 +48,16 @@ potrace_param_t *potrace_param_default(void) { /* On success, returns a Potrace state st with st->status == POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state could be created (with errno set), or returns an incomplete Potrace - state (with st->status == POTRACE_STATUS_INCOMPLETE). Complete or - incomplete Potrace state can be freed with potrace_state_free(). */ + state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno + set). Complete or incomplete Potrace state can be freed with + potrace_state_free(). */ potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) { int r; path_t *plist = NULL; potrace_state_t *st; progress_t prog; progress_t subprog; - + /* prepare private progress bar state */ prog.callback = param->progress.callback; prog.data = param->progress.data; diff --git a/src/trace/potrace/potracelib.h b/src/trace/potrace/potracelib.h index 0b93d65de..d15b05e5c 100644 --- a/src/trace/potrace/potracelib.h +++ b/src/trace/potrace/potracelib.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ @@ -6,7 +6,11 @@ #define POTRACELIB_H /* this file defines the API for the core Potrace library. For a more - detailed description of the API, see doc/potracelib.txt */ + detailed description of the API, see potracelib.pdf */ + +#ifdef __cplusplus +extern "C" { +#endif /* ---------------------------------------------------------------------- */ /* tracing parameters */ @@ -128,4 +132,8 @@ void potrace_state_free(potrace_state_t *st); of potracelib */ char *potrace_version(void); +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + #endif /* POTRACELIB_H */ diff --git a/src/trace/potrace/progress.h b/src/trace/potrace/progress.h index 0e077430d..220639c6e 100644 --- a/src/trace/potrace/progress.h +++ b/src/trace/potrace/progress.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ @@ -28,7 +28,7 @@ typedef struct progress_s progress_t; static inline void progress_update(double d, progress_t *prog) { double d_scaled; - if (prog->callback != NULL) { + if (prog != NULL && prog->callback != NULL) { d_scaled = prog->min * (1-d) + prog->max * d; if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) { prog->callback(prog->min * (1-d) + prog->max * d, prog->data); @@ -43,7 +43,7 @@ static inline void progress_update(double d, progress_t *prog) { static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) { double min, max; - if (prog->callback == NULL) { + if (prog == NULL || prog->callback == NULL) { sub->callback = NULL; return; } @@ -66,7 +66,7 @@ static inline void progress_subrange_start(double a, double b, const progress_t } static inline void progress_subrange_end(progress_t *prog, progress_t *sub) { - if (prog->callback != NULL) { + if (prog != NULL && prog->callback != NULL) { if (sub->callback == NULL) { progress_update(sub->b, prog); } else { diff --git a/src/trace/potrace/render.cpp b/src/trace/potrace/render.cpp index f9183b931..39bec0684 100644 --- a/src/trace/potrace/render.cpp +++ b/src/trace/potrace/render.cpp @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: render.c 227 2010-12-16 05:47:19Z selinger $ */ #include <stdio.h> #include <stdlib.h> diff --git a/src/trace/potrace/render.h b/src/trace/potrace/render.h index 9c9d921d2..6cfbe0964 100644 --- a/src/trace/potrace/render.h +++ b/src/trace/potrace/render.h @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: render.h 227 2010-12-16 05:47:19Z selinger $ */ #ifndef RENDER_H #define RENDER_H diff --git a/src/trace/potrace/trace.cpp b/src/trace/potrace/trace.cpp index 909ffb712..8fe1a1bc4 100644 --- a/src/trace/potrace/trace.cpp +++ b/src/trace/potrace/trace.cpp @@ -1,8 +1,8 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: trace.c 227 2010-12-16 05:47:19Z selinger $ */ /* transform jaggy paths into smooth curves */ #include <stdio.h> @@ -483,28 +483,38 @@ static double penalty3(privpath_t *pp, int i, int j) { double a, b, c, s; double px, py, ex, ey; - int r=0; /* rotations from i to j */ + int r = 0; /* rotations from i to j */ if (j>=n) { - j-=n; - r+=1; + j -= n; + r = 1; } - x = sums[j+1].x-sums[i].x+r*sums[n].x; - y = sums[j+1].y-sums[i].y+r*sums[n].y; - x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2; - xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy; - y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2; - k = j+1-i+r*n; - - px = (pt[i].x+pt[j].x)/2.0-pt[0].x; - py = (pt[i].y+pt[j].y)/2.0-pt[0].y; - ey = (pt[j].x-pt[i].x); - ex = -(pt[j].y-pt[i].y); - - a = ((x2-2*x*px)/k+px*px); - b = ((xy-x*py-y*px)/k+px*py); - c = ((y2-2*y*py)/k+py*py); + /* critical inner loop: the "if" gives a 4.6 percent speedup */ + if (r == 0) { + x = sums[j+1].x - sums[i].x; + y = sums[j+1].y - sums[i].y; + x2 = sums[j+1].x2 - sums[i].x2; + xy = sums[j+1].xy - sums[i].xy; + y2 = sums[j+1].y2 - sums[i].y2; + k = j+1 - i; + } else { + x = sums[j+1].x - sums[i].x + sums[n].x; + y = sums[j+1].y - sums[i].y + sums[n].y; + x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2; + xy = sums[j+1].xy - sums[i].xy + sums[n].xy; + y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2; + k = j+1 - i + n; + } + + px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x; + py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y; + ey = (pt[j].x - pt[i].x); + ex = -(pt[j].y - pt[i].y); + + a = ((x2 - 2*x*px) / k + px*px); + b = ((xy - x*py - y*px) / k + px*py); + c = ((y2 - 2*y*py) / k + py*py); s = ex*ex*a + 2*ex*ey*b + ey*ey*c; @@ -513,7 +523,7 @@ static double penalty3(privpath_t *pp, int i, int j) { /* find the optimal polygon. Fill in the m and po components. Return 1 on failure with errno set, else 0. Non-cyclic version: assumes i=0 - is in the polygon. Fixme: ### implement cyclic version. */ + is in the polygon. Fixme: implement cyclic version. */ static int bestpolygon(privpath_t *pp) { int i, j, m, k; @@ -576,7 +586,7 @@ static int bestpolygon(privpath_t *pp) seg1[0] = 0; /* now find the shortest path with m segments, based on penalty3 */ - /* note: the outer 2 loops jointly have at most n interations, thus + /* note: the outer 2 loops jointly have at most n iterations, thus the worst-case behavior here is quadratic. In practice, it is close to linear since the inner loop tends to be short. */ pen[0]=0; @@ -828,24 +838,27 @@ static int adjust_vertices(privpath_t *pp) { /* ---------------------------------------------------------------------- */ /* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */ -/* Always succeeds and returns 0 */ -static int smooth(privcurve_t *curve, int sign, double alphamax) { +/* reverse orientation of a path */ +static void reverse(privcurve_t *curve) { + int m = curve->n; + int i, j; + dpoint_t tmp; + + for (i=0, j=m-1; i<j; i++, j--) { + tmp = curve->vertex[i]; + curve->vertex[i] = curve->vertex[j]; + curve->vertex[j] = tmp; + } +} + +/* Always succeeds */ +static void smooth(privcurve_t *curve, double alphamax) { int m = curve->n; int i, j, k; double dd, denom, alpha; dpoint_t p2, p3, p4; - if (sign == '-') { - /* reverse orientation of negative paths */ - for (i=0, j=m-1; i<j; i++, j--) { - dpoint_t tmp; - tmp = curve->vertex[i]; - curve->vertex[i] = curve->vertex[j]; - curve->vertex[j] = tmp; - } - } - /* examine each vertex and find its best fit */ for (i=0; i<m; i++) { j = mod(i+1, m); @@ -885,7 +898,7 @@ static int smooth(privcurve_t *curve, int sign, double alphamax) { } curve->alphacurve = 1; - return 0; + return; } /* ---------------------------------------------------------------------- */ @@ -1098,7 +1111,7 @@ static int opticurve(privpath_t *pp, double opttolerance) { len[0] = 0; /* Fixme: we always start from a fixed point -- should find the best - curve cyclically ### */ + curve cyclically */ for (j=1; j<=m; j++) { /* calculate best path from 0 to j */ @@ -1206,7 +1219,10 @@ int process_path(path_t *plist, const potrace_param_t *param, progress_t *progre TRY(calc_lon(p->priv)); TRY(bestpolygon(p->priv)); TRY(adjust_vertices(p->priv)); - TRY(smooth(&p->priv->curve, p->sign, param->alphamax)); + if (p->sign == '-') { /* reverse orientation of negative paths */ + reverse(&p->priv->curve); + } + smooth(&p->priv->curve, param->alphamax); if (param->opticurve) { TRY(opticurve(p->priv, param->opttolerance)); p->priv->fcurve = &p->priv->ocurve; diff --git a/src/trace/potrace/trace.h b/src/trace/potrace/trace.h index b33f8ba4d..72d1a3696 100644 --- a/src/trace/potrace/trace.h +++ b/src/trace/potrace/trace.h @@ -1,14 +1,15 @@ -/* Copyright (C) 2001-2007 Peter Selinger. +/* Copyright (C) 2001-2010 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. */ -/* $Id$ */ +/* $Id: trace.h 227 2010-12-16 05:47:19Z selinger $ */ #ifndef TRACE_H #define TRACE_H #include "potracelib.h" #include "progress.h" +#include "curve.h" int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress); |
