Merge lp:~valavanisalex/inkscape/fix-1156664 into lp:~inkscape.dev/inkscape/trunk
- fix-1156664
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Inkscape Developers | Pending | ||
Review via email: mp+277406@code.launchpad.net |
Commit message
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?
su_v (suv-lp) wrote : | # |
- 14456. By Alex Valavanis
-
Hide unused verbs if Potrace is not available
Alex Valavanis (valavanisalex) wrote : | # |
(c) Hopefully fixed in r14456: The impossible verbs are disabled if Potrace is not found
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
Alex Valavanis (valavanisalex) wrote : | # |
(b) Added a warning about missing Potrace to the CMake build in r14457
Preview Diff
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, ¶m_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 @@ |
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).