Commit ac11d86c authored by jean-pierre charras's avatar jean-pierre charras

Added an experimental tool to create logos from .bmp bitmaps. Added Potrace...

Added an experimental tool to create logos from .bmp bitmaps. Added Potrace library to convert bitmaps to polygons
parent 82aadca8
...@@ -187,6 +187,8 @@ add_subdirectory(kicad) ...@@ -187,6 +187,8 @@ add_subdirectory(kicad)
add_subdirectory(pcbnew) add_subdirectory(pcbnew)
add_subdirectory(polygon) add_subdirectory(polygon)
add_subdirectory(polygon/kbool/src) add_subdirectory(polygon/kbool/src)
add_subdirectory(potrace)
add_subdirectory(bitmap2component)
############# #############
# Resources # # Resources #
......
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
../potrace
../polygon/kbool/include
)
set(BITMAP2COMPONENT_SRCS
bitmap2component.cpp
)
add_executable(bitmap2component WIN32 MACOSX_BUNDLE ${BITMAP2COMPONENT_SRCS} ${BITMAP2COMPONENT_RESOURCES})
target_link_libraries( bitmap2component potrace kbool )
if(APPLE)
set_target_properties(bitmap2component PROPERTIES )
endif(APPLE)
install(TARGETS bitmap2component
DESTINATION ${KICAD_BIN}
COMPONENT binary)
This diff is collapsed.
...@@ -676,7 +676,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, ...@@ -676,7 +676,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum,
{ {
aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ), aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
*aLineNum ); *aLineNum );
while( GetLine( aFile, aLine, aLineNum, 1024 ) ) while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
{ {
p = strtok( aLine, " \t\n" ); p = strtok( aLine, " \t\n" );
if( stricmp( p, "ENDDEF" ) == 0 ) if( stricmp( p, "ENDDEF" ) == 0 )
...@@ -726,7 +726,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, ...@@ -726,7 +726,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum,
m_options = ENTRY_POWER; m_options = ENTRY_POWER;
/* Read next lines */ /* Read next lines */
while( GetLine( aFile, aLine, aLineNum, 1024 ) ) while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
{ {
p = strtok( aLine, " \t\n" ); p = strtok( aLine, " \t\n" );
...@@ -775,7 +775,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine, ...@@ -775,7 +775,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,
while( true ) while( true )
{ {
if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL ) if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
{ {
aErrorMsg = wxT( "file ended prematurely loading component draw element" ); aErrorMsg = wxT( "file ended prematurely loading component draw element" );
return false; return false;
...@@ -830,7 +830,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine, ...@@ -830,7 +830,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,
/* Flush till end of draw section */ /* Flush till end of draw section */
do do
{ {
if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL ) if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
{ {
aErrorMsg = wxT( "file ended prematurely while attempting \ aErrorMsg = wxT( "file ended prematurely while attempting \
to flush to end of drawing section." ); to flush to end of drawing section." );
...@@ -899,7 +899,7 @@ bool LIB_COMPONENT::LoadFootprints( FILE* aFile, char* aLine, ...@@ -899,7 +899,7 @@ bool LIB_COMPONENT::LoadFootprints( FILE* aFile, char* aLine,
{ {
while( true ) while( true )
{ {
if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL ) if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
{ {
aErrorMsg = wxT( "file ended prematurely while loading footprints" ); aErrorMsg = wxT( "file ended prematurely while loading footprints" );
return false; return false;
......
...@@ -551,7 +551,7 @@ bool CMP_LIBRARY::Load( wxString& aErrorMsg ) ...@@ -551,7 +551,7 @@ bool CMP_LIBRARY::Load( wxString& aErrorMsg )
{ {
FILE* file; FILE* file;
int lineNumber = 0; int lineNumber = 0;
char line[1024]; char line[LINE_BUFFER_LEN_LARGE]; // Use a very large buffer to load data
LIB_COMPONENT* libEntry; LIB_COMPONENT* libEntry;
wxString msg; wxString msg;
...@@ -716,7 +716,7 @@ void CMP_LIBRARY::LoadAliases( LIB_COMPONENT* component ) ...@@ -716,7 +716,7 @@ void CMP_LIBRARY::LoadAliases( LIB_COMPONENT* component )
bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum ) bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum )
{ {
char Line[1024], * text, * data; char Line[LINE_BUFFER_LEN], * text, * data;
while( GetLine( libfile, Line, LineNum, sizeof(Line) ) ) while( GetLine( libfile, Line, LineNum, sizeof(Line) ) )
{ {
...@@ -735,7 +735,7 @@ bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum ) ...@@ -735,7 +735,7 @@ bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum )
bool CMP_LIBRARY::LoadDocs( wxString& aErrorMsg ) bool CMP_LIBRARY::LoadDocs( wxString& aErrorMsg )
{ {
int lineNumber = 0; int lineNumber = 0;
char line[1024], * name, * text; char line[LINE_BUFFER_LEN_LARGE], * name, * text;
CMP_LIB_ENTRY* entry; CMP_LIB_ENTRY* entry;
FILE* file; FILE* file;
wxString msg; wxString msg;
......
...@@ -1369,6 +1369,8 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg ) ...@@ -1369,6 +1369,8 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg )
i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert,
&m_Width ); &m_Width );
m_Fill = NO_FILL;
if( i < 4 ) if( i < 4 )
{ {
aErrorMsg.Printf( _( "polyline only had %d parameters of the required 4" ), i ); aErrorMsg.Printf( _( "polyline only had %d parameters of the required 4" ), i );
...@@ -1389,13 +1391,13 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg ) ...@@ -1389,13 +1391,13 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg )
{ {
wxPoint point; wxPoint point;
p = strtok( NULL, " \t\n" ); p = strtok( NULL, " \t\n" );
if( sscanf( p, "%d", &pt.x ) != 1 ) if( p == NULL || sscanf( p, "%d", &pt.x ) != 1 )
{ {
aErrorMsg.Printf( _( "polyline point %d X position not defined" ), i ); aErrorMsg.Printf( _( "polyline point %d X position not defined" ), i );
return false; return false;
} }
p = strtok( NULL, " \t\n" ); p = strtok( NULL, " \t\n" );
if( sscanf( p, "%d", &pt.y ) != 1 ) if( p == NULL || sscanf( p, "%d", &pt.y ) != 1 )
{ {
aErrorMsg.Printf( _( "polyline point %d Y position not defined" ), i ); aErrorMsg.Printf( _( "polyline point %d Y position not defined" ), i );
return false; return false;
...@@ -1403,8 +1405,6 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg ) ...@@ -1403,8 +1405,6 @@ bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg )
AddPoint( pt ); AddPoint( pt );
} }
m_Fill = NO_FILL;
if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) if( ( p = strtok( NULL, " \t\n" ) ) != NULL )
{ {
if( p[0] == 'F' ) if( p[0] == 'F' )
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
#define EESCHEMA_FILE_STAMP "EESchema" #define EESCHEMA_FILE_STAMP "EESchema"
#define NULL_STRING "_NONAME_" #define NULL_STRING "_NONAME_"
// Define the char buffer size used to read library files
#define LINE_BUFFER_LEN_LARGE 8000
#define LINE_BUFFER_LEN 1024
#define MAX_PIN_INFO 10 #define MAX_PIN_INFO 10
#define TXTMARGE 10 /* Offset in mils for placement of labels #define TXTMARGE 10 /* Offset in mils for placement of labels
......
*
%FSLAX26Y26*%
%MOIN*%
G04 A4 - i274x.oc8.d36 *
%AMA4top*
4,1,8,
0.034500,0.014290,
0.034500,-0.014290,
0.014290,-0.034500,
-0.014290,-0.034500,
-0.034500,-0.014290,
-0.034500,0.014290,
-0.014290,0.034500,
0.014290,0.034500,
0.034500,0.014290,
0.0000*
%
%ADD40A4top*%
%IPPOS*%
%LNfp0149448top.gbx*%
%LPD*%
G75*
G54D40*
X04750000Y00344900D03*
X04856300Y00246400D03*
X04750000Y00148000D03*
M02*
...@@ -487,7 +487,7 @@ void Plot_1_EdgeModule( PLOTTER* plotter, EDGE_MODULE* PtEdge, ...@@ -487,7 +487,7 @@ void Plot_1_EdgeModule( PLOTTER* plotter, EDGE_MODULE* PtEdge,
*ptr++ = y; *ptr++ = y;
} }
plotter->poly( PtEdge->m_PolyPoints.size(), ptr_base, NO_FILL, plotter->poly( PtEdge->m_PolyPoints.size(), ptr_base, FILLED_SHAPE,
thickness ); thickness );
free( ptr_base ); free( ptr_base );
} }
......
Known contributors are listed here, in alphabetical order by their
abbreviations (which are used in Changelog).
PS1 Peter Selinger <selinger at users.sourceforge.net> (author)
TA1 Tor Andersson <tor at ghostscript.com>
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
)
set(POTRACE_SRCS
bitmap_io.cpp
curve.cpp
decompose.cpp
greymap.cpp
potracelib.cpp
render.cpp
trace.cpp
)
add_library(potrace ${POTRACE_SRCS})
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* This header file collects some general-purpose macros (and static
* inline functions) that are used in various places. */
#ifndef AUXILIARY_H
#define AUXILIARY_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* ---------------------------------------------------------------------- */
/* point arithmetic */
#include "potracelib.h"
struct point_s
{
long x;
long y;
};
typedef struct point_s point_t;
typedef potrace_dpoint_t dpoint_t;
/* convert point_t to dpoint_t */
static inline dpoint_t dpoint( point_t p )
{
dpoint_t res;
res.x = p.x;
res.y = p.y;
return res;
}
/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
static inline dpoint_t interval( double lambda, dpoint_t a, dpoint_t b )
{
dpoint_t res;
res.x = a.x + lambda * (b.x - a.x);
res.y = a.y + lambda * (b.y - a.y);
return res;
}
/* ---------------------------------------------------------------------- */
/* some useful macros. Note: the "mod" macro works correctly for
* negative a. Also note that the test for a>=n, while redundant,
* speeds up the mod function by 70% in the average case (significant
* since the program spends about 16% of its time here - or 40%
* without the test). The "floordiv" macro returns the largest integer
* <= a/n, and again this works correctly for negative a, as long as
* a,n are integers and n>0. */
/* integer arithmetic */
static inline int mod( int a, int n )
{
return a>=n ? a % n : a>=0 ? a : n - 1 - (-1 - a) % n;
}
static inline int floordiv( int a, int n )
{
return a>=0 ? a / n : -1 - (-1 - a) / n;
}
/* Note: the following work for integers and other numeric types. */
#undef sign
#undef abs
#undef min
#undef max
#undef sq
#undef cu
#define sign( x ) ( (x)>0 ? 1 : (x)<0 ? -1 : 0 )
#define abs( a ) ( (a)>0 ? (a) : -(a) )
#define min( a, b ) ( (a)<(b) ? (a) : (b) )
#define max( a, b ) ( (a)>(b) ? (a) : (b) )
#define sq( a ) ( (a) * (a) )
#define cu( a ) ( (a) * (a) * (a) )
#endif /* AUXILIARY_H */
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
#ifndef BITMAP_H
#define BITMAP_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
/* The bitmap type is defined in potracelib.h */
#include "potracelib.h"
/* The present file defines some convenient macros and static inline
* functions for accessing bitmaps. Since they only produce inline
* code, they can be conveniently shared by the library and frontends,
* if desired */
/* ---------------------------------------------------------------------- */
/* some measurements */
#define BM_WORDSIZE ( (int) sizeof(potrace_word) )
#define BM_WORDBITS (8 * BM_WORDSIZE)
#define BM_HIBIT ( ( (potrace_word) 1 ) << (BM_WORDBITS - 1) )
#define BM_ALLBITS (~(potrace_word) 0)
/* macros for accessing pixel at index (x,y). U* macros omit the
* bounds check. */
#define bm_scanline( bm, y ) ( (bm)->map + (y) * (bm)->dy )
#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_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_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_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_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_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_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)
/* free the given bitmap. Leaves errno untouched. */
static inline void bm_free( potrace_bitmap_t* bm )
{
if( bm )
{
free( bm->map );
}
free( bm );
}
/* return new un-initialized bitmap. NULL with errno on error */
static inline potrace_bitmap_t* bm_new( int w, int h )
{
potrace_bitmap_t* bm;
int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
bm = (potrace_bitmap_t*) malloc( sizeof(potrace_bitmap_t) );
if( !bm )
{
return NULL;
}
bm->w = w;
bm->h = h;
bm->dy = dy;
bm->map = (potrace_word*) malloc( dy * h * BM_WORDSIZE );
if( !bm->map )
{
free( bm );
return NULL;
}
return bm;
}
/* clear the given bitmap. Set all bits to c. */
static inline void bm_clear( potrace_bitmap_t* bm, int c )
{
memset( bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE );
}
/* duplicate the given bitmap. Return NULL on error with errno set. */
static inline potrace_bitmap_t* bm_dup( const potrace_bitmap_t* bm )
{
potrace_bitmap_t* bm1 = bm_new( bm->w, bm->h );
if( !bm1 )
{
return NULL;
}
memcpy( bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE );
return bm1;
}
/* invert the given bitmap. */
static inline void bm_invert( potrace_bitmap_t* bm )
{
int i;
for( i = 0; i < bm->dy * bm->h; i++ )
{
bm->map[i] ^= BM_ALLBITS;
}
}
#endif /* BITMAP_H */
This diff is collapsed.
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* $Id: bitmap_io.h 147 2007-04-09 00:44:09Z selinger $ */
/* bitmap input/output functions */
#ifndef BITMAP_IO_H
#define BITMAP_IO_H
#include <stdio.h>
#include "bitmap.h"
/* Note that bitmaps are stored bottom to top, i.e., the first
* scanline is the bottom-most one */
extern char* bm_read_error;
int bm_read( FILE* f, double blacklevel, potrace_bitmap_t** bmp );
void bm_writepbm( FILE* f, potrace_bitmap_t* bm );
int bm_print( FILE* f, potrace_bitmap_t* bm );
#endif /* BITMAP_IO_H */
/* Copyright (C) 2001-2007 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
/* $Id: bitops.h 147 2007-04-09 00:44:09Z selinger $ */
/* bits.h: this file defines some macros for bit manipulations. We
provide a generic implementation */
/* lobit: return the position of the rightmost "1" bit of an int, or
32 if none. hibit: return 1 + the position of the leftmost "1" bit
of an int, or 0 if none. Note: these functions work on 32-bit
integers. */
#ifndef BITOPS_H
#define BITOPS_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* generic macros */
static inline unsigned int lobit(unsigned int x) {
unsigned int res = 32;
while (x & 0xffffff) {
x <<= 8;
res -= 8;
}
while (x) {
x <<= 1;
res -= 1;
}
return res;
}
static inline unsigned int hibit(unsigned int x) {
unsigned int res = 0;
while (x > 0xff) {
x >>= 8;
res += 8;
}
while (x) {
x >>= 1;
res += 1;
}
return res;
}
#endif /* BITOPS_H */
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* $Id: curve.c 147 2007-04-09 00:44:09Z selinger $ */
/* private part of the path and curve data structures */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "potracelib.h"
#include "lists.h"
#include "curve.h"
#define SAFE_MALLOC( var, n, typ ) \
if( ( var = (typ*) malloc( (n)* sizeof(typ) ) ) == NULL ) \
goto malloc_error
/* ---------------------------------------------------------------------- */
/* allocate and free path objects */
path_t* path_new( void )
{
path_t* p = NULL;
privpath_t* priv = NULL;
SAFE_MALLOC( p, 1, path_t );
memset( p, 0, sizeof(path_t) );
SAFE_MALLOC( priv, 1, privpath_t );
memset( priv, 0, sizeof(privpath_t) );
p->priv = priv;
return p;
malloc_error:
free( p );
free( priv );
return NULL;
}
/* free the members of the given curve structure. Leave errno unchanged. */
static void privcurve_free_members( privcurve_t* curve )
{
free( curve->tag );
free( curve->c );
free( curve->vertex );
free( curve->alpha );
free( curve->alpha0 );
free( curve->beta );
}
/* free a path. Leave errno untouched. */
void path_free( path_t* p )
{
if( p )
{
if( p->priv )
{
free( p->priv->pt );
free( p->priv->lon );
free( p->priv->sums );
free( p->priv->po );
privcurve_free_members( &p->priv->curve );
privcurve_free_members( &p->priv->ocurve );
}
free( p->priv );
/* do not free p->fcurve ! */
}
free( p );
}
/* free a pathlist, leaving errno untouched. */
void pathlist_free( path_t* plist )
{
path_t* p;
list_forall_unlink( p, plist ) {
path_free( p );
}
}
/* ---------------------------------------------------------------------- */
/* initialize and finalize curve structures */
typedef dpoint_t dpoint3_t[3];
/* initialize the members of the given curve structure to size m.
* Return 0 on success, 1 on error with errno set. */
int privcurve_init( privcurve_t* curve, int n )
{
memset( curve, 0, sizeof(privcurve_t) );
curve->n = n;
SAFE_MALLOC( curve->tag, n, int );
SAFE_MALLOC( curve->c, n, dpoint3_t );
SAFE_MALLOC( curve->vertex, n, dpoint_t );
SAFE_MALLOC( curve->alpha, n, double );
SAFE_MALLOC( curve->alpha0, n, double );
SAFE_MALLOC( curve->beta, n, double );
return 0;
malloc_error:
free( curve->tag );
free( curve->c );
free( curve->vertex );
free( curve->alpha );
free( curve->alpha0 );
free( curve->beta );
return 1;
}
/* copy private to public curve structure */
void privcurve_to_curve( privcurve_t* pc, potrace_curve_t* c )
{
c->n = pc->n;
c->tag = pc->tag;
c->c = pc->c;
}
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
#ifndef CURVE_H
#define CURVE_H
#include "auxiliary.h"
/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
* .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
* defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve:
* .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and
* c[2]..c[1] = alpha*(c[2]..vertex).
* Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
*/
struct privcurve_s
{
int n; /* number of segments */
int* tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
dpoint_t( * c )[3]; /* c[n][i]: control points.
* c[n][0] is unused for tag[n]=POTRACE_CORNER */
/* the remainder of this structure is special to privcurve, and is
* used in EPS debug output and special EPS "short coding". These
* fields are valid only if "alphacurve" is set. */
int alphacurve; /* have the following fields been initialized? */
dpoint_t* vertex; /* for POTRACE_CORNER, this equals c[1] */
double* alpha; /* only for POTRACE_CURVETO */
double* alpha0; /* "uncropped" alpha parameter - for debug output only */
double* beta;
};
typedef struct privcurve_s privcurve_t;
struct sums_s
{
double x;
double y;
double x2;
double xy;
double y2;
};
typedef struct sums_s sums_t;
/* the path structure is filled in with information about a given path
* as it is accumulated and passed through the different stages of the
* Potrace algorithm. Backends only need to read the fcurve and fm
* fields of this data structure, but debugging backends may read
* other fields. */
struct potrace_privpath_s
{
int len;
point_t* pt; /* pt[len]: path as extracted from bitmap */
int* lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
int x0, y0; /* origin for sums */
sums_t* sums; /* sums[len+1]: cache for fast summing */
int m; /* length of optimal polygon */
int* po; /* po[m]: optimal polygon */
privcurve_t curve; /* curve[m]: array of curve elements */
privcurve_t ocurve; /* ocurve[om]: array of curve elements */
privcurve_t* fcurve; /* final curve: this points to either curve or
* ocurve. Do not free this separately. */
};
typedef struct potrace_privpath_s potrace_privpath_t;
/* shorter names */
typedef potrace_privpath_t privpath_t;
typedef potrace_path_t path_t;
path_t* path_new( void );
void path_free( path_t* p );
void pathlist_free( path_t* plist );
int privcurve_init( privcurve_t* curve, int n );
void privcurve_to_curve( privcurve_t* pc, potrace_curve_t* c );
#endif /* CURVE_H */
This diff is collapsed.
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* $Id: decompose.h 147 2007-04-09 00:44:09Z selinger $ */
#ifndef DECOMPOSE_H
#define DECOMPOSE_H
#include "potracelib.h"
#include "progress.h"
int bm_to_pathlist( const potrace_bitmap_t* bm,
path_t** plistp,
const potrace_param_t* param,
progress_t* progress );
#endif /* DECOMPOSE_H */
This diff is collapsed.
/* Copyright (C) 2001-2007 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
/* $Id: greymap.h 147 2007-04-09 00:44:09Z selinger $ */
#ifndef PGM_H
#define PGM_H
#include <stdio.h>
/* internal format for greymaps. Note: in this format, rows are
ordered from bottom to top. The pixels in each row are given from
left to right. */
struct greymap_s {
int w; /* width, in pixels */
int h; /* height, in pixels */
signed short int *map; /* raw data, w*h values */
};
typedef struct greymap_s greymap_t;
/* macros for accessing pixel at index (x,y). Note that the origin is
in the *lower* left corner. U* macros omit the bounds check. */
#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(gm)->w])
#define gm_safe(gm, x, y) ((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_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_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_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_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_BGET(gm, x, y) GM_UGET(gm, gm_bound(x, gm->w), gm_bound(y, gm->h))
/* modes for cutting off out-of-range values. The following names
refer to winding numbers. I.e., make a pixel black if winding
number is nonzero, odd, or positive, respectively. We assume that 0
winding number corresponds to white (255). */
#define GM_MODE_NONZERO 1
#define GM_MODE_ODD 2
#define GM_MODE_POSITIVE 3
#define GM_MODE_NEGATIVE 4
extern const char *gm_read_error;
greymap_t *gm_new(int w, int h);
greymap_t *gm_dup(greymap_t *gm);
void gm_free(greymap_t *gm);
void gm_clear(greymap_t *gm, int b);
int gm_read(FILE *f, greymap_t **gmp);
int gm_writepgm(FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma);
int gm_print(FILE *f, greymap_t *gm);
#endif /* PGM_H */
This diff is collapsed.
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* this header file contains some platform dependent stuff */
#ifndef PLATFORM_H
#define PLATFORM_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* in Windows, set all file i/o to binary */
#ifdef __MINGW32__
#include <fcntl.h>
unsigned int _CRT_fmode = _O_BINARY;
#endif
#ifdef __CYGWIN__
#include <fcntl.h>
#include <io.h>
static inline void platform_init( void )
{
setmode( 0, O_BINARY );
setmode( 1, O_BINARY );
}
#else
static inline void platform_init( void )
{
/* NOP */
}
#endif
#endif /* PLATFORM_H */
#define POTRACELIB_VERSION "potracelib 1.8"
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details.
*/
#include <stdlib.h>
#include <string.h>
#include "potracelib.h"
#include "curve.h"
#include "decompose.h"
#include "trace.h"
#include "progress.h"
#include "potrace_version.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* default parameters */
static const potrace_param_t param_default =
{
2, /* turdsize */
POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */
1.0, /* alphamax */
1, /* opticurve */
0.2, /* opttolerance */
{
NULL, /* callback function */
NULL, /* callback data */
0.0, 1.0, /* progress range */
0.0, /* granularity */
},
};
/* Return a fresh copy of the set of default parameters, or NULL on
* failure with errno set. */
potrace_param_t* potrace_param_default( void )
{
potrace_param_t* p;
p = (potrace_param_t*) malloc( sizeof(potrace_param_t) );
if( !p )
{
return NULL;
}
memcpy( p, &param_default, sizeof(potrace_param_t) );
return p;
}
/* On success, returns a Potrace state st with st->status ==
* POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
* could be created (with errno set), or returns an incomplete Potrace
* state (with st->status == POTRACE_STATUS_INCOMPLETE). Complete or
* incomplete Potrace state can be freed with potrace_state_free(). */
potrace_state_t* potrace_trace( const potrace_param_t* param, const potrace_bitmap_t* bm )
{
int r;
path_t* plist = NULL;
potrace_state_t* st;
progress_t prog;
progress_t subprog;
/* prepare private progress bar state */
prog.callback = param->progress.callback;
prog.data = param->progress.data;
prog.min = param->progress.min;
prog.max = param->progress.max;
prog.epsilon = param->progress.epsilon;
prog.d_prev = param->progress.min;
/* allocate state object */
st = (potrace_state_t*) malloc( sizeof(potrace_state_t) );
if( !st )
{
return NULL;
}
progress_subrange_start( 0.0, 0.1, &prog, &subprog );
/* process the image */
r = bm_to_pathlist( bm, &plist, param, &subprog );
if( r )
{
free( st );
return NULL;
}
st->status = POTRACE_STATUS_OK;
st->plist = plist;
st->priv = NULL; /* private state currently unused */
progress_subrange_end( &prog, &subprog );
progress_subrange_start( 0.1, 1.0, &prog, &subprog );
/* partial success. */
r = process_path( plist, param, &subprog );
if( r )
{
st->status = POTRACE_STATUS_INCOMPLETE;
}
progress_subrange_end( &prog, &subprog );
return st;
}
/* free a Potrace state, without disturbing errno. */
void potrace_state_free( potrace_state_t* st )
{
pathlist_free( st->plist );
free( st );
}
/* free a parameter list, without disturbing errno. */
void potrace_param_free( potrace_param_t* p )
{
free( p );
}
const char* potrace_version( void )
{
return POTRACELIB_VERSION;
}
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
#ifndef POTRACELIB_H
#define POTRACELIB_H
/* this file defines the API for the core Potrace library. For a more
* detailed description of the API, see doc/potracelib.txt */
/* ---------------------------------------------------------------------- */
/* tracing parameters */
/* turn policies */
#define POTRACE_TURNPOLICY_BLACK 0
#define POTRACE_TURNPOLICY_WHITE 1
#define POTRACE_TURNPOLICY_LEFT 2
#define POTRACE_TURNPOLICY_RIGHT 3
#define POTRACE_TURNPOLICY_MINORITY 4
#define POTRACE_TURNPOLICY_MAJORITY 5
#define POTRACE_TURNPOLICY_RANDOM 6
/* structure to hold progress bar callback data */
struct potrace_progress_s
{
void (* callback)( double progress, void* privdata ); /* callback fn */
void* data; /* callback function's private data */
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
double epsilon; /* granularity: can skip smaller increments */
};
typedef struct potrace_progress_s potrace_progress_t;
/* structure to hold tracing parameters */
struct potrace_param_s
{
int turdsize; /* area of largest path to be ignored */
int turnpolicy; /* resolves ambiguous turns in path decomposition */
double alphamax; /* corner threshold */
int opticurve; /* use curve optimization? */
double opttolerance; /* curve optimization tolerance */
potrace_progress_t progress; /* progress callback function */
};
typedef struct potrace_param_s potrace_param_t;
/* ---------------------------------------------------------------------- */
/* bitmaps */
/* native word size */
typedef unsigned long potrace_word;
/* Internal bitmap format. The n-th scanline starts at scanline(n) =
* (map + n*dy). Raster data is stored as a sequence of potrace_words
* (NOT bytes). The leftmost bit of scanline n is the most significant
* bit of scanline(n)[0]. */
struct potrace_bitmap_s
{
int w, h; /* width and height, in pixels */
int dy; /* words per scanline (not bytes) */
potrace_word* map; /* raw data, dy*h words */
};
typedef struct potrace_bitmap_s potrace_bitmap_t;
/* ---------------------------------------------------------------------- */
/* curves */
/* point */
struct potrace_dpoint_s
{
double x, y;
};
typedef struct potrace_dpoint_s potrace_dpoint_t;
/* segment tags */
#define POTRACE_CURVETO 1
#define POTRACE_CORNER 2
/* closed curve segment */
struct potrace_curve_s
{
int n; /* number of segments */
int* tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
potrace_dpoint_t( * c )[3]; /* c[n][3]: control points.
* c[n][0] is unused for tag[n]=POTRACE_CORNER */
};
typedef struct potrace_curve_s potrace_curve_t;
/* Linked list of signed curve segments. Also carries a tree structure. */
struct potrace_path_s
{
int area; /* area of the bitmap path */
int sign; /* '+' or '-', depending on orientation */
potrace_curve_t curve; /* this path's vector data */
struct potrace_path_s* next; /* linked list structure */
struct potrace_path_s* childlist; /* tree structure */
struct potrace_path_s* sibling; /* tree structure */
struct potrace_privpath_s* priv; /* private state */
};
typedef struct potrace_path_s potrace_path_t;
/* ---------------------------------------------------------------------- */
/* Potrace state */
#define POTRACE_STATUS_OK 0
#define POTRACE_STATUS_INCOMPLETE 1
struct potrace_state_s
{
int status;
potrace_path_t* plist; /* vector data */
struct potrace_privstate_s* priv; /* private state */
};
typedef struct potrace_state_s potrace_state_t;
/* ---------------------------------------------------------------------- */
/* API functions */
/* get default parameters */
potrace_param_t* potrace_param_default( void );
/* free parameter set */
void potrace_param_free( potrace_param_t* p );
/* trace a bitmap*/
potrace_state_t* potrace_trace( const potrace_param_t* param,
const potrace_bitmap_t* bm );
/* free a Potrace state */
void potrace_state_free( potrace_state_t* st );
/* return a static plain text version string identifying this version
* of potracelib */
const char* potrace_version( void );
#endif /* POTRACELIB_H */
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* operations on potrace_progress_t objects, which are defined in
* potracelib.h. Note: the code attempts to minimize runtime overhead
* when no progress monitoring was requested. It also tries to
* minimize excessive progress calculations beneath the "epsilon"
* threshold. */
#ifndef PROGRESS_H
#define PROGRESS_H
/* structure to hold progress bar callback data */
struct progress_s
{
void (* callback)( double progress, void* privdata ); /* callback fn */
void* data; /* callback function's private data */
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
double epsilon; /* granularity: can skip smaller increments */
double b; /* upper limit of subrange in superrange units */
double d_prev; /* previous value of d */
};
typedef struct progress_s progress_t;
/* notify given progress object of current progress. Note that d is
* given in the 0.0-1.0 range, which will be scaled and translated to
* the progress object's range. */
static inline void progress_update( double d, progress_t* prog )
{
double d_scaled;
if( prog->callback != NULL )
{
d_scaled = prog->min * (1 - d) + prog->max * d;
if( d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon )
{
prog->callback( prog->min * (1 - d) + prog->max * d, prog->data );
prog->d_prev = d_scaled;
}
}
}
/* start a subrange of the given progress object. The range is
* narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
* is below granularity threshold, disable further subdivisions. */
static inline void progress_subrange_start( double a,
double b,
const progress_t* prog,
progress_t* sub )
{
double min, max;
if( prog->callback == NULL )
{
sub->callback = NULL;
return;
}
min = prog->min * (1 - a) + prog->max * a;
max = prog->min * (1 - b) + prog->max * b;
if( max - min < prog->epsilon )
{
sub->callback = NULL; /* no further progress info in subrange */
sub->b = b;
return;
}
sub->callback = prog->callback;
sub->data = prog->data;
sub->epsilon = prog->epsilon;
sub->min = min;
sub->max = max;
sub->d_prev = prog->d_prev;
return;
}
static inline void progress_subrange_end( progress_t* prog, progress_t* sub )
{
if( prog->callback != NULL )
{
if( sub->callback == NULL )
{
progress_update( sub->b, prog );
}
else
{
prog->d_prev = sub->d_prev;
}
}
}
#endif /* PROGRESS_H */
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* $Id: render.c 147 2007-04-09 00:44:09Z selinger $ */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "render.h"
#include "greymap.h"
#include "auxiliary.h"
/* ---------------------------------------------------------------------- */
/* routines for anti-aliased rendering of curves */
/* we use the following method. Given a point (x,y) (with real-valued
* coordinates) in the plane, let (xi,yi) be the integer part of the
* coordinates, i.e., xi=floor(x), yi=floor(y). Define a path from
* (x,y) to infinity as follows: path(x,y) =
* (x,y)--(xi+1,y)--(xi+1,yi)--(+infty,yi). Now as the point (x,y)
* moves smoothly across the plane, the path path(x,y) sweeps
* (non-smoothly) across a certain area. We proportionately blacken
* the area as the path moves "downward", and we whiten the area as
* the path moves "upward". This way, after the point has traversed a
* closed curve, the interior of the curve has been darkened
* (counterclockwise movement) or lightened (clockwise movement). (The
* "grey shift" is actually proportional to the winding number). By
* choosing the above path with mostly integer coordinates, we achieve
* that only pixels close to (x,y) receive grey values and are subject
* to round-off errors. The grey value of pixels far away from (x,y)
* is always in "integer" (where 0=black, 1=white). As a special
* trick, we keep an accumulator rm->a1, which holds a double value to
* be added to the grey value to be added to the current pixel
* (xi,yi). Only when changing "current" pixels, we convert this
* double value to an integer. This way we avoid round-off errors at
* the meeting points of line segments. Another speedup measure is
* that we sometimes use the rm->incrow_buf array to postpone
* incrementing or decrementing an entire row. If incrow_buf[y]=x+1!=0,
* then all the pixels (x,y),(x+1,y),(x+2,y),... are scheduled to be
* incremented/decremented (which one is the case will be clear from
* context). This keeps the greymap operations reasonably local. */
/* allocate a new rendering state */
render_t* render_new( greymap_t* gm )
{
render_t* rm;
rm = (render_t*) malloc( sizeof(render_t) );
if( !rm )
{
return NULL;
}
memset( rm, 0, sizeof(render_t) );
rm->gm = gm;
rm->incrow_buf = (int*) malloc( gm->h * sizeof(int) );
if( !rm->incrow_buf )
{
free( rm );
return NULL;
}
memset( rm->incrow_buf, 0, gm->h * sizeof(int) );
return rm;
}
/* free a given rendering state. Note: this does not free the
* underlying greymap. */
void render_free( render_t* rm )
{
free( rm->incrow_buf );
free( rm );
}
/* close path */
void render_close( render_t* rm )
{
if( rm->x0 != rm->x1 || rm->y0 != rm->y1 )
{
render_lineto( rm, rm->x0, rm->y0 );
}
GM_INC( rm->gm, rm->x0i, rm->y0i, (rm->a0 + rm->a1) * 255 );
/* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
/* the persistent state is now undefined */
}
/* move point */
void render_moveto( render_t* rm, double x, double y )
{
/* close the previous path */
render_close( rm );
rm->x0 = rm->x1 = x;
rm->y0 = rm->y1 = y;
rm->x0i = (int) floor( rm->x0 );
rm->x1i = (int) floor( rm->x1 );
rm->y0i = (int) floor( rm->y0 );
rm->y1i = (int) floor( rm->y1 );
rm->a0 = rm->a1 = 0;
}
/* add b to pixels (x,y) and all pixels to the right of it. However,
* use rm->incrow_buf as a buffer to economize on multiple calls */
static void incrow( render_t* rm, int x, int y, int b )
{
int i, x0;
if( y < 0 || y >= rm->gm->h )
{
return;
}
if( x < 0 )
{
x = 0;
}
else if( x > rm->gm->w )
{
x = rm->gm->w;
}
if( rm->incrow_buf[y] == 0 )
{
rm->incrow_buf[y] = x + 1; /* store x+1 so that we can use 0 for "vacant" */
return;
}
x0 = rm->incrow_buf[y] - 1;
rm->incrow_buf[y] = 0;
if( x0 < x )
{
for( i = x0; i<x; i++ )
{
GM_INC( rm->gm, i, y, -b );
}
}
else
{
for( i = x; i<x0; i++ )
{
GM_INC( rm->gm, i, y, b );
}
}
}
/* render a straight line */
void render_lineto( render_t* rm, double x2, double y2 )
{
int x2i, y2i;
double t0 = 2, s0 = 2;
int sn, tn;
double ss = 2, ts = 2;
double r0, r1;
int i, j;
int rxi, ryi;
int s;
x2i = (int) floor( x2 );
y2i = (int) floor( y2 );
sn = abs( x2i - rm->x1i );
tn = abs( y2i - rm->y1i );
if( sn )
{
s0 = ( (x2>rm->x1 ? rm->x1i + 1 : rm->x1i) - rm->x1 ) / (x2 - rm->x1);
ss = fabs( 1.0 / (x2 - rm->x1) );
}
if( tn )
{
t0 = ( (y2>rm->y1 ? rm->y1i + 1 : rm->y1i) - rm->y1 ) / (y2 - rm->y1);
ts = fabs( 1.0 / (y2 - rm->y1) );
}
r0 = 0;
i = 0;
j = 0;
rxi = rm->x1i;
ryi = rm->y1i;
while( i<sn || j<tn )
{
if( j>=tn || (i<sn && s0 + i * ss < t0 + j * ts) )
{
r1 = s0 + i * ss;
i++;
s = 1;
}
else
{
r1 = t0 + j * ts;
j++;
s = 0;
}
/* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
/* move point to r1 */
rm->a1 +=
(r1 - r0) * (y2 - rm->y1) * ( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
/* move point across pixel boundary */
if( s && x2>rm->x1 )
{
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
rm->a1 = 0;
rxi++;
rm->a1 += rm->y1 + r1 * (y2 - rm->y1) - ryi;
}
else if( !s && y2>rm->y1 )
{
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
rm->a1 = 0;
incrow( rm, rxi + 1, ryi, 255 );
ryi++;
}
else if( s && x2<=rm->x1 )
{
rm->a1 -= rm->y1 + r1 * (y2 - rm->y1) - ryi;
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
rm->a1 = 0;
rxi--;
}
else if( !s && y2<=rm->y1 )
{
GM_INC( rm->gm, rxi, ryi, rm->a1 * 255 );
rm->a1 = 0;
ryi--;
incrow( rm, rxi + 1, ryi, -255 );
}
r0 = r1;
}
/* move point to (x2,y2) */
r1 = 1;
rm->a1 += (r1 - r0) * (y2 - rm->y1) * ( rxi + 1 - ( (r0 + r1) / 2.0 * (x2 - rm->x1) + rm->x1 ) );
rm->x1i = x2i;
rm->y1i = y2i;
rm->x1 = x2;
rm->y1 = y2;
/* assert (rxi != rm->x1i || ryi != rm->y1i); */
}
/* render a Bezier curve. */
void render_curveto( render_t* rm,
double x2,
double y2,
double x3,
double y3,
double x4,
double y4 )
{
double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
x1 = rm->x1; /* starting point */
y1 = rm->y1;
/* we approximate the curve by small line segments. The interval
* size, epsilon, is determined on the fly so that the distance
* between the true curve and its approximation does not exceed the
* desired accuracy delta. */
delta = .1; /* desired accuracy, in pixels */
/* let dd = maximal value of 2nd derivative over curve - this must
* occur at an endpoint. */
dd0 = sq( x1 - 2 * x2 + x3 ) + sq( y1 - 2 * y2 + y3 );
dd1 = sq( x2 - 2 * x3 + x4 ) + sq( y2 - 2 * y3 + y4 );
dd = 6 * sqrt( max( dd0, dd1 ) );
e2 = 8 * delta <= dd ? 8 * delta / dd : 1;
epsilon = sqrt( e2 ); /* necessary interval size */
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(
t ) + x4 * cu( t ),
y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq(
t ) + y4 * cu( t ) );
}
render_lineto( rm, x4, y4 );
}
This diff is collapsed.
This diff is collapsed.
/* Copyright (C) 2001-2007 Peter Selinger.
* This file is part of Potrace. It is free software and it is covered
* by the GNU General Public License. See the file COPYING for details. */
/* $Id: trace.h 147 2007-04-09 00:44:09Z selinger $ */
#ifndef TRACE_H
#define TRACE_H
#include "potracelib.h"
#include "progress.h"
int process_path( path_t* plist, const potrace_param_t* param, progress_t* progress );
#endif /* TRACE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment