Merge lp:~valavanisalex/inkscape/fix-1156664 into lp:~inkscape.dev/inkscape/trunk

Proposed by Alex Valavanis
Status: Merged
Merged at revision: 14480
Proposed branch: lp:~valavanisalex/inkscape/fix-1156664
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 5061 lines (+276/-4099)
40 files modified
CMakeLists.txt (+0/-1)
CMakeScripts/DefineDependsandFlags.cmake (+11/-0)
CMakeScripts/Modules/FindPotrace.cmake (+62/-0)
configure.ac (+12/-0)
src/menus-skeleton.h (+9/-1)
src/shortcuts.cpp (+8/-1)
src/trace/CMakeLists.txt (+3/-17)
src/trace/Makefile_insert (+5/-16)
src/trace/potrace/auxiliary.h (+0/-80)
src/trace/potrace/bitmap.h (+9/-8)
src/trace/potrace/bitops.h (+0/-83)
src/trace/potrace/curve.cpp (+0/-108)
src/trace/potrace/curve.h (+0/-77)
src/trace/potrace/decompose.cpp (+0/-511)
src/trace/potrace/decompose.h (+0/-16)
src/trace/potrace/greymap.cpp (+0/-941)
src/trace/potrace/greymap.h (+0/-58)
src/trace/potrace/inkscape-potrace.cpp (+3/-4)
src/trace/potrace/inkscape-potrace.h (+1/-1)
src/trace/potrace/lists.h (+0/-285)
src/trace/potrace/potracelib.cpp (+0/-128)
src/trace/potrace/potracelib.h (+0/-139)
src/trace/potrace/progress.h (+0/-77)
src/trace/potrace/render.cpp (+0/-243)
src/trace/potrace/render.h (+0/-27)
src/trace/potrace/trace.cpp (+0/-1245)
src/trace/potrace/trace.h (+0/-15)
src/ui/CMakeLists.txt (+11/-4)
src/ui/dialog/Makefile_insert (+8/-2)
src/ui/dialog/dialog-manager.cpp (+13/-1)
src/ui/dialog/inkscape-preferences.cpp (+2/-0)
src/ui/dialog/inkscape-preferences.h (+8/-0)
src/ui/tool-factory.cpp (+7/-1)
src/ui/tools-switch.h (+8/-0)
src/ui/tools/Makefile_insert (+8/-2)
src/verbs.cpp (+41/-2)
src/verbs.h (+16/-0)
src/widgets/CMakeLists.txt (+9/-2)
src/widgets/Makefile_insert (+8/-2)
src/widgets/toolbox.cpp (+14/-1)
To merge this branch: bzr merge lp:~valavanisalex/inkscape/fix-1156664
Reviewer Review Type Date Requested Status
Inkscape Developers Pending
Review via email: mp+277406@code.launchpad.net

Description of the change

This branch removes the embedded copy of Potrace (except for the handy bitmap.h macros) and links to an external installation instead.

I've also allowed Inkscape to build without Potrace being present, so this can be applied (hopefully) independently of the DevLibs update. If Potrace is not found on the user's system, then the flood and trace tools are disabled.

I've tested on Ubuntu 15.10 with and without Potrace, and using either Autotools or CMake.

I'd appreciate someone checking:
(a) does this work on Windows and OS X?
(b) is my CMake implementation sensible?

To post a comment you must log in.
Revision history for this message
su_v (suv-lp) wrote :

On 2015-11-13 24:49 (+0100), Alex Valavanis wrote:
> I've tested on Ubuntu 15.10 with and without Potrace, and using
> either Autotools or CMake.
>
> I'd appreciate someone checking:
> (a) does this work on Windows and OS X?

Tested successfully with trunk r14478 (GTK2) on OS X 10.7.5 with and
without Potrace, for Autotools- as well as CMake-based build system. Not
tested specifically with osx packaging (it should not cause issues there
though - the external linked library will be copied automagically into
the app bundle, and the library paths rewritten).

Uninformed question wrt potrace: I noticed that in MacPorts (package
manager for OS X) potrace's configure options for metric units
(--enable-metric) and default page size (--enable-a4) are offered as
variants - are these only relevant for the command line tools installed
by potrace, or would different defaults somehow affect trace mode /
flood fill in Inkscape?

> (b) is my CMake implementation sensible?

I noticed that cmake does not inform the user if potrace is not found
(it does report it if found though). Maybe let users know if features
are disabled due to missing optional dependencies?

(c) Independent of build system: it might be safer to disable the
related verbs too (tool, dialog), if compiling without potrace: inkscape
e.g. crashes if launched with one of the (defunct) verbs on the command
line:

$ inkscape --verb=ToolPaintBucket

or when switching tools using keyboard shortcuts (Shift+F7).

14456. By Alex Valavanis

Hide unused verbs if Potrace is not available

Revision history for this message
Alex Valavanis (valavanisalex) wrote :

(c) Hopefully fixed in r14456: The impossible verbs are disabled if Potrace is not found

Revision history for this message
Alex Valavanis (valavanisalex) wrote :

(a) Yes, these options (AFAIU) are only used for the Potrace command-line application. In Inkscape, we just use the API function that converts a bitmap (i.e., an array of pixels rather than a drawing in real-world units) into vector objects using the same scale.

14457. By Alex Valavanis

Add warning about missing Potrace to CMake build

Revision history for this message
Alex Valavanis (valavanisalex) wrote :

(b) Added a warning about missing Potrace to the CMake build in r14457

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-10-26 22:50:52 +0000
3+++ CMakeLists.txt 2015-11-21 12:39:21 +0000
4@@ -100,7 +100,6 @@
5 # -----------------------------------------------------------------------------
6 # BAD HACKS, NEED TO INVESTIGATE MAKING THESE LESS BAD
7 add_definitions(-D_FORTIFY_SOURCE=2)
8-add_definitions(-DPOTRACE="potrace")
9 add_definitions(-DORBIT2=1)
10 add_definitions(-DHAVE_CONFIG_H)
11 add_definitions(-DHAVE_CAIRO_PDF=1) # needed for src/libnrtype/Layout-TNG.h
12
13=== modified file 'CMakeScripts/DefineDependsandFlags.cmake'
14--- CMakeScripts/DefineDependsandFlags.cmake 2015-10-26 22:50:52 +0000
15+++ CMakeScripts/DefineDependsandFlags.cmake 2015-11-21 12:39:21 +0000
16@@ -197,6 +197,17 @@
17 list(APPEND INKSCAPE_LIBS ${POPT_LIBRARIES})
18 add_definitions(${POPT_DEFINITIONS})
19
20+find_package(Potrace)
21+if(POTRACE_FOUND)
22+ list(APPEND INKSCAPE_INCS_SYS ${POTRACE_INCLUDE_DIRS})
23+ list(APPEND INKSCAPE_LIBS ${POTRACE_LIBRARIES})
24+ set(HAVE_POTRACE ON)
25+ add_definitions(-DHAVE_POTRACE)
26+else(POTRACE_FOUND)
27+ set(HAVE_POTRACE OFF)
28+ message(STATUS "Could not locate the Potrace library headers: the Trace Bitmap and Paintbucket tools will be disabled")
29+endif()
30+
31 if(WITH_DBUS)
32 find_package(DBus REQUIRED)
33 if(DBUS_FOUND)
34
35=== added file 'CMakeScripts/Modules/FindPotrace.cmake'
36--- CMakeScripts/Modules/FindPotrace.cmake 1970-01-01 00:00:00 +0000
37+++ CMakeScripts/Modules/FindPotrace.cmake 2015-11-21 12:39:21 +0000
38@@ -0,0 +1,62 @@
39+# POTRACE_FOUND - system has Potrace
40+# POTRACE_INCLUDE_DIRS - the Potrace include directory
41+# POTRACE_LIBRARIES - The libraries needed to use Potrace
42+
43+IF (POTRACE_LIBRARIES AND POTRACE_INCLUDE_DIRS)
44+ # in cache already
45+ SET(POTRACE_FOUND TRUE)
46+ELSE (POTRACE_LIBRARIES AND POTRACE_INCLUDE_DIRS)
47+ FIND_PATH (POTRACE_INCLUDE_DIR
48+ NAMES
49+ potracelib.h
50+ PATHS
51+ /usr/include
52+ /usr/local/include
53+ $ENV{DEVLIBS_PATH}/include
54+ PATH_SUFFIXES
55+ potrace
56+ )
57+
58+ FIND_LIBRARY (POTRACE_LIBRARY
59+ NAMES
60+ potrace
61+ libpotrace
62+ PATHS
63+ /usr/lib
64+ /usr/local/lib
65+ $ENV{DEVLIBS_PATH}/lib
66+ )
67+
68+ if (POTRACE_LIBRARY)
69+ set (POTRACE_FOUND TRUE)
70+ endif (POTRACE_LIBRARY)
71+
72+ set (POTRACE_INCLUDE_DIRS
73+ ${POTRACE_INCLUDE_DIR}
74+ )
75+
76+ if (POTRACE_FOUND)
77+ set(POTRACE_LIBRARIES
78+ ${POTRACE_LIBRARIES}
79+ ${POTRACE_LIBRARY}
80+ )
81+ endif (POTRACE_FOUND)
82+
83+ if (POTRACE_INCLUDE_DIRS AND POTRACE_LIBRARIES)
84+ set(POTRACE_FOUND TRUE)
85+ endif (POTRACE_INCLUDE_DIRS AND POTRACE_LIBRARIES)
86+
87+ if (POTRACE_FOUND)
88+ if (NOT Potrace_FIND_QUIETLY)
89+ message(STATUS "Found Potrace: ${POTRACE_LIBRARIES}")
90+ endif (NOT Potrace_FIND_QUIETLY)
91+ else (POTRACE_FOUND)
92+ if (Potrace_FIND_REQUIRED)
93+ message(FATAL_ERROR "Could not find potrace")
94+ endif (Potrace_FIND_REQUIRED)
95+ endif (POTRACE_FOUND)
96+
97+ # show the POTRACE_INCLUDE_DIRS and POTRACE_LIBRARIES variables only in the advanced view
98+ MARK_AS_ADVANCED(POTRACE_INCLUDE_DIRS POTRACE_LIBRARIES)
99+
100+endif (POTRACE_LIBRARIES AND POTRACE_INCLUDE_DIRS)
101
102=== modified file 'configure.ac'
103--- configure.ac 2015-08-23 07:03:34 +0000
104+++ configure.ac 2015-11-21 12:39:21 +0000
105@@ -240,6 +240,17 @@
106 AC_DEFINE(HAVE_OPENMP, 1, [Use OpenMP])
107 fi
108
109+dnl ********************
110+dnl Check for libpotrace
111+dnl ********************
112+AC_CHECK_LIB(potrace, potrace_trace, [AC_CHECK_HEADER(potracelib.h, potrace_ok=yes, potrace_ok=no)], potrace_ok=no)
113+if test "x$potrace_ok" = "xyes"; then
114+ LIBS="-lpotrace $LIBS"
115+ AC_DEFINE(HAVE_POTRACE, 1, [Use Potrace])
116+fi
117+
118+AM_CONDITIONAL(HAVE_POTRACE, test "x$potrace_ok" = "xyes")
119+
120 dnl ******************************
121 dnl Check for libexif
122 dnl ******************************
123@@ -1192,6 +1203,7 @@
124 Enable LittleCms: ${enable_lcms}
125 Enable DBUS: ${with_dbus}
126 Enable Poppler-Cairo: ${enable_poppler_cairo}
127+ Enable Potrace: ${potrace_ok}
128 ImageMagick Magick++: ${magick_ok}
129 Libwpg: ${with_libwpg}
130 Libvisio: ${with_libvisio}
131
132=== modified file 'src/menus-skeleton.h'
133--- src/menus-skeleton.h 2015-01-25 11:26:05 +0000
134+++ src/menus-skeleton.h 2015-11-21 12:39:21 +0000
135@@ -1,7 +1,9 @@
136 #ifndef SEEN_MENUS_SKELETON_H
137 #define SEEN_MENUS_SKELETON_H
138
139-#include "config.h"
140+#ifdef HAVE_CONFIG_H
141+# include "config.h"
142+#endif
143
144 #ifdef __cplusplus
145 #undef N_
146@@ -221,7 +223,11 @@
147 " <submenu name=\"" N_("_Path") "\">\n"
148 " <verb verb-id=\"ObjectToPath\" />\n"
149 " <verb verb-id=\"StrokeToPath\" />\n"
150+
151+#if HAVE_POTRACE
152 " <verb verb-id=\"SelectionTrace\" />\n"
153+#endif
154+
155 " <verb verb-id=\"SelectionPixelArt\" />\n"
156 " <separator/>\n"
157 " <verb verb-id=\"SelectionUnion\" />\n"
158@@ -284,7 +290,9 @@
159 " <verb verb-id=\"TutorialsBasic\" />\n"
160 " <verb verb-id=\"TutorialsShapes\" />\n"
161 " <verb verb-id=\"TutorialsAdvanced\" />\n"
162+#if HAVE_POTRACE
163 " <verb verb-id=\"TutorialsTracing\" />\n"
164+#endif
165 " <verb verb-id=\"TutorialsTracingPixelArt\" />\n"
166 " <verb verb-id=\"TutorialsCalligraphy\" />\n"
167 " <verb verb-id=\"TutorialsInterpolate\" />\n"
168
169=== modified file 'src/shortcuts.cpp'
170--- src/shortcuts.cpp 2014-06-26 19:40:39 +0000
171+++ src/shortcuts.cpp 2015-11-21 12:39:21 +0000
172@@ -575,7 +575,14 @@
173 }
174
175 Inkscape::Verb *verb=Inkscape::Verb::getbyid(verb_name);
176- if (!verb) {
177+ if (!verb
178+#if !HAVE_POTRACE
179+ // Squash warning about disabled features
180+ && strcmp(verb_name, "ToolPaintBucket") != 0
181+ && strcmp(verb_name, "SelectionTrace") != 0
182+ && strcmp(verb_name, "PaintBucketPrefs") != 0
183+#endif
184+ ) {
185 g_warning("Unknown verb name: %s", verb_name);
186 continue;
187 }
188
189=== modified file 'src/trace/CMakeLists.txt'
190--- src/trace/CMakeLists.txt 2015-06-08 19:01:23 +0000
191+++ src/trace/CMakeLists.txt 2015-11-21 12:39:21 +0000
192@@ -1,3 +1,4 @@
193+if (${HAVE_POTRACE})
194
195 set(trace_SRC
196 filterset.cpp
197@@ -7,14 +8,7 @@
198 siox.cpp
199 trace.cpp
200
201- potrace/curve.cpp
202- potrace/decompose.cpp
203- potrace/greymap.cpp
204 potrace/inkscape-potrace.cpp
205- potrace/potracelib.cpp
206- potrace/render.cpp
207- potrace/trace.cpp
208-
209
210 # -------
211 # Headers
212@@ -26,19 +20,11 @@
213 siox.h
214 trace.h
215
216- potrace/auxiliary.h
217 potrace/bitmap.h
218- potrace/bitops.h
219- potrace/curve.h
220- potrace/decompose.h
221- potrace/greymap.h
222 potrace/inkscape-potrace.h
223- potrace/lists.h
224- potrace/potracelib.h
225- potrace/progress.h
226- potrace/render.h
227- potrace/trace.h
228 )
229
230 # add_inkscape_lib(trace_LIB "${trace_SRC}")
231 add_inkscape_source("${trace_SRC}")
232+
233+endif()
234
235=== modified file 'src/trace/Makefile_insert'
236--- src/trace/Makefile_insert 2009-02-20 22:15:27 +0000
237+++ src/trace/Makefile_insert 2015-11-21 12:39:21 +0000
238@@ -1,5 +1,7 @@
239 ## Makefile.am fragment sourced by src/Makefile.am.
240
241+if HAVE_POTRACE
242+
243 ink_common_sources += \
244 trace/pool.h \
245 trace/trace.h \
246@@ -14,21 +16,8 @@
247 trace/filterset.cpp \
248 trace/siox.h \
249 trace/siox.cpp \
250- trace/potrace/auxiliary.h \
251- trace/potrace/bitmap.h \
252- trace/potrace/curve.cpp \
253- trace/potrace/curve.h \
254- trace/potrace/decompose.cpp \
255- trace/potrace/decompose.h \
256- trace/potrace/greymap.cpp \
257- trace/potrace/greymap.h \
258- trace/potrace/lists.h \
259- trace/potrace/potracelib.cpp \
260- trace/potrace/potracelib.h \
261- trace/potrace/progress.h \
262- trace/potrace/render.cpp \
263- trace/potrace/render.h \
264- trace/potrace/trace.cpp \
265- trace/potrace/trace.h \
266+ trace/potrace/bitmap.h \
267 trace/potrace/inkscape-potrace.cpp \
268 trace/potrace/inkscape-potrace.h
269+
270+endif
271
272=== removed file 'src/trace/potrace/auxiliary.h'
273--- src/trace/potrace/auxiliary.h 2015-03-31 10:33:40 +0000
274+++ src/trace/potrace/auxiliary.h 1970-01-01 00:00:00 +0000
275@@ -1,80 +0,0 @@
276-/* Copyright (C) 2001-2015 Peter Selinger.
277- This file is part of Potrace. It is free software and it is covered
278- by the GNU General Public License. See the file COPYING for details. */
279-
280-/* This header file collects some general-purpose macros (and static
281- inline functions) that are used in various places. */
282-
283-#ifndef AUXILIARY_H
284-#define AUXILIARY_H
285-
286-#include <stdlib.h>
287-
288-#ifdef HAVE_CONFIG_H
289-#include "config.h"
290-#endif
291-
292-/* ---------------------------------------------------------------------- */
293-/* point arithmetic */
294-
295-#include "potracelib.h"
296-
297-struct point_s {
298- long x;
299- long y;
300-};
301-typedef struct point_s point_t;
302-
303-typedef potrace_dpoint_t dpoint_t;
304-
305-/* convert point_t to dpoint_t */
306-static inline dpoint_t dpoint(point_t p) {
307- dpoint_t res;
308- res.x = p.x;
309- res.y = p.y;
310- return res;
311-}
312-
313-/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
314-static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
315- dpoint_t res;
316-
317- res.x = a.x + lambda * (b.x - a.x);
318- res.y = a.y + lambda * (b.y - a.y);
319- return res;
320-}
321-
322-/* ---------------------------------------------------------------------- */
323-/* some useful macros. Note: the "mod" macro works correctly for
324- negative a. Also note that the test for a>=n, while redundant,
325- speeds up the mod function by 70% in the average case (significant
326- since the program spends about 16% of its time here - or 40%
327- without the test). The "floordiv" macro returns the largest integer
328- <= a/n, and again this works correctly for negative a, as long as
329- a,n are integers and n>0. */
330-
331-/* integer arithmetic */
332-
333-static inline int mod(int a, int n) {
334- return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
335-}
336-
337-static inline int floordiv(int a, int n) {
338- return a>=0 ? a/n : -1-(-1-a)/n;
339-}
340-
341-/* Note: the following work for integers and other numeric types. */
342-#undef sign
343-#undef abs
344-#undef min
345-#undef max
346-#undef sq
347-#undef cu
348-#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0)
349-#define abs(a) ((a)>0 ? (a) : -(a))
350-#define min(a,b) ((a)<(b) ? (a) : (b))
351-#define max(a,b) ((a)>(b) ? (a) : (b))
352-#define sq(a) ((a)*(a))
353-#define cu(a) ((a)*(a)*(a))
354-
355-#endif /* AUXILIARY_H */
356
357=== modified file 'src/trace/potrace/bitmap.h'
358--- src/trace/potrace/bitmap.h 2015-03-31 10:33:40 +0000
359+++ src/trace/potrace/bitmap.h 2015-11-21 12:39:21 +0000
360@@ -8,6 +8,7 @@
361 #include <string.h>
362 #include <stdlib.h>
363 #include <errno.h>
364+#include <stddef.h>
365
366 /* The bitmap type is defined in potracelib.h */
367 #include "potracelib.h"
368@@ -28,7 +29,7 @@
369 /* macros for accessing pixel at index (x,y). U* macros omit the
370 bounds check. */
371
372-#define bm_scanline(bm, y) ((bm)->map + (ssize_t)(y)*(ssize_t)(bm)->dy)
373+#define bm_scanline(bm, y) ((bm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(bm)->dy)
374 #define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
375 #define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
376 #define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
377@@ -57,10 +58,10 @@
378 static inline potrace_bitmap_t *bm_new(int w, int h) {
379 potrace_bitmap_t *bm;
380 int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
381- ssize_t size = (ssize_t)dy * (ssize_t)h * (ssize_t)BM_WORDSIZE;
382+ ptrdiff_t size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE;
383
384 /* check for overflow error */
385- if (size < 0 || size / h / dy != BM_WORDSIZE) {
386+ if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) {
387 errno = ENOMEM;
388 return NULL;
389 }
390@@ -83,15 +84,15 @@
391 /* clear the given bitmap. Set all bits to c. */
392 static inline void bm_clear(potrace_bitmap_t *bm, int c) {
393 /* Note: if the bitmap was created with bm_new, then it is
394- guaranteed that size will fit into the ssize_t type. */
395- ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h * (ssize_t)BM_WORDSIZE;
396+ guaranteed that size will fit into the ptrdiff_t type. */
397+ ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h * (ptrdiff_t)BM_WORDSIZE;
398 memset(bm->map, c ? -1 : 0, size);
399 }
400
401 /* duplicate the given bitmap. Return NULL on error with errno set. */
402 static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
403 potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
404- ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h * (ssize_t)BM_WORDSIZE;
405+ ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h * (ptrdiff_t)BM_WORDSIZE;
406 if (!bm1) {
407 return NULL;
408 }
409@@ -101,8 +102,8 @@
410
411 /* invert the given bitmap. */
412 static inline void bm_invert(potrace_bitmap_t *bm) {
413- ssize_t i;
414- ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h;
415+ ptrdiff_t i;
416+ ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h;
417
418 for (i = 0; i < size; i++) {
419 bm->map[i] ^= BM_ALLBITS;
420
421=== removed file 'src/trace/potrace/bitops.h'
422--- src/trace/potrace/bitops.h 2015-03-31 10:33:40 +0000
423+++ src/trace/potrace/bitops.h 1970-01-01 00:00:00 +0000
424@@ -1,83 +0,0 @@
425-/* Copyright (C) 2001-2015 Peter Selinger.
426- This file is part of Potrace. It is free software and it is covered
427- by the GNU General Public License. See the file COPYING for details. */
428-
429-
430-/* bits.h: this file defines some macros for bit manipulations. We
431- provide a generic implementation, as well as machine- and
432- compiler-specific fast implementations */
433-
434-/* lobit: return the position of the rightmost "1" bit of an int, or
435- 32 if none. hibit: return 1 + the position of the leftmost "1" bit
436- of an int, or 0 if none. Note: these functions work on 32-bit
437- integers. */
438-
439-#ifndef BITOPS_H
440-#define BITOPS_H
441-
442-#ifdef HAVE_CONFIG_H
443-#include "config.h"
444-#endif
445-
446-/* ---------------------------------------------------------------------- */
447-/* machine specific macros */
448-
449-#if defined(HAVE_I386)
450-
451-static inline unsigned int lobit(unsigned int x) {
452- unsigned int res;
453- asm ("bsf %1,%0\n\t"
454- "jnz 0f\n\t"
455- "movl $32,%0\n"
456- "0:"
457- : "=r" (res)
458- : "r" (x)
459- : "cc");
460- return res;
461-}
462-
463-static inline unsigned int hibit(unsigned int x) {
464- unsigned int res;
465-
466- asm ("bsr %1,%0\n\t"
467- "jnz 0f\n\t"
468- "movl $-1,%0\n"
469- "0:"
470- : "=r" (res)
471- : "r" (x)
472- : "cc");
473- return res+1;
474-}
475-
476-/* ---------------------------------------------------------------------- */
477-#else /* generic macros */
478-
479-static inline unsigned int lobit(unsigned int x) {
480- unsigned int res = 32;
481- while (x & 0xffffff) {
482- x <<= 8;
483- res -= 8;
484- }
485- while (x) {
486- x <<= 1;
487- res -= 1;
488- }
489- return res;
490-}
491-
492-static inline unsigned int hibit(unsigned int x) {
493- unsigned int res = 0;
494- while (x > 0xff) {
495- x >>= 8;
496- res += 8;
497- }
498- while (x) {
499- x >>= 1;
500- res += 1;
501- }
502- return res;
503-}
504-
505-#endif
506-
507-#endif /* BITOPS_H */
508
509=== removed file 'src/trace/potrace/curve.cpp'
510--- src/trace/potrace/curve.cpp 2015-03-31 10:33:40 +0000
511+++ src/trace/potrace/curve.cpp 1970-01-01 00:00:00 +0000
512@@ -1,108 +0,0 @@
513-/* Copyright (C) 2001-2015 Peter Selinger.
514- This file is part of Potrace. It is free software and it is covered
515- by the GNU General Public License. See the file COPYING for details. */
516-
517-/* private part of the path and curve data structures */
518-
519-#include <stdio.h>
520-#include <stdlib.h>
521-#include <string.h>
522-
523-#include "potracelib.h"
524-#include "lists.h"
525-#include "curve.h"
526-
527-#define SAFE_CALLOC(var, n, typ) \
528- if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
529-
530-/* ---------------------------------------------------------------------- */
531-/* allocate and free path objects */
532-
533-path_t *path_new(void) {
534- path_t *p = NULL;
535- privpath_t *priv = NULL;
536-
537- SAFE_CALLOC(p, 1, path_t);
538- memset(p, 0, sizeof(path_t));
539- SAFE_CALLOC(priv, 1, privpath_t);
540- memset(priv, 0, sizeof(privpath_t));
541- p->priv = priv;
542- return p;
543-
544- calloc_error:
545- free(p);
546- free(priv);
547- return NULL;
548-}
549-
550-/* free the members of the given curve structure. Leave errno unchanged. */
551-static void privcurve_free_members(privcurve_t *curve) {
552- free(curve->tag);
553- free(curve->c);
554- free(curve->vertex);
555- free(curve->alpha);
556- free(curve->alpha0);
557- free(curve->beta);
558-}
559-
560-/* free a path. Leave errno untouched. */
561-void path_free(path_t *p) {
562- if (p) {
563- if (p->priv) {
564- free(p->priv->pt);
565- free(p->priv->lon);
566- free(p->priv->sums);
567- free(p->priv->po);
568- privcurve_free_members(&p->priv->curve);
569- privcurve_free_members(&p->priv->ocurve);
570- }
571- free(p->priv);
572- /* do not free p->fcurve ! */
573- }
574- free(p);
575-}
576-
577-/* free a pathlist, leaving errno untouched. */
578-void pathlist_free(path_t *plist) {
579- path_t *p;
580-
581- list_forall_unlink(p, plist) {
582- path_free(p);
583- }
584-}
585-
586-/* ---------------------------------------------------------------------- */
587-/* initialize and finalize curve structures */
588-
589-typedef dpoint_t dpoint3_t[3];
590-
591-/* initialize the members of the given curve structure to size m.
592- Return 0 on success, 1 on error with errno set. */
593-int privcurve_init(privcurve_t *curve, int n) {
594- memset(curve, 0, sizeof(privcurve_t));
595- curve->n = n;
596- SAFE_CALLOC(curve->tag, n, int);
597- SAFE_CALLOC(curve->c, n, dpoint3_t);
598- SAFE_CALLOC(curve->vertex, n, dpoint_t);
599- SAFE_CALLOC(curve->alpha, n, double);
600- SAFE_CALLOC(curve->alpha0, n, double);
601- SAFE_CALLOC(curve->beta, n, double);
602- return 0;
603-
604- calloc_error:
605- free(curve->tag);
606- free(curve->c);
607- free(curve->vertex);
608- free(curve->alpha);
609- free(curve->alpha0);
610- free(curve->beta);
611- return 1;
612-}
613-
614-/* copy private to public curve structure */
615-void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) {
616- c->n = pc->n;
617- c->tag = pc->tag;
618- c->c = pc->c;
619-}
620-
621
622=== removed file 'src/trace/potrace/curve.h'
623--- src/trace/potrace/curve.h 2015-03-31 10:33:40 +0000
624+++ src/trace/potrace/curve.h 1970-01-01 00:00:00 +0000
625@@ -1,77 +0,0 @@
626-/* Copyright (C) 2001-2015 Peter Selinger.
627- This file is part of Potrace. It is free software and it is covered
628- by the GNU General Public License. See the file COPYING for details. */
629-
630-#ifndef CURVE_H
631-#define CURVE_H
632-
633-#include "auxiliary.h"
634-
635-/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
636- .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
637- defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve:
638- .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and
639- c[2]..c[1] = alpha*(c[2]..vertex).
640- Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
641-*/
642-
643-struct privcurve_s {
644- int n; /* number of segments */
645- int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
646- dpoint_t (*c)[3]; /* c[n][i]: control points.
647- c[n][0] is unused for tag[n]=POTRACE_CORNER */
648- /* the remainder of this structure is special to privcurve, and is
649- used in EPS debug output and special EPS "short coding". These
650- fields are valid only if "alphacurve" is set. */
651- int alphacurve; /* have the following fields been initialized? */
652- dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
653- double *alpha; /* only for POTRACE_CURVETO */
654- double *alpha0; /* "uncropped" alpha parameter - for debug output only */
655- double *beta;
656-};
657-typedef struct privcurve_s privcurve_t;
658-
659-struct sums_s {
660- double x;
661- double y;
662- double x2;
663- double xy;
664- double y2;
665-};
666-typedef struct sums_s sums_t;
667-
668-/* the path structure is filled in with information about a given path
669- as it is accumulated and passed through the different stages of the
670- Potrace algorithm. Backends only need to read the fcurve and fm
671- fields of this data structure, but debugging backends may read
672- other fields. */
673-struct potrace_privpath_s {
674- int len;
675- point_t *pt; /* pt[len]: path as extracted from bitmap */
676- int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
677-
678- int x0, y0; /* origin for sums */
679- sums_t *sums; /* sums[len+1]: cache for fast summing */
680-
681- int m; /* length of optimal polygon */
682- int *po; /* po[m]: optimal polygon */
683-
684- privcurve_t curve; /* curve[m]: array of curve elements */
685- privcurve_t ocurve; /* ocurve[om]: array of curve elements */
686- privcurve_t *fcurve; /* final curve: this points to either curve or
687- ocurve. Do not free this separately. */
688-};
689-typedef struct potrace_privpath_s potrace_privpath_t;
690-
691-/* shorter names */
692-typedef potrace_privpath_t privpath_t;
693-typedef potrace_path_t path_t;
694-
695-path_t *path_new(void);
696-void path_free(path_t *p);
697-void pathlist_free(path_t *plist);
698-int privcurve_init(privcurve_t *curve, int n);
699-void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c);
700-
701-#endif /* CURVE_H */
702-
703
704=== removed file 'src/trace/potrace/decompose.cpp'
705--- src/trace/potrace/decompose.cpp 2015-03-31 10:33:40 +0000
706+++ src/trace/potrace/decompose.cpp 1970-01-01 00:00:00 +0000
707@@ -1,511 +0,0 @@
708-/* Copyright (C) 2001-2015 Peter Selinger.
709- This file is part of Potrace. It is free software and it is covered
710- by the GNU General Public License. See the file COPYING for details. */
711-
712-
713-#include <stdio.h>
714-#include <stdlib.h>
715-#include <string.h>
716-#include <limits.h>
717-
718-#include "potracelib.h"
719-#include "curve.h"
720-#include "lists.h"
721-#include "bitmap.h"
722-#include "decompose.h"
723-#include "progress.h"
724-
725-/* ---------------------------------------------------------------------- */
726-/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
727-
728-static inline int detrand(int x, int y) {
729- unsigned int z;
730- static const unsigned char t[256] = {
731- /* non-linear sequence: constant term of inverse in GF(8),
732- mod x^8+x^4+x^3+x+1 */
733- 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
734- 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
735- 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
736- 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
737- 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
738- 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
739- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
740- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
741- 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
742- 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
743- 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
744- };
745-
746- /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
747- 5-bit sequence */
748- z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
749- z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
750- return z;
751-}
752-
753-/* ---------------------------------------------------------------------- */
754-/* auxiliary bitmap manipulations */
755-
756-/* set the excess padding to 0 */
757-static void bm_clearexcess(potrace_bitmap_t *bm) {
758- if (bm->w % BM_WORDBITS != 0) {
759- potrace_word mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
760- for (int y=0; y<bm->h; y++) {
761- *bm_index(bm, bm->w, y) &= mask;
762- }
763- }
764-}
765-
766-struct bbox_s {
767- int x0, x1, y0, y1; /* bounding box */
768-};
769-typedef struct bbox_s bbox_t;
770-
771-/* clear the bm, assuming the bounding box is set correctly (faster
772- than clearing the whole bitmap) */
773-static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
774- int imin = (bbox->x0 / BM_WORDBITS);
775- int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
776- int i, y;
777-
778- for (y=bbox->y0; y<bbox->y1; y++) {
779- for (i=imin; i<imax; i++) {
780- bm_scanline(bm, y)[i] = 0;
781- }
782- }
783-}
784-
785-/* ---------------------------------------------------------------------- */
786-/* auxiliary functions */
787-
788-/* return the "majority" value of bitmap bm at intersection (x,y). We
789- assume that the bitmap is balanced at "radius" 1. */
790-static int majority(potrace_bitmap_t *bm, int x, int y) {
791- int i, a, ct;
792-
793- for (i=2; i<5; i++) { /* check at "radius" i */
794- ct = 0;
795- for (a=-i+1; a<=i-1; a++) {
796- ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
797- ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
798- ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
799- ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
800- }
801- if (ct>0) {
802- return 1;
803- } else if (ct<0) {
804- return 0;
805- }
806- }
807- return 0;
808-}
809-
810-/* ---------------------------------------------------------------------- */
811-/* decompose image into paths */
812-
813-/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
814- must be a multiple of BM_WORDBITS. */
815-static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
816- int xhi = x & -BM_WORDBITS;
817- int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */
818- int i;
819-
820- if (xhi<xa) {
821- for (i = xhi; i < xa; i+=BM_WORDBITS) {
822- *bm_index(bm, i, y) ^= BM_ALLBITS;
823- }
824- } else {
825- for (i = xa; i < xhi; i+=BM_WORDBITS) {
826- *bm_index(bm, i, y) ^= BM_ALLBITS;
827- }
828- }
829- /* note: the following "if" is needed because x86 treats a<<b as
830- a<<(b&31). I spent hours looking for this bug. */
831- if (xlo) {
832- *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
833- }
834-}
835-
836-/* a path is represented as an array of points, which are thought to
837- lie on the corners of pixels (not on their centers). The path point
838- (x,y) is the lower left corner of the pixel (x,y). Paths are
839- represented by the len/pt components of a path_t object (which
840- also stores other information about the path) */
841-
842-/* xor the given pixmap with the interior of the given path. Note: the
843- path must be within the dimensions of the pixmap. */
844-static void xor_path(potrace_bitmap_t *bm, path_t *p) {
845- int xa, x, y, k, y1;
846-
847- if (p->priv->len <= 0) { /* a path of length 0 is silly, but legal */
848- return;
849- }
850-
851- y1 = p->priv->pt[p->priv->len-1].y;
852-
853- xa = p->priv->pt[0].x & -BM_WORDBITS;
854- for (k=0; k<p->priv->len; k++) {
855- x = p->priv->pt[k].x;
856- y = p->priv->pt[k].y;
857-
858- if (y != y1) {
859- /* efficiently invert the rectangle [x,xa] x [y,y1] */
860- xor_to_ref(bm, x, min(y,y1), xa);
861- y1 = y;
862- }
863- }
864-}
865-
866-/* Find the bounding box of a given path. Path is assumed to be of
867- non-zero length. */
868-static void setbbox_path(bbox_t *bbox, path_t *p) {
869- int x, y;
870- int k;
871-
872- bbox->y0 = INT_MAX;
873- bbox->y1 = 0;
874- bbox->x0 = INT_MAX;
875- bbox->x1 = 0;
876-
877- for (k=0; k<p->priv->len; k++) {
878- x = p->priv->pt[k].x;
879- y = p->priv->pt[k].y;
880-
881- if (x < bbox->x0) {
882- bbox->x0 = x;
883- }
884- if (x > bbox->x1) {
885- bbox->x1 = x;
886- }
887- if (y < bbox->y0) {
888- bbox->y0 = y;
889- }
890- if (y > bbox->y1) {
891- bbox->y1 = y;
892- }
893- }
894-}
895-
896-/* compute a path in the given pixmap, separating black from white.
897- Start path at the point (x0,x1), which must be an upper left corner
898- of the path. Also compute the area enclosed by the path. Return a
899- new path_t object, or NULL on error (note that a legitimate path
900- cannot have length 0). Sign is required for correct interpretation
901- of turnpolicies. */
902-static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
903- int x, y, dirx, diry, len, size, area;
904- int c, d, tmp;
905- point_t *pt, *pt1;
906- path_t *p = NULL;
907-
908- x = x0;
909- y = y0;
910- dirx = 0;
911- diry = -1;
912-
913- len = size = 0;
914- pt = NULL;
915- area = 0;
916-
917- while (1) {
918- /* add point to path */
919- if (len>=size) {
920- size += 100;
921- size = (int)(1.3 * size);
922- pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
923- if (!pt1) {
924- goto error;
925- }
926- pt = pt1;
927- }
928- pt[len].x = x;
929- pt[len].y = y;
930- len++;
931-
932- /* move to next point */
933- x += dirx;
934- y += diry;
935- area += x*diry;
936-
937- /* path complete? */
938- if (x==x0 && y==y0) {
939- break;
940- }
941-
942- /* determine next direction */
943- c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
944- d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
945-
946- if (c && !d) { /* ambiguous turn */
947- if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
948- || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
949- || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
950- || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
951- || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
952- || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
953- tmp = dirx; /* right turn */
954- dirx = diry;
955- diry = -tmp;
956- } else {
957- tmp = dirx; /* left turn */
958- dirx = -diry;
959- diry = tmp;
960- }
961- } else if (c) { /* right turn */
962- tmp = dirx;
963- dirx = diry;
964- diry = -tmp;
965- } else if (!d) { /* left turn */
966- tmp = dirx;
967- dirx = -diry;
968- diry = tmp;
969- }
970- } /* while this path */
971-
972- /* allocate new path object */
973- p = path_new();
974- if (!p) {
975- goto error;
976- }
977-
978- p->priv->pt = pt;
979- p->priv->len = len;
980- p->area = area;
981- p->sign = sign;
982-
983- return p;
984-
985- error:
986- free(pt);
987- return NULL;
988-}
989-
990-/* Give a tree structure to the given path list, based on "insideness"
991- testing. I.e., path A is considered "below" path B if it is inside
992- path B. The input pathlist is assumed to be ordered so that "outer"
993- paths occur before "inner" paths. The tree structure is stored in
994- the "childlist" and "sibling" components of the path_t
995- structure. The linked list structure is also changed so that
996- negative path components are listed immediately after their
997- positive parent. Note: some backends may ignore the tree
998- structure, others may use it e.g. to group path components. We
999- assume that in the input, point 0 of each path is an "upper left"
1000- corner of the path, as returned by bm_to_pathlist. This makes it
1001- easy to find an "interior" point. The bm argument should be a
1002- bitmap of the correct size (large enough to hold all the paths),
1003- and will be used as scratch space. Return 0 on success or -1 on
1004- error with errno set. */
1005-
1006-static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
1007- path_t *p, *p1;
1008- path_t *heap, *heap1;
1009- path_t *cur;
1010- path_t *head;
1011- path_t **plist_hook; /* for fast appending to linked list */
1012- path_t **hook_in, **hook_out; /* for fast appending to linked list */
1013- bbox_t bbox;
1014-
1015- bm_clear(bm, 0);
1016-
1017- /* save original "next" pointers */
1018- list_forall(p, plist) {
1019- p->sibling = p->next;
1020- p->childlist = NULL;
1021- }
1022-
1023- heap = plist;
1024-
1025- /* the heap holds a list of lists of paths. Use "childlist" field
1026- for outer list, "next" field for inner list. Each of the sublists
1027- is to be turned into a tree. This code is messy, but it is
1028- actually fast. Each path is rendered exactly once. We use the
1029- heap to get a tail recursive algorithm: the heap holds a list of
1030- pathlists which still need to be transformed. */
1031-
1032- while (heap) {
1033- /* unlink first sublist */
1034- cur = heap;
1035- heap = heap->childlist;
1036- cur->childlist = NULL;
1037-
1038- /* unlink first path */
1039- head = cur;
1040- cur = cur->next;
1041- head->next = NULL;
1042-
1043- /* render path */
1044- xor_path(bm, head);
1045- setbbox_path(&bbox, head);
1046-
1047- /* now do insideness test for each element of cur; append it to
1048- head->childlist if it's inside head, else append it to
1049- head->next. */
1050- hook_in=&head->childlist;
1051- hook_out=&head->next;
1052- list_forall_unlink(p, cur) {
1053- if (p->priv->pt[0].y <= bbox.y0) {
1054- list_insert_beforehook(p, hook_out);
1055- /* append the remainder of the list to hook_out */
1056- *hook_out = cur;
1057- break;
1058- }
1059- if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
1060- list_insert_beforehook(p, hook_in);
1061- } else {
1062- list_insert_beforehook(p, hook_out);
1063- }
1064- }
1065-
1066- /* clear bm */
1067- clear_bm_with_bbox(bm, &bbox);
1068-
1069- /* now schedule head->childlist and head->next for further
1070- processing */
1071- if (head->next) {
1072- head->next->childlist = heap;
1073- heap = head->next;
1074- }
1075- if (head->childlist) {
1076- head->childlist->childlist = heap;
1077- heap = head->childlist;
1078- }
1079- }
1080-
1081- /* copy sibling structure from "next" to "sibling" component */
1082- p = plist;
1083- while (p) {
1084- p1 = p->sibling;
1085- p->sibling = p->next;
1086- p = p1;
1087- }
1088-
1089- /* reconstruct a new linked list ("next") structure from tree
1090- ("childlist", "sibling") structure. This code is slightly messy,
1091- because we use a heap to make it tail recursive: the heap
1092- contains a list of childlists which still need to be
1093- processed. */
1094- heap = plist;
1095- if (heap) {
1096- heap->next = NULL; /* heap is a linked list of childlists */
1097- }
1098- plist = NULL;
1099- plist_hook = &plist;
1100- while (heap) {
1101- heap1 = heap->next;
1102- for (p=heap; p; p=p->sibling) {
1103- /* p is a positive path */
1104- /* append to linked list */
1105- list_insert_beforehook(p, plist_hook);
1106-
1107- /* go through its children */
1108- for (p1=p->childlist; p1; p1=p1->sibling) {
1109- /* append to linked list */
1110- list_insert_beforehook(p1, plist_hook);
1111- /* append its childlist to heap, if non-empty */
1112- if (p1->childlist) {
1113- list_append(path_t, heap1, p1->childlist);
1114- }
1115- }
1116- }
1117- heap = heap1;
1118- }
1119-
1120- return;
1121-}
1122-
1123-/* find the next set pixel in a row <= y. Pixels are searched first
1124- left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y'
1125- or y=y' and x<x'. If found, return 0 and store pixel in
1126- (*xp,*yp). Else return 1. Note that this function assumes that
1127- excess bytes have been cleared with bm_clearexcess. */
1128-static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
1129- int x;
1130- int y;
1131- int x0;
1132-
1133- x0 = (*xp) & ~(BM_WORDBITS-1);
1134-
1135- for (y=*yp; y>=0; y--) {
1136- for (x=x0; x<bm->w; x+=BM_WORDBITS) {
1137- if (*bm_index(bm, x, y)) {
1138- while (!BM_GET(bm, x, y)) {
1139- x++;
1140- }
1141- /* found */
1142- *xp = x;
1143- *yp = y;
1144- return 0;
1145- }
1146- }
1147- x0 = 0;
1148- }
1149- /* not found */
1150- return 1;
1151-}
1152-
1153-/* Decompose the given bitmap into paths. Returns a linked list of
1154- path_t objects with the fields len, pt, area, sign filled
1155- in. Returns 0 on success with plistp set, or -1 on error with errno
1156- set. */
1157-
1158-int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress) {
1159- int x;
1160- int y;
1161- path_t *p;
1162- path_t *plist = NULL; /* linked list of path objects */
1163- path_t **plist_hook = &plist; /* used to speed up appending to linked list */
1164- potrace_bitmap_t *bm1 = NULL;
1165- int sign;
1166-
1167- bm1 = bm_dup(bm);
1168- if (!bm1) {
1169- goto error;
1170- }
1171-
1172- /* be sure the byte padding on the right is set to 0, as the fast
1173- pixel search below relies on it */
1174- bm_clearexcess(bm1);
1175-
1176- /* iterate through components */
1177- x = 0;
1178- y = bm1->h - 1;
1179- while (findnext(bm1, &x, &y) == 0) {
1180- /* calculate the sign by looking at the original */
1181- sign = BM_GET(bm, x, y) ? '+' : '-';
1182-
1183- /* calculate the path */
1184- p = findpath(bm1, x, y+1, sign, param->turnpolicy);
1185- if (p==NULL) {
1186- goto error;
1187- }
1188-
1189- /* update buffered image */
1190- xor_path(bm1, p);
1191-
1192- /* if it's a turd, eliminate it, else append it to the list */
1193- if (p->area <= param->turdsize) {
1194- path_free(p);
1195- } else {
1196- list_insert_beforehook(p, plist_hook);
1197- }
1198-
1199- if (bm1->h > 0) { /* to be sure */
1200- progress_update(1-y/(double)bm1->h, progress);
1201- }
1202- }
1203-
1204- pathlist_to_tree(plist, bm1);
1205- bm_free(bm1);
1206- *plistp = plist;
1207-
1208- progress_update(1.0, progress);
1209-
1210- return 0;
1211-
1212- error:
1213- bm_free(bm1);
1214- list_forall_unlink(p, plist) {
1215- path_free(p);
1216- }
1217- return -1;
1218-}
1219
1220=== removed file 'src/trace/potrace/decompose.h'
1221--- src/trace/potrace/decompose.h 2015-03-31 10:33:40 +0000
1222+++ src/trace/potrace/decompose.h 1970-01-01 00:00:00 +0000
1223@@ -1,16 +0,0 @@
1224-/* Copyright (C) 2001-2015 Peter Selinger.
1225- This file is part of Potrace. It is free software and it is covered
1226- by the GNU General Public License. See the file COPYING for details. */
1227-
1228-
1229-#ifndef DECOMPOSE_H
1230-#define DECOMPOSE_H
1231-
1232-#include "potracelib.h"
1233-#include "progress.h"
1234-#include "curve.h"
1235-
1236-int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress);
1237-
1238-#endif /* DECOMPOSE_H */
1239-
1240
1241=== removed file 'src/trace/potrace/greymap.cpp'
1242--- src/trace/potrace/greymap.cpp 2015-03-31 10:33:40 +0000
1243+++ src/trace/potrace/greymap.cpp 1970-01-01 00:00:00 +0000
1244@@ -1,941 +0,0 @@
1245-/* Copyright (C) 2001-2015 Peter Selinger.
1246- This file is part of Potrace. It is free software and it is covered
1247- by the GNU General Public License. See the file COPYING for details. */
1248-
1249-
1250-/* Routines for manipulating greymaps, including reading pgm files. We
1251- only deal with greymaps of depth 8 bits. */
1252-
1253-#include <stdlib.h>
1254-#include <string.h>
1255-#include <math.h>
1256-#include <errno.h>
1257-
1258-#include "greymap.h"
1259-#include "bitops.h"
1260-
1261-#define INTBITS (8*sizeof(int))
1262-
1263-#define mod(a,n) ((a)>=(n) ? (a)%(n) : (a)>=0 ? (a) : (n)-1-(-1-(a))%(n))
1264-
1265-static int gm_readbody_pnm(FILE *f, greymap_t **gmp, int magic);
1266-static int gm_readbody_bmp(FILE *f, greymap_t **gmp);
1267-
1268-/* ---------------------------------------------------------------------- */
1269-/* basic greymap routines */
1270-
1271-/* return new un-initialized greymap. NULL with errno on error.
1272- Assumes w, h >= 0. */
1273-greymap_t *gm_new(int w, int h) {
1274- greymap_t *gm;
1275- ssize_t size = (ssize_t)w * (ssize_t)h * (ssize_t)sizeof(signed short int);
1276-
1277- /* check for overflow error */
1278- if (size < 0 || size / w / h != sizeof(signed short int)) {
1279- errno = ENOMEM;
1280- return NULL;
1281- }
1282-
1283- gm = (greymap_t *) malloc(sizeof(greymap_t));
1284- if (!gm) {
1285- return NULL;
1286- }
1287- gm->w = w;
1288- gm->h = h;
1289- gm->map = (signed short int *) malloc(size);
1290- if (!gm->map) {
1291- free(gm);
1292- return NULL;
1293- }
1294- return gm;
1295-}
1296-
1297-/* free the given greymap */
1298-void gm_free(greymap_t *gm) {
1299- if (gm) {
1300- free(gm->map);
1301- }
1302- free(gm);
1303-}
1304-
1305-/* duplicate the given greymap. Return NULL on error with errno set. */
1306-greymap_t *gm_dup(greymap_t *gm) {
1307- greymap_t *gm1 = gm_new(gm->w, gm->h);
1308- if (!gm1) {
1309- return NULL;
1310- }
1311- memcpy(gm1->map, gm->map, gm->w*gm->h*sizeof(signed short int));
1312- return gm1;
1313-}
1314-
1315-/* clear the given greymap to color b. */
1316-void gm_clear(greymap_t *gm, int b) {
1317- if (b==0) {
1318- memset(gm->map, 0, gm->w*gm->h*sizeof(signed short int));
1319- } else {
1320- for (int i=0; i<gm->w*gm->h; i++) {
1321- gm->map[i] = b;
1322- }
1323- }
1324-}
1325-
1326-/* ---------------------------------------------------------------------- */
1327-/* routines for reading pnm streams */
1328-
1329-/* read next character after whitespace and comments. Return EOF on
1330- end of file or error. */
1331-static int fgetc_ws(FILE *f) {
1332- int c;
1333-
1334- while (1) {
1335- c = fgetc(f);
1336- if (c=='#') {
1337- while (1) {
1338- c = fgetc(f);
1339- if (c=='\n' || c==EOF) {
1340- break;
1341- }
1342- }
1343- }
1344- /* space, tab, line feed, carriage return, form-feed */
1345- if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12) {
1346- return c;
1347- }
1348- }
1349-}
1350-
1351-/* skip whitespace and comments, then read a non-negative decimal
1352- number from a stream. Return -1 on EOF. Tolerate other errors (skip
1353- bad characters). Do not the read any characters following the
1354- number (put next character back into the stream) */
1355-
1356-static int readnum(FILE *f) {
1357- int c;
1358- int acc;
1359-
1360- /* skip whitespace and comments */
1361- while (1) {
1362- c = fgetc_ws(f);
1363- if (c==EOF) {
1364- return -1;
1365- }
1366- if (c>='0' && c<='9') {
1367- break;
1368- }
1369- }
1370-
1371- /* first digit is already in c */
1372- acc = c-'0';
1373- while (1) {
1374- c = fgetc(f);
1375- if (c==EOF) {
1376- break;
1377- }
1378- if (c<'0' || c>'9') {
1379- ungetc(c, f);
1380- break;
1381- }
1382- acc *= 10;
1383- acc += c-'0';
1384- }
1385- return acc;
1386-}
1387-
1388-/* similar to readnum, but read only a single 0 or 1, and do not read
1389- any characters after it. */
1390-
1391-static int readbit(FILE *f) {
1392- int c;
1393-
1394- /* skip whitespace and comments */
1395- while (1) {
1396- c = fgetc_ws(f);
1397- if (c==EOF) {
1398- return -1;
1399- }
1400- if (c>='0' && c<='1') {
1401- break;
1402- }
1403- }
1404-
1405- return c-'0';
1406-}
1407-
1408-/* ---------------------------------------------------------------------- */
1409-
1410-/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
1411- convert the output to a greymap. Return greymap in *gmp. Return 0
1412- on success, -1 on error with errno set, -2 on bad file format (with
1413- error message in gm_read_error), and 1 on premature end of file, -3
1414- on empty file (including files with only whitespace and comments),
1415- -4 if wrong magic number. If the return value is >=0, *gmp is
1416- valid. */
1417-
1418-char const *gm_read_error = NULL;
1419-
1420-int gm_read(FILE *f, greymap_t **gmp) {
1421- int magic[2];
1422-
1423- /* read magic number. We ignore whitespace and comments before the
1424- magic, for the benefit of concatenated files in P1-P3 format.
1425- Multiple P1-P3 images in a single file are not formally allowed
1426- by the PNM standard, but there is no harm in being lenient. */
1427-
1428- magic[0] = fgetc_ws(f);
1429- if (magic[0] == EOF) {
1430- /* files which contain only comments and whitespace count as "empty" */
1431- return -3;
1432- }
1433- magic[1] = fgetc(f);
1434- if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
1435- return gm_readbody_pnm(f, gmp, magic[1]);
1436- }
1437- if (magic[0] == 'B' && magic[1] == 'M') {
1438- return gm_readbody_bmp(f, gmp);
1439- }
1440- return -4;
1441-}
1442-
1443-/* ---------------------------------------------------------------------- */
1444-/* read PNM format */
1445-
1446-/* read PNM stream after magic number. Return values as for gm_read */
1447-static int gm_readbody_pnm(FILE *f, greymap_t **gmp, int magic) {
1448- greymap_t *gm;
1449- int x, y, i, j, b, b1, sum;
1450- int bpr; /* bytes per row (as opposed to 4*gm->c) */
1451- int w, h, max;
1452-
1453- gm = NULL;
1454-
1455- w = readnum(f);
1456- if (w<0) {
1457- goto format_error;
1458- }
1459-
1460- h = readnum(f);
1461- if (h<0) {
1462- goto format_error;
1463- }
1464-
1465- /* allocate greymap */
1466- gm = gm_new(w, h);
1467- if (!gm) {
1468- return -1;
1469- }
1470-
1471- /* zero it out */
1472- gm_clear(gm, 0);
1473-
1474- switch (magic) {
1475- default:
1476- /* not reached */
1477- goto format_error;
1478-
1479- case '1':
1480- /* read P1 format: PBM ascii */
1481-
1482- for (y=h-1; y>=0; y--) {
1483- for (x=0; x<w; x++) {
1484- b = readbit(f);
1485- if (b<0) {
1486- goto eof;
1487- }
1488- GM_UPUT(gm, x, y, b ? 0 : 255);
1489- }
1490- }
1491- break;
1492-
1493- case '2':
1494- /* read P2 format: PGM ascii */
1495-
1496- max = readnum(f);
1497- if (max<1) {
1498- goto format_error;
1499- }
1500-
1501- for (y=h-1; y>=0; y--) {
1502- for (x=0; x<w; x++) {
1503- b = readnum(f);
1504- if (b<0) {
1505- goto eof;
1506- }
1507- GM_UPUT(gm, x, y, b*255/max);
1508- }
1509- }
1510- break;
1511-
1512- case '3':
1513- /* read P3 format: PPM ascii */
1514-
1515- max = readnum(f);
1516- if (max<1) {
1517- goto format_error;
1518- }
1519-
1520- for (y=h-1; y>=0; y--) {
1521- for (x=0; x<w; x++) {
1522- sum = 0;
1523- for (i=0; i<3; i++) {
1524- b = readnum(f);
1525- if (b<0) {
1526- goto eof;
1527- }
1528- sum += b;
1529- }
1530- GM_UPUT(gm, x, y, sum*(255/3)/max);
1531- }
1532- }
1533- break;
1534-
1535- case '4':
1536- /* read P4 format: PBM raw */
1537-
1538- b = fgetc(f); /* read single white-space character after height */
1539- if (b==EOF) {
1540- goto format_error;
1541- }
1542-
1543- bpr = (w+7)/8;
1544-
1545- for (y=h-1; y>=0; y--) {
1546- for (i=0; i<bpr; i++) {
1547- b = fgetc(f);
1548- if (b==EOF) {
1549- goto eof;
1550- }
1551- for (j=0; j<8; j++) {
1552- GM_PUT(gm, i*8+j, y, b & (0x80 >> j) ? 0 : 255);
1553- }
1554- }
1555- }
1556- break;
1557-
1558- case '5':
1559- /* read P5 format: PGM raw */
1560-
1561- max = readnum(f);
1562- if (max<1) {
1563- goto format_error;
1564- }
1565-
1566- b = fgetc(f); /* read single white-space character after max */
1567- if (b==EOF) {
1568- goto format_error;
1569- }
1570-
1571- for (y=h-1; y>=0; y--) {
1572- for (x=0; x<w; x++) {
1573- b = fgetc(f);
1574- if (b==EOF)
1575- goto eof;
1576- if (max>=256) {
1577- b <<= 8;
1578- b1 = fgetc(f);
1579- if (b1==EOF)
1580- goto eof;
1581- b |= b1;
1582- }
1583- GM_UPUT(gm, x, y, b*255/max);
1584- }
1585- }
1586- break;
1587-
1588- case '6':
1589- /* read P6 format: PPM raw */
1590-
1591- max = readnum(f);
1592- if (max<1) {
1593- goto format_error;
1594- }
1595-
1596- b = fgetc(f); /* read single white-space character after max */
1597- if (b==EOF) {
1598- goto format_error;
1599- }
1600-
1601- for (y=h-1; y>=0; y--) {
1602- for (x=0; x<w; x++) {
1603- sum = 0;
1604- for (i=0; i<3; i++) {
1605- b = fgetc(f);
1606- if (b==EOF) {
1607- goto eof;
1608- }
1609- if (max>=256) {
1610- b <<= 8;
1611- b1 = fgetc(f);
1612- if (b1==EOF)
1613- goto eof;
1614- b |= b1;
1615- }
1616- sum += b;
1617- }
1618- GM_UPUT(gm, x, y, sum*(255/3)/max);
1619- }
1620- }
1621- break;
1622- }
1623-
1624- *gmp = gm;
1625- return 0;
1626-
1627- eof:
1628- *gmp = gm;
1629- return 1;
1630-
1631- format_error:
1632- gm_free(gm);
1633- if (magic == '1' || magic == '4') {
1634- gm_read_error = "invalid pbm file";
1635- } else if (magic == '2' || magic == '5') {
1636- gm_read_error = "invalid pgm file";
1637- } else {
1638- gm_read_error = "invalid ppm file";
1639- }
1640- return -2;
1641-}
1642-
1643-/* ---------------------------------------------------------------------- */
1644-/* read BMP format */
1645-
1646-struct bmp_info_s {
1647- unsigned int FileSize;
1648- unsigned int reserved;
1649- unsigned int DataOffset;
1650- unsigned int InfoSize;
1651- unsigned int w; /* width */
1652- unsigned int h; /* height */
1653- unsigned int Planes;
1654- unsigned int bits; /* bits per sample */
1655- unsigned int comp; /* compression mode */
1656- unsigned int ImageSize;
1657- unsigned int XpixelsPerM;
1658- unsigned int YpixelsPerM;
1659- unsigned int ncolors; /* number of colors in palette */
1660- unsigned int ColorsImportant;
1661- unsigned int RedMask;
1662- unsigned int GreenMask;
1663- unsigned int BlueMask;
1664- unsigned int AlphaMask;
1665- unsigned int ctbits; /* sample size for color table */
1666- int topdown; /* top-down mode? */
1667-};
1668-typedef struct bmp_info_s bmp_info_t;
1669-
1670-/* auxiliary */
1671-
1672-static int bmp_count = 0; /* counter for byte padding */
1673-static int bmp_pos = 0; /* counter from start of BMP data */
1674-
1675-/* read n-byte little-endian integer. Return 1 on EOF or error, else
1676- 0. Assume n<=4. */
1677-static int bmp_readint(FILE *f, int n, unsigned int *p) {
1678- int i;
1679- unsigned int sum = 0;
1680- int b;
1681-
1682- for (i=0; i<n; i++) {
1683- b = fgetc(f);
1684- if (b==EOF) {
1685- return 1;
1686- }
1687- sum += b << (8*i);
1688- }
1689- bmp_count += n;
1690- bmp_pos += n;
1691- *p = sum;
1692- return 0;
1693-}
1694-
1695-/* reset padding boundary */
1696-static void bmp_pad_reset(void) {
1697- bmp_count = 0;
1698-}
1699-
1700-/* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
1701- else 0. */
1702-static int bmp_pad(FILE *f) {
1703- int c, i, b;
1704-
1705- c = (-bmp_count) & 3;
1706- for (i=0; i<c; i++) {
1707- b = fgetc(f);
1708- if (b==EOF) {
1709- return 1;
1710- }
1711- }
1712- bmp_pos += c;
1713- bmp_count = 0;
1714- return 0;
1715-}
1716-
1717-/* forward to the new file position. Return 1 on EOF or error, else 0 */
1718-static int bmp_forward(FILE *f, int pos) {
1719- int b;
1720-
1721- while (bmp_pos < pos) {
1722- b = fgetc(f);
1723- if (b==EOF) {
1724- return 1;
1725- }
1726- bmp_pos++;
1727- bmp_count++;
1728- }
1729- return 0;
1730-}
1731-
1732-#define TRY(x) if (x) goto try_error
1733-#define TRY_EOF(x) if (x) goto eof
1734-
1735-/* correct y-coordinate for top-down format */
1736-#define ycorr(y) (bmpinfo.topdown ? bmpinfo.h-1-y : y)
1737-
1738-/* read BMP stream after magic number. Return values as for gm_read.
1739- We choose to be as permissive as possible, since there are many
1740- programs out there which produce BMP. For instance, ppmtobmp can
1741- produce codings with anywhere from 1-8 or 24 bits per sample,
1742- although most specifications only allow 1,4,8,24,32. We can also
1743- read both the old and new OS/2 BMP formats in addition to the
1744- Windows BMP format. */
1745-static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
1746- bmp_info_t bmpinfo;
1747- int *coltable;
1748- unsigned int b, c;
1749- unsigned int i, j;
1750- greymap_t *gm;
1751- unsigned int x, y;
1752- int col[2];
1753- unsigned int bitbuf;
1754- unsigned int n;
1755- unsigned int redshift, greenshift, blueshift;
1756-
1757- gm_read_error = NULL;
1758- gm = NULL;
1759- coltable = NULL;
1760-
1761- bmp_pos = 2; /* set file position */
1762-
1763- /* file header (minus magic number) */
1764- TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
1765- TRY(bmp_readint(f, 4, &bmpinfo.reserved));
1766- TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
1767-
1768- /* info header */
1769- TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
1770- if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
1771- || bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124) {
1772- /* Windows or new OS/2 format */
1773- bmpinfo.ctbits = 32; /* sample size in color table */
1774- TRY(bmp_readint(f, 4, &bmpinfo.w));
1775- TRY(bmp_readint(f, 4, &bmpinfo.h));
1776- TRY(bmp_readint(f, 2, &bmpinfo.Planes));
1777- TRY(bmp_readint(f, 2, &bmpinfo.bits));
1778- TRY(bmp_readint(f, 4, &bmpinfo.comp));
1779- TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
1780- TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
1781- TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
1782- TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
1783- TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
1784- if (bmpinfo.InfoSize >= 108) { /* V4 and V5 bitmaps */
1785- TRY(bmp_readint(f, 4, &bmpinfo.RedMask));
1786- TRY(bmp_readint(f, 4, &bmpinfo.GreenMask));
1787- TRY(bmp_readint(f, 4, &bmpinfo.BlueMask));
1788- TRY(bmp_readint(f, 4, &bmpinfo.AlphaMask));
1789- }
1790- if (bmpinfo.w > 0x7fffffff) {
1791- goto format_error;
1792- }
1793- if (bmpinfo.h > 0x7fffffff) {
1794- bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
1795- bmpinfo.topdown = 1;
1796- } else {
1797- bmpinfo.topdown = 0;
1798- }
1799- if (bmpinfo.h > 0x7fffffff) {
1800- goto format_error;
1801- }
1802- } else if (bmpinfo.InfoSize == 12) {
1803- /* old OS/2 format */
1804- bmpinfo.ctbits = 24; /* sample size in color table */
1805- TRY(bmp_readint(f, 2, &bmpinfo.w));
1806- TRY(bmp_readint(f, 2, &bmpinfo.h));
1807- TRY(bmp_readint(f, 2, &bmpinfo.Planes));
1808- TRY(bmp_readint(f, 2, &bmpinfo.bits));
1809- bmpinfo.comp = 0;
1810- bmpinfo.ncolors = 0;
1811- bmpinfo.topdown = 0;
1812- } else {
1813- goto format_error;
1814- }
1815-
1816- if (bmpinfo.comp == 3 && bmpinfo.InfoSize < 108) {
1817- /* bitfield feature is only understood with V4 and V5 format */
1818- goto format_error;
1819- }
1820-
1821- /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
1822- TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
1823-
1824- if (bmpinfo.Planes != 1) {
1825- gm_read_error = "cannot handle bmp planes";
1826- goto format_error; /* can't handle planes */
1827- }
1828-
1829- if (bmpinfo.ncolors == 0) {
1830- bmpinfo.ncolors = 1 << bmpinfo.bits;
1831- }
1832-
1833- /* color table, present only if bmpinfo.bits <= 8. */
1834- if (bmpinfo.bits <= 8) {
1835- coltable = (int *) calloc(bmpinfo.ncolors, sizeof(int));
1836- if (!coltable) {
1837- goto std_error;
1838- }
1839- /* NOTE: since we are reading a greymap, we can immediately convert
1840- the color table entries to grey values. */
1841- for (i=0; i<bmpinfo.ncolors; i++) {
1842- TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
1843- c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
1844- coltable[i] = c/3;
1845- }
1846- }
1847-
1848- /* forward to data */
1849- if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
1850- TRY(bmp_forward(f, bmpinfo.DataOffset));
1851- }
1852-
1853- /* allocate greymap */
1854- gm = gm_new(bmpinfo.w, bmpinfo.h);
1855- if (!gm) {
1856- goto std_error;
1857- }
1858-
1859- /* zero it out */
1860- gm_clear(gm, 0);
1861-
1862- switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
1863-
1864- default:
1865- goto format_error;
1866- break;
1867-
1868- case 0x001: /* monochrome palette */
1869-
1870- /* raster data */
1871- for (y=0; y<bmpinfo.h; y++) {
1872- bmp_pad_reset();
1873- for (i=0; 8*i<bmpinfo.w; i++) {
1874- TRY_EOF(bmp_readint(f, 1, &b));
1875- for (j=0; j<8; j++) {
1876- GM_PUT(gm, i*8+j, ycorr(y), b & (0x80 >> j) ? coltable[1] : coltable[0]);
1877- }
1878- }
1879- TRY(bmp_pad(f));
1880- }
1881- break;
1882-
1883- case 0x002: /* 2-bit to 8-bit palettes */
1884- case 0x003:
1885- case 0x004:
1886- case 0x005:
1887- case 0x006:
1888- case 0x007:
1889- case 0x008:
1890- for (y=0; y<bmpinfo.h; y++) {
1891- bmp_pad_reset();
1892- bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
1893- n = 0; /* number of bits currently in bitbuffer */
1894- for (x=0; x<bmpinfo.w; x++) {
1895- if (n < bmpinfo.bits) {
1896- TRY_EOF(bmp_readint(f, 1, &b));
1897- bitbuf |= b << (INTBITS - 8 - n);
1898- n += 8;
1899- }
1900- b = bitbuf >> (INTBITS - bmpinfo.bits);
1901- bitbuf <<= bmpinfo.bits;
1902- n -= bmpinfo.bits;
1903- GM_UPUT(gm, x, ycorr(y), coltable[b]);
1904- }
1905- TRY(bmp_pad(f));
1906- }
1907- break;
1908-
1909- case 0x010: /* 16-bit encoding */
1910- /* can't do this format because it is not well-documented and I
1911- don't have any samples */
1912- gm_read_error = "cannot handle bmp 16-bit coding";
1913- goto format_error;
1914- break;
1915-
1916- case 0x018: /* 24-bit encoding */
1917- case 0x020: /* 32-bit encoding */
1918- for (y=0; y<bmpinfo.h; y++) {
1919- bmp_pad_reset();
1920- for (x=0; x<bmpinfo.w; x++) {
1921- TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
1922- c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
1923- GM_UPUT(gm, x, ycorr(y), c/3);
1924- }
1925- TRY(bmp_pad(f));
1926- }
1927- break;
1928-
1929- case 0x320: /* 32-bit encoding with bitfields */
1930- redshift = lobit(bmpinfo.RedMask);
1931- greenshift = lobit(bmpinfo.GreenMask);
1932- blueshift = lobit(bmpinfo.BlueMask);
1933-
1934- for (y=0; y<bmpinfo.h; y++) {
1935- bmp_pad_reset();
1936- for (x=0; x<bmpinfo.w; x++) {
1937- TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
1938- c = ((c & bmpinfo.RedMask) >> redshift) + ((c & bmpinfo.GreenMask) >> greenshift) + ((c & bmpinfo.BlueMask) >> blueshift);
1939- GM_UPUT(gm, x, ycorr(y), c/3);
1940- }
1941- TRY(bmp_pad(f));
1942- }
1943- break;
1944-
1945- case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
1946- x = 0;
1947- y = 0;
1948- while (1) {
1949- TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
1950- TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
1951- if (b>0) {
1952- /* repeat count */
1953- col[0] = coltable[(c>>4) & 0xf];
1954- col[1] = coltable[c & 0xf];
1955- for (i=0; i<b && x<bmpinfo.w; i++) {
1956- if (x>=bmpinfo.w) {
1957- x=0;
1958- y++;
1959- }
1960- if (y>=bmpinfo.h) {
1961- break;
1962- }
1963- GM_UPUT(gm, x, ycorr(y), col[i&1]);
1964- x++;
1965- }
1966- } else if (c == 0) {
1967- /* end of line */
1968- y++;
1969- x = 0;
1970- } else if (c == 1) {
1971- /* end of greymap */
1972- break;
1973- } else if (c == 2) {
1974- /* "delta": skip pixels in x and y directions */
1975- TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
1976- TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
1977- x += b;
1978- y += c;
1979- } else {
1980- /* verbatim segment */
1981- for (i=0; i<c; i++) {
1982- if ((i&1)==0) {
1983- TRY_EOF(bmp_readint(f, 1, &b));
1984- }
1985- if (x>=bmpinfo.w) {
1986- x=0;
1987- y++;
1988- }
1989- if (y>=bmpinfo.h) {
1990- break;
1991- }
1992- GM_PUT(gm, x, ycorr(y), coltable[(b>>(4-4*(i&1))) & 0xf]);
1993- x++;
1994- }
1995- if ((c+1) & 2) {
1996- /* pad to 16-bit boundary */
1997- TRY_EOF(bmp_readint(f, 1, &b));
1998- }
1999- }
2000- }
2001- break;
2002-
2003- case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
2004- x = 0;
2005- y = 0;
2006- while (1) {
2007- TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
2008- TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
2009- if (b>0) {
2010- /* repeat count */
2011- for (i=0; i<b; i++) {
2012- if (x>=bmpinfo.w) {
2013- x=0;
2014- y++;
2015- }
2016- if (y>=bmpinfo.h) {
2017- break;
2018- }
2019- GM_UPUT(gm, x, ycorr(y), coltable[c]);
2020- x++;
2021- }
2022- } else if (c == 0) {
2023- /* end of line */
2024- y++;
2025- x = 0;
2026- } else if (c == 1) {
2027- /* end of greymap */
2028- break;
2029- } else if (c == 2) {
2030- /* "delta": skip pixels in x and y directions */
2031- TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
2032- TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
2033- x += b;
2034- y += c;
2035- } else {
2036- /* verbatim segment */
2037- for (i=0; i<c; i++) {
2038- TRY_EOF(bmp_readint(f, 1, &b));
2039- if (x>=bmpinfo.w) {
2040- x=0;
2041- y++;
2042- }
2043- if (y>=bmpinfo.h) {
2044- break;
2045- }
2046- GM_PUT(gm, x, ycorr(y), coltable[b]);
2047- x++;
2048- }
2049- if (c & 1) {
2050- /* pad input to 16-bit boundary */
2051- TRY_EOF(bmp_readint(f, 1, &b));
2052- }
2053- }
2054- }
2055- break;
2056-
2057- } /* switch */
2058-
2059- /* skip any potential junk after the data section, but don't
2060- complain in case EOF is encountered */
2061- bmp_forward(f, bmpinfo.FileSize);
2062-
2063- free(coltable);
2064- *gmp = gm;
2065- return 0;
2066-
2067- eof:
2068- free(coltable);
2069- *gmp = gm;
2070- return 1;
2071-
2072- format_error:
2073- try_error:
2074- free(coltable);
2075- free(gm);
2076- if (!gm_read_error) {
2077- gm_read_error = "invalid bmp file";
2078- }
2079- return -2;
2080-
2081- std_error:
2082- free(coltable);
2083- free(gm);
2084- return -1;
2085-}
2086-
2087-/* ---------------------------------------------------------------------- */
2088-
2089-/* write a pgm stream, either P2 or (if raw != 0) P5 format. Include
2090- one-line comment if non-NULL. Mode determines how out-of-range
2091- color values are converted. Gamma is the desired gamma correction,
2092- if any (set to 2.2 if the image is to look optimal on a CRT monitor,
2093- 2.8 for LCD). Set to 1.0 for no gamma correction */
2094-
2095-int gm_writepgm(FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma) {
2096- int x, y, v;
2097- int gammatable[256];
2098-
2099- /* prepare gamma correction lookup table */
2100- if (gamma != 1.0) {
2101- gammatable[0] = 0;
2102- for (v=1; v<256; v++) {
2103- gammatable[v] = (int)(255 * exp(log(v/255.0)/gamma) + 0.5);
2104- }
2105- } else {
2106- for (v=0; v<256; v++) {
2107- gammatable[v] = v;
2108- }
2109- }
2110-
2111- fprintf(f, raw ? "P5\n" : "P2\n");
2112- if (comment && *comment) {
2113- fprintf(f, "# %s\n", comment);
2114- }
2115- fprintf(f, "%d %d 255\n", gm->w, gm->h);
2116- for (y=gm->h-1; y>=0; y--) {
2117- for (x=0; x<gm->w; x++) {
2118- v = GM_UGET(gm, x, y);
2119- if (mode == GM_MODE_NONZERO) {
2120- if (v > 255) {
2121- v = 510 - v;
2122- }
2123- if (v < 0) {
2124- v = 0;
2125- }
2126- } else if (mode == GM_MODE_ODD) {
2127- v = mod(v, 510);
2128- if (v > 255) {
2129- v = 510 - v;
2130- }
2131- } else if (mode == GM_MODE_POSITIVE) {
2132- if (v < 0) {
2133- v = 0;
2134- } else if (v > 255) {
2135- v = 255;
2136- }
2137- } else if (mode == GM_MODE_NEGATIVE) {
2138- v = 510 - v;
2139- if (v < 0) {
2140- v = 0;
2141- } else if (v > 255) {
2142- v = 255;
2143- }
2144- }
2145- v = gammatable[v];
2146-
2147- if (raw) {
2148- fputc(v, f);
2149- } else {
2150- fprintf(f, x == gm->w-1 ? "%d\n" : "%d ", v);
2151- }
2152- }
2153- }
2154- return 0;
2155-}
2156-
2157-/* ---------------------------------------------------------------------- */
2158-/* output - for primitive debugging purposes only! */
2159-
2160-/* print greymap to screen */
2161-int gm_print(FILE *f, greymap_t *gm) {
2162- int x, y;
2163- int xx, yy;
2164- int d, t;
2165- int sw, sh;
2166-
2167- sw = gm->w < 79 ? gm->w : 79;
2168- sh = gm->w < 79 ? gm->h : gm->h*sw*44/(79*gm->w);
2169-
2170- for (yy=sh-1; yy>=0; yy--) {
2171- for (xx=0; xx<sw; xx++) {
2172- d=0;
2173- t=0;
2174- for (x=xx*gm->w/sw; x<(xx+1)*gm->w/sw; x++) {
2175- for (y=yy*gm->h/sh; y<(yy+1)*gm->h/sh; y++) {
2176- d += GM_GET(gm, x, y);
2177- t += 256;
2178- }
2179- }
2180- fputc("*#=- "[5*d/t], f); /* what a cute trick :) */
2181- }
2182- fputc('\n', f);
2183- }
2184- return 0;
2185-}
2186
2187=== removed file 'src/trace/potrace/greymap.h'
2188--- src/trace/potrace/greymap.h 2015-03-31 10:33:40 +0000
2189+++ src/trace/potrace/greymap.h 1970-01-01 00:00:00 +0000
2190@@ -1,58 +0,0 @@
2191-/* Copyright (C) 2001-2015 Peter Selinger.
2192- This file is part of Potrace. It is free software and it is covered
2193- by the GNU General Public License. See the file COPYING for details. */
2194-
2195-
2196-#ifndef GREYMAP_H
2197-#define GREYMAP_H
2198-
2199-#include <stdio.h>
2200-#include <stdlib.h>
2201-
2202-/* internal format for greymaps. Note: in this format, rows are
2203- ordered from bottom to top. The pixels in each row are given from
2204- left to right. */
2205-
2206-struct greymap_s {
2207- int w; /* width, in pixels */
2208- int h; /* height, in pixels */
2209- signed short int *map; /* raw data, w*h values */
2210-};
2211-typedef struct greymap_s greymap_t;
2212-
2213-/* macros for accessing pixel at index (x,y). Note that the origin is
2214- in the *lower* left corner. U* macros omit the bounds check. */
2215-
2216-#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(ssize_t)(gm)->w])
2217-#define gm_safe(gm, x, y) ((int)(x)>=0 && (int)(x)<(gm)->w && (int)(y)>=0 && (int)(y)<(gm)->h)
2218-#define gm_bound(x, m) ((x)<0 ? 0 : (x)>=(m) ? (m)-1 : (x))
2219-#define GM_UGET(gm, x, y) (*gm_index(gm, x, y))
2220-#define GM_UINC(gm, x, y, b) (*gm_index(gm, x, y) += (short int)(b))
2221-#define GM_UINV(gm, x, y) (*gm_index(gm, x, y) = 255 - *gm_index(gm, x, y))
2222-#define GM_UPUT(gm, x, y, b) (*gm_index(gm, x, y) = (short int)(b))
2223-#define GM_GET(gm, x, y) (gm_safe(gm, x, y) ? GM_UGET(gm, x, y) : 0)
2224-#define GM_INC(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UINC(gm, x, y, b) : 0)
2225-#define GM_INV(gm, x, y) (gm_safe(gm, x, y) ? GM_UINV(gm, x, y) : 0)
2226-#define GM_PUT(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UPUT(gm, x, y, b) : 0)
2227-#define GM_BGET(gm, x, y) GM_UGET(gm, gm_bound(x, gm->w), gm_bound(y, gm->h))
2228-
2229-/* modes for cutting off out-of-range values. The following names
2230- refer to winding numbers. I.e., make a pixel black if winding
2231- number is nonzero, odd, or positive, respectively. We assume that 0
2232- winding number corresponds to white (255). */
2233-#define GM_MODE_NONZERO 1
2234-#define GM_MODE_ODD 2
2235-#define GM_MODE_POSITIVE 3
2236-#define GM_MODE_NEGATIVE 4
2237-
2238-extern char const *gm_read_error;
2239-
2240-greymap_t *gm_new(int w, int h);
2241-greymap_t *gm_dup(greymap_t *gm);
2242-void gm_free(greymap_t *gm);
2243-void gm_clear(greymap_t *gm, int b);
2244-int gm_read(FILE *f, greymap_t **gmp);
2245-int gm_writepgm(FILE *f, greymap_t *gm, char *comment, int raw, int mode, double gamma);
2246-int gm_print(FILE *f, greymap_t *gm);
2247-
2248-#endif /* GREYMAP_H */
2249
2250=== modified file 'src/trace/potrace/inkscape-potrace.cpp'
2251--- src/trace/potrace/inkscape-potrace.cpp 2015-06-22 19:16:52 +0000
2252+++ src/trace/potrace/inkscape-potrace.cpp 2015-11-21 12:39:21 +0000
2253@@ -29,7 +29,6 @@
2254 #include "message-stack.h"
2255 #include <sp-path.h>
2256 #include <svg/path-string.h>
2257-#include "curve.h"
2258 #include "bitmap.h"
2259
2260 using Glib::ustring;
2261@@ -128,7 +127,7 @@
2262
2263
2264 /**
2265- * Recursively descend the path_t node tree, writing paths in SVG
2266+ * Recursively descend the potrace_path_t node tree, writing paths in SVG
2267 * format into the output stream. The Point vector is used to prevent
2268 * redundant paths. Returns number of paths processed.
2269 */
2270@@ -144,7 +143,7 @@
2271 //g_message("node->fm:%d\n", node->fm);
2272 if (!curve->n)
2273 continue;
2274- dpoint_t *pt = curve->c[curve->n - 1];
2275+ const potrace_dpoint_t *pt = curve->c[curve->n - 1];
2276 double x0 = 0.0;
2277 double y0 = 0.0;
2278 double x1 = 0.0;
2279@@ -192,7 +191,7 @@
2280 }
2281 data.closePath();
2282
2283- for (path_t *child=node->childlist; child ; child=child->sibling)
2284+ for (potrace_path_t *child=node->childlist; child ; child=child->sibling)
2285 {
2286 nodeCount += writePaths(engine, child, data, points);
2287 }
2288
2289=== modified file 'src/trace/potrace/inkscape-potrace.h'
2290--- src/trace/potrace/inkscape-potrace.h 2012-02-29 01:16:51 +0000
2291+++ src/trace/potrace/inkscape-potrace.h 2015-11-21 12:39:21 +0000
2292@@ -18,7 +18,7 @@
2293 #define __INKSCAPE_POTRACE_H__
2294
2295 #include <trace/trace.h>
2296-#include "potracelib.h"
2297+#include <potracelib.h>
2298
2299 struct GrayMap_def;
2300 typedef GrayMap_def GrayMap;
2301
2302=== removed file 'src/trace/potrace/lists.h'
2303--- src/trace/potrace/lists.h 2015-03-31 10:33:40 +0000
2304+++ src/trace/potrace/lists.h 1970-01-01 00:00:00 +0000
2305@@ -1,285 +0,0 @@
2306-/* Copyright (C) 2001-2015 Peter Selinger.
2307- This file is part of Potrace. It is free software and it is covered
2308- by the GNU General Public License. See the file COPYING for details. */
2309-
2310-
2311-#ifndef _PS_LISTS_H
2312-#define _PS_LISTS_H
2313-
2314-/* here we define some general list macros. Because they are macros,
2315- they should work on any datatype with a "->next" component. Some of
2316- them use a "hook". If elt and list are of type t* then hook is of
2317- type t**. A hook stands for an insertion point in the list, i.e.,
2318- either before the first element, or between two elements, or after
2319- the last element. If an operation "sets the hook" for an element,
2320- then the hook is set to just before the element. One can insert
2321- something at a hook. One can also unlink at a hook: this means,
2322- unlink the element just after the hook. By "to unlink", we mean the
2323- element is removed from the list, but not deleted. Thus, it and its
2324- components still need to be freed. */
2325-
2326-/* Note: these macros are somewhat experimental. Only the ones that
2327- are actually *used* have been tested. So be careful to test any
2328- that you use. Looking at the output of the preprocessor, "gcc -E"
2329- (possibly piped though "indent"), might help too. Also: these
2330- macros define some internal (local) variables that start with
2331- "_". */
2332-
2333-/* we enclose macro definitions whose body consists of more than one
2334- statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The
2335- reason is that we want to be able to use the macro in a context
2336- such as "if (...) macro(...); else ...". If we didn't use this obscure
2337- trick, we'd have to omit the ";" in such cases. */
2338-
2339-#define MACRO_BEGIN do {
2340-#define MACRO_END } while (0)
2341-
2342-/* ---------------------------------------------------------------------- */
2343-/* macros for singly-linked lists */
2344-
2345-/* traverse list. At the end, elt is set to NULL. */
2346-#define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next)
2347-
2348-/* set elt to the first element of list satisfying boolean condition
2349- c, or NULL if not found */
2350-#define list_find(elt, list, c) \
2351- MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
2352-
2353-/* like forall, except also set hook for elt. */
2354-#define list_forall2(elt, list, hook) \
2355- for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
2356-
2357-/* same as list_find, except also set hook for elt. */
2358-#define list_find2(elt, list, c, hook) \
2359- MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
2360-
2361-/* same, except only use hook. */
2362-#define _list_forall_hook(list, hook) \
2363- for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
2364-
2365-/* same, except only use hook. Note: c may only refer to *hook, not elt. */
2366-#define _list_find_hook(list, c, hook) \
2367- MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
2368-
2369-/* insert element after hook */
2370-#define list_insert_athook(elt, hook) \
2371- MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
2372-
2373-/* insert element before hook */
2374-#define list_insert_beforehook(elt, hook) \
2375- MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
2376-
2377-/* unlink element after hook, let elt be unlinked element, or NULL.
2378- hook remains. */
2379-#define list_unlink_athook(list, elt, hook) \
2380- MACRO_BEGIN \
2381- elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
2382- MACRO_END
2383-
2384-/* unlink the specific element, if it is in the list. Otherwise, set
2385- elt to NULL */
2386-#define list_unlink(listtype, list, elt) \
2387- MACRO_BEGIN \
2388- listtype **_hook; \
2389- _list_find_hook(list, *_hook==elt, _hook); \
2390- list_unlink_athook(list, elt, _hook); \
2391- MACRO_END
2392-
2393-/* prepend elt to list */
2394-#define list_prepend(list, elt) \
2395- MACRO_BEGIN elt->next = list; list = elt; MACRO_END
2396-
2397-/* append elt to list. */
2398-#define list_append(listtype, list, elt) \
2399- MACRO_BEGIN \
2400- listtype **_hook; \
2401- _list_forall_hook(list, _hook) {} \
2402- list_insert_athook(elt, _hook); \
2403- MACRO_END
2404-
2405-/* unlink the first element that satisfies the condition. */
2406-#define list_unlink_cond(listtype, list, elt, c) \
2407- MACRO_BEGIN \
2408- listtype **_hook; \
2409- list_find2(elt, list, c, _hook); \
2410- list_unlink_athook(list, elt, _hook); \
2411- MACRO_END
2412-
2413-/* let elt be the nth element of the list, starting to count from 0.
2414- Return NULL if out of bounds. */
2415-#define list_nth(elt, list, n) \
2416- MACRO_BEGIN \
2417- int _x; /* only evaluate n once */ \
2418- for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \
2419- MACRO_END
2420-
2421-/* let elt be the nth element of the list, starting to count from 0.
2422- Return NULL if out of bounds. */
2423-#define list_nth_hook(elt, list, n, hook) \
2424- MACRO_BEGIN \
2425- int _x; /* only evaluate n once */ \
2426- for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \
2427- MACRO_END
2428-
2429-/* set n to the length of the list */
2430-#define list_length(listtype, list, n) \
2431- MACRO_BEGIN \
2432- listtype *_elt; \
2433- n=0; \
2434- list_forall(_elt, list) \
2435- n++; \
2436- MACRO_END
2437-
2438-/* set n to the index of the first element satisfying cond, or -1 if
2439- none found. Also set elt to the element, or NULL if none found. */
2440-#define list_index(list, n, elt, c) \
2441- MACRO_BEGIN \
2442- n=0; \
2443- list_forall(elt, list) { \
2444- if (c) break; \
2445- n++; \
2446- } \
2447- if (!elt) \
2448- n=-1; \
2449- MACRO_END
2450-
2451-/* set n to the number of elements in the list that satisfy condition c */
2452-#define list_count(list, n, elt, c) \
2453- MACRO_BEGIN \
2454- n=0; \
2455- list_forall(elt, list) { \
2456- if (c) n++; \
2457- } \
2458- MACRO_END
2459-
2460-/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
2461-#define list_forall_unlink(elt, list) \
2462- for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
2463-
2464-/* reverse a list (efficient) */
2465-#define list_reverse(listtype, list) \
2466- MACRO_BEGIN \
2467- listtype *_list1=NULL, *elt; \
2468- list_forall_unlink(elt, list) \
2469- list_prepend(_list1, elt); \
2470- list = _list1; \
2471- MACRO_END
2472-
2473-/* insert the element ELT just before the first element TMP of the
2474- list for which COND holds. Here COND must be a condition of ELT and
2475- TMP. Typical usage is to insert an element into an ordered list:
2476- for instance, list_insert_ordered(listtype, list, elt, tmp,
2477- elt->size <= tmp->size). Note: if we give a "less than or equal"
2478- condition, the new element will be inserted just before a sequence
2479- of equal elements. If we give a "less than" condition, the new
2480- element will be inserted just after a list of equal elements.
2481- Note: it is much more efficient to construct a list with
2482- list_prepend and then order it with list_merge_sort, than to
2483- construct it with list_insert_ordered. */
2484-#define list_insert_ordered(listtype, list, elt, tmp, cond) \
2485- MACRO_BEGIN \
2486- listtype **_hook; \
2487- _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \
2488- list_insert_athook(elt, _hook); \
2489- MACRO_END
2490-
2491-/* sort the given list, according to the comparison condition.
2492- Typical usage is list_sort(listtype, list, a, b, a->size <
2493- b->size). Note: if we give "less than or equal" condition, each
2494- segment of equal elements will be reversed in order. If we give a
2495- "less than" condition, each segment of equal elements will retain
2496- the original order. The latter is slower but sometimes
2497- prettier. Average running time: n*n/2. */
2498-#define list_sort(listtype, list, a, b, cond) \
2499- MACRO_BEGIN \
2500- listtype *_newlist=NULL; \
2501- list_forall_unlink(a, list) \
2502- list_insert_ordered(listtype, _newlist, a, b, cond); \
2503- list = _newlist; \
2504- MACRO_END
2505-
2506-/* a much faster sort algorithm (merge sort, n log n worst case). It
2507- is required that the list type has an additional, unused next1
2508- component. Note there is no curious reversal of order of equal
2509- elements as for list_sort. */
2510-
2511-#define list_mergesort(listtype, list, a, b, cond) \
2512- MACRO_BEGIN \
2513- listtype *_elt, **_hook1; \
2514- \
2515- for (_elt=list; _elt; _elt=_elt->next1) { \
2516- _elt->next1 = _elt->next; \
2517- _elt->next = NULL; \
2518- } \
2519- do { \
2520- _hook1 = &(list); \
2521- while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
2522- _elt = b->next1; \
2523- _list_merge_cond(listtype, a, b, cond, *_hook1); \
2524- _hook1 = &((*_hook1)->next1); \
2525- *_hook1 = _elt; \
2526- } \
2527- } while (_hook1 != &(list)); \
2528- MACRO_END
2529-
2530-/* merge two sorted lists. Store result at &result */
2531-#define _list_merge_cond(listtype, a, b, cond, result) \
2532- MACRO_BEGIN \
2533- listtype **_hook; \
2534- _hook = &(result); \
2535- while (1) { \
2536- if (a==NULL) { \
2537- *_hook = b; \
2538- break; \
2539- } else if (b==NULL) { \
2540- *_hook = a; \
2541- break; \
2542- } else if (cond) { \
2543- *_hook = a; \
2544- _hook = &(a->next); \
2545- a = a->next; \
2546- } else { \
2547- *_hook = b; \
2548- _hook = &(b->next); \
2549- b = b->next; \
2550- } \
2551- } \
2552- MACRO_END
2553-
2554-/* ---------------------------------------------------------------------- */
2555-/* macros for doubly-linked lists */
2556-
2557-#define dlist_append(head, end, elt) \
2558- MACRO_BEGIN \
2559- elt->prev = end; \
2560- elt->next = NULL; \
2561- if (end) { \
2562- end->next = elt; \
2563- } else { \
2564- head = elt; \
2565- } \
2566- end = elt; \
2567- MACRO_END
2568-
2569-/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
2570-#define dlist_forall_unlink(elt, head, end) \
2571- for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
2572-
2573-/* unlink the first element of the list */
2574-#define dlist_unlink_first(head, end, elt) \
2575- MACRO_BEGIN \
2576- elt = head; \
2577- if (head) { \
2578- head = head->next; \
2579- if (head) { \
2580- head->prev = NULL; \
2581- } else { \
2582- end = NULL; \
2583- } \
2584- elt->prev = NULL; \
2585- elt->next = NULL; \
2586- } \
2587- MACRO_END
2588-
2589-#endif /* _PS_LISTS_H */
2590-
2591
2592=== removed file 'src/trace/potrace/potracelib.cpp'
2593--- src/trace/potrace/potracelib.cpp 2015-03-31 10:33:40 +0000
2594+++ src/trace/potrace/potracelib.cpp 1970-01-01 00:00:00 +0000
2595@@ -1,128 +0,0 @@
2596-/* Copyright (C) 2001-2015 Peter Selinger.
2597- This file is part of Potrace. It is free software and it is covered
2598- by the GNU General Public License. See the file COPYING for details. */
2599-
2600-#include <stdlib.h>
2601-#include <string.h>
2602-#include <glib.h>
2603-
2604-#include "potracelib.h"
2605-#include "inkscape-version.h"
2606-#include "curve.h"
2607-#include "decompose.h"
2608-#include "trace.h"
2609-#include "progress.h"
2610-
2611-#ifdef HAVE_CONFIG_H
2612-#include "config.h"
2613-#endif
2614-
2615-/* default parameters */
2616-static const potrace_param_t param_default = {
2617- 2, /* turdsize */
2618- POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */
2619- 1.0, /* alphamax */
2620- 1, /* opticurve */
2621- 0.2, /* opttolerance */
2622- {
2623- NULL, /* callback function */
2624- NULL, /* callback data */
2625- 0.0, 1.0, /* progress range */
2626- 0.0, /* granularity */
2627- },
2628-};
2629-
2630-/* Return a fresh copy of the set of default parameters, or NULL on
2631- failure with errno set. */
2632-potrace_param_t *potrace_param_default(void) {
2633- potrace_param_t *p;
2634-
2635- p = (potrace_param_t *) malloc(sizeof(potrace_param_t));
2636- if (!p) {
2637- return NULL;
2638- }
2639- memcpy(p, &param_default, sizeof(potrace_param_t));
2640- return p;
2641-}
2642-
2643-/* On success, returns a Potrace state st with st->status ==
2644- POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
2645- could be created (with errno set), or returns an incomplete Potrace
2646- state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno
2647- set). Complete or incomplete Potrace state can be freed with
2648- potrace_state_free(). */
2649-potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) {
2650- int r;
2651- path_t *plist = NULL;
2652- potrace_state_t *st;
2653- progress_t prog;
2654- progress_t subprog;
2655-
2656- /* prepare private progress bar state */
2657- prog.callback = param->progress.callback;
2658- prog.data = param->progress.data;
2659- prog.min = param->progress.min;
2660- prog.max = param->progress.max;
2661- prog.epsilon = param->progress.epsilon;
2662- prog.d_prev = param->progress.min;
2663-
2664- /* allocate state object */
2665- st = (potrace_state_t *)malloc(sizeof(potrace_state_t));
2666- if (!st) {
2667- return NULL;
2668- }
2669-
2670- progress_subrange_start(0.0, 0.1, &prog, &subprog);
2671-
2672- /* process the image */
2673- r = bm_to_pathlist(bm, &plist, param, &subprog);
2674- if (r) {
2675- free(st);
2676- return NULL;
2677- }
2678-
2679- st->status = POTRACE_STATUS_OK;
2680- st->plist = plist;
2681- st->priv = NULL; /* private state currently unused */
2682-
2683- progress_subrange_end(&prog, &subprog);
2684-
2685- progress_subrange_start(0.1, 1.0, &prog, &subprog);
2686-
2687- /* partial success. */
2688- r = process_path(plist, param, &subprog);
2689- if (r) {
2690- st->status = POTRACE_STATUS_INCOMPLETE;
2691- }
2692-
2693- progress_subrange_end(&prog, &subprog);
2694-
2695- return st;
2696-}
2697-
2698-/* free a Potrace state, without disturbing errno. */
2699-void potrace_state_free(potrace_state_t *st) {
2700- pathlist_free(st->plist);
2701- free(st);
2702-}
2703-
2704-/* free a parameter list, without disturbing errno. */
2705-void potrace_param_free(potrace_param_t *p) {
2706- free(p);
2707-}
2708-
2709-char *potrace_version(void) {
2710- static char *ver = g_strdup_printf("potracelib %s", Inkscape::version_string);
2711- return ver;
2712-}
2713-
2714-/*
2715- Local Variables:
2716- mode:c++
2717- c-file-style:"stroustrup"
2718- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
2719- indent-tabs-mode:nil
2720- fill-column:99
2721- End:
2722-*/
2723-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
2724
2725=== removed file 'src/trace/potrace/potracelib.h'
2726--- src/trace/potrace/potracelib.h 2015-03-31 10:33:40 +0000
2727+++ src/trace/potrace/potracelib.h 1970-01-01 00:00:00 +0000
2728@@ -1,139 +0,0 @@
2729-/* Copyright (C) 2001-2015 Peter Selinger.
2730- This file is part of Potrace. It is free software and it is covered
2731- by the GNU General Public License. See the file COPYING for details. */
2732-
2733-#ifndef POTRACELIB_H
2734-#define POTRACELIB_H
2735-
2736-/* this file defines the API for the core Potrace library. For a more
2737- detailed description of the API, see potracelib.pdf */
2738-
2739-#ifdef __cplusplus
2740-extern "C" {
2741-#endif
2742-
2743-/* ---------------------------------------------------------------------- */
2744-/* tracing parameters */
2745-
2746-/* turn policies */
2747-#define POTRACE_TURNPOLICY_BLACK 0
2748-#define POTRACE_TURNPOLICY_WHITE 1
2749-#define POTRACE_TURNPOLICY_LEFT 2
2750-#define POTRACE_TURNPOLICY_RIGHT 3
2751-#define POTRACE_TURNPOLICY_MINORITY 4
2752-#define POTRACE_TURNPOLICY_MAJORITY 5
2753-#define POTRACE_TURNPOLICY_RANDOM 6
2754-
2755-/* structure to hold progress bar callback data */
2756-struct potrace_progress_s {
2757- void (*callback)(double progress, void *privdata); /* callback fn */
2758- void *data; /* callback function's private data */
2759- double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
2760- double epsilon; /* granularity: can skip smaller increments */
2761-};
2762-typedef struct potrace_progress_s potrace_progress_t;
2763-
2764-/* structure to hold tracing parameters */
2765-struct potrace_param_s {
2766- int turdsize; /* area of largest path to be ignored */
2767- int turnpolicy; /* resolves ambiguous turns in path decomposition */
2768- double alphamax; /* corner threshold */
2769- int opticurve; /* use curve optimization? */
2770- double opttolerance; /* curve optimization tolerance */
2771- potrace_progress_t progress; /* progress callback function */
2772-};
2773-typedef struct potrace_param_s potrace_param_t;
2774-
2775-/* ---------------------------------------------------------------------- */
2776-/* bitmaps */
2777-
2778-/* native word size */
2779-typedef unsigned long potrace_word;
2780-
2781-/* Internal bitmap format. The n-th scanline starts at scanline(n) =
2782- (map + n*dy). Raster data is stored as a sequence of potrace_words
2783- (NOT bytes). The leftmost bit of scanline n is the most significant
2784- bit of scanline(n)[0]. */
2785-struct potrace_bitmap_s {
2786- int w, h; /* width and height, in pixels */
2787- int dy; /* words per scanline (not bytes) */
2788- potrace_word *map; /* raw data, dy*h words */
2789-};
2790-typedef struct potrace_bitmap_s potrace_bitmap_t;
2791-
2792-/* ---------------------------------------------------------------------- */
2793-/* curves */
2794-
2795-/* point */
2796-struct potrace_dpoint_s {
2797- double x, y;
2798-};
2799-typedef struct potrace_dpoint_s potrace_dpoint_t;
2800-
2801-/* segment tags */
2802-#define POTRACE_CURVETO 1
2803-#define POTRACE_CORNER 2
2804-
2805-/* closed curve segment */
2806-struct potrace_curve_s {
2807- int n; /* number of segments */
2808- int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
2809- potrace_dpoint_t (*c)[3]; /* c[n][3]: control points.
2810- c[n][0] is unused for tag[n]=POTRACE_CORNER */
2811-};
2812-typedef struct potrace_curve_s potrace_curve_t;
2813-
2814-/* Linked list of signed curve segments. Also carries a tree structure. */
2815-struct potrace_path_s {
2816- int area; /* area of the bitmap path */
2817- int sign; /* '+' or '-', depending on orientation */
2818- potrace_curve_t curve; /* this path's vector data */
2819-
2820- struct potrace_path_s *next; /* linked list structure */
2821-
2822- struct potrace_path_s *childlist; /* tree structure */
2823- struct potrace_path_s *sibling; /* tree structure */
2824-
2825- struct potrace_privpath_s *priv; /* private state */
2826-};
2827-typedef struct potrace_path_s potrace_path_t;
2828-
2829-/* ---------------------------------------------------------------------- */
2830-/* Potrace state */
2831-
2832-#define POTRACE_STATUS_OK 0
2833-#define POTRACE_STATUS_INCOMPLETE 1
2834-
2835-struct potrace_state_s {
2836- int status;
2837- potrace_path_t *plist; /* vector data */
2838-
2839- struct potrace_privstate_s *priv; /* private state */
2840-};
2841-typedef struct potrace_state_s potrace_state_t;
2842-
2843-/* ---------------------------------------------------------------------- */
2844-/* API functions */
2845-
2846-/* get default parameters */
2847-potrace_param_t *potrace_param_default(void);
2848-
2849-/* free parameter set */
2850-void potrace_param_free(potrace_param_t *p);
2851-
2852-/* trace a bitmap*/
2853-potrace_state_t *potrace_trace(const potrace_param_t *param,
2854- const potrace_bitmap_t *bm);
2855-
2856-/* free a Potrace state */
2857-void potrace_state_free(potrace_state_t *st);
2858-
2859-/* return a static plain text version string identifying this version
2860- of potracelib */
2861-char *potrace_version(void);
2862-
2863-#ifdef __cplusplus
2864-} /* end of extern "C" */
2865-#endif
2866-
2867-#endif /* POTRACELIB_H */
2868
2869=== removed file 'src/trace/potrace/progress.h'
2870--- src/trace/potrace/progress.h 2015-03-31 10:33:40 +0000
2871+++ src/trace/potrace/progress.h 1970-01-01 00:00:00 +0000
2872@@ -1,77 +0,0 @@
2873-/* Copyright (C) 2001-2015 Peter Selinger.
2874- This file is part of Potrace. It is free software and it is covered
2875- by the GNU General Public License. See the file COPYING for details. */
2876-
2877-/* operations on potrace_progress_t objects, which are defined in
2878- potracelib.h. Note: the code attempts to minimize runtime overhead
2879- when no progress monitoring was requested. It also tries to
2880- minimize excessive progress calculations beneath the "epsilon"
2881- threshold. */
2882-
2883-#ifndef PROGRESS_H
2884-#define PROGRESS_H
2885-
2886-/* structure to hold progress bar callback data */
2887-struct progress_s {
2888- void (*callback)(double progress, void *privdata); /* callback fn */
2889- void *data; /* callback function's private data */
2890- double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
2891- double epsilon; /* granularity: can skip smaller increments */
2892- double b; /* upper limit of subrange in superrange units */
2893- double d_prev; /* previous value of d */
2894-};
2895-typedef struct progress_s progress_t;
2896-
2897-/* notify given progress object of current progress. Note that d is
2898- given in the 0.0-1.0 range, which will be scaled and translated to
2899- the progress object's range. */
2900-static inline void progress_update(double d, progress_t *prog) {
2901- if (prog != NULL && prog->callback != NULL) {
2902- double d_scaled = prog->min * (1-d) + prog->max * d;
2903- if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) {
2904- prog->callback(prog->min * (1-d) + prog->max * d, prog->data);
2905- prog->d_prev = d_scaled;
2906- }
2907- }
2908-}
2909-
2910-/* start a subrange of the given progress object. The range is
2911- narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
2912- is below granularity threshold, disable further subdivisions. */
2913-static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) {
2914- double min, max;
2915-
2916- if (prog == NULL || prog->callback == NULL) {
2917- sub->callback = NULL;
2918- return;
2919- }
2920-
2921- min = prog->min * (1-a) + prog->max * a;
2922- max = prog->min * (1-b) + prog->max * b;
2923-
2924- if (max - min < prog->epsilon) {
2925- sub->callback = NULL; /* no further progress info in subrange */
2926- sub->b = b;
2927- return;
2928- }
2929- sub->callback = prog->callback;
2930- sub->data = prog->data;
2931- sub->epsilon = prog->epsilon;
2932- sub->min = min;
2933- sub->max = max;
2934- sub->d_prev = prog->d_prev;
2935- return;
2936-}
2937-
2938-static inline void progress_subrange_end(progress_t *prog, progress_t *sub) {
2939- if (prog != NULL && prog->callback != NULL) {
2940- if (sub->callback == NULL) {
2941- progress_update(sub->b, prog);
2942- } else {
2943- prog->d_prev = sub->d_prev;
2944- }
2945- }
2946-}
2947-
2948-#endif /* PROGRESS_H */
2949-
2950
2951=== removed file 'src/trace/potrace/render.cpp'
2952--- src/trace/potrace/render.cpp 2015-03-31 10:33:40 +0000
2953+++ src/trace/potrace/render.cpp 1970-01-01 00:00:00 +0000
2954@@ -1,243 +0,0 @@
2955-/* Copyright (C) 2001-2015 Peter Selinger.
2956- This file is part of Potrace. It is free software and it is covered
2957- by the GNU General Public License. See the file COPYING for details. */
2958-
2959-
2960-#include <stdio.h>
2961-#include <stdlib.h>
2962-#include <math.h>
2963-#include <string.h>
2964-
2965-#include "render.h"
2966-#include "greymap.h"
2967-#include "auxiliary.h"
2968-
2969-/* ---------------------------------------------------------------------- */
2970-/* routines for anti-aliased rendering of curves */
2971-
2972-/* we use the following method. Given a point (x,y) (with real-valued
2973- coordinates) in the plane, let (xi,yi) be the integer part of the
2974- coordinates, i.e., xi=floor(x), yi=floor(y). Define a path from
2975- (x,y) to infinity as follows: path(x,y) =
2976- (x,y)--(xi+1,y)--(xi+1,yi)--(+infty,yi). Now as the point (x,y)
2977- moves smoothly across the plane, the path path(x,y) sweeps
2978- (non-smoothly) across a certain area. We proportionately blacken
2979- the area as the path moves "downward", and we whiten the area as
2980- the path moves "upward". This way, after the point has traversed a
2981- closed curve, the interior of the curve has been darkened
2982- (counterclockwise movement) or lightened (clockwise movement). (The
2983- "grey shift" is actually proportional to the winding number). By
2984- choosing the above path with mostly integer coordinates, we achieve
2985- that only pixels close to (x,y) receive grey values and are subject
2986- to round-off errors. The grey value of pixels far away from (x,y)
2987- is always in "integer" (where 0=black, 1=white). As a special
2988- trick, we keep an accumulator rm->a1, which holds a double value to
2989- be added to the grey value to be added to the current pixel
2990- (xi,yi). Only when changing "current" pixels, we convert this
2991- double value to an integer. This way we avoid round-off errors at
2992- the meeting points of line segments. Another speedup measure is
2993- that we sometimes use the rm->incrow_buf array to postpone
2994- incrementing or decrementing an entire row. If incrow_buf[y]=x+1!=0,
2995- then all the pixels (x,y),(x+1,y),(x+2,y),... are scheduled to be
2996- incremented/decremented (which one is the case will be clear from
2997- context). This keeps the greymap operations reasonably local. */
2998-
2999-/* allocate a new rendering state */
3000-render_t *render_new(greymap_t *gm) {
3001- render_t *rm;
3002-
3003- rm = (render_t *) malloc(sizeof(render_t));
3004- if (!rm) {
3005- return NULL;
3006- }
3007- memset(rm, 0, sizeof(render_t));
3008- rm->gm = gm;
3009- rm->incrow_buf = (int *) calloc(gm->h, sizeof(int));
3010- if (!rm->incrow_buf) {
3011- free(rm);
3012- return NULL;
3013- }
3014- memset(rm->incrow_buf, 0, gm->h * sizeof(int));
3015- return rm;
3016-}
3017-
3018-/* free a given rendering state. Note: this does not free the
3019- underlying greymap. */
3020-void render_free(render_t *rm) {
3021- free(rm->incrow_buf);
3022- free(rm);
3023-}
3024-
3025-/* close path */
3026-void render_close(render_t *rm) {
3027- if (rm->x0 != rm->x1 || rm->y0 != rm->y1) {
3028- render_lineto(rm, rm->x0, rm->y0);
3029- }
3030- GM_INC(rm->gm, rm->x0i, rm->y0i, (rm->a0+rm->a1)*255);
3031-
3032- /* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
3033-
3034- /* the persistent state is now undefined */
3035-}
3036-
3037-/* move point */
3038-void render_moveto(render_t *rm, double x, double y) {
3039- /* close the previous path */
3040- render_close(rm);
3041-
3042- rm->x0 = rm->x1 = x;
3043- rm->y0 = rm->y1 = y;
3044- rm->x0i = (int)floor(rm->x0);
3045- rm->x1i = (int)floor(rm->x1);
3046- rm->y0i = (int)floor(rm->y0);
3047- rm->y1i = (int)floor(rm->y1);
3048- rm->a0 = rm->a1 = 0;
3049-}
3050-
3051-/* add b to pixels (x,y) and all pixels to the right of it. However,
3052- use rm->incrow_buf as a buffer to economize on multiple calls */
3053-static void incrow(render_t *rm, int x, int y, int b) {
3054- int i, x0;
3055-
3056- if (y < 0 || y >= rm->gm->h) {
3057- return;
3058- }
3059-
3060- if (x < 0) {
3061- x = 0;
3062- } else if (x > rm->gm->w) {
3063- x = rm->gm->w;
3064- }
3065- if (rm->incrow_buf[y] == 0) {
3066- rm->incrow_buf[y] = x+1; /* store x+1 so that we can use 0 for "vacant" */
3067- return;
3068- }
3069- x0 = rm->incrow_buf[y]-1;
3070- rm->incrow_buf[y] = 0;
3071- if (x0 < x) {
3072- for (i=x0; i<x; i++) {
3073- GM_INC(rm->gm, i, y, -b);
3074- }
3075- } else {
3076- for (i=x; i<x0; i++) {
3077- GM_INC(rm->gm, i, y, b);
3078- }
3079- }
3080-}
3081-
3082-/* render a straight line */
3083-void render_lineto(render_t *rm, double x2, double y2) {
3084- int x2i, y2i;
3085- double t0=2, s0=2;
3086- int sn, tn;
3087- double ss=2, ts=2;
3088- double r0, r1;
3089- int i, j;
3090- int rxi, ryi;
3091- int s;
3092-
3093- x2i = (int)floor(x2);
3094- y2i = (int)floor(y2);
3095-
3096- sn = abs(x2i - rm->x1i);
3097- tn = abs(y2i - rm->y1i);
3098-
3099- if (sn) {
3100- s0 = ((x2>rm->x1 ? rm->x1i+1 : rm->x1i) - rm->x1)/(x2-rm->x1);
3101- ss = fabs(1.0/(x2-rm->x1));
3102- }
3103- if (tn) {
3104- t0 = ((y2>rm->y1 ? rm->y1i+1 : rm->y1i) - rm->y1)/(y2-rm->y1);
3105- ts = fabs(1.0/(y2-rm->y1));
3106- }
3107-
3108- r0 = 0;
3109-
3110- i = 0;
3111- j = 0;
3112-
3113- rxi = rm->x1i;
3114- ryi = rm->y1i;
3115-
3116- while (i<sn || j<tn) {
3117- if (j>=tn || (i<sn && s0+i*ss < t0+j*ts)) {
3118- r1 = s0+i*ss;
3119- i++;
3120- s = 1;
3121- } else {
3122- r1 = t0+j*ts;
3123- j++;
3124- s = 0;
3125- }
3126- /* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
3127-
3128- /* move point to r1 */
3129- rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
3130-
3131- /* move point across pixel boundary */
3132- if (s && x2>rm->x1) {
3133- GM_INC(rm->gm, rxi, ryi, rm->a1*255);
3134- rm->a1 = 0;
3135- rxi++;
3136- rm->a1 += rm->y1+r1*(y2-rm->y1)-ryi;
3137- } else if (!s && y2>rm->y1) {
3138- GM_INC(rm->gm, rxi, ryi, rm->a1*255);
3139- rm->a1 = 0;
3140- incrow(rm, rxi+1, ryi, 255);
3141- ryi++;
3142- } else if (s && x2<=rm->x1) {
3143- rm->a1 -= rm->y1+r1*(y2-rm->y1)-ryi;
3144- GM_INC(rm->gm, rxi, ryi, rm->a1*255);
3145- rm->a1 = 0;
3146- rxi--;
3147- } else if (!s && y2<=rm->y1) {
3148- GM_INC(rm->gm, rxi, ryi, rm->a1*255);
3149- rm->a1 = 0;
3150- ryi--;
3151- incrow(rm, rxi+1, ryi, -255);
3152- }
3153-
3154- r0 = r1;
3155- }
3156-
3157- /* move point to (x2,y2) */
3158-
3159- r1 = 1;
3160- rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
3161-
3162- rm->x1i = x2i;
3163- rm->y1i = y2i;
3164- rm->x1 = x2;
3165- rm->y1 = y2;
3166-
3167- /* assert (rxi != rm->x1i || ryi != rm->y1i); */
3168-}
3169-
3170-/* render a Bezier curve. */
3171-void render_curveto(render_t *rm, double x2, double y2, double x3, double y3, double x4, double y4) {
3172- double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
3173-
3174- x1 = rm->x1; /* starting point */
3175- y1 = rm->y1;
3176-
3177- /* we approximate the curve by small line segments. The interval
3178- size, epsilon, is determined on the fly so that the distance
3179- between the true curve and its approximation does not exceed the
3180- desired accuracy delta. */
3181-
3182- delta = .1; /* desired accuracy, in pixels */
3183-
3184- /* let dd = maximal value of 2nd derivative over curve - this must
3185- occur at an endpoint. */
3186- dd0 = sq(x1-2*x2+x3) + sq(y1-2*y2+y3);
3187- dd1 = sq(x2-2*x3+x4) + sq(y2-2*y3+y4);
3188- dd = 6*sqrt(max(dd0, dd1));
3189- e2 = 8*delta <= dd ? 8*delta/dd : 1;
3190- epsilon = sqrt(e2); /* necessary interval size */
3191-
3192- for (t=epsilon; t<1; t+=epsilon) {
3193- render_lineto(rm, x1*cu(1-t)+3*x2*sq(1-t)*t+3*x3*(1-t)*sq(t)+x4*cu(t),
3194- y1*cu(1-t)+3*y2*sq(1-t)*t+3*y3*(1-t)*sq(t)+y4*cu(t));
3195- }
3196- render_lineto(rm, x4, y4);
3197-}
3198
3199=== removed file 'src/trace/potrace/render.h'
3200--- src/trace/potrace/render.h 2015-03-31 10:33:40 +0000
3201+++ src/trace/potrace/render.h 1970-01-01 00:00:00 +0000
3202@@ -1,27 +0,0 @@
3203-/* Copyright (C) 2001-2015 Peter Selinger.
3204- This file is part of Potrace. It is free software and it is covered
3205- by the GNU General Public License. See the file COPYING for details. */
3206-
3207-
3208-#ifndef RENDER_H
3209-#define RENDER_H
3210-
3211-#include "greymap.h"
3212-
3213-struct render_s {
3214- greymap_t *gm;
3215- double x0, y0, x1, y1;
3216- int x0i, y0i, x1i, y1i;
3217- double a0, a1;
3218- int *incrow_buf;
3219-};
3220-typedef struct render_s render_t;
3221-
3222-render_t *render_new(greymap_t *gm);
3223-void render_free(render_t *rm);
3224-void render_close(render_t *rm);
3225-void render_moveto(render_t *rm, double x, double y);
3226-void render_lineto(render_t *rm, double x, double y);
3227-void render_curveto(render_t *rm, double x2, double y2, double x3, double y3, double x4, double y4);
3228-
3229-#endif /* RENDER_H */
3230
3231=== removed file 'src/trace/potrace/trace.cpp'
3232--- src/trace/potrace/trace.cpp 2015-03-31 10:33:40 +0000
3233+++ src/trace/potrace/trace.cpp 1970-01-01 00:00:00 +0000
3234@@ -1,1245 +0,0 @@
3235-/* Copyright (C) 2001-2015 Peter Selinger.
3236- This file is part of Potrace. It is free software and it is covered
3237- by the GNU General Public License. See the file COPYING for details. */
3238-
3239-/* transform jaggy paths into smooth curves */
3240-
3241-#include <stdio.h>
3242-#include <math.h>
3243-#include <stdlib.h>
3244-#include <string.h>
3245-
3246-#include "potracelib.h"
3247-#include "curve.h"
3248-#include "lists.h"
3249-#include "auxiliary.h"
3250-#include "trace.h"
3251-#include "progress.h"
3252-
3253-#define INFTY 10000000 /* it suffices that this is longer than any
3254- path; it need not be really infinite */
3255-#define COS179 -0.999847695156 /* the cosine of 179 degrees */
3256-
3257-/* ---------------------------------------------------------------------- */
3258-#define SAFE_CALLOC(var, n, typ) \
3259- if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
3260-
3261-/* ---------------------------------------------------------------------- */
3262-/* auxiliary functions */
3263-
3264-/* return a direction that is 90 degrees counterclockwise from p2-p0,
3265- but then restricted to one of the major wind directions (n, nw, w, etc) */
3266-static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
3267- point_t r;
3268-
3269- r.y = sign(p2.x-p0.x);
3270- r.x = -sign(p2.y-p0.y);
3271-
3272- return r;
3273-}
3274-
3275-/* return (p1-p0)x(p2-p0), the area of the parallelogram */
3276-static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
3277- double x1, y1, x2, y2;
3278-
3279- x1 = p1.x-p0.x;
3280- y1 = p1.y-p0.y;
3281- x2 = p2.x-p0.x;
3282- y2 = p2.y-p0.y;
3283-
3284- return x1*y2 - x2*y1;
3285-}
3286-
3287-/* ddenom/dpara have the property that the square of radius 1 centered
3288- at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
3289-static inline double ddenom(dpoint_t p0, dpoint_t p2) {
3290- point_t r = dorth_infty(p0, p2);
3291-
3292- return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
3293-}
3294-
3295-/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
3296-static inline int cyclic(int a, int b, int c) {
3297- if (a<=c) {
3298- return (a<=b && b<c);
3299- } else {
3300- return (a<=b || b<c);
3301- }
3302-}
3303-
3304-/* determine the center and slope of the line i..j. Assume i<j. Needs
3305- "sum" components of p to be set. */
3306-static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
3307- /* assume i<j */
3308-
3309- int n = pp->len;
3310- sums_t *sums = pp->sums;
3311-
3312- double x, y, x2, xy, y2;
3313- double k;
3314- double a, b, c, lambda2, l;
3315- int r=0; /* rotations from i to j */
3316-
3317- while (j>=n) {
3318- j-=n;
3319- r+=1;
3320- }
3321- while (i>=n) {
3322- i-=n;
3323- r-=1;
3324- }
3325- while (j<0) {
3326- j+=n;
3327- r-=1;
3328- }
3329- while (i<0) {
3330- i+=n;
3331- r+=1;
3332- }
3333-
3334- x = sums[j+1].x-sums[i].x+r*sums[n].x;
3335- y = sums[j+1].y-sums[i].y+r*sums[n].y;
3336- x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
3337- xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
3338- y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
3339- k = j+1-i+r*n;
3340-
3341- ctr->x = x/k;
3342- ctr->y = y/k;
3343-
3344- a = (x2-(double)x*x/k)/k;
3345- b = (xy-(double)x*y/k)/k;
3346- c = (y2-(double)y*y/k)/k;
3347-
3348- lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
3349-
3350- /* now find e.vector for lambda2 */
3351- a -= lambda2;
3352- c -= lambda2;
3353-
3354- if (fabs(a) >= fabs(c)) {
3355- l = sqrt(a*a+b*b);
3356- if (l!=0) {
3357- dir->x = -b/l;
3358- dir->y = a/l;
3359- }
3360- } else {
3361- l = sqrt(c*c+b*b);
3362- if (l!=0) {
3363- dir->x = -c/l;
3364- dir->y = b/l;
3365- }
3366- }
3367- if (l==0) {
3368- dir->x = dir->y = 0; /* sometimes this can happen when k=4:
3369- the two eigenvalues coincide */
3370- }
3371-}
3372-
3373-/* the type of (affine) quadratic forms, represented as symmetric 3x3
3374- matrices. The value of the quadratic form at a vector (x,y) is v^t
3375- Q v, where v = (x,y,1)^t. */
3376-typedef double quadform_t[3][3];
3377-
3378-/* Apply quadratic form Q to vector w = (w.x,w.y) */
3379-static inline double quadform(quadform_t Q, dpoint_t w) {
3380- double v[3];
3381- int i, j;
3382- double sum;
3383-
3384- v[0] = w.x;
3385- v[1] = w.y;
3386- v[2] = 1;
3387- sum = 0.0;
3388-
3389- for (i=0; i<3; i++) {
3390- for (j=0; j<3; j++) {
3391- sum += v[i] * Q[i][j] * v[j];
3392- }
3393- }
3394- return sum;
3395-}
3396-
3397-/* calculate p1 x p2 */
3398-static inline int xprod(point_t p1, point_t p2) {
3399- return p1.x*p2.y - p1.y*p2.x;
3400-}
3401-
3402-/* calculate (p1-p0)x(p3-p2) */
3403-static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
3404- double x1, y1, x2, y2;
3405-
3406- x1 = p1.x - p0.x;
3407- y1 = p1.y - p0.y;
3408- x2 = p3.x - p2.x;
3409- y2 = p3.y - p2.y;
3410-
3411- return x1*y2 - x2*y1;
3412-}
3413-
3414-/* calculate (p1-p0)*(p2-p0) */
3415-static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
3416- double x1, y1, x2, y2;
3417-
3418- x1 = p1.x - p0.x;
3419- y1 = p1.y - p0.y;
3420- x2 = p2.x - p0.x;
3421- y2 = p2.y - p0.y;
3422-
3423- return x1*x2 + y1*y2;
3424-}
3425-
3426-/* calculate (p1-p0)*(p3-p2) */
3427-static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
3428- double x1, y1, x2, y2;
3429-
3430- x1 = p1.x - p0.x;
3431- y1 = p1.y - p0.y;
3432- x2 = p3.x - p2.x;
3433- y2 = p3.y - p2.y;
3434-
3435- return x1*x2 + y1*y2;
3436-}
3437-
3438-/* calculate distance between two points */
3439-static inline double ddist(dpoint_t p, dpoint_t q) {
3440- return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
3441-}
3442-
3443-/* calculate point of a bezier curve */
3444-static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
3445- double s = 1-t;
3446- dpoint_t res;
3447-
3448- /* Note: a good optimizing compiler (such as gcc-3) reduces the
3449- following to 16 multiplications, using common subexpression
3450- elimination. */
3451-
3452- res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
3453- res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
3454-
3455- return res;
3456-}
3457-
3458-/* calculate the point t in [0..1] on the (convex) bezier curve
3459- (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
3460- solution in [0..1]. */
3461-static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
3462- double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
3463- double a, b, c; /* a t^2 + b t + c = 0 */
3464- double d, s, r1, r2;
3465-
3466- A = cprod(p0, p1, q0, q1);
3467- B = cprod(p1, p2, q0, q1);
3468- C = cprod(p2, p3, q0, q1);
3469-
3470- a = A - 2*B + C;
3471- b = -2*A + 2*B;
3472- c = A;
3473-
3474- d = b*b - 4*a*c;
3475-
3476- if (a==0 || d<0) {
3477- return -1.0;
3478- }
3479-
3480- s = sqrt(d);
3481-
3482- r1 = (-b + s) / (2 * a);
3483- r2 = (-b - s) / (2 * a);
3484-
3485- if (r1 >= 0 && r1 <= 1) {
3486- return r1;
3487- } else if (r2 >= 0 && r2 <= 1) {
3488- return r2;
3489- } else {
3490- return -1.0;
3491- }
3492-}
3493-
3494-/* ---------------------------------------------------------------------- */
3495-/* Preparation: fill in the sum* fields of a path (used for later
3496- rapid summing). Return 0 on success, 1 with errno set on
3497- failure. */
3498-static int calc_sums(privpath_t *pp) {
3499- int i, x, y;
3500- int n = pp->len;
3501-
3502- SAFE_CALLOC(pp->sums, pp->len+1, sums_t);
3503-
3504- /* origin */
3505- pp->x0 = pp->pt[0].x;
3506- pp->y0 = pp->pt[0].y;
3507-
3508- /* preparatory computation for later fast summing */
3509- pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
3510- for (i=0; i<n; i++) {
3511- x = pp->pt[i].x - pp->x0;
3512- y = pp->pt[i].y - pp->y0;
3513- pp->sums[i+1].x = pp->sums[i].x + x;
3514- pp->sums[i+1].y = pp->sums[i].y + y;
3515- pp->sums[i+1].x2 = pp->sums[i].x2 + x*x;
3516- pp->sums[i+1].xy = pp->sums[i].xy + x*y;
3517- pp->sums[i+1].y2 = pp->sums[i].y2 + y*y;
3518- }
3519- return 0;
3520-
3521- calloc_error:
3522- return 1;
3523-}
3524-
3525-/* ---------------------------------------------------------------------- */
3526-/* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the
3527- "lon" component of a path object (based on pt/len). For each i,
3528- lon[i] is the furthest index such that a straight line can be drawn
3529- from i to lon[i]. Return 1 on error with errno set, else 0. */
3530-
3531-/* this algorithm depends on the fact that the existence of straight
3532- subpaths is a triplewise property. I.e., there exists a straight
3533- line through squares i0,...,in iff there exists a straight line
3534- through i,j,k, for all i0<=i<j<k<=in. (Proof?) */
3535-
3536-/* this implementation of calc_lon is O(n^2). It replaces an older
3537- O(n^3) version. A "constraint" means that future points must
3538- satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1],
3539- cur) <= 0. */
3540-
3541-/* Remark for Potrace 1.1: the current implementation of calc_lon is
3542- more complex than the implementation found in Potrace 1.0, but it
3543- is considerably faster. The introduction of the "nc" data structure
3544- means that we only have to test the constraints for "corner"
3545- points. On a typical input file, this speeds up the calc_lon
3546- function by a factor of 31.2, thereby decreasing its time share
3547- within the overall Potrace algorithm from 72.6% to 7.82%, and
3548- speeding up the overall algorithm by a factor of 3.36. On another
3549- input file, calc_lon was sped up by a factor of 6.7, decreasing its
3550- time share from 51.4% to 13.61%, and speeding up the overall
3551- algorithm by a factor of 1.78. In any case, the savings are
3552- substantial. */
3553-
3554-/* returns 0 on success, 1 on error with errno set */
3555-static int calc_lon(privpath_t *pp) {
3556- point_t *pt = pp->pt;
3557- int n = pp->len;
3558- int i, j, k, k1;
3559- int ct[4], dir;
3560- point_t constraint[2];
3561- point_t cur;
3562- point_t off;
3563- int *pivk = NULL; /* pivk[n] */
3564- int *nc = NULL; /* nc[n]: next corner */
3565- point_t dk; /* direction of k-k1 */
3566- int a, b, c, d;
3567-
3568- SAFE_CALLOC(pivk, n, int);
3569- SAFE_CALLOC(nc, n, int);
3570-
3571- /* initialize the nc data structure. Point from each point to the
3572- furthest future point to which it is connected by a vertical or
3573- horizontal segment. We take advantage of the fact that there is
3574- always a direction change at 0 (due to the path decomposition
3575- algorithm). But even if this were not so, there is no harm, as
3576- in practice, correctness does not depend on the word "furthest"
3577- above. */
3578- k = 0;
3579- for (i=n-1; i>=0; i--) {
3580- if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
3581- k = i+1; /* necessarily i<n-1 in this case */
3582- }
3583- nc[i] = k;
3584- }
3585-
3586- SAFE_CALLOC(pp->lon, n, int);
3587-
3588- /* determine pivot points: for each i, let pivk[i] be the furthest k
3589- such that all j with i<j<k lie on a line connecting i,k. */
3590-
3591- for (i=n-1; i>=0; i--) {
3592- ct[0] = ct[1] = ct[2] = ct[3] = 0;
3593-
3594- /* keep track of "directions" that have occurred */
3595- dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
3596- ct[dir]++;
3597-
3598- constraint[0].x = 0;
3599- constraint[0].y = 0;
3600- constraint[1].x = 0;
3601- constraint[1].y = 0;
3602-
3603- /* find the next k such that no straight line from i to k */
3604- k = nc[i];
3605- k1 = i;
3606- while (1) {
3607-
3608- dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
3609- ct[dir]++;
3610-
3611- /* if all four "directions" have occurred, cut this path */
3612- if (ct[0] && ct[1] && ct[2] && ct[3]) {
3613- pivk[i] = k1;
3614- goto foundk;
3615- }
3616-
3617- cur.x = pt[k].x - pt[i].x;
3618- cur.y = pt[k].y - pt[i].y;
3619-
3620- /* see if current constraint is violated */
3621- if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
3622- goto constraint_viol;
3623- }
3624-
3625- /* else, update constraint */
3626- if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
3627- /* no constraint */
3628- } else {
3629- off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
3630- off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
3631- if (xprod(constraint[0], off) >= 0) {
3632- constraint[0] = off;
3633- }
3634- off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
3635- off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
3636- if (xprod(constraint[1], off) <= 0) {
3637- constraint[1] = off;
3638- }
3639- }
3640- k1 = k;
3641- k = nc[k1];
3642- if (!cyclic(k,i,k1)) {
3643- break;
3644- }
3645- }
3646- constraint_viol:
3647- /* k1 was the last "corner" satisfying the current constraint, and
3648- k is the first one violating it. We now need to find the last
3649- point along k1..k which satisfied the constraint. */
3650- dk.x = sign(pt[k].x-pt[k1].x);
3651- dk.y = sign(pt[k].y-pt[k1].y);
3652- cur.x = pt[k1].x - pt[i].x;
3653- cur.y = pt[k1].y - pt[i].y;
3654- /* find largest integer j such that xprod(constraint[0], cur+j*dk)
3655- >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
3656- of xprod. */
3657- a = xprod(constraint[0], cur);
3658- b = xprod(constraint[0], dk);
3659- c = xprod(constraint[1], cur);
3660- d = xprod(constraint[1], dk);
3661- /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
3662- can be solved with integer arithmetic. */
3663- j = INFTY;
3664- if (b<0) {
3665- j = floordiv(a,-b);
3666- }
3667- if (d>0) {
3668- j = min(j, floordiv(-c,d));
3669- }
3670- pivk[i] = mod(k1+j,n);
3671- foundk:
3672- ;
3673- } /* for i */
3674-
3675- /* clean up: for each i, let lon[i] be the largest k such that for
3676- all i' with i<=i'<k, i'<k<=pivk[i']. */
3677-
3678- j=pivk[n-1];
3679- pp->lon[n-1]=j;
3680- for (i=n-2; i>=0; i--) {
3681- if (cyclic(i+1,pivk[i],j)) {
3682- j=pivk[i];
3683- }
3684- pp->lon[i]=j;
3685- }
3686-
3687- for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
3688- pp->lon[i] = j;
3689- }
3690-
3691- free(pivk);
3692- free(nc);
3693- return 0;
3694-
3695- calloc_error:
3696- free(pivk);
3697- free(nc);
3698- return 1;
3699-}
3700-
3701-
3702-/* ---------------------------------------------------------------------- */
3703-/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
3704-
3705-/* Auxiliary function: calculate the penalty of an edge from i to j in
3706- the given path. This needs the "lon" and "sum*" data. */
3707-
3708-static double penalty3(privpath_t *pp, int i, int j) {
3709- int n = pp->len;
3710- point_t *pt = pp->pt;
3711- sums_t *sums = pp->sums;
3712-
3713- /* assume 0<=i<j<=n */
3714- double x, y, x2, xy, y2;
3715- double k;
3716- double a, b, c, s;
3717- double px, py, ex, ey;
3718-
3719- int r = 0; /* rotations from i to j */
3720-
3721- if (j>=n) {
3722- j -= n;
3723- r = 1;
3724- }
3725-
3726- /* critical inner loop: the "if" gives a 4.6 percent speedup */
3727- if (r == 0) {
3728- x = sums[j+1].x - sums[i].x;
3729- y = sums[j+1].y - sums[i].y;
3730- x2 = sums[j+1].x2 - sums[i].x2;
3731- xy = sums[j+1].xy - sums[i].xy;
3732- y2 = sums[j+1].y2 - sums[i].y2;
3733- k = j+1 - i;
3734- } else {
3735- x = sums[j+1].x - sums[i].x + sums[n].x;
3736- y = sums[j+1].y - sums[i].y + sums[n].y;
3737- x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2;
3738- xy = sums[j+1].xy - sums[i].xy + sums[n].xy;
3739- y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2;
3740- k = j+1 - i + n;
3741- }
3742-
3743- px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
3744- py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
3745- ey = (pt[j].x - pt[i].x);
3746- ex = -(pt[j].y - pt[i].y);
3747-
3748- a = ((x2 - 2*x*px) / k + px*px);
3749- b = ((xy - x*py - y*px) / k + px*py);
3750- c = ((y2 - 2*y*py) / k + py*py);
3751-
3752- s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
3753-
3754- return sqrt(s);
3755-}
3756-
3757-/* find the optimal polygon. Fill in the m and po components. Return 1
3758- on failure with errno set, else 0. Non-cyclic version: assumes i=0
3759- is in the polygon. Fixme: implement cyclic version. */
3760-static int bestpolygon(privpath_t *pp)
3761-{
3762- int i, j, m, k;
3763- int n = pp->len;
3764- double *pen = NULL; /* pen[n+1]: penalty vector */
3765- int *prev = NULL; /* prev[n+1]: best path pointer vector */
3766- int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */
3767- int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */
3768- int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */
3769- int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */
3770- double thispen;
3771- double best;
3772- int c;
3773-
3774- SAFE_CALLOC(pen, n+1, double);
3775- SAFE_CALLOC(prev, n+1, int);
3776- SAFE_CALLOC(clip0, n, int);
3777- SAFE_CALLOC(clip1, n+1, int);
3778- SAFE_CALLOC(seg0, n+1, int);
3779- SAFE_CALLOC(seg1, n+1, int);
3780-
3781- /* calculate clipped paths */
3782- for (i=0; i<n; i++) {
3783- c = mod(pp->lon[mod(i-1,n)]-1,n);
3784- if (c == i) {
3785- c = mod(i+1,n);
3786- }
3787- if (c < i) {
3788- clip0[i] = n;
3789- } else {
3790- clip0[i] = c;
3791- }
3792- }
3793-
3794- /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
3795- clip1[j] <= i, for i,j=0..n. */
3796- j = 1;
3797- for (i=0; i<n; i++) {
3798- while (j <= clip0[i]) {
3799- clip1[j] = i;
3800- j++;
3801- }
3802- }
3803-
3804- /* calculate seg0[j] = longest path from 0 with j segments */
3805- i = 0;
3806- for (j=0; i<n; j++) {
3807- seg0[j] = i;
3808- i = clip0[i];
3809- }
3810- seg0[j] = n;
3811- m = j;
3812-
3813- /* calculate seg1[j] = longest path to n with m-j segments */
3814- i = n;
3815- for (j=m; j>0; j--) {
3816- seg1[j] = i;
3817- i = clip1[i];
3818- }
3819- seg1[0] = 0;
3820-
3821- /* now find the shortest path with m segments, based on penalty3 */
3822- /* note: the outer 2 loops jointly have at most n iterations, thus
3823- the worst-case behavior here is quadratic. In practice, it is
3824- close to linear since the inner loop tends to be short. */
3825- pen[0]=0;
3826- for (j=1; j<=m; j++) {
3827- for (i=seg1[j]; i<=seg0[j]; i++) {
3828- best = -1;
3829- for (k=seg0[j-1]; k>=clip1[i]; k--) {
3830- thispen = penalty3(pp, k, i) + pen[k];
3831- if (best < 0 || thispen < best) {
3832- prev[i] = k;
3833- best = thispen;
3834- }
3835- }
3836- pen[i] = best;
3837- }
3838- }
3839-
3840- pp->m = m;
3841- SAFE_CALLOC(pp->po, m, int);
3842-
3843- /* read off shortest path */
3844- for (i=n, j=m-1; i>0; j--) {
3845- i = prev[i];
3846- pp->po[j] = i;
3847- }
3848-
3849- free(pen);
3850- free(prev);
3851- free(clip0);
3852- free(clip1);
3853- free(seg0);
3854- free(seg1);
3855- return 0;
3856-
3857- calloc_error:
3858- free(pen);
3859- free(prev);
3860- free(clip0);
3861- free(clip1);
3862- free(seg0);
3863- free(seg1);
3864- return 1;
3865-}
3866-
3867-/* ---------------------------------------------------------------------- */
3868-/* Stage 3: vertex adjustment (Sec. 2.3.1). */
3869-
3870-/* Adjust vertices of optimal polygon: calculate the intersection of
3871- the two "optimal" line segments, then move it into the unit square
3872- if it lies outside. Return 1 with errno set on error; 0 on
3873- success. */
3874-
3875-static int adjust_vertices(privpath_t *pp) {
3876- int m = pp->m;
3877- int *po = pp->po;
3878- int n = pp->len;
3879- point_t *pt = pp->pt;
3880- int x0 = pp->x0;
3881- int y0 = pp->y0;
3882-
3883- dpoint_t *ctr = NULL; /* ctr[m] */
3884- dpoint_t *dir = NULL; /* dir[m] */
3885- quadform_t *q = NULL; /* q[m] */
3886- double v[3];
3887- double d;
3888- int i, j, k, l;
3889- dpoint_t s;
3890- int r;
3891-
3892- SAFE_CALLOC(ctr, m, dpoint_t);
3893- SAFE_CALLOC(dir, m, dpoint_t);
3894- SAFE_CALLOC(q, m, quadform_t);
3895-
3896- r = privcurve_init(&pp->curve, m);
3897- if (r) {
3898- goto calloc_error;
3899- }
3900-
3901- /* calculate "optimal" point-slope representation for each line
3902- segment */
3903- for (i=0; i<m; i++) {
3904- j = po[mod(i+1,m)];
3905- j = mod(j-po[i],n)+po[i];
3906- pointslope(pp, po[i], j, &ctr[i], &dir[i]);
3907- }
3908-
3909- /* represent each line segment as a singular quadratic form; the
3910- distance of a point (x,y) from the line segment will be
3911- (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
3912- for (i=0; i<m; i++) {
3913- d = sq(dir[i].x) + sq(dir[i].y);
3914- if (d == 0.0) {
3915- for (j=0; j<3; j++) {
3916- for (k=0; k<3; k++) {
3917- q[i][j][k] = 0;
3918- }
3919- }
3920- } else {
3921- v[0] = dir[i].y;
3922- v[1] = -dir[i].x;
3923- v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
3924- for (l=0; l<3; l++) {
3925- for (k=0; k<3; k++) {
3926- q[i][l][k] = v[l] * v[k] / d;
3927- }
3928- }
3929- }
3930- }
3931-
3932- /* now calculate the "intersections" of consecutive segments.
3933- Instead of using the actual intersection, we find the point
3934- within a given unit square which minimizes the square distance to
3935- the two lines. */
3936- for (i=0; i<m; i++) {
3937- quadform_t Q;
3938- dpoint_t w;
3939- double dx, dy;
3940- double det;
3941- double min, cand; /* minimum and candidate for minimum of quad. form */
3942- double xmin, ymin; /* coordinates of minimum */
3943- int z;
3944-
3945- /* let s be the vertex, in coordinates relative to x0/y0 */
3946- s.x = pt[po[i]].x-x0;
3947- s.y = pt[po[i]].y-y0;
3948-
3949- /* intersect segments i-1 and i */
3950-
3951- j = mod(i-1,m);
3952-
3953- /* add quadratic forms */
3954- for (l=0; l<3; l++) {
3955- for (k=0; k<3; k++) {
3956- Q[l][k] = q[j][l][k] + q[i][l][k];
3957- }
3958- }
3959-
3960- while(1) {
3961- /* minimize the quadratic form Q on the unit square */
3962- /* find intersection */
3963-
3964-#ifdef HAVE_GCC_LOOP_BUG
3965- /* work around gcc bug #12243 */
3966- free(NULL);
3967-#endif
3968-
3969- det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
3970- if (det != 0.0) {
3971- w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
3972- w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
3973- break;
3974- }
3975-
3976- /* matrix is singular - lines are parallel. Add another,
3977- orthogonal axis, through the center of the unit square */
3978- if (Q[0][0]>Q[1][1]) {
3979- v[0] = -Q[0][1];
3980- v[1] = Q[0][0];
3981- } else if (Q[1][1]) {
3982- v[0] = -Q[1][1];
3983- v[1] = Q[1][0];
3984- } else {
3985- v[0] = 1;
3986- v[1] = 0;
3987- }
3988- d = sq(v[0]) + sq(v[1]);
3989- v[2] = - v[1] * s.y - v[0] * s.x;
3990- for (l=0; l<3; l++) {
3991- for (k=0; k<3; k++) {
3992- Q[l][k] += v[l] * v[k] / d;
3993- }
3994- }
3995- }
3996- dx = fabs(w.x-s.x);
3997- dy = fabs(w.y-s.y);
3998- if (dx <= .5 && dy <= .5) {
3999- pp->curve.vertex[i].x = w.x+x0;
4000- pp->curve.vertex[i].y = w.y+y0;
4001- continue;
4002- }
4003-
4004- /* the minimum was not in the unit square; now minimize quadratic
4005- on boundary of square */
4006- min = quadform(Q, s);
4007- xmin = s.x;
4008- ymin = s.y;
4009-
4010- if (Q[0][0] == 0.0) {
4011- goto fixx;
4012- }
4013- for (z=0; z<2; z++) { /* value of the y-coordinate */
4014- w.y = s.y-0.5+z;
4015- w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
4016- dx = fabs(w.x-s.x);
4017- cand = quadform(Q, w);
4018- if (dx <= .5 && cand < min) {
4019- min = cand;
4020- xmin = w.x;
4021- ymin = w.y;
4022- }
4023- }
4024- fixx:
4025- if (Q[1][1] == 0.0) {
4026- goto corners;
4027- }
4028- for (z=0; z<2; z++) { /* value of the x-coordinate */
4029- w.x = s.x-0.5+z;
4030- w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
4031- dy = fabs(w.y-s.y);
4032- cand = quadform(Q, w);
4033- if (dy <= .5 && cand < min) {
4034- min = cand;
4035- xmin = w.x;
4036- ymin = w.y;
4037- }
4038- }
4039- corners:
4040- /* check four corners */
4041- for (l=0; l<2; l++) {
4042- for (k=0; k<2; k++) {
4043- w.x = s.x-0.5+l;
4044- w.y = s.y-0.5+k;
4045- cand = quadform(Q, w);
4046- if (cand < min) {
4047- min = cand;
4048- xmin = w.x;
4049- ymin = w.y;
4050- }
4051- }
4052- }
4053-
4054- pp->curve.vertex[i].x = xmin + x0;
4055- pp->curve.vertex[i].y = ymin + y0;
4056- continue;
4057- }
4058-
4059- free(ctr);
4060- free(dir);
4061- free(q);
4062- return 0;
4063-
4064- calloc_error:
4065- free(ctr);
4066- free(dir);
4067- free(q);
4068- return 1;
4069-}
4070-
4071-/* ---------------------------------------------------------------------- */
4072-/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
4073-
4074-/* reverse orientation of a path */
4075-static void reverse(privcurve_t *curve) {
4076- int m = curve->n;
4077- int i, j;
4078- dpoint_t tmp;
4079-
4080- for (i=0, j=m-1; i<j; i++, j--) {
4081- tmp = curve->vertex[i];
4082- curve->vertex[i] = curve->vertex[j];
4083- curve->vertex[j] = tmp;
4084- }
4085-}
4086-
4087-/* Always succeeds */
4088-static void smooth(privcurve_t *curve, double alphamax) {
4089- int m = curve->n;
4090-
4091- int i, j, k;
4092- double dd, denom, alpha;
4093- dpoint_t p2, p3, p4;
4094-
4095- /* examine each vertex and find its best fit */
4096- for (i=0; i<m; i++) {
4097- j = mod(i+1, m);
4098- k = mod(i+2, m);
4099- p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
4100-
4101- denom = ddenom(curve->vertex[i], curve->vertex[k]);
4102- if (denom != 0.0) {
4103- dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
4104- dd = fabs(dd);
4105- alpha = dd>1 ? (1 - 1.0/dd) : 0;
4106- alpha = alpha / 0.75;
4107- } else {
4108- alpha = 4/3.0;
4109- }
4110- curve->alpha0[j] = alpha; /* remember "original" value of alpha */
4111-
4112- if (alpha >= alphamax) { /* pointed corner */
4113- curve->tag[j] = POTRACE_CORNER;
4114- curve->c[j][1] = curve->vertex[j];
4115- curve->c[j][2] = p4;
4116- } else {
4117- if (alpha < 0.55) {
4118- alpha = 0.55;
4119- } else if (alpha > 1) {
4120- alpha = 1;
4121- }
4122- p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
4123- p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
4124- curve->tag[j] = POTRACE_CURVETO;
4125- curve->c[j][0] = p2;
4126- curve->c[j][1] = p3;
4127- curve->c[j][2] = p4;
4128- }
4129- curve->alpha[j] = alpha; /* store the "cropped" value of alpha */
4130- curve->beta[j] = 0.5;
4131- }
4132- curve->alphacurve = 1;
4133-
4134- return;
4135-}
4136-
4137-/* ---------------------------------------------------------------------- */
4138-/* Stage 5: Curve optimization (Sec. 2.4) */
4139-
4140-/* a private type for the result of opti_penalty */
4141-struct opti_s {
4142- double pen; /* penalty */
4143- dpoint_t c[2]; /* curve parameters */
4144- double t, s; /* curve parameters */
4145- double alpha; /* curve parameter */
4146-};
4147-typedef struct opti_s opti_t;
4148-
4149-/* calculate best fit from i+.5 to j+.5. Assume i<j (cyclically).
4150- Return 0 and set badness and parameters (alpha, beta), if
4151- possible. Return 1 if impossible. */
4152-static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
4153- int m = pp->curve.n;
4154- int k, k1, k2, conv, i1;
4155- double area, alpha, d, d1, d2;
4156- dpoint_t p0, p1, p2, p3, pt;
4157- double A, R, A1, A2, A3, A4;
4158- double s, t;
4159-
4160- /* check convexity, corner-freeness, and maximum bend < 179 degrees */
4161-
4162- if (i==j) { /* sanity - a full loop can never be an opticurve */
4163- return 1;
4164- }
4165-
4166- k = i;
4167- i1 = mod(i+1, m);
4168- k1 = mod(k+1, m);
4169- conv = convc[k1];
4170- if (conv == 0) {
4171- return 1;
4172- }
4173- d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
4174- for (k=k1; k!=j; k=k1) {
4175- k1 = mod(k+1, m);
4176- k2 = mod(k+2, m);
4177- if (convc[k1] != conv) {
4178- return 1;
4179- }
4180- if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
4181- return 1;
4182- }
4183- if (iprod1(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) {
4184- return 1;
4185- }
4186- }
4187-
4188- /* the curve we're working in: */
4189- p0 = pp->curve.c[mod(i,m)][2];
4190- p1 = pp->curve.vertex[mod(i+1,m)];
4191- p2 = pp->curve.vertex[mod(j,m)];
4192- p3 = pp->curve.c[mod(j,m)][2];
4193-
4194- /* determine its area */
4195- area = areac[j] - areac[i];
4196- area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
4197- if (i>=j) {
4198- area += areac[m];
4199- }
4200-
4201- /* find intersection o of p0p1 and p2p3. Let t,s such that o =
4202- interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
4203- triangle (p0,o,p3). */
4204-
4205- A1 = dpara(p0, p1, p2);
4206- A2 = dpara(p0, p1, p3);
4207- A3 = dpara(p0, p2, p3);
4208- /* A4 = dpara(p1, p2, p3); */
4209- A4 = A1+A3-A2;
4210-
4211- if (A2 == A1) { /* this should never happen */
4212- return 1;
4213- }
4214-
4215- t = A3/(A3-A4);
4216- s = A2/(A2-A1);
4217- A = A2 * t / 2.0;
4218-
4219- if (A == 0.0) { /* this should never happen */
4220- return 1;
4221- }
4222-
4223- R = area / A; /* relative area */
4224- alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */
4225-
4226- res->c[0] = interval(t * alpha, p0, p1);
4227- res->c[1] = interval(s * alpha, p3, p2);
4228- res->alpha = alpha;
4229- res->t = t;
4230- res->s = s;
4231-
4232- p1 = res->c[0];
4233- p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */
4234-
4235- res->pen = 0;
4236-
4237- /* calculate penalty */
4238- /* check tangency with edges */
4239- for (k=mod(i+1,m); k!=j; k=k1) {
4240- k1 = mod(k+1,m);
4241- t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
4242- if (t<-.5) {
4243- return 1;
4244- }
4245- pt = bezier(t, p0, p1, p2, p3);
4246- d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
4247- if (d == 0.0) { /* this should never happen */
4248- return 1;
4249- }
4250- d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
4251- if (fabs(d1) > opttolerance) {
4252- return 1;
4253- }
4254- if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
4255- return 1;
4256- }
4257- res->pen += sq(d1);
4258- }
4259-
4260- /* check corners */
4261- for (k=i; k!=j; k=k1) {
4262- k1 = mod(k+1,m);
4263- t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
4264- if (t<-.5) {
4265- return 1;
4266- }
4267- pt = bezier(t, p0, p1, p2, p3);
4268- d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
4269- if (d == 0.0) { /* this should never happen */
4270- return 1;
4271- }
4272- d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
4273- d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
4274- d2 *= 0.75 * pp->curve.alpha[k1];
4275- if (d2 < 0) {
4276- d1 = -d1;
4277- d2 = -d2;
4278- }
4279- if (d1 < d2 - opttolerance) {
4280- return 1;
4281- }
4282- if (d1 < d2) {
4283- res->pen += sq(d1 - d2);
4284- }
4285- }
4286-
4287- return 0;
4288-}
4289-
4290-/* optimize the path p, replacing sequences of Bezier segments by a
4291- single segment when possible. Return 0 on success, 1 with errno set
4292- on failure. */
4293-static int opticurve(privpath_t *pp, double opttolerance) {
4294- int m = pp->curve.n;
4295- int *pt = NULL; /* pt[m+1] */
4296- double *pen = NULL; /* pen[m+1] */
4297- int *len = NULL; /* len[m+1] */
4298- opti_t *opt = NULL; /* opt[m+1] */
4299- int om;
4300- int i,j,r;
4301- opti_t o;
4302- dpoint_t p0;
4303- int i1;
4304- double area;
4305- double alpha;
4306- double *s = NULL;
4307- double *t = NULL;
4308-
4309- int *convc = NULL; /* conv[m]: pre-computed convexities */
4310- double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
4311-
4312- SAFE_CALLOC(pt, m+1, int);
4313- SAFE_CALLOC(pen, m+1, double);
4314- SAFE_CALLOC(len, m+1, int);
4315- SAFE_CALLOC(opt, m+1, opti_t);
4316- SAFE_CALLOC(convc, m, int);
4317- SAFE_CALLOC(areac, m+1, double);
4318-
4319- /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
4320- for (i=0; i<m; i++) {
4321- if (pp->curve.tag[i] == POTRACE_CURVETO) {
4322- convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
4323- } else {
4324- convc[i] = 0;
4325- }
4326- }
4327-
4328- /* pre-calculate areas */
4329- area = 0.0;
4330- areac[0] = 0.0;
4331- p0 = pp->curve.vertex[0];
4332- for (i=0; i<m; i++) {
4333- i1 = mod(i+1, m);
4334- if (pp->curve.tag[i1] == POTRACE_CURVETO) {
4335- alpha = pp->curve.alpha[i1];
4336- area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
4337- area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
4338- }
4339- areac[i+1] = area;
4340- }
4341-
4342- pt[0] = -1;
4343- pen[0] = 0;
4344- len[0] = 0;
4345-
4346- /* Fixme: we always start from a fixed point -- should find the best
4347- curve cyclically */
4348-
4349- for (j=1; j<=m; j++) {
4350- /* calculate best path from 0 to j */
4351- pt[j] = j-1;
4352- pen[j] = pen[j-1];
4353- len[j] = len[j-1]+1;
4354-
4355- for (i=j-2; i>=0; i--) {
4356- r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
4357- if (r) {
4358- break;
4359- }
4360- if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
4361- pt[j] = i;
4362- pen[j] = pen[i] + o.pen;
4363- len[j] = len[i] + 1;
4364- opt[j] = o;
4365- }
4366- }
4367- }
4368- om = len[m];
4369- r = privcurve_init(&pp->ocurve, om);
4370- if (r) {
4371- goto calloc_error;
4372- }
4373- SAFE_CALLOC(s, om, double);
4374- SAFE_CALLOC(t, om, double);
4375-
4376- j = m;
4377- for (i=om-1; i>=0; i--) {
4378- if (pt[j]==j-1) {
4379- pp->ocurve.tag[i] = pp->curve.tag[mod(j,m)];
4380- pp->ocurve.c[i][0] = pp->curve.c[mod(j,m)][0];
4381- pp->ocurve.c[i][1] = pp->curve.c[mod(j,m)][1];
4382- pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
4383- pp->ocurve.vertex[i] = pp->curve.vertex[mod(j,m)];
4384- pp->ocurve.alpha[i] = pp->curve.alpha[mod(j,m)];
4385- pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j,m)];
4386- pp->ocurve.beta[i] = pp->curve.beta[mod(j,m)];
4387- s[i] = t[i] = 1.0;
4388- } else {
4389- pp->ocurve.tag[i] = POTRACE_CURVETO;
4390- pp->ocurve.c[i][0] = opt[j].c[0];
4391- pp->ocurve.c[i][1] = opt[j].c[1];
4392- pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
4393- pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
4394- pp->ocurve.alpha[i] = opt[j].alpha;
4395- pp->ocurve.alpha0[i] = opt[j].alpha;
4396- s[i] = opt[j].s;
4397- t[i] = opt[j].t;
4398- }
4399- j = pt[j];
4400- }
4401-
4402- /* calculate beta parameters */
4403- for (i=0; i<om; i++) {
4404- i1 = mod(i+1,om);
4405- pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
4406- }
4407- pp->ocurve.alphacurve = 1;
4408-
4409- free(pt);
4410- free(pen);
4411- free(len);
4412- free(opt);
4413- free(s);
4414- free(t);
4415- free(convc);
4416- free(areac);
4417- return 0;
4418-
4419- calloc_error:
4420- free(pt);
4421- free(pen);
4422- free(len);
4423- free(opt);
4424- free(s);
4425- free(t);
4426- free(convc);
4427- free(areac);
4428- return 1;
4429-}
4430-
4431-/* ---------------------------------------------------------------------- */
4432-
4433-#define TRY(x) if (x) goto try_error
4434-
4435-/* return 0 on success, 1 on error with errno set. */
4436-int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress) {
4437- path_t *p;
4438- double nn = 0, cn = 0;
4439-
4440- if (progress->callback) {
4441- /* precompute task size for progress estimates */
4442- nn = 0;
4443- list_forall (p, plist) {
4444- nn += p->priv->len;
4445- }
4446- cn = 0;
4447- }
4448-
4449- /* call downstream function with each path */
4450- list_forall (p, plist) {
4451- TRY(calc_sums(p->priv));
4452- TRY(calc_lon(p->priv));
4453- TRY(bestpolygon(p->priv));
4454- TRY(adjust_vertices(p->priv));
4455- if (p->sign == '-') { /* reverse orientation of negative paths */
4456- reverse(&p->priv->curve);
4457- }
4458- smooth(&p->priv->curve, param->alphamax);
4459- if (param->opticurve) {
4460- TRY(opticurve(p->priv, param->opttolerance));
4461- p->priv->fcurve = &p->priv->ocurve;
4462- } else {
4463- p->priv->fcurve = &p->priv->curve;
4464- }
4465- privcurve_to_curve(p->priv->fcurve, &p->curve);
4466-
4467- if (progress->callback) {
4468- cn += p->priv->len;
4469- progress_update(cn/nn, progress);
4470- }
4471- }
4472-
4473- progress_update(1.0, progress);
4474-
4475- return 0;
4476-
4477- try_error:
4478- return 1;
4479-}
4480
4481=== removed file 'src/trace/potrace/trace.h'
4482--- src/trace/potrace/trace.h 2015-03-31 10:33:40 +0000
4483+++ src/trace/potrace/trace.h 1970-01-01 00:00:00 +0000
4484@@ -1,15 +0,0 @@
4485-/* Copyright (C) 2001-2015 Peter Selinger.
4486- This file is part of Potrace. It is free software and it is covered
4487- by the GNU General Public License. See the file COPYING for details. */
4488-
4489-
4490-#ifndef TRACE_H
4491-#define TRACE_H
4492-
4493-#include "potracelib.h"
4494-#include "progress.h"
4495-#include "curve.h"
4496-
4497-int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress);
4498-
4499-#endif /* TRACE_H */
4500
4501=== modified file 'src/ui/CMakeLists.txt'
4502--- src/ui/CMakeLists.txt 2015-06-08 19:01:23 +0000
4503+++ src/ui/CMakeLists.txt 2015-11-21 12:39:21 +0000
4504@@ -34,7 +34,6 @@
4505 tools/dropper-tool.cpp
4506 tools/dynamic-base.cpp
4507 tools/eraser-tool.cpp
4508- tools/flood-tool.cpp
4509 tools/freehand-base.cpp
4510 tools/gradient-tool.cpp
4511 tools/lpe-tool.cpp
4512@@ -107,7 +106,6 @@
4513 dialog/template-widget.cpp
4514 dialog/text-edit.cpp
4515 dialog/tile.cpp
4516- dialog/tracedialog.cpp
4517 dialog/transformation.cpp
4518 dialog/undo-history.cpp
4519 dialog/xml-tree.cpp
4520@@ -248,7 +246,6 @@
4521 dialog/template-widget.h
4522 dialog/text-edit.h
4523 dialog/tile.h
4524- dialog/tracedialog.h
4525 dialog/transformation.h
4526 dialog/undo-history.h
4527 dialog/xml-tree.h
4528@@ -276,7 +273,6 @@
4529 tools/dropper-tool.h
4530 tools/dynamic-base.h
4531 tools/eraser-tool.h
4532- tools/flood-tool.h
4533 tools/freehand-base.h
4534 tools/gradient-tool.h
4535 tools/lpe-tool.h
4536@@ -364,3 +360,14 @@
4537
4538 # add_inkscape_lib(ui_LIB "${ui_SRC}")
4539 add_inkscape_source("${ui_SRC}")
4540+
4541+set ( ui_flood_and_trace_SRC
4542+ tools/flood-tool.h
4543+ tools/flood-tool.cpp
4544+ dialog/tracedialog.cpp
4545+ dialog/tracedialog.h
4546+)
4547+
4548+if ("${HAVE_POTRACE}")
4549+ add_inkscape_source("${ui_flood_and_trace_SRC}")
4550+endif()
4551
4552=== modified file 'src/ui/dialog/Makefile_insert'
4553--- src/ui/dialog/Makefile_insert 2014-11-09 05:13:46 +0000
4554+++ src/ui/dialog/Makefile_insert 2015-11-21 12:39:21 +0000
4555@@ -106,8 +106,6 @@
4556 ui/dialog/text-edit.h \
4557 ui/dialog/tile.cpp \
4558 ui/dialog/tile.h \
4559- ui/dialog/tracedialog.cpp \
4560- ui/dialog/tracedialog.h \
4561 ui/dialog/pixelartdialog.cpp \
4562 ui/dialog/pixelartdialog.h \
4563 ui/dialog/transformation.cpp \
4564@@ -123,3 +121,11 @@
4565 ui/dialog/lpe-fillet-chamfer-properties.cpp \
4566 ui/dialog/lpe-fillet-chamfer-properties.h \
4567 $(inkboard_dialogs)
4568+
4569+if HAVE_POTRACE
4570+
4571+ink_common_sources += \
4572+ ui/dialog/tracedialog.cpp \
4573+ ui/dialog/tracedialog.h
4574+
4575+endif
4576
4577=== modified file 'src/ui/dialog/dialog-manager.cpp'
4578--- src/ui/dialog/dialog-manager.cpp 2014-10-08 02:22:03 +0000
4579+++ src/ui/dialog/dialog-manager.cpp 2015-11-21 12:39:21 +0000
4580@@ -34,7 +34,11 @@
4581 #include "ui/dialog/messages.h"
4582 #include "ui/dialog/symbols.h"
4583 #include "ui/dialog/tile.h"
4584-#include "ui/dialog/tracedialog.h"
4585+
4586+#if HAVE_POTRACE
4587+# include "ui/dialog/tracedialog.h"
4588+#endif
4589+
4590 #include "ui/dialog/pixelartdialog.h"
4591 #include "ui/dialog/transformation.h"
4592 #include "ui/dialog/undo-history.h"
4593@@ -124,7 +128,11 @@
4594 registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>);
4595 registerFactory("TileDialog", &create<ArrangeDialog, FloatingBehavior>);
4596 registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>);
4597+
4598+#if HAVE_POTRACE
4599 registerFactory("Trace", &create<TraceDialog, FloatingBehavior>);
4600+#endif
4601+
4602 registerFactory("PixelArt", &create<PixelArtDialog, FloatingBehavior>);
4603 registerFactory("Transformation", &create<Transformation, FloatingBehavior>);
4604 registerFactory("UndoHistory", &create<UndoHistory, FloatingBehavior>);
4605@@ -159,7 +167,11 @@
4606 registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>);
4607 registerFactory("TileDialog", &create<ArrangeDialog, DockBehavior>);
4608 registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>);
4609+
4610+#if HAVE_POTRACE
4611 registerFactory("Trace", &create<TraceDialog, DockBehavior>);
4612+#endif
4613+
4614 registerFactory("PixelArt", &create<PixelArtDialog, DockBehavior>);
4615 registerFactory("Transformation", &create<Transformation, DockBehavior>);
4616 registerFactory("UndoHistory", &create<UndoHistory, DockBehavior>);
4617
4618=== modified file 'src/ui/dialog/inkscape-preferences.cpp'
4619--- src/ui/dialog/inkscape-preferences.cpp 2015-11-01 12:50:42 +0000
4620+++ src/ui/dialog/inkscape-preferences.cpp 2015-11-21 12:39:21 +0000
4621@@ -478,10 +478,12 @@
4622 this->AddPage(_page_eraser, _("Eraser"), iter_tools, PREFS_PAGE_TOOLS_ERASER);
4623 this->AddNewObjectsStyle(_page_eraser, "/tools/eraser");
4624
4625+#if HAVE_POTRACE
4626 //Paint Bucket
4627 this->AddPage(_page_paintbucket, _("Paint Bucket"), iter_tools, PREFS_PAGE_TOOLS_PAINTBUCKET);
4628 this->AddSelcueCheckbox(_page_paintbucket, "/tools/paintbucket", false);
4629 this->AddNewObjectsStyle(_page_paintbucket, "/tools/paintbucket");
4630+#endif
4631
4632 //Gradient
4633 this->AddPage(_page_gradient, _("Gradient"), iter_tools, PREFS_PAGE_TOOLS_GRADIENT);
4634
4635=== modified file 'src/ui/dialog/inkscape-preferences.h'
4636--- src/ui/dialog/inkscape-preferences.h 2015-07-24 19:38:06 +0000
4637+++ src/ui/dialog/inkscape-preferences.h 2015-11-21 12:39:21 +0000
4638@@ -15,6 +15,10 @@
4639 #ifndef INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
4640 #define INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
4641
4642+#if HAVE_CONFIG_H
4643+# include "config.h"
4644+#endif
4645+
4646 #include <iostream>
4647 #include <vector>
4648 #include "ui/widget/preferences-widget.h"
4649@@ -56,7 +60,11 @@
4650 PREFS_PAGE_TOOLS_TEXT,
4651 PREFS_PAGE_TOOLS_SPRAY,
4652 PREFS_PAGE_TOOLS_ERASER,
4653+
4654+#if HAVE_POTRACE
4655 PREFS_PAGE_TOOLS_PAINTBUCKET,
4656+#endif
4657+
4658 PREFS_PAGE_TOOLS_GRADIENT,
4659 PREFS_PAGE_TOOLS_DROPPER,
4660 PREFS_PAGE_TOOLS_CONNECTOR,
4661
4662=== modified file 'src/ui/tool-factory.cpp'
4663--- src/ui/tool-factory.cpp 2015-02-25 01:04:28 +0000
4664+++ src/ui/tool-factory.cpp 2015-11-21 12:39:21 +0000
4665@@ -16,7 +16,11 @@
4666 #include "ui/tools/connector-tool.h"
4667 #include "ui/tools/dropper-tool.h"
4668 #include "ui/tools/eraser-tool.h"
4669-#include "ui/tools/flood-tool.h"
4670+
4671+#if HAVE_POTRACE
4672+# include "ui/tools/flood-tool.h"
4673+#endif
4674+
4675 #include "ui/tools/gradient-tool.h"
4676 #include "ui/tools/lpe-tool.h"
4677 #include "ui/tools/measure-tool.h"
4678@@ -52,8 +56,10 @@
4679 tool = new DropperTool;
4680 else if (id == "/tools/eraser")
4681 tool = new EraserTool;
4682+#if HAVE_POTRACE
4683 else if (id == "/tools/paintbucket")
4684 tool = new FloodTool;
4685+#endif
4686 else if (id == "/tools/gradient")
4687 tool = new GradientTool;
4688 else if (id == "/tools/lpetool")
4689
4690=== modified file 'src/ui/tools-switch.h'
4691--- src/ui/tools-switch.h 2014-10-05 23:24:27 +0000
4692+++ src/ui/tools-switch.h 2015-11-21 12:39:21 +0000
4693@@ -12,6 +12,10 @@
4694 #ifndef SEEN_TOOLS_SWITCH_H
4695 #define SEEN_TOOLS_SWITCH_H
4696
4697+#if HAVE_CONFIG_H
4698+# include "config.h"
4699+#endif
4700+
4701 class SPDesktop;
4702 class SPItem;
4703 namespace Geom {
4704@@ -40,7 +44,11 @@
4705 TOOLS_MEASURE,
4706 TOOLS_DROPPER,
4707 TOOLS_CONNECTOR,
4708+
4709+#if HAVE_POTRACE
4710 TOOLS_PAINTBUCKET,
4711+#endif
4712+
4713 TOOLS_ERASER,
4714 TOOLS_LPETOOL
4715 };
4716
4717=== modified file 'src/ui/tools/Makefile_insert'
4718--- src/ui/tools/Makefile_insert 2013-11-09 22:36:13 +0000
4719+++ src/ui/tools/Makefile_insert 2015-11-21 12:39:21 +0000
4720@@ -8,7 +8,6 @@
4721 ui/tools/dropper-tool.cpp ui/tools/dropper-tool.h \
4722 ui/tools/dynamic-base.cpp ui/tools/dynamic-base.h \
4723 ui/tools/eraser-tool.cpp ui/tools/eraser-tool.h \
4724- ui/tools/flood-tool.cpp ui/tools/flood-tool.h \
4725 ui/tools/freehand-base.cpp ui/tools/freehand-base.h \
4726 ui/tools/gradient-tool.cpp ui/tools/gradient-tool.h \
4727 ui/tools/lpe-tool.cpp ui/tools/lpe-tool.h \
4728@@ -25,4 +24,11 @@
4729 ui/tools/text-tool.cpp ui/tools/text-tool.h \
4730 ui/tools/tool-base.cpp ui/tools/tool-base.h \
4731 ui/tools/tweak-tool.cpp ui/tools/tweak-tool.h \
4732- ui/tools/zoom-tool.cpp ui/tools/zoom-tool.h
4733\ No newline at end of file
4734+ ui/tools/zoom-tool.cpp ui/tools/zoom-tool.h
4735+
4736+if HAVE_POTRACE
4737+
4738+ink_common_sources += \
4739+ ui/tools/flood-tool.cpp ui/tools/flood-tool.h
4740+
4741+endif
4742
4743=== modified file 'src/verbs.cpp'
4744--- src/verbs.cpp 2015-05-09 12:59:00 +0000
4745+++ src/verbs.cpp 2015-11-21 12:39:21 +0000
4746@@ -832,7 +832,14 @@
4747 verb = verb_found->second;
4748 }
4749
4750- if (verb == NULL)
4751+ if (verb == NULL
4752+#if !HAVE_POTRACE
4753+ // Squash warning about disabled features
4754+ && strcmp(id, "ToolPaintBucket") != 0
4755+ && strcmp(id, "SelectionTrace") != 0
4756+ && strcmp(id, "PaintBucketPrefs") != 0
4757+#endif
4758+ )
4759 printf("Unable to find: %s\n", id);
4760
4761 return verb;
4762@@ -1201,10 +1208,14 @@
4763 case SP_VERB_SELECTION_REVERSE:
4764 SelectionHelper::reverse(dt);
4765 break;
4766+
4767+#if HAVE_POTRACE
4768 case SP_VERB_SELECTION_TRACE:
4769 INKSCAPE.dialogs_unhide();
4770 dt->_dlg_mgr->showDialog("Trace");
4771 break;
4772+#endif
4773+
4774 case SP_VERB_SELECTION_PIXEL_ART:
4775 INKSCAPE.dialogs_unhide();
4776 dt->_dlg_mgr->showDialog("PixelArt");
4777@@ -1606,7 +1617,7 @@
4778 /** \todo !!! hopefully this can go away soon and actions can look after
4779 * themselves
4780 */
4781- for (vidx = SP_VERB_CONTEXT_SELECT; vidx <= SP_VERB_CONTEXT_PAINTBUCKET_PREFS; vidx++)
4782+ for (vidx = SP_VERB_CONTEXT_SELECT; vidx <= SP_VERB_CONTEXT_LPETOOL_PREFS; vidx++)
4783 {
4784 SPAction *tool_action= get((sp_verb_t)vidx)->get_action(action->context);
4785 if (tool_action) {
4786@@ -1673,9 +1684,13 @@
4787 case SP_VERB_CONTEXT_CONNECTOR:
4788 tools_switch(dt, TOOLS_CONNECTOR);
4789 break;
4790+
4791+#if HAVE_POTRACE
4792 case SP_VERB_CONTEXT_PAINTBUCKET:
4793 tools_switch(dt, TOOLS_PAINTBUCKET);
4794 break;
4795+#endif
4796+
4797 case SP_VERB_CONTEXT_ERASER:
4798 tools_switch(dt, TOOLS_ERASER);
4799 break;
4800@@ -1759,10 +1774,14 @@
4801 prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_CONNECTOR);
4802 dt->_dlg_mgr->showDialog("InkscapePreferences");
4803 break;
4804+
4805+#if HAVE_POTRACE
4806 case SP_VERB_CONTEXT_PAINTBUCKET_PREFS:
4807 prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_PAINTBUCKET);
4808 dt->_dlg_mgr->showDialog("InkscapePreferences");
4809 break;
4810+#endif
4811+
4812 case SP_VERB_CONTEXT_ERASER_PREFS:
4813 prefs->setInt("/dialogs/preferences/page", PREFS_PAGE_TOOLS_ERASER);
4814 dt->_dlg_mgr->showDialog("InkscapePreferences");
4815@@ -2160,10 +2179,14 @@
4816 // TRANSLATORS: See "tutorial-basic.svg" comment.
4817 sp_help_open_tutorial(NULL, (gpointer)_("tutorial-advanced.svg"));
4818 break;
4819+
4820+#if HAVE_POTRACE
4821 case SP_VERB_TUTORIAL_TRACING:
4822 // TRANSLATORS: See "tutorial-basic.svg" comment.
4823 sp_help_open_tutorial(NULL, (gpointer)_("tutorial-tracing.svg"));
4824 break;
4825+#endif
4826+
4827 case SP_VERB_TUTORIAL_TRACING_PIXELART:
4828 sp_help_open_tutorial(NULL, (gpointer)_("tutorial-tracing-pixelart.svg"));
4829 break;
4830@@ -2593,9 +2616,13 @@
4831 N_("Simplify selected paths (remove extra nodes)"), INKSCAPE_ICON("path-simplify")),
4832 new SelectionVerb(SP_VERB_SELECTION_REVERSE, "SelectionReverse", N_("_Reverse"),
4833 N_("Reverse the direction of selected paths (useful for flipping markers)"), INKSCAPE_ICON("path-reverse")),
4834+
4835+#if HAVE_POTRACE
4836 // TRANSLATORS: "to trace" means "to convert a bitmap to vector graphics" (to vectorize)
4837 new SelectionVerb(SP_VERB_SELECTION_TRACE, "SelectionTrace", N_("_Trace Bitmap..."),
4838 N_("Create one or more paths from a bitmap by tracing it"), INKSCAPE_ICON("bitmap-trace")),
4839+#endif
4840+
4841 new SelectionVerb(SP_VERB_SELECTION_PIXEL_ART, "SelectionPixelArt", N_("Trace Pixel Art..."),
4842 N_("Create paths using Kopf-Lischinski algorithm to vectorize pixel art"), INKSCAPE_ICON("pixelart-trace")),
4843 new SelectionVerb(SP_VERB_SELECTION_CREATE_BITMAP, "SelectionCreateBitmap", N_("Make a _Bitmap Copy"),
4844@@ -2733,8 +2760,12 @@
4845 N_("Pick colors from image"), INKSCAPE_ICON("color-picker")),
4846 new ContextVerb(SP_VERB_CONTEXT_CONNECTOR, "ToolConnector", NC_("ContextVerb", "Connector"),
4847 N_("Create diagram connectors"), INKSCAPE_ICON("draw-connector")),
4848+
4849+#if HAVE_POTRACE
4850 new ContextVerb(SP_VERB_CONTEXT_PAINTBUCKET, "ToolPaintBucket", NC_("ContextVerb", "Paint Bucket"),
4851 N_("Fill bounded areas"), INKSCAPE_ICON("color-fill")),
4852+#endif
4853+
4854 new ContextVerb(SP_VERB_CONTEXT_LPE, "ToolLPE", NC_("ContextVerb", "LPE Edit"),
4855 N_("Edit Path Effect parameters"), NULL),
4856 new ContextVerb(SP_VERB_CONTEXT_ERASER, "ToolEraser", NC_("ContextVerb", "Eraser"),
4857@@ -2780,8 +2811,12 @@
4858 N_("Open Preferences for the Dropper tool"), NULL),
4859 new ContextVerb(SP_VERB_CONTEXT_CONNECTOR_PREFS, "ConnectorPrefs", N_("Connector Preferences"),
4860 N_("Open Preferences for the Connector tool"), NULL),
4861+
4862+#if HAVE_POTRACE
4863 new ContextVerb(SP_VERB_CONTEXT_PAINTBUCKET_PREFS, "PaintBucketPrefs", N_("Paint Bucket Preferences"),
4864 N_("Open Preferences for the Paint Bucket tool"), NULL),
4865+#endif
4866+
4867 new ContextVerb(SP_VERB_CONTEXT_ERASER_PREFS, "EraserPrefs", N_("Eraser Preferences"),
4868 N_("Open Preferences for the Eraser tool"), NULL),
4869 new ContextVerb(SP_VERB_CONTEXT_LPETOOL_PREFS, "LPEToolPrefs", N_("LPE Tool Preferences"),
4870@@ -2937,9 +2972,13 @@
4871 N_("Using shape tools to create and edit shapes"), NULL),
4872 new TutorialVerb(SP_VERB_TUTORIAL_ADVANCED, "TutorialsAdvanced", N_("Inkscape: _Advanced"),
4873 N_("Advanced Inkscape topics"), NULL/*"tutorial_advanced"*/),
4874+
4875+#if HAVE_POTRACE
4876 // TRANSLATORS: "to trace" means "to convert a bitmap to vector graphics" (to vectorize)
4877 new TutorialVerb(SP_VERB_TUTORIAL_TRACING, "TutorialsTracing", N_("Inkscape: T_racing"),
4878 N_("Using bitmap tracing"), NULL/*"tutorial_tracing"*/),
4879+#endif
4880+
4881 new TutorialVerb(SP_VERB_TUTORIAL_TRACING_PIXELART, "TutorialsTracingPixelArt", N_("Inkscape: Tracing Pixel Art"),
4882 N_("Using Trace Pixel Art dialog"), NULL),
4883 new TutorialVerb(SP_VERB_TUTORIAL_CALLIGRAPHY, "TutorialsCalligraphy", N_("Inkscape: _Calligraphy"),
4884
4885=== modified file 'src/verbs.h'
4886--- src/verbs.h 2014-10-08 02:22:03 +0000
4887+++ src/verbs.h 2015-11-21 12:39:21 +0000
4888@@ -136,7 +136,11 @@
4889 SP_VERB_SELECTION_OUTLINE,
4890 SP_VERB_SELECTION_SIMPLIFY,
4891 SP_VERB_SELECTION_REVERSE,
4892+
4893+#if HAVE_POTRACE
4894 SP_VERB_SELECTION_TRACE,
4895+#endif
4896+
4897 SP_VERB_SELECTION_PIXEL_ART,
4898 SP_VERB_SELECTION_CREATE_BITMAP,
4899 SP_VERB_SELECTION_COMBINE,
4900@@ -203,7 +207,11 @@
4901 SP_VERB_CONTEXT_MEASURE,
4902 SP_VERB_CONTEXT_DROPPER,
4903 SP_VERB_CONTEXT_CONNECTOR,
4904+
4905+#if HAVE_POTRACE
4906 SP_VERB_CONTEXT_PAINTBUCKET,
4907+#endif
4908+
4909 SP_VERB_CONTEXT_LPE, /* not really a tool but used for editing LPE parameters on-canvas for example */
4910 SP_VERB_CONTEXT_ERASER,
4911 SP_VERB_CONTEXT_LPETOOL, /* note that this is very different from SP_VERB_CONTEXT_LPE above! */
4912@@ -227,7 +235,11 @@
4913 SP_VERB_CONTEXT_MEASURE_PREFS,
4914 SP_VERB_CONTEXT_DROPPER_PREFS,
4915 SP_VERB_CONTEXT_CONNECTOR_PREFS,
4916+
4917+#if HAVE_POTRACE
4918 SP_VERB_CONTEXT_PAINTBUCKET_PREFS,
4919+#endif
4920+
4921 SP_VERB_CONTEXT_ERASER_PREFS,
4922 SP_VERB_CONTEXT_LPETOOL_PREFS,
4923 /* Zooming and desktop settings */
4924@@ -311,7 +323,11 @@
4925 SP_VERB_TUTORIAL_BASIC,
4926 SP_VERB_TUTORIAL_SHAPES,
4927 SP_VERB_TUTORIAL_ADVANCED,
4928+
4929+#if HAVE_POTRACE
4930 SP_VERB_TUTORIAL_TRACING,
4931+#endif
4932+
4933 SP_VERB_TUTORIAL_TRACING_PIXELART,
4934 SP_VERB_TUTORIAL_CALLIGRAPHY,
4935 SP_VERB_TUTORIAL_INTERPOLATE,
4936
4937=== modified file 'src/widgets/CMakeLists.txt'
4938--- src/widgets/CMakeLists.txt 2015-04-26 17:51:08 +0000
4939+++ src/widgets/CMakeLists.txt 2015-11-21 12:39:21 +0000
4940@@ -11,7 +11,6 @@
4941 measure-toolbar.cpp
4942 mesh-toolbar.cpp
4943 node-toolbar.cpp
4944- paintbucket-toolbar.cpp
4945 pencil-toolbar.cpp
4946 rect-toolbar.cpp
4947 spiral-toolbar.cpp
4948@@ -67,7 +66,6 @@
4949 measure-toolbar.h
4950 mesh-toolbar.h
4951 node-toolbar.h
4952- paintbucket-toolbar.h
4953 pencil-toolbar.h
4954 rect-toolbar.h
4955 spiral-toolbar.h
4956@@ -114,3 +112,12 @@
4957
4958 # add_inkscape_lib(widgets_LIB "${widgets_SRC}")
4959 add_inkscape_source("${widgets_SRC}")
4960+
4961+set ( widgets_paintbucket_SRC
4962+ paintbucket-toolbar.cpp
4963+ paintbucket-toolbar.h
4964+)
4965+
4966+if ("${HAVE_POTRACE}")
4967+ add_inkscape_source("${widgets_paintbucket_SRC}")
4968+endif()
4969
4970=== modified file 'src/widgets/Makefile_insert'
4971--- src/widgets/Makefile_insert 2015-04-26 17:51:08 +0000
4972+++ src/widgets/Makefile_insert 2015-11-21 12:39:21 +0000
4973@@ -58,8 +58,6 @@
4974 widgets/node-toolbar.h \
4975 widgets/paint-selector.cpp \
4976 widgets/paint-selector.h \
4977- widgets/paintbucket-toolbar.cpp \
4978- widgets/paintbucket-toolbar.h \
4979 widgets/pencil-toolbar.cpp \
4980 widgets/pencil-toolbar.h \
4981 widgets/rect-toolbar.cpp \
4982@@ -109,5 +107,13 @@
4983 widgets/zoom-toolbar.h \
4984 widgets/widget-sizes.h
4985
4986+if HAVE_POTRACE
4987+
4988+ink_common_sources += \
4989+ widgets/paintbucket-toolbar.cpp \
4990+ widgets/paintbucket-toolbar.h
4991+
4992+endif
4993+
4994 widgets/button.$(OBJEXT): helper/sp-marshal.h
4995 widgets/menu.$(OBJEXT): helper/sp-marshal.h
4996
4997=== modified file 'src/widgets/toolbox.cpp'
4998--- src/widgets/toolbox.cpp 2015-11-12 23:48:16 +0000
4999+++ src/widgets/toolbox.cpp 2015-11-21 12:39:21 +0000
5000@@ -79,7 +79,11 @@
The diff has been truncated for viewing.