Update potrace to version 1.15 (that fixes some bugs)
This commit is contained in:
parent
e5847b7953
commit
23d1905c55
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ static inline dpoint_t interval( double lambda, dpoint_t a, dpoint_t b )
|
||||||
{
|
{
|
||||||
dpoint_t res;
|
dpoint_t res;
|
||||||
|
|
||||||
res.x = a.x + lambda * (b.x - a.x);
|
res.x = a.x + lambda * ( b.x - a.x );
|
||||||
res.y = a.y + lambda * (b.y - a.y);
|
res.y = a.y + lambda * ( b.y - a.y );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,13 +63,13 @@ static inline dpoint_t interval( double lambda, dpoint_t a, dpoint_t b )
|
||||||
|
|
||||||
static inline int mod( int a, int n )
|
static inline int mod( int a, int n )
|
||||||
{
|
{
|
||||||
return a>=n ? a % n : a>=0 ? a : n - 1 - (-1 - a) % n;
|
return a >= n ? a % n : a >= 0 ? a : n - 1 - ( -1 - a ) % n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int floordiv( int a, int n )
|
static inline int floordiv( int a, int n )
|
||||||
{
|
{
|
||||||
return a>=0 ? a / n : -1 - (-1 - a) / n;
|
return a >= 0 ? a / n : -1 - ( -1 - a ) / n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,11 +80,11 @@ static inline int floordiv( int a, int n )
|
||||||
#undef max
|
#undef max
|
||||||
#undef sq
|
#undef sq
|
||||||
#undef cu
|
#undef cu
|
||||||
#define sign( x ) ( (x)>0 ? 1 : (x)<0 ? -1 : 0 )
|
#define sign( x ) ( ( x ) > 0 ? 1 : ( x ) < 0 ? -1 : 0 )
|
||||||
#define abs( a ) ( (a)>0 ? (a) : -(a) )
|
#define abs( a ) ( ( a ) > 0 ? ( a ) : -( a ) )
|
||||||
#define min( a, b ) ( (a)<(b) ? (a) : (b) )
|
#define min( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
|
||||||
#define max( a, b ) ( (a)>(b) ? (a) : (b) )
|
#define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
|
||||||
#define sq( a ) ( (a) * (a) )
|
#define sq( a ) ( ( a ) * ( a ) )
|
||||||
#define cu( a ) ( (a) * (a) * (a) )
|
#define cu( a ) ( ( a ) * ( a ) * ( a ) )
|
||||||
|
|
||||||
#endif /* AUXILIARY_H */
|
#endif /* AUXILIARY_H */
|
||||||
|
|
226
potrace/bitmap.h
226
potrace/bitmap.h
|
@ -1,14 +1,14 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
#ifndef BITMAP_H
|
#ifndef BITMAP_H
|
||||||
#define BITMAP_H
|
#define BITMAP_H
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* The bitmap type is defined in potracelib.h */
|
/* The bitmap type is defined in potracelib.h */
|
||||||
#include "potracelib.h"
|
#include "potracelib.h"
|
||||||
|
@ -21,58 +21,117 @@
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* some measurements */
|
/* some measurements */
|
||||||
|
|
||||||
#define BM_WORDSIZE ( (int) sizeof(potrace_word) )
|
#define BM_WORDSIZE ( (int) sizeof( potrace_word ) )
|
||||||
#define BM_WORDBITS (8 * BM_WORDSIZE)
|
#define BM_WORDBITS ( 8 * BM_WORDSIZE )
|
||||||
#define BM_HIBIT ( ( (potrace_word) 1 ) << (BM_WORDBITS - 1) )
|
#define BM_HIBIT ( ( (potrace_word) 1 ) << ( BM_WORDBITS - 1 ) )
|
||||||
#define BM_ALLBITS (~(potrace_word) 0)
|
#define BM_ALLBITS ( ~(potrace_word) 0 )
|
||||||
|
|
||||||
/* macros for accessing pixel at index (x,y). U* macros omit the
|
/* macros for accessing pixel at index (x,y). U* macros omit the
|
||||||
* bounds check. */
|
* bounds check. */
|
||||||
|
|
||||||
#define bm_scanline( bm, y ) ( (bm)->map + (ptrdiff_t) (y) * (ptrdiff_t) (bm)->dy )
|
#define bm_scanline( bm, y ) ( ( bm )->map + (ptrdiff_t) ( y ) * (ptrdiff_t) ( bm )->dy )
|
||||||
#define bm_index( bm, x, y ) (&bm_scanline( bm, y )[(x) / BM_WORDBITS])
|
#define bm_index( bm, x, y ) ( &bm_scanline( bm, y )[( x ) / BM_WORDBITS] )
|
||||||
#define bm_mask( x ) ( BM_HIBIT >> ( (x) & (BM_WORDBITS - 1) ) )
|
#define bm_mask( x ) ( BM_HIBIT >> ( ( x ) & ( BM_WORDBITS - 1 ) ) )
|
||||||
#define bm_range( x, a ) ( (int) (x) >= 0 && (int) (x) < (a) )
|
#define bm_range( x, a ) ( (int) ( x ) >= 0 && (int) ( x ) < ( a ) )
|
||||||
#define bm_safe( bm, x, y ) ( bm_range( x, (bm)->w ) && bm_range( y, (bm)->h ) )
|
#define bm_safe( bm, x, y ) ( bm_range( x, ( bm )->w ) && bm_range( y, ( bm )->h ) )
|
||||||
#define BM_UGET( bm, x, y ) ( ( *bm_index( bm, x, y ) & bm_mask( x ) ) != 0 )
|
#define BM_UGET( bm, x, y ) ( ( *bm_index( bm, x, y ) & bm_mask( x ) ) != 0 )
|
||||||
#define BM_USET( bm, x, y ) ( *bm_index( bm, x, y ) |= bm_mask( x ) )
|
#define BM_USET( bm, x, y ) ( *bm_index( bm, x, y ) |= bm_mask( x ) )
|
||||||
#define BM_UCLR( bm, x, y ) ( *bm_index( bm, x, y ) &= ~bm_mask( x ) )
|
#define BM_UCLR( bm, x, y ) ( *bm_index( bm, x, y ) &= ~bm_mask( x ) )
|
||||||
#define BM_UINV( bm, x, y ) ( *bm_index( bm, x, y ) ^= bm_mask( x ) )
|
#define BM_UINV( bm, x, y ) ( *bm_index( bm, x, y ) ^= bm_mask( x ) )
|
||||||
#define BM_UPUT( bm, x, y, b ) ( (b) ? BM_USET( bm, x, y ) : BM_UCLR( bm, x, y ) )
|
#define BM_UPUT( bm, x, y, b ) ( ( b ) ? BM_USET( bm, x, y ) : BM_UCLR( bm, x, y ) )
|
||||||
#define BM_GET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UGET( bm, x, y ) : 0)
|
#define BM_GET( bm, x, y ) ( bm_safe( bm, x, y ) ? BM_UGET( bm, x, y ) : 0 )
|
||||||
#define BM_SET( bm, x, y ) (bm_safe( bm, x, y ) ? BM_USET( bm, x, y ) : 0)
|
#define BM_SET( bm, x, y ) ( bm_safe( bm, x, y ) ? BM_USET( bm, x, y ) : 0 )
|
||||||
#define BM_CLR( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UCLR( bm, x, y ) : 0)
|
#define BM_CLR( bm, x, y ) ( bm_safe( bm, x, y ) ? BM_UCLR( bm, x, y ) : 0 )
|
||||||
#define BM_INV( bm, x, y ) (bm_safe( bm, x, y ) ? BM_UINV( bm, x, y ) : 0)
|
#define BM_INV( bm, x, y ) ( bm_safe( bm, x, y ) ? BM_UINV( bm, x, y ) : 0 )
|
||||||
#define BM_PUT( bm, x, y, b ) (bm_safe( bm, x, y ) ? BM_UPUT( bm, x, y, b ) : 0)
|
#define BM_PUT( bm, x, y, b ) ( bm_safe( bm, x, y ) ? BM_UPUT( bm, x, y, b ) : 0 )
|
||||||
|
|
||||||
|
/* calculate the size, in bytes, required for the data area of a
|
||||||
|
* bitmap of the given dy and h. Assume h >= 0. Return -1 if the size
|
||||||
|
* does not fit into the ptrdiff_t type. */
|
||||||
|
static inline ptrdiff_t getsize( int dy, int h )
|
||||||
|
{
|
||||||
|
ptrdiff_t size;
|
||||||
|
|
||||||
|
if( dy < 0 )
|
||||||
|
{
|
||||||
|
dy = -dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) BM_WORDSIZE;
|
||||||
|
|
||||||
|
/* check for overflow error */
|
||||||
|
if( size < 0 || ( h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE ) )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return the size, in bytes, of the data area of the bitmap. Return
|
||||||
|
* -1 if the size does not fit into the ptrdiff_t type; however, this
|
||||||
|
* cannot happen if the bitmap is well-formed, i.e., if created with
|
||||||
|
* bm_new or bm_dup. */
|
||||||
|
static inline ptrdiff_t bm_size( const potrace_bitmap_t* bm )
|
||||||
|
{
|
||||||
|
return getsize( bm->dy, bm->h );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* calculate the base address of the bitmap data. Assume that the
|
||||||
|
* bitmap is well-formed, i.e., its size fits into the ptrdiff_t type.
|
||||||
|
* This is the case if created with bm_new or bm_dup. The base address
|
||||||
|
* may differ from bm->map if dy is negative */
|
||||||
|
static inline potrace_word* bm_base( const potrace_bitmap_t* bm )
|
||||||
|
{
|
||||||
|
int dy = bm->dy;
|
||||||
|
|
||||||
|
if( dy >= 0 || bm->h == 0 )
|
||||||
|
{
|
||||||
|
return bm->map;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return bm_scanline( bm, bm->h - 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* free the given bitmap. Leaves errno untouched. */
|
/* free the given bitmap. Leaves errno untouched. */
|
||||||
static inline void bm_free( potrace_bitmap_t* bm )
|
static inline void bm_free( potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
if( bm )
|
if( bm && bm->map )
|
||||||
{
|
{
|
||||||
free( bm->map );
|
free( bm_base( bm ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
free( bm );
|
free( bm );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* return new un-initialized bitmap. NULL with errno on error.
|
/* return new bitmap initialized to 0. NULL with errno on error.
|
||||||
* Assumes w, h >= 0. */
|
* Assumes w, h >= 0. */
|
||||||
static inline potrace_bitmap_t* bm_new( int w, int h )
|
static inline potrace_bitmap_t* bm_new( int w, int h )
|
||||||
{
|
{
|
||||||
potrace_bitmap_t* bm;
|
potrace_bitmap_t* bm;
|
||||||
int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
|
int dy = w == 0 ? 0 : ( w - 1 ) / BM_WORDBITS + 1;
|
||||||
ptrdiff_t size = (ptrdiff_t) dy * (ptrdiff_t) h * (ptrdiff_t) BM_WORDSIZE;
|
ptrdiff_t size;
|
||||||
|
|
||||||
/* check for overflow error */
|
size = getsize( dy, h );
|
||||||
if( size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE) )
|
|
||||||
|
if( size < 0 )
|
||||||
{
|
{
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bm = (potrace_bitmap_t*) malloc( sizeof(potrace_bitmap_t) );
|
if( size == 0 )
|
||||||
|
{
|
||||||
|
size = 1; /* make sure calloc() doesn't return NULL */
|
||||||
|
}
|
||||||
|
|
||||||
|
bm = (potrace_bitmap_t*) malloc( sizeof( potrace_bitmap_t ) );
|
||||||
|
|
||||||
if( !bm )
|
if( !bm )
|
||||||
{
|
{
|
||||||
|
@ -82,7 +141,7 @@ static inline potrace_bitmap_t* bm_new( int w, int h )
|
||||||
bm->w = w;
|
bm->w = w;
|
||||||
bm->h = h;
|
bm->h = h;
|
||||||
bm->dy = dy;
|
bm->dy = dy;
|
||||||
bm->map = (potrace_word*) malloc( size );
|
bm->map = (potrace_word*) calloc( 1, size );
|
||||||
|
|
||||||
if( !bm->map )
|
if( !bm->map )
|
||||||
{
|
{
|
||||||
|
@ -94,29 +153,36 @@ static inline potrace_bitmap_t* bm_new( int w, int h )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* clear the given bitmap. Set all bits to c. */
|
/* clear the given bitmap. Set all bits to c. Assumes a well-formed
|
||||||
|
* bitmap. */
|
||||||
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
static inline void bm_clear( potrace_bitmap_t* bm, int c )
|
||||||
{
|
{
|
||||||
/* Note: if the bitmap was created with bm_new, then it is
|
/* Note: if the bitmap was created with bm_new, then it is
|
||||||
* guaranteed that size will fit into the ptrdiff_t type. */
|
* guaranteed that size will fit into the ptrdiff_t type. */
|
||||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
ptrdiff_t size = bm_size( bm );
|
||||||
|
|
||||||
memset( bm->map, c ? -1 : 0, size );
|
memset( bm_base( bm ), c ? -1 : 0, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* duplicate the given bitmap. Return NULL on error with errno set. */
|
/* duplicate the given bitmap. Return NULL on error with errno
|
||||||
|
* set. Assumes a well-formed bitmap. */
|
||||||
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
|
||||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h * (ptrdiff_t) BM_WORDSIZE;
|
int y;
|
||||||
|
|
||||||
if( !bm1 )
|
if( !bm1 )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( bm1->map, bm->map, size );
|
for( y = 0; y < bm->h; y++ )
|
||||||
|
{
|
||||||
|
memcpy( bm_scanline( bm1, y ), bm_scanline( bm, y ),
|
||||||
|
(size_t) bm1->dy * (size_t) BM_WORDSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
return bm1;
|
return bm1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +190,100 @@ static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
|
||||||
/* invert the given bitmap. */
|
/* invert the given bitmap. */
|
||||||
static inline void bm_invert( potrace_bitmap_t* bm )
|
static inline void bm_invert( potrace_bitmap_t* bm )
|
||||||
{
|
{
|
||||||
ptrdiff_t i;
|
int dy = bm->dy;
|
||||||
ptrdiff_t size = (ptrdiff_t) bm->dy * (ptrdiff_t) bm->h;
|
int y;
|
||||||
|
int i;
|
||||||
|
potrace_word* p;
|
||||||
|
|
||||||
for( i = 0; i < size; i++ )
|
if( dy < 0 )
|
||||||
{
|
{
|
||||||
bm->map[i] ^= BM_ALLBITS;
|
dy = -dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( y = 0; y < bm->h; y++ )
|
||||||
|
{
|
||||||
|
p = bm_scanline( bm, y );
|
||||||
|
|
||||||
|
for( i = 0; i < dy; i++ )
|
||||||
|
{
|
||||||
|
p[i] ^= BM_ALLBITS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* turn the given bitmap upside down. This does not move the bitmap
|
||||||
|
* data or change the bm_base() address. */
|
||||||
|
static inline void bm_flip( potrace_bitmap_t* bm )
|
||||||
|
{
|
||||||
|
int dy = bm->dy;
|
||||||
|
|
||||||
|
if( bm->h == 0 || bm->h == 1 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bm->map = bm_scanline( bm, bm->h - 1 );
|
||||||
|
bm->dy = -dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* resize the bitmap to the given new height. The bitmap data remains
|
||||||
|
* bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
|
||||||
|
* (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
|
||||||
|
* error with errno set. If the new height is <= the old one, no error
|
||||||
|
* should occur. If the new height is larger, the additional bitmap
|
||||||
|
* data is *not* initialized. */
|
||||||
|
static inline int bm_resize( potrace_bitmap_t* bm, int h )
|
||||||
|
{
|
||||||
|
int dy = bm->dy;
|
||||||
|
ptrdiff_t newsize;
|
||||||
|
potrace_word* newmap;
|
||||||
|
|
||||||
|
if( dy < 0 )
|
||||||
|
{
|
||||||
|
bm_flip( bm );
|
||||||
|
}
|
||||||
|
|
||||||
|
newsize = getsize( dy, h );
|
||||||
|
|
||||||
|
if( newsize < 0 )
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( newsize == 0 )
|
||||||
|
{
|
||||||
|
newsize = 1; /* make sure realloc() doesn't return NULL */
|
||||||
|
}
|
||||||
|
|
||||||
|
newmap = (potrace_word*) realloc( bm->map, newsize );
|
||||||
|
|
||||||
|
if( newmap == NULL )
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bm->map = newmap;
|
||||||
|
bm->h = h;
|
||||||
|
|
||||||
|
if( dy < 0 )
|
||||||
|
{
|
||||||
|
bm_flip( bm );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
if( dy < 0 )
|
||||||
|
{
|
||||||
|
bm_flip( bm );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* BITMAP_H */
|
#endif /* BITMAP_H */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -12,13 +12,24 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
#include "bitmap_io.h"
|
||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
|
|
||||||
#define INTBITS ( 8 * sizeof(int) )
|
#define INTBITS ( 8 * sizeof( int ) )
|
||||||
|
|
||||||
static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp );
|
static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp );
|
||||||
static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic );
|
static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, int magic );
|
||||||
|
|
||||||
|
#define TRY( x ) \
|
||||||
|
if( x ) \
|
||||||
|
goto try_error
|
||||||
|
#define TRY_EOF( x ) \
|
||||||
|
if( x ) \
|
||||||
|
goto eof
|
||||||
|
#define TRY_STD( x ) \
|
||||||
|
if( x ) \
|
||||||
|
goto std_error
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* routines for reading pnm streams */
|
/* routines for reading pnm streams */
|
||||||
|
|
||||||
|
@ -32,13 +43,13 @@ static int fgetc_ws( FILE* f )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='#' )
|
if( c == '#' )
|
||||||
{
|
{
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c=='\n' || c==EOF )
|
if( c == '\n' || c == EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +57,7 @@ static int fgetc_ws( FILE* f )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* space, tab, line feed, carriage return, form-feed */
|
/* space, tab, line feed, carriage return, form-feed */
|
||||||
if( c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12 )
|
if( c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != 12 )
|
||||||
{
|
{
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -69,12 +80,12 @@ static int readnum( FILE* f )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c == EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='9' )
|
if( c >= '0' && c <= '9' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -87,12 +98,12 @@ static int readnum( FILE* f )
|
||||||
{
|
{
|
||||||
c = fgetc( f );
|
c = fgetc( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c == EOF )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c<'0' || c>'9' )
|
if( c < '0' || c > '9' )
|
||||||
{
|
{
|
||||||
ungetc( c, f );
|
ungetc( c, f );
|
||||||
break;
|
break;
|
||||||
|
@ -118,12 +129,12 @@ static int readbit( FILE* f )
|
||||||
{
|
{
|
||||||
c = fgetc_ws( f );
|
c = fgetc_ws( f );
|
||||||
|
|
||||||
if( c==EOF )
|
if( c == EOF )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c>='0' && c<='1' )
|
if( c >= '0' && c <= '1' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,19 +198,21 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
int x, y, i, b, b1, sum;
|
int x, y, i, b, b1, sum;
|
||||||
int bpr; /* bytes per row (as opposed to 4*bm->c) */
|
int bpr; /* bytes per row (as opposed to 4*bm->c) */
|
||||||
int w, h, max;
|
int w, h, max;
|
||||||
|
int realheight; /* in case of incomplete file, keeps track of how
|
||||||
|
* many scan lines actually contain data */
|
||||||
|
|
||||||
bm = NULL;
|
bm = NULL;
|
||||||
|
|
||||||
w = readnum( f );
|
w = readnum( f );
|
||||||
|
|
||||||
if( w<0 )
|
if( w < 0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
h = readnum( f );
|
h = readnum( f );
|
||||||
|
|
||||||
if( h<0 )
|
if( h < 0 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
@ -209,11 +222,10 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
if( !bm )
|
if( !bm )
|
||||||
{
|
{
|
||||||
return -1;
|
goto std_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zero it out */
|
realheight = 0;
|
||||||
bm_clear( bm, 0 );
|
|
||||||
|
|
||||||
switch( magic )
|
switch( magic )
|
||||||
{
|
{
|
||||||
|
@ -224,13 +236,15 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
case '1':
|
case '1':
|
||||||
/* read P1 format: PBM ascii */
|
/* read P1 format: PBM ascii */
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( x = 0; x<w; x++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( x = 0; x < w; x++ )
|
||||||
{
|
{
|
||||||
b = readbit( f );
|
b = readbit( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b < 0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
@ -246,18 +260,20 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max < 1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( x = 0; x<w; x++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( x = 0; x < w; x++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b < 0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
@ -273,22 +289,24 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max < 1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( x = 0; x<w; x++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( x = 0; x < w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i < 3; i++ )
|
||||||
{
|
{
|
||||||
b = readnum( f );
|
b = readnum( f );
|
||||||
|
|
||||||
if( b<0 )
|
if( b < 0 )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
@ -307,27 +325,28 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after height */
|
b = fgetc( f ); /* read single white-space character after height */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bpr = (w + 7) / 8;
|
bpr = ( w + 7 ) / 8;
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( i = 0; i<bpr; i++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( i = 0; i < bpr; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
*bm_index( bm, i * 8,
|
*bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
|
||||||
y ) |= ( (potrace_word) b ) <<
|
<< ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
|
||||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,33 +357,35 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max < 1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( x = 0; x<w; x++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( x = 0; x < w; x++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
if( max>=256 )
|
if( max >= 256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1 == EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
|
@ -381,39 +402,41 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
|
|
||||||
max = readnum( f );
|
max = readnum( f );
|
||||||
|
|
||||||
if( max<1 )
|
if( max < 1 )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = fgetc( f ); /* read single white-space character after max */
|
b = fgetc( f ); /* read single white-space character after max */
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = 0; y < h; y++ )
|
||||||
{
|
{
|
||||||
for( x = 0; x<w; x++ )
|
realheight = y + 1;
|
||||||
|
|
||||||
|
for( x = 0; x < w; x++ )
|
||||||
{
|
{
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i < 3; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
goto eof;
|
goto eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( max>=256 )
|
if( max >= 256 )
|
||||||
{
|
{
|
||||||
b <<= 8;
|
b <<= 8;
|
||||||
b1 = fgetc( f );
|
b1 = fgetc( f );
|
||||||
|
|
||||||
if( b1==EOF )
|
if( b1 == EOF )
|
||||||
goto eof;
|
goto eof;
|
||||||
|
|
||||||
b |= b1;
|
b |= b1;
|
||||||
|
@ -429,10 +452,13 @@ static int bm_readbody_pnm( FILE* f, double threshold, potrace_bitmap_t** bmp, i
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bm_flip( bm );
|
||||||
*bmp = bm;
|
*bmp = bm;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
eof:
|
eof:
|
||||||
|
TRY_STD( bm_resize( bm, realheight ) );
|
||||||
|
bm_flip( bm );
|
||||||
*bmp = bm;
|
*bmp = bm;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -453,6 +479,10 @@ format_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
|
std_error:
|
||||||
|
bm_free( bm );
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -497,16 +527,16 @@ static int bmp_readint( FILE* f, int n, unsigned int* p )
|
||||||
unsigned int sum = 0;
|
unsigned int sum = 0;
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += b << (8 * i);
|
sum += (unsigned) b << ( 8 * i );
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp_count += n;
|
bmp_count += n;
|
||||||
|
@ -529,13 +559,13 @@ static int bmp_pad( FILE* f )
|
||||||
{
|
{
|
||||||
int c, i, b;
|
int c, i, b;
|
||||||
|
|
||||||
c = (-bmp_count) & 3;
|
c = ( -bmp_count ) & 3;
|
||||||
|
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i < c; i++ )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -556,7 +586,7 @@ static int bmp_forward( FILE* f, int pos )
|
||||||
{
|
{
|
||||||
b = fgetc( f );
|
b = fgetc( f );
|
||||||
|
|
||||||
if( b==EOF )
|
if( b == EOF )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -569,16 +599,8 @@ 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)
|
|
||||||
|
|
||||||
/* safe colortable access */
|
/* safe colortable access */
|
||||||
#define COLTABLE( c ) ( (c) < bmpinfo.ncolors ? coltable[(c)] : 0 )
|
#define COLTABLE( c ) ( ( c ) < bmpinfo.ncolors ? coltable[( c )] : 0 )
|
||||||
|
|
||||||
/* read BMP stream after magic number. Return values as for bm_read.
|
/* read BMP stream after magic number. Return values as for bm_read.
|
||||||
* We choose to be as permissive as possible, since there are many
|
* We choose to be as permissive as possible, since there are many
|
||||||
|
@ -601,6 +623,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
unsigned int redshift, greenshift, blueshift;
|
unsigned int redshift, greenshift, blueshift;
|
||||||
int col1[2];
|
int col1[2];
|
||||||
|
int realheight; /* in case of incomplete file, keeps track of how
|
||||||
|
* many scan lines actually contain data */
|
||||||
|
|
||||||
bm_read_error = NULL;
|
bm_read_error = NULL;
|
||||||
bm = NULL;
|
bm = NULL;
|
||||||
|
@ -616,8 +640,8 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
/* info header */
|
/* info header */
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.InfoSize ) );
|
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 == 108 || bmpinfo.InfoSize == 124 )
|
|| bmpinfo.InfoSize == 124 )
|
||||||
{
|
{
|
||||||
/* Windows or new OS/2 format */
|
/* Windows or new OS/2 format */
|
||||||
bmpinfo.ctbits = 32; /* sample size in color table */
|
bmpinfo.ctbits = 32; /* sample size in color table */
|
||||||
|
@ -632,8 +656,9 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ncolors ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.ColorsImportant ) );
|
||||||
|
|
||||||
if( bmpinfo.InfoSize >= 108 ) /* V4 and V5 bitmaps */
|
if( bmpinfo.InfoSize >= 108 )
|
||||||
{
|
{
|
||||||
|
/* V4 and V5 bitmaps */
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.RedMask ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.RedMask ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.GreenMask ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.GreenMask ) );
|
||||||
TRY( bmp_readint( f, 4, &bmpinfo.BlueMask ) );
|
TRY( bmp_readint( f, 4, &bmpinfo.BlueMask ) );
|
||||||
|
@ -647,7 +672,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
|
|
||||||
if( bmpinfo.h > 0x7fffffff )
|
if( bmpinfo.h > 0x7fffffff )
|
||||||
{
|
{
|
||||||
bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
|
bmpinfo.h = ( -bmpinfo.h ) & 0xffffffff;
|
||||||
bmpinfo.topdown = 1;
|
bmpinfo.topdown = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -697,7 +722,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
goto format_error; /* can't handle planes */
|
goto format_error; /* can't handle planes */
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bmpinfo.ncolors == 0 )
|
if( bmpinfo.ncolors == 0 && bmpinfo.bits <= 8 )
|
||||||
{
|
{
|
||||||
bmpinfo.ncolors = 1 << bmpinfo.bits;
|
bmpinfo.ncolors = 1 << bmpinfo.bits;
|
||||||
}
|
}
|
||||||
|
@ -705,7 +730,7 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
/* color table, present only if bmpinfo.bits <= 8. */
|
/* color table, present only if bmpinfo.bits <= 8. */
|
||||||
if( bmpinfo.bits <= 8 )
|
if( bmpinfo.bits <= 8 )
|
||||||
{
|
{
|
||||||
coltable = (int*) calloc( bmpinfo.ncolors, sizeof(int) );
|
coltable = (int*) calloc( bmpinfo.ncolors, sizeof( int ) );
|
||||||
|
|
||||||
if( !coltable )
|
if( !coltable )
|
||||||
{
|
{
|
||||||
|
@ -714,13 +739,13 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
|
|
||||||
/* NOTE: since we are reading a bitmap, we can immediately convert
|
/* NOTE: since we are reading a bitmap, we can immediately convert
|
||||||
* the color table entries to bits. */
|
* the color table entries to bits. */
|
||||||
for( i = 0; i<bmpinfo.ncolors; i++ )
|
for( i = 0; i < bmpinfo.ncolors; i++ )
|
||||||
{
|
{
|
||||||
TRY( bmp_readint( f, bmpinfo.ctbits / 8, &c ) );
|
TRY( bmp_readint( f, bmpinfo.ctbits / 8, &c ) );
|
||||||
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
|
||||||
coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
|
coltable[i] = ( c > 3 * threshold * 255 ? 0 : 1 );
|
||||||
|
|
||||||
if( i<2 )
|
if( i < 2 )
|
||||||
{
|
{
|
||||||
col1[i] = c;
|
col1[i] = c;
|
||||||
}
|
}
|
||||||
|
@ -728,8 +753,9 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward to data */
|
/* forward to data */
|
||||||
if( bmpinfo.InfoSize != 12 ) /* not old OS/2 format */
|
if( bmpinfo.InfoSize != 12 )
|
||||||
{
|
{
|
||||||
|
/* not old OS/2 format */
|
||||||
TRY( bmp_forward( f, bmpinfo.DataOffset ) );
|
TRY( bmp_forward( f, bmpinfo.DataOffset ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,19 +767,18 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
goto std_error;
|
goto std_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zero it out */
|
realheight = 0;
|
||||||
bm_clear( bm, 0 );
|
|
||||||
|
|
||||||
switch( bmpinfo.bits + 0x100 * bmpinfo.comp )
|
switch( bmpinfo.bits + 0x100 * bmpinfo.comp )
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
goto format_error;
|
goto format_error; break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x001: /* monochrome palette */
|
case 0x001: /* monochrome palette */
|
||||||
|
|
||||||
if( col1[0] < col1[1] ) /* make the darker color black */
|
if( col1[0] < col1[1] )
|
||||||
{
|
{
|
||||||
|
/* make the darker color black */
|
||||||
mask = 0xff;
|
mask = 0xff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -762,17 +787,17 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* raster data */
|
/* raster data */
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y < bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
|
realheight = y + 1;
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( i = 0; 8 * i<bmpinfo.w; i++ )
|
for( i = 0; 8 * i < bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
b ^= mask;
|
b ^= mask;
|
||||||
*bm_index( bm, i * 8,
|
*bm_index( bm, i * 8, y ) |= ( (potrace_word) b )
|
||||||
ycorr( y ) ) |= ( (potrace_word) b ) <<
|
<< ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) );
|
||||||
( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -788,25 +813,26 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
case 0x007:
|
case 0x007:
|
||||||
case 0x008:
|
case 0x008:
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y < bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
|
realheight = y + 1;
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
|
||||||
n = 0; /* number of bits currently in bitbuffer */
|
n = 0; /* number of bits currently in bitbuffer */
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x < bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
if( n < bmpinfo.bits )
|
if( n < bmpinfo.bits )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
bitbuf |= b << (INTBITS - 8 - n);
|
bitbuf |= b << ( INTBITS - 8 - n );
|
||||||
n += 8;
|
n += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = bitbuf >> (INTBITS - bmpinfo.bits);
|
b = bitbuf >> ( INTBITS - bmpinfo.bits );
|
||||||
bitbuf <<= bmpinfo.bits;
|
bitbuf <<= bmpinfo.bits;
|
||||||
n -= bmpinfo.bits;
|
n -= bmpinfo.bits;
|
||||||
BM_UPUT( bm, x, ycorr( y ), COLTABLE( b ) );
|
BM_UPUT( bm, x, y, COLTABLE( b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -824,15 +850,16 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
case 0x018: /* 24-bit encoding */
|
case 0x018: /* 24-bit encoding */
|
||||||
case 0x020: /* 32-bit encoding */
|
case 0x020: /* 32-bit encoding */
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y < bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
|
realheight = y + 1;
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x < bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||||
c = ( (c >> 16) & 0xff ) + ( (c >> 8) & 0xff ) + (c & 0xff);
|
c = ( ( c >> 16 ) & 0xff ) + ( ( c >> 8 ) & 0xff ) + ( c & 0xff );
|
||||||
BM_UPUT( bm, x, ycorr( y ), c > 3 * threshold * 255 ? 0 : 1 );
|
BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -841,21 +868,28 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x320: /* 32-bit encoding with bitfields */
|
case 0x320: /* 32-bit encoding with bitfields */
|
||||||
|
|
||||||
|
if( bmpinfo.RedMask == 0 || bmpinfo.GreenMask == 0 || bmpinfo.BlueMask == 0 )
|
||||||
|
{
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
|
||||||
redshift = lobit( bmpinfo.RedMask );
|
redshift = lobit( bmpinfo.RedMask );
|
||||||
greenshift = lobit( bmpinfo.GreenMask );
|
greenshift = lobit( bmpinfo.GreenMask );
|
||||||
blueshift = lobit( bmpinfo.BlueMask );
|
blueshift = lobit( bmpinfo.BlueMask );
|
||||||
|
|
||||||
for( y = 0; y<bmpinfo.h; y++ )
|
for( y = 0; y < bmpinfo.h; y++ )
|
||||||
{
|
{
|
||||||
|
realheight = y + 1;
|
||||||
bmp_pad_reset();
|
bmp_pad_reset();
|
||||||
|
|
||||||
for( x = 0; x<bmpinfo.w; x++ )
|
for( x = 0; x < bmpinfo.w; x++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
TRY_EOF( bmp_readint( f, bmpinfo.bits / 8, &c ) );
|
||||||
c = ( (c & bmpinfo.RedMask) >> redshift ) +
|
c = ( ( c & bmpinfo.RedMask ) >> redshift )
|
||||||
( (c & bmpinfo.GreenMask) >> greenshift ) +
|
+ ( ( c & bmpinfo.GreenMask ) >> greenshift )
|
||||||
( (c & bmpinfo.BlueMask) >> blueshift );
|
+ ( ( c & bmpinfo.BlueMask ) >> blueshift );
|
||||||
BM_UPUT( bm, x, ycorr( y ), c > 3 * threshold * 255 ? 0 : 1 );
|
BM_UPUT( bm, x, y, c > 3 * threshold * 255 ? 0 : 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY( bmp_pad( f ) );
|
TRY( bmp_pad( f ) );
|
||||||
|
@ -872,26 +906,27 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b > 0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
col[0] = COLTABLE( (c >> 4) & 0xf );
|
col[0] = COLTABLE( ( c >> 4 ) & 0xf );
|
||||||
col[1] = COLTABLE( c & 0xf );
|
col[1] = COLTABLE( c & 0xf );
|
||||||
|
|
||||||
for( i = 0; i<b && x<bmpinfo.w; i++ )
|
for( i = 0; i < b && x < bmpinfo.w; i++ )
|
||||||
{
|
{
|
||||||
if( x>=bmpinfo.w )
|
if( x >= bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_UPUT( bm, x, ycorr( y ), col[i & 1] );
|
realheight = y + 1;
|
||||||
|
BM_PUT( bm, x, y, col[i & 1] );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -917,29 +952,30 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* verbatim segment */
|
/* verbatim segment */
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i < c; i++ )
|
||||||
{
|
{
|
||||||
if( (i & 1)==0 )
|
if( ( i & 1 ) == 0 )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x >= bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_PUT( bm, x, ycorr( y ), COLTABLE( ( b >> ( 4 - 4 * (i & 1) ) ) & 0xf ) );
|
realheight = y + 1;
|
||||||
|
BM_PUT( bm, x, y, COLTABLE( ( b >> ( 4 - 4 * ( i & 1 ) ) ) & 0xf ) );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (c + 1) & 2 )
|
if( ( c + 1 ) & 2 )
|
||||||
{
|
{
|
||||||
/* pad to 16-bit boundary */
|
/* pad to 16-bit boundary */
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
|
@ -958,23 +994,24 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
TRY_EOF( bmp_readint( f, 1, &b ) ); /* opcode */
|
||||||
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
TRY_EOF( bmp_readint( f, 1, &c ) ); /* argument */
|
||||||
|
|
||||||
if( b>0 )
|
if( b > 0 )
|
||||||
{
|
{
|
||||||
/* repeat count */
|
/* repeat count */
|
||||||
for( i = 0; i<b; i++ )
|
for( i = 0; i < b; i++ )
|
||||||
{
|
{
|
||||||
if( x>=bmpinfo.w )
|
if( x >= bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_UPUT( bm, x, ycorr( y ), COLTABLE( c ) );
|
realheight = y + 1;
|
||||||
|
BM_PUT( bm, x, y, COLTABLE( c ) );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1000,22 +1037,23 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* verbatim segment */
|
/* verbatim segment */
|
||||||
for( i = 0; i<c; i++ )
|
for( i = 0; i < c; i++ )
|
||||||
{
|
{
|
||||||
TRY_EOF( bmp_readint( f, 1, &b ) );
|
TRY_EOF( bmp_readint( f, 1, &b ) );
|
||||||
|
|
||||||
if( x>=bmpinfo.w )
|
if( x >= bmpinfo.w )
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( y>=bmpinfo.h )
|
if( x >= bmpinfo.w || y >= bmpinfo.h )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_PUT( bm, x, ycorr( y ), COLTABLE( b ) );
|
realheight = y + 1;
|
||||||
|
BM_PUT( bm, x, y, COLTABLE( b ) );
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1035,11 +1073,24 @@ static int bm_readbody_bmp( FILE* f, double threshold, potrace_bitmap_t** bmp )
|
||||||
bmp_forward( f, bmpinfo.FileSize );
|
bmp_forward( f, bmpinfo.FileSize );
|
||||||
|
|
||||||
free( coltable );
|
free( coltable );
|
||||||
|
|
||||||
|
if( bmpinfo.topdown )
|
||||||
|
{
|
||||||
|
bm_flip( bm );
|
||||||
|
}
|
||||||
|
|
||||||
*bmp = bm;
|
*bmp = bm;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
eof:
|
eof:
|
||||||
|
TRY_STD( bm_resize( bm, realheight ) );
|
||||||
free( coltable );
|
free( coltable );
|
||||||
|
|
||||||
|
if( bmpinfo.topdown )
|
||||||
|
{
|
||||||
|
bm_flip( bm );
|
||||||
|
}
|
||||||
|
|
||||||
*bmp = bm;
|
*bmp = bm;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -1072,17 +1123,16 @@ void bm_writepbm( FILE* f, potrace_bitmap_t* bm )
|
||||||
w = bm->w;
|
w = bm->w;
|
||||||
h = bm->h;
|
h = bm->h;
|
||||||
|
|
||||||
bpr = (w + 7) / 8;
|
bpr = ( w + 7 ) / 8;
|
||||||
|
|
||||||
fprintf( f, "P4\n%d %d\n", w, h );
|
fprintf( f, "P4\n%d %d\n", w, h );
|
||||||
|
|
||||||
for( y = h - 1; y>=0; y-- )
|
for( y = h - 1; y >= 0; y-- )
|
||||||
{
|
{
|
||||||
for( i = 0; i<bpr; i++ )
|
for( i = 0; i < bpr; i++ )
|
||||||
{
|
{
|
||||||
c =
|
c = ( *bm_index( bm, i * 8, y ) >> ( 8 * ( BM_WORDSIZE - 1 - ( i % BM_WORDSIZE ) ) ) )
|
||||||
( *bm_index( bm, i * 8,
|
& 0xff;
|
||||||
y ) >> ( 8 * ( BM_WORDSIZE - 1 - (i % BM_WORDSIZE) ) ) ) & 0xff;
|
|
||||||
fputc( c, f );
|
fputc( c, f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1101,17 +1151,17 @@ int bm_print( FILE* f, potrace_bitmap_t* bm )
|
||||||
int sw, sh;
|
int sw, sh;
|
||||||
|
|
||||||
sw = bm->w < 79 ? bm->w : 79;
|
sw = bm->w < 79 ? bm->w : 79;
|
||||||
sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / (79 * bm->w);
|
sh = bm->w < 79 ? bm->h : bm->h * sw * 44 / ( 79 * bm->w );
|
||||||
|
|
||||||
for( yy = sh - 1; yy>=0; yy-- )
|
for( yy = sh - 1; yy >= 0; yy-- )
|
||||||
{
|
{
|
||||||
for( xx = 0; xx<sw; xx++ )
|
for( xx = 0; xx < sw; xx++ )
|
||||||
{
|
{
|
||||||
d = 0;
|
d = 0;
|
||||||
|
|
||||||
for( x = xx * bm->w / sw; x<(xx + 1) * bm->w / sw; x++ )
|
for( x = xx * bm->w / sw; x < ( xx + 1 ) * bm->w / sw; x++ )
|
||||||
{
|
{
|
||||||
for( y = yy * bm->h / sh; y<(yy + 1) * bm->h / sh; y++ )
|
for( y = yy * bm->h / sh; y < ( yy + 1 ) * bm->h / sh; y++ )
|
||||||
{
|
{
|
||||||
if( BM_GET( bm, x, y ) )
|
if( BM_GET( bm, x, y ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@
|
||||||
#ifndef BITMAP_IO_H
|
#ifndef BITMAP_IO_H
|
||||||
#define BITMAP_IO_H
|
#define BITMAP_IO_H
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* Note that bitmaps are stored bottom to top, i.e., the first
|
/* Note that bitmaps are stored bottom to top, i.e., the first
|
||||||
* scanline is the bottom-most one */
|
* scanline is the bottom-most one */
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
/* bits.h: this file defines some macros for bit manipulations. We
|
/* bits.h: this file defines some macros for bit manipulations. We
|
||||||
* provide a generic implementation, as well as machine- and
|
* provide a generic implementation, as well as machine- and
|
||||||
* compiler-specific fast implementations */
|
* compiler-specific fast implementations */
|
||||||
|
@ -22,19 +21,19 @@
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* machine specific macros */
|
/* machine specific macros */
|
||||||
|
|
||||||
#if defined(HAVE_I386)
|
#if defined( HAVE_I386 )
|
||||||
|
|
||||||
static inline unsigned int lobit( unsigned int x )
|
static inline unsigned int lobit( unsigned int x )
|
||||||
{
|
{
|
||||||
unsigned int res;
|
unsigned int res;
|
||||||
|
|
||||||
asm ("bsf %1,%0\n\t"
|
asm ( "bsf %1,%0\n\t"
|
||||||
"jnz 0f\n\t"
|
"jnz 0f\n\t"
|
||||||
"movl $32,%0\n"
|
"movl $32,%0\n"
|
||||||
"0:"
|
"0:"
|
||||||
: "=r" (res)
|
: "=r" ( res )
|
||||||
: "r" (x)
|
: "r" ( x )
|
||||||
: "cc");
|
: "cc" );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,13 +42,13 @@ static inline unsigned int hibit( unsigned int x )
|
||||||
{
|
{
|
||||||
unsigned int res;
|
unsigned int res;
|
||||||
|
|
||||||
asm ("bsr %1,%0\n\t"
|
asm ( "bsr %1,%0\n\t"
|
||||||
"jnz 0f\n\t"
|
"jnz 0f\n\t"
|
||||||
"movl $-1,%0\n"
|
"movl $-1,%0\n"
|
||||||
"0:"
|
"0:"
|
||||||
: "=r" (res)
|
: "=r" ( res )
|
||||||
: "r" (x)
|
: "r" ( x )
|
||||||
: "cc");
|
: "cc" );
|
||||||
return res + 1;
|
return res + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -12,12 +12,12 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "potracelib.h"
|
|
||||||
#include "lists.h"
|
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
|
#include "lists.h"
|
||||||
|
#include "potracelib.h"
|
||||||
|
|
||||||
#define SAFE_CALLOC( var, n, typ ) \
|
#define SAFE_CALLOC( var, n, typ ) \
|
||||||
if( ( var = (typ*) calloc( n, sizeof(typ) ) ) == NULL ) \
|
if( ( var = (typ*) calloc( n, sizeof( typ ) ) ) == NULL ) \
|
||||||
goto calloc_error
|
goto calloc_error
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
@ -29,9 +29,9 @@ path_t* path_new( void )
|
||||||
privpath_t* priv = NULL;
|
privpath_t* priv = NULL;
|
||||||
|
|
||||||
SAFE_CALLOC( p, 1, path_t );
|
SAFE_CALLOC( p, 1, path_t );
|
||||||
memset( p, 0, sizeof(path_t) );
|
memset( p, 0, sizeof( path_t ) );
|
||||||
SAFE_CALLOC( priv, 1, privpath_t );
|
SAFE_CALLOC( priv, 1, privpath_t );
|
||||||
memset( priv, 0, sizeof(privpath_t) );
|
memset( priv, 0, sizeof( privpath_t ) );
|
||||||
p->priv = priv;
|
p->priv = priv;
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ typedef dpoint_t dpoint3_t[3];
|
||||||
* Return 0 on success, 1 on error with errno set. */
|
* Return 0 on success, 1 on error with errno set. */
|
||||||
int privcurve_init( privcurve_t* curve, int n )
|
int privcurve_init( privcurve_t* curve, int n )
|
||||||
{
|
{
|
||||||
memset( curve, 0, sizeof(privcurve_t) );
|
memset( curve, 0, sizeof( privcurve_t ) );
|
||||||
curve->n = n;
|
curve->n = n;
|
||||||
SAFE_CALLOC( curve->tag, n, int );
|
SAFE_CALLOC( curve->tag, n, int );
|
||||||
SAFE_CALLOC( curve->c, n, dpoint3_t );
|
SAFE_CALLOC( curve->c, n, dpoint3_t );
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -6,16 +6,21 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "potracelib.h"
|
|
||||||
#include "curve.h"
|
|
||||||
#include "lists.h"
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
#include "curve.h"
|
||||||
#include "decompose.h"
|
#include "decompose.h"
|
||||||
|
#include "lists.h"
|
||||||
|
#include "potracelib.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
@ -28,23 +33,22 @@ static inline int detrand( int x, int y )
|
||||||
{
|
{
|
||||||
/* non-linear sequence: constant term of inverse in GF(8),
|
/* non-linear sequence: constant term of inverse in GF(8),
|
||||||
* mod x^8+x^4+x^3+x+1 */
|
* 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,
|
||||||
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 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, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
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, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 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,
|
||||||
0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 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, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
|
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,
|
||||||
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 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,
|
||||||
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, 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,
|
||||||
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, 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, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
|
0, 1, 0, 1, 0, 1, 0,
|
||||||
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
|
/* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
|
||||||
* 5-bit sequence */
|
* 5-bit sequence */
|
||||||
z = ( (0x04b3e375 * x) ^ y ) * 0x05a8ef93;
|
z = ( ( 0x04b3e375 * x ) ^ y ) * 0x05a8ef93;
|
||||||
z = t[z & 0xff] ^ t[(z >> 8) & 0xff] ^ t[(z >> 16) & 0xff] ^ t[(z >> 24) & 0xff];
|
z = t[z & 0xff] ^ t[( z >> 8 ) & 0xff] ^ t[( z >> 16 ) & 0xff] ^ t[( z >> 24 ) & 0xff];
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +64,9 @@ static void bm_clearexcess( potrace_bitmap_t* bm )
|
||||||
|
|
||||||
if( bm->w % BM_WORDBITS != 0 )
|
if( bm->w % BM_WORDBITS != 0 )
|
||||||
{
|
{
|
||||||
mask = BM_ALLBITS << ( BM_WORDBITS - (bm->w % BM_WORDBITS) );
|
mask = BM_ALLBITS << ( BM_WORDBITS - ( bm->w % BM_WORDBITS ) );
|
||||||
|
|
||||||
for( y = 0; y<bm->h; y++ )
|
for( y = 0; y < bm->h; y++ )
|
||||||
{
|
{
|
||||||
*bm_index( bm, bm->w, y ) &= mask;
|
*bm_index( bm, bm->w, y ) &= mask;
|
||||||
}
|
}
|
||||||
|
@ -80,13 +84,13 @@ typedef struct bbox_s bbox_t;
|
||||||
* than clearing the whole bitmap) */
|
* than clearing the whole bitmap) */
|
||||||
static void clear_bm_with_bbox( potrace_bitmap_t* bm, bbox_t* bbox )
|
static void clear_bm_with_bbox( potrace_bitmap_t* bm, bbox_t* bbox )
|
||||||
{
|
{
|
||||||
int imin = (bbox->x0 / BM_WORDBITS);
|
int imin = ( bbox->x0 / BM_WORDBITS );
|
||||||
int imax = ( (bbox->x1 + BM_WORDBITS - 1) / BM_WORDBITS );
|
int imax = ( ( bbox->x1 + BM_WORDBITS - 1 ) / BM_WORDBITS );
|
||||||
int i, y;
|
int i, y;
|
||||||
|
|
||||||
for( y = bbox->y0; y<bbox->y1; y++ )
|
for( y = bbox->y0; y < bbox->y1; y++ )
|
||||||
{
|
{
|
||||||
for( i = imin; i<imax; i++ )
|
for( i = imin; i < imax; i++ )
|
||||||
{
|
{
|
||||||
bm_scanline( bm, y )[i] = 0;
|
bm_scanline( bm, y )[i] = 0;
|
||||||
}
|
}
|
||||||
|
@ -103,11 +107,12 @@ static int majority( potrace_bitmap_t* bm, int x, int y )
|
||||||
{
|
{
|
||||||
int i, a, ct;
|
int i, a, ct;
|
||||||
|
|
||||||
for( i = 2; i<5; i++ ) /* check at "radius" i */
|
for( i = 2; i < 5; i++ )
|
||||||
{
|
{
|
||||||
|
/* check at "radius" i */
|
||||||
ct = 0;
|
ct = 0;
|
||||||
|
|
||||||
for( a = -i + 1; a<=i - 1; a++ )
|
for( a = -i + 1; a <= i - 1; a++ )
|
||||||
{
|
{
|
||||||
ct += BM_GET( bm, x + a, y + i - 1 ) ? 1 : -1;
|
ct += BM_GET( bm, x + a, y + i - 1 ) ? 1 : -1;
|
||||||
ct += BM_GET( bm, x + i - 1, y + a - 1 ) ? 1 : -1;
|
ct += BM_GET( bm, x + i - 1, y + a - 1 ) ? 1 : -1;
|
||||||
|
@ -115,11 +120,11 @@ static int majority( potrace_bitmap_t* bm, int x, int y )
|
||||||
ct += BM_GET( bm, x - i, y + a ) ? 1 : -1;
|
ct += BM_GET( bm, x - i, y + a ) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ct>0 )
|
if( ct > 0 )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if( ct<0 )
|
else if( ct < 0 )
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -137,10 +142,10 @@ static int majority( potrace_bitmap_t* bm, int x, int y )
|
||||||
static void xor_to_ref( potrace_bitmap_t* bm, int x, int y, int xa )
|
static void xor_to_ref( potrace_bitmap_t* bm, int x, int y, int xa )
|
||||||
{
|
{
|
||||||
int xhi = x & - BM_WORDBITS;
|
int xhi = x & - BM_WORDBITS;
|
||||||
int xlo = x & (BM_WORDBITS - 1); /* = x % BM_WORDBITS */
|
int xlo = x & ( BM_WORDBITS - 1 ); /* = x % BM_WORDBITS */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( xhi<xa )
|
if( xhi < xa )
|
||||||
{
|
{
|
||||||
for( i = xhi; i < xa; i += BM_WORDBITS )
|
for( i = xhi; i < xa; i += BM_WORDBITS )
|
||||||
{
|
{
|
||||||
|
@ -159,7 +164,7 @@ static void xor_to_ref( potrace_bitmap_t* bm, int x, int y, int xa )
|
||||||
* a<<(b&31). I spent hours looking for this bug. */
|
* a<<(b&31). I spent hours looking for this bug. */
|
||||||
if( xlo )
|
if( xlo )
|
||||||
{
|
{
|
||||||
*bm_index( bm, xhi, y ) ^= ( BM_ALLBITS << (BM_WORDBITS - xlo) );
|
*bm_index( bm, xhi, y ) ^= ( BM_ALLBITS << ( BM_WORDBITS - xlo ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +181,9 @@ static void xor_path( potrace_bitmap_t* bm, path_t* p )
|
||||||
{
|
{
|
||||||
int xa, x, y, k, y1;
|
int xa, x, y, k, y1;
|
||||||
|
|
||||||
if( p->priv->len <= 0 ) /* a path of length 0 is silly, but legal */
|
if( p->priv->len <= 0 )
|
||||||
{
|
{
|
||||||
|
/* a path of length 0 is silly, but legal */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +191,7 @@ static void xor_path( potrace_bitmap_t* bm, path_t* p )
|
||||||
|
|
||||||
xa = p->priv->pt[0].x & - BM_WORDBITS;
|
xa = p->priv->pt[0].x & - BM_WORDBITS;
|
||||||
|
|
||||||
for( k = 0; k<p->priv->len; k++ )
|
for( k = 0; k < p->priv->len; k++ )
|
||||||
{
|
{
|
||||||
x = p->priv->pt[k].x;
|
x = p->priv->pt[k].x;
|
||||||
y = p->priv->pt[k].y;
|
y = p->priv->pt[k].y;
|
||||||
|
@ -212,7 +218,7 @@ static void setbbox_path( bbox_t* bbox, path_t* p )
|
||||||
bbox->x0 = INT_MAX;
|
bbox->x0 = INT_MAX;
|
||||||
bbox->x1 = 0;
|
bbox->x1 = 0;
|
||||||
|
|
||||||
for( k = 0; k<p->priv->len; k++ )
|
for( k = 0; k < p->priv->len; k++ )
|
||||||
{
|
{
|
||||||
x = p->priv->pt[k].x;
|
x = p->priv->pt[k].x;
|
||||||
y = p->priv->pt[k].y;
|
y = p->priv->pt[k].y;
|
||||||
|
@ -248,7 +254,8 @@ static void setbbox_path( bbox_t* bbox, path_t* p )
|
||||||
* of turnpolicies. */
|
* of turnpolicies. */
|
||||||
static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int turnpolicy )
|
static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int turnpolicy )
|
||||||
{
|
{
|
||||||
int x, y, dirx, diry, len, size, area;
|
int x, y, dirx, diry, len, size;
|
||||||
|
uint64_t area;
|
||||||
int c, d, tmp;
|
int c, d, tmp;
|
||||||
point_t* pt, * pt1;
|
point_t* pt, * pt1;
|
||||||
path_t* p = NULL;
|
path_t* p = NULL;
|
||||||
|
@ -265,11 +272,11 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
/* add point to path */
|
/* add point to path */
|
||||||
if( len>=size )
|
if( len >= size )
|
||||||
{
|
{
|
||||||
size += 100;
|
size += 100;
|
||||||
size = (int) (1.3 * size);
|
size = (int) ( 1.3 * size );
|
||||||
pt1 = (point_t*) realloc( pt, size * sizeof(point_t) );
|
pt1 = (point_t*) realloc( pt, size * sizeof( point_t ) );
|
||||||
|
|
||||||
if( !pt1 )
|
if( !pt1 )
|
||||||
{
|
{
|
||||||
|
@ -289,20 +296,21 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
area += x * diry;
|
area += x * diry;
|
||||||
|
|
||||||
/* path complete? */
|
/* path complete? */
|
||||||
if( x==x0 && y==y0 )
|
if( x == x0 && y == y0 )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine next direction */
|
/* determine next direction */
|
||||||
c = BM_GET( bm, x + (dirx + diry - 1) / 2, y + (diry - dirx - 1) / 2 );
|
c = BM_GET( bm, x + ( dirx + diry - 1 ) / 2, y + ( diry - dirx - 1 ) / 2 );
|
||||||
d = BM_GET( bm, x + (dirx - diry - 1) / 2, y + (diry + dirx - 1) / 2 );
|
d = BM_GET( bm, x + ( dirx - diry - 1 ) / 2, y + ( diry + dirx - 1 ) / 2 );
|
||||||
|
|
||||||
if( c && !d ) /* ambiguous turn */
|
if( c && !d )
|
||||||
{
|
{
|
||||||
|
/* ambiguous turn */
|
||||||
if( turnpolicy == POTRACE_TURNPOLICY_RIGHT
|
if( turnpolicy == POTRACE_TURNPOLICY_RIGHT
|
||||||
|| (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
|
|| ( turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+' )
|
||||||
|| (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
|
|| ( turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-' )
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand( x, y ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand( x, y ) )
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority( bm, x, y ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority( bm, x, y ) )
|
||||||
|| ( turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority( bm, x, y ) ) )
|
|| ( turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority( bm, x, y ) ) )
|
||||||
|
@ -318,14 +326,16 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
diry = tmp;
|
diry = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( c ) /* right turn */
|
else if( c )
|
||||||
{
|
{
|
||||||
|
/* right turn */
|
||||||
tmp = dirx;
|
tmp = dirx;
|
||||||
dirx = diry;
|
dirx = diry;
|
||||||
diry = -tmp;
|
diry = -tmp;
|
||||||
}
|
}
|
||||||
else if( !d ) /* left turn */
|
else if( !d )
|
||||||
{
|
{
|
||||||
|
/* left turn */
|
||||||
tmp = dirx;
|
tmp = dirx;
|
||||||
dirx = -diry;
|
dirx = -diry;
|
||||||
diry = tmp;
|
diry = tmp;
|
||||||
|
@ -342,7 +352,7 @@ static path_t* findpath( potrace_bitmap_t* bm, int x0, int y0, int sign, int tur
|
||||||
|
|
||||||
p->priv->pt = pt;
|
p->priv->pt = pt;
|
||||||
p->priv->len = len;
|
p->priv->len = len;
|
||||||
p->area = area;
|
p->area = area <= INT_MAX ? area : INT_MAX; /* avoid overflow */
|
||||||
p->sign = sign;
|
p->sign = sign;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
@ -519,11 +529,11 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
||||||
int y;
|
int y;
|
||||||
int x0;
|
int x0;
|
||||||
|
|
||||||
x0 = (*xp) & ~(BM_WORDBITS - 1);
|
x0 = ( *xp ) & ~( BM_WORDBITS - 1 );
|
||||||
|
|
||||||
for( y = *yp; y>=0; y-- )
|
for( y = *yp; y >= 0; y-- )
|
||||||
{
|
{
|
||||||
for( x = x0; x<bm->w; x += BM_WORDBITS )
|
for( x = x0; x < bm->w && x >= 0; x += (unsigned) BM_WORDBITS )
|
||||||
{
|
{
|
||||||
if( *bm_index( bm, x, y ) )
|
if( *bm_index( bm, x, y ) )
|
||||||
{
|
{
|
||||||
|
@ -552,9 +562,7 @@ static int findnext( potrace_bitmap_t* bm, int* xp, int* yp )
|
||||||
* in. Returns 0 on success with plistp set, or -1 on error with errno
|
* in. Returns 0 on success with plistp set, or -1 on error with errno
|
||||||
* set. */
|
* set. */
|
||||||
|
|
||||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
int bm_to_pathlist( const potrace_bitmap_t* bm, path_t** plistp, const potrace_param_t* param,
|
||||||
path_t** plistp,
|
|
||||||
const potrace_param_t* param,
|
|
||||||
progress_t* progress )
|
progress_t* progress )
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
@ -588,7 +596,7 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
/* calculate the path */
|
/* calculate the path */
|
||||||
p = findpath( bm1, x, y + 1, sign, param->turnpolicy );
|
p = findpath( bm1, x, y + 1, sign, param->turnpolicy );
|
||||||
|
|
||||||
if( p==NULL )
|
if( p == NULL )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -606,8 +614,9 @@ int bm_to_pathlist( const potrace_bitmap_t* bm,
|
||||||
list_insert_beforehook( p, plist_hook );
|
list_insert_beforehook( p, plist_hook );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bm1->h > 0 ) /* to be sure */
|
if( bm1->h > 0 )
|
||||||
{
|
{
|
||||||
|
/* to be sure */
|
||||||
progress_update( 1 - y / (double) bm1->h, progress );
|
progress_update( 1 - y / (double) bm1->h, progress );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
#ifndef DECOMPOSE_H
|
#ifndef DECOMPOSE_H
|
||||||
#define DECOMPOSE_H
|
#define DECOMPOSE_H
|
||||||
|
|
||||||
|
#include "curve.h"
|
||||||
#include "potracelib.h"
|
#include "potracelib.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "curve.h"
|
|
||||||
|
|
||||||
int bm_to_pathlist( const potrace_bitmap_t* bm,
|
int bm_to_pathlist( const potrace_bitmap_t* bm, path_t** plistp, const potrace_param_t* param,
|
||||||
path_t** plistp,
|
|
||||||
const potrace_param_t* param,
|
|
||||||
progress_t* progress );
|
progress_t* progress );
|
||||||
|
|
||||||
#endif /* DECOMPOSE_H */
|
#endif /* DECOMPOSE_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,44 +1,50 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
#ifndef GREYMAP_H
|
#ifndef GREYMAP_H
|
||||||
#define GREYMAP_H
|
#define GREYMAP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
/* type for greymap samples */
|
||||||
|
typedef signed short int gm_sample_t;
|
||||||
|
|
||||||
/* internal format for greymaps. Note: in this format, rows are
|
/* internal format for greymaps. Note: in this format, rows are
|
||||||
* ordered from bottom to top. The pixels in each row are given from
|
* ordered from bottom to top. The pixels in each row are given from
|
||||||
* left to right. */
|
* left to right. */
|
||||||
|
|
||||||
struct greymap_s
|
struct greymap_s
|
||||||
{
|
{
|
||||||
int w; /* width, in pixels */
|
int w; /* width, in pixels */
|
||||||
int h; /* height, in pixels */
|
int h; /* height, in pixels */
|
||||||
signed short int* map; /* raw data, w*h values */
|
int dy; /* offset between scanlines (in samples);
|
||||||
|
* can be negative */
|
||||||
|
gm_sample_t* base; /* root of allocated data */
|
||||||
|
gm_sample_t* map; /* points to the lower left pixel */
|
||||||
};
|
};
|
||||||
typedef struct greymap_s greymap_t;
|
typedef struct greymap_s greymap_t;
|
||||||
|
|
||||||
/* macros for accessing pixel at index (x,y). Note that the origin is
|
/* macros for accessing pixel at index (x,y). Note that the origin is
|
||||||
* in the *lower* left corner. U* macros omit the bounds check. */
|
* in the *lower* left corner. U* macros omit the bounds check. */
|
||||||
|
|
||||||
#define gm_index( gm, x, y ) (&(gm)->map[(x) + (y) * (ptrdiff_t) (gm)->w])
|
#define gm_scanline( gm, y ) ( ( gm )->map + (ptrdiff_t) ( y ) * (ptrdiff_t) ( gm )->dy )
|
||||||
#define gm_safe( gm, x, \
|
#define gm_index( gm, x, y ) ( gm_scanline( gm, y ) + ( x ) )
|
||||||
y ) ( (int) (x)>=0 && (int) (x)<(gm)->w && (int) (y)>=0 \
|
#define gm_safe( gm, x, y ) \
|
||||||
&& (int) (y)<(gm)->h )
|
( (int) ( x ) >= 0 && (int) ( x ) < ( gm )->w && (int) ( y ) >= 0 && (int) ( y ) < ( gm )->h )
|
||||||
#define gm_bound( x, m ) ( (x)<0 ? 0 : (x)>=(m) ? (m) - 1 : (x) )
|
#define gm_bound( x, m ) ( ( x ) < 0 ? 0 : ( x ) >= ( m ) ? (m) - 1 : ( x ) )
|
||||||
#define GM_UGET( gm, x, y ) ( *gm_index( gm, x, y ) )
|
#define GM_UGET( gm, x, y ) ( *gm_index( gm, x, y ) )
|
||||||
#define GM_UINC( gm, x, y, b ) ( *gm_index( gm, x, y ) += (short int) (b) )
|
#define GM_UINC( gm, x, y, b ) ( *gm_index( gm, x, y ) += (gm_sample_t) ( b ) )
|
||||||
#define GM_UINV( gm, x, y ) ( *gm_index( gm, x, y ) = 255 - *gm_index( gm, x, y ) )
|
#define GM_UINV( gm, x, y ) ( *gm_index( gm, x, y ) = 255 - *gm_index( gm, x, y ) )
|
||||||
#define GM_UPUT( gm, x, y, b ) ( *gm_index( gm, x, y ) = (short int) (b) )
|
#define GM_UPUT( gm, x, y, b ) ( *gm_index( gm, x, y ) = (gm_sample_t) ( b ) )
|
||||||
#define GM_GET( gm, x, y ) (gm_safe( gm, x, y ) ? GM_UGET( gm, x, y ) : 0)
|
#define GM_GET( gm, x, y ) ( gm_safe( gm, x, y ) ? GM_UGET( gm, x, y ) : 0 )
|
||||||
#define GM_INC( gm, x, y, b ) (gm_safe( gm, x, y ) ? GM_UINC( gm, x, y, b ) : 0)
|
#define GM_INC( gm, x, y, b ) ( gm_safe( gm, x, y ) ? GM_UINC( gm, x, y, b ) : 0 )
|
||||||
#define GM_INV( gm, x, y ) (gm_safe( gm, x, y ) ? GM_UINV( gm, x, y ) : 0)
|
#define GM_INV( gm, x, y ) ( gm_safe( gm, x, y ) ? GM_UINV( gm, x, y ) : 0 )
|
||||||
#define GM_PUT( gm, x, y, b ) (gm_safe( gm, x, y ) ? GM_UPUT( gm, x, y, b ) : 0)
|
#define GM_PUT( gm, x, y, b ) ( gm_safe( gm, x, y ) ? GM_UPUT( gm, x, y, b ) : 0 )
|
||||||
#define GM_BGET( gm, x, y ) GM_UGET( gm, gm_bound( x, gm->w ), gm_bound( y, gm->h ) )
|
#define GM_BGET( gm, x, y ) \
|
||||||
|
( ( gm )->w == 0 || ( gm )->h == 0 ? 0 : GM_UGET( gm, gm_bound( x, ( gm )->w ), \
|
||||||
|
gm_bound( y, ( gm )->h ) ) )
|
||||||
|
|
||||||
/* modes for cutting off out-of-range values. The following names
|
/* modes for cutting off out-of-range values. The following names
|
||||||
* refer to winding numbers. I.e., make a pixel black if winding
|
* refer to winding numbers. I.e., make a pixel black if winding
|
||||||
|
@ -56,7 +62,12 @@ greymap_t* gm_dup( greymap_t* gm );
|
||||||
void gm_free( greymap_t* gm );
|
void gm_free( greymap_t* gm );
|
||||||
void gm_clear( greymap_t* gm, int b );
|
void gm_clear( greymap_t* gm, int b );
|
||||||
int gm_read( FILE* f, greymap_t** gmp );
|
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_writepgm( FILE* f,
|
||||||
|
greymap_t* gm,
|
||||||
|
const char* comment,
|
||||||
|
int raw,
|
||||||
|
int mode,
|
||||||
|
double gamma );
|
||||||
int gm_print( FILE* f, greymap_t* gm );
|
int gm_print( FILE* f, greymap_t* gm );
|
||||||
|
|
||||||
#endif /* GREYMAP_H */
|
#endif /* GREYMAP_H */
|
||||||
|
|
125
potrace/lists.h
125
potrace/lists.h
|
@ -1,8 +1,7 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
#ifndef _PS_LISTS_H
|
#ifndef _PS_LISTS_H
|
||||||
#define _PS_LISTS_H
|
#define _PS_LISTS_H
|
||||||
|
|
||||||
|
@ -31,15 +30,18 @@
|
||||||
* such as "if (...) macro(...); else ...". If we didn't use this obscure
|
* such as "if (...) macro(...); else ...". If we didn't use this obscure
|
||||||
* trick, we'd have to omit the ";" in such cases. */
|
* trick, we'd have to omit the ";" in such cases. */
|
||||||
|
|
||||||
#define MACRO_BEGIN do {
|
#define MACRO_BEGIN \
|
||||||
#define MACRO_END } \
|
do \
|
||||||
|
{
|
||||||
|
#define MACRO_END \
|
||||||
|
} \
|
||||||
while( 0 )
|
while( 0 )
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* macros for singly-linked lists */
|
/* macros for singly-linked lists */
|
||||||
|
|
||||||
/* traverse list. At the end, elt is set to NULL. */
|
/* traverse list. At the end, elt is set to NULL. */
|
||||||
#define list_forall( elt, list ) for( elt = list; elt!=NULL; elt = elt->next )
|
#define list_forall( elt, list ) for( elt = list; elt != NULL; elt = elt->next )
|
||||||
|
|
||||||
/* set elt to the first element of list satisfying boolean condition
|
/* set elt to the first element of list satisfying boolean condition
|
||||||
* c, or NULL if not found */
|
* c, or NULL if not found */
|
||||||
|
@ -50,7 +52,7 @@
|
||||||
|
|
||||||
/* like forall, except also set hook for elt. */
|
/* like forall, except also set hook for elt. */
|
||||||
#define list_forall2( elt, list, hook ) \
|
#define list_forall2( elt, list, hook ) \
|
||||||
for( elt = list, hook = &list; elt!=NULL; hook = &elt->next, elt = elt->next )
|
for( elt = list, hook = &list; elt != NULL; hook = &elt->next, elt = elt->next )
|
||||||
|
|
||||||
/* same as list_find, except also set hook for elt. */
|
/* same as list_find, except also set hook for elt. */
|
||||||
#define list_find2( elt, list, c, hook ) \
|
#define list_find2( elt, list, c, hook ) \
|
||||||
|
@ -59,8 +61,7 @@
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* same, except only use hook. */
|
/* same, except only use hook. */
|
||||||
#define _list_forall_hook( list, hook ) \
|
#define _list_forall_hook( list, hook ) for( hook = &list; *hook != NULL; hook = &( *hook )->next )
|
||||||
for( hook = &list; *hook!=NULL; hook = &(*hook)->next )
|
|
||||||
|
|
||||||
/* same, except only use hook. Note: c may only refer to *hook, not elt. */
|
/* same, except only use hook. Note: c may only refer to *hook, not elt. */
|
||||||
#define _list_find_hook( list, c, hook ) \
|
#define _list_find_hook( list, c, hook ) \
|
||||||
|
@ -70,17 +71,27 @@
|
||||||
|
|
||||||
/* insert element after hook */
|
/* insert element after hook */
|
||||||
#define list_insert_athook( elt, hook ) \
|
#define list_insert_athook( elt, hook ) \
|
||||||
MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
|
MACRO_BEGIN elt->next = *hook; \
|
||||||
|
*hook = elt; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* insert element before hook */
|
/* insert element before hook */
|
||||||
#define list_insert_beforehook( elt, hook ) \
|
#define list_insert_beforehook( elt, hook ) \
|
||||||
MACRO_BEGIN elt->next = *hook; *hook = elt; hook = &elt->next; MACRO_END
|
MACRO_BEGIN elt->next = *hook; \
|
||||||
|
*hook = elt; \
|
||||||
|
hook = &elt->next; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* unlink element after hook, let elt be unlinked element, or NULL.
|
/* unlink element after hook, let elt be unlinked element, or NULL.
|
||||||
* hook remains. */
|
* hook remains. */
|
||||||
#define list_unlink_athook( list, elt, hook ) \
|
#define list_unlink_athook( list, elt, hook ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
elt = hook ? *hook : NULL; if( elt ) { *hook = elt->next; elt->next = NULL; } \
|
elt = hook ? *hook : NULL; \
|
||||||
|
if( elt ) \
|
||||||
|
{ \
|
||||||
|
*hook = elt->next; \
|
||||||
|
elt->next = NULL; \
|
||||||
|
} \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* unlink the specific element, if it is in the list. Otherwise, set
|
/* unlink the specific element, if it is in the list. Otherwise, set
|
||||||
|
@ -88,19 +99,23 @@
|
||||||
#define list_unlink( listtype, list, elt ) \
|
#define list_unlink( listtype, list, elt ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * *_hook; \
|
listtype * *_hook; \
|
||||||
_list_find_hook( list, *_hook==elt, _hook ); \
|
_list_find_hook( list, *_hook == elt, _hook ); \
|
||||||
list_unlink_athook( list, elt, _hook ); \
|
list_unlink_athook( list, elt, _hook ); \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* prepend elt to list */
|
/* prepend elt to list */
|
||||||
#define list_prepend( list, elt ) \
|
#define list_prepend( list, elt ) \
|
||||||
MACRO_BEGIN elt->next = list; list = elt; MACRO_END
|
MACRO_BEGIN elt->next = list; \
|
||||||
|
list = elt; \
|
||||||
|
MACRO_END
|
||||||
|
|
||||||
/* append elt to list. */
|
/* append elt to list. */
|
||||||
#define list_append( listtype, list, elt ) \
|
#define list_append( listtype, list, elt ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * *_hook; \
|
listtype * *_hook; \
|
||||||
_list_forall_hook( list, _hook ) {} \
|
_list_forall_hook( list, _hook ) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
list_insert_athook( elt, _hook ); \
|
list_insert_athook( elt, _hook ); \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
|
@ -117,7 +132,9 @@
|
||||||
#define list_nth( elt, list, n ) \
|
#define list_nth( elt, list, n ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
int _x; /* only evaluate n once */ \
|
int _x; /* only evaluate n once */ \
|
||||||
for( _x = (n), elt = list; _x && elt; _x--, elt = elt->next ) {} \
|
for( _x = ( n ), elt = list; _x && elt; _x--, elt = elt->next ) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* let elt be the nth element of the list, starting to count from 0.
|
/* let elt be the nth element of the list, starting to count from 0.
|
||||||
|
@ -125,8 +142,10 @@
|
||||||
#define list_nth_hook( elt, list, n, hook ) \
|
#define list_nth_hook( elt, list, n, hook ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
int _x; /* only evaluate n once */ \
|
int _x; /* only evaluate n once */ \
|
||||||
for( _x = (n), elt = list, hook = &list; _x && elt; \
|
for( _x = ( n ), elt = list, hook = &list; _x && elt; \
|
||||||
_x--, hook = &elt->next, elt = elt->next ) {} \
|
_x--, hook = &elt->next, elt = elt->next ) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* set n to the length of the list */
|
/* set n to the length of the list */
|
||||||
|
@ -134,8 +153,7 @@
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * _elt; \
|
listtype * _elt; \
|
||||||
n = 0; \
|
n = 0; \
|
||||||
list_forall( _elt, list ) \
|
list_forall( _elt, list ) n++; \
|
||||||
n++; \
|
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* set n to the index of the first element satisfying cond, or -1 if
|
/* set n to the index of the first element satisfying cond, or -1 if
|
||||||
|
@ -143,7 +161,8 @@
|
||||||
#define list_index( list, n, elt, c ) \
|
#define list_index( list, n, elt, c ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
n = 0; \
|
n = 0; \
|
||||||
list_forall( elt, list ) { \
|
list_forall( elt, list ) \
|
||||||
|
{ \
|
||||||
if( c ) \
|
if( c ) \
|
||||||
break; \
|
break; \
|
||||||
n++; \
|
n++; \
|
||||||
|
@ -156,7 +175,8 @@
|
||||||
#define list_count( list, n, elt, c ) \
|
#define list_count( list, n, elt, c ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
n = 0; \
|
n = 0; \
|
||||||
list_forall( elt, list ) { \
|
list_forall( elt, list ) \
|
||||||
|
{ \
|
||||||
if( c ) \
|
if( c ) \
|
||||||
n++; \
|
n++; \
|
||||||
} \
|
} \
|
||||||
|
@ -164,14 +184,13 @@
|
||||||
|
|
||||||
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
||||||
#define list_forall_unlink( elt, list ) \
|
#define list_forall_unlink( elt, list ) \
|
||||||
for( elt = list; elt ? (list = elt->next, elt->next = NULL), 1 : 0; elt = list )
|
for( elt = list; elt ? ( list = elt->next, elt->next = NULL ), 1 : 0; elt = list )
|
||||||
|
|
||||||
/* reverse a list (efficient) */
|
/* reverse a list (efficient) */
|
||||||
#define list_reverse( listtype, list ) \
|
#define list_reverse( listtype, list ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * _list1 = NULL, *elt; \
|
listtype * _list1 = NULL, *elt; \
|
||||||
list_forall_unlink( elt, list ) \
|
list_forall_unlink( elt, list ) list_prepend( _list1, elt ); \
|
||||||
list_prepend( _list1, elt ); \
|
|
||||||
list = _list1; \
|
list = _list1; \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
|
@ -189,7 +208,7 @@
|
||||||
#define list_insert_ordered( listtype, list, elt, tmp, cond ) \
|
#define list_insert_ordered( listtype, list, elt, tmp, cond ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * *_hook; \
|
listtype * *_hook; \
|
||||||
_list_find_hook( list, ( tmp = *_hook, (cond) ), _hook ); \
|
_list_find_hook( list, ( tmp = *_hook, ( cond ) ), _hook ); \
|
||||||
list_insert_athook( elt, _hook ); \
|
list_insert_athook( elt, _hook ); \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
|
@ -203,8 +222,7 @@
|
||||||
#define list_sort( listtype, list, a, b, cond ) \
|
#define list_sort( listtype, list, a, b, cond ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * _newlist = NULL; \
|
listtype * _newlist = NULL; \
|
||||||
list_forall_unlink( a, list ) \
|
list_forall_unlink( a, list ) list_insert_ordered( listtype, _newlist, a, b, cond ); \
|
||||||
list_insert_ordered( listtype, _newlist, a, b, cond ); \
|
|
||||||
list = _newlist; \
|
list = _newlist; \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
|
@ -217,44 +235,52 @@
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * _elt, **_hook1; \
|
listtype * _elt, **_hook1; \
|
||||||
\
|
\
|
||||||
for( _elt = list; _elt; _elt = _elt->next1 ) { \
|
for( _elt = list; _elt; _elt = _elt->next1 ) \
|
||||||
|
{ \
|
||||||
_elt->next1 = _elt->next; \
|
_elt->next1 = _elt->next; \
|
||||||
_elt->next = NULL; \
|
_elt->next = NULL; \
|
||||||
} \
|
} \
|
||||||
do { \
|
do \
|
||||||
_hook1 = &(list); \
|
{ \
|
||||||
while( (a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
|
_hook1 = &( list ); \
|
||||||
|
while( ( a = *_hook1 ) != NULL && ( b = a->next1 ) != NULL ) \
|
||||||
|
{ \
|
||||||
_elt = b->next1; \
|
_elt = b->next1; \
|
||||||
_list_merge_cond( listtype, a, b, cond, *_hook1 ); \
|
_list_merge_cond( listtype, a, b, cond, *_hook1 ); \
|
||||||
_hook1 = &( (*_hook1)->next1 ); \
|
_hook1 = &( ( *_hook1 )->next1 ); \
|
||||||
*_hook1 = _elt; \
|
*_hook1 = _elt; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while( _hook1 != &(list) ); \
|
while( _hook1 != &( list ) ); \
|
||||||
MACRO_END
|
MACRO_END
|
||||||
|
|
||||||
/* merge two sorted lists. Store result at &result */
|
/* merge two sorted lists. Store result at &result */
|
||||||
#define _list_merge_cond( listtype, a, b, cond, result ) \
|
#define _list_merge_cond( listtype, a, b, cond, result ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
listtype * *_hook; \
|
listtype * *_hook; \
|
||||||
_hook = &(result); \
|
_hook = &( result ); \
|
||||||
while( 1 ) { \
|
while( 1 ) \
|
||||||
if( a==NULL ) { \
|
{ \
|
||||||
|
if( a == NULL ) \
|
||||||
|
{ \
|
||||||
*_hook = b; \
|
*_hook = b; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
else if( b==NULL ) { \
|
else if( b == NULL ) \
|
||||||
|
{ \
|
||||||
*_hook = a; \
|
*_hook = a; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
else if( cond ) { \
|
else if( cond ) \
|
||||||
|
{ \
|
||||||
*_hook = a; \
|
*_hook = a; \
|
||||||
_hook = &(a->next); \
|
_hook = &( a->next ); \
|
||||||
a = a->next; \
|
a = a->next; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else \
|
||||||
|
{ \
|
||||||
*_hook = b; \
|
*_hook = b; \
|
||||||
_hook = &(b->next); \
|
_hook = &( b->next ); \
|
||||||
b = b->next; \
|
b = b->next; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -267,10 +293,12 @@
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
elt->prev = end; \
|
elt->prev = end; \
|
||||||
elt->next = NULL; \
|
elt->next = NULL; \
|
||||||
if( end ) { \
|
if( end ) \
|
||||||
|
{ \
|
||||||
end->next = elt; \
|
end->next = elt; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else \
|
||||||
|
{ \
|
||||||
head = elt; \
|
head = elt; \
|
||||||
} \
|
} \
|
||||||
end = elt; \
|
end = elt; \
|
||||||
|
@ -279,19 +307,22 @@
|
||||||
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
|
||||||
#define dlist_forall_unlink( elt, head, end ) \
|
#define dlist_forall_unlink( elt, head, end ) \
|
||||||
for( elt = head; \
|
for( elt = head; \
|
||||||
elt ? (head = elt->next, elt->next = NULL, elt->prev = NULL), 1 : (end = NULL, 0); \
|
elt ? ( head = elt->next, elt->next = NULL, elt->prev = NULL ), 1 : ( end = NULL, 0 ); \
|
||||||
elt = head )
|
elt = head )
|
||||||
|
|
||||||
/* unlink the first element of the list */
|
/* unlink the first element of the list */
|
||||||
#define dlist_unlink_first( head, end, elt ) \
|
#define dlist_unlink_first( head, end, elt ) \
|
||||||
MACRO_BEGIN \
|
MACRO_BEGIN \
|
||||||
elt = head; \
|
elt = head; \
|
||||||
if( head ) { \
|
if( head ) \
|
||||||
|
{ \
|
||||||
head = head->next; \
|
head = head->next; \
|
||||||
if( head ) { \
|
if( head ) \
|
||||||
|
{ \
|
||||||
head->prev = NULL; \
|
head->prev = NULL; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else \
|
||||||
|
{ \
|
||||||
end = NULL; \
|
end = NULL; \
|
||||||
} \
|
} \
|
||||||
elt->prev = NULL; \
|
elt->prev = NULL; \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
#define PLATFORM_H
|
#define PLATFORM_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* in Windows, set all file i/o to binary */
|
/* in Windows, set all file i/o to binary */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
#define POTRACELIB_VERSION "potracelib 1.13"
|
#define POTRACELIB_VERSION "potracelib 1.15"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -9,12 +9,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "potracelib.h"
|
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
#include "decompose.h"
|
#include "decompose.h"
|
||||||
#include "trace.h"
|
#include "potracelib.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include <potrace_version.h>
|
#include "trace.h"
|
||||||
|
|
||||||
/* default parameters */
|
/* default parameters */
|
||||||
static const potrace_param_t param_default =
|
static const potrace_param_t param_default =
|
||||||
|
@ -38,14 +37,14 @@ potrace_param_t* potrace_param_default( void )
|
||||||
{
|
{
|
||||||
potrace_param_t* p;
|
potrace_param_t* p;
|
||||||
|
|
||||||
p = (potrace_param_t*) malloc( sizeof(potrace_param_t) );
|
p = (potrace_param_t*) malloc( sizeof( potrace_param_t ) );
|
||||||
|
|
||||||
if( !p )
|
if( !p )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( p, ¶m_default, sizeof(potrace_param_t) );
|
memcpy( p, ¶m_default, sizeof( potrace_param_t ) );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +72,7 @@ potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitm
|
||||||
prog.d_prev = param->progress.min;
|
prog.d_prev = param->progress.min;
|
||||||
|
|
||||||
/* allocate state object */
|
/* allocate state object */
|
||||||
st = (potrace_state_t*) malloc( sizeof(potrace_state_t) );
|
st = (potrace_state_t*) malloc( sizeof( potrace_state_t ) );
|
||||||
|
|
||||||
if( !st )
|
if( !st )
|
||||||
{
|
{
|
||||||
|
@ -128,6 +127,7 @@ void potrace_param_free( potrace_param_t* p )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "potrace_version.h"
|
||||||
const char* potrace_version( void )
|
const char* potrace_version( void )
|
||||||
{
|
{
|
||||||
return POTRACELIB_VERSION;
|
return POTRACELIB_VERSION;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ extern "C" {
|
||||||
/* structure to hold progress bar callback data */
|
/* structure to hold progress bar callback data */
|
||||||
struct potrace_progress_s
|
struct potrace_progress_s
|
||||||
{
|
{
|
||||||
void (* callback)( double progress, void* privdata ); /* callback fn */
|
void ( * callback )( double progress, void* privdata ); /* callback fn */
|
||||||
void* data; /* callback function's private data */
|
void* data; /* callback function's private data */
|
||||||
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
||||||
double epsilon; /* granularity: can skip smaller increments */
|
double epsilon; /* granularity: can skip smaller increments */
|
||||||
|
@ -128,9 +128,8 @@ potrace_param_t* potrace_param_default( void );
|
||||||
/* free parameter set */
|
/* free parameter set */
|
||||||
void potrace_param_free( potrace_param_t* p );
|
void potrace_param_free( potrace_param_t* p );
|
||||||
|
|
||||||
/* trace a bitmap*/
|
/* trace a bitmap */
|
||||||
potrace_state_t* potrace_trace( const potrace_param_t* param,
|
potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitmap_t* bm );
|
||||||
const potrace_bitmap_t* bm );
|
|
||||||
|
|
||||||
/* free a Potrace state */
|
/* free a Potrace state */
|
||||||
void potrace_state_free( potrace_state_t* st );
|
void potrace_state_free( potrace_state_t* st );
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
/* structure to hold progress bar callback data */
|
/* structure to hold progress bar callback data */
|
||||||
struct progress_s
|
struct progress_s
|
||||||
{
|
{
|
||||||
void (* callback)( double progress, void* privdata ); /* callback fn */
|
void ( * callback )( double progress, void* privdata ); /* callback fn */
|
||||||
void* data; /* callback function's private data */
|
void* data; /* callback function's private data */
|
||||||
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
|
||||||
double epsilon; /* granularity: can skip smaller increments */
|
double epsilon; /* granularity: can skip smaller increments */
|
||||||
|
@ -32,11 +32,11 @@ static inline void progress_update( double d, progress_t* prog )
|
||||||
|
|
||||||
if( prog != NULL && prog->callback != NULL )
|
if( prog != NULL && prog->callback != NULL )
|
||||||
{
|
{
|
||||||
d_scaled = prog->min * (1 - d) + prog->max * d;
|
d_scaled = prog->min * ( 1 - d ) + prog->max * d;
|
||||||
|
|
||||||
if( d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon )
|
if( d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon )
|
||||||
{
|
{
|
||||||
prog->callback( prog->min * (1 - d) + prog->max * d, prog->data );
|
prog->callback( prog->min * ( 1 - d ) + prog->max * d, prog->data );
|
||||||
prog->d_prev = d_scaled;
|
prog->d_prev = d_scaled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ static inline void progress_subrange_start( double a,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
min = prog->min * (1 - a) + prog->max * a;
|
min = prog->min * ( 1 - a ) + prog->max * a;
|
||||||
max = prog->min * (1 - b) + prog->max * b;
|
max = prog->min * ( 1 - b ) + prog->max * b;
|
||||||
|
|
||||||
if( max - min < prog->epsilon )
|
if( max - min < prog->epsilon )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "render.h"
|
|
||||||
#include "greymap.h"
|
|
||||||
#include "auxiliary.h"
|
#include "auxiliary.h"
|
||||||
|
#include "greymap.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* routines for anti-aliased rendering of curves */
|
/* routines for anti-aliased rendering of curves */
|
||||||
|
@ -50,16 +50,16 @@ render_t* render_new( greymap_t* gm )
|
||||||
{
|
{
|
||||||
render_t* rm;
|
render_t* rm;
|
||||||
|
|
||||||
rm = (render_t*) malloc( sizeof(render_t) );
|
rm = (render_t*) malloc( sizeof( render_t ) );
|
||||||
|
|
||||||
if( !rm )
|
if( !rm )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset( rm, 0, sizeof(render_t) );
|
memset( rm, 0, sizeof( render_t ) );
|
||||||
rm->gm = gm;
|
rm->gm = gm;
|
||||||
rm->incrow_buf = (int*) calloc( gm->h, sizeof(int) );
|
rm->incrow_buf = (int*) calloc( gm->h, sizeof( int ) );
|
||||||
|
|
||||||
if( !rm->incrow_buf )
|
if( !rm->incrow_buf )
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,6 @@ render_t* render_new( greymap_t* gm )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset( rm->incrow_buf, 0, gm->h * sizeof(int) );
|
|
||||||
return rm;
|
return rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +88,7 @@ void render_close( render_t* rm )
|
||||||
render_lineto( rm, rm->x0, rm->y0 );
|
render_lineto( rm, rm->x0, rm->y0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
GM_INC( rm->gm, rm->x0i, rm->y0i, (rm->a0 + rm->a1) * 255 );
|
GM_INC( rm->gm, rm->x0i, rm->y0i, ( rm->a0 + rm->a1 ) * 255 );
|
||||||
|
|
||||||
/* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
|
/* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
|
||||||
|
|
||||||
|
@ -144,14 +143,14 @@ static void incrow( render_t* rm, int x, int y, int b )
|
||||||
|
|
||||||
if( x0 < x )
|
if( x0 < x )
|
||||||
{
|
{
|
||||||
for( i = x0; i<x; i++ )
|
for( i = x0; i < x; i++ )
|
||||||
{
|
{
|
||||||
GM_INC( rm->gm, i, y, -b );
|
GM_INC( rm->gm, i, y, -b );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for( i = x; i<x0; i++ )
|
for( i = x; i < x0; i++ )
|
||||||
{
|
{
|
||||||
GM_INC( rm->gm, i, y, b );
|
GM_INC( rm->gm, i, y, b );
|
||||||
}
|
}
|
||||||
|
@ -179,14 +178,14 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
|
|
||||||
if( sn )
|
if( sn )
|
||||||
{
|
{
|
||||||
s0 = ( (x2>rm->x1 ? rm->x1i + 1 : rm->x1i) - rm->x1 ) / (x2 - rm->x1);
|
s0 = ( ( x2 > rm->x1 ? rm->x1i + 1 : rm->x1i ) - rm->x1 ) / ( x2 - rm->x1 );
|
||||||
ss = fabs( 1.0 / (x2 - rm->x1) );
|
ss = fabs( 1.0 / ( x2 - rm->x1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( tn )
|
if( tn )
|
||||||
{
|
{
|
||||||
t0 = ( (y2>rm->y1 ? rm->y1i + 1 : rm->y1i) - rm->y1 ) / (y2 - rm->y1);
|
t0 = ( ( y2 > rm->y1 ? rm->y1i + 1 : rm->y1i ) - rm->y1 ) / ( y2 - rm->y1 );
|
||||||
ts = fabs( 1.0 / (y2 - rm->y1) );
|
ts = fabs( 1.0 / ( y2 - rm->y1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
r0 = 0;
|
r0 = 0;
|
||||||
|
@ -197,9 +196,9 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
rxi = rm->x1i;
|
rxi = rm->x1i;
|
||||||
ryi = rm->y1i;
|
ryi = rm->y1i;
|
||||||
|
|
||||||
while( i<sn || j<tn )
|
while( i < sn || j < tn )
|
||||||
{
|
{
|
||||||
if( j>=tn || (i<sn && s0 + i * ss < t0 + j * ts) )
|
if( j >= tn || ( i < sn && s0 + i * ss < t0 + j * ts ) )
|
||||||
{
|
{
|
||||||
r1 = s0 + i * ss;
|
r1 = s0 + i * ss;
|
||||||
i++;
|
i++;
|
||||||
|
@ -215,32 +214,32 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
|
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
|
||||||
|
|
||||||
/* move point to r1 */
|
/* move point to r1 */
|
||||||
rm->a1 += (r1 - r0) * (y2 - rm->y1) *
|
rm->a1 += ( r1 - r0 ) * ( y2 - rm->y1 )
|
||||||
( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
* ( rxi + 1 - ( ( r0 + r1 ) / 2.0 * ( x2 - rm->x1 ) + rm->x1 ) );
|
||||||
|
|
||||||
/* move point across pixel boundary */
|
/* move point across pixel boundary */
|
||||||
if( s && x2>rm->x1 )
|
if( s && x2 > rm->x1 )
|
||||||
{
|
{
|
||||||
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
||||||
rm->a1 = 0;
|
rm->a1 = 0;
|
||||||
rxi++;
|
rxi++;
|
||||||
rm->a1 += rm->y1 + r1 * (y2 - rm->y1) - ryi;
|
rm->a1 += rm->y1 + r1 * ( y2 - rm->y1 ) - ryi;
|
||||||
}
|
}
|
||||||
else if( !s && y2>rm->y1 )
|
else if( !s && y2 > rm->y1 )
|
||||||
{
|
{
|
||||||
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
||||||
rm->a1 = 0;
|
rm->a1 = 0;
|
||||||
incrow( rm, rxi + 1, ryi, 255 );
|
incrow( rm, rxi + 1, ryi, 255 );
|
||||||
ryi++;
|
ryi++;
|
||||||
}
|
}
|
||||||
else if( s && x2<=rm->x1 )
|
else if( s && x2 <= rm->x1 )
|
||||||
{
|
{
|
||||||
rm->a1 -= rm->y1 + r1 * (y2 - rm->y1) - ryi;
|
rm->a1 -= rm->y1 + r1 * ( y2 - rm->y1 ) - ryi;
|
||||||
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
||||||
rm->a1 = 0;
|
rm->a1 = 0;
|
||||||
rxi--;
|
rxi--;
|
||||||
}
|
}
|
||||||
else if( !s && y2<=rm->y1 )
|
else if( !s && y2 <= rm->y1 )
|
||||||
{
|
{
|
||||||
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
|
||||||
rm->a1 = 0;
|
rm->a1 = 0;
|
||||||
|
@ -254,8 +253,8 @@ void render_lineto( render_t* rm, double x2, double y2 )
|
||||||
/* move point to (x2,y2) */
|
/* move point to (x2,y2) */
|
||||||
|
|
||||||
r1 = 1;
|
r1 = 1;
|
||||||
rm->a1 += (r1 - r0) * (y2 - rm->y1) *
|
rm->a1 += ( r1 - r0 ) * ( y2 - rm->y1 )
|
||||||
( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
|
* ( rxi + 1 - ( ( r0 + r1 ) / 2.0 * ( x2 - rm->x1 ) + rm->x1 ) );
|
||||||
|
|
||||||
rm->x1i = x2i;
|
rm->x1i = x2i;
|
||||||
rm->y1i = y2i;
|
rm->y1i = y2i;
|
||||||
|
@ -290,12 +289,12 @@ void render_curveto( render_t* rm, double x2, double y2, double x3, double y3, d
|
||||||
e2 = 8 * delta <= dd ? 8 * delta / dd : 1;
|
e2 = 8 * delta <= dd ? 8 * delta / dd : 1;
|
||||||
epsilon = sqrt( e2 ); /* necessary interval size */
|
epsilon = sqrt( e2 ); /* necessary interval size */
|
||||||
|
|
||||||
for( t = epsilon; t<1; t += epsilon )
|
for( t = epsilon; t < 1; t += epsilon )
|
||||||
{
|
{
|
||||||
render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t + 3 * x3 * (1 - t) * sq(
|
render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t
|
||||||
t ) + x4 * cu( t ),
|
+ 3 * x3 * ( 1 - t ) * sq( t ) + x4 * cu( t ),
|
||||||
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq( t ) + y4 *
|
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * ( 1 - t ) * sq( t )
|
||||||
cu( t ) );
|
+ y4 * cu( t ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
render_lineto( rm, x4, y4 );
|
render_lineto( rm, x4, y4 );
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
#ifndef RENDER_H
|
#ifndef RENDER_H
|
||||||
#define RENDER_H
|
#define RENDER_H
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
@ -8,25 +8,26 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "potracelib.h"
|
#include "auxiliary.h"
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
#include "lists.h"
|
#include "lists.h"
|
||||||
#include "auxiliary.h"
|
#include "potracelib.h"
|
||||||
#include "trace.h"
|
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
#define INFTY 10000000 /* it suffices that this is longer than any
|
#define INFTY \
|
||||||
|
10000000 /* it suffices that this is longer than any
|
||||||
* path; it need not be really infinite */
|
* path; it need not be really infinite */
|
||||||
#define COS179 -0.999847695156 /* the cosine of 179 degrees */
|
#define COS179 -0.999847695156 /* the cosine of 179 degrees */
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
#define SAFE_CALLOC( var, n, typ ) \
|
#define SAFE_CALLOC( var, n, typ ) \
|
||||||
if( ( var = (typ*) calloc( n, sizeof(typ) ) ) == NULL ) \
|
if( ( var = (typ*) calloc( n, sizeof( typ ) ) ) == NULL ) \
|
||||||
goto calloc_error
|
goto calloc_error
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
@ -65,20 +66,20 @@ static inline double ddenom( dpoint_t p0, dpoint_t p2 )
|
||||||
{
|
{
|
||||||
point_t r = dorth_infty( p0, p2 );
|
point_t r = dorth_infty( p0, p2 );
|
||||||
|
|
||||||
return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y);
|
return r.y * ( p2.x - p0.x ) - r.x * ( p2.y - p0.y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
|
/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
|
||||||
static inline int cyclic( int a, int b, int c )
|
static inline int cyclic( int a, int b, int c )
|
||||||
{
|
{
|
||||||
if( a<=c )
|
if( a <= c )
|
||||||
{
|
{
|
||||||
return a<=b && b<c;
|
return a <= b && b < c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return a<=b || b<c;
|
return a <= b || b < c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,25 +98,25 @@ static void pointslope( privpath_t* pp, int i, int j, dpoint_t* ctr, dpoint_t* d
|
||||||
double a, b, c, lambda2, l;
|
double a, b, c, lambda2, l;
|
||||||
int r = 0; /* rotations from i to j */
|
int r = 0; /* rotations from i to j */
|
||||||
|
|
||||||
while( j>=n )
|
while( j >= n )
|
||||||
{
|
{
|
||||||
j -= n;
|
j -= n;
|
||||||
r += 1;
|
r += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( i>=n )
|
while( i >= n )
|
||||||
{
|
{
|
||||||
i -= n;
|
i -= n;
|
||||||
r -= 1;
|
r -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( j<0 )
|
while( j < 0 )
|
||||||
{
|
{
|
||||||
j += n;
|
j += n;
|
||||||
r -= 1;
|
r -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( i<0 )
|
while( i < 0 )
|
||||||
{
|
{
|
||||||
i += n;
|
i += n;
|
||||||
r += 1;
|
r += 1;
|
||||||
|
@ -131,11 +132,11 @@ static void pointslope( privpath_t* pp, int i, int j, dpoint_t* ctr, dpoint_t* d
|
||||||
ctr->x = x / k;
|
ctr->x = x / k;
|
||||||
ctr->y = y / k;
|
ctr->y = y / k;
|
||||||
|
|
||||||
a = (x2 - (double) x * x / k) / k;
|
a = ( x2 - (double) x * x / k ) / k;
|
||||||
b = (xy - (double) x * y / k) / k;
|
b = ( xy - (double) x * y / k ) / k;
|
||||||
c = (y2 - (double) y * y / k) / k;
|
c = ( y2 - (double) y * y / k ) / k;
|
||||||
|
|
||||||
lambda2 = ( a + c + sqrt( (a - c) * (a - c) + 4 * b * b ) ) / 2; /* larger e.value */
|
lambda2 = ( a + c + sqrt( ( a - c ) * ( a - c ) + 4 * b * b ) ) / 2; /* larger e.value */
|
||||||
|
|
||||||
/* now find e.vector for lambda2 */
|
/* now find e.vector for lambda2 */
|
||||||
a -= lambda2;
|
a -= lambda2;
|
||||||
|
@ -145,7 +146,7 @@ static void pointslope( privpath_t* pp, int i, int j, dpoint_t* ctr, dpoint_t* d
|
||||||
{
|
{
|
||||||
l = sqrt( a * a + b * b );
|
l = sqrt( a * a + b * b );
|
||||||
|
|
||||||
if( l!=0 )
|
if( l != 0 )
|
||||||
{
|
{
|
||||||
dir->x = -b / l;
|
dir->x = -b / l;
|
||||||
dir->y = a / l;
|
dir->y = a / l;
|
||||||
|
@ -155,14 +156,14 @@ static void pointslope( privpath_t* pp, int i, int j, dpoint_t* ctr, dpoint_t* d
|
||||||
{
|
{
|
||||||
l = sqrt( c * c + b * b );
|
l = sqrt( c * c + b * b );
|
||||||
|
|
||||||
if( l!=0 )
|
if( l != 0 )
|
||||||
{
|
{
|
||||||
dir->x = -c / l;
|
dir->x = -c / l;
|
||||||
dir->y = b / l;
|
dir->y = b / l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( l==0 )
|
if( l == 0 )
|
||||||
{
|
{
|
||||||
dir->x = dir->y = 0; /* sometimes this can happen when k=4:
|
dir->x = dir->y = 0; /* sometimes this can happen when k=4:
|
||||||
* the two eigenvalues coincide */
|
* the two eigenvalues coincide */
|
||||||
|
@ -187,9 +188,9 @@ static inline double quadform( quadform_t Q, dpoint_t w )
|
||||||
v[2] = 1;
|
v[2] = 1;
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
|
|
||||||
for( i = 0; i<3; i++ )
|
for( i = 0; i < 3; i++ )
|
||||||
{
|
{
|
||||||
for( j = 0; j<3; j++ )
|
for( j = 0; j < 3; j++ )
|
||||||
{
|
{
|
||||||
sum += v[i] * Q[i][j] * v[j];
|
sum += v[i] * Q[i][j] * v[j];
|
||||||
}
|
}
|
||||||
|
@ -265,8 +266,10 @@ static inline dpoint_t bezier( double t, dpoint_t p0, dpoint_t p1, dpoint_t p2,
|
||||||
* following to 16 multiplications, using common subexpression
|
* following to 16 multiplications, using common subexpression
|
||||||
* elimination. */
|
* elimination. */
|
||||||
|
|
||||||
res.x = s * s * s * p0.x + 3 * (s * s * t) * p1.x + 3 * (t * t * s) * p2.x + t * t * t * p3.x;
|
res.x = s * s * s * p0.x + 3 * ( s * s * t ) * p1.x + 3 * ( t * t * s ) * p2.x
|
||||||
res.y = s * s * s * p0.y + 3 * (s * s * t) * p1.y + 3 * (t * t * s) * p2.y + t * t * t * p3.y;
|
+ t * t * t * p3.x;
|
||||||
|
res.y = s * s * s * p0.y + 3 * ( s * s * t ) * p1.y + 3 * ( t * t * s ) * p2.y
|
||||||
|
+ t * t * t * p3.y;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -292,15 +295,15 @@ static double tangent( dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoin
|
||||||
|
|
||||||
d = b * b - 4 * a * c;
|
d = b * b - 4 * a * c;
|
||||||
|
|
||||||
if( a==0 || d<0 )
|
if( a == 0 || d < 0 )
|
||||||
{
|
{
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = sqrt( d );
|
s = sqrt( d );
|
||||||
|
|
||||||
r1 = (-b + s) / (2 * a);
|
r1 = ( -b + s ) / ( 2 * a );
|
||||||
r2 = (-b - s) / (2 * a);
|
r2 = ( -b - s ) / ( 2 * a );
|
||||||
|
|
||||||
if( r1 >= 0 && r1 <= 1 )
|
if( r1 >= 0 && r1 <= 1 )
|
||||||
{
|
{
|
||||||
|
@ -335,15 +338,15 @@ static int calc_sums( privpath_t* pp )
|
||||||
/* preparatory computation for later fast summing */
|
/* preparatory computation for later fast summing */
|
||||||
pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
|
pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
|
||||||
|
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
{
|
{
|
||||||
x = pp->pt[i].x - pp->x0;
|
x = pp->pt[i].x - pp->x0;
|
||||||
y = pp->pt[i].y - pp->y0;
|
y = pp->pt[i].y - pp->y0;
|
||||||
pp->sums[i + 1].x = pp->sums[i].x + x;
|
pp->sums[i + 1].x = pp->sums[i].x + x;
|
||||||
pp->sums[i + 1].y = pp->sums[i].y + y;
|
pp->sums[i + 1].y = pp->sums[i].y + y;
|
||||||
pp->sums[i + 1].x2 = pp->sums[i].x2 + x * x;
|
pp->sums[i + 1].x2 = pp->sums[i].x2 + (double) x * x;
|
||||||
pp->sums[i + 1].xy = pp->sums[i].xy + x * y;
|
pp->sums[i + 1].xy = pp->sums[i].xy + (double) x * y;
|
||||||
pp->sums[i + 1].y2 = pp->sums[i].y2 + y * y;
|
pp->sums[i + 1].y2 = pp->sums[i].y2 + (double) y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -409,7 +412,7 @@ static int calc_lon( privpath_t* pp )
|
||||||
* above. */
|
* above. */
|
||||||
k = 0;
|
k = 0;
|
||||||
|
|
||||||
for( i = n - 1; i>=0; i-- )
|
for( i = n - 1; i >= 0; i-- )
|
||||||
{
|
{
|
||||||
if( pt[i].x != pt[k].x && pt[i].y != pt[k].y )
|
if( pt[i].x != pt[k].x && pt[i].y != pt[k].y )
|
||||||
{
|
{
|
||||||
|
@ -424,12 +427,13 @@ static int calc_lon( privpath_t* pp )
|
||||||
/* determine pivot points: for each i, let pivk[i] be the furthest k
|
/* determine pivot points: for each i, let pivk[i] be the furthest k
|
||||||
* such that all j with i<j<k lie on a line connecting i,k. */
|
* such that all j with i<j<k lie on a line connecting i,k. */
|
||||||
|
|
||||||
for( i = n - 1; i>=0; i-- )
|
for( i = n - 1; i >= 0; i-- )
|
||||||
{
|
{
|
||||||
ct[0] = ct[1] = ct[2] = ct[3] = 0;
|
ct[0] = ct[1] = ct[2] = ct[3] = 0;
|
||||||
|
|
||||||
/* keep track of "directions" that have occurred */
|
/* keep track of "directions" that have occurred */
|
||||||
dir = ( 3 + 3 * (pt[mod( i + 1, n )].x - pt[i].x) + (pt[mod( i + 1, n )].y - pt[i].y) ) / 2;
|
dir = ( 3 + 3 * ( pt[mod( i + 1, n )].x - pt[i].x ) + ( pt[mod( i + 1, n )].y - pt[i].y ) )
|
||||||
|
/ 2;
|
||||||
ct[dir]++;
|
ct[dir]++;
|
||||||
|
|
||||||
constraint[0].x = 0;
|
constraint[0].x = 0;
|
||||||
|
@ -469,16 +473,16 @@ static int calc_lon( privpath_t* pp )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
off.x = cur.x + ( ( cur.y>=0 && (cur.y>0 || cur.x<0) ) ? 1 : -1 );
|
off.x = cur.x + ( ( cur.y >= 0 && ( cur.y > 0 || cur.x < 0 ) ) ? 1 : -1 );
|
||||||
off.y = cur.y + ( ( cur.x<=0 && (cur.x<0 || cur.y<0) ) ? 1 : -1 );
|
off.y = cur.y + ( ( cur.x <= 0 && ( cur.x < 0 || cur.y < 0 ) ) ? 1 : -1 );
|
||||||
|
|
||||||
if( xprod( constraint[0], off ) >= 0 )
|
if( xprod( constraint[0], off ) >= 0 )
|
||||||
{
|
{
|
||||||
constraint[0] = off;
|
constraint[0] = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
off.x = cur.x + ( ( cur.y<=0 && (cur.y<0 || cur.x<0) ) ? 1 : -1 );
|
off.x = cur.x + ( ( cur.y <= 0 && ( cur.y < 0 || cur.x < 0 ) ) ? 1 : -1 );
|
||||||
off.y = cur.y + ( ( cur.x>=0 && (cur.x>0 || cur.y<0) ) ? 1 : -1 );
|
off.y = cur.y + ( ( cur.x >= 0 && ( cur.x > 0 || cur.y < 0 ) ) ? 1 : -1 );
|
||||||
|
|
||||||
if( xprod( constraint[1], off ) <= 0 )
|
if( xprod( constraint[1], off ) <= 0 )
|
||||||
{
|
{
|
||||||
|
@ -514,19 +518,18 @@ constraint_viol:
|
||||||
* can be solved with integer arithmetic. */
|
* can be solved with integer arithmetic. */
|
||||||
j = INFTY;
|
j = INFTY;
|
||||||
|
|
||||||
if( b<0 )
|
if( b < 0 )
|
||||||
{
|
{
|
||||||
j = floordiv( a, -b );
|
j = floordiv( a, -b );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( d>0 )
|
if( d > 0 )
|
||||||
{
|
{
|
||||||
j = min( j, floordiv( -c, d ) );
|
j = min( j, floordiv( -c, d ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
pivk[i] = mod( k1 + j, n );
|
pivk[i] = mod( k1 + j, n );
|
||||||
foundk:
|
foundk:;
|
||||||
;
|
|
||||||
} /* for i */
|
} /* for i */
|
||||||
|
|
||||||
/* clean up: for each i, let lon[i] be the largest k such that for
|
/* clean up: for each i, let lon[i] be the largest k such that for
|
||||||
|
@ -535,7 +538,7 @@ foundk:
|
||||||
j = pivk[n - 1];
|
j = pivk[n - 1];
|
||||||
pp->lon[n - 1] = j;
|
pp->lon[n - 1] = j;
|
||||||
|
|
||||||
for( i = n - 2; i>=0; i-- )
|
for( i = n - 2; i >= 0; i-- )
|
||||||
{
|
{
|
||||||
if( cyclic( i + 1, pivk[i], j ) )
|
if( cyclic( i + 1, pivk[i], j ) )
|
||||||
{
|
{
|
||||||
|
@ -581,7 +584,7 @@ static double penalty3( privpath_t* pp, int i, int j )
|
||||||
|
|
||||||
int r = 0; /* rotations from i to j */
|
int r = 0; /* rotations from i to j */
|
||||||
|
|
||||||
if( j>=n )
|
if( j >= n )
|
||||||
{
|
{
|
||||||
j -= n;
|
j -= n;
|
||||||
r = 1;
|
r = 1;
|
||||||
|
@ -607,14 +610,14 @@ static double penalty3( privpath_t* pp, int i, int j )
|
||||||
k = j + 1 - i + n;
|
k = j + 1 - i + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
|
px = ( pt[i].x + pt[j].x ) / 2.0 - pt[0].x;
|
||||||
py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
|
py = ( pt[i].y + pt[j].y ) / 2.0 - pt[0].y;
|
||||||
ey = (pt[j].x - pt[i].x);
|
ey = ( pt[j].x - pt[i].x );
|
||||||
ex = -(pt[j].y - pt[i].y);
|
ex = -( pt[j].y - pt[i].y );
|
||||||
|
|
||||||
a = ( (x2 - 2 * x * px) / k + px * px );
|
a = ( ( x2 - 2 * x * px ) / k + px * px );
|
||||||
b = ( (xy - x * py - y * px) / k + px * py );
|
b = ( ( xy - x * py - y * px ) / k + px * py );
|
||||||
c = ( (y2 - 2 * y * py) / k + py * py );
|
c = ( ( y2 - 2 * y * py ) / k + py * py );
|
||||||
|
|
||||||
s = ex * ex * a + 2 * ex * ey * b + ey * ey * c;
|
s = ex * ex * a + 2 * ex * ey * b + ey * ey * c;
|
||||||
|
|
||||||
|
@ -647,7 +650,7 @@ static int bestpolygon( privpath_t* pp )
|
||||||
SAFE_CALLOC( seg1, n + 1, int );
|
SAFE_CALLOC( seg1, n + 1, int );
|
||||||
|
|
||||||
/* calculate clipped paths */
|
/* calculate clipped paths */
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
{
|
{
|
||||||
c = mod( pp->lon[mod( i - 1, n )] - 1, n );
|
c = mod( pp->lon[mod( i - 1, n )] - 1, n );
|
||||||
|
|
||||||
|
@ -670,7 +673,7 @@ static int bestpolygon( privpath_t* pp )
|
||||||
* clip1[j] <= i, for i,j=0..n. */
|
* clip1[j] <= i, for i,j=0..n. */
|
||||||
j = 1;
|
j = 1;
|
||||||
|
|
||||||
for( i = 0; i<n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
{
|
{
|
||||||
while( j <= clip0[i] )
|
while( j <= clip0[i] )
|
||||||
{
|
{
|
||||||
|
@ -682,7 +685,7 @@ static int bestpolygon( privpath_t* pp )
|
||||||
/* calculate seg0[j] = longest path from 0 with j segments */
|
/* calculate seg0[j] = longest path from 0 with j segments */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
for( j = 0; i<n; j++ )
|
for( j = 0; i < n; j++ )
|
||||||
{
|
{
|
||||||
seg0[j] = i;
|
seg0[j] = i;
|
||||||
i = clip0[i];
|
i = clip0[i];
|
||||||
|
@ -694,7 +697,7 @@ static int bestpolygon( privpath_t* pp )
|
||||||
/* calculate seg1[j] = longest path to n with m-j segments */
|
/* calculate seg1[j] = longest path to n with m-j segments */
|
||||||
i = n;
|
i = n;
|
||||||
|
|
||||||
for( j = m; j>0; j-- )
|
for( j = m; j > 0; j-- )
|
||||||
{
|
{
|
||||||
seg1[j] = i;
|
seg1[j] = i;
|
||||||
i = clip1[i];
|
i = clip1[i];
|
||||||
|
@ -708,13 +711,13 @@ static int bestpolygon( privpath_t* pp )
|
||||||
* close to linear since the inner loop tends to be short. */
|
* close to linear since the inner loop tends to be short. */
|
||||||
pen[0] = 0;
|
pen[0] = 0;
|
||||||
|
|
||||||
for( j = 1; j<=m; j++ )
|
for( j = 1; j <= m; j++ )
|
||||||
{
|
{
|
||||||
for( i = seg1[j]; i<=seg0[j]; i++ )
|
for( i = seg1[j]; i <= seg0[j]; i++ )
|
||||||
{
|
{
|
||||||
best = -1;
|
best = -1;
|
||||||
|
|
||||||
for( k = seg0[j - 1]; k>=clip1[i]; k-- )
|
for( k = seg0[j - 1]; k >= clip1[i]; k-- )
|
||||||
{
|
{
|
||||||
thispen = penalty3( pp, k, i ) + pen[k];
|
thispen = penalty3( pp, k, i ) + pen[k];
|
||||||
|
|
||||||
|
@ -733,7 +736,7 @@ static int bestpolygon( privpath_t* pp )
|
||||||
SAFE_CALLOC( pp->po, m, int );
|
SAFE_CALLOC( pp->po, m, int );
|
||||||
|
|
||||||
/* read off shortest path */
|
/* read off shortest path */
|
||||||
for( i = n, j = m - 1; i>0; j-- )
|
for( i = n, j = m - 1; i > 0; j-- )
|
||||||
{
|
{
|
||||||
i = prev[i];
|
i = prev[i];
|
||||||
pp->po[j] = i;
|
pp->po[j] = i;
|
||||||
|
@ -797,7 +800,7 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
|
|
||||||
/* calculate "optimal" point-slope representation for each line
|
/* calculate "optimal" point-slope representation for each line
|
||||||
* segment */
|
* segment */
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
j = po[mod( i + 1, m )];
|
j = po[mod( i + 1, m )];
|
||||||
j = mod( j - po[i], n ) + po[i];
|
j = mod( j - po[i], n ) + po[i];
|
||||||
|
@ -807,15 +810,15 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
/* represent each line segment as a singular quadratic form; the
|
/* represent each line segment as a singular quadratic form; the
|
||||||
* distance of a point (x,y) from the line segment will be
|
* distance of a point (x,y) from the line segment will be
|
||||||
* (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
|
* (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
d = sq( dir[i].x ) + sq( dir[i].y );
|
d = sq( dir[i].x ) + sq( dir[i].y );
|
||||||
|
|
||||||
if( d == 0.0 )
|
if( d == 0.0 )
|
||||||
{
|
{
|
||||||
for( j = 0; j<3; j++ )
|
for( j = 0; j < 3; j++ )
|
||||||
{
|
{
|
||||||
for( k = 0; k<3; k++ )
|
for( k = 0; k < 3; k++ )
|
||||||
{
|
{
|
||||||
q[i][j][k] = 0;
|
q[i][j][k] = 0;
|
||||||
}
|
}
|
||||||
|
@ -827,9 +830,9 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
v[1] = -dir[i].x;
|
v[1] = -dir[i].x;
|
||||||
v[2] = -v[1] * ctr[i].y - v[0] * ctr[i].x;
|
v[2] = -v[1] * ctr[i].y - v[0] * ctr[i].x;
|
||||||
|
|
||||||
for( l = 0; l<3; l++ )
|
for( l = 0; l < 3; l++ )
|
||||||
{
|
{
|
||||||
for( k = 0; k<3; k++ )
|
for( k = 0; k < 3; k++ )
|
||||||
{
|
{
|
||||||
q[i][l][k] = v[l] * v[k] / d;
|
q[i][l][k] = v[l] * v[k] / d;
|
||||||
}
|
}
|
||||||
|
@ -841,7 +844,7 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
* Instead of using the actual intersection, we find the point
|
* Instead of using the actual intersection, we find the point
|
||||||
* within a given unit square which minimizes the square distance to
|
* within a given unit square which minimizes the square distance to
|
||||||
* the two lines. */
|
* the two lines. */
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
quadform_t Q;
|
quadform_t Q;
|
||||||
dpoint_t w;
|
dpoint_t w;
|
||||||
|
@ -860,9 +863,9 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
j = mod( i - 1, m );
|
j = mod( i - 1, m );
|
||||||
|
|
||||||
/* add quadratic forms */
|
/* add quadratic forms */
|
||||||
for( l = 0; l<3; l++ )
|
for( l = 0; l < 3; l++ )
|
||||||
{
|
{
|
||||||
for( k = 0; k<3; k++ )
|
for( k = 0; k < 3; k++ )
|
||||||
{
|
{
|
||||||
Q[l][k] = q[j][l][k] + q[i][l][k];
|
Q[l][k] = q[j][l][k] + q[i][l][k];
|
||||||
}
|
}
|
||||||
|
@ -870,8 +873,8 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
/* minimize the quadratic form Q on the unit square */
|
/* minimize the quadratic form Q on the unit square */
|
||||||
/* find intersection */
|
/* find intersection */
|
||||||
|
|
||||||
#ifdef HAVE_GCC_LOOP_BUG
|
#ifdef HAVE_GCC_LOOP_BUG
|
||||||
/* work around gcc bug #12243 */
|
/* work around gcc bug #12243 */
|
||||||
|
@ -882,14 +885,14 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
|
|
||||||
if( det != 0.0 )
|
if( det != 0.0 )
|
||||||
{
|
{
|
||||||
w.x = (-Q[0][2] * Q[1][1] + Q[1][2] * Q[0][1]) / det;
|
w.x = ( -Q[0][2] * Q[1][1] + Q[1][2] * Q[0][1] ) / det;
|
||||||
w.y = ( Q[0][2] * Q[1][0] - Q[1][2] * Q[0][0]) / det;
|
w.y = ( Q[0][2] * Q[1][0] - Q[1][2] * Q[0][0] ) / det;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* matrix is singular - lines are parallel. Add another,
|
/* matrix is singular - lines are parallel. Add another,
|
||||||
* orthogonal axis, through the center of the unit square */
|
* orthogonal axis, through the center of the unit square */
|
||||||
if( Q[0][0]>Q[1][1] )
|
if( Q[0][0] > Q[1][1] )
|
||||||
{
|
{
|
||||||
v[0] = -Q[0][1];
|
v[0] = -Q[0][1];
|
||||||
v[1] = Q[0][0];
|
v[1] = Q[0][0];
|
||||||
|
@ -908,9 +911,9 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
d = sq( v[0] ) + sq( v[1] );
|
d = sq( v[0] ) + sq( v[1] );
|
||||||
v[2] = -v[1] * s.y - v[0] * s.x;
|
v[2] = -v[1] * s.y - v[0] * s.x;
|
||||||
|
|
||||||
for( l = 0; l<3; l++ )
|
for( l = 0; l < 3; l++ )
|
||||||
{
|
{
|
||||||
for( k = 0; k<3; k++ )
|
for( k = 0; k < 3; k++ )
|
||||||
{
|
{
|
||||||
Q[l][k] += v[l] * v[k] / d;
|
Q[l][k] += v[l] * v[k] / d;
|
||||||
}
|
}
|
||||||
|
@ -938,10 +941,11 @@ static int adjust_vertices( privpath_t* pp )
|
||||||
goto fixx;
|
goto fixx;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( z = 0; z<2; z++ ) /* value of the y-coordinate */
|
for( z = 0; z < 2; z++ )
|
||||||
{
|
{
|
||||||
|
/* value of the y-coordinate */
|
||||||
w.y = s.y - 0.5 + z;
|
w.y = s.y - 0.5 + z;
|
||||||
w.x = -(Q[0][1] * w.y + Q[0][2]) / Q[0][0];
|
w.x = -( Q[0][1] * w.y + Q[0][2] ) / Q[0][0];
|
||||||
dx = fabs( w.x - s.x );
|
dx = fabs( w.x - s.x );
|
||||||
cand = quadform( Q, w );
|
cand = quadform( Q, w );
|
||||||
|
|
||||||
|
@ -960,10 +964,11 @@ fixx:
|
||||||
goto corners;
|
goto corners;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( z = 0; z<2; z++ ) /* value of the x-coordinate */
|
for( z = 0; z < 2; z++ )
|
||||||
{
|
{
|
||||||
|
/* value of the x-coordinate */
|
||||||
w.x = s.x - 0.5 + z;
|
w.x = s.x - 0.5 + z;
|
||||||
w.y = -(Q[1][0] * w.x + Q[1][2]) / Q[1][1];
|
w.y = -( Q[1][0] * w.x + Q[1][2] ) / Q[1][1];
|
||||||
dy = fabs( w.y - s.y );
|
dy = fabs( w.y - s.y );
|
||||||
cand = quadform( Q, w );
|
cand = quadform( Q, w );
|
||||||
|
|
||||||
|
@ -978,9 +983,9 @@ fixx:
|
||||||
corners:
|
corners:
|
||||||
|
|
||||||
/* check four corners */
|
/* check four corners */
|
||||||
for( l = 0; l<2; l++ )
|
for( l = 0; l < 2; l++ )
|
||||||
{
|
{
|
||||||
for( k = 0; k<2; k++ )
|
for( k = 0; k < 2; k++ )
|
||||||
{
|
{
|
||||||
w.x = s.x - 0.5 + l;
|
w.x = s.x - 0.5 + l;
|
||||||
w.y = s.y - 0.5 + k;
|
w.y = s.y - 0.5 + k;
|
||||||
|
@ -1023,7 +1028,7 @@ static void reverse( privcurve_t* curve )
|
||||||
int i, j;
|
int i, j;
|
||||||
dpoint_t tmp;
|
dpoint_t tmp;
|
||||||
|
|
||||||
for( i = 0, j = m - 1; i<j; i++, j-- )
|
for( i = 0, j = m - 1; i < j; i++, j-- )
|
||||||
{
|
{
|
||||||
tmp = curve->vertex[i];
|
tmp = curve->vertex[i];
|
||||||
curve->vertex[i] = curve->vertex[j];
|
curve->vertex[i] = curve->vertex[j];
|
||||||
|
@ -1042,7 +1047,7 @@ static void smooth( privcurve_t* curve, double alphamax )
|
||||||
dpoint_t p2, p3, p4;
|
dpoint_t p2, p3, p4;
|
||||||
|
|
||||||
/* examine each vertex and find its best fit */
|
/* examine each vertex and find its best fit */
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
j = mod( i + 1, m );
|
j = mod( i + 1, m );
|
||||||
k = mod( i + 2, m );
|
k = mod( i + 2, m );
|
||||||
|
@ -1054,7 +1059,7 @@ static void smooth( privcurve_t* curve, double alphamax )
|
||||||
{
|
{
|
||||||
dd = dpara( curve->vertex[i], curve->vertex[j], curve->vertex[k] ) / denom;
|
dd = dpara( curve->vertex[i], curve->vertex[j], curve->vertex[k] ) / denom;
|
||||||
dd = fabs( dd );
|
dd = fabs( dd );
|
||||||
alpha = dd>1 ? (1 - 1.0 / dd) : 0;
|
alpha = dd > 1 ? ( 1 - 1.0 / dd ) : 0;
|
||||||
alpha = alpha / 0.75;
|
alpha = alpha / 0.75;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1064,8 +1069,9 @@ static void smooth( privcurve_t* curve, double alphamax )
|
||||||
|
|
||||||
curve->alpha0[j] = alpha; /* remember "original" value of alpha */
|
curve->alpha0[j] = alpha; /* remember "original" value of alpha */
|
||||||
|
|
||||||
if( alpha >= alphamax ) /* pointed corner */
|
if( alpha >= alphamax )
|
||||||
{
|
{
|
||||||
|
/* pointed corner */
|
||||||
curve->tag[j] = POTRACE_CORNER;
|
curve->tag[j] = POTRACE_CORNER;
|
||||||
curve->c[j][1] = curve->vertex[j];
|
curve->c[j][1] = curve->vertex[j];
|
||||||
curve->c[j][2] = p4;
|
curve->c[j][2] = p4;
|
||||||
|
@ -1130,8 +1136,9 @@ static int opti_penalty( privpath_t* pp,
|
||||||
|
|
||||||
/* check convexity, corner-freeness, and maximum bend < 179 degrees */
|
/* check convexity, corner-freeness, and maximum bend < 179 degrees */
|
||||||
|
|
||||||
if( i==j ) /* sanity - a full loop can never be an opticurve */
|
if( i == j )
|
||||||
{
|
{
|
||||||
|
/* sanity - a full loop can never be an opticurve */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,7 +1154,7 @@ static int opti_penalty( privpath_t* pp,
|
||||||
|
|
||||||
d = ddist( pp->curve.vertex[i], pp->curve.vertex[i1] );
|
d = ddist( pp->curve.vertex[i], pp->curve.vertex[i1] );
|
||||||
|
|
||||||
for( k = k1; k!=j; k = k1 )
|
for( k = k1; k != j; k = k1 )
|
||||||
{
|
{
|
||||||
k1 = mod( k + 1, m );
|
k1 = mod( k + 1, m );
|
||||||
k2 = mod( k + 2, m );
|
k2 = mod( k + 2, m );
|
||||||
|
@ -1158,14 +1165,15 @@ static int opti_penalty( privpath_t* pp,
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sign( cprod( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
if( sign( cprod( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
||||||
pp->curve.vertex[k2] ) ) != conv )
|
pp->curve.vertex[k2] ) )
|
||||||
|
!= conv )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iprod1( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
if( iprod1( pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
|
||||||
pp->curve.vertex[k2] ) <
|
pp->curve.vertex[k2] )
|
||||||
d * ddist( pp->curve.vertex[k1], pp->curve.vertex[k2] ) * COS179 )
|
< d * ddist( pp->curve.vertex[k1], pp->curve.vertex[k2] ) * COS179 )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1181,7 +1189,7 @@ static int opti_penalty( privpath_t* pp,
|
||||||
area = areac[j] - areac[i];
|
area = areac[j] - areac[i];
|
||||||
area -= dpara( pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2] ) / 2;
|
area -= dpara( pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2] ) / 2;
|
||||||
|
|
||||||
if( i>=j )
|
if( i >= j )
|
||||||
{
|
{
|
||||||
area += areac[m];
|
area += areac[m];
|
||||||
}
|
}
|
||||||
|
@ -1196,17 +1204,19 @@ static int opti_penalty( privpath_t* pp,
|
||||||
/* A4 = dpara(p1, p2, p3); */
|
/* A4 = dpara(p1, p2, p3); */
|
||||||
A4 = A1 + A3 - A2;
|
A4 = A1 + A3 - A2;
|
||||||
|
|
||||||
if( A2 == A1 ) /* this should never happen */
|
if( A2 == A1 )
|
||||||
{
|
{
|
||||||
|
/* this should never happen */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = A3 / (A3 - A4);
|
t = A3 / ( A3 - A4 );
|
||||||
s = A2 / (A2 - A1);
|
s = A2 / ( A2 - A1 );
|
||||||
A = A2 * t / 2.0;
|
A = A2 * t / 2.0;
|
||||||
|
|
||||||
if( A == 0.0 ) /* this should never happen */
|
if( A == 0.0 )
|
||||||
{
|
{
|
||||||
|
/* this should never happen */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,12 +1236,12 @@ static int opti_penalty( privpath_t* pp,
|
||||||
|
|
||||||
/* calculate penalty */
|
/* calculate penalty */
|
||||||
/* check tangency with edges */
|
/* check tangency with edges */
|
||||||
for( k = mod( i + 1, m ); k!=j; k = k1 )
|
for( k = mod( i + 1, m ); k != j; k = k1 )
|
||||||
{
|
{
|
||||||
k1 = mod( k + 1, m );
|
k1 = mod( k + 1, m );
|
||||||
t = tangent( p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1] );
|
t = tangent( p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1] );
|
||||||
|
|
||||||
if( t<-.5 )
|
if( t < -.5 )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1239,8 +1249,9 @@ static int opti_penalty( privpath_t* pp,
|
||||||
pt = bezier( t, p0, p1, p2, p3 );
|
pt = bezier( t, p0, p1, p2, p3 );
|
||||||
d = ddist( pp->curve.vertex[k], pp->curve.vertex[k1] );
|
d = ddist( pp->curve.vertex[k], pp->curve.vertex[k1] );
|
||||||
|
|
||||||
if( d == 0.0 ) /* this should never happen */
|
if( d == 0.0 )
|
||||||
{
|
{
|
||||||
|
/* this should never happen */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1251,8 +1262,8 @@ static int opti_penalty( privpath_t* pp,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iprod( pp->curve.vertex[k], pp->curve.vertex[k1],
|
if( iprod( pp->curve.vertex[k], pp->curve.vertex[k1], pt ) < 0
|
||||||
pt ) < 0 || iprod( pp->curve.vertex[k1], pp->curve.vertex[k], pt ) < 0 )
|
|| iprod( pp->curve.vertex[k1], pp->curve.vertex[k], pt ) < 0 )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1261,12 +1272,12 @@ static int opti_penalty( privpath_t* pp,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check corners */
|
/* check corners */
|
||||||
for( k = i; k!=j; k = k1 )
|
for( k = i; k != j; k = k1 )
|
||||||
{
|
{
|
||||||
k1 = mod( k + 1, m );
|
k1 = mod( k + 1, m );
|
||||||
t = tangent( p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2] );
|
t = tangent( p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2] );
|
||||||
|
|
||||||
if( t<-.5 )
|
if( t < -.5 )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1274,8 +1285,9 @@ static int opti_penalty( privpath_t* pp,
|
||||||
pt = bezier( t, p0, p1, p2, p3 );
|
pt = bezier( t, p0, p1, p2, p3 );
|
||||||
d = ddist( pp->curve.c[k][2], pp->curve.c[k1][2] );
|
d = ddist( pp->curve.c[k][2], pp->curve.c[k1][2] );
|
||||||
|
|
||||||
if( d == 0.0 ) /* this should never happen */
|
if( d == 0.0 )
|
||||||
{
|
{
|
||||||
|
/* this should never happen */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,12 +1347,11 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
SAFE_CALLOC( areac, m + 1, double );
|
SAFE_CALLOC( areac, m + 1, double );
|
||||||
|
|
||||||
/* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
|
/* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
if( pp->curve.tag[i] == POTRACE_CURVETO )
|
if( pp->curve.tag[i] == POTRACE_CURVETO )
|
||||||
{
|
{
|
||||||
convc[i] =
|
convc[i] = sign( dpara( pp->curve.vertex[mod( i - 1, m )], pp->curve.vertex[i],
|
||||||
sign( dpara( pp->curve.vertex[mod( i - 1, m )], pp->curve.vertex[i],
|
|
||||||
pp->curve.vertex[mod( i + 1, m )] ) );
|
pp->curve.vertex[mod( i + 1, m )] ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1354,16 +1365,15 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
areac[0] = 0.0;
|
areac[0] = 0.0;
|
||||||
p0 = pp->curve.vertex[0];
|
p0 = pp->curve.vertex[0];
|
||||||
|
|
||||||
for( i = 0; i<m; i++ )
|
for( i = 0; i < m; i++ )
|
||||||
{
|
{
|
||||||
i1 = mod( i + 1, m );
|
i1 = mod( i + 1, m );
|
||||||
|
|
||||||
if( pp->curve.tag[i1] == POTRACE_CURVETO )
|
if( pp->curve.tag[i1] == POTRACE_CURVETO )
|
||||||
{
|
{
|
||||||
alpha = pp->curve.alpha[i1];
|
alpha = pp->curve.alpha[i1];
|
||||||
area += 0.3 * alpha * (4 - alpha) * dpara( pp->curve.c[i][2],
|
area += 0.3 * alpha * ( 4 - alpha )
|
||||||
pp->curve.vertex[i1],
|
* dpara( pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2] ) / 2;
|
||||||
pp->curve.c[i1][2] ) / 2;
|
|
||||||
area += dpara( p0, pp->curve.c[i][2], pp->curve.c[i1][2] ) / 2;
|
area += dpara( p0, pp->curve.c[i][2], pp->curve.c[i1][2] ) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,14 +1387,14 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
/* Fixme: we always start from a fixed point -- should find the best
|
/* Fixme: we always start from a fixed point -- should find the best
|
||||||
* curve cyclically */
|
* curve cyclically */
|
||||||
|
|
||||||
for( j = 1; j<=m; j++ )
|
for( j = 1; j <= m; j++ )
|
||||||
{
|
{
|
||||||
/* calculate best path from 0 to j */
|
/* calculate best path from 0 to j */
|
||||||
pt[j] = j - 1;
|
pt[j] = j - 1;
|
||||||
pen[j] = pen[j - 1];
|
pen[j] = pen[j - 1];
|
||||||
len[j] = len[j - 1] + 1;
|
len[j] = len[j - 1] + 1;
|
||||||
|
|
||||||
for( i = j - 2; i>=0; i-- )
|
for( i = j - 2; i >= 0; i-- )
|
||||||
{
|
{
|
||||||
r = opti_penalty( pp, i, mod( j, m ), &o, opttolerance, convc, areac );
|
r = opti_penalty( pp, i, mod( j, m ), &o, opttolerance, convc, areac );
|
||||||
|
|
||||||
|
@ -1393,7 +1403,7 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( len[j] > len[i] + 1 || (len[j] == len[i] + 1 && pen[j] > pen[i] + o.pen) )
|
if( len[j] > len[i] + 1 || ( len[j] == len[i] + 1 && pen[j] > pen[i] + o.pen ) )
|
||||||
{
|
{
|
||||||
pt[j] = i;
|
pt[j] = i;
|
||||||
pen[j] = pen[i] + o.pen;
|
pen[j] = pen[i] + o.pen;
|
||||||
|
@ -1416,9 +1426,9 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
|
|
||||||
j = m;
|
j = m;
|
||||||
|
|
||||||
for( i = om - 1; i>=0; i-- )
|
for( i = om - 1; i >= 0; i-- )
|
||||||
{
|
{
|
||||||
if( pt[j]==j - 1 )
|
if( pt[j] == j - 1 )
|
||||||
{
|
{
|
||||||
pp->ocurve.tag[i] = pp->curve.tag[mod( j, m )];
|
pp->ocurve.tag[i] = pp->curve.tag[mod( j, m )];
|
||||||
pp->ocurve.c[i][0] = pp->curve.c[mod( j, m )][0];
|
pp->ocurve.c[i][0] = pp->curve.c[mod( j, m )][0];
|
||||||
|
@ -1436,9 +1446,8 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
pp->ocurve.c[i][0] = opt[j].c[0];
|
pp->ocurve.c[i][0] = opt[j].c[0];
|
||||||
pp->ocurve.c[i][1] = opt[j].c[1];
|
pp->ocurve.c[i][1] = opt[j].c[1];
|
||||||
pp->ocurve.c[i][2] = pp->curve.c[mod( j, m )][2];
|
pp->ocurve.c[i][2] = pp->curve.c[mod( j, m )][2];
|
||||||
pp->ocurve.vertex[i] = interval( opt[j].s, pp->curve.c[mod( j,
|
pp->ocurve.vertex[i] = interval(
|
||||||
m )][2],
|
opt[j].s, pp->curve.c[mod( j, m )][2], pp->curve.vertex[mod( j, m )] );
|
||||||
pp->curve.vertex[mod( j, m )] );
|
|
||||||
pp->ocurve.alpha[i] = opt[j].alpha;
|
pp->ocurve.alpha[i] = opt[j].alpha;
|
||||||
pp->ocurve.alpha0[i] = opt[j].alpha;
|
pp->ocurve.alpha0[i] = opt[j].alpha;
|
||||||
s[i] = opt[j].s;
|
s[i] = opt[j].s;
|
||||||
|
@ -1449,10 +1458,10 @@ static int opticurve( privpath_t* pp, double opttolerance )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate beta parameters */
|
/* calculate beta parameters */
|
||||||
for( i = 0; i<om; i++ )
|
for( i = 0; i < om; i++ )
|
||||||
{
|
{
|
||||||
i1 = mod( i + 1, om );
|
i1 = mod( i + 1, om );
|
||||||
pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
|
pp->ocurve.beta[i] = s[i] / ( s[i] + t[i1] );
|
||||||
}
|
}
|
||||||
|
|
||||||
pp->ocurve.alphacurve = 1;
|
pp->ocurve.alphacurve = 1;
|
||||||
|
@ -1482,7 +1491,8 @@ calloc_error:
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define TRY( x ) if( x ) \
|
#define TRY( x ) \
|
||||||
|
if( x ) \
|
||||||
goto try_error
|
goto try_error
|
||||||
|
|
||||||
/* return 0 on success, 1 on error with errno set. */
|
/* return 0 on success, 1 on error with errno set. */
|
||||||
|
@ -1508,8 +1518,9 @@ int process_path( path_t* plist, const potrace_param_t* param, progress_t* progr
|
||||||
TRY( bestpolygon( p->priv ) );
|
TRY( bestpolygon( p->priv ) );
|
||||||
TRY( adjust_vertices( p->priv ) );
|
TRY( adjust_vertices( p->priv ) );
|
||||||
|
|
||||||
if( p->sign == '-' ) /* reverse orientation of negative paths */
|
if( p->sign == '-' )
|
||||||
{
|
{
|
||||||
|
/* reverse orientation of negative paths */
|
||||||
reverse( &p->priv->curve );
|
reverse( &p->priv->curve );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
/* Copyright (C) 2001-2015 Peter Selinger.
|
/* Copyright (C) 2001-2017 Peter Selinger.
|
||||||
* This file is part of Potrace. It is free software and it is covered
|
* 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. */
|
* by the GNU General Public License. See the file COPYING for details. */
|
||||||
|
|
||||||
|
|
||||||
#ifndef TRACE_H
|
#ifndef TRACE_H
|
||||||
#define TRACE_H
|
#define TRACE_H
|
||||||
|
|
||||||
|
#include "curve.h"
|
||||||
#include "potracelib.h"
|
#include "potracelib.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "curve.h"
|
|
||||||
|
|
||||||
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
|
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue