[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
gEDA-cvs: pcb.git: branch: sdb-playpen updated (df0e28d9f58bf5d3278fcddf0459fd93f7f08aa8)
The branch, sdb-playpen has been updated
via df0e28d9f58bf5d3278fcddf0459fd93f7f08aa8 (commit)
via 7e95250675a70d8fec2bc9ed7ffb8ab067f4390b (commit)
via 8e622b2c0aa88e2fe131c45438429d3524dc4da6 (commit)
via 542c19ff457755ce9d26ec1883650c125fcfe576 (commit)
via 480e81559af88dacbfb6bd94cd5fb705ec4f7cb4 (commit)
via e85f5eea45e6db6245dd960916cd544e844e5cab (commit)
via 050e6e6fea127f611ee0db11ef162c2dd27fb3d6 (commit)
via ed9779ba20a26180b1e30a2f37c5ba1a5039c673 (commit)
via 3f65efa13e373fc05e96dab360086271cdcd8759 (commit)
via d9e4279e4c0af142bc776bdd4a3b905388ce6b5a (commit)
via 340d9546656b529c12fe8fecc4be950f5ff9bff8 (commit)
via 6081daa8966c8c83bb734789c38dd5c42dd97443 (commit)
via 2a406dec9df0eecf9923a19971363fa39b481e04 (commit)
via 607c3056963b68654bac3fae70ac3d02eee60eaf (commit)
via 5672c37af126b75f687e693602c393f16aca46c7 (commit)
via 1ee723379413c20973bdad27b1e1cf1d722cf3d1 (commit)
via 9ef73a58992bcc5c2eb3a550bc9910bc20bd1778 (commit)
via e45f4e8d15f2c30f8ccb37de5b0bfa801fca572c (commit)
via b89fa5b38ebf2c7d59a2bdd3385878fffe117f26 (commit)
via 86055f4273cae0c00d55b30f4bd610052ca350a4 (commit)
via ee8c65db8257eee155071ec7beab6dabb1a77c86 (commit)
via 2185dc1f86f7ffc830d950ca821080bc7238e7d6 (commit)
via 46dab7d5d39aa9f45c59b50862c41c39e51d6f8c (commit)
via 886348e148fdd2951983910c1f39b260831605c3 (commit)
via d0062d735ba2194a64cc78726c9867e3ffa39460 (commit)
via 8e8fbf053f12bbd741d4842258e7f7f62f6e1799 (commit)
via da4b3b720d55aa5cfe9868f56d54cde7d5a02e5f (commit)
via b1a35c9c9afc64ebfcf2208bc13968a641da4b1a (commit)
via 28f6cd1f67b6c3a7a9639ceea67b29474d5a649b (commit)
via 880affd3b2680782e923c421136b4286c1e94c74 (commit)
via 8d881c4fcaa2faddb2b4e47a8f6309c80d147632 (commit)
via 2d7de84dd42cb9e2eccd8f41f878b4cacad3c895 (commit)
via 7c0af9f92a78cafc9d81ca77937b26f18f0b5531 (commit)
via 7ef3aa04772b11db6afd14c626a6c49882c5850b (commit)
via a86548a6c26429e0b420602f98152d881f84cc2a (commit)
via 128ac62fe7270950eafb1c59c408bae974972e8d (commit)
via b75d1fe8d42c138ae499898db5b926948b73f767 (commit)
via 5a22f98ca0d0c064d4d40af7785c81d434ce92ec (commit)
via 897640d7b920b4d593d2b0a6644a061698610b69 (commit)
via af5b9b3a96e9f42089ecfbe878807b68044dbdfd (commit)
via 3352f8b5a2cf99d55f360d9c319e32a3ca092553 (commit)
via 832f7928fd3828c4d0588fc73fd9db8858e3d968 (commit)
via be80f0c5771c91dc2795f5832af8fb2013cb3992 (commit)
via 1d674bcfe2388533001b7789d348ac5fcfa1b788 (commit)
via b402a144e19225f0648189bca6fbfad95d046047 (commit)
via 175810a3743aba5d1f34b8630e2b5edb472c1841 (commit)
via f3e5290c8a883a103a3931767bdc47d9f5181997 (commit)
via 1590f4c65c15e6a3ba27079866ea8d14252ce7bf (commit)
via e2e741ab7589bd3e6c925fc9b2a81c7c2121f820 (commit)
via e1d647498921eaca00b2f6930fe1ae9af0c1aab1 (commit)
via e053d592a107887438071ef111ee3f811e2a5490 (commit)
via 920d274f40b327f3c83f7c6bf360b66f07966a7e (commit)
via 13cada5ddfeb813da99ddf3788a27274958bbfd4 (commit)
via 91ba9f3a8b5a71914d928aad1e545a154c3678f5 (commit)
via 802576013b5d780cd87caafa31c694279ee2dc4f (commit)
via 6d03d0539e0afd51383f11fd6b06ec7ced0fbf12 (commit)
via a096a8b84c1d0e2beb94a859bde9f2bc2799fe73 (commit)
via beb4c7c5626b8b28c0a203a23fb41f28e5662618 (commit)
via fd1c65c236bdcd4b36400e82074d66ab83bc5de3 (commit)
via b6378a3845066adb23601d8fa781fd58233176dd (commit)
via c544e63eca400b33127ac539e4737c7959e8db2c (commit)
via 9babb216b2921ad716b740068988d04a0d9dfe45 (commit)
via 0e008cb83dcfc4fc6a3455bdd3c8dd86ed65b374 (commit)
via 290c968566837132afbfc63d5fe1436c03dcec1e (commit)
via 073463e605095692e2cf8d4238df0c817e68e3c3 (commit)
via ca738957694927538dad15f037d5622571fd3173 (commit)
via 7467c8b2cedb80ee32e2ff19662d6894a6d7f345 (commit)
via 19f7443c3249a9cc40efd04c1895b89445add385 (commit)
via 47edc12beab88ea5a6d7608e5741131eb5c0e8d4 (commit)
via e402b491c199d1df9808e129461d585346a03c9e (commit)
via b4ca96d312884a8bc2314e490c2c957ab590b427 (commit)
via 5c7cc398ffc8f646d68eada8d6cd74dff4bceb85 (commit)
via ca1af54230754bde0cda442a6d966a4aa1a3e6b4 (commit)
via 2eb25f8f7cc9584528b2caa54a6097fc17fcec8b (commit)
via d2a7382d1fcecd85a1feee399543a3e89fe1ef6b (commit)
from 0f395de81e170934f965efe1483e24aeb2010b4d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
=========
Summary
=========
INSTALL | 8 +-
README | 5 +-
README.snapshots | 2 +
configure.ac | 49 +-
data/pcb.desktop.in | 1 -
doc/pcb.1 | 5 +-
doc/pcb.texi | 5 +-
lib/Makefile.am | 5 +
src/Makefile.am | 38 +-
src/action.c | 5 +-
src/change.c | 2 +-
src/copy.c | 11 +
src/create.c | 4 +
src/djopt.c | 30 +
src/draw.c | 16 +-
src/global.h | 2 -
src/gpcb-menu.res | 27 -
src/hid.h | 36 +-
src/hid/batch/batch.c | 8 +-
src/hid/bom/bom.c | 1 -
src/hid/common/actions.c | 224 +---
src/hid/common/extents.c | 2 -
src/hid/common/hidinit.c | 18 +-
src/hid/common/hidnogui.c | 10 +-
src/hid/gcode/auxiliary.h | 87 ++
src/hid/gcode/bitmap.h | 116 ++
src/hid/gcode/curve.c | 123 ++
src/hid/gcode/curve.h | 79 +
src/hid/gcode/decompose.c | 599 ++++++++
src/hid/gcode/decompose.h | 16 +
src/hid/gcode/gcode.c | 1099 +++++++++++++++
src/hid/gcode/gcode.h | 3 +
src/hid/{bom => gcode}/hid.conf | 0
src/hid/gcode/lists.h | 285 ++++
src/hid/gcode/potracelib.h | 138 ++
src/hid/gcode/trace.c | 1485 ++++++++++++++++++++
src/hid/gcode/trace.h | 15 +
src/hid/gerber/gerber.c | 1 -
src/hid/gtk/gtkhid-main.c | 11 +-
src/hid/gtk/gui-config.c | 3 +-
src/hid/gtk/gui-dialog-print.c | 30 +-
src/hid/gtk/gui-top-window.c | 10 +-
src/hid/hidint.h | 2 +-
src/hid/lesstif/main.c | 14 +-
src/hid/lesstif/menu.c | 15 +-
src/hid/lpr/lpr.c | 1 -
src/hid/nelma/nelma.c | 1 -
src/hid/png/png.c | 12 +-
src/hid/ps/eps.c | 1 -
src/hid/ps/ps.c | 224 +++-
src/main.c | 99 +-
src/misc.c | 11 +-
src/parse_y.y | 2 +-
src/report.c | 3 +-
src/toporouter.c | 397 +++++-
src/toporouter.h | 2 +
tests/README.txt | 56 +-
tests/golden/Makefile.am | 16 +-
tests/golden/hid_gcode1/Makefile.am | 6 +
.../golden/hid_gcode1/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode1/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode1/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode10/Makefile.am | 6 +
.../hid_gcode10/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode10/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode10/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode11/Makefile.am | 6 +
.../hid_gcode11/gcode_oneline.gcode.back.cnc | 49 +
.../hid_gcode11/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode11/gcode_oneline.gcode.front.cnc | 45 +
tests/golden/hid_gcode2/Makefile.am | 6 +
tests/golden/hid_gcode2/out.back.cnc | 34 +
tests/golden/hid_gcode2/out.drill.cnc | 12 +
tests/golden/hid_gcode2/out.front.cnc | 34 +
tests/golden/hid_gcode3/Makefile.am | 6 +
.../golden/hid_gcode3/gcode_oneline.gcode.back.cnc | 40 +
.../hid_gcode3/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode3/gcode_oneline.gcode.front.cnc | 40 +
tests/golden/hid_gcode4/Makefile.am | 6 +
.../golden/hid_gcode4/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode4/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode4/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode5/Makefile.am | 6 +
.../golden/hid_gcode5/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode5/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode5/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode6/Makefile.am | 6 +
.../golden/hid_gcode6/gcode_oneline.gcode.back.cnc | 43 +
.../hid_gcode6/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode6/gcode_oneline.gcode.front.cnc | 43 +
tests/golden/hid_gcode7/Makefile.am | 6 +
.../golden/hid_gcode7/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode7/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode7/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode8/Makefile.am | 6 +
.../golden/hid_gcode8/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode8/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode8/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/hid_gcode9/Makefile.am | 6 +
.../golden/hid_gcode9/gcode_oneline.gcode.back.cnc | 34 +
.../hid_gcode9/gcode_oneline.gcode.drill.cnc | 12 +
.../hid_gcode9/gcode_oneline.gcode.front.cnc | 34 +
tests/golden/{hid_png1 => hid_png2}/Makefile.am | 2 +-
.../gerber_oneline.png => hid_png2/myfile.png} | Bin 218 -> 218 bytes
tests/golden/{hid_png1 => hid_png3}/Makefile.am | 0
tests/golden/hid_png3/gerber_oneline.png | Bin 0 -> 844 bytes
tests/inputs/Makefile.am | 1 +
.../{gerber_oneline.pcb => gcode_oneline.pcb} | 0
tests/run_tests.sh | 69 +-
tests/tests.list | 39 +-
tools/Makefile.am | 6 +-
win32/Readme.txt | 3 +-
112 files changed, 6079 insertions(+), 513 deletions(-)
create mode 100644 src/hid/gcode/auxiliary.h
create mode 100644 src/hid/gcode/bitmap.h
create mode 100644 src/hid/gcode/curve.c
create mode 100644 src/hid/gcode/curve.h
create mode 100644 src/hid/gcode/decompose.c
create mode 100644 src/hid/gcode/decompose.h
create mode 100644 src/hid/gcode/gcode.c
create mode 100644 src/hid/gcode/gcode.h
copy src/hid/{bom => gcode}/hid.conf (100%)
create mode 100644 src/hid/gcode/lists.h
create mode 100644 src/hid/gcode/potracelib.h
create mode 100644 src/hid/gcode/trace.c
create mode 100644 src/hid/gcode/trace.h
create mode 100644 tests/golden/hid_gcode1/Makefile.am
create mode 100644 tests/golden/hid_gcode1/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode1/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode1/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode10/Makefile.am
create mode 100644 tests/golden/hid_gcode10/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode10/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode10/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode11/Makefile.am
create mode 100644 tests/golden/hid_gcode11/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode11/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode11/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode2/Makefile.am
create mode 100644 tests/golden/hid_gcode2/out.back.cnc
create mode 100644 tests/golden/hid_gcode2/out.drill.cnc
create mode 100644 tests/golden/hid_gcode2/out.front.cnc
create mode 100644 tests/golden/hid_gcode3/Makefile.am
create mode 100644 tests/golden/hid_gcode3/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode3/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode3/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode4/Makefile.am
create mode 100644 tests/golden/hid_gcode4/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode4/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode4/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode5/Makefile.am
create mode 100644 tests/golden/hid_gcode5/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode5/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode5/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode6/Makefile.am
create mode 100644 tests/golden/hid_gcode6/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode6/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode6/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode7/Makefile.am
create mode 100644 tests/golden/hid_gcode7/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode7/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode7/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode8/Makefile.am
create mode 100644 tests/golden/hid_gcode8/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode8/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode8/gcode_oneline.gcode.front.cnc
create mode 100644 tests/golden/hid_gcode9/Makefile.am
create mode 100644 tests/golden/hid_gcode9/gcode_oneline.gcode.back.cnc
create mode 100644 tests/golden/hid_gcode9/gcode_oneline.gcode.drill.cnc
create mode 100644 tests/golden/hid_gcode9/gcode_oneline.gcode.front.cnc
copy tests/golden/{hid_png1 => hid_png2}/Makefile.am (64%)
copy tests/golden/{hid_png1/gerber_oneline.png => hid_png2/myfile.png} (100%)
copy tests/golden/{hid_png1 => hid_png3}/Makefile.am (100%)
create mode 100644 tests/golden/hid_png3/gerber_oneline.png
copy tests/inputs/{gerber_oneline.pcb => gcode_oneline.pcb} (100%)
=================
Commit Messages
=================
commit 7e95250675a70d8fec2bc9ed7ffb8ab067f4390b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Remove conflicting declaration of ParseLibraryTree.
This is a static function declared in file.c. Therefore I
took it out of file.h.
:100644 100644 2822525... 64eba23... M src/file.h
commit 8e622b2c0aa88e2fe131c45438429d3524dc4da6
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Place components in middle of board instead of at 0,0.
:100644 100644 94bf07e... c15c7c0... M src/action.c
commit 542c19ff457755ce9d26ec1883650c125fcfe576
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Support for footprints not in subdirectories
Added tons of debug spew to various files to aid in program tracing
Also, modify library loading stuff in file.c to allow footprints to live
directly in library directory (rather than only one level down).
:100644 100644 d7c754b... 94bf07e... M src/action.c
:100644 100644 7daecf5... fbd1735... M src/buffer.c
:100644 100644 db13d5e... 8cbd384... M src/change.c
:100644 100644 5a030c9... 583feb8... M src/copy.c
:100644 100644 518a35b... eced68d... M src/create.c
:100644 100644 fd18340... 639c971... M src/file.c
:100644 100644 64eba23... 2822525... M src/file.h
:100644 100644 80bea72... 1082dd1... M src/global.h
:100644 100644 e5d93eb... 3026f8d... M src/main.c
commit 480e81559af88dacbfb6bd94cd5fb705ec4f7cb4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
When built with less than all of the graphic formats that
the png exporter supports, don't segfault anymore. The problem
is an array is defined differently at compile time but the
default value for the format was constant and a ways into the
array. Problem reported by jean on irc.
:100644 100644 404eb53... ba7e763... M src/hid/png/png.c
commit e85f5eea45e6db6245dd960916cd544e844e5cab
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Inform the user where (what file or compiled in defaults) the
menu config came from. Should help with some of the gpcb-menu.res
versus pcb-menu.res and the ./gpcb-menu.res versus ~/.pcb/gpcb-menu.res
confusion which comes up from time to time.
:100644 100644 eb8ba18... a594330... M src/hid/gtk/gui-top-window.c
commit 050e6e6fea127f611ee0db11ef162c2dd27fb3d6
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Return non-fail for ReportAllNetLengths()
:100644 100644 08613dd... 2e80e66... M src/report.c
commit ed9779ba20a26180b1e30a2f37c5ba1a5039c673
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Record the calculated length in Report(NetLength)
:100644 100644 974c0be... 08613dd... M src/report.c
commit d9e4279e4c0af142bc776bdd4a3b905388ce6b5a
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add checklist item to update the web site for a new release news
item.
:100644 100644 9a4582e... ca516e8... M README.snapshots
commit 6081daa8966c8c83bb734789c38dd5c42dd97443
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: line constraints
:100644 100644 f749d22... 50195d3... M src/toporouter.c
commit 2a406dec9df0eecf9923a19971363fa39b481e04
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Fix Typo
:100644 100644 9869483... 44edaba... M src/hid/lesstif/menu.c
commit 607c3056963b68654bac3fae70ac3d02eee60eaf
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: Speccut bug fix
:100644 100644 7a40005... f749d22... M src/toporouter.c
commit 1ee723379413c20973bdad27b1e1cf1d722cf3d1
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: line constraints
:100644 100644 a02f628... 83eb65e... M src/toporouter.c
:100644 100644 37c9ac7... 0e98115... M src/toporouter.h
commit e45f4e8d15f2c30f8ccb37de5b0bfa801fca572c
Author: Anthony M. Blake <anthonix@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Commit: Anthony M. Blake <anthonix@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Toporouter: fixed a few AMD64 warnings
:100644 100644 a02f628... ff6d804... M src/toporouter.c
commit b89fa5b38ebf2c7d59a2bdd3385878fffe117f26
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Missed the copyright bump when adding the gcode compare routines a
few weeks back.
:100755 100755 44bdcc7... e9a4ac2... M tests/run_tests.sh
commit 86055f4273cae0c00d55b30f4bd610052ca350a4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add tests for --outfile and --dpi arguments to the PNG exporter
:100644 100644 f0e19bd... 4e9476d... M configure.ac
:100644 100644 de5bb08... 515419e... M tests/golden/Makefile.am
:000000 100644 0000000... f0387c4... A tests/golden/hid_png2/Makefile.am
:000000 100644 0000000... be346ad... A tests/golden/hid_png2/myfile.png
:000000 100644 0000000... 8ef143b... A tests/golden/hid_png3/Makefile.am
:000000 100644 0000000... 3b30ed3... A tests/golden/hid_png3/gerber_oneline.png
:100644 100644 95af71d... ac1a11a... M tests/tests.list
commit ee8c65db8257eee155071ec7beab6dabb1a77c86
Author: Kai-Martin Knaak <kmk@xxxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
replaces "pcb.sourceforge.net" with "pcb.gpleda.org"
:100644 100644 be006fd... 9b9da9a... M README
:100644 100644 526ad9a... 2f4c374... M doc/pcb.texi
:100644 100644 2fe588c... e5d93eb... M src/main.c
:100644 100644 7d73a68... 93273a4... M win32/Readme.txt
commit 2185dc1f86f7ffc830d950ca821080bc7238e7d6
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Add function to register single action.
The possibility to register a single action has been introduced with
commit 337fa8ba8094cee1ed291cec7bf29895ac7c9d72 but then reverted later
when changing way of passing context to action callback.
:100644 100644 823e4e3... 7b30022... M src/hid.h
:100644 100644 7bc336a... a2ad612... M src/hid/common/actions.c
commit 46dab7d5d39aa9f45c59b50862c41c39e51d6f8c
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Modify HID actions storage.
It removes the HID_ActionNode structure and directly store registered
actions in an array of HID_Action*.
It also provides a nicer way of making sure the array is sorted and
the code for binary search within the array has been removed in favor of
a call to bsearch().
:100644 100644 04270f1... 7bc336a... M src/hid/common/actions.c
commit 886348e148fdd2951983910c1f39b260831605c3
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Set 'exporter' global variable before
printing defaults.
In print_defaults(), when the HID to print defaults is not a gui, set
'exporter' global variable prior to calling HID's get_export_options()
callback.
:100644 100644 3c5ecae... 2fe588c... M src/main.c
commit d0062d735ba2194a64cc78726c9867e3ffa39460
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Rewrite function that print HID options.
The previous version of usage_hid() had a strange search for gui HID
attributes through 'hid_attr_node' rather than requesting them directly
from the HID.
As a result it was calling the get_export_options() callback on exporter
without prior setting of the exporter global variable.
:100644 100644 99dcba1... 3c5ecae... M src/main.c
commit 8e8fbf053f12bbd741d4842258e7f7f62f6e1799
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: gtkhid: Avoid use of 'exporter' when testing
for exporter availability.
:100644 100644 1d4fbda... 0c50aed... M src/hid/gtk/gui-dialog-print.c
commit da4b3b720d55aa5cfe9868f56d54cde7d5a02e5f
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: gtkhid: Set and unset global variable
'exporter' when printing.
The GTK hid was not setting the global variable 'exporter' before
exporting the layout in ghid_dialog_print(): exporter HID relying on
this variable being set were lost.
:100644 100644 c5c2fff... 1d4fbda... M src/hid/gtk/gui-dialog-print.c
commit b1a35c9c9afc64ebfcf2208bc13968a641da4b1a
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Provide context to callbacks of actions
through global variable.
Providing a context to action is necessary for scripting languages (for
example). To do so, a global variable ('current_action') is being
defined: it is saved, set and restored when running the callback of an
action in a way similar to what PCB already does with HIDs.
The callback function may access the action it belongs to and cast it
the way it wants to extract information from a potentially extended
HID_Action structure.
:100644 100644 067beb0... 823e4e3... M src/hid.h
:100644 100644 123a2f4... 04270f1... M src/hid/common/actions.c
:100644 100644 f391778... 9869483... M src/hid/lesstif/menu.c
commit 28f6cd1f67b6c3a7a9639ceea67b29474d5a649b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Sort actions by references in 'all_actions'.
Previously, when building 'all_actions', a copy of every HID_Action
was performed for each action. Now it builds 'all_actions' with pointers
to the actual HID_Action structures (without reallocating).
:100644 100644 e172d51... 123a2f4... M src/hid/common/actions.c
commit 880affd3b2680782e923c421136b4286c1e94c74
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Revert "single-action register/deregister".
This reverts commits 337fa8ba8094cee1ed291cec7bf29895ac7c9d72 and
b274cf8fe9c8caf5bcd4edc28935c88cf5bab7f4 before the introduction of a
new context passing scheme for actions.
:100644 100644 9b26ef8... 067beb0... M src/hid.h
:100644 100644 8678ad9... e172d51... M src/hid/common/actions.c
:100644 100644 5840e20... a2148a0... M src/hid/hidint.h
:100644 100644 d3e421d... f391778... M src/hid/lesstif/menu.c
commit 8d881c4fcaa2faddb2b4e47a8f6309c80d147632
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Fix comment for global variable 'gui' in
hid.h.
hid_start_gui() does not exist. The variable is instead set in main()
and hid_expose_callback().
:100644 100644 7409bbf... 9b26ef8... M src/hid.h
commit 2d7de84dd42cb9e2eccd8f41f878b4cacad3c895
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Modify DrawSpecialPolygon() prototype to not
take a pointer on HID.
DrawSpecialPolygon() was the only function to take a HID as parameter.
Every other draw function works on the current HID through global
variable 'gui'.
:100644 100644 9571b29... d06813d... M src/draw.c
commit 7c0af9f92a78cafc9d81ca77937b26f18f0b5531
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Support HID_Mixed options in attribute dialog
Since an HID_Mixed attribute is the combination of a real and an enum,
reuse the code for HID_Enum to provide a combo box next to the spin button
for the real part.
:100644 100644 922b719... c5c2fff... M src/hid/gtk/gui-dialog-print.c
commit 7ef3aa04772b11db6afd14c626a6c49882c5850b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud.
Modified code to not abort on HID_Mixed attributes. Th gtk HID is
modified to understand such an attribute (though the attribute dialog
has still no support for them), the lesstif HID is unchanged.
:100644 100644 9581d32... bb1a66b... M src/hid/common/hidinit.c
:100644 100644 490befc... c9bf82b... M src/hid/gtk/gui-config.c
:100644 100644 5f68465... 99dcba1... M src/main.c
commit a86548a6c26429e0b420602f98152d881f84cc2a
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Applying patch from Patrick Bernaud.
HIDs with a name too long were breaking alignement in usage() as the
code requested insertion of a tab after the name even for HID names
already exceeding the length of the tabulation.
This is similar to how usage_attr() already does alignment of
name and help text.
:100644 100644 162a0e0... 5f68465... M src/main.c
commit b75d1fe8d42c138ae499898db5b926948b73f767
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove an out of date comment about mouse resources not being
understood. Also remove an old and unused popup section that
had been used for testing.
:100644 100644 11251b2... 17a0fbf... M src/gpcb-menu.res
commit 5a22f98ca0d0c064d4d40af7785c81d434ce92ec
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove invalidate_wh from the new gcode HID too.
:100644 100644 bbc1d53... c3c2e4e... M src/hid/gcode/gcode.c
commit 897640d7b920b4d593d2b0a6644a061698610b69
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove Settings.init_done variable and its usage
This variable was previously used to allow action scripts run prior to
loading the GUI to avoid GUI startup if they executed a "Quit" action.
The requirement dates back prior to the HID split, where the "Quit"
action would cause PCB to call gtk_main_quit(), an operation which is
illegal if the GUI main loop was not yet started. The init_done flag
was used in QuitApplication(), both to determine whether the GUI had
started, and if not - to note that the GUI should not be initialised
later. (Instead of calling gtk_main_quit()).
With the HID split, the QuitApplication() function was changed to call
exit(0) rather than gtk_main_quit(), so this dance isn't necessary at
all now.. in either case, we can just exit the application immediately.
:100644 100644 19f4454... 80bea72... M src/global.h
:100644 100644 bb79991... 162a0e0... M src/main.c
:100644 100644 b675090... cca9e1b... M src/misc.c
commit af5b9b3a96e9f42089ecfbe878807b68044dbdfd
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused HistorySize field from the settings structure
:100644 100644 3794448... 19f4454... M src/global.h
commit 3352f8b5a2cf99d55f360d9c319e32a3ca092553
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused "last" parameter from HID "invalidate_lr" method
:100644 100644 b843da6... 9571b29... M src/draw.c
:100644 100644 0e0c479... 7409bbf... M src/hid.h
:100644 100644 1baa2d8... f26321d... M src/hid/batch/batch.c
:100644 100644 3e5e9db... d5dc9e1... M src/hid/common/hidnogui.c
:100644 100644 330e716... b8fdc75... M src/hid/gtk/gtkhid-main.c
:100644 100644 2fec418... 51c52fe... M src/hid/lesstif/main.c
commit 832f7928fd3828c4d0588fc73fd9db8858e3d968
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused HID method invalidate_wh()
invalidate_lr and invalidate_all are sufficient APIs for our needs.
:100644 100644 3c23338... 0e0c479... M src/hid.h
:100644 100644 c10b280... 1baa2d8... M src/hid/batch/batch.c
:100644 100644 e593bdd... 04ad123... M src/hid/bom/bom.c
:100644 100644 bf53c14... a0dbf6b... M src/hid/common/extents.c
:100644 100644 51c95cb... 3e5e9db... M src/hid/common/hidnogui.c
:100644 100644 afa6a08... dee7d06... M src/hid/gerber/gerber.c
:100644 100644 81f0d77... 330e716... M src/hid/gtk/gtkhid-main.c
:100644 100644 84e095a... 2fec418... M src/hid/lesstif/main.c
:100644 100644 e47c40f... aa696be... M src/hid/lpr/lpr.c
:100644 100644 dc1cee5... 8e5ff0c... M src/hid/nelma/nelma.c
:100644 100644 2e8e40c... 404eb53... M src/hid/png/png.c
:100644 100644 b0e7a7d... 0c9345b... M src/hid/ps/eps.c
:100644 100644 f21ce84... 810ceba... M src/hid/ps/ps.c
commit be80f0c5771c91dc2795f5832af8fb2013cb3992
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Revert "As silly as it seems to group any sort of scientific or EDA"
I've pushed really hard to sort this nonsense out, and this patch is
not in my opinion suitable for applcation. gEDA, gerbv and PCB all
deliberately omit the Education category.. this is not where we need
to fix this issue.
I strongly object to putting bogus categories into our apps.
If Debian want to patch these in, let them.
This reverts commit b402a144e19225f0648189bca6fbfad95d046047.
:100644 100644 bc61016... 61091b4... M data/pcb.desktop.in
commit 1d674bcfe2388533001b7789d348ac5fcfa1b788
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix an obvious bug in the previous commit. Caught by harry.
:100644 100644 d680903... f21ce84... M src/hid/ps/ps.c
commit b402a144e19225f0648189bca6fbfad95d046047
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
As silly as it seems to group any sort of scientific or EDA
software under "Education", this appears to be the standard
documented by http://standards.freedesktop.org/menu-spec/1.0/apa.html
Noted in patch #2889228 by Ahmed El-Mahmoudy.
:100644 100644 61091b4... bc61016... M data/pcb.desktop.in
commit 175810a3743aba5d1f34b8630e2b5edb472c1841
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
"Encoding" is deprecated. http://standards.freedesktop.org/desktop-entry-spec/1.0/apc.html
Noted in patch #2889228
:100644 100644 967ba82... 61091b4... M data/pcb.desktop.in
commit f3e5290c8a883a103a3931767bdc47d9f5181997
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
It is gcode/hid.conf not gcode/gcode.conf that needs to be distributed.
Also put this file in the correct sorted location.
:100644 100644 561a6f4... e719268... M src/Makefile.am
commit 1590f4c65c15e6a3ba27079866ea8d14252ce7bf
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add missing AC_PROG_MKDIR_P check.
:100644 100644 43ebfaf... f0e19bd... M configure.ac
commit e2e741ab7589bd3e6c925fc9b2a81c7c2121f820
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix building outside of the source tree with dependency tracking
disabled. In that case some directories need to be manually
created. Fixes bug #2889226.
:100644 100644 a5441d6... 561a6f4... M src/Makefile.am
commit e1d647498921eaca00b2f6930fe1ae9af0c1aab1
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
In the rectangle fill code fix a bug in swapping of the coordinates.
It doesn't appear that this code path is encountered much.
:100644 100644 98f3eb4... d680903... M src/hid/ps/ps.c
commit e053d592a107887438071ef111ee3f811e2a5490
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add DSC to the postscript outputs to keep certain windows based
postscript viewers a little happier. Patch supplied in patch #2700352
by Bob Paddock.
:100644 100644 3a92dc3... 98f3eb4... M src/hid/ps/ps.c
commit 920d274f40b327f3c83f7c6bf360b66f07966a7e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
The gcode exporter used libgd so make sure we check for it and
document that we need it. Noted by Patrick Bernaud in bug #2967313
:100644 100644 db27639... c4df37d... M INSTALL
:100644 100644 3f8ed62... 43ebfaf... M configure.ac
commit 13cada5ddfeb813da99ddf3788a27274958bbfd4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Make sure the simple gcode test layout makes it into the distfile.
:100644 100644 b7dbb1e... ee76973... M tests/inputs/Makefile.am
commit 802576013b5d780cd87caafa31c694279ee2dc4f
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Update the documentation to more closely match reality.
:100644 100644 dd7750f... 8f2a5fb... M tests/README.txt
:100755 100755 5320c54... 44bdcc7... M tests/run_tests.sh
commit 6d03d0539e0afd51383f11fd6b06ec7ced0fbf12
Author: Stephen Ecob <silicon.on.inspiration@xxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Fix Freckles
The autorouter sometimes ends a trace just past a pad. The optimizer
cuts this trace at the pad center, leaving a tiny trace left over.
This tiny trace is a "freckle" and it inhibits mitering. Check
for such freckles and remove them.
:100644 100644 68b3641... c8ae961... M src/djopt.c
commit a096a8b84c1d0e2beb94a859bde9f2bc2799fe73
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Make the xy file check actually do something.
:100755 100755 0667fb8... 5320c54... M tests/run_tests.sh
commit beb4c7c5626b8b28c0a203a23fb41f28e5662618
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add testsuite entries to test the gcode export HID and all of its
command line options.
:100644 100644 356e02e... 3f8ed62... M configure.ac
:100644 100644 1c7afa2... de5bb08... M tests/golden/Makefile.am
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode1/Makefile.am
:000000 100644 0000000... 2031270... A tests/golden/hid_gcode1/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 63f6a2d... A tests/golden/hid_gcode1/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... afd6cb2... A tests/golden/hid_gcode1/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode10/Makefile.am
:000000 100644 0000000... 19a703d... A tests/golden/hid_gcode10/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 7deace0... A tests/golden/hid_gcode10/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... a1d48bd... A tests/golden/hid_gcode10/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode11/Makefile.am
:000000 100644 0000000... c144b05... A tests/golden/hid_gcode11/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 37b9668... A tests/golden/hid_gcode11/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... ddf7394... A tests/golden/hid_gcode11/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... a757c9e... A tests/golden/hid_gcode2/Makefile.am
:000000 100644 0000000... c3b0526... A tests/golden/hid_gcode2/out.back.cnc
:000000 100644 0000000... f7c6d78... A tests/golden/hid_gcode2/out.drill.cnc
:000000 100644 0000000... ca2b079... A tests/golden/hid_gcode2/out.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode3/Makefile.am
:000000 100644 0000000... e67b085... A tests/golden/hid_gcode3/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... e7be01d... A tests/golden/hid_gcode3/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... d7c8c9f... A tests/golden/hid_gcode3/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode4/Makefile.am
:000000 100644 0000000... d049972... A tests/golden/hid_gcode4/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... c648655... A tests/golden/hid_gcode4/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... 78e64a5... A tests/golden/hid_gcode4/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode5/Makefile.am
:000000 100644 0000000... 8041f98... A tests/golden/hid_gcode5/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 77d8d60... A tests/golden/hid_gcode5/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... e3bbd7e... A tests/golden/hid_gcode5/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode6/Makefile.am
:000000 100644 0000000... 7d33799... A tests/golden/hid_gcode6/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 6b44265... A tests/golden/hid_gcode6/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... 7dfd6a0... A tests/golden/hid_gcode6/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode7/Makefile.am
:000000 100644 0000000... b92e532... A tests/golden/hid_gcode7/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... e8c41bf... A tests/golden/hid_gcode7/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... 4c64804... A tests/golden/hid_gcode7/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode8/Makefile.am
:000000 100644 0000000... 286cab5... A tests/golden/hid_gcode8/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... 77ac526... A tests/golden/hid_gcode8/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... a57aeb7... A tests/golden/hid_gcode8/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... b071e19... A tests/golden/hid_gcode9/Makefile.am
:000000 100644 0000000... 49ebcd5... A tests/golden/hid_gcode9/gcode_oneline.gcode.back.cnc
:000000 100644 0000000... c4b730a... A tests/golden/hid_gcode9/gcode_oneline.gcode.drill.cnc
:000000 100644 0000000... 638cec1... A tests/golden/hid_gcode9/gcode_oneline.gcode.front.cnc
:000000 100644 0000000... c20eacf... A tests/inputs/gcode_oneline.pcb
:100755 100755 3892856... 0667fb8... M tests/run_tests.sh
:100644 100644 8949763... 95af71d... M tests/tests.list
commit fd1c65c236bdcd4b36400e82074d66ab83bc5de3
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove RCSID. We don't use those anymore.
:100644 100644 3767ad4... bbc1d53... M src/hid/gcode/gcode.c
commit b6378a3845066adb23601d8fa781fd58233176dd
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Change options like 'drill depth' to 'drill-depth' as a space in
a command line option is non-standard. Also be consistent with
having or not having a "." at the end of the option help strings.
:100644 100644 c5ca8df... 3767ad4... M src/hid/gcode/gcode.c
commit c544e63eca400b33127ac539e4737c7959e8db2c
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove unix2dos system() call. It was not needed.
:100644 100644 317e6a1... c5ca8df... M src/hid/gcode/gcode.c
commit 9babb216b2921ad716b740068988d04a0d9dfe45
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Get rid of compiler warnings.
:100644 100644 5f1c48e... 8d7e5e6... M src/hid/gcode/trace.c
commit 0e008cb83dcfc4fc6a3455bdd3c8dd86ed65b374
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Get rid of some gcc warnings.
:100644 100644 6d022ce... 317e6a1... M src/hid/gcode/gcode.c
commit 290c968566837132afbfc63d5fe1436c03dcec1e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
C++ style comments -> C style comments
:100644 100644 e8c38db... 6d022ce... M src/hid/gcode/gcode.c
commit 073463e605095692e2cf8d4238df0c817e68e3c3
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix nroff error. Noted in sf patch #2889227 by Ahmed El-Mahmoudy.
:100644 100644 3dd9867... b84c653... M doc/pcb.1
commit ca738957694927538dad15f037d5622571fd3173
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
add the gcode exporter to the export hid list
:100644 100644 d5578fb... 356e02e... M configure.ac
commit 7467c8b2cedb80ee32e2ff19662d6894a6d7f345
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
add notes about what libs may be needed (none) for the gcode exporter.
:100644 100644 1dfa0f8... db27639... M INSTALL
commit 19f7443c3249a9cc40efd04c1895b89445add385
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
indent to conform to the coding style used by pcb.
:100644 100644 7baab85... 254e4c0... M src/hid/gcode/auxiliary.h
:100644 100644 2a172b1... 589b80b... M src/hid/gcode/bitmap.h
:100644 100644 0dc1005... abf85d7... M src/hid/gcode/curve.c
:100644 100644 45c0790... 6f7e8a1... M src/hid/gcode/curve.h
:100644 100644 abc5e0a... 0b42882... M src/hid/gcode/decompose.c
:100644 100644 d5be99c... 333003e... M src/hid/gcode/decompose.h
:100644 100644 5792d0c... e8c38db... M src/hid/gcode/gcode.c
:100644 100644 352cbd9... ae9d7a0... M src/hid/gcode/gcode.h
:100644 100644 931cbb0... 2a2353f... M src/hid/gcode/lists.h
:100644 100644 0b93d65... 2456c01... M src/hid/gcode/potracelib.h
:100644 100644 2c615e6... 5f1c48e... M src/hid/gcode/trace.c
:100644 100644 4a9683c... 2a07e61... M src/hid/gcode/trace.h
commit 47edc12beab88ea5a6d7608e5741131eb5c0e8d4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
gcode_lists.h should depend on gcode sources, not png sources.
:100644 100644 371173a... a5441d6... M src/Makefile.am
commit e402b491c199d1df9808e129461d585346a03c9e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Apply sf patch 2948711 from Alberto Maccioni which adds a g-code
exporter.
:000000 100644 0000000... 7baab85... A src/hid/gcode/auxiliary.h
:000000 100644 0000000... 2a172b1... A src/hid/gcode/bitmap.h
:000000 100644 0000000... 0dc1005... A src/hid/gcode/curve.c
:000000 100644 0000000... 45c0790... A src/hid/gcode/curve.h
:000000 100644 0000000... abc5e0a... A src/hid/gcode/decompose.c
:000000 100644 0000000... d5be99c... A src/hid/gcode/decompose.h
:000000 100644 0000000... 5792d0c... A src/hid/gcode/gcode.c
:000000 100644 0000000... 352cbd9... A src/hid/gcode/gcode.h
:000000 100644 0000000... 7be6c4c... A src/hid/gcode/hid.conf
:000000 100644 0000000... 931cbb0... A src/hid/gcode/lists.h
:000000 100644 0000000... 0b93d65... A src/hid/gcode/potracelib.h
:000000 100644 0000000... 2c615e6... A src/hid/gcode/trace.c
:000000 100644 0000000... 4a9683c... A src/hid/gcode/trace.h
commit b4ca96d312884a8bc2314e490c2c957ab590b427
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
When building the docs have configure check for epsf.tex being in the TeX
installation. Problem noted by Kai-Martin Knaak and the method for checking
suggested by Peter Clifton.
:100644 100644 415c400... d5578fb... M configure.ac
commit 5c7cc398ffc8f646d68eada8d6cd74dff4bceb85
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix test for whether to rebuild the shipped pcblib-newlib library
${top_srcdir} is a Makefile variable, we need $srcdir in configure.ac
:100644 100644 9c14582... 415c400... M configure.ac
commit ca1af54230754bde0cda442a6d966a4aa1a3e6b4
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix make distcheck by removing regenerated newlib footprints
The generated newlib files need to be removed by make distclean
if they are being updated by the build process. If the files aren't
being updated, we should not delete them as they were originally
distributed with the source tarball.
:100644 100644 95be997... ae1b485... M lib/Makefile.am
commit 2eb25f8f7cc9584528b2caa54a6097fc17fcec8b
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix distribution of gnet-pcbfwd.scm in the dist tarball
Use the dist_ prefix to make this simple, so our installed
targets are now listed in dist_..._DATA, rather than ..._DATA
and EXTRA_DIST.
:100644 100644 002fecc... d9665a9... M tools/Makefile.am
commit d2a7382d1fcecd85a1feee399543a3e89fe1ef6b
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Allow empty attribute values.
The STRING token is NULL when an empty string is indicated, but
empty attributes are different than missing attributes, so if a STRING
is NULL, store an empty string instead.
:100644 100644 646ef77... bbb7255... M src/parse_y.y
=========
Changes
=========
commit 7e95250675a70d8fec2bc9ed7ffb8ab067f4390b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Remove conflicting declaration of ParseLibraryTree.
This is a static function declared in file.c. Therefore I
took it out of file.h.
diff --git a/src/file.h b/src/file.h
index 2822525..64eba23 100644
--- a/src/file.h
+++ b/src/file.h
@@ -48,7 +48,6 @@ int SaveBufferElements (char *);
void PreLoadElementPCB (void);
void PostLoadElementPCB (void);
void sort_netlist (void);
-int ParseLibraryTree (void);
/*
* Whenever the pcb file format is modified, this version number
commit 8e622b2c0aa88e2fe131c45438429d3524dc4da6
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Place components in middle of board instead of at 0,0.
diff --git a/src/action.c b/src/action.c
index 94bf07e..c15c7c0 100644
--- a/src/action.c
+++ b/src/action.c
@@ -6968,7 +6968,8 @@ ActionElementList (int argc, char **argv, int x, int y)
/* Not on board, need to add it. */
if (LoadFootprint(argc, args, x, y))
return 1;
- if (CopyPastebufferToLayout (0, 0))
+ /* Place components onto center of board. */
+ if (CopyPastebufferToLayout (PCB->MaxWidth/2, PCB->MaxHeight/2))
SetChangedFlag (True);
}
commit 542c19ff457755ce9d26ec1883650c125fcfe576
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Support for footprints not in subdirectories
Added tons of debug spew to various files to aid in program tracing
Also, modify library loading stuff in file.c to allow footprints to live
directly in library directory (rather than only one level down).
diff --git a/src/action.c b/src/action.c
index d7c754b..94bf07e 100644
--- a/src/action.c
+++ b/src/action.c
@@ -6864,6 +6864,7 @@ delete_attr (AttributeListTypePtr list, AttributeType *attr)
list->Number --;
}
+/* ---------------------------------------------------------------- */
static const char elementlist_syntax[] = "ElementList(Start|Done|Need,<refdes>,<footprint>,<value>)";
static const char elementlist_help[] = "Adds the given element if it doesn't already exist.";
@@ -6901,6 +6902,10 @@ ActionElementList (int argc, char **argv, int x, int y)
char *args[3];
char *function = argv[0];
+#ifdef DEBUG
+ printf("Entered ActionElementList, executing function %s\n", function);
+#endif
+
if (strcasecmp (function, "start") == 0)
{
ELEMENT_LOOP (PCB->Data);
@@ -6947,10 +6952,19 @@ ActionElementList (int argc, char **argv, int x, int y)
args[1] = refdes;
args[2] = value;
+#ifdef DEBUG
+ printf(" ... footprint = %s\n", footprint);
+ printf(" ... refdes = %s\n", refdes);
+ printf(" ... value = %s\n", value);
+#endif
+
e = find_element_by_refdes (refdes);
if (!e)
{
+#ifdef DEBUG
+ printf(" ... Footprint not on board, need to add it.\n");
+#endif
/* Not on board, need to add it. */
if (LoadFootprint(argc, args, x, y))
return 1;
@@ -6960,6 +6974,9 @@ ActionElementList (int argc, char **argv, int x, int y)
else if (e && strcmp (DESCRIPTION_NAME(e), footprint) != 0)
{
+#ifdef DEBUG
+ printf(" ... Footprint on board, but different from footprint loaded.\n");
+#endif
int er, pr, i;
LocationType mx, my;
ElementType *pe;
@@ -6992,6 +7009,7 @@ ActionElementList (int argc, char **argv, int x, int y)
SetChangedFlag (True);
}
+ /* Now reload footprint */
e = find_element_by_refdes (refdes);
old = ChangeElementText (PCB, PCB->Data, e, NAMEONPCB_INDEX, strdup (refdes));
@@ -7003,9 +7021,14 @@ ActionElementList (int argc, char **argv, int x, int y)
SET_FLAG (FOUNDFLAG, e);
+#ifdef DEBUG
+ printf(" ... Leaving ActionElementList.\n");
+#endif
+
return 0;
}
+/* ---------------------------------------------------------------- */
static const char elementsetattr_syntax[] = "ElementSetAttr(refdes,name[,value])";
static const char elementsetattr_help[] = "Sets or clears an element-specific attribute";
@@ -7069,6 +7092,7 @@ ActionElementSetAttr (int argc, char **argv, int x, int y)
return 0;
}
+/* ---------------------------------------------------------------- */
static const char execcommand_syntax[] = "ExecCommand(command)";
static const char execcommand_help[] = "Runs a command";
@@ -7096,6 +7120,7 @@ ActionExecCommand (int argc, char **argv, int x, int y)
return 0;
}
+/* ---------------------------------------------------------------- */
static const char import_syntax[] =
"Import()\n"
"Import([gnetlist|make[,source,source,...]])\n";
@@ -7192,6 +7217,7 @@ pcb_spawnvp (char **argv)
return 0;
}
+/* ---------------------------------------------------------------- */
/*
* Creates a new temporary file name. Hopefully the operating system
* provides a mkdtemp() function to securily create a temporary
@@ -7278,6 +7304,7 @@ tempfile_name_new (char * name)
return tmpfile;
}
+/* ---------------------------------------------------------------- */
/*
* Unlink a temporary file. If we have mkdtemp() then our temp file
* lives in a temporary directory and we need to remove that directory
@@ -7288,6 +7315,11 @@ tempfile_unlink (char * name)
{
int rc;
+#ifdef DEBUG
+ /* SDB says: Want to keep old temp files for examiniation when debugging */
+ return 0;
+#endif
+
#ifdef HAVE_MKDTEMP
int e, rc2 = 0;
char *dname;
@@ -7348,6 +7380,7 @@ tempfile_unlink (char * name)
return 0;
}
+/* ---------------------------------------------------------------- */
static int
ActionImport (int argc, char **argv, int x, int y)
{
@@ -7355,6 +7388,10 @@ ActionImport (int argc, char **argv, int x, int y)
char **sources = NULL;
int nsources = 0;
+#ifdef DEBUG
+ printf("ActionImport: =========== Entering ActionImport ============\n");
+#endif
+
mode = ARG (0);
if (! mode)
mode = AttributeGet (PCB, "import::mode");
@@ -7447,12 +7484,22 @@ ActionImport (int argc, char **argv, int x, int y)
cmd[5+i] = sources[i];
cmd[5+nsources] = NULL;
+#ifdef DEBUG
+ printf("ActionImport: =========== About to run gnetlist ============\n");
+ printf("%s %s %s %s %s %s ...\n",
+ cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
+#endif
+
if (pcb_spawnvp (cmd))
{
unlink (tmpfile);
return 1;
}
+#ifdef DEBUG
+ printf("ActionImport: =========== About to run ActionExecuteFile, file = %s ============\n", tmpfile);
+#endif
+
cmd[0] = tmpfile;
cmd[1] = NULL;
ActionExecuteFile (1, cmd, 0, 0);
@@ -7546,6 +7593,10 @@ ActionImport (int argc, char **argv, int x, int y)
DeleteRats (False);
AddAllRats (False, NULL);
+#ifdef DEBUG
+ printf("ActionImport: =========== Leaving ActionImport ============\n");
+#endif
+
return 0;
}
diff --git a/src/buffer.c b/src/buffer.c
index 7daecf5..fbd1735 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -683,23 +683,40 @@ make_footprint_hash ()
in brackets in the description. */
for (i=0; i<Library.MenuN; i++)
{
- for (j=0; j<Library.Menu[i].EntryN; j++)
+#ifdef DEBUG
+ printf("In make_footprint_hash, looking for footprints in %s\n",
+ Library.Menu[i].directory);
+#endif
+
+ for (j=0; j<Library.Menu[i].EntryN; j++)
{
footprint_hash[num_entries].menu_idx = i;
footprint_hash[num_entries].entry_idx = j;
- if (Library.Menu[i].Entry[j].Template == (char *) -1)
+ if (Library.Menu[i].Entry[j].Template == (char *) -1)
+ /* file */
{
+#ifdef DEBUG
+/* printf(" ... Examining file %s\n", Library.Menu[i].Entry[j].AllocatedMemory); */
+#endif
fp = strrchr (Library.Menu[i].Entry[j].AllocatedMemory, '/');
+
if (!fp)
fp = strrchr (Library.Menu[i].Entry[j].AllocatedMemory, '\\');
+
if (fp)
fp ++;
- else
+ else
fp = Library.Menu[i].Entry[j].AllocatedMemory;
+
+#ifdef DEBUG
+/* printf(" ... found file footprint %s\n", fp); */
+#endif
+
footprint_hash[num_entries].footprint = fp;
footprint_hash[num_entries].footprint_allocated = 0;
}
- else
+ else
+ /* m4 */
{
fp = strrchr (Library.Menu[i].Entry[j].Description, '[');
if (fp)
@@ -723,10 +740,13 @@ make_footprint_hash ()
footprint_hash_size = num_entries;
qsort (footprint_hash, num_entries, sizeof(footprint_hash[0]), footprint_hash_cmp);
-#if 0
+/*
+#ifdef DEBUG
+ printf(" found footprints: \n");
for (i=0; i<num_entries; i++)
printf("[%s]\n", footprint_hash[i].footprint);
#endif
+*/
}
FootprintHashEntry *
@@ -810,7 +830,7 @@ LoadFootprintByName (BufferTypePtr Buffer, char *Footprint)
return i ? 0 : 1;
}
-#if 1
+#ifdef DEBUG
{
int j;
printf("Library path: %s\n", Settings.LibraryPath);
diff --git a/src/change.c b/src/change.c
index db13d5e..8cbd384 100644
--- a/src/change.c
+++ b/src/change.c
@@ -988,6 +988,10 @@ ChangeElementText (PCBType *pcb, DataType *data, ElementTypePtr Element, int whi
{
char *old = Element->Name[which].TextString;
+#ifdef DEBUG
+ printf("In ChangeElementText, updating old TextString %s to %s\n", old, new_name);
+#endif
+
if (pcb && which == NAME_INDEX (pcb))
EraseElementName (Element);
diff --git a/src/copy.c b/src/copy.c
index 5a030c9..583feb8 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -277,11 +277,17 @@ CopyPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
}
/* ---------------------------------------------------------------------------
- * copies a element
+ * copies an element onto the PCB. Then does a draw.
*/
static void *
CopyElement (ElementTypePtr Element)
{
+
+#ifdef DEBUG
+ printf("Entered CopyElement, trying to copy element %s\n",
+ Element->Name[1].TextString);
+#endif
+
Boolean didDraw = False;
ElementTypePtr element = CopyElementLowLevel (PCB->Data,
NULL, Element,
@@ -302,6 +308,9 @@ CopyElement (ElementTypePtr Element)
DrawElementPinsAndPads (element, 0);
didDraw = True;
}
+#ifdef DEBUG
+ printf(" ... Leaving CopyElement.\n");
+#endif
return (element);
}
@@ -315,6 +324,10 @@ CopyPastebufferToLayout (LocationType X, LocationType Y)
Cardinal i;
Boolean changed = False;
+#ifdef DEBUG
+ printf("Entering CopyPastebufferToLayout.....\n");
+#endif
+
/* set movement vector */
DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y;
@@ -358,6 +371,10 @@ CopyPastebufferToLayout (LocationType X, LocationType Y)
{
ELEMENT_LOOP (PASTEBUFFER->Data);
{
+#ifdef DEBUG
+ printf("In CopyPastebufferToLayout, pasting element %s\n",
+ element->Name[1].TextString);
+#endif
if (FRONT (element) || PCB->InvisibleObjectsOn)
{
CopyElement (element);
@@ -377,11 +394,17 @@ CopyPastebufferToLayout (LocationType X, LocationType Y)
}
END_LOOP;
}
+
if (changed)
{
Draw ();
IncrementUndoSerialNumber ();
}
+
+#ifdef DEBUG
+ printf(" .... Leaving CopyPastebufferToLayout.\n");
+#endif
+
return (changed);
}
diff --git a/src/create.c b/src/create.c
index 518a35b..eced68d 100644
--- a/src/create.c
+++ b/src/create.c
@@ -199,6 +199,9 @@ CreateNewPCB (Boolean SetDefaultNames)
return (ptr);
}
+/* This post-processing step adds the top and bottom silk layers to a
+ * pre-existing PCB.
+ */
int
CreateNewPCBPost (PCBTypePtr pcb, int use_defaults)
{
@@ -643,6 +646,10 @@ CreateNewElement (DataTypePtr Data, ElementTypePtr Element,
LocationType TextX, LocationType TextY, BYTE Direction,
int TextScale, FlagType TextFlags, Boolean uniqueName)
{
+#ifdef DEBUG
+ printf("Entered CreateNewElement.....\n");
+#endif
+
if (!Element)
Element = GetElementMemory (Data);
@@ -661,6 +668,11 @@ CreateNewElement (DataTypePtr Data, ElementTypePtr Element,
VALUE_TEXT (Element).Element = Element;
Element->Flags = Flags;
Element->ID = ID++;
+
+#ifdef DEBUG
+ printf(" .... Leaving CreateNewElement.\n");
+#endif
+
return (Element);
}
diff --git a/src/file.c b/src/file.c
index fd18340..639c971 100644
--- a/src/file.c
+++ b/src/file.c
@@ -124,6 +124,8 @@ static int WritePCB (FILE *);
static int WritePCBFile (char *);
static int WritePipe (char *, Boolean);
static int ParseLibraryTree (void);
+static int LoadNewlibFootprintsFromDir(char *path, char *toppath);
+static char *pcb_basename (char *p);
/* ---------------------------------------------------------------------------
* Flag helper functions
@@ -1093,9 +1095,10 @@ RemoveTMPData (void)
#endif
/* ---------------------------------------------------------------------------
- * parse the directory tree where additional library elements are found
+ * Parse the directory tree where newlib footprints are found
*/
+/* Helper function for ParseLibraryTree */
static char *
pcb_basename (char *p)
{
@@ -1105,132 +1108,205 @@ pcb_basename (char *p)
return p;
}
-int
-ParseLibraryTree (void)
+/* This is a helper function for ParseLibrary Tree. Given a char *path,
+ * it finds all newlib footprints in that dir and sticks them into the
+ * library menu structure named entry.
+ */
+static int
+LoadNewlibFootprintsFromDir(char *libpath, char *toppath)
{
- char path[MAXPATHLEN + 1];
- char working[MAXPATHLEN + 1];
- char *libpaths, *p;
- DIR *dir, *subdir;
- struct stat buffer;
- struct dirent *direntry, *e2;
- LibraryMenuTypePtr menu = NULL;
- LibraryEntryTypePtr entry;
+ char olddir[MAXPATHLEN + 1]; /* The directory we start out in (cwd) */
+ char subdir[MAXPATHLEN + 1]; /* The directory holding footprints to load */
+ DIR *subdirobj; /* Interable object holding all subdir entries */
+ struct dirent *subdirentry; /* Individual subdir entry */
+ struct stat buffer; /* Buffer used in stat */
+ LibraryMenuTypePtr menu = NULL; /* Pointer to PCB's library menu structure */
+ LibraryEntryTypePtr entry; /* Pointer to individual menu entry */
size_t l;
- int n_footprints = 0;
+ size_t len;
+ int n_footprints = 0; /* Running count of footprints found in this subdir */
+
+ /* Cache old dir, then cd into subdir because stat is given relative file names. */
+ memset (subdir, 0, sizeof subdir);
+ memset (olddir, 0, sizeof olddir);
+ GetWorkingDirectory(olddir);
+ strcpy (subdir, libpath);
+ chdir(subdir);
+ GetWorkingDirectory(subdir); /* subdir is abs path */
+
+ /* First try opening the directory specified by path */
+ if ( (subdirobj = opendir (subdir)) == NULL )
+ {
+ OpendirErrorMessage (subdir);
+ return 0;
+ }
+
+ /* Get pointer to memory holding menu */
+ menu = GetLibraryMenuMemory (&Library);
+ /* Populate menuname and path vars */
+ menu->Name = MyStrdup (pcb_basename(subdir), "Newlib");
+ menu->directory = strdup (pcb_basename(toppath));
+
+ /* Now loop over files in this directory looking for files.
+ * We ignore certain files which are not footprints.
+ */
+ while ((subdirentry = readdir (subdirobj)) != NULL)
+ {
+#ifdef DEBUG
+/* printf("... Examining file %s ... \n", subdirentry->d_name); */
+#endif
+
+ /* Ignore non-footprint files found in this directory
+ * We're skipping .png and .html because those
+ * may exist in a library tree to provide an html browsable
+ * index of the library.
+ */
+ l = strlen (subdirentry->d_name);
+ if (!stat (subdirentry->d_name, &buffer) && S_ISREG (buffer.st_mode)
+ && subdirentry->d_name[0] != '.'
+ && NSTRCMP (subdirentry->d_name, "CVS") != 0
+ && NSTRCMP (subdirentry->d_name, "Makefile") != 0
+ && NSTRCMP (subdirentry->d_name, "Makefile.am") != 0
+ && NSTRCMP (subdirentry->d_name, "Makefile.in") != 0
+ && (l < 4 || NSTRCMP(subdirentry->d_name + (l - 4), ".png") != 0)
+ && (l < 5 || NSTRCMP(subdirentry->d_name + (l - 5), ".html") != 0) )
+ {
+#ifdef DEBUG
+/* printf("... Found a footprint %s ... \n", subdirentry->d_name); */
+#endif
+ n_footprints++;
+ entry = GetLibraryEntryMemory (menu);
+
+ /*
+ * entry->AllocatedMemory points to abs path to the footprint.
+ * entry->ListEntry points to fp name itself.
+ */
+ len = strlen(subdir) + strlen("/") + strlen(subdirentry->d_name) + 1;
+ entry->AllocatedMemory = MyCalloc (1, len, "ParseLibraryTree()");
+ strcat (entry->AllocatedMemory, subdir);
+ strcat (entry->AllocatedMemory, PCB_DIR_SEPARATOR_S);
+
+ /* store pointer to start of footprint name */
+ entry->ListEntry = entry->AllocatedMemory
+ + strlen (entry->AllocatedMemory);
+
+ /* Now place footprint name into AllocatedMemory */
+ strcat (entry->AllocatedMemory, subdirentry->d_name);
+
+ /* mark as directory tree (newlib) library */
+ entry->Template = (char *) -1;
+ }
+ }
+ /* Done. Clean up, cd back into old dir, and return */
+ closedir (subdirobj);
+ chdir(olddir);
+ return n_footprints;
+}
- memset (path, 0, sizeof path);
+
+/* This function loads the newlib footprints into the Library.
+ * It examines all directories pointed to by Settings.LibraryTree.
+ * In each directory specified there, it looks both in that directory,
+ * as well as *one* level down. It calls the subfunction
+ * LoadNewlibFootprintsFromDir to put the footprints into PCB's internal
+ * datastructures.
+ */
+static int
+ParseLibraryTree (void)
+{
+ char toppath[MAXPATHLEN + 1]; /* String holding abs path to top level library dir */
+ char working[MAXPATHLEN + 1]; /* String holding abs path to working dir */
+ char *libpaths; /* String holding list of library paths to search */
+ char *p; /* Helper string used in iteration */
+ DIR *dirobj; /* Iterable directory object */
+ struct dirent *direntry = NULL; /* Object holding individual directory entries */
+ struct stat buffer; /* buffer used in stat */
+ int n_footprints = 0; /* Running count of footprints found */
+
+ /* Initialize path, working by writing 0 into every byte. */
+ memset (toppath, 0, sizeof toppath);
memset (working, 0, sizeof working);
- /* save the current working directory */
+ /* Save the current working directory as an absolute path.
+ * This fcn writes the abs path into the memory pointed to by the input arg.
+ */
GetWorkingDirectory (working);
- /* Additional loop to allow for multiple 'newlib' style library directories */
+ /* Additional loop to allow for multiple 'newlib' style library directories
+ * called out in Settings.LibraryTree
+ */
libpaths = MyStrdup (Settings.LibraryTree, "ParseLibraryTree");
for (p = strtok (libpaths, PCB_PATH_DELIMETER); p && *p; p = strtok (NULL, PCB_PATH_DELIMETER))
{
- strncpy (path, p, sizeof (path) - 1);
+ /* remove trailing path delimeter */
+ strncpy (toppath, p, sizeof (toppath) - 1);
- /*
- * start out in the working directory in case the path is a
+ /* start out in the working directory in case the path is a
* relative path
*/
chdir (working);
- if ((dir = opendir (path)) == NULL)
+ /*
+ * Next change to the directory which is the top of the library tree
+ * and extract its abs path.
+ */
+ chdir (toppath);
+ GetWorkingDirectory (toppath);
+
+#ifdef DEBUG
+ printf("In ParseLibraryTree, looking for newlib footprints inside top level directory %s ... \n",
+ toppath);
+#endif
+
+ /* Next read in any footprints in the top level dir */
+ n_footprints += LoadNewlibFootprintsFromDir("(local)", toppath);
+
+ /* Then open this dir so we can loop over its contents. */
+ if ((dirobj = opendir (toppath)) == NULL)
{
- OpendirErrorMessage (path);
+ OpendirErrorMessage (toppath);
continue;
}
- /*
- * change to the directory which is the top of the library tree
- * and then extract that directory to ensure we have a full path
- * name, not a relative path name.
+ /* Now loop over files in this directory looking for subdirs.
+ * For each direntry which is a valid subdirectory,
+ * try to load newlib footprints inside it.
*/
- chdir (path);
- GetWorkingDirectory (path);
-
- /* read all entries */
- while ((direntry = readdir (dir)) != NULL)
+ while ((direntry = readdir (dirobj)) != NULL)
{
- chdir (path);
- /* find directories
- * ignore entries beginning with "." and CVS
- * directories as well as a few other specific
- * files. We're skipping .png and .html because those
- * may exist in a library tree to provide an html browsable
- * index of the library.
+#ifdef DEBUG
+ printf("In ParseLibraryTree loop examining 2nd level direntry %s ... \n", direntry->d_name);
+#endif
+ /* Find subdirectories. Ignore entries beginning with "." and CVS
+ * directories.
*/
if (!stat (direntry->d_name, &buffer)
- && S_ISDIR (buffer.st_mode) && direntry->d_name[0] != '.'
+ && S_ISDIR (buffer.st_mode)
+ && direntry->d_name[0] != '.'
&& NSTRCMP (direntry->d_name, "CVS") != 0)
{
- /* add directory name into menu */
- menu = GetLibraryMenuMemory (&Library);
- menu->Name = MyStrdup (direntry->d_name, "ParseLibraryTree()");
- /* FIXME ? */
- menu->directory = strdup (pcb_basename (path));
- subdir = opendir (direntry->d_name);
- chdir (direntry->d_name);
- while (subdir && (e2 = readdir (subdir)))
- {
- l = strlen (e2->d_name);
- if (!stat (e2->d_name, &buffer) && S_ISREG (buffer.st_mode)
- && e2->d_name[0] != '.'
- && NSTRCMP (e2->d_name, "CVS") != 0
- && NSTRCMP (e2->d_name, "Makefile") != 0
- && NSTRCMP (e2->d_name, "Makefile.am") != 0
- && NSTRCMP (e2->d_name, "Makefile.in") != 0
- && (l < 4 || NSTRCMP(e2->d_name + (l - 4), ".png") != 0)
- && (l < 5 || NSTRCMP(e2->d_name + (l - 5), ".html") != 0) )
- {
-
- /*
- * Besides the length for the 3 strings listed,
- * we have two "/" added in below, and also we
- * have 2 '\0' characters since
- * entry->AllocatedMemory actually will contain
- * 2 null terminated strings. Thats why we
- * add 4
- */
- long len = strlen (path) + strlen (e2->d_name) +
- strlen (direntry->d_name) + 4;
-#if 0
- if (NSTRCMP
- (e2->d_name + strlen (e2->d_name) - 4, ".lel") != 0)
- break;
-#endif
- n_footprints++;
- entry = GetLibraryEntryMemory (menu);
- entry->AllocatedMemory = MyCalloc (1, len,
- "ParseLibraryTree()");
- strcat (entry->AllocatedMemory, path);
- strcat (entry->AllocatedMemory, PCB_DIR_SEPARATOR_S);
- strcat (entry->AllocatedMemory, direntry->d_name);
- strcat (entry->AllocatedMemory, PCB_DIR_SEPARATOR_S);
- entry->ListEntry = entry->AllocatedMemory
- + strlen (entry->AllocatedMemory);
- strcat (entry->AllocatedMemory, e2->d_name);
- /* mark as directory tree library */
- entry->Template = (char *) -1;
- }
- }
- closedir (subdir);
+ /* Found a valid subdirectory. Try to load footprints from it.
+ */
+ n_footprints += LoadNewlibFootprintsFromDir(direntry->d_name, toppath);
}
}
- closedir (dir);
+ closedir (dirobj);
}
- free (libpaths);
/* restore the original working directory */
chdir (working);
+
+#ifdef DEBUG
+ printf("Leaving ParseLibraryTree, found %d footprints.\n", n_footprints);
+#endif
+
return n_footprints;
}
/* ---------------------------------------------------------------------------
- * read contents of the library description file
- * also parse a special library directory tree
+ * Read contents of the library description file (for M4)
+ * and then read in M4 libs. Then call a fcn to read the newlib
+ * footprints.
*/
int
ReadLibraryContents (void)
@@ -1241,18 +1317,28 @@ ReadLibraryContents (void)
LibraryMenuTypePtr menu = NULL;
LibraryEntryTypePtr entry;
+
+ /* First load the M4 stuff. The variable Settings.LibraryPath
+ * points to it.
+ */
MYFREE (command);
command = EvaluateFilename (Settings.LibraryContentsCommand,
Settings.LibraryPath, Settings.LibraryFilename,
NULL);
- /* open a pipe to the output of the command */
+#ifdef DEBUG
+ printf("In ReadLibraryContents, about to execute command %s\n", command);
+#endif
+
+ /* This uses a pipe to execute a shell script which provides the names of
+ * all M4 libs and footprints. The results are placed in resultFP.
+ */
if (command && *command && (resultFP = popen (command, "r")) == NULL)
{
PopenErrorMessage (command);
}
- /* the library contents are separated by colons;
+ /* the M4 library contents are separated by colons;
* template : package : name : description
*/
while (resultFP != NULL && fgets (inputline, MAX_LIBRARY_LINE_LENGTH, resultFP))
@@ -1312,7 +1398,11 @@ ReadLibraryContents (void)
}
if (resultFP != NULL)
pclose (resultFP);
-
+
+ /* Now after reading in the M4 libs, call a function to
+ * read the newlib footprint libraries. Then sort the whole
+ * library.
+ */
if (ParseLibraryTree () > 0 || resultFP != NULL)
{
sort_library (&Library);
diff --git a/src/file.h b/src/file.h
index 64eba23..2822525 100644
--- a/src/file.h
+++ b/src/file.h
@@ -48,6 +48,7 @@ int SaveBufferElements (char *);
void PreLoadElementPCB (void);
void PostLoadElementPCB (void);
void sort_netlist (void);
+int ParseLibraryTree (void);
/*
* Whenever the pcb file format is modified, this version number
diff --git a/src/global.h b/src/global.h
index 80bea72..1082dd1 100644
--- a/src/global.h
+++ b/src/global.h
@@ -178,8 +178,8 @@ typedef struct
struct BoxType /* a bounding box */
{
- LocationType X1, Y1, /* upper left */
- X2, Y2; /* and lower right corner */
+ LocationType X1, Y1; /* upper left */
+ LocationType X2, Y2; /* and lower right corner */
};
typedef struct
@@ -231,8 +231,7 @@ typedef struct
{
ANYOBJECTFIELDS;
BDimension Scale; /* text scaling in percent */
- LocationType X, /* origin */
- Y;
+ LocationType X, Y; /* origin */
BYTE Direction;
char *TextString; /* string */
void *Element;
@@ -809,11 +808,11 @@ struct drc_violation_st
* Variables with absolute paths to various directories. These are deduced
* at runtime to allow pcb to be relocatable
*/
-extern char *bindir;
-extern char *pcblibdir;
-extern char *pcblibpath;
-extern char *pcbtreedir;
-extern char *pcbtreepath;
+extern char *bindir; /* The dir in which PCB installation was found */
+extern char *pcblibdir; /* The system M4 fp directory */
+extern char *pcblibpath; /* The search path for M4 fps */
+extern char *pcbtreedir; /* The system newlib fp directory */
+extern char *pcbtreepath; /* The search path for newlib fps */
extern char *exec_prefix;
extern char *homedir;
diff --git a/src/main.c b/src/main.c
index e5d93eb..3026f8d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -896,11 +896,13 @@ main (int argc, char *argv[])
program_basename = program_name;
}
Progname = program_basename;
-
+
+ /* Print usage or version if requested. Then exit. */
if (argc > 1 && strcmp (argv[1], "-h") == 0)
usage ();
if (argc > 1 && strcmp (argv[1], "-V") == 0)
print_version ();
+ /* Export pcb from command line if requested. */
if (argc > 1 && strcmp (argv[1], "-p") == 0)
{
exporter = gui = hid_find_printer ();
@@ -913,12 +915,15 @@ main (int argc, char *argv[])
argc -= 2;
argv += 2;
}
+ /* Otherwise start GUI. */
else
gui = hid_find_gui ();
+ /* Exit with error if GUI failed to start. */
if (!gui)
exit (1);
+ /* Set up layers. */
for (i = 0; i < MAX_LAYER; i++)
{
char buf[20];
@@ -960,9 +965,11 @@ main (int argc, char *argv[])
exit (0);
}
+ /* Create a new PCB object in memory */
PCB = CreateNewPCB (True);
PCB->Data->LayerN = DEF_LAYER;
ParseGroupString (Settings.Groups, &PCB->LayerGroups, DEF_LAYER);
+ /* Add silk layers to newly created PCB */
CreateNewPCBPost (PCB, 1);
if (argc > 1)
command_line_pcb = argv[1];
commit 480e81559af88dacbfb6bd94cd5fb705ec4f7cb4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
When built with less than all of the graphic formats that
the png exporter supports, don't segfault anymore. The problem
is an array is defined differently at compile time but the
default value for the format was constant and a ways into the
array. Problem reported by jean on irc.
diff --git a/src/hid/png/png.c b/src/hid/png/png.c
index 404eb53..ba7e763 100644
--- a/src/hid/png/png.c
+++ b/src/hid/png/png.c
@@ -124,6 +124,10 @@ static int photo_groups[MAX_LAYER+2], photo_ngroups;
#define FMT_png "PNG"
static const char *filetypes[] = {
+#ifdef HAVE_GDIMAGEPNG
+ FMT_png,
+#endif
+
#ifdef HAVE_GDIMAGEGIF
FMT_gif,
#endif
@@ -132,10 +136,6 @@ static const char *filetypes[] = {
FMT_jpg,
#endif
-#ifdef HAVE_GDIMAGEPNG
- FMT_png,
-#endif
-
NULL
};
@@ -178,7 +178,7 @@ HID_Attribute png_attribute_list[] = {
#define HA_use_alpha 8
{"format", "Graphics file format",
- HID_Enum, 0, 0, {2, 0, 0}, filetypes, 0},
+ HID_Enum, 0, 0, {0, 0, 0}, filetypes, 0},
#define HA_filetype 9
{"png-bloat", "Amount (in/mm/mil/pix) to add to trace/pad/pin edges (1 = 1/100 mil)",
@@ -221,7 +221,6 @@ static const char *get_file_suffix(void)
const char *fmt;
const char *result;
fmt = filetypes[png_attribute_list[HA_filetype].default_val.int_value];
- /* or is it filetypes[png_attribute_list[HA_filetype].default_val.int_value]; ? */
if (strcmp (fmt, FMT_gif) == 0) result=".gif";
else if (strcmp (fmt, FMT_jpg) == 0) result=".jpg";
else if (strcmp (fmt, FMT_png) == 0) result=".png";
commit e85f5eea45e6db6245dd960916cd544e844e5cab
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Inform the user where (what file or compiled in defaults) the
menu config came from. Should help with some of the gpcb-menu.res
versus pcb-menu.res and the ./gpcb-menu.res versus ~/.pcb/gpcb-menu.res
confusion which comes up from time to time.
diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index eb8ba18..a594330 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -3756,7 +3756,10 @@ ghid_load_menus (void)
}
if (filename)
- r = resource_parse (filename, 0);
+ {
+ Message ("Loading menus from %s\n", filename);
+ r = resource_parse (filename, 0);
+ }
if (home_pcbmenu != NULL)
{
@@ -3764,7 +3767,10 @@ ghid_load_menus (void)
}
if (!r)
- r = bir;
+ {
+ Message ("Using default menus\n");
+ r = bir;
+ }
mr = resource_subres (r, "MainMenu");
if (!mr)
commit 050e6e6fea127f611ee0db11ef162c2dd27fb3d6
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Return non-fail for ReportAllNetLengths()
diff --git a/src/report.c b/src/report.c
index 08613dd..2e80e66 100644
--- a/src/report.c
+++ b/src/report.c
@@ -677,6 +677,7 @@ ReportAllNetLengths (int argc, char **argv, int x, int y)
break;
}
}
+ return 0;
}
static int
commit ed9779ba20a26180b1e30a2f37c5ba1a5039c673
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Record the calculated length in Report(NetLength)
diff --git a/src/report.c b/src/report.c
index 974c0be..08613dd 100644
--- a/src/report.c
+++ b/src/report.c
@@ -693,7 +693,7 @@ ReportNetLength (int argc, char **argv, int x, int y)
RestoreUndoSerialNumber ();
gui->get_coords ("Click on a connection", &x, &y);
- XYtoNetLength (x, y, &found);
+ length = XYtoNetLength (x, y, &found);
if (!found)
{
commit d9e4279e4c0af142bc776bdd4a3b905388ce6b5a
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add checklist item to update the web site for a new release news
item.
diff --git a/README.snapshots b/README.snapshots
index 9a4582e..ca516e8 100644
--- a/README.snapshots
+++ b/README.snapshots
@@ -162,3 +162,5 @@ To make a pcb release do the following:
=) gmake distclean ; ./autogen.sh &&./configure && gmake distcheck
+=) Update the web pages. In particular, update news.shtml and index.shtml
+ and then rebuild the corresponding .html files.
commit 6081daa8966c8c83bb734789c38dd5c42dd97443
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: line constraints
diff --git a/src/toporouter.c b/src/toporouter.c
index f749d22..50195d3 100644
--- a/src/toporouter.c
+++ b/src/toporouter.c
@@ -2195,11 +2195,13 @@ read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln)
if(!(xs[0] == xs[1] && ys[0] == ys[1])) {
vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, xs[0], ys[0], l - r->layers));
vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, xs[1], ys[1], l - r->layers));
+ // TODO: replace this with surface version
bbox = toporouter_bbox_create_from_points(GetLayerGroupNumberByNumber(ln), vlist, LINE, line);
r->bboxes = g_slist_prepend(r->bboxes, bbox);
//new;;
//insert_constraints_from_list(r, l, vlist, bbox);
g_list_free(vlist);
+// bbox->point = GTS_POINT( insert_vertex(r, l, (xs[0]+xs[1])/2., (ys[0]+ys[1])/2., bbox) );
bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, xs[0], ys[0], 0, xs[1], ys[1], 0, bbox));
}
@@ -2296,7 +2298,26 @@ print_edge(toporouter_edge_t *e)
print_vertex(tedge_v2(e));
}
+static void pick_first_face (GtsFace * f, GtsFace ** first)
+{
+ if (*first == NULL)
+ *first = f;
+}
+
+void
+unconstrain(toporouter_layer_t *l, toporouter_constraint_t *c)
+{
+ toporouter_edge_t *e;
+ gts_allow_floating_vertices = TRUE;
+ e = TOPOROUTER_EDGE(gts_edge_new (GTS_EDGE_CLASS (toporouter_edge_class ()), GTS_SEGMENT(c)->v1, GTS_SEGMENT(c)->v2));
+ gts_edge_replace(GTS_EDGE(c), GTS_EDGE(e));
+ l->constraints = g_list_remove(l->constraints, c);
+ c->box->constraints = g_list_remove(c->box->constraints, c);
+ c->box = NULL;
+ gts_object_destroy (GTS_OBJECT (c));
+ gts_allow_floating_vertices = FALSE;
+}
void
build_cdt(toporouter_t *r, toporouter_layer_t *l)
@@ -2307,16 +2328,14 @@ build_cdt(toporouter_t *r, toporouter_layer_t *l)
//GtsVertex *v;
GtsTriangle *t;
GtsVertex *v1, *v2, *v3;
- GtsFace *topface = NULL;
GSList *vertices_slist;
- guint rerun;
-build_cdt_continuation:
vertices_slist = list_to_slist(l->vertices);
- rerun =0;
- if(l->surface && topface) {
- gts_surface_traverse_destroy (gts_surface_traverse_new (l->surface, topface));
+ if(l->surface) {
+ GtsFace * first = NULL;
+ gts_surface_foreach_face (l->surface, (GtsFunc) pick_first_face, &first);
+ gts_surface_traverse_destroy(gts_surface_traverse_new (l->surface, first));
}
t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 1000.0f);
@@ -2327,21 +2346,8 @@ build_cdt_continuation:
l->surface = gts_surface_new (gts_surface_class (), gts_face_class (),
GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
- topface = gts_face_new (gts_face_class (), t->e1, t->e2, t->e3);
- gts_surface_add_face (l->surface, topface);
-
- i = l->vertices;
- while (i) {
- //v = i->data;
- //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
- // fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y);
- toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, i->data, NULL));
- if(v) {
- printf("conflict: "); print_vertex(v);
- }
+ gts_surface_add_face (l->surface, gts_face_new (gts_face_class (), t->e1, t->e2, t->e3));
- i = i->next;
- }
// fprintf(stderr, "ADDED VERTICES\n");
/*
@@ -2380,180 +2386,209 @@ build_cdt_continuation:
}
*/
+check_cons_continuation:
i = l->constraints;
- while (i) {
-
+ while (i) {
toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
- //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
-/* fprintf(r->debug, "edge p1=%f,%f p2=%f,%f\n",
- temp->segment.v1->p.x,
- temp->segment.v1->p.y,
- temp->segment.v2->p.x,
- temp->segment.v2->p.y);
-*/
- GSList *conflicts = gts_delaunay_add_constraint (l->surface, i->data);
- GSList *j = conflicts;
+ GList *j = i->next;
+ // printf("adding cons: "); print_constraint(c1);
+
while(j) {
- if(TOPOROUTER_IS_CONSTRAINT(j->data)) {
- toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
- GList *temp, *newcons = NULL;
-
- printf("conflict: "); print_constraint(c2);
- printf("with: "); print_constraint(c1);
-
- gts_allow_floating_vertices = TRUE;
- l->constraints = g_list_remove(l->constraints, c1);
- l->constraints = g_list_remove(l->constraints, c2);
- c1->box->constraints = g_list_remove(c1->box->constraints, c1);
- c2->box->constraints = g_list_remove(c2->box->constraints, c2);
-
- if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) {
- // proper intersection
- toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertex_intersect(edge_v1(c1), edge_v2(c1), edge_v1(c2), edge_v2(c2)));
- // remove both constraints
- // replace with 4x constraints
- // insert new intersection vertex
- GTS_POINT(v)->z = vz(edge_v1(c1));
-
- l->vertices = g_list_prepend(l->vertices, v);
-
- v->bbox = c1->box;
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(v), vy(v), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(v), vy(v), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(v), vy(v), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(v), vy(v), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- }else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
- printf("all colinear\n");
- exit(1);
- }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
+ toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
+ guint rem = 0;
+ GList *temp;
+
+ // printf("\tconflict: "); print_constraint(c2);
+ toporouter_bbox_t *c1box = c1->box, *c2box = c2->box;
+ toporouter_vertex_t *c1v1 = tedge_v1(c1);
+ toporouter_vertex_t *c1v2 = tedge_v2(c1);
+ toporouter_vertex_t *c2v1 = tedge_v1(c2);
+ toporouter_vertex_t *c2v2 = tedge_v2(c2);
+
+ if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
+ // proper intersection
+ toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertex_intersect(
+ GTS_VERTEX(c1v1),
+ GTS_VERTEX(c1v2),
+ GTS_VERTEX(c2v1),
+ GTS_VERTEX(c2v2)));
+
+ // remove both constraints
+ // replace with 4x constraints
+ // insert new intersection vertex
+ GTS_POINT(v)->z = vz(c1v1);
+
+ l->vertices = g_list_prepend(l->vertices, v);
+// gts_delaunay_add_vertex (l->surface, GTS_VERTEX(v), NULL);
+
+ v->bbox = c1box;
+
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(v), vy(v), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(v), vy(v), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(v), vy(v), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(v), vy(v), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+
+ }else if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_ON ||
+ gts_segments_are_intersecting(GTS_SEGMENT(c2), GTS_SEGMENT(c1)) == GTS_ON) {
+
+ if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
// remove c1
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
}else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
// remove c2
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
- /*
-
- }else {
- exit(1);
- if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
- toporouter_constraint_t *tempc = c1;
- c1 = c2;
- c2 = tempc;
- }
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
-
- if(tvdistance2(edge_v1(c1), edge_v2(c2)) < tvdistance2(edge_v2(c1), edge_v2(c2))) {
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- }else{
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- }
- */
- }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1))) {
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ //}else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ /* }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) || vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
+ printf("all colinear\n");
+ // exit(1);
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ if(vertex_between(GTS_VERTEX(c1v1), GTS_VERTEX(c1v2), GTS_VERTEX(c2v2))) {
+ // v2 of c2 is inner
+ if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
+ // v2 of c1 is inner
+ // c2 = c1.v2 -> c2.v1
+ temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ }else{
+ // v1 of c1 is inner
+ // c2 = c1.v1 -> c2.v1
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ }
+ }else{
+ // v1 of c2 is inner
+ if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
+ // v2 of c1 is inner
+ // c2 = c1.v2 -> c2.v2
+ temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ }else{
+ // v1 of c1 is inner
+ // c2 = c1.v1 -> c2.v2
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ }
+ }*/
+ }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && c1v1 != c2v1 && c1v1 != c2v2) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
//v1 of c1 is on c2
printf("v1 of c1 on c2\n");
// replace with 2x constraints
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v1), vy(c1v1), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v1), vy(c1v1), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
// restore c1
//temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c1->box);
//c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
+ }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1)) && c1v2 != c2v1 && c1v2 != c2v2) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
//v2 of c1 is on c2
printf("v2 of c1 on c2\n");
// replace with 2x constraints
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
- }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2))) {
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v2), vy(c1v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v2), vy(c1v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && c2v1 != c1v1 && c2v1 != c1v2) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
//v1 of c2 is on c1
printf("v1 of c2 on c1\n");
// replace with 2x constraints
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
- }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
+ }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2)) && c2v2 != c1v1 && c2v2 != c1v2) {
+ unconstrain(l, c1); unconstrain(l, c2);
+ rem = 1;
//v2 of c2 is on c1
printf("v2 of c2 on c1\n");
// replace with 2x constraints
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
- temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c1->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c1->box->constraints = g_list_concat(c1->box->constraints, temp);
-
- temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
- newcons = g_list_concat(newcons, g_list_copy(temp));
- c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c1box);
+ c1box->constraints = g_list_concat(c1box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
+ c2box->constraints = g_list_concat(c2box->constraints, temp);
}
- gts_object_destroy (GTS_OBJECT (c1));
- gts_object_destroy (GTS_OBJECT (c2));
+ }
+ if(rem) goto check_cons_continuation;
- gts_allow_floating_vertices = FALSE;
-/*
- {
- GList *k = newcons;
+ j = j->next;
+ }
- while(k) {
- if(gts_delaunay_add_constraint (l->surface, k->data) || gts_delaunay_add_constraint (l->surface, k->data)) {
- printf("ERROR INSERTING NEWCONS\n");
- }
- k = k->next;
- }
- g_list_free(newcons);
- }
-*/
- goto build_cdt_continuation;
- // rerun = 1;
+ i = i->next;
+ }
+
+ i = l->vertices;
+ while (i) {
+ //v = i->data;
+ //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
+ // fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y);
+ toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, i->data, NULL));
+ if(v) {
+ printf("conflict: "); print_vertex(v);
+ }
+
+ i = i->next;
+ }
+ i = l->constraints;
+ while (i) {
+
+ toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
+
+ // printf("adding cons: "); print_constraint(c1);
+
+ GSList *conflicts = gts_delaunay_add_constraint (l->surface, i->data);
+ GSList *j = conflicts;
+ while(j) {
+ if(TOPOROUTER_IS_CONSTRAINT(j->data)) {
+ toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
+
+ printf("\tconflict: "); print_constraint(c2);
+
}
j = j->next;
}
@@ -2587,6 +2622,14 @@ build_cdt_continuation:
#ifdef DEBUG_IMPORT
gts_surface_print_stats(l->surface, stderr);
#endif
+
+ {
+ char buffer[64];
+ sprintf(buffer, "surface%d.gts", l - r->layers);
+ FILE *fout2 = fopen(buffer, "w");
+ gts_surface_write(l->surface, fout2);
+ }
+
}
gint
@@ -2940,7 +2983,7 @@ compare_segments(gconstpointer a, gconstpointer b)
if(a < b) return -1;
return 1;
}
-
+#define DEBUG_CLUSTER_FIND 1
toporouter_cluster_t *
cluster_find(toporouter_t *r, gdouble x, gdouble y, gdouble z)
{
@@ -2965,9 +3008,19 @@ cluster_find(toporouter_t *r, gdouble x, gdouble y, gdouble z)
LineType *line = (LineType *)box->data;
gint linewind = coord_wind(line->Point1.X, line->Point1.Y, x, y, line->Point2.X, line->Point2.Y);
+ if(line->Point1.X > x - EPSILON && line->Point1.X < x + EPSILON &&
+ line->Point1.Y > y - EPSILON && line->Point1.Y < y + EPSILON) {
+ rval = box->cluster;
+ // break;
+ }
+ if(line->Point2.X > x - EPSILON && line->Point2.X < x + EPSILON &&
+ line->Point2.Y > y - EPSILON && line->Point2.Y < y + EPSILON) {
+ rval = box->cluster;
+ // break;
+ }
if(!linewind) {
rval = box->cluster;
- //break;
+ // break;
}
}else if(box->surface) {
@@ -7008,7 +7061,7 @@ netscore_create(toporouter_t *r, toporouter_route_t *routedata, guint n, guint i
printf("WARNING: !finite(detourscore)\n");
print_cluster(routedata->src);
print_cluster(routedata->dest);
-
+ return NULL;
}
netscore->pairwise_nodetour = malloc(n * sizeof(guint));
@@ -7141,7 +7194,8 @@ order_nets_preroute_greedy(toporouter_t *r, GList *nets, GList **rnets)
guint failcount = 0;
while(nets) {
- g_ptr_array_add(netscores, netscore_create(r, TOPOROUTER_ROUTE(nets->data), len, failcount++));
+ toporouter_netscore_t *ns = netscore_create(r, TOPOROUTER_ROUTE(nets->data), len, failcount++);
+ if(ns) g_ptr_array_add(netscores, ns);
nets = nets->next;
}
commit 2a406dec9df0eecf9923a19971363fa39b481e04
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Fix Typo
diff --git a/src/hid/lesstif/menu.c b/src/hid/lesstif/menu.c
index 9869483..44edaba 100644
--- a/src/hid/lesstif/menu.c
+++ b/src/hid/lesstif/menu.c
@@ -853,7 +853,7 @@ lesstif_call_action (const char *aname, int argc, char **argv)
old_action = current_action;
current_action = a;
- ret = current_action->trigger_cb (argc, argv, x, y);
+ ret = current_action->trigger_cb (argc, argv, px, py);
current_action = old_action;
return ret;
commit 607c3056963b68654bac3fae70ac3d02eee60eaf
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: Speccut bug fix
diff --git a/src/toporouter.c b/src/toporouter.c
index 7a40005..f749d22 100644
--- a/src/toporouter.c
+++ b/src/toporouter.c
@@ -6463,6 +6463,7 @@ opposite_triangle(GtsTriangle *t, toporouter_edge_t *e)
void
speccut_edge_routing_from_edge(GList *i, toporouter_edge_t *e)
{
+ g_assert(TOPOROUTER_IS_EDGE(e));
while(i) {
toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
@@ -6545,6 +6546,7 @@ void
speccut_edge_patch_links(toporouter_edge_t *e)
{
GList *i = e->routing;
+ g_assert(TOPOROUTER_IS_EDGE(e));
while(i) {
toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
v->parent->child = v;
@@ -6563,14 +6565,13 @@ check_speccut(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter
if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
-
if(!(t = gts_triangle_use_edges(GTS_EDGE(e), GTS_EDGE(e1), GTS_EDGE(e2)))) {
printf("check_speccut: NULL t\n");
return 0;
}
if(!(opt = opposite_triangle(t, e))) {
- printf("check_speccut: NULL opt\n");
+// printf("check_speccut: NULL opt\n");
return 0;
}
@@ -6598,6 +6599,10 @@ check_speccut(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter
ope1 = tedge(opv2, tedge_v1(e));
ope2 = tedge(opv2, tedge_v2(e));
+ //this fixes the weird pad exits in r8c board
+// if(TOPOROUTER_IS_CONSTRAINT(ope1)) return 0;
+ if(TOPOROUTER_IS_CONSTRAINT(ope2)) return 0;
+
if(!tvertex_wind(opv2, tedge_v1(e), opv)) return 0;
if(!tvertex_wind(opv2, tedge_v2(e), opv)) return 0;
@@ -7883,9 +7888,9 @@ toporouter (int argc, char **argv, int x, int y)
hybrid_router(r);
/*
-// for(gint i=0;i<groupcount();i++) {
-// gts_surface_foreach_edge(r->layers[i].surface, space_edge, NULL);
-// }
+ for(gint i=0;i<groupcount();i++) {
+ gts_surface_foreach_edge(r->layers[i].surface, space_edge, NULL);
+ }
{
int i;
for(i=0;i<groupcount();i++) {
commit 1ee723379413c20973bdad27b1e1cf1d722cf3d1
Author: anthonix <anthonix@anthonix-desktop.(none)>
Commit: anthonix <anthonix@anthonix-desktop.(none)>
Toporouter: line constraints
diff --git a/src/toporouter.c b/src/toporouter.c
index a02f628..83eb65e 100644
--- a/src/toporouter.c
+++ b/src/toporouter.c
@@ -1753,7 +1753,8 @@ insert_vertex(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y, topo
}
GList *
-insert_constraint_edge(toporouter_t *r, toporouter_layer_t *l, gdouble x1, gdouble y1, guint flags1, gdouble x2, gdouble y2, guint flags2, toporouter_bbox_t *box)
+insert_constraint_edge(toporouter_t *r, toporouter_layer_t *l, gdouble x1, gdouble y1, guint flags1,
+ gdouble x2, gdouble y2, guint flags2, toporouter_bbox_t *box)
{
GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
GtsEdgeClass *edge_class = GTS_EDGE_CLASS (toporouter_constraint_class ());
@@ -2196,6 +2197,8 @@ read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln)
vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, xs[1], ys[1], l - r->layers));
bbox = toporouter_bbox_create_from_points(GetLayerGroupNumberByNumber(ln), vlist, LINE, line);
r->bboxes = g_slist_prepend(r->bboxes, bbox);
+ //new;;
+ //insert_constraints_from_list(r, l, vlist, bbox);
g_list_free(vlist);
bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, xs[0], ys[0], 0, xs[1], ys[1], 0, bbox));
@@ -2206,8 +2209,6 @@ read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln)
return 0;
}
-
-
void
create_board_edge(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble max, gint layer, GList **vlist)
{
@@ -2270,6 +2271,31 @@ triangle_cost(GtsTriangle *t, gpointer *data){
}
+void
+print_constraint(toporouter_constraint_t *e)
+{
+ printf("CONSTRAINT:\n");
+ print_vertex(tedge_v1(e));
+ print_vertex(tedge_v2(e));
+}
+
+void
+print_edge(toporouter_edge_t *e)
+{
+ GList *i = edge_routing(e);
+
+ printf("EDGE:\n");
+
+ print_vertex(tedge_v1(e));
+
+ while(i) {
+ toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
+ print_vertex(v);
+ i = i->next;
+ }
+
+ print_vertex(tedge_v2(e));
+}
void
@@ -2277,34 +2303,50 @@ build_cdt(toporouter_t *r, toporouter_layer_t *l)
{
/* TODO: generalize into surface *cdt_create(vertices, constraints) */
GList *i;
- GtsEdge *temp;
- GtsVertex *v;
+ //GtsEdge *temp;
+ //GtsVertex *v;
GtsTriangle *t;
GtsVertex *v1, *v2, *v3;
- GSList *vertices_slist = list_to_slist(l->vertices);
+ GtsFace *topface = NULL;
+ GSList *vertices_slist;
+ guint rerun;
+build_cdt_continuation:
+ vertices_slist = list_to_slist(l->vertices);
+ rerun =0;
+ if(l->surface && topface) {
+ gts_surface_traverse_destroy (gts_surface_traverse_new (l->surface, topface));
+ }
+
t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 1000.0f);
gts_triangle_vertices (t, &v1, &v2, &v3);
g_slist_free(vertices_slist);
-
+
l->surface = gts_surface_new (gts_surface_class (), gts_face_class (),
GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
- gts_surface_add_face (l->surface, gts_face_new (gts_face_class (), t->e1, t->e2, t->e3));
+ topface = gts_face_new (gts_face_class (), t->e1, t->e2, t->e3);
+ gts_surface_add_face (l->surface, topface);
i = l->vertices;
while (i) {
- v = i->data;
+ //v = i->data;
//if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
// fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y);
- g_assert (gts_delaunay_add_vertex (l->surface, i->data, NULL) == NULL);
+ toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, i->data, NULL));
+ if(v) {
+ printf("conflict: "); print_vertex(v);
+ }
+
i = i->next;
}
// fprintf(stderr, "ADDED VERTICES\n");
/*
+ GtsFace *debugface;
+
if((debugface = gts_delaunay_check(l->surface))) {
fprintf(stderr, "WARNING: Delaunay check failed\n");
fprintf(stderr, "\tViolating triangle:\n");
@@ -2326,19 +2368,22 @@ build_cdt(toporouter_t *r, toporouter_layer_t *l)
debugface->triangle.e3->segment.v2->p.x,
debugface->triangle.e3->segment.v2->p.y
);
- if((f=fopen("fail.oogl", "w")) == NULL) {
- fprintf(stderr, "Error opening file fail.oogl for output\n");
- }else{
- gts_surface_write_oogl(l->surface, f);
- fclose(f);
+// toporouter_draw_surface(r, l->surface, "debug.png", 4096, 4096);
+ {
+ int i;
+ for(i=0;i<groupcount();i++) {
+ char buffer[256];
+ sprintf(buffer, "debug-%d.png", i);
+ toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
}
- toporouter_draw_surface(l->surface, "debug.png", 4096, 4096);
+ }
}
*/
i = l->constraints;
while (i) {
- temp = i->data;
+
+ toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
//if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
/* fprintf(r->debug, "edge p1=%f,%f p2=%f,%f\n",
temp->segment.v1->p.x,
@@ -2346,15 +2391,186 @@ build_cdt(toporouter_t *r, toporouter_layer_t *l)
temp->segment.v2->p.x,
temp->segment.v2->p.y);
*/
- g_assert (gts_delaunay_add_constraint (l->surface, i->data) == NULL);
+ GSList *conflicts = gts_delaunay_add_constraint (l->surface, i->data);
+ GSList *j = conflicts;
+ while(j) {
+ if(TOPOROUTER_IS_CONSTRAINT(j->data)) {
+ toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
+ GList *temp, *newcons = NULL;
+
+ printf("conflict: "); print_constraint(c2);
+ printf("with: "); print_constraint(c1);
+
+ gts_allow_floating_vertices = TRUE;
+ l->constraints = g_list_remove(l->constraints, c1);
+ l->constraints = g_list_remove(l->constraints, c2);
+ c1->box->constraints = g_list_remove(c1->box->constraints, c1);
+ c2->box->constraints = g_list_remove(c2->box->constraints, c2);
+
+ if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) {
+ // proper intersection
+ toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertex_intersect(edge_v1(c1), edge_v2(c1), edge_v1(c2), edge_v2(c2)));
+ // remove both constraints
+ // replace with 4x constraints
+ // insert new intersection vertex
+ GTS_POINT(v)->z = vz(edge_v1(c1));
+
+ l->vertices = g_list_prepend(l->vertices, v);
+
+ v->bbox = c1->box;
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(v), vy(v), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(v), vy(v), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(v), vy(v), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(v), vy(v), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ }else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ printf("all colinear\n");
+ exit(1);
+ }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
+ // remove c1
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+
+ }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ // remove c2
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+ /*
+
+ }else {
+ exit(1);
+ if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ toporouter_constraint_t *tempc = c1;
+ c1 = c2;
+ c2 = tempc;
+ }
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ if(tvdistance2(edge_v1(c1), edge_v2(c2)) < tvdistance2(edge_v2(c1), edge_v2(c2))) {
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ }else{
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ }
+ */
+ }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1))) {
+ //v1 of c1 is on c2
+ printf("v1 of c1 on c2\n");
+
+ // replace with 2x constraints
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ // restore c1
+ //temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c1->box);
+ //c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+
+ }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
+ //v2 of c1 is on c2
+ printf("v2 of c1 on c2\n");
+
+ // replace with 2x constraints
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+ }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2))) {
+ //v1 of c2 is on c1
+ printf("v1 of c2 on c1\n");
+
+ // replace with 2x constraints
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
+ //v2 of c2 is on c1
+ printf("v2 of c2 on c1\n");
+
+ // replace with 2x constraints
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+ temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c1->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c1->box->constraints = g_list_concat(c1->box->constraints, temp);
+
+ temp = insert_constraint_edge(r, l, vx(tedge_v1(c2)), vy(tedge_v1(c2)), 0, vx(tedge_v2(c2)), vy(tedge_v2(c2)), 0, c2->box);
+ newcons = g_list_concat(newcons, g_list_copy(temp));
+ c2->box->constraints = g_list_concat(c2->box->constraints, temp);
+ }
+ gts_object_destroy (GTS_OBJECT (c1));
+ gts_object_destroy (GTS_OBJECT (c2));
+
+ gts_allow_floating_vertices = FALSE;
+/*
+ {
+ GList *k = newcons;
+
+ while(k) {
+ if(gts_delaunay_add_constraint (l->surface, k->data) || gts_delaunay_add_constraint (l->surface, k->data)) {
+ printf("ERROR INSERTING NEWCONS\n");
+ }
+ k = k->next;
+ }
+ g_list_free(newcons);
+ }
+*/
+ goto build_cdt_continuation;
+ // rerun = 1;
+ }
+ j = j->next;
+ }
+ g_slist_free(conflicts);
+
i = i->next;
}
+
+// if(rerun)
+// goto build_cdt_continuation;
// fprintf(stderr, "ADDED CONSTRAINTS\n");
gts_allow_floating_vertices = TRUE;
gts_object_destroy (GTS_OBJECT (v1));
gts_object_destroy (GTS_OBJECT (v2));
gts_object_destroy (GTS_OBJECT (v3));
gts_allow_floating_vertices = FALSE;
+
/*
{
gpointer data[2];
@@ -2676,6 +2892,15 @@ import_geometry(toporouter_t *r)
printf("building CDT\n");
#endif
build_cdt(r, cur_layer);
+ printf("finished\n");
+/* {
+ int i;
+ for(i=0;i<groupcount();i++) {
+ char buffer[256];
+ sprintf(buffer, "build%d.png", i);
+ toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
+ }
+ }*/
#ifdef DEBUG_IMPORT
printf("finished building CDT\n");
#endif
@@ -2978,23 +3203,6 @@ routing_edge_insert(gconstpointer a, gconstpointer b, gpointer user_data)
return 0;
}
-void
-print_edge(toporouter_edge_t *e)
-{
- GList *i = edge_routing(e);
-
- printf("EDGE:\n");
-
- print_vertex(tedge_v1(e));
-
- while(i) {
- toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
- print_vertex(v);
- i = i->next;
- }
-
- print_vertex(tedge_v2(e));
-}
toporouter_vertex_t *
new_temp_toporoutervertex(gdouble x, gdouble y, toporouter_edge_t *e)
@@ -4210,7 +4418,7 @@ compute_candidate_points(toporouter_t *tr, toporouter_layer_t *l, toporouter_ver
compute_candidate_points_finish:
- if(vertex_bbox(curpoint)) {
+ if(vertex_bbox(curpoint) && vertex_bbox(curpoint)->cluster) {
if(vertex_bbox(curpoint)->cluster->c == data->src->c) {
r = g_list_concat(r, g_list_copy(data->srcvertices));
}
@@ -4246,15 +4454,18 @@ path_score(toporouter_t *r, GList *path)
{
gdouble score = 0.;
toporouter_vertex_t *pv = NULL;
+ toporouter_vertex_t *v0 = NULL;
if(!path) return INFINITY;
+ v0 = TOPOROUTER_VERTEX(path->data);
+
while(path) {
toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data);
if(pv) {
score += gts_point_distance(GTS_POINT(pv), GTS_POINT(v));
- if(vz(pv) != vz(v))
+ if(pv != v0 && vz(pv) != vz(v))
if(path->next)
score += r->viacost;
diff --git a/src/toporouter.h b/src/toporouter.h
index 37c9ac7..0e98115 100644
--- a/src/toporouter.h
+++ b/src/toporouter.h
@@ -100,8 +100,10 @@
#define tev1x(e) (vx(tedge_v1(e))
#define tev1y(e) (vy(tedge_v1(e))
+#define tev1z(e) (vz(tedge_v1(e))
#define tev2x(e) (vx(tedge_v2(e))
#define tev2y(e) (vy(tedge_v2(e))
+#define tev2z(e) (vz(tedge_v2(e))
#define tvertex_intersect(a,b,c,d) (TOPOROUTER_VERTEX(vertex_intersect(GTS_VERTEX(a),GTS_VERTEX(b),GTS_VERTEX(c),GTS_VERTEX(d))))
commit e45f4e8d15f2c30f8ccb37de5b0bfa801fca572c
Author: Anthony M. Blake <anthonix@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Commit: Anthony M. Blake <anthonix@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Toporouter: fixed a few AMD64 warnings
diff --git a/src/toporouter.c b/src/toporouter.c
index a02f628..ff6d804 100644
--- a/src/toporouter.c
+++ b/src/toporouter.c
@@ -2798,14 +2798,14 @@ toporouter_heap_search(gpointer data, gpointer user_data)
toporouter_heap_search_data_t *heap_search_data = (toporouter_heap_search_data_t *)user_data;
if(v == heap_search_data->key) heap_search_data->result = v;
}
-
+/*
void
toporouter_heap_color(gpointer data, gpointer user_data)
{
toporouter_vertex_t *v = TOPOROUTER_VERTEX(data);
- v->flags |= (unsigned int) user_data;
+ v->flags |= (guint) user_data;
}
-
+*/
inline gdouble
angle_span(gdouble a1, gdouble a2)
{
@@ -6095,7 +6095,7 @@ oproute_rubberband_segment(toporouter_t *r, toporouter_oproute_t *oproute, GList
}
arcs = g_list_sort(arcs, (GCompareFunc) compare_rubberband_arcs);
-rubberband_insert_maxarc:
+//rubberband_insert_maxarc:
if(!arcs) return NULL;
max = TOPOROUTER_RUBBERBAND_ARC(arcs->data);
@@ -6828,8 +6828,11 @@ print_netscores(GPtrArray* netscores)
printf(" %15s %15s %15s\n----------------------------------------------------\n", "Score", "Detour Sum", "Pairwise Fails");
for(toporouter_netscore_t **i = (toporouter_netscore_t **) netscores->pdata; i < (toporouter_netscore_t **) netscores->pdata + netscores->len; i++) {
- printf("%4d %15f %15f %15d %15x\n", (*i)->id, (*i)->score, (*i)->pairwise_detour_sum, (*i)->pairwise_fails, (unsigned int)*i);
+#ifdef DEBUG_NETSCORES
+ printf("%4d %15f %15f %15d %15x\n", (*i)->id, (*i)->score, (*i)->pairwise_detour_sum, (*i)->pairwise_fails, (guint)*i);
+#endif
}
+
printf("\n");
}
commit b89fa5b38ebf2c7d59a2bdd3385878fffe117f26
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Missed the copyright bump when adding the gcode compare routines a
few weeks back.
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 44bdcc7..e9a4ac2 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -2,7 +2,7 @@
#
# $Id: run_tests.sh,v 1.8 2009/02/17 00:42:31 danmc Exp $
#
-# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2009 Dan McMahill
+# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Dan McMahill
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
commit 86055f4273cae0c00d55b30f4bd610052ca350a4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add tests for --outfile and --dpi arguments to the PNG exporter
diff --git a/configure.ac b/configure.ac
index f0e19bd..4e9476d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1167,6 +1167,8 @@ AC_CONFIG_FILES(tests/golden/hid_gcode11/Makefile)
AC_CONFIG_FILES(tests/golden/hid_gerber1/Makefile)
AC_CONFIG_FILES(tests/golden/hid_gerber2/Makefile)
AC_CONFIG_FILES(tests/golden/hid_png1/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_png2/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_png3/Makefile)
AC_CONFIG_FILES(tests/Makefile)
dnl win32 build scripts
diff --git a/tests/golden/Makefile.am b/tests/golden/Makefile.am
index de5bb08..515419e 100644
--- a/tests/golden/Makefile.am
+++ b/tests/golden/Makefile.am
@@ -18,4 +18,6 @@ SUBDIRS= \
hid_gcode11 \
hid_gerber1 \
hid_gerber2 \
- hid_png1
+ hid_png1 \
+ hid_png2 \
+ hid_png3
diff --git a/tests/golden/hid_png2/Makefile.am b/tests/golden/hid_png2/Makefile.am
new file mode 100644
index 0000000..f0387c4
--- /dev/null
+++ b/tests/golden/hid_png2/Makefile.am
@@ -0,0 +1,4 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ myfile.png
diff --git a/tests/golden/hid_png2/myfile.png b/tests/golden/hid_png2/myfile.png
new file mode 100644
index 0000000..be346ad
Binary files /dev/null and b/tests/golden/hid_png2/myfile.png differ
diff --git a/tests/golden/hid_png3/Makefile.am b/tests/golden/hid_png3/Makefile.am
new file mode 100644
index 0000000..8ef143b
--- /dev/null
+++ b/tests/golden/hid_png3/Makefile.am
@@ -0,0 +1,4 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gerber_oneline.png
diff --git a/tests/golden/hid_png3/gerber_oneline.png b/tests/golden/hid_png3/gerber_oneline.png
new file mode 100644
index 0000000..3b30ed3
Binary files /dev/null and b/tests/golden/hid_png3/gerber_oneline.png differ
diff --git a/tests/tests.list b/tests/tests.list
index 95af71d..ac1a11a 100644
--- a/tests/tests.list
+++ b/tests/tests.list
@@ -1,4 +1,4 @@
-# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2009 Dan McMahill
+# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Dan McMahill
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
@@ -159,5 +159,7 @@ hid_gerber2 | gerber_oneline.pcb | gerber | --gerberfile out | | gbx:out.back.gb
# Produces GIF/JPEG/PNG (image) files
#
hid_png1 | gerber_oneline.pcb | png | | | png:gerber_oneline.png
+hid_png2 | gerber_oneline.pcb | png | --outfile myfile.png | | png:myfile.png
+hid_png3 | gerber_oneline.pcb | png | --dpi 300 | | png:gerber_oneline.png
#
commit ee8c65db8257eee155071ec7beab6dabb1a77c86
Author: Kai-Martin Knaak <kmk@xxxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
replaces "pcb.sourceforge.net" with "pcb.gpleda.org"
diff --git a/README b/README
index be006fd..9b9da9a 100644
--- a/README
+++ b/README
@@ -6,9 +6,8 @@ For additional information read the manual (doc/pcb.pdf)
If you are updating you may wish to read the ChangeLog
-There is also a bug tracking system and user forum available
-on the sourceforge project page which can be found from
-http://pcb.sourceforge.net.
+There is also a bug tracking system available which can
+be found from http://pcb.gpleda.org.
-------------------------------------------------------------------------
diff --git a/doc/pcb.texi b/doc/pcb.texi
index 526ad9a..2f4c374 100644
--- a/doc/pcb.texi
+++ b/doc/pcb.texi
@@ -5280,9 +5280,8 @@ Centroid (X-Y) data for driving automated assembly equipment.
@cindex xcircuit, how to interface with
If anyone cares to contribute this section, it will get added. Please
-submit changes to the bug tracking system at the sourceforge project
-page for PCB which can be found from the PCB homepage at
-@url{http://pcb.sourceforge.net}.
+submit changes to the bug tracking system for PCB which can be found from
+the PCB homepage at @url{http://pcb.gpleda.org}.
@c --------------------------- Appendix A -------------------------------
diff --git a/src/main.c b/src/main.c
index 2fe588c..e5d93eb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -237,7 +237,7 @@ usage (void)
n_exporter++;
}
- u ("PCB Printed Circuit Board editing program, http://pcb.sourceforge.net");
+ u ("PCB Printed Circuit Board editing program, http://pcb.gpleda.org");
u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
u ("%s [gui options] <pcb file>\t\tto edit", Progname);
u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
diff --git a/win32/Readme.txt b/win32/Readme.txt
index 7d73a68..93273a4 100644
--- a/win32/Readme.txt
+++ b/win32/Readme.txt
@@ -4,8 +4,7 @@
This is the windows port of the pcb printed circuit board
layout editor.
-Please visit http://pcb.sourceforge.net for more information
-about PCB.
+Please visit http://pcb.gpleda.org for more information about PCB.
The windows port makes use of GTK+ for windows. Please visit
http://www.gtk.org for more information about GTK. Without all the hard
commit 2185dc1f86f7ffc830d950ca821080bc7238e7d6
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Add function to register single action.
The possibility to register a single action has been introduced with
commit 337fa8ba8094cee1ed291cec7bf29895ac7c9d72 but then reverted later
when changing way of passing context to action callback.
diff --git a/src/hid.h b/src/hid.h
index 823e4e3..7b30022 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -86,6 +86,8 @@ extern "C"
const char *syntax;
} HID_Action;
+ extern void hid_register_action (HID_Action *);
+
extern void hid_register_actions (HID_Action *, int);
#define REGISTER_ACTIONS(a) HIDCONCAT(void register_,a) ()\
{ hid_register_actions(a, sizeof(a)/sizeof(a[0])); }
diff --git a/src/hid/common/actions.c b/src/hid/common/actions.c
index 7bc336a..a2ad612 100644
--- a/src/hid/common/actions.c
+++ b/src/hid/common/actions.c
@@ -40,6 +40,12 @@ hid_register_actions (HID_Action * a, int n)
all_actions_sorted = 0;
}
+void
+hid_register_action (HID_Action * a)
+{
+ hid_register_actions (a, 1);
+}
+
static int
action_sort_compar (const void *va, const void *vb)
{
commit 46dab7d5d39aa9f45c59b50862c41c39e51d6f8c
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Modify HID actions storage.
It removes the HID_ActionNode structure and directly store registered
actions in an array of HID_Action*.
It also provides a nicer way of making sure the array is sorted and
the code for binary search within the array has been removed in favor of
a call to bsearch().
diff --git a/src/hid/common/actions.c b/src/hid/common/actions.c
index 04270f1..7bc336a 100644
--- a/src/hid/common/actions.c
+++ b/src/hid/common/actions.c
@@ -21,81 +21,64 @@
RCSID ("$Id$");
-typedef struct HID_ActionNode
-{
- struct HID_ActionNode *next;
- HID_Action *actions;
- int n;
-} HID_ActionNode;
-
-HID_ActionNode *hid_action_nodes = 0;
-static int n_actions = 0;
static HID_Action **all_actions = 0;
+static int all_actions_sorted = 0;
+static int n_actions = 0;
HID_Action *current_action = NULL;
void
hid_register_actions (HID_Action * a, int n)
{
- HID_ActionNode *ha;
-
- /*printf("%d actions registered\n", n); */
- ha = (HID_ActionNode *) malloc (sizeof (HID_ActionNode));
- ha->next = hid_action_nodes;
- hid_action_nodes = ha;
- ha->actions = a;
- ha->n = n;
+ int i;
+
+ all_actions = realloc (all_actions,
+ (n_actions + n) * sizeof (HID_Action*));
+ for (i = 0; i < n; i++)
+ all_actions[n_actions + i] = a + i;
n_actions += n;
- if (all_actions)
- {
- free (all_actions);
- all_actions = 0;
- }
+ all_actions_sorted = 0;
}
static int
-action_sort (const void *va, const void *vb)
+action_sort_compar (const void *va, const void *vb)
{
HID_Action *a = *(HID_Action **) va;
HID_Action *b = *(HID_Action **) vb;
return strcmp (a->name, b->name);
}
+static void
+sort_actions ()
+{
+ qsort (all_actions, n_actions, sizeof (HID_Action*), action_sort_compar);
+ all_actions_sorted = 1;
+}
+
+static int
+action_search_compar (const void *va, const void *vb)
+{
+ char *name = (char*)va;
+ HID_Action *action = *(HID_Action**)vb;
+ return strcmp (name, action->name);
+}
+
HID_Action *
hid_find_action (const char *name)
{
- HID_ActionNode *ha;
- int i, n, lower, upper;
-
+ HID_Action **action;
+ int i;
+
if (name == NULL)
return 0;
- if (all_actions == 0)
- {
- n = 0;
- all_actions = malloc (n_actions * sizeof (HID_Action*));
- for (ha = hid_action_nodes; ha; ha = ha->next)
- for (i = 0; i < ha->n; i++)
- all_actions[n++] = &(ha->actions[i]);
- qsort (all_actions, n_actions, sizeof (HID_Action*), action_sort);
- }
-
+ if (!all_actions_sorted)
+ sort_actions ();
- lower = -1;
- upper = n_actions;
- /*printf("search action %s\n", name); */
- while (lower < upper - 1)
- {
- i = (lower + upper) / 2;
- n = strcmp (all_actions[i]->name, name);
- /*printf("try [%d].%s, cmp %d\n", i, all_actions[i].name, n); */
- if (n == 0)
- return all_actions[i];
- if (n > 0)
- upper = i;
- else
- lower = i;
- }
+ action = bsearch (name, all_actions, n_actions, sizeof (HID_Action*),
+ action_search_compar);
+ if (action)
+ return *action;
for (i = 0; i < n_actions; i++)
if (strcasecmp (all_actions[i]->name, name) == 0)
@@ -109,8 +92,10 @@ void
print_actions ()
{
int i;
- /* Forces them to be sorted in all_actions */
- hid_find_action (hid_action_nodes->actions[0].name);
+
+ if (!all_actions_sorted)
+ sort_actions ();
+
fprintf (stderr, "Registered Actions:\n");
for (i = 0; i < n_actions; i++)
{
@@ -162,8 +147,10 @@ void
dump_actions ()
{
int i;
- /* Forces them to be sorted in all_actions */
- hid_find_action (hid_action_nodes->actions[0].name);
+
+ if (!all_actions_sorted)
+ sort_actions ();
+
for (i = 0; i < n_actions; i++)
{
const char *desc = all_actions[i]->description;
commit 886348e148fdd2951983910c1f39b260831605c3
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Set 'exporter' global variable before
printing defaults.
In print_defaults(), when the HID to print defaults is not a gui, set
'exporter' global variable prior to calling HID's get_export_options()
callback.
diff --git a/src/main.c b/src/main.c
index 3c5ecae..2fe588c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -332,7 +332,9 @@ print_defaults ()
else
{
fprintf (stderr, "\n%s defaults:\n", h->name);
- e = h->get_export_options (&n);
+ exporter = h;
+ e = exporter->get_export_options (&n);
+ exporter = NULL;
if (e)
for (i = 0; i < n; i++)
print_defaults_1 (e + i, 0);
commit d0062d735ba2194a64cc78726c9867e3ffa39460
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Rewrite function that print HID options.
The previous version of usage_hid() had a strange search for gui HID
attributes through 'hid_attr_node' rather than requesting them directly
from the HID.
As a result it was calling the get_export_options() callback on exporter
without prior setting of the exporter global variable.
diff --git a/src/main.c b/src/main.c
index 99dcba1..3c5ecae 100644
--- a/src/main.c
+++ b/src/main.c
@@ -200,33 +200,24 @@ usage_attr (HID_Attribute * a)
static void
usage_hid (HID * h)
{
- HID_Attribute *e;
- int i, n;
+ HID_Attribute *attributes;
+ int i, n_attributes = 0;
if (h->gui)
{
- HID **hl = hid_enumerate ();
- HID_AttrNode *ha;
fprintf (stderr, "\n%s gui options:\n", h->name);
- for (ha = hid_attr_nodes; ha; ha = ha->next)
- {
- for (i = 0; hl[i]; i++)
- if (ha->attributes == hl[i]->get_export_options (0))
- goto skip_this_one;
- for (i = 0; i < ha->n; i++)
- usage_attr (ha->attributes + i);
- skip_this_one:;
- }
- return;
+ attributes = h->get_export_options (&n_attributes);
}
- fprintf (stderr, "\n%s options:\n", h->name);
- exporter = h;
- e = h->get_export_options (&n);
- if (!e)
- return;
- for (i = 0; i < n; i++)
- usage_attr (e + i);
- exporter = NULL;
+ else
+ {
+ fprintf (stderr, "\n%s options:\n", h->name);
+ exporter = h;
+ attributes = exporter->get_export_options (&n_attributes);
+ exporter = NULL;
+ }
+
+ for (i = 0; i < n_attributes; i++)
+ usage_attr (attributes + i);
}
static void
commit 8e8fbf053f12bbd741d4842258e7f7f62f6e1799
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: gtkhid: Avoid use of 'exporter' when testing
for exporter availability.
diff --git a/src/hid/gtk/gui-dialog-print.c b/src/hid/gtk/gui-dialog-print.c
index 1d4fbda..0c50aed 100644
--- a/src/hid/gtk/gui-dialog-print.c
+++ b/src/hid/gtk/gui-dialog-print.c
@@ -367,6 +367,7 @@ ghid_dialog_export (void)
int i;
HID **hids;
GtkTooltips *tips;
+ gboolean no_exporter = TRUE;
tips = gtk_tooltips_new ();
@@ -395,7 +396,7 @@ ghid_dialog_export (void)
{
if (hids[i]->exporter)
{
- exporter = hids[i];
+ no_exporter = FALSE;
button = gtk_button_new_with_label (hids[i]->name);
gtk_tooltips_set_tip (tips, button, hids[i]->description, NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
@@ -404,7 +405,7 @@ ghid_dialog_export (void)
}
}
- if (exporter == NULL)
+ if (no_exporter)
{
gui->log (_("Can't find a suitable exporter HID"));
}
@@ -415,6 +416,4 @@ ghid_dialog_export (void)
if (export_dialog != NULL)
gtk_widget_destroy (export_dialog);
export_dialog = NULL;
-
- exporter = NULL;
}
commit da4b3b720d55aa5cfe9868f56d54cde7d5a02e5f
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: gtkhid: Set and unset global variable
'exporter' when printing.
The GTK hid was not setting the global variable 'exporter' before
exporting the layout in ghid_dialog_print(): exporter HID relying on
this variable being set were lost.
diff --git a/src/hid/gtk/gui-dialog-print.c b/src/hid/gtk/gui-dialog-print.c
index c5c2fff..1d4fbda 100644
--- a/src/hid/gtk/gui-dialog-print.c
+++ b/src/hid/gtk/gui-dialog-print.c
@@ -315,7 +315,7 @@ exporter_clicked_cb (GtkButton * button, HID * exporter)
}
void
-ghid_dialog_print (HID *exporter)
+ghid_dialog_print (HID *hid)
{
HID_Attribute *attr;
int n = 0;
@@ -326,6 +326,8 @@ ghid_dialog_print (HID *exporter)
if (export_dialog)
gtk_dialog_response (GTK_DIALOG (export_dialog), GTK_RESPONSE_CANCEL);
+ exporter = hid;
+
attr = exporter->get_export_options (&n);
if (n > 0)
{
@@ -354,6 +356,7 @@ ghid_dialog_print (HID *exporter)
if (results)
free (results);
+ exporter = NULL;
}
void
commit b1a35c9c9afc64ebfcf2208bc13968a641da4b1a
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Provide context to callbacks of actions
through global variable.
Providing a context to action is necessary for scripting languages (for
example). To do so, a global variable ('current_action') is being
defined: it is saved, set and restored when running the callback of an
action in a way similar to what PCB already does with HIDs.
The callback function may access the action it belongs to and cast it
the way it wants to extract information from a potentially extended
HID_Action structure.
diff --git a/src/hid.h b/src/hid.h
index 067beb0..823e4e3 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -579,6 +579,10 @@ typedef enum
do the exporting. The gui HIDs set and unset this var.*/
extern HID *exporter;
+/* This is either NULL or points to the current HID_Action that is being
+ called. The action launcher sets and unsets this variable. */
+ extern HID_Action *current_action;
+
/* The GUI may set this to be approximately the PCB size of a pixel,
to allow for near-misses in selection and changes in drawing items
smaller than a screen pixel. */
diff --git a/src/hid/common/actions.c b/src/hid/common/actions.c
index 123a2f4..04270f1 100644
--- a/src/hid/common/actions.c
+++ b/src/hid/common/actions.c
@@ -32,6 +32,8 @@ HID_ActionNode *hid_action_nodes = 0;
static int n_actions = 0;
static HID_Action **all_actions = 0;
+HID_Action *current_action = NULL;
+
void
hid_register_actions (HID_Action * a, int n)
{
@@ -200,8 +202,8 @@ hid_actionl (const char *name, ...)
int
hid_actionv (const char *name, int argc, char **argv)
{
- int x = 0, y = 0, i;
- HID_Action *a;
+ int x = 0, y = 0, i, ret;
+ HID_Action *a, *old_action;
if (Settings.verbose && name)
{
@@ -216,7 +218,13 @@ hid_actionv (const char *name, int argc, char **argv)
return 1;
if (a->need_coord_msg)
gui->get_coords (a->need_coord_msg, &x, &y);
- return a->trigger_cb (argc, argv, x, y);
+
+ old_action = current_action;
+ current_action = a;
+ ret = current_action->trigger_cb (argc, argv, x, y);
+ current_action = old_action;
+
+ return ret;
}
int
diff --git a/src/hid/lesstif/menu.c b/src/hid/lesstif/menu.c
index f391778..9869483 100644
--- a/src/hid/lesstif/menu.c
+++ b/src/hid/lesstif/menu.c
@@ -815,8 +815,8 @@ lesstif_get_coords (const char *msg, int *px, int *py)
int
lesstif_call_action (const char *aname, int argc, char **argv)
{
- int px, py;
- HID_Action *a;
+ int px, py, ret;
+ HID_Action *a, *old_action;
if (!aname)
return 1;
@@ -850,7 +850,13 @@ lesstif_call_action (const char *aname, int argc, char **argv)
printf ("%s%s", i ? "," : "", argv[i]);
printf (")\033[0m\n");
}
- return a->trigger_cb (argc, argv, px, py);
+
+ old_action = current_action;
+ current_action = a;
+ ret = current_action->trigger_cb (argc, argv, x, y);
+ current_action = old_action;
+
+ return ret;
}
static void
commit 28f6cd1f67b6c3a7a9639ceea67b29474d5a649b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Sort actions by references in 'all_actions'.
Previously, when building 'all_actions', a copy of every HID_Action
was performed for each action. Now it builds 'all_actions' with pointers
to the actual HID_Action structures (without reallocating).
diff --git a/src/hid/common/actions.c b/src/hid/common/actions.c
index e172d51..123a2f4 100644
--- a/src/hid/common/actions.c
+++ b/src/hid/common/actions.c
@@ -30,7 +30,7 @@ typedef struct HID_ActionNode
HID_ActionNode *hid_action_nodes = 0;
static int n_actions = 0;
-static HID_Action *all_actions = 0;
+static HID_Action **all_actions = 0;
void
hid_register_actions (HID_Action * a, int n)
@@ -54,8 +54,8 @@ hid_register_actions (HID_Action * a, int n)
static int
action_sort (const void *va, const void *vb)
{
- HID_Action *a = (HID_Action *) va;
- HID_Action *b = (HID_Action *) vb;
+ HID_Action *a = *(HID_Action **) va;
+ HID_Action *b = *(HID_Action **) vb;
return strcmp (a->name, b->name);
}
@@ -71,11 +71,11 @@ hid_find_action (const char *name)
if (all_actions == 0)
{
n = 0;
- all_actions = malloc (n_actions * sizeof (HID_Action));
+ all_actions = malloc (n_actions * sizeof (HID_Action*));
for (ha = hid_action_nodes; ha; ha = ha->next)
for (i = 0; i < ha->n; i++)
- all_actions[n++] = ha->actions[i];
- qsort (all_actions, n_actions, sizeof (HID_Action), action_sort);
+ all_actions[n++] = &(ha->actions[i]);
+ qsort (all_actions, n_actions, sizeof (HID_Action*), action_sort);
}
@@ -85,10 +85,10 @@ hid_find_action (const char *name)
while (lower < upper - 1)
{
i = (lower + upper) / 2;
- n = strcmp (all_actions[i].name, name);
+ n = strcmp (all_actions[i]->name, name);
/*printf("try [%d].%s, cmp %d\n", i, all_actions[i].name, n); */
if (n == 0)
- return all_actions + i;
+ return all_actions[i];
if (n > 0)
upper = i;
else
@@ -96,8 +96,8 @@ hid_find_action (const char *name)
}
for (i = 0; i < n_actions; i++)
- if (strcasecmp (all_actions[i].name, name) == 0)
- return all_actions + i;
+ if (strcasecmp (all_actions[i]->name, name) == 0)
+ return all_actions[i];
printf ("unknown action `%s'\n", name);
return 0;
@@ -112,15 +112,15 @@ print_actions ()
fprintf (stderr, "Registered Actions:\n");
for (i = 0; i < n_actions; i++)
{
- if (all_actions[i].description)
- fprintf (stderr, " %s - %s\n", all_actions[i].name,
- all_actions[i].description);
+ if (all_actions[i]->description)
+ fprintf (stderr, " %s - %s\n", all_actions[i]->name,
+ all_actions[i]->description);
else
- fprintf (stderr, " %s\n", all_actions[i].name);
- if (all_actions[i].syntax)
+ fprintf (stderr, " %s\n", all_actions[i]->name);
+ if (all_actions[i]->syntax)
{
const char *bb, *eb;
- bb = eb = all_actions[i].syntax;
+ bb = eb = all_actions[i]->syntax;
while (1)
{
for (eb = bb; *eb && *eb != '\n'; eb++)
@@ -164,13 +164,13 @@ dump_actions ()
hid_find_action (hid_action_nodes->actions[0].name);
for (i = 0; i < n_actions; i++)
{
- const char *desc = all_actions[i].description;
- const char *synt = all_actions[i].syntax;
+ const char *desc = all_actions[i]->description;
+ const char *synt = all_actions[i]->syntax;
desc = desc ? desc : "";
synt = synt ? synt : "";
- printf ("A%s\n", all_actions[i].name);
+ printf ("A%s\n", all_actions[i]->name);
dump_string ('D', desc);
dump_string ('S', synt);
}
commit 880affd3b2680782e923c421136b4286c1e94c74
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Revert "single-action register/deregister".
This reverts commits 337fa8ba8094cee1ed291cec7bf29895ac7c9d72 and
b274cf8fe9c8caf5bcd4edc28935c88cf5bab7f4 before the introduction of a
new context passing scheme for actions.
diff --git a/src/hid.h b/src/hid.h
index 9b26ef8..067beb0 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -86,25 +86,7 @@ extern "C"
const char *syntax;
} HID_Action;
- /* This global variable is always set to the action context, before
- an action callback is called. Action context can be specified
- when registering an action with hid_register_action() Intended
- for plugins with hub action callbacks. */
- extern void *hid_action_context;
-
- /* Register a singe action associated with an action context. Makes
- a copy of HID_Action. Intended for plugins to register actions
- with a hub callback. */
- extern void hid_register_action(const HID_Action *, void *);
-
- /* Deregister an action registered using hid_register_action().
- Action context pointer is copied in the 2nd argument if it's not
- NULL. Intended for plugins to deregister custom actions. */
- extern void hid_deregister_action(const char *, void **);
-
- /* Register a list of static actions without action context */
extern void hid_register_actions (HID_Action *, int);
-
#define REGISTER_ACTIONS(a) HIDCONCAT(void register_,a) ()\
{ hid_register_actions(a, sizeof(a)/sizeof(a[0])); }
diff --git a/src/hid/common/actions.c b/src/hid/common/actions.c
index 8678ad9..e172d51 100644
--- a/src/hid/common/actions.c
+++ b/src/hid/common/actions.c
@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <assert.h>
#include "global.h"
#include "data.h"
@@ -27,29 +26,14 @@ typedef struct HID_ActionNode
struct HID_ActionNode *next;
HID_Action *actions;
int n;
- /* The registrar the callback function may use this pointer to
- remember context; the action infrastructure will just pass it
- along. */
- void *context;
- /* is this ActionNode registered runtime? (can be deregistered) */
- int dynamic;
} HID_ActionNode;
-/* The master list of all actions registered */
-typedef struct HID_ActionContext
-{
- HID_Action action;
- void *context;
-} HID_ActionContext;
+HID_ActionNode *hid_action_nodes = 0;
static int n_actions = 0;
-static HID_ActionContext *all_actions = NULL;
-
-HID_ActionNode *hid_action_nodes = NULL;
+static HID_Action *all_actions = 0;
-void *hid_action_context = NULL;
-
-static void
-hid_register_actions_context (HID_Action * a, int n, void *context, int dynamic)
+void
+hid_register_actions (HID_Action * a, int n)
{
HID_ActionNode *ha;
@@ -57,87 +41,26 @@ hid_register_actions_context (HID_Action * a, int n, void *context, int dynamic)
ha = (HID_ActionNode *) malloc (sizeof (HID_ActionNode));
ha->next = hid_action_nodes;
hid_action_nodes = ha;
- if (dynamic) {
- assert(n == 1); /* we register dynamic actions one by one */
- ha->actions = malloc(sizeof(HID_Action));
- memcpy(ha->actions, a, sizeof(HID_Action));
- }
- else
- ha->actions = a;
-
+ ha->actions = a;
ha->n = n;
- ha->context = context;
- ha->dynamic = dynamic;
n_actions += n;
if (all_actions)
{
free (all_actions);
- all_actions = NULL;
+ all_actions = 0;
}
}
-void
-hid_register_actions (HID_Action * a, int n)
-{
- hid_register_actions_context (a, n, NULL, 0);
-}
-
-void
-hid_register_action (const HID_Action * a, void *context)
-{
- hid_register_actions_context (a, 1, context, 1);
-}
-
-void
-hid_deregister_action (const char *name, void **context)
-{
- HID_ActionNode *prev, *ha;
-
- if (context != NULL)
- *context = NULL;
-
- /* find the action in hid_action_nodes */
- for(prev = NULL, ha = hid_action_nodes; ha != NULL; prev = ha, ha = ha->next) {
- if (ha->dynamic) {
- if (strcmp(ha->actions->name, name) == 0) {
- /* found the action in the tree, save context */
- if (context != NULL)
- *context = ha->context;
-
- /* remove ha */
- if (prev == NULL)
- hid_action_nodes = ha->next;
- else
- prev->next = ha->next;
-
- free(ha->actions);
- free(ha);
-
- /* to make sure the rebuild of the sorted list next time */
- if (all_actions != NULL) {
- free (all_actions);
- all_actions = NULL;
- }
-
- n_actions--;
- return;
- }
- }
- }
-
- /* action not found - nothing to do */
-}
-
static int
action_sort (const void *va, const void *vb)
{
- HID_ActionContext *a = (HID_ActionContext *) va;
- HID_ActionContext *b = (HID_ActionContext *) vb;
- return strcmp (a->action.name, b->action.name);
+ HID_Action *a = (HID_Action *) va;
+ HID_Action *b = (HID_Action *) vb;
+ return strcmp (a->name, b->name);
}
HID_Action *
-hid_find_action (const char *name, void **context)
+hid_find_action (const char *name)
{
HID_ActionNode *ha;
int i, n, lower, upper;
@@ -145,17 +68,14 @@ hid_find_action (const char *name, void **context)
if (name == NULL)
return 0;
- if (all_actions == NULL)
+ if (all_actions == 0)
{
n = 0;
- all_actions = malloc (n_actions * sizeof (HID_ActionContext));
+ all_actions = malloc (n_actions * sizeof (HID_Action));
for (ha = hid_action_nodes; ha; ha = ha->next)
- for (i = 0; i < ha->n; i++) {
- all_actions[n].action = ha->actions[i];
- all_actions[n].context = ha->context;
- n++;
- }
- qsort (all_actions, n_actions, sizeof (HID_ActionContext), action_sort);
+ for (i = 0; i < ha->n; i++)
+ all_actions[n++] = ha->actions[i];
+ qsort (all_actions, n_actions, sizeof (HID_Action), action_sort);
}
@@ -165,13 +85,10 @@ hid_find_action (const char *name, void **context)
while (lower < upper - 1)
{
i = (lower + upper) / 2;
- n = strcmp (all_actions[i].action.name, name);
+ n = strcmp (all_actions[i].name, name);
/*printf("try [%d].%s, cmp %d\n", i, all_actions[i].name, n); */
- if (n == 0) {
- if (context != NULL)
- *context = all_actions[i].context;
- return &(all_actions[i].action);
- }
+ if (n == 0)
+ return all_actions + i;
if (n > 0)
upper = i;
else
@@ -179,11 +96,8 @@ hid_find_action (const char *name, void **context)
}
for (i = 0; i < n_actions; i++)
- if (strcasecmp (all_actions[i].action.name, name) == 0) {
- if (context != NULL)
- *context = all_actions[i].context;
- return &(all_actions[i].action);
- }
+ if (strcasecmp (all_actions[i].name, name) == 0)
+ return all_actions + i;
printf ("unknown action `%s'\n", name);
return 0;
@@ -194,19 +108,19 @@ print_actions ()
{
int i;
/* Forces them to be sorted in all_actions */
- hid_find_action (hid_action_nodes->actions[0].name, NULL);
+ hid_find_action (hid_action_nodes->actions[0].name);
fprintf (stderr, "Registered Actions:\n");
for (i = 0; i < n_actions; i++)
{
- if (all_actions[i].action.description)
- fprintf (stderr, " %s - %s\n", all_actions[i].action.name,
- all_actions[i].action.description);
+ if (all_actions[i].description)
+ fprintf (stderr, " %s - %s\n", all_actions[i].name,
+ all_actions[i].description);
else
- fprintf (stderr, " %s\n", all_actions[i].action.name);
- if (all_actions[i].action.syntax)
+ fprintf (stderr, " %s\n", all_actions[i].name);
+ if (all_actions[i].syntax)
{
const char *bb, *eb;
- bb = eb = all_actions[i].action.syntax;
+ bb = eb = all_actions[i].syntax;
while (1)
{
for (eb = bb; *eb && *eb != '\n'; eb++)
@@ -247,16 +161,16 @@ dump_actions ()
{
int i;
/* Forces them to be sorted in all_actions */
- hid_find_action (hid_action_nodes->actions[0].name, NULL);
+ hid_find_action (hid_action_nodes->actions[0].name);
for (i = 0; i < n_actions; i++)
{
- const char *desc = all_actions[i].action.description;
- const char *synt = all_actions[i].action.syntax;
+ const char *desc = all_actions[i].description;
+ const char *synt = all_actions[i].syntax;
desc = desc ? desc : "";
synt = synt ? synt : "";
- printf ("A%s\n", all_actions[i].action.name);
+ printf ("A%s\n", all_actions[i].name);
dump_string ('D', desc);
dump_string ('S', synt);
}
@@ -286,10 +200,8 @@ hid_actionl (const char *name, ...)
int
hid_actionv (const char *name, int argc, char **argv)
{
- int x = 0, y = 0, i, ret;
+ int x = 0, y = 0, i;
HID_Action *a;
- void *old_context;
- void *context;
if (Settings.verbose && name)
{
@@ -299,21 +211,12 @@ hid_actionv (const char *name, int argc, char **argv)
printf (")\033[0m\n");
}
- a = hid_find_action (name, &context);
+ a = hid_find_action (name);
if (!a)
return 1;
if (a->need_coord_msg)
gui->get_coords (a->need_coord_msg, &x, &y);
-
- /* save old action context and set it to the context associated with the action */
- old_context = hid_action_context;
- hid_action_context = context;
-
- ret = a->trigger_cb (argc, argv, x, y);
-
- /* restore old context and return */
- hid_action_context = old_context;
- return ret;
+ return a->trigger_cb (argc, argv, x, y);
}
int
diff --git a/src/hid/hidint.h b/src/hid/hidint.h
index 5840e20..a2148a0 100644
--- a/src/hid/hidint.h
+++ b/src/hid/hidint.h
@@ -35,7 +35,7 @@ typedef struct HID_AttrNode
extern HID_AttrNode *hid_attr_nodes;
-HID_Action *hid_find_action (const char *name, void **context);
+HID_Action *hid_find_action (const char *name);
HID_Flag *hid_find_flag (const char *name);
diff --git a/src/hid/lesstif/menu.c b/src/hid/lesstif/menu.c
index d3e421d..f391778 100644
--- a/src/hid/lesstif/menu.c
+++ b/src/hid/lesstif/menu.c
@@ -815,13 +815,12 @@ lesstif_get_coords (const char *msg, int *px, int *py)
int
lesstif_call_action (const char *aname, int argc, char **argv)
{
- int px, py, ret;
+ int px, py;
HID_Action *a;
- void *context, *old_context;
if (!aname)
return 1;
- a = hid_find_action (aname, &context);
+ a = hid_find_action (aname);
if (!a)
{
int i;
@@ -851,11 +850,7 @@ lesstif_call_action (const char *aname, int argc, char **argv)
printf ("%s%s", i ? "," : "", argv[i]);
printf (")\033[0m\n");
}
- old_context = hid_action_context;
- hid_action_context = context;
- ret = a->trigger_cb (argc, argv, px, py);
- hid_action_context = old_context;
- return ret;
+ return a->trigger_cb (argc, argv, px, py);
}
static void
commit 8d881c4fcaa2faddb2b4e47a8f6309c80d147632
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Fix comment for global variable 'gui' in
hid.h.
hid_start_gui() does not exist. The variable is instead set in main()
and hid_expose_callback().
diff --git a/src/hid.h b/src/hid.h
index 7409bbf..9b26ef8 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -590,7 +590,7 @@ typedef enum
void hid_expose_callback (HID * hid_, struct BoxType *region_, void *item_);
/* This is initially set to a "no-gui" gui, and later reset by
- hid_start_gui. */
+ main. hid_expose_callback also temporarily set it for drawing. */
extern HID *gui;
/* This is either NULL or points to the current HID that is being called to
commit 2d7de84dd42cb9e2eccd8f41f878b4cacad3c895
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Modify DrawSpecialPolygon() prototype to not
take a pointer on HID.
DrawSpecialPolygon() was the only function to take a HID as parameter.
Every other draw function works on the current HID through global
variable 'gui'.
diff --git a/src/draw.c b/src/draw.c
index 9571b29..d06813d 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -925,7 +925,7 @@ DrawLayerGroup (int group, const BoxType * screen)
* 2 --- 1
*/
static void
-DrawSpecialPolygon (HID * hid, hidGC DrawGC,
+DrawSpecialPolygon (hidGC DrawGC,
LocationType X, LocationType Y, int Thickness,
int thin_draw)
{
@@ -973,16 +973,16 @@ DrawSpecialPolygon (HID * hid, hidGC DrawGC,
if (thin_draw)
{
int i;
- hid->set_line_cap (DrawGC, Round_Cap);
- hid->set_line_width (DrawGC, 0);
+ gui->set_line_cap (DrawGC, Round_Cap);
+ gui->set_line_width (DrawGC, 0);
polygon_x[8] = X + scaled_x[0];
polygon_y[8] = Y + scaled_y[0];
for (i = 0; i < 8; i++)
- hid->draw_line (DrawGC, polygon_x[i], polygon_y[i],
+ gui->draw_line (DrawGC, polygon_x[i], polygon_y[i],
polygon_x[i + 1], polygon_y[i + 1]);
}
else
- hid->fill_polygon (DrawGC, 8, polygon_x, polygon_y);
+ gui->fill_polygon (DrawGC, 8, polygon_x, polygon_y);
}
/* ---------------------------------------------------------------------------
@@ -1032,7 +1032,7 @@ DrawPinOrViaLowLevel (PinTypePtr Ptr, Boolean drawHole)
}
else if (TEST_FLAG (OCTAGONFLAG, Ptr))
{
- DrawSpecialPolygon (gui, Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness,
+ DrawSpecialPolygon (Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness,
TEST_FLAG (THINDRAWFLAG, PCB));
}
else
@@ -1145,7 +1145,7 @@ ClearOnlyPin (PinTypePtr Pin, Boolean mask)
}
else if (TEST_FLAG (OCTAGONFLAG, Pin))
{
- DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2,
+ DrawSpecialPolygon (Output.pmGC, Pin->X, Pin->Y, half * 2,
TEST_FLAG (THINDRAWFLAG, PCB) ||
TEST_FLAG (THINDRAWPOLYFLAG, PCB));
}
commit 7c0af9f92a78cafc9d81ca77937b26f18f0b5531
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud: Support HID_Mixed options in attribute dialog
Since an HID_Mixed attribute is the combination of a real and an enum,
reuse the code for HID_Enum to provide a combo box next to the spin button
for the real part.
diff --git a/src/hid/gtk/gui-dialog-print.c b/src/hid/gtk/gui-dialog-print.c
index 922b719..c5c2fff 100644
--- a/src/hid/gtk/gui-dialog-print.c
+++ b/src/hid/gtk/gui-dialog-print.c
@@ -213,6 +213,7 @@ ghid_attribute_dialog (HID_Attribute * attrs,
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ do_enum:
/*
* We have to put the combo_box inside of an event_box in
* order for tooltips to work.
@@ -246,7 +247,22 @@ ghid_attribute_dialog (HID_Attribute * attrs,
break;
case HID_Mixed:
- printf ("HID_Mixed\n");
+ hbox = gtk_hbox_new (FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ /*
+ * FIXME
+ * need to pick the "digits" and step size argument more
+ * intelligently
+ */
+ ghid_spin_button (hbox, &widget, attrs[j].default_val.real_value,
+ attrs[j].min_val, attrs[j].max_val, 0.01, 0.01, 3,
+ 0,
+ dblspinner_changed_cb,
+ &(attrs[j].default_val.real_value), FALSE, NULL);
+ gtk_tooltips_set_tip (tips, widget, attrs[j].help_text, NULL);
+
+ goto do_enum;
break;
case HID_Path:
commit 7ef3aa04772b11db6afd14c626a6c49882c5850b
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Apply patch from Patrick Bernaud.
Modified code to not abort on HID_Mixed attributes. Th gtk HID is
modified to understand such an attribute (though the attribute dialog
has still no support for them), the lesstif HID is unchanged.
diff --git a/src/hid/common/hidinit.c b/src/hid/common/hidinit.c
index 9581d32..bb1a66b 100644
--- a/src/hid/common/hidinit.c
+++ b/src/hid/common/hidinit.c
@@ -291,6 +291,11 @@ hid_parse_command_line (int *argc, char ***argv)
if (a->value)
*(int *) a->value = a->default_val.int_value;
break;
+ case HID_Mixed:
+ if (a->value) {
+ *(HID_Attr_Val *) a->value = a->default_val;
+ }
+ break;
default:
abort ();
}
@@ -345,7 +350,6 @@ hid_parse_command_line (int *argc, char ***argv)
a->default_val.int_value = bool_val;
break;
case HID_Mixed:
- abort ();
a->default_val.real_value = strtod ((*argv)[1], &ep);
goto do_enum;
case HID_Enum:
@@ -353,7 +357,7 @@ hid_parse_command_line (int *argc, char ***argv)
do_enum:
ok = 0;
for (e = 0; a->enumerations[e]; e++)
- if (strcmp (a->enumerations[e], (*argv)[1]) == 0)
+ if (strcmp (a->enumerations[e], ep) == 0)
{
ok = 1;
a->default_val.int_value = e;
@@ -491,7 +495,14 @@ hid_save_settings (int locally)
a->enumerations[a->value ? *(int *)a->value : a->default_val.int_value]);
break;
case HID_Mixed:
- abort ();
+ {
+ HID_Attr_Val *value =
+ a->value ? (HID_Attr_Val*) a->value : &(a->default_val);
+ fprintf (f, "%s = %g%s\n",
+ a->name,
+ value->real_value,
+ a->enumerations[value->int_value]);
+ }
break;
}
}
@@ -529,7 +540,6 @@ hid_set_attribute (char *name, char *value)
a->default_val.int_value = 1;
break;
case HID_Mixed:
- abort ();
a->default_val.real_value = strtod (value, &value);
/* fall through */
case HID_Enum:
diff --git a/src/hid/gtk/gui-config.c b/src/hid/gtk/gui-config.c
index 490befc..c9bf82b 100644
--- a/src/hid/gtk/gui-config.c
+++ b/src/hid/gtk/gui-config.c
@@ -588,7 +588,6 @@ parse_optionv (gint * argc, gchar *** argv, gboolean from_cmd_line)
a->default_val.int_value = 1;
break;
case HID_Mixed:
- abort ();
a->default_val.real_value = strtod ((*argv)[1], &ep);
goto do_enum;
case HID_Enum:
@@ -596,7 +595,7 @@ parse_optionv (gint * argc, gchar *** argv, gboolean from_cmd_line)
do_enum:
ok = 0;
for (e = 0; a->enumerations[e]; e++)
- if (strcmp (a->enumerations[e], (*argv)[1]) == 0)
+ if (strcmp (a->enumerations[e], ep) == 0)
{
ok = 1;
a->default_val.int_value = e;
diff --git a/src/main.c b/src/main.c
index 5f68465..99dcba1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -309,8 +309,10 @@ print_defaults_1 (HID_Attribute * a, void *value)
fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
break;
case HID_Mixed:
- i = value ? *(int *) value : a->default_val.int_value;
- d = value ? *(double *) value : a->default_val.real_value;
+ i = value ?
+ ((HID_Attr_Val*)value)->int_value : a->default_val.int_value;
+ d = value ?
+ ((HID_Attr_Val*)value)->real_value : a->default_val.real_value;
fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
break;
case HID_Label:
commit a86548a6c26429e0b420602f98152d881f84cc2a
Author: Stuart Brorson <sdb@xxxxxxxxxx>
Commit: Stuart Brorson <sdb@xxxxxxxxxx>
Applying patch from Patrick Bernaud.
HIDs with a name too long were breaking alignement in usage() as the
code requested insertion of a tab after the name even for HID names
already exceeding the length of the tabulation.
This is similar to how usage_attr() already does alignment of
name and help text.
diff --git a/src/main.c b/src/main.c
index 162a0e0..5f68465 100644
--- a/src/main.c
+++ b/src/main.c
@@ -252,17 +252,17 @@ usage (void)
u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
for (i = 0; hl[i]; i++)
if (hl[i]->gui)
- fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
+ fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
u ("%s -p [printing options] <pcb file>\tto print", Progname);
u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
for (i = 0; hl[i]; i++)
if (hl[i]->printer)
- fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
+ fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
u ("%s -x hid [export options] <pcb file>\tto export", Progname);
u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
for (i = 0; hl[i]; i++)
if (hl[i]->exporter)
- fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
+ fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
for (i = 0; hl[i]; i++)
if (hl[i]->gui)
commit b75d1fe8d42c138ae499898db5b926948b73f767
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove an out of date comment about mouse resources not being
understood. Also remove an old and unused popup section that
had been used for testing.
diff --git a/src/gpcb-menu.res b/src/gpcb-menu.res
index 11251b2..17a0fbf 100644
--- a/src/gpcb-menu.res
+++ b/src/gpcb-menu.res
@@ -2,12 +2,6 @@
# Note - gpcb-menu.res is used to build gpcb-menu.h
# Note - parameters are sensitive to extra spaces around the commas
-#
-# NOTE: I have not figured out what to do with this
-# section yet. The Mouse section is currently ignored until
-# I figure out how to handle it.
-#
-
Mouse =
{
Left = {
@@ -528,26 +522,5 @@ PopupMenus =
{"Cancel" Mode(Escape) a={"Esc" "<Key>Escape"}}
}
}
-
-#
-# A dummy popup menu to help test out the parser and also
-# it will be used to help test the Popup() action when
-# I get around to writing it.
-#
- Popup2 =
- {
- {"Submenu1"
- {"Choice1a"}
- {"Choice1b"}
- {"Choice1c"}
- {"Choice1d"}
- }
- {"Submenu2"
- {"Choice2a"}
- {"Choice2b"}
- }
- {"Choice1"}
- {"Choice2"}
- }
}
commit 5a22f98ca0d0c064d4d40af7785c81d434ce92ec
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove invalidate_wh from the new gcode HID too.
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index bbc1d53..c3c2e4e 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -1040,7 +1040,6 @@ HID gcode_hid = {
gcode_get_export_options,
gcode_do_export,
gcode_parse_arguments,
- 0 /* gcode_invalidate_wh */ ,
0 /* gcode_invalidate_lr */ ,
0 /* gcode_invalidate_all */ ,
gcode_set_layer,
commit 897640d7b920b4d593d2b0a6644a061698610b69
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove Settings.init_done variable and its usage
This variable was previously used to allow action scripts run prior to
loading the GUI to avoid GUI startup if they executed a "Quit" action.
The requirement dates back prior to the HID split, where the "Quit"
action would cause PCB to call gtk_main_quit(), an operation which is
illegal if the GUI main loop was not yet started. The init_done flag
was used in QuitApplication(), both to determine whether the GUI had
started, and if not - to note that the GUI should not be initialised
later. (Instead of calling gtk_main_quit()).
With the HID split, the QuitApplication() function was changed to call
exit(0) rather than gtk_main_quit(), so this dance isn't necessary at
all now.. in either case, we can just exit the application immediately.
diff --git a/src/global.h b/src/global.h
index 19f4454..80bea72 100644
--- a/src/global.h
+++ b/src/global.h
@@ -668,7 +668,6 @@ typedef struct /* some resources... */
/* connections is done */
AutoPlace; /* flag which says we should force placement of the
windows on startup */
- int init_done;
}
SettingType, *SettingTypePtr;
diff --git a/src/main.c b/src/main.c
index bb79991..162a0e0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1021,12 +1021,6 @@ main (int argc, char *argv[])
#ifdef HAVE_LIBSTROKE
stroke_init ();
#endif
- /*
- * Set this flag to zero. Then if we have a startup
- * action which includes Quit(), the flag will be set
- * to -1 and we can avoid ever calling gtk_main();
- */
- Settings.init_done = 0;
if (Settings.ScriptFilename)
{
@@ -1040,37 +1034,33 @@ main (int argc, char *argv[])
hid_parse_actions (Settings.ActionString, 0);
}
- if (Settings.init_done == 0)
- {
- Settings.init_done = 1;
#if HAVE_DBUS
- pcb_dbus_setup();
+ pcb_dbus_setup();
#endif
- EnableAutosave ();
+ EnableAutosave ();
#ifdef DEBUG
- printf ("Settings.LibraryCommandDir = \"%s\"\n",
- Settings.LibraryCommandDir);
- printf ("Settings.FontPath = \"%s\"\n",
- Settings.FontPath);
- printf ("Settings.ElementPath = \"%s\"\n",
- Settings.ElementPath);
- printf ("Settings.LibraryPath = \"%s\"\n",
- Settings.LibraryPath);
- printf ("Settings.LibraryTree = \"%s\"\n",
- Settings.LibraryTree);
- printf ("Settings.MakeProgram = \"%s\"\n",
- UNKNOWN (Settings.MakeProgram));
- printf ("Settings.GnetlistProgram = \"%s\"\n",
- UNKNOWN (Settings.GnetlistProgram));
+ printf ("Settings.LibraryCommandDir = \"%s\"\n",
+ Settings.LibraryCommandDir);
+ printf ("Settings.FontPath = \"%s\"\n",
+ Settings.FontPath);
+ printf ("Settings.ElementPath = \"%s\"\n",
+ Settings.ElementPath);
+ printf ("Settings.LibraryPath = \"%s\"\n",
+ Settings.LibraryPath);
+ printf ("Settings.LibraryTree = \"%s\"\n",
+ Settings.LibraryTree);
+ printf ("Settings.MakeProgram = \"%s\"\n",
+ UNKNOWN (Settings.MakeProgram));
+ printf ("Settings.GnetlistProgram = \"%s\"\n",
+ UNKNOWN (Settings.GnetlistProgram));
#endif
- gui->do_export (0);
+ gui->do_export (0);
#if HAVE_DBUS
- pcb_dbus_finish();
+ pcb_dbus_finish();
#endif
- }
return (0);
}
diff --git a/src/misc.c b/src/misc.c
index b675090..cca9e1b 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -879,16 +879,7 @@ QuitApplication (void)
else
DisableEmergencySave ();
- /*
- * if Settings.init_done is not > 0 then we haven't even called
- * gtk_main() yet so gtk_main_quit() will give an error. In
- * this case just set the flag to -1 and we will exit instead
- * of calling gtk_main()
- */
- if (Settings.init_done > 0)
- exit (0);
- else
- Settings.init_done = -1;
+ exit (0);
}
/* ---------------------------------------------------------------------------
commit af5b9b3a96e9f42089ecfbe878807b68044dbdfd
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused HistorySize field from the settings structure
diff --git a/src/global.h b/src/global.h
index 3794448..19f4454 100644
--- a/src/global.h
+++ b/src/global.h
@@ -668,8 +668,7 @@ typedef struct /* some resources... */
/* connections is done */
AutoPlace; /* flag which says we should force placement of the
windows on startup */
- int HistorySize, /* FIXME? Used in hid/xaw code only. */
- init_done;
+ int init_done;
}
SettingType, *SettingTypePtr;
commit 3352f8b5a2cf99d55f360d9c319e32a3ca092553
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused "last" parameter from HID "invalidate_lr" method
diff --git a/src/draw.c b/src/draw.c
index b843da6..9571b29 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -194,7 +194,7 @@ Draw (void)
/* clear and create event if not drawing to a pixmap
*/
- gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2, 1);
+ gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
RestoreCrosshair (True);
diff --git a/src/hid.h b/src/hid.h
index 0e0c479..7409bbf 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -304,8 +304,7 @@ typedef enum
void (*parse_arguments) (int *argc_, char ***argv_);
/* This may be called to ask the GUI to force a redraw of a given area */
- void (*invalidate_lr) (int left_, int right_, int top_, int bottom_,
- int last_);
+ void (*invalidate_lr) (int left_, int right_, int top_, int bottom_);
void (*invalidate_all) (void);
/* During redraw or print/export cycles, this is called once per
diff --git a/src/hid/batch/batch.c b/src/hid/batch/batch.c
index 1baa2d8..f26321d 100644
--- a/src/hid/batch/batch.c
+++ b/src/hid/batch/batch.c
@@ -191,7 +191,7 @@ batch_parse_arguments (int *argc, char ***argv)
}
static void
-batch_invalidate_lr (int l, int r, int t, int b, int last)
+batch_invalidate_lr (int l, int r, int t, int b)
{
}
diff --git a/src/hid/common/hidnogui.c b/src/hid/common/hidnogui.c
index 3e5e9db..d5dc9e1 100644
--- a/src/hid/common/hidnogui.c
+++ b/src/hid/common/hidnogui.c
@@ -50,7 +50,7 @@ nogui_parse_arguments (int *argc, char ***argv)
}
static void
-nogui_invalidate_lr (int l, int r, int t, int b, int last)
+nogui_invalidate_lr (int l, int r, int t, int b)
{
CRASH;
}
diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index 330e716..b8fdc75 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -318,7 +318,7 @@ ghid_get_export_options (int *n_ret)
}
void
-ghid_invalidate_lr (int left, int right, int top, int bottom, int last)
+ghid_invalidate_lr (int left, int right, int top, int bottom)
{
ghid_invalidate_all ();
}
diff --git a/src/hid/lesstif/main.c b/src/hid/lesstif/main.c
index 2fec418..51c52fe 100644
--- a/src/hid/lesstif/main.c
+++ b/src/hid/lesstif/main.c
@@ -2828,9 +2828,9 @@ lesstif_need_idle_proc ()
}
static void
-lesstif_invalidate_lr (int l, int r, int t, int b, int last)
+lesstif_invalidate_lr (int l, int r, int t, int b)
{
- if (!last || !window)
+ if (!window)
return;
need_redraw = 1;
@@ -2840,7 +2840,7 @@ lesstif_invalidate_lr (int l, int r, int t, int b, int last)
void
lesstif_invalidate_all (void)
{
- lesstif_invalidate_lr (0, PCB->MaxWidth, 0, PCB->MaxHeight, 1);
+ lesstif_invalidate_lr (0, PCB->MaxWidth, 0, PCB->MaxHeight);
}
static int
commit 832f7928fd3828c4d0588fc73fd9db8858e3d968
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Remove unused HID method invalidate_wh()
invalidate_lr and invalidate_all are sufficient APIs for our needs.
diff --git a/src/hid.h b/src/hid.h
index 3c23338..0e0c479 100644
--- a/src/hid.h
+++ b/src/hid.h
@@ -303,12 +303,7 @@ typedef enum
names behind. */
void (*parse_arguments) (int *argc_, char ***argv_);
- /* This may be called outside of redraw to force a redraw. Pass
- zero for "last" for all but the last call before control returns
- to the user (pass nonzero the last time). If determining the
- last call is difficult, call *_wh at the end with width and
- height zero. */
- void (*invalidate_wh) (int x_, int y_, int width_, int height_, int last_);
+ /* This may be called to ask the GUI to force a redraw of a given area */
void (*invalidate_lr) (int left_, int right_, int top_, int bottom_,
int last_);
void (*invalidate_all) (void);
diff --git a/src/hid/batch/batch.c b/src/hid/batch/batch.c
index c10b280..1baa2d8 100644
--- a/src/hid/batch/batch.c
+++ b/src/hid/batch/batch.c
@@ -191,11 +191,6 @@ batch_parse_arguments (int *argc, char ***argv)
}
static void
-batch_invalidate_wh (int x, int y, int width, int height, int last)
-{
-}
-
-static void
batch_invalidate_lr (int l, int r, int t, int b, int last)
{
}
@@ -471,7 +466,6 @@ HID batch_gui = {
batch_get_export_options,
batch_do_export,
batch_parse_arguments,
- batch_invalidate_wh,
batch_invalidate_lr,
batch_invalidate_all,
batch_set_layer,
diff --git a/src/hid/bom/bom.c b/src/hid/bom/bom.c
index e593bdd..04ad123 100644
--- a/src/hid/bom/bom.c
+++ b/src/hid/bom/bom.c
@@ -544,7 +544,6 @@ HID bom_hid = {
bom_get_export_options,
bom_do_export,
bom_parse_arguments,
- 0, /* bom_invalidate_wh */
0, /* bom_invalidate_lr */
0, /* bom_invalidate_all */
0, /* bom_set_layer */
diff --git a/src/hid/common/extents.c b/src/hid/common/extents.c
index bf53c14..a0dbf6b 100644
--- a/src/hid/common/extents.c
+++ b/src/hid/common/extents.c
@@ -184,8 +184,6 @@ static HID extents_hid = {
0 /* extents_get_export_options */ ,
0 /* extents_do_export */ ,
0 /* extents_parse_arguments */ ,
-
- 0 /* extents_invalidate_wh */ ,
0 /* extents_invalidate_lr */ ,
0 /* extents_invalidate_all */ ,
extents_set_layer,
diff --git a/src/hid/common/hidnogui.c b/src/hid/common/hidnogui.c
index 51c95cb..3e5e9db 100644
--- a/src/hid/common/hidnogui.c
+++ b/src/hid/common/hidnogui.c
@@ -50,12 +50,6 @@ nogui_parse_arguments (int *argc, char ***argv)
}
static void
-nogui_invalidate_wh (int x, int y, int width, int height, int last)
-{
- CRASH;
-}
-
-static void
nogui_invalidate_lr (int l, int r, int t, int b, int last)
{
CRASH;
@@ -359,7 +353,6 @@ HID hid_nogui = {
nogui_get_export_options,
nogui_do_export,
nogui_parse_arguments,
- nogui_invalidate_wh,
nogui_invalidate_lr,
nogui_invalidate_all,
nogui_set_layer,
@@ -417,7 +410,6 @@ apply_default_hid (HID * d, HID * s)
AD (get_export_options);
AD (do_export);
AD (parse_arguments);
- AD (invalidate_wh);
AD (invalidate_lr);
AD (invalidate_all);
AD (set_layer);
diff --git a/src/hid/gerber/gerber.c b/src/hid/gerber/gerber.c
index afa6a08..dee7d06 100644
--- a/src/hid/gerber/gerber.c
+++ b/src/hid/gerber/gerber.c
@@ -1079,7 +1079,6 @@ static HID gerber_hid = {
gerber_get_export_options,
gerber_do_export,
gerber_parse_arguments,
- 0 /* gerber_invalidate_wh */ ,
0 /* gerber_invalidate_lr */ ,
0 /* gerber_invalidate_all */ ,
gerber_set_layer,
diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index 81f0d77..330e716 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -317,13 +317,6 @@ ghid_get_export_options (int *n_ret)
return NULL;
}
-
-void
-ghid_invalidate_wh (int x, int y, int width, int height, int last)
-{
- ghid_invalidate_all ();
-}
-
void
ghid_invalidate_lr (int left, int right, int top, int bottom, int last)
{
@@ -1128,8 +1121,6 @@ HID ghid_hid = {
ghid_get_export_options,
ghid_do_export,
ghid_parse_arguments,
-
- ghid_invalidate_wh,
ghid_invalidate_lr,
ghid_invalidate_all,
ghid_set_layer,
diff --git a/src/hid/lesstif/main.c b/src/hid/lesstif/main.c
index 84e095a..2fec418 100644
--- a/src/hid/lesstif/main.c
+++ b/src/hid/lesstif/main.c
@@ -2828,7 +2828,7 @@ lesstif_need_idle_proc ()
}
static void
-lesstif_invalidate_wh (int x, int y, int width, int height, int last)
+lesstif_invalidate_lr (int l, int r, int t, int b, int last)
{
if (!last || !window)
return;
@@ -2837,16 +2837,10 @@ lesstif_invalidate_wh (int x, int y, int width, int height, int last)
need_idle_proc ();
}
-static void
-lesstif_invalidate_lr (int l, int r, int t, int b, int last)
-{
- lesstif_invalidate_wh (l, t, r - l + 1, b - t + 1, last);
-}
-
void
lesstif_invalidate_all (void)
{
- lesstif_invalidate_wh (0, 0, PCB->MaxWidth, PCB->MaxHeight, 1);
+ lesstif_invalidate_lr (0, PCB->MaxWidth, 0, PCB->MaxHeight, 1);
}
static int
@@ -3772,8 +3766,6 @@ HID lesstif_gui = {
lesstif_get_export_options,
lesstif_do_export,
lesstif_parse_arguments,
-
- lesstif_invalidate_wh,
lesstif_invalidate_lr,
lesstif_invalidate_all,
lesstif_set_layer,
diff --git a/src/hid/lpr/lpr.c b/src/hid/lpr/lpr.c
index e47c40f..aa696be 100644
--- a/src/hid/lpr/lpr.c
+++ b/src/hid/lpr/lpr.c
@@ -121,7 +121,6 @@ HID lpr_hid = {
lpr_get_export_options,
lpr_do_export,
lpr_parse_arguments,
- 0 /* lpr_invalidate_wh */ ,
0 /* lpr_invalidate_lr */ ,
0 /* lpr_invalidate_all */ ,
0 /* lpr_set_layer */ ,
diff --git a/src/hid/nelma/nelma.c b/src/hid/nelma/nelma.c
index dc1cee5..8e5ff0c 100644
--- a/src/hid/nelma/nelma.c
+++ b/src/hid/nelma/nelma.c
@@ -1056,7 +1056,6 @@ HID nelma_hid = {
nelma_get_export_options,
nelma_do_export,
nelma_parse_arguments,
- 0 /* nelma_invalidate_wh */ ,
0 /* nelma_invalidate_lr */ ,
0 /* nelma_invalidate_all */ ,
nelma_set_layer,
diff --git a/src/hid/png/png.c b/src/hid/png/png.c
index 2e8e40c..404eb53 100644
--- a/src/hid/png/png.c
+++ b/src/hid/png/png.c
@@ -1475,7 +1475,6 @@ HID png_hid = {
png_get_export_options,
png_do_export,
png_parse_arguments,
- 0 /* png_invalidate_wh */ ,
0 /* png_invalidate_lr */ ,
0 /* png_invalidate_all */ ,
png_set_layer,
diff --git a/src/hid/ps/eps.c b/src/hid/ps/eps.c
index b0e7a7d..0c9345b 100644
--- a/src/hid/ps/eps.c
+++ b/src/hid/ps/eps.c
@@ -619,7 +619,6 @@ static HID eps_hid = {
eps_get_export_options,
eps_do_export,
eps_parse_arguments,
- 0 /* eps_invalidate_wh */ ,
0 /* eps_invalidate_lr */ ,
0 /* eps_invalidate_all */ ,
eps_set_layer,
diff --git a/src/hid/ps/ps.c b/src/hid/ps/ps.c
index f21ce84..810ceba 100644
--- a/src/hid/ps/ps.c
+++ b/src/hid/ps/ps.c
@@ -1337,7 +1337,6 @@ HID ps_hid = {
ps_get_export_options,
ps_do_export,
ps_parse_arguments,
- 0 /* ps_invalidate_wh */ ,
0 /* ps_invalidate_lr */ ,
0 /* ps_invalidate_all */ ,
ps_set_layer,
commit be80f0c5771c91dc2795f5832af8fb2013cb3992
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Revert "As silly as it seems to group any sort of scientific or EDA"
I've pushed really hard to sort this nonsense out, and this patch is
not in my opinion suitable for applcation. gEDA, gerbv and PCB all
deliberately omit the Education category.. this is not where we need
to fix this issue.
I strongly object to putting bogus categories into our apps.
If Debian want to patch these in, let them.
This reverts commit b402a144e19225f0648189bca6fbfad95d046047.
diff --git a/data/pcb.desktop.in b/data/pcb.desktop.in
index bc61016..61091b4 100644
--- a/data/pcb.desktop.in
+++ b/data/pcb.desktop.in
@@ -7,4 +7,4 @@ Type=Application
Exec=pcb %f
Icon=pcb
MimeType=application/x-pcb-layout;application/x-pcb-footprint;
-Categories=Education;Science;Engineering;Electronics;
+Categories=Engineering;Electronics;
commit 1d674bcfe2388533001b7789d348ac5fcfa1b788
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix an obvious bug in the previous commit. Caught by harry.
diff --git a/src/hid/ps/ps.c b/src/hid/ps/ps.c
index d680903..f21ce84 100644
--- a/src/hid/ps/ps.c
+++ b/src/hid/ps/ps.c
@@ -1124,13 +1124,13 @@ ps_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
if (x1 > x2)
{
int t = x1;
- x2 = x1;
+ x1 = x2;
x2 = t;
}
if (y1 > y2)
{
int t = y1;
- y2 = y1;
+ y1 = y2;
y2 = t;
}
#if 0
commit b402a144e19225f0648189bca6fbfad95d046047
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
As silly as it seems to group any sort of scientific or EDA
software under "Education", this appears to be the standard
documented by http://standards.freedesktop.org/menu-spec/1.0/apa.html
Noted in patch #2889228 by Ahmed El-Mahmoudy.
diff --git a/data/pcb.desktop.in b/data/pcb.desktop.in
index 61091b4..bc61016 100644
--- a/data/pcb.desktop.in
+++ b/data/pcb.desktop.in
@@ -7,4 +7,4 @@ Type=Application
Exec=pcb %f
Icon=pcb
MimeType=application/x-pcb-layout;application/x-pcb-footprint;
-Categories=Engineering;Electronics;
+Categories=Education;Science;Engineering;Electronics;
commit 175810a3743aba5d1f34b8630e2b5edb472c1841
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
"Encoding" is deprecated. http://standards.freedesktop.org/desktop-entry-spec/1.0/apc.html
Noted in patch #2889228
diff --git a/data/pcb.desktop.in b/data/pcb.desktop.in
index 967ba82..61091b4 100644
--- a/data/pcb.desktop.in
+++ b/data/pcb.desktop.in
@@ -1,6 +1,5 @@
[Desktop Entry]
Version=1.0
-Encoding=UTF-8
_Name=PCB Designer
_GenericName=PCB Design
_Comment=Create and edit printed circuit board designs
commit f3e5290c8a883a103a3931767bdc47d9f5181997
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
It is gcode/hid.conf not gcode/gcode.conf that needs to be distributed.
Also put this file in the correct sorted location.
diff --git a/src/Makefile.am b/src/Makefile.am
index 561a6f4..e719268 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -200,6 +200,7 @@ EXTRA_DIST= \
default_font \
$(srcdir)/hid/batch/hid.conf \
$(srcdir)/hid/bom/hid.conf \
+ $(srcdir)/hid/gcode/hid.conf \
$(srcdir)/hid/gerber/hid.conf \
$(srcdir)/hid/gtk/gui-icons-misc.data \
$(srcdir)/hid/gtk/gui-icons-mode-buttons.data \
@@ -208,7 +209,6 @@ EXTRA_DIST= \
$(srcdir)/hid/lesstif/hid.conf \
$(srcdir)/hid/lpr/hid.conf \
$(srcdir)/hid/png/hid.conf \
- $(srcdir)/hid/gcode/gcode.conf \
$(srcdir)/hid/nelma/hid.conf \
$(srcdir)/hid/ps/hid.conf \
gpcb-menu.res \
commit 1590f4c65c15e6a3ba27079866ea8d14252ce7bf
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add missing AC_PROG_MKDIR_P check.
diff --git a/configure.ac b/configure.ac
index 43ebfaf..f0e19bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,6 +143,7 @@ AC_PROG_CC_STDC
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_AWK
+AC_PROG_MKDIR_P
AM_PROG_LEX
AC_PATH_PROG(LEX_PATH, $LEX, [notfound])
commit e2e741ab7589bd3e6c925fc9b2a81c7c2121f820
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix building outside of the source tree with dependency tracking
disabled. In that case some directories need to be manually
created. Fixes bug #2889226.
diff --git a/src/Makefile.am b/src/Makefile.am
index a5441d6..561a6f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -233,6 +233,7 @@ gpcb-menu.h : gpcb-menu.res
echo '0};' >> $@
hid/common/hidlist.h : Makefile
+ $(MKDIR_P) hid/common
true > $@
for e in ${HIDLIST}; do \
echo "HID_DEF($${e})" >> $@; \
@@ -269,6 +270,7 @@ LIBGTK_SRCS = \
libgtk_a_SOURCES = ${LIBGTK_SRCS} hid/gtk/gtk_lists.h
hid/gtk/gtk_lists.h : ${LIBGTK_SRCS} Makefile
+ $(MKDIR_P) hid/gtk
true > $@
(for f in ${LIBGTK_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -317,6 +319,7 @@ LIBLESSTIF_SRCS = \
liblesstif_a_SOURCES = ${LIBLESSTIF_SRCS} hid/lesstif/lesstif_lists.h
hid/lesstif/lesstif_lists.h : ${LIBLESSTIF_SRCS} Makefile
+ $(MKDIR_P) hid/lesstif
true > $@
(for f in ${LIBLESSTIF_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -364,6 +367,7 @@ LIBGTS_SRCS = \
libgts_a_SOURCES = ${LIBGTS_SRCS} gts/gts_lists.h
gts/gts_lists.h : ${LIBGTS_SRCS} Makefile
+ $(MKDIR_P) gts
true > $@
# Uncomment out the following if/when we ever end up with REGISTER in any of the gts
# source files. For now, there aren't any and so the grep fails and make stops
@@ -377,6 +381,7 @@ LIBBATCH_SRCS = \
libbatch_a_SOURCES = ${LIBBATCH_SRCS} hid/batch/batch_lists.h
hid/batch/batch_lists.h : ${LIBBATCH_SRCS} Makefile
+ $(MKDIR_P) hid/batch
true > $@
(for f in ${LIBBATCH_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -399,6 +404,7 @@ LIBPS_SRCS = \
libps_a_SOURCES = ${LIBPS_SRCS} hid/ps/ps_lists.h
hid/ps/ps_lists.h : ${LIBPS_SRCS} Makefile
+ $(MKDIR_P) hid/ps
true > $@
(for f in ${LIBPS_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -412,6 +418,7 @@ LIBPNG_SRCS = \
libpng_a_SOURCES = ${LIBPNG_SRCS} hid/png/png_lists.h
hid/png/png_lists.h : ${LIBPNG_SRCS} Makefile
+ $(MKDIR_P) hid/png
true > $@
(for f in ${LIBPNG_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -435,6 +442,7 @@ LIBGCODE_SRCS = \
libgcode_a_SOURCES = ${LIBGCODE_SRCS} hid/gcode/gcode_lists.h
hid/gcode/gcode_lists.h : ${LIBGCODE_SRCS} Makefile
+ $(MKDIR_P) hid/gcode
true > $@
(for f in ${LIBGCODE_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
@@ -448,6 +456,7 @@ LIBNELMA_SRCS = \
libnelma_a_SOURCES = ${LIBNELMA_SRCS} hid/nelma/nelma_lists.h
hid/nelma/nelma_lists.h : ${LIBNELMA_SRCS} Makefile
+ $(MKDIR_P) hid/nelma
true > $@
(for f in ${LIBNELMA_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
commit e1d647498921eaca00b2f6930fe1ae9af0c1aab1
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
In the rectangle fill code fix a bug in swapping of the coordinates.
It doesn't appear that this code path is encountered much.
diff --git a/src/hid/ps/ps.c b/src/hid/ps/ps.c
index 98f3eb4..d680903 100644
--- a/src/hid/ps/ps.c
+++ b/src/hid/ps/ps.c
@@ -1124,13 +1124,13 @@ ps_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
if (x1 > x2)
{
int t = x1;
- x2 = x2;
+ x2 = x1;
x2 = t;
}
if (y1 > y2)
{
int t = y1;
- y2 = y2;
+ y2 = y1;
y2 = t;
}
#if 0
commit e053d592a107887438071ef111ee3f811e2a5490
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add DSC to the postscript outputs to keep certain windows based
postscript viewers a little happier. Patch supplied in patch #2700352
by Bob Paddock.
diff --git a/src/hid/ps/ps.c b/src/hid/ps/ps.c
index 3a92dc3..98f3eb4 100644
--- a/src/hid/ps/ps.c
+++ b/src/hid/ps/ps.c
@@ -5,10 +5,11 @@
#endif
#include <stdio.h>
-#include <stdarg.h>
+#include <stdarg.h> /* not used */
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
+#include <assert.h> /* not used */
+#include <time.h>
#include "global.h"
#include "data.h"
@@ -55,13 +56,13 @@ static double antifade_ratio = 0.6;
static int multi_file = 0;
static double media_width, media_height, ps_width, ps_height;
-static const char *medias[] = {
+static const char *medias[] = {
"A0", "A1", "A2", "A3", "A4", "A5",
"A6", "A7", "A8", "A9", "A10",
"B0", "B1", "B2", "B3", "B4", "B5",
"B6", "B7", "B8", "B9", "B10",
"Letter", "11x17", "Ledger",
- "Legal", "Executive",
+ "Legal", "Executive",
"A-Size", "B-size",
"C-Size", "D-size", "E-size",
"US-Business_Card", "Intl-Business_Card",
@@ -270,13 +271,119 @@ static double scale_value;
void
ps_start_file (FILE *f)
{
- fprintf (f, "%%!PS-Adobe-3.0\n\n");
+ time_t currenttime = time( NULL );
+
+ fprintf (f, "%%!PS-Adobe-3.0\n");
+
+ /* Document Structuring Conventions (DCS): */
+
+ /* Start General Header Comments: */
+
+ /*
+ * %%Title DCS provides text title for the document that is useful
+ * for printing banner pages.
+ */
+ fprintf (f, "%%%%Title: %s\n", PCB->Filename);
+
+ /*
+ * %%CreationDate DCS indicates the date and time the document was
+ * created. Neither the date nor time need be in any standard
+ * format. This comment is meant to be used purely for informational
+ * purposes, such as printing on banner pages.
+ */
+ fprintf (f, "%%%%CreationDate: %s", asctime (localtime (¤ttime)));
+
+ /*
+ * %%Creator DCS indicates the document creator, usually the name of
+ * the document composition software.
+ */
+ fprintf (f, "%%%%Creator: PCB release: %s " VERSION "\n", Progname);
+
+ /*
+ * %%Version DCS comment can be used to note the version and
+ * revision number of a document or resource. A document manager may
+ * wish to provide version control services, or allow substitution
+ * of compatible versions/revisions of a resource or document.
+ *
+ * The format should be in the form of 'procname':
+ * <procname>::= < name> < version> < revision>
+ * < name> ::= < text>
+ * < version> ::= < real>
+ * < revision> ::= < uint>
+ *
+ * If a version numbering scheme is not used, these fields should
+ * still be filled with a dummy value of 0.
+ *
+ * There is currently no code in PCB to manage this revision number.
+ *
+ */
+ fprintf (f, "%%%%Version: (PCB %s " VERSION ") 0.0 0\n", Progname );
+
+
+ /*
+ * %%PageOrder DCS is intended to help document managers determine
+ * the order of pages in the document file, which in turn enables a
+ * document manager optionally to reorder the pages. 'Ascend'-The
+ * pages are in ascending order for example, 1-2-3-4-5-6.
+ */
+ fprintf (f, "%%%%PageOrder: Ascend\n" );
+
+ /*
+ * %%Pages: < numpages> | (atend) < numpages> ::= < uint> (Total
+ * %%number of pages)
+ *
+ * %%Pages DCS defines the number of virtual pages that a document
+ * will image. (atend) defers the count until the end of the file,
+ * which is useful for dynamically generated contents.
+ */
+ fprintf (f, "%%%%Pages: (atend)\n" );
+
+ /* End General Header Comments. */
+
+ /* General Body Comments go here. Currently there are none. */
+
+ /*
+ * %%EndComments DCS indicates an explicit end to the header
+ * comments of the document. All global DCS's must preceded
+ * this. A blank line gives an implicit end to the comments.
+ */
+ fprintf (f, "%%%%EndComments\n\n" );
+}
+
+static void
+ps_end_file (FILE *f)
+{
+ /*
+ * %%Trailer DCS must only occur once at the end of the document
+ * script. Any post-processing or cleanup should be contained in
+ * the trailer of the document, which is anything that follows the
+ * %%Trailer comment. Any of the document level structure comments
+ * that were deferred by using the (atend) convention must be
+ * mentioned in the trailer of the document after the %%Trailer
+ * comment.
+ */
+ fprintf (f, "%%%%Trailer\n" );
+
+ /*
+ * %%Pages was deferred until the end of the document via the
+ * (atend) mentioned, in the General Header section.
+ */
+ fprintf (f, "%%%%Pages: %d\n", pagecount );
+
+ /*
+ * %%EOF DCS signifies the end of the document. When the document
+ * manager sees this comment, it issues an end-of-file signal to the
+ * PostScript interpreter. This is done so system-dependent file
+ * endings, such as Control-D and end-of-file packets, do not
+ * confuse the PostScript interpreter.
+ */
+ fprintf (f, "%%%%EOF\n" );
}
static FILE *
psopen (const char *base, const char *which)
{
- FILE *f;
+ FILE *ps_open_file;
char *buf, *suff, *buf2;
if (!multi_file)
@@ -296,9 +403,9 @@ psopen (const char *base, const char *which)
sprintf(buf, "%s.%s.ps", base, which);
}
printf("PS: open %s\n", buf);
- f = fopen(buf, "w");
+ ps_open_file = fopen(buf, "w");
free (buf);
- return f;
+ return ps_open_file;
}
static BoxType region;
@@ -405,19 +512,20 @@ ps_hid_export_to_file (FILE * the_file, HID_Attr_Val * options)
if (! multi_file)
{
- pagecount = 1;
- fprintf (f, "%%%%Page: 1\n");
+ fprintf (f, "%%%%Page: TableOfContents 1\n"); /* %%Page DSC requires both a label and an ordinal */
fprintf (f, "/Times-Roman findfont 24 scalefont setfont\n");
fprintf (f,
"/rightshow { /s exch def s stringwidth pop -1 mul 0 rmoveto s show } def\n");
fprintf (f,
"/y 72 9 mul def /toc { 100 y moveto show /y y 24 sub def } bind def\n");
fprintf (f, "/tocp { /y y 12 sub def 90 y moveto rightshow } bind def\n");
+
doing_toc = 1;
+ pagecount = 1; /* 'pagecount' is modified by hid_expose_callback() call */
hid_expose_callback (&ps_hid, ®ion, 0);
}
- pagecount = 1;
+ pagecount = 1; /* Reset 'pagecount' if single file */
doing_toc = 0;
lastgroup = -1;
hid_expose_callback (&ps_hid, ®ion, 0);
@@ -468,7 +576,10 @@ ps_do_export (HID_Attr_Val * options)
multi_file = 0;
if (f)
- fclose (f);
+ {
+ ps_end_file (f);
+ fclose (f);
+ }
}
extern void hid_parse_command_line (int *argc, char ***argv);
@@ -493,6 +604,14 @@ corner (int x, int y, int dx, int dy)
int len2 = 20000;
#endif
int thick = 0;
+ /*
+ * Originally 'thick' used thicker lines. Currently is uses
+ * Postscript's "device thin" line - i.e. zero width means one
+ * device pixel. The code remains in case you want to make them
+ * thicker - it needs to offset everything so that the *edge* of the
+ * thick line lines up with the edge of the board, not the *center*
+ * of the thick line.
+ */
fprintf (f, "gsave %d setlinewidth %d %d translate %d %d scale\n",
thick * 2, x, y, dx, dy);
@@ -513,6 +632,7 @@ static int is_paste;
static int
ps_set_layer (const char *name, int group, int empty)
{
+ time_t currenttime;
int idx = (group >= 0
&& group <
max_layer) ? PCB->LayerGroups.Entries[group][0] : group;
@@ -542,6 +662,18 @@ ps_set_layer (const char *name, int group, int empty)
{
if (group < 0 || group != lastgroup)
{
+ if( 1 == pagecount )
+ {
+ currenttime = time( NULL );
+ fprintf (f, "30 30 moveto (%s) show\n", PCB->Filename);
+
+ fprintf (f, "(%d.) tocp\n", pagecount);
+ fprintf (f, "(Table of Contents \\(This Page\\)) toc\n" );
+
+ fprintf (f, "(Created on %s) toc\n", asctime (localtime (¤ttime)));
+ fprintf (f, "( ) tocp\n" );
+ }
+
pagecount++;
lastgroup = group;
fprintf (f, "(%d.) tocp\n", pagecount);
@@ -564,17 +696,29 @@ ps_set_layer (const char *name, int group, int empty)
if (multi_file)
{
if (f)
- fclose (f);
+ {
+ ps_end_file (f);
+ fclose (f);
+ }
f = psopen (filename, layer_type_to_file_name (idx));
if (!f)
{
perror(filename);
return 0;
}
-
+
ps_start_file (f);
}
- fprintf (f, "%%%%Page: %d\n", pagecount);
+
+ /*
+ * %%Page DSC comment marks the beginning of the PostScript
+ * language instructions that describe a particular
+ * page. %%Page: requires two arguments: a page label and a
+ * sequential page number. The label may be anything, but the
+ * ordinal page number must reflect the position of that page in
+ * the body of the PostScript file and must start with 1, not 0.
+ */
+ fprintf (f, "%%%%Page: %s %d\n", layer_type_to_file_name(idx), pagecount);
if (mirror)
mirror_this = 1 - mirror_this;
@@ -585,7 +729,7 @@ ps_set_layer (const char *name, int group, int empty)
mirror_this = 1 - mirror_this;
fprintf (f, "/Helvetica findfont 10 scalefont setfont\n");
- if (legend)
+ if (legend)
{
fprintf (f, "30 30 moveto (%s) show\n", PCB->Filename);
if (PCB->Name)
@@ -596,16 +740,16 @@ ps_set_layer (const char *name, int group, int empty)
layer_type_to_file_name (idx));
if (mirror_this)
fprintf (f, "( \\(mirrored\\)) show\n");
-
+
if (fillpage)
fprintf (f, "(, not to scale) show\n");
else
fprintf (f, "(, scale = 1:%.3f) show\n", scale_value);
}
fprintf (f, "newpath\n");
-
+
fprintf (f, "72 72 scale %g %g translate\n", 0.5*media_width, 0.5*media_height);
-
+
boffset = 0.5*media_height;
if (PCB->MaxWidth > PCB->MaxHeight)
{
@@ -1013,8 +1157,13 @@ HID_Attribute ps_calib_attribute_list[] = {
};
static const char * const calib_lines[] = {
- "%!PS-Adobe\n",
+ "%!PS-Adobe-3.0\n",
+ "%%Title: Calibration Page\n",
+ "%%PageOrder: Ascend\n",
+ "%%Pages: 1\n",
+ "%%EndComments\n",
"\n",
+ "%%Page: Calibrate 1\n",
"72 72 scale\n",
"\n",
"0 setlinewidth\n",
@@ -1099,7 +1248,7 @@ void
ps_calibrate_1 (double xval, double yval, int use_command)
{
HID_Attr_Val vals[3];
- FILE *f;
+ FILE *ps_cal_file;
int used_popen = 0, c;
if (xval > 0 && yval > 0)
@@ -1142,29 +1291,31 @@ ps_calibrate_1 (double xval, double yval, int use_command)
char *cmd = vals[0].str_value;
while (*cmd == ' ' || *cmd == '|')
cmd ++;
- f = popen (cmd, "w");
+ ps_cal_file = popen (cmd, "w");
used_popen = 1;
}
else
- f = fopen (vals[0].str_value, "w");
+ ps_cal_file = fopen (vals[0].str_value, "w");
for (c=0; calib_lines[c]; c++)
- fputs(calib_lines[c], f);
+ fputs(calib_lines[c], ps_cal_file);
+
+ fprintf (ps_cal_file, "4 in 0.5 (Y in) cbar\n");
+ fprintf (ps_cal_file, "20 cm 1.5 (Y cm) cbar\n");
+ fprintf (ps_cal_file, "10 in 2.5 (Y in) cbar\n");
+ fprintf (ps_cal_file, "-90 rotate\n");
+ fprintf (ps_cal_file, "4 in -0.5 (X in) cbar\n");
+ fprintf (ps_cal_file, "15 cm -1.5 (X cm) cbar\n");
+ fprintf (ps_cal_file, "7.5 in -2.5 (X in) cbar\n");
- fprintf (f, "4 in 0.5 (Y in) cbar\n");
- fprintf (f, "20 cm 1.5 (Y cm) cbar\n");
- fprintf (f, "10 in 2.5 (Y in) cbar\n");
- fprintf (f, "-90 rotate\n");
- fprintf (f, "4 in -0.5 (X in) cbar\n");
- fprintf (f, "15 cm -1.5 (X cm) cbar\n");
- fprintf (f, "7.5 in -2.5 (X in) cbar\n");
+ fprintf (ps_cal_file, "showpage\n");
- fprintf (f, "showpage\n");
+ fprintf (ps_cal_file, "%%%%EOF\n");
if (used_popen)
- pclose (f);
+ pclose (ps_cal_file);
else
- fclose (f);
+ fclose (ps_cal_file);
}
static void
commit 920d274f40b327f3c83f7c6bf360b66f07966a7e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
The gcode exporter used libgd so make sure we check for it and
document that we need it. Noted by Patrick Bernaud in bug #2967313
diff --git a/INSTALL b/INSTALL
index db27639..c4df37d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,3 @@
-$Id$
-
PCB uses a standard GNU autoconf/automake based build
system which should make compilation go smoothly on most unix-like
systems. Please do read this first section however.
@@ -36,6 +34,10 @@ Export HID's:
ps -- Postscript and Encapsulated Postscript output. No
additional libraries are needed for this.
+ gcode -- CNC G-CODE output (experimental). The gdlib library
+ is used by this HID. gdlib may be found at
+ http://www.libgd.org
+
gerber -- RS-274-X (Gerber) and Excellon drill output. No
additional libraries are needed for this.
@@ -44,7 +46,7 @@ Export HID's:
png -- png/gif/jpeg output. This HID uses gdlib to do
the majority of the work. gdlib may be obtained
- from http://www.boutell.com/gd. At the time of
+ from http://www.libgd.org. At the time of
writing this document, I have tested with
gd-2.0.23 and gd-2.0.33. Other versions may
work as well.
@@ -59,9 +61,6 @@ Export HID's:
formats hopefully it will avoid suprises when the
disabled formats are not available at runtime.
- gcode -- CNC G-CODE output (experimental). No
- additional libraries are needed for this.
-
The choice of which export HID's to compile is indicated with:
--with-exporters="ps gerber bom png"
diff --git a/configure.ac b/configure.ac
index 3f8ed62..43ebfaf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -723,7 +723,7 @@ $GTK_PKG_ERRORS])]
GLIB_VERSION=`$PKG_CONFIG glib-2.0 --modversion`
;;
- nelma|png )
+ gcode|nelma|png )
# Check for gdlib-config for gd (www.boutell.com/gd)
AC_PATH_PROG(GDLIB_CONFIG, gdlib-config, no)
if test "$GDLIB_CONFIG" = "no"; then
@@ -735,10 +735,10 @@ you will get lucky.
])
if test "$WIN32" != "yes" ; then
AC_CHECK_LIB(gd,main,,
- AC_MSG_ERROR([You have requested the nelma and/or png HID but -lgd could not be found]))
+ AC_MSG_ERROR([[You have requested gcode, nelma, or png HIDs but -lgd could not be found]]))
else
AC_CHECK_LIB(bgd,main,,
- AC_MSG_ERROR([You have requested the nelma and/or png HID but -lbgd could not be found]))
+ AC_MSG_ERROR([[You have requested gcode, nelma, or png HIDs but -lbgd could not be found]]))
fi
else
if test "$WIN32" = "yes" ; then
commit 13cada5ddfeb813da99ddf3788a27274958bbfd4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Make sure the simple gcode test layout makes it into the distfile.
diff --git a/tests/inputs/Makefile.am b/tests/inputs/Makefile.am
index b7dbb1e..ee76973 100644
--- a/tests/inputs/Makefile.am
+++ b/tests/inputs/Makefile.am
@@ -2,5 +2,6 @@
EXTRA_DIST= \
bom_general.pcb \
+ gcode_oneline.pcb \
gerber_oneline.pcb
commit 802576013b5d780cd87caafa31c694279ee2dc4f
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Update the documentation to more closely match reality.
diff --git a/tests/README.txt b/tests/README.txt
index dd7750f..8f2a5fb 100644
--- a/tests/README.txt
+++ b/tests/README.txt
@@ -1,9 +1,41 @@
-FIXME -- this is not really updated yet. It is more or less verbatim
-from gerbv and needs updating for pcb.
-
Please read this file before making any modifications to the test suite.
+**********************************************************************
+**********************************************************************
+* Overview
+**********************************************************************
+**********************************************************************
+
+The test suite is based on a shell script, 'run_tests.sh', which
+calls pcb to export various test case layouts to different output
+formats. The tests to be run are defined in the file 'tests.list'.
+The 'tests.list' file defines the export command line options passed
+to pcb, the name of the input .pcb file, and the names and file types
+for the expected output files.
+
+After a particular test is run, the output files are compared against
+a set of "golden" files which are in the golden/ subdirectory.
+ALL CHANGES TO THE GOLDEN FILES MUST BE HAND VERIFIED. This point
+can not be emphasized too much.
+
+While this testsuite is clearly not comprehensive (the GUI is totally
+left out of the testing for example), it is still better than nothing
+and can help detect newly introduced bugs.
+
+**********************************************************************
+**********************************************************************
+* Running an existing test
+**********************************************************************
+**********************************************************************
+
+To run all of the tests defined in tests.list run:
+
+ ./run_tests.sh
+
+To only run a specific test or tests, then simply list them by name
+on the command line like:
+ ./run_tests.sh test_one test_two ...
**********************************************************************
**********************************************************************
@@ -13,12 +45,14 @@ Please read this file before making any modifications to the test suite.
./run_tests.sh --regen <testname>
-will regenerate the golden file for <testname>. I suggest saving
-off a copy and using ImageMagick to look for the differences visually.
-The run_tests.sh script has examples of comparing .png files. Make
-sure the changes are only the expected ones and then check the new
-files back into cvs. Do not blindly update these files as that defeats
-the purpose of the tests.
+will regenerate the golden file for <testname>. If you are generating
+ASCII output such as BOMs or RS-274X files, then use the diff(3) program
+to examine all differences. If you are generating a graphics file
+such as a PNG, then I suggest saving off a copy and using ImageMagick
+to look for the differences visually. The run_tests.sh script has
+examples of comparing .png files. Make sure the changes are only
+the expected ones and then check the new files back into git. Do
+not blindly update these files as that defeats the purpose of the tests.
**********************************************************************
**********************************************************************
@@ -62,11 +96,11 @@ Update Makefile.am's
----------------------------------------------------------------------
Update inputs/Makefile.am and golden/Makefile.am to include your new
-files.
+files. If you added new Makefile.am's then be sure to also update
+configure.ac at the top level of the source tree.
----------------------------------------------------------------------
Add the new files to git
----------------------------------------------------------------------
-FIXME -- fill in this section
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 5320c54..44bdcc7 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -33,9 +33,11 @@ This causes the testsuite to skip all tests and report no errors.
This is used for certain debugging *only*. The primary use is to
allow testing of the 'distcheck' target without including the effects
of the testsuite. The reason this is useful is that due to minor differences
-in cairo versions and perhaps roundoff in different CPU's, the testsuite
+in library versions and perhaps roundoff in different CPU's, the testsuite
may falsely report failures on some systems. These reported failures
prevent using 'distcheck' for verifying the rest of the build system.
+These comments only apply to the tests which try to compare image files
+like PNG files.
EOF
@@ -62,7 +64,8 @@ The resulting output files are examined in various ways to make sure
they are correct. The exact details of how they are compared varies.
For example, the PNG outputs are compared using tools from the ImageMagick
suite while the ASCII centroid and bill of materials files are normalized
-with awk and then compared with the standard diff utility.
+with awk and then compared with the standard diff utility. The normalization
+removes things like a comment line which contains the creation date.
OPTIONS
@@ -266,6 +269,12 @@ fi
# utility functions for comparison
#
+# Usage:
+# compare_check "test_name" "file1" "file2"
+#
+# Makes sure that file1 and file2 both exist. If not, mark the current
+# test as skipped and give an error message
+#
compare_check() {
fn="$1"
f1="$2"
@@ -290,6 +299,9 @@ compare_check() {
# ASCII file comparison routines
#
+# Usage:
+# run_diff "file1" "file2"
+#
run_diff() {
f1="$1"
f2="$2"
commit 6d03d0539e0afd51383f11fd6b06ec7ced0fbf12
Author: Stephen Ecob <silicon.on.inspiration@xxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Fix Freckles
The autorouter sometimes ends a trace just past a pad. The optimizer
cuts this trace at the pad center, leaving a tiny trace left over.
This tiny trace is a "freckle" and it inhibits mitering. Check
for such freckles and remove them.
diff --git a/src/djopt.c b/src/djopt.c
index 68b3641..c8ae961 100644
--- a/src/djopt.c
+++ b/src/djopt.c
@@ -75,6 +75,9 @@ RCSID ("$Id$");
#define ORIENT(x) ((x) & 0xf0)
#define DIRECT(x) ((x) & 0x0f)
+/* Manhattan length of the longest "freckle" */
+#define LONGEST_FRECKLE 2
+
struct line_s;
typedef struct corner_s
@@ -1230,6 +1233,33 @@ simple_optimize_corner (corner_s * c)
}
}
check (c, 0);
+ if (c->n_lines == 1 && !c->via)
+ {
+ corner_s *c0 = other_corner (c->lines[0], c);
+ if (abs(c->x - c0->x) + abs(c->y - c0->y) <= LONGEST_FRECKLE)
+ {
+ /*
+ * Remove this line, as it is a "freckle". A freckle is an extremely
+ * short line (around 0.01 thou) that is unconnected at one end.
+ * Freckles are almost insignificantly small, but are annoying as
+ * they prevent the mitering optimiser from working.
+ * Freckles sometimes arise because of a bug in the autorouter that
+ * causes it to create small overshoots (typically 0.01 thou) at the
+ * intersections of vertical and horizontal lines. These overshoots
+ * are converted to freckles as a side effect of canonicalize_line().
+ * Note that canonicalize_line() is not at fault, the bug is in the
+ * autorouter creating overshoots.
+ * The autorouter bug arose some time between the 20080202 and 20091103
+ * releases.
+ * This code is probably worth keeping even when the autorouter bug is
+ * fixed, as "freckles" could conceivably arise in other ways.
+ */
+ dprintf ("freckle %d,%d to %d,%d\n",
+ c->x, c->y, c0->x, c0->y);
+ move_corner (c, c0->x, c0->y);
+ }
+ }
+ check (c, 0);
return rv;
}
commit a096a8b84c1d0e2beb94a859bde9f2bc2799fe73
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Make the xy file check actually do something.
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 0667fb8..5320c54 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -347,10 +347,24 @@ compare_bom() {
# X-Y (centroid) comparison routines
#
+# used to remove things like creation date from BOM files
+normalize_xy() {
+ f1="$1"
+ f2="$2"
+ $AWK '
+ /^# Date:/ {print "# Date: today"; next}
+ /^# Author:/ {print "# Author: PCB"; next}
+ {print}' \
+ $f1 > $f2
+}
+
compare_xy() {
f1="$1"
f2="$2"
compare_check "compare_xy" "$f1" "$f2" || return 1
+ normalize_xy "$f1" "$cf1"
+ normalize_xy "$f2" "$cf2"
+ run_diff "$cf1" "$cf2" || test_failed=yes
}
##########################################################################
commit beb4c7c5626b8b28c0a203a23fb41f28e5662618
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Add testsuite entries to test the gcode export HID and all of its
command line options.
diff --git a/configure.ac b/configure.ac
index 356e02e..3f8ed62 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1152,6 +1152,17 @@ AC_CONFIG_FILES(tests/golden/hid_bom1/Makefile)
AC_CONFIG_FILES(tests/golden/hid_bom2/Makefile)
AC_CONFIG_FILES(tests/golden/hid_bom3/Makefile)
AC_CONFIG_FILES(tests/golden/hid_bom4/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode1/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode2/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode3/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode4/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode5/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode6/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode7/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode8/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode9/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode10/Makefile)
+AC_CONFIG_FILES(tests/golden/hid_gcode11/Makefile)
AC_CONFIG_FILES(tests/golden/hid_gerber1/Makefile)
AC_CONFIG_FILES(tests/golden/hid_gerber2/Makefile)
AC_CONFIG_FILES(tests/golden/hid_png1/Makefile)
diff --git a/tests/golden/Makefile.am b/tests/golden/Makefile.am
index 1c7afa2..de5bb08 100644
--- a/tests/golden/Makefile.am
+++ b/tests/golden/Makefile.am
@@ -5,7 +5,17 @@ SUBDIRS= \
hid_bom2 \
hid_bom3 \
hid_bom4 \
+ hid_gcode1 \
+ hid_gcode2 \
+ hid_gcode3 \
+ hid_gcode4 \
+ hid_gcode5 \
+ hid_gcode6 \
+ hid_gcode7 \
+ hid_gcode8 \
+ hid_gcode9 \
+ hid_gcode10 \
+ hid_gcode11 \
hid_gerber1 \
hid_gerber2 \
hid_png1
-
diff --git a/tests/golden/hid_gcode1/Makefile.am b/tests/golden/hid_gcode1/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode1/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode1/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode1/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..2031270
--- /dev/null
+++ b/tests/golden/hid_gcode1/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:31:54 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode1/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode1/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..63f6a2d
--- /dev/null
+++ b/tests/golden/hid_gcode1/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:31:54 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode1/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode1/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..afd6cb2
--- /dev/null
+++ b/tests/golden/hid_gcode1/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:31:51 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode10/Makefile.am b/tests/golden/hid_gcode10/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode10/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode10/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode10/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..19a703d
--- /dev/null
+++ b/tests/golden/hid_gcode10/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:32 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=0.002000 (safe Z)
+#101=-0.000050 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.462000 (start point)
+G1 Z#101
+G1 X27.516667 Y13.335000
+G1 X27.347333 Y13.208000
+G1 X7.408333 Y13.165667
+G1 X7.112000 Y12.869333
+G1 X7.112000 Y12.488333
+G1 X7.408333 Y12.192000
+G1 X27.347333 Y12.149667
+G1 X27.643667 Y11.938000
+G1 X27.940000 Y11.895667
+G1 X28.278667 Y11.980333
+G1 X28.532667 Y12.192000
+G1 X28.702000 Y12.530667
+G1 X28.702000 Y12.827000
+G1 X28.532667 Y13.165667
+G1 X28.321000 Y13.335000
+G1 X28.024667 Y13.462000
+G1 X27.770667 Y13.462000
+G0 Z#100
+(polygon end, distance 44.84)
+(end, total distance 44.84mm = 1.77in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode10/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode10/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..7deace0
--- /dev/null
+++ b/tests/golden/hid_gcode10/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:32 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=0.002000 (safe Z)
+#101=-0.002000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode10/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode10/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..a1d48bd
--- /dev/null
+++ b/tests/golden/hid_gcode10/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:28 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=0.002000 (safe Z)
+#101=-0.000050 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.462000 (start point)
+G1 Z#101
+G1 X22.479000 Y13.335000
+G1 X22.309667 Y13.208000
+G1 X2.370667 Y13.165667
+G1 X2.074333 Y12.869333
+G1 X2.074333 Y12.488333
+G1 X2.370667 Y12.192000
+G1 X22.309667 Y12.149667
+G1 X22.606000 Y11.938000
+G1 X22.902333 Y11.895667
+G1 X23.241000 Y11.980333
+G1 X23.495000 Y12.192000
+G1 X23.664333 Y12.530667
+G1 X23.664333 Y12.827000
+G1 X23.495000 Y13.165667
+G1 X23.283333 Y13.335000
+G1 X22.987000 Y13.462000
+G1 X22.733000 Y13.462000
+G0 Z#100
+(polygon end, distance 44.84)
+(end, total distance 44.84mm = 1.77in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode11/Makefile.am b/tests/golden/hid_gcode11/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode11/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode11/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode11/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..c144b05
--- /dev/null
+++ b/tests/golden/hid_gcode11/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,49 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:55 2010 )
+(600 dpi)
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G0 Z#100
+(polygon 1)
+G0 X1.085000 Y0.630000 (start point)
+G1 Z#101
+G1 X1.063333 Y0.625000
+G1 X1.055000 Y0.621667
+G1 X0.276667 Y0.618333
+G1 X0.251667 Y0.610000
+G1 X0.230000 Y0.598333
+G1 X0.200000 Y0.568333
+G1 X0.188333 Y0.546667
+G1 X0.180000 Y0.521667
+G1 X0.180000 Y0.476667
+G1 X0.188333 Y0.451667
+G1 X0.200000 Y0.430000
+G1 X0.230000 Y0.400000
+G1 X0.251667 Y0.388333
+G1 X0.276667 Y0.380000
+G1 X1.055000 Y0.376667
+G1 X1.068333 Y0.371667
+G1 X1.093333 Y0.368333
+G1 X1.121667 Y0.370000
+G1 X1.140000 Y0.375000
+G1 X1.171667 Y0.390000
+G1 X1.191667 Y0.406667
+G1 X1.208333 Y0.426667
+G1 X1.223333 Y0.458333
+G1 X1.228333 Y0.478333
+G1 X1.228333 Y0.520000
+G1 X1.223333 Y0.540000
+G1 X1.208333 Y0.571667
+G1 X1.191667 Y0.591667
+G1 X1.171667 Y0.608333
+G1 X1.140000 Y0.623333
+G1 X1.121667 Y0.628333
+G1 X1.085000 Y0.630000
+G0 Z#100
+(polygon end, distance 2.39)
+(end, total distance 60.74mm = 2.39in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode11/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode11/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..37b9668
--- /dev/null
+++ b/tests/golden/hid_gcode11/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:55 2010 )
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G81 X1.100000 Y0.500000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode11/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode11/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..ddf7394
--- /dev/null
+++ b/tests/golden/hid_gcode11/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,45 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:43 2010 )
+(600 dpi)
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G0 Z#100
+(polygon 1)
+G0 X0.886667 Y0.630000 (start point)
+G1 Z#101
+G1 X0.865000 Y0.625000
+G1 X0.856667 Y0.621667
+G1 X0.078333 Y0.618333
+G1 X0.053333 Y0.610000
+G1 X0.031667 Y0.598333
+G1 X0.000000 Y0.566667
+G1 X0.000000 Y0.431667
+G1 X0.031667 Y0.400000
+G1 X0.053333 Y0.388333
+G1 X0.078333 Y0.380000
+G1 X0.856667 Y0.376667
+G1 X0.870000 Y0.371667
+G1 X0.895000 Y0.368333
+G1 X0.923333 Y0.370000
+G1 X0.941667 Y0.375000
+G1 X0.973333 Y0.390000
+G1 X0.993333 Y0.406667
+G1 X1.010000 Y0.426667
+G1 X1.025000 Y0.458333
+G1 X1.030000 Y0.478333
+G1 X1.030000 Y0.520000
+G1 X1.025000 Y0.540000
+G1 X1.010000 Y0.571667
+G1 X0.993333 Y0.591667
+G1 X0.973333 Y0.608333
+G1 X0.941667 Y0.623333
+G1 X0.923333 Y0.628333
+G1 X0.886667 Y0.630000
+G0 Z#100
+(polygon end, distance 2.38)
+(end, total distance 60.56mm = 2.38in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode2/Makefile.am b/tests/golden/hid_gcode2/Makefile.am
new file mode 100644
index 0000000..a757c9e
--- /dev/null
+++ b/tests/golden/hid_gcode2/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ out.back.cnc \
+ out.drill.cnc \
+ out.front.cnc
diff --git a/tests/golden/hid_gcode2/out.back.cnc b/tests/golden/hid_gcode2/out.back.cnc
new file mode 100644
index 0000000..c3b0526
--- /dev/null
+++ b/tests/golden/hid_gcode2/out.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:35:19 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode2/out.drill.cnc b/tests/golden/hid_gcode2/out.drill.cnc
new file mode 100644
index 0000000..f7c6d78
--- /dev/null
+++ b/tests/golden/hid_gcode2/out.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:35:19 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode2/out.front.cnc b/tests/golden/hid_gcode2/out.front.cnc
new file mode 100644
index 0000000..ca2b079
--- /dev/null
+++ b/tests/golden/hid_gcode2/out.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:35:16 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode3/Makefile.am b/tests/golden/hid_gcode3/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode3/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode3/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode3/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..e67b085
--- /dev/null
+++ b/tests/golden/hid_gcode3/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,40 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:36:04 2010 )
+(1200 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.813000 Y13.546667 (start point)
+G1 Z#101
+G1 X27.664833 Y13.504333
+G1 X27.453167 Y13.398500
+G1 X27.326167 Y13.292667
+G1 X7.535333 Y13.292667
+G1 X7.323667 Y13.229167
+G1 X7.069667 Y12.975167
+G1 X7.006167 Y12.763500
+G1 X7.006167 Y12.615333
+G1 X7.069667 Y12.403667
+G1 X7.323667 Y12.149667
+G1 X7.535333 Y12.086167
+G1 X27.326167 Y12.086167
+G1 X27.495500 Y11.959167
+G1 X27.728333 Y11.853333
+G1 X28.130500 Y11.853333
+G1 X28.448000 Y12.001500
+G1 X28.638500 Y12.213167
+G1 X28.765500 Y12.488333
+G1 X28.765500 Y12.890500
+G1 X28.638500 Y13.165667
+G1 X28.448000 Y13.377333
+G1 X28.130500 Y13.525500
+G1 X27.813000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.35)
+(end, total distance 45.35mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode3/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode3/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..e7be01d
--- /dev/null
+++ b/tests/golden/hid_gcode3/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:36:04 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode3/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode3/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..d7c8c9f
--- /dev/null
+++ b/tests/golden/hid_gcode3/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,40 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:35:46 2010 )
+(1200 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.754167 Y13.546667 (start point)
+G1 Z#101
+G1 X22.606000 Y13.504333
+G1 X22.394333 Y13.398500
+G1 X22.267333 Y13.292667
+G1 X2.476500 Y13.292667
+G1 X2.264833 Y13.229167
+G1 X2.010833 Y12.975167
+G1 X1.947333 Y12.763500
+G1 X1.947333 Y12.615333
+G1 X2.010833 Y12.403667
+G1 X2.264833 Y12.149667
+G1 X2.476500 Y12.086167
+G1 X22.267333 Y12.086167
+G1 X22.436667 Y11.959167
+G1 X22.669500 Y11.853333
+G1 X23.071667 Y11.853333
+G1 X23.389167 Y12.001500
+G1 X23.579667 Y12.213167
+G1 X23.706667 Y12.488333
+G1 X23.706667 Y12.890500
+G1 X23.579667 Y13.165667
+G1 X23.389167 Y13.377333
+G1 X23.071667 Y13.525500
+G1 X22.754167 Y13.546667
+G0 Z#100
+(polygon end, distance 45.35)
+(end, total distance 45.35mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode4/Makefile.am b/tests/golden/hid_gcode4/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode4/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode4/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode4/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..d049972
--- /dev/null
+++ b/tests/golden/hid_gcode4/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:36:12 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=5.000000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode4/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode4/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..c648655
--- /dev/null
+++ b/tests/golden/hid_gcode4/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:36:12 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode4/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode4/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..78e64a5
--- /dev/null
+++ b/tests/golden/hid_gcode4/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:36:08 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=5.000000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode5/Makefile.am b/tests/golden/hid_gcode5/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode5/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode5/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode5/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..8041f98
--- /dev/null
+++ b/tests/golden/hid_gcode5/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 18:06:42 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=10.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode5/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode5/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..77d8d60
--- /dev/null
+++ b/tests/golden/hid_gcode5/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 18:06:42 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=10.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode5/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode5/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..e3bbd7e
--- /dev/null
+++ b/tests/golden/hid_gcode5/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 18:06:40 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=10.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode6/Makefile.am b/tests/golden/hid_gcode6/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode6/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode6/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode6/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..7d33799
--- /dev/null
+++ b/tests/golden/hid_gcode6/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,43 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:05 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X0.000000 Y25.400000 (start point)
+G1 Z#101
+G1 X0.000000 Y0.000000
+G1 X37.295667 Y0.000000
+G1 X38.057667 Y0.635000
+G1 X39.073667 Y1.524000
+G1 X39.962667 Y2.540000
+G1 X40.597667 Y3.302000
+G1 X41.486667 Y4.656667
+G1 X41.952333 Y5.503333
+G1 X42.418000 Y6.477000
+G1 X42.883667 Y7.704667
+G1 X43.264667 Y9.017000
+G1 X43.518667 Y10.329333
+G1 X43.645667 Y11.514667
+G1 X43.645667 Y13.843000
+G1 X43.518667 Y15.028333
+G1 X43.264667 Y16.340667
+G1 X42.883667 Y17.653000
+G1 X42.418000 Y18.880667
+G1 X41.952333 Y19.854333
+G1 X41.486667 Y20.701000
+G1 X40.597667 Y22.055667
+G1 X39.962667 Y22.817667
+G1 X39.073667 Y23.833667
+G1 X38.057667 Y24.722667
+G1 X37.253333 Y25.400000
+G1 X0.000000 Y25.400000
+G0 Z#100
+(polygon end, distance 129.45)
+(end, total distance 129.45mm = 5.10in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode6/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode6/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..6b44265
--- /dev/null
+++ b/tests/golden/hid_gcode6/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:05 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode6/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode6/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..7dfd6a0
--- /dev/null
+++ b/tests/golden/hid_gcode6/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,43 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:39:31 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X0.000000 Y25.400000 (start point)
+G1 Z#101
+G1 X0.000000 Y0.000000
+G1 X32.258000 Y0.000000
+G1 X33.020000 Y0.635000
+G1 X34.036000 Y1.524000
+G1 X34.925000 Y2.540000
+G1 X35.560000 Y3.302000
+G1 X36.449000 Y4.656667
+G1 X36.914667 Y5.503333
+G1 X37.380333 Y6.477000
+G1 X37.846000 Y7.704667
+G1 X38.227000 Y9.017000
+G1 X38.481000 Y10.329333
+G1 X38.608000 Y11.514667
+G1 X38.608000 Y13.843000
+G1 X38.481000 Y15.028333
+G1 X38.227000 Y16.340667
+G1 X37.846000 Y17.653000
+G1 X37.380333 Y18.880667
+G1 X36.914667 Y19.854333
+G1 X36.449000 Y20.701000
+G1 X35.560000 Y22.055667
+G1 X34.925000 Y22.817667
+G1 X34.036000 Y23.833667
+G1 X33.020000 Y24.722667
+G1 X32.215667 Y25.400000
+G1 X0.000000 Y25.400000
+G0 Z#100
+(polygon end, distance 119.38)
+(end, total distance 119.38mm = 4.70in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode7/Makefile.am b/tests/golden/hid_gcode7/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode7/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode7/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode7/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..b92e532
--- /dev/null
+++ b/tests/golden/hid_gcode7/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:12 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode7/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode7/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..e8c41bf
--- /dev/null
+++ b/tests/golden/hid_gcode7/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:12 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=70.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode7/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode7/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..4c64804
--- /dev/null
+++ b/tests/golden/hid_gcode7/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:08 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode8/Makefile.am b/tests/golden/hid_gcode8/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode8/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode8/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode8/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..286cab5
--- /dev/null
+++ b/tests/golden/hid_gcode8/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:19 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X27.770667 Y13.546667 (start point)
+G1 Z#101
+G1 X27.559000 Y13.462000
+G1 X27.305000 Y13.292667
+G1 X7.450667 Y13.292667
+G1 X7.196667 Y13.081000
+G1 X6.985000 Y12.827000
+G1 X6.985000 Y12.530667
+G1 X7.196667 Y12.276667
+G1 X7.450667 Y12.065000
+G1 X27.305000 Y12.065000
+G1 X27.643667 Y11.853333
+G1 X28.194000 Y11.853333
+G1 X28.532667 Y12.065000
+G1 X28.744333 Y12.403667
+G1 X28.744333 Y12.954000
+G1 X28.532667 Y13.292667
+G1 X28.194000 Y13.504333
+G1 X27.770667 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode8/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode8/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..77ac526
--- /dev/null
+++ b/tests/golden/hid_gcode8/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:19 2010 )
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-2.000000 (drill depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G81 X27.940000 Y12.700000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode8/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode8/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..a57aeb7
--- /dev/null
+++ b/tests/golden/hid_gcode8/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:16 2010 )
+(600 dpi)
+(Unit: mm)
+(Board size: 50.80x25.40 mm)
+#100=2.000000 (safe Z)
+#101=-0.050000 (cutting depth)
+(---------------------------------)
+G17 G21 G90 G64 P0.003 M3 S3000 M7 F25
+G0 Z#100
+(polygon 1)
+G0 X22.733000 Y13.546667 (start point)
+G1 Z#101
+G1 X22.521333 Y13.462000
+G1 X22.267333 Y13.292667
+G1 X2.413000 Y13.292667
+G1 X2.159000 Y13.081000
+G1 X1.947333 Y12.827000
+G1 X1.947333 Y12.530667
+G1 X2.159000 Y12.276667
+G1 X2.413000 Y12.065000
+G1 X22.267333 Y12.065000
+G1 X22.606000 Y11.853333
+G1 X23.156333 Y11.853333
+G1 X23.495000 Y12.065000
+G1 X23.706667 Y12.403667
+G1 X23.706667 Y12.954000
+G1 X23.495000 Y13.292667
+G1 X23.156333 Y13.504333
+G1 X22.733000 Y13.546667
+G0 Z#100
+(polygon end, distance 45.38)
+(end, total distance 45.38mm = 1.79in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode9/Makefile.am b/tests/golden/hid_gcode9/Makefile.am
new file mode 100644
index 0000000..b071e19
--- /dev/null
+++ b/tests/golden/hid_gcode9/Makefile.am
@@ -0,0 +1,6 @@
+## -*- makefile -*-
+
+EXTRA_DIST= \
+ gcode_oneline.gcode.back.cnc \
+ gcode_oneline.gcode.drill.cnc \
+ gcode_oneline.gcode.front.cnc
diff --git a/tests/golden/hid_gcode9/gcode_oneline.gcode.back.cnc b/tests/golden/hid_gcode9/gcode_oneline.gcode.back.cnc
new file mode 100644
index 0000000..49ebcd5
--- /dev/null
+++ b/tests/golden/hid_gcode9/gcode_oneline.gcode.back.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:25 2010 )
+(600 dpi)
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=0.002000 (safe Z)
+#101=-0.000050 (cutting depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G0 Z#100
+(polygon 1)
+G0 X1.093333 Y0.530000 (start point)
+G1 Z#101
+G1 X1.083333 Y0.525000
+G1 X1.076667 Y0.520000
+G1 X0.291667 Y0.518333
+G1 X0.280000 Y0.506667
+G1 X0.280000 Y0.491667
+G1 X0.291667 Y0.480000
+G1 X1.076667 Y0.478333
+G1 X1.088333 Y0.470000
+G1 X1.100000 Y0.468333
+G1 X1.113333 Y0.471667
+G1 X1.123333 Y0.480000
+G1 X1.130000 Y0.493333
+G1 X1.130000 Y0.505000
+G1 X1.123333 Y0.518333
+G1 X1.115000 Y0.525000
+G1 X1.103333 Y0.530000
+G1 X1.093333 Y0.530000
+G0 Z#100
+(polygon end, distance 1.77)
+(end, total distance 44.84mm = 1.77in)
+M5 M9 M2
diff --git a/tests/golden/hid_gcode9/gcode_oneline.gcode.drill.cnc b/tests/golden/hid_gcode9/gcode_oneline.gcode.drill.cnc
new file mode 100644
index 0000000..c4b730a
--- /dev/null
+++ b/tests/golden/hid_gcode9/gcode_oneline.gcode.drill.cnc
@@ -0,0 +1,12 @@
+(Created by G-code exporter)
+(drill file: 1 drills)
+( Tue Mar 9 17:45:25 2010 )
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=0.002000 (safe Z)
+#101=-0.002000 (drill depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G81 X1.100000 Y0.500000 Z#101 R#100
+M5 M9 M2
+(end, total distance 0.00mm = 0.00in)
diff --git a/tests/golden/hid_gcode9/gcode_oneline.gcode.front.cnc b/tests/golden/hid_gcode9/gcode_oneline.gcode.front.cnc
new file mode 100644
index 0000000..638cec1
--- /dev/null
+++ b/tests/golden/hid_gcode9/gcode_oneline.gcode.front.cnc
@@ -0,0 +1,34 @@
+(Created by G-code exporter)
+( Tue Mar 9 17:45:22 2010 )
+(600 dpi)
+(Unit: inch)
+(Board size: 2.00x1.00 inches)
+#100=0.002000 (safe Z)
+#101=-0.000050 (cutting depth)
+(---------------------------------)
+G17 G20 G90 G64 P0.003 M3 S3000 M7 F1
+G0 Z#100
+(polygon 1)
+G0 X0.895000 Y0.530000 (start point)
+G1 Z#101
+G1 X0.885000 Y0.525000
+G1 X0.878333 Y0.520000
+G1 X0.093333 Y0.518333
+G1 X0.081667 Y0.506667
+G1 X0.081667 Y0.491667
+G1 X0.093333 Y0.480000
+G1 X0.878333 Y0.478333
+G1 X0.890000 Y0.470000
+G1 X0.901667 Y0.468333
+G1 X0.915000 Y0.471667
+G1 X0.925000 Y0.480000
+G1 X0.931667 Y0.493333
+G1 X0.931667 Y0.505000
+G1 X0.925000 Y0.518333
+G1 X0.916667 Y0.525000
+G1 X0.905000 Y0.530000
+G1 X0.895000 Y0.530000
+G0 Z#100
+(polygon end, distance 1.77)
+(end, total distance 44.84mm = 1.77in)
+M5 M9 M2
diff --git a/tests/inputs/gcode_oneline.pcb b/tests/inputs/gcode_oneline.pcb
new file mode 100644
index 0000000..c20eacf
--- /dev/null
+++ b/tests/inputs/gcode_oneline.pcb
@@ -0,0 +1,832 @@
+# release: pcb 1.99y
+# date: Wed Jun 24 12:26:14 2009
+# user: dan (Dan McMahill,At Home ,258-8142,)
+# host: bondage
+
+# To read pcb files, the pcb version (or the cvs source date) must be >= the file version
+FileVersion[20070407]
+
+PCB["Basic Single Trace RS274-X Test" 200000 100000]
+
+Grid[10000.000000 0 0 1]
+Cursor[0 500000 0.000000]
+PolyArea[200000000.000000]
+Thermal[0.500000]
+DRC[1000 1000 1000 1000 1500 1000]
+Flags("nameonpcb,uniquename,clearnew,snappin")
+Groups("1,c:2,s:3:4:5:6:7:8")
+Styles["Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600"]
+
+Symbol(' ' 18)
+(
+)
+Symbol('!' 12)
+(
+ SymbolLine(0 45 0 50 8)
+ SymbolLine(0 10 0 35 8)
+)
+Symbol('"' 12)
+(
+ SymbolLine(0 10 0 20 8)
+ SymbolLine(10 10 10 20 8)
+)
+Symbol('#' 12)
+(
+ SymbolLine(0 35 20 35 8)
+ SymbolLine(0 25 20 25 8)
+ SymbolLine(15 20 15 40 8)
+ SymbolLine(5 20 5 40 8)
+)
+Symbol('$' 12)
+(
+ SymbolLine(15 15 20 20 8)
+ SymbolLine(5 15 15 15 8)
+ SymbolLine(0 20 5 15 8)
+ SymbolLine(0 20 0 25 8)
+ SymbolLine(0 25 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 40 8)
+ SymbolLine(15 45 20 40 8)
+ SymbolLine(5 45 15 45 8)
+ SymbolLine(0 40 5 45 8)
+ SymbolLine(10 10 10 50 8)
+)
+Symbol('%' 12)
+(
+ SymbolLine(0 15 0 20 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 10 10 8)
+ SymbolLine(10 10 15 15 8)
+ SymbolLine(15 15 15 20 8)
+ SymbolLine(10 25 15 20 8)
+ SymbolLine(5 25 10 25 8)
+ SymbolLine(0 20 5 25 8)
+ SymbolLine(0 50 40 10 8)
+ SymbolLine(35 50 40 45 8)
+ SymbolLine(40 40 40 45 8)
+ SymbolLine(35 35 40 40 8)
+ SymbolLine(30 35 35 35 8)
+ SymbolLine(25 40 30 35 8)
+ SymbolLine(25 40 25 45 8)
+ SymbolLine(25 45 30 50 8)
+ SymbolLine(30 50 35 50 8)
+)
+Symbol('&' 12)
+(
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 15 0 25 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 35 15 20 8)
+ SymbolLine(5 50 10 50 8)
+ SymbolLine(10 50 20 40 8)
+ SymbolLine(0 25 25 50 8)
+ SymbolLine(5 10 10 10 8)
+ SymbolLine(10 10 15 15 8)
+ SymbolLine(15 15 15 20 8)
+ SymbolLine(0 35 0 45 8)
+)
+Symbol(''' 12)
+(
+ SymbolLine(0 20 10 10 8)
+)
+Symbol('(' 12)
+(
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 15 0 45 8)
+)
+Symbol(')' 12)
+(
+ SymbolLine(0 10 5 15 8)
+ SymbolLine(5 15 5 45 8)
+ SymbolLine(0 50 5 45 8)
+)
+Symbol('*' 12)
+(
+ SymbolLine(0 20 20 40 8)
+ SymbolLine(0 40 20 20 8)
+ SymbolLine(0 30 20 30 8)
+ SymbolLine(10 20 10 40 8)
+)
+Symbol('+' 12)
+(
+ SymbolLine(0 30 20 30 8)
+ SymbolLine(10 20 10 40 8)
+)
+Symbol(',' 12)
+(
+ SymbolLine(0 60 10 50 8)
+)
+Symbol('-' 12)
+(
+ SymbolLine(0 30 20 30 8)
+)
+Symbol('.' 12)
+(
+ SymbolLine(0 50 5 50 8)
+)
+Symbol('/' 12)
+(
+ SymbolLine(0 45 30 15 8)
+)
+Symbol('0' 12)
+(
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 40 20 20 8)
+)
+Symbol('1' 12)
+(
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(10 10 10 50 8)
+ SymbolLine(0 20 10 10 8)
+)
+Symbol('2' 12)
+(
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 20 10 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 25 8)
+ SymbolLine(0 50 25 25 8)
+ SymbolLine(0 50 25 50 8)
+)
+Symbol('3' 12)
+(
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 30 20 30 8)
+)
+Symbol('4' 12)
+(
+ SymbolLine(0 30 20 10 8)
+ SymbolLine(0 30 25 30 8)
+ SymbolLine(20 10 20 50 8)
+)
+Symbol('5' 12)
+(
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(0 10 0 30 8)
+ SymbolLine(0 30 5 25 8)
+ SymbolLine(5 25 15 25 8)
+ SymbolLine(15 25 20 30 8)
+ SymbolLine(20 30 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('6' 12)
+(
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(0 30 15 30 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(20 35 20 45 8)
+)
+Symbol('7' 12)
+(
+ SymbolLine(0 50 25 25 8)
+ SymbolLine(25 10 25 25 8)
+ SymbolLine(0 10 25 10 8)
+)
+Symbol('8' 12)
+(
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 25 5 30 8)
+ SymbolLine(0 15 0 25 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 25 8)
+ SymbolLine(15 30 20 25 8)
+)
+Symbol('9' 12)
+(
+ SymbolLine(0 50 20 30 8)
+ SymbolLine(20 15 20 30 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 15 0 25 8)
+ SymbolLine(0 25 5 30 8)
+ SymbolLine(5 30 20 30 8)
+)
+Symbol(':' 12)
+(
+ SymbolLine(0 25 5 25 8)
+ SymbolLine(0 35 5 35 8)
+)
+Symbol(';' 12)
+(
+ SymbolLine(0 50 10 40 8)
+ SymbolLine(10 25 10 30 8)
+)
+Symbol('<' 12)
+(
+ SymbolLine(0 30 10 20 8)
+ SymbolLine(0 30 10 40 8)
+)
+Symbol('=' 12)
+(
+ SymbolLine(0 25 20 25 8)
+ SymbolLine(0 35 20 35 8)
+)
+Symbol('>' 12)
+(
+ SymbolLine(0 20 10 30 8)
+ SymbolLine(0 40 10 30 8)
+)
+Symbol('?' 12)
+(
+ SymbolLine(10 30 10 35 8)
+ SymbolLine(10 45 10 50 8)
+ SymbolLine(0 15 0 20 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 20 8)
+ SymbolLine(10 30 20 20 8)
+)
+Symbol('@' 12)
+(
+ SymbolLine(0 10 0 40 8)
+ SymbolLine(0 40 10 50 8)
+ SymbolLine(10 50 40 50 8)
+ SymbolLine(50 35 50 10 8)
+ SymbolLine(50 10 40 0 8)
+ SymbolLine(40 0 10 0 8)
+ SymbolLine(10 0 0 10 8)
+ SymbolLine(15 20 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 30 35 8)
+ SymbolLine(30 35 35 30 8)
+ SymbolLine(35 30 40 35 8)
+ SymbolLine(35 30 35 15 8)
+ SymbolLine(35 20 30 15 8)
+ SymbolLine(20 15 30 15 8)
+ SymbolLine(20 15 15 20 8)
+ SymbolLine(40 35 50 35 8)
+)
+Symbol('A' 12)
+(
+ SymbolLine(0 15 0 50 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 20 10 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 50 8)
+ SymbolLine(0 30 25 30 8)
+)
+Symbol('B' 12)
+(
+ SymbolLine(0 50 20 50 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(25 35 25 45 8)
+ SymbolLine(20 30 25 35 8)
+ SymbolLine(5 30 20 30 8)
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 25 8)
+ SymbolLine(20 30 25 25 8)
+)
+Symbol('C' 12)
+(
+ SymbolLine(5 50 20 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 20 10 8)
+)
+Symbol('D' 12)
+(
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 45 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(0 50 20 50 8)
+ SymbolLine(0 10 20 10 8)
+)
+Symbol('E' 12)
+(
+ SymbolLine(0 30 15 30 8)
+ SymbolLine(0 50 20 50 8)
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 10 20 10 8)
+)
+Symbol('F' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(0 30 15 30 8)
+)
+Symbol('G' 12)
+(
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(5 10 20 10 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 20 50 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(25 35 25 45 8)
+ SymbolLine(20 30 25 35 8)
+ SymbolLine(10 30 20 30 8)
+)
+Symbol('H' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(25 10 25 50 8)
+ SymbolLine(0 30 25 30 8)
+)
+Symbol('I' 12)
+(
+ SymbolLine(0 10 10 10 8)
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(0 50 10 50 8)
+)
+Symbol('J' 12)
+(
+ SymbolLine(0 10 15 10 8)
+ SymbolLine(15 10 15 45 8)
+ SymbolLine(10 50 15 45 8)
+ SymbolLine(5 50 10 50 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('K' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 30 20 10 8)
+ SymbolLine(0 30 20 50 8)
+)
+Symbol('L' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 50 20 50 8)
+)
+Symbol('M' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 10 15 25 8)
+ SymbolLine(15 25 30 10 8)
+ SymbolLine(30 10 30 50 8)
+)
+Symbol('N' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 10 0 15 8)
+ SymbolLine(0 15 25 40 8)
+ SymbolLine(25 10 25 50 8)
+)
+Symbol('O' 12)
+(
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('P' 12)
+(
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 25 8)
+ SymbolLine(20 30 25 25 8)
+ SymbolLine(5 30 20 30 8)
+)
+Symbol('Q' 12)
+(
+ SymbolLine(0 15 0 45 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 15 10 8)
+ SymbolLine(15 10 20 15 8)
+ SymbolLine(20 15 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(10 40 20 50 8)
+)
+Symbol('R' 12)
+(
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(25 15 25 25 8)
+ SymbolLine(20 30 25 25 8)
+ SymbolLine(5 30 20 30 8)
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(5 30 25 50 8)
+)
+Symbol('S' 12)
+(
+ SymbolLine(20 10 25 15 8)
+ SymbolLine(5 10 20 10 8)
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(0 15 0 25 8)
+ SymbolLine(0 25 5 30 8)
+ SymbolLine(5 30 20 30 8)
+ SymbolLine(20 30 25 35 8)
+ SymbolLine(25 35 25 45 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(5 50 20 50 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('T' 12)
+(
+ SymbolLine(0 10 20 10 8)
+ SymbolLine(10 10 10 50 8)
+)
+Symbol('U' 12)
+(
+ SymbolLine(0 10 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(20 10 20 45 8)
+)
+Symbol('V' 12)
+(
+ SymbolLine(0 10 0 40 8)
+ SymbolLine(0 40 10 50 8)
+ SymbolLine(10 50 20 40 8)
+ SymbolLine(20 10 20 40 8)
+)
+Symbol('W' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 50 15 35 8)
+ SymbolLine(15 35 30 50 8)
+ SymbolLine(30 10 30 50 8)
+)
+Symbol('X' 12)
+(
+ SymbolLine(0 10 0 15 8)
+ SymbolLine(0 15 25 40 8)
+ SymbolLine(25 40 25 50 8)
+ SymbolLine(0 40 0 50 8)
+ SymbolLine(0 40 25 15 8)
+ SymbolLine(25 10 25 15 8)
+)
+Symbol('Y' 12)
+(
+ SymbolLine(0 10 0 15 8)
+ SymbolLine(0 15 10 25 8)
+ SymbolLine(10 25 20 15 8)
+ SymbolLine(20 10 20 15 8)
+ SymbolLine(10 25 10 50 8)
+)
+Symbol('Z' 12)
+(
+ SymbolLine(0 10 25 10 8)
+ SymbolLine(25 10 25 15 8)
+ SymbolLine(0 40 25 15 8)
+ SymbolLine(0 40 0 50 8)
+ SymbolLine(0 50 25 50 8)
+)
+Symbol('[' 12)
+(
+ SymbolLine(0 10 5 10 8)
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 50 5 50 8)
+)
+Symbol('\' 12)
+(
+ SymbolLine(0 15 30 45 8)
+)
+Symbol(']' 12)
+(
+ SymbolLine(0 10 5 10 8)
+ SymbolLine(5 10 5 50 8)
+ SymbolLine(0 50 5 50 8)
+)
+Symbol('^' 12)
+(
+ SymbolLine(0 15 5 10 8)
+ SymbolLine(5 10 10 15 8)
+)
+Symbol('_' 12)
+(
+ SymbolLine(0 50 20 50 8)
+)
+Symbol('a' 12)
+(
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(20 30 20 45 8)
+ SymbolLine(20 45 25 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+)
+Symbol('b' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(20 35 20 45 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(0 35 5 30 8)
+)
+Symbol('c' 12)
+(
+ SymbolLine(5 30 20 30 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 20 50 8)
+)
+Symbol('d' 12)
+(
+ SymbolLine(20 10 20 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+)
+Symbol('e' 12)
+(
+ SymbolLine(5 50 20 50 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(0 40 20 40 8)
+ SymbolLine(20 40 20 35 8)
+)
+Symbol('f' 10)
+(
+ SymbolLine(5 15 5 50 8)
+ SymbolLine(5 15 10 10 8)
+ SymbolLine(10 10 15 10 8)
+ SymbolLine(0 30 10 30 8)
+)
+Symbol('g' 12)
+(
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(0 60 5 65 8)
+ SymbolLine(5 65 15 65 8)
+ SymbolLine(15 65 20 60 8)
+ SymbolLine(20 30 20 60 8)
+)
+Symbol('h' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 50 8)
+)
+Symbol('i' 10)
+(
+ SymbolLine(0 20 0 25 8)
+ SymbolLine(0 35 0 50 8)
+)
+Symbol('j' 10)
+(
+ SymbolLine(5 20 5 25 8)
+ SymbolLine(5 35 5 60 8)
+ SymbolLine(0 65 5 60 8)
+)
+Symbol('k' 12)
+(
+ SymbolLine(0 10 0 50 8)
+ SymbolLine(0 35 15 50 8)
+ SymbolLine(0 35 10 25 8)
+)
+Symbol('l' 10)
+(
+ SymbolLine(0 10 0 45 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('m' 12)
+(
+ SymbolLine(5 35 5 50 8)
+ SymbolLine(5 35 10 30 8)
+ SymbolLine(10 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 50 8)
+ SymbolLine(20 35 25 30 8)
+ SymbolLine(25 30 30 30 8)
+ SymbolLine(30 30 35 35 8)
+ SymbolLine(35 35 35 50 8)
+ SymbolLine(0 30 5 35 8)
+)
+Symbol('n' 12)
+(
+ SymbolLine(5 35 5 50 8)
+ SymbolLine(5 35 10 30 8)
+ SymbolLine(10 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 50 8)
+ SymbolLine(0 30 5 35 8)
+)
+Symbol('o' 12)
+(
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(20 35 20 45 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('p' 12)
+(
+ SymbolLine(5 35 5 65 8)
+ SymbolLine(0 30 5 35 8)
+ SymbolLine(5 35 10 30 8)
+ SymbolLine(10 30 20 30 8)
+ SymbolLine(20 30 25 35 8)
+ SymbolLine(25 35 25 45 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(10 50 20 50 8)
+ SymbolLine(5 45 10 50 8)
+)
+Symbol('q' 12)
+(
+ SymbolLine(20 35 20 65 8)
+ SymbolLine(15 30 20 35 8)
+ SymbolLine(5 30 15 30 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(0 35 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+)
+Symbol('r' 12)
+(
+ SymbolLine(5 35 5 50 8)
+ SymbolLine(5 35 10 30 8)
+ SymbolLine(10 30 20 30 8)
+ SymbolLine(0 30 5 35 8)
+)
+Symbol('s' 12)
+(
+ SymbolLine(5 50 20 50 8)
+ SymbolLine(20 50 25 45 8)
+ SymbolLine(20 40 25 45 8)
+ SymbolLine(5 40 20 40 8)
+ SymbolLine(0 35 5 40 8)
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 20 30 8)
+ SymbolLine(20 30 25 35 8)
+ SymbolLine(0 45 5 50 8)
+)
+Symbol('t' 10)
+(
+ SymbolLine(5 10 5 45 8)
+ SymbolLine(5 45 10 50 8)
+ SymbolLine(0 25 10 25 8)
+)
+Symbol('u' 12)
+(
+ SymbolLine(0 30 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+ SymbolLine(20 30 20 45 8)
+)
+Symbol('v' 12)
+(
+ SymbolLine(0 30 0 40 8)
+ SymbolLine(0 40 10 50 8)
+ SymbolLine(10 50 20 40 8)
+ SymbolLine(20 30 20 40 8)
+)
+Symbol('w' 12)
+(
+ SymbolLine(0 30 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(5 50 10 50 8)
+ SymbolLine(10 50 15 45 8)
+ SymbolLine(15 30 15 45 8)
+ SymbolLine(15 45 20 50 8)
+ SymbolLine(20 50 25 50 8)
+ SymbolLine(25 50 30 45 8)
+ SymbolLine(30 30 30 45 8)
+)
+Symbol('x' 12)
+(
+ SymbolLine(0 30 20 50 8)
+ SymbolLine(0 50 20 30 8)
+)
+Symbol('y' 12)
+(
+ SymbolLine(0 30 0 45 8)
+ SymbolLine(0 45 5 50 8)
+ SymbolLine(20 30 20 60 8)
+ SymbolLine(15 65 20 60 8)
+ SymbolLine(5 65 15 65 8)
+ SymbolLine(0 60 5 65 8)
+ SymbolLine(5 50 15 50 8)
+ SymbolLine(15 50 20 45 8)
+)
+Symbol('z' 12)
+(
+ SymbolLine(0 30 20 30 8)
+ SymbolLine(0 50 20 30 8)
+ SymbolLine(0 50 20 50 8)
+)
+Symbol('{' 12)
+(
+ SymbolLine(5 15 10 10 8)
+ SymbolLine(5 15 5 25 8)
+ SymbolLine(0 30 5 25 8)
+ SymbolLine(0 30 5 35 8)
+ SymbolLine(5 35 5 45 8)
+ SymbolLine(5 45 10 50 8)
+)
+Symbol('|' 12)
+(
+ SymbolLine(0 10 0 50 8)
+)
+Symbol('}' 12)
+(
+ SymbolLine(0 10 5 15 8)
+ SymbolLine(5 15 5 25 8)
+ SymbolLine(5 25 10 30 8)
+ SymbolLine(5 35 10 30 8)
+ SymbolLine(5 35 5 45 8)
+ SymbolLine(0 50 5 45 8)
+)
+Symbol('~' 12)
+(
+ SymbolLine(0 35 5 30 8)
+ SymbolLine(5 30 10 30 8)
+ SymbolLine(10 30 15 35 8)
+ SymbolLine(15 35 20 35 8)
+ SymbolLine(20 35 25 30 8)
+)
+Via[90000 50000 6000 2000 0 3500 "" ""]
+Layer(1 "component")
+(
+ Line[10000 50000 90000 50000 4000 2000 "clearline"]
+)
+Layer(2 "solder")
+(
+ Line[170000 50000 90000 50000 4000 2000 "clearline"]
+)
+Layer(3 "GND")
+(
+)
+Layer(4 "power")
+(
+)
+Layer(5 "signal1")
+(
+)
+Layer(6 "signal2")
+(
+)
+Layer(7 "signal3")
+(
+)
+Layer(8 "signal4")
+(
+)
+Layer(9 "silk")
+(
+)
+Layer(10 "silk")
+(
+)
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 3892856..0667fb8 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -333,7 +333,7 @@ compare_bom() {
# 8,"Dual in-line package, narrow (300 mil)","DIP8",UDIP90_TOP UDIP180_TOP UDIP270_TOP UDIP0_TOP UDIP270_BOT UDIP180_BOT UDIP90_BOT UDIP0_BOT
# 8,"Small outline package, narrow (150mil)","SO8",USO90_TOP USO180_TOP USO270_TOP USO0_TOP USO270_BOT USO180_BOT USO90_BOT USO0_BOT
- # For comparison, we need to ignore chnages in the Date and Author lines.
+ # For comparison, we need to ignore changes in the Date and Author lines.
cf1=${tmpd}/`basename $f1`
cf2=${tmpd}/`basename $f2`
@@ -355,6 +355,36 @@ compare_xy() {
##########################################################################
#
+# GCODE comparison routines
+#
+
+# used to remove things like creation date from gcode files
+normalize_gcode() {
+ f1="$1"
+ f2="$2"
+ $AWK '
+ d == 1 {gsub(/ .* /, "Creation Date and Time"); d = 0;}
+ /^\(Created by G-code exporter\)/ {d=1}
+ {print}' \
+ $f1 > $f2
+}
+
+compare_gcode() {
+ f1="$1"
+ f2="$2"
+ compare_check "compare_gcode" "$f1" "$f2" || return 1
+
+ # For comparison, we need to ignore changes in the Date and Author lines.
+ cf1=${tmpd}/`basename $f1`
+ cf2=${tmpd}/`basename $f2`
+
+ normalize_gcode $f1 $cf1
+ normalize_gcode $f2 $cf2
+ run_diff "$cf1" "$cf2" || test_failed=yes
+}
+
+##########################################################################
+#
# RS274-X and Excellon comparison
#
@@ -549,6 +579,11 @@ for t in $all_tests ; do
compare_xy ${refdir}/${fn} ${rundir}/${fn}
;;
+ # GCODE HID
+ gcode)
+ compare_gcode ${refdir}/${fn} ${rundir}/${fn}
+ ;;
+
# GERBER HID
cnc)
compare_cnc ${refdir}/${fn} ${rundir}/${fn}
diff --git a/tests/tests.list b/tests/tests.list
index 8949763..95af71d 100644
--- a/tests/tests.list
+++ b/tests/tests.list
@@ -55,6 +55,12 @@
# bom -- PCB bill of materials file
# xy -- PCB centroid file
#
+# GCODE
+#
+# gcode -- G-Code file. Note that these typically have .cnc as the
+# extension but we're already using the 'cnc' type for
+# Excellon drill files.
+#
# GERBER
#
# cnc -- Excellon drill file
@@ -66,7 +72,6 @@
# jpg -- JPEG file
# png -- Portable network graphics (PNG) file
#
-#
######################################################################
# ---------------------------------------------
# BOM export HID
@@ -88,6 +93,33 @@ hid_bom4 | bom_general.pcb | bom | --xy-in-mm | | bom:bom_general.bom xy:bom_ge
#
######################################################################
# ---------------------------------------------
+# Gcode export HID
+# ---------------------------------------------
+######################################################################
+#
+# options:
+# --basename <string> File name prefix
+# --dpi <num> Resolution of intermediate image (pixels/inch).
+# --mill depth <num> Milling depth.
+# --safe Z <num> Safe Z for traverse move.
+# --tool radius <num> Milling tool radius compensation.
+# --drill depth <num> Drilling depth.
+# --measurement unit <mm|mil|um|inch> Measurement unit
+#
+hid_gcode1 | gcode_oneline.pcb | gcode | | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode2 | gcode_oneline.pcb | gcode | --basename out | | gcode:out.front.cnc gcode:out.back.cnc gcode:out.drill.cnc
+hid_gcode3 | gcode_oneline.pcb | gcode | --dpi 1200 | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode4 | gcode_oneline.pcb | gcode | --mill-depth 5 | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode5 | gcode_oneline.pcb | gcode | --safe-Z 10 | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode6 | gcode_oneline.pcb | gcode | --tool-radius 15 | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode7 | gcode_oneline.pcb | gcode | --drill-depth 70 | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode8 | gcode_oneline.pcb | gcode | --measurement-unit mm | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode9 | gcode_oneline.pcb | gcode | --measurement-unit mil | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode10 | gcode_oneline.pcb | gcode | --measurement-unit um | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+hid_gcode11 | gcode_oneline.pcb | gcode | --measurement-unit inch | | gcode:gcode_oneline.gcode.front.cnc gcode:gcode_oneline.gcode.back.cnc gcode:gcode_oneline.gcode.drill.cnc
+#
+######################################################################
+# ---------------------------------------------
# Gerber export HID
# ---------------------------------------------
######################################################################
@@ -129,4 +161,3 @@ hid_gerber2 | gerber_oneline.pcb | gerber | --gerberfile out | | gbx:out.back.gb
hid_png1 | gerber_oneline.pcb | png | | | png:gerber_oneline.png
#
-
commit fd1c65c236bdcd4b36400e82074d66ab83bc5de3
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove RCSID. We don't use those anymore.
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index 3767ad4..bbc1d53 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -64,8 +64,6 @@
#include <dmalloc.h>
#endif
-RCSID ("$Id: gcode.c, v 0.1 2010/2/8 14:00:00 Alberto Maccioni Exp $");
-
#define CRASH fprintf(stderr, "HID error: pcb called unimplemented GCODE function %s.\n", __FUNCTION__); abort()
#define pcb_unit 100000.0 /* pcb internal units per inch */
struct color_struct
commit b6378a3845066adb23601d8fa781fd58233176dd
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Change options like 'drill depth' to 'drill-depth' as a space in
a command line option is non-standard. Also be consistent with
having or not having a "." at the end of the option help strings.
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index c5ca8df..3767ad4 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -148,27 +148,27 @@ HID_Attribute gcode_attribute_list[] = {
HID_String, 0, 0, {0, 0, 0}, 0, 0},
#define HA_basename 0
- {"dpi", "Resolution of intermediate image (pixels/inch).",
+ {"dpi", "Resolution of intermediate image (pixels/inch)",
HID_Integer, 0, 2000, {600, 0, 0}, 0, 0},
#define HA_dpi 1
- {"mill depth", "Milling depth.",
+ {"mill-depth", "Milling depth",
HID_Real, -1000, 1000, {0, 0, -0.05}, 0, 0},
#define HA_cutdepth 2
- {"safe Z", "Safe Z for traverse move.",
+ {"safe-Z", "Safe Z for traverse move",
HID_Real, -1000, 10000, {0, 0, 2}, 0, 0},
#define HA_safeZ 3
- {"tool radius", "Milling tool radius compensation.",
+ {"tool-radius", "Milling tool radius compensation",
HID_Real, 0, 10000, {0, 0, 0.1}, 0, 0},
#define HA_toolradius 4
- {"drill depth", "Drilling depth.",
+ {"drill-depth", "Drilling depth",
HID_Real, -10000, 10000, {0, 0, -2}, 0, 0},
#define HA_drilldepth 5
- {"measurement unit", "Measurement unit",
+ {"measurement-unit", "Measurement unit",
HID_Enum, 0, 0, {0, 0, 0}, units, 0},
#define HA_unit 6
commit c544e63eca400b33127ac539e4737c7959e8db2c
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Remove unix2dos system() call. It was not needed.
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index 317e6a1..c5ca8df 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -617,7 +617,7 @@ gcode_do_export (HID_Attr_Val * options)
n_drill = nmax_drill = 0;
}
free (filename);
- system ("unix2dos *.cnc");
+
/* ******************* end gcode conversion **************************** */
gcode_finish_png ();
}
commit 9babb216b2921ad716b740068988d04a0d9dfe45
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Get rid of compiler warnings.
diff --git a/src/hid/gcode/trace.c b/src/hid/gcode/trace.c
index 5f1c48e..8d7e5e6 100644
--- a/src/hid/gcode/trace.c
+++ b/src/hid/gcode/trace.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
+#include "global.h"
#include "potracelib.h"
#include "curve.h"
#include "lists.h"
@@ -968,7 +969,7 @@ malloc_error:
/* Always succeeds and returns 0 */
static int
-smooth (privcurve_t * curve, int sign, double alphamax)
+ATTRIBUTE_UNUSED smooth (privcurve_t * curve, int sign, double alphamax)
{
int m = curve->n;
@@ -1233,7 +1234,7 @@ opti_penalty (privpath_t * pp, int i, int j, opti_t * res,
single segment when possible. Return 0 on success, 1 with errno set
on failure. */
static int
-opticurve (privpath_t * pp, double opttolerance)
+ATTRIBUTE_UNUSED opticurve (privpath_t * pp, double opttolerance)
{
int m = pp->curve.n;
int *pt = NULL; /* pt[m+1] */
@@ -1404,15 +1405,23 @@ plotpolygon (privpath_t * pp, FILE * f, double scale)
{
int i;
int m = pp->m;
- if (!m)
- return 0;
int *po = pp->po;
int n = pp->len;
point_t *pt = pp->pt;
int x0 = pp->x0;
int y0 = pp->y0;
- //double scale=1.0/dpi;
+ /* double scale=1.0/dpi; */
double dm = 0;
+
+ if (!m)
+ return 0;
+
+ po = pp->po;
+ n = pp->len;
+ pt = pp->pt;
+ x0 = pp->x0;
+ y0 = pp->y0;
+
fprintf (f, "G0 X%f Y%f (start point)\n", pt[po[0]].x * scale,
pt[po[0]].y * scale);
fprintf (f, "G1 Z#101\n");
@@ -1447,7 +1456,6 @@ process_path (path_t * plist, const potrace_param_t * param,
const potrace_bitmap_t * bm, FILE * f, double scale)
{
path_t *p;
- double nn = 0, cn = 0;
double dm = 0;
int n = 0;
/* call downstream function with each path */
@@ -1469,7 +1477,7 @@ process_path (path_t * plist, const potrace_param_t * param,
}
privcurve_to_curve(p->priv->fcurve, &p->curve);*/
}
-// fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm);
+/* fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm); */
return dm;
try_error:
commit 0e008cb83dcfc4fc6a3455bdd3c8dd86ed65b374
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Get rid of some gcc warnings.
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index 6d022ce..317e6a1 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -216,6 +216,7 @@ sort_drill (struct drill_struct *drill, int n_drill)
for (j = 0; j < n_drill; j++)
{
dmin = 1e20;
+ imin = 0;
for (i = 0; i < n_drill - j; i++)
{
d =
@@ -626,7 +627,7 @@ gcode_do_export (HID_Attr_Val * options)
/* *** PNG export (slightly modified code from PNG export HID) ************* */
static int
-gcode_set_layer (const char *name, int group)
+gcode_set_layer (const char *name, int group, int empty)
{
int idx = (group >= 0 && group < max_layer) ?
PCB->LayerGroups.Entries[group][0] : group;
commit 290c968566837132afbfc63d5fe1436c03dcec1e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
C++ style comments -> C style comments
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index e8c38db..6d022ce 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -67,7 +67,7 @@
RCSID ("$Id: gcode.c, v 0.1 2010/2/8 14:00:00 Alberto Maccioni Exp $");
#define CRASH fprintf(stderr, "HID error: pcb called unimplemented GCODE function %s.\n", __FUNCTION__); abort()
-#define pcb_unit 100000.0 //pcb internal units per inch
+#define pcb_unit 100000.0 /* pcb internal units per inch */
struct color_struct
{
/* the descriptor used by the gd library */
@@ -119,10 +119,10 @@ static char *gcode_basename = NULL;
/* Horizontal DPI (grid points per inch) */
static int gcode_dpi = -1;
-static double gcode_cutdepth = 0; //milling depth (inch)
-static double gcode_drilldepth = 0; //drilling depth (inch)
-static double gcode_safeZ = 100; //safe Z (inch)
-static double gcode_toolradius = 0; //tool radius(inch)
+static double gcode_cutdepth = 0; /* milling depth (inch) */
+static double gcode_drilldepth = 0; /* drilling depth (inch) */
+static double gcode_safeZ = 100; /* safe Z (inch) */
+static double gcode_toolradius = 0; /* tool radius(inch) */
static int save_drill = 0;
static int n_drill = 0;
static int nmax_drill = 0;
@@ -186,7 +186,7 @@ REGISTER_ATTRIBUTES (gcode_attribute_list)
{
int gcode;
- gcode = (pcb * gcode_dpi) / pcb_unit; //100000;
+ gcode = (pcb * gcode_dpi) / pcb_unit;
return gcode;
}
@@ -205,7 +205,7 @@ gcode_get_png_name (const char *basename, const char *suffix)
return buf;
}
-//Sorts drills in order of distance from the origin
+/* Sorts drills in order of distance from the origin */
struct drill_struct *
sort_drill (struct drill_struct *drill, int n_drill)
{
@@ -228,7 +228,7 @@ sort_drill (struct drill_struct *drill, int n_drill)
dmin = d;
}
}
- //printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y);
+ /* printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y); */
temp[j] = drill[imin];
drill[imin] = drill[n_drill - j - 1];
p = temp[j];
@@ -390,16 +390,16 @@ gcode_do_export (HID_Attr_Val * options)
path_t *plist = NULL;
potrace_bitmap_t *bm = NULL;
potrace_param_t param_default = {
- 2, // turdsize
- POTRACE_TURNPOLICY_MINORITY, // turnpolicy
- 1.0, // alphamax
- 1, // opticurve
- 0.2, // opttolerance
+ 2, /* turnsize */
+ POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */
+ 1.0, /* alphamax */
+ 1, /* opticurve */
+ 0.2, /* opttolerance */
{
- NULL, // callback function
- NULL, // callback data
- 0.0, 1.0, // progress range
- 0.0, // granularity
+ NULL, /* callback function */
+ NULL, /* callback data */
+ 0.0, 1.0, /* progress range */
+ 0.0, /* granularity */
},
};
@@ -428,25 +428,25 @@ gcode_do_export (HID_Attr_Val * options)
switch (options[HA_unit].int_value)
{
case 0:
- scale = 1.0; //mm
+ scale = 1.0; /* mm */
metric = 1;
break;
case 1:
- scale = 0.001; //mil
+ scale = 0.001; /* mil */
metric = 0;
break;
case 2:
- scale = 0.001; //um
+ scale = 0.001; /* um */
metric = 1;
break;
default:
- scale = 1.0; //inch
+ scale = 1.0; /* inch */
metric = 0;
}
gcode_cutdepth = options[HA_cutdepth].real_value * scale;
gcode_drilldepth = options[HA_drilldepth].real_value * scale;
gcode_safeZ = options[HA_safeZ].real_value * scale;
- gcode_toolradius = options[HA_toolradius].real_value * scale * pcb_unit; //in PCB units (1/100 mil)
+ gcode_toolradius = options[HA_toolradius].real_value * scale * pcb_unit; /* in PCB units (1/100 mil) */
if (metric)
gcode_toolradius *= 1 / 25.4;
gcode_choose_groups ();
@@ -465,19 +465,19 @@ gcode_do_export (HID_Attr_Val * options)
is_solder =
(GetLayerGroupNumberByNumber (idx) ==
GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER)) ? 1 : 0;
- save_drill = is_solder; //save drills for one layer only
+ save_drill = is_solder; /* save drills for one layer only */
gcode_start_png (gcode_basename, layer_type_to_file_name (idx));
hid_save_and_show_layer_ons (save_ons);
gcode_start_png_export ();
hid_restore_layer_ons (save_ons);
-//***************** gcode conversion ***************************
-// potrace uses a different kind of bitmap; for simplicity gcode_im is copied to this format
+/* ***************** gcode conversion *************************** */
+/* potrace uses a different kind of bitmap; for simplicity gcode_im is copied to this format */
bm = bm_new (gdImageSX (gcode_im), gdImageSY (gcode_im));
filename = malloc (512);
plist = NULL;
if (is_solder)
- { //only for back layer
+ { /* only for back layer */
gdImagePtr temp_im =
gdImageCreate (gdImageSX (gcode_im), gdImageSY (gcode_im));
gdImageCopy (temp_im, gcode_im, 0, 0, 0, 0,
@@ -532,14 +532,14 @@ gcode_do_export (HID_Attr_Val * options)
fprintf (gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",
metric ? 21 : 20, metric ? 25 : 1);
fprintf (gcode_f2, "G0 Z#100\n");
- //extract contour points from image
+ /* extract contour points from image */
r = bm_to_pathlist (bm, &plist, ¶m_default);
if (r)
{
fprintf (stderr, "ERROR: pathlist function failed\n");
return;
}
- //generate best polygon and write vertices in g-code format
+ /* generate best polygon and write vertices in g-code format */
d =
process_path (plist, ¶m_default, bm, gcode_f2,
metric ? 25.4 / gcode_dpi : 1.0 / gcode_dpi);
@@ -587,19 +587,19 @@ gcode_do_export (HID_Attr_Val * options)
fprintf (gcode_f2, "(---------------------------------)\n");
fprintf (gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",
metric ? 21 : 20, metric ? 25 : 1);
-// fprintf(gcode_f2,"G0 Z#100\n");
+/* fprintf(gcode_f2,"G0 Z#100\n"); */
for (r = 0; r < n_drill; r++)
{
-// if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4);
-// else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y);
+/* if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4); */
+/* else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y); */
if (metric)
fprintf (gcode_f2, "G81 X%f Y%f Z#101 R#100\n",
drill[r].x * 25.4, drill[r].y * 25.4);
else
fprintf (gcode_f2, "G81 X%f Y%f Z#101 R#100\n",
drill[r].x, drill[r].y);
-// fprintf(gcode_f2,"G1 Z#101\n");
-// fprintf(gcode_f2,"G0 Z#100\n");
+/* fprintf(gcode_f2,"G1 Z#101\n"); */
+/* fprintf(gcode_f2,"G0 Z#100\n"); */
if (r > 0)
d +=
sqrt ((drill[r].x - drill[r - 1].x) * (drill[r].x -
@@ -617,7 +617,7 @@ gcode_do_export (HID_Attr_Val * options)
}
free (filename);
system ("unix2dos *.cnc");
-//******************* end gcode conversion ****************************
+/* ******************* end gcode conversion **************************** */
gcode_finish_png ();
}
}
@@ -873,7 +873,7 @@ gcode_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
pcb_to_gcode (y1 - gcode_toolradius),
pcb_to_gcode (x2 + gcode_toolradius),
pcb_to_gcode (y2 + gcode_toolradius), gc->color->c);
-// printf("Rect %d %d %d %d\n",x1,y1,x2,y2);
+/* printf("Rect %d %d %d %d\n",x1,y1,x2,y2); */
}
static void
@@ -887,7 +887,7 @@ gcode_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
pcb_to_gcode (y1 - gcode_toolradius),
pcb_to_gcode (x2 + gcode_toolradius),
pcb_to_gcode (y2 + gcode_toolradius), gc->color->c);
-// printf("FillRect %d %d %d %d\n",x1,y1,x2,y2);
+/* printf("FillRect %d %d %d %d\n",x1,y1,x2,y2); */
}
static void
@@ -983,10 +983,10 @@ gcode_fill_circle (hidGC gc, int cx, int cy, int radius)
sizeof (struct drill_struct));
nmax_drill += 100;
}
- drill[n_drill].x = (PCB->MaxWidth - cx) / pcb_unit; //convert to inch, flip: will drill from bottom side
- drill[n_drill].y = (PCB->MaxHeight - cy) / pcb_unit; //PCB reverses y axis
+ drill[n_drill].x = (PCB->MaxWidth - cx) / pcb_unit; /* convert to inch, flip: will drill from bottom side */
+ drill[n_drill].y = (PCB->MaxHeight - cy) / pcb_unit; /* PCB reverses y axis */
n_drill++;
-// printf("Circle %d %d\n",cx,cy);
+/* printf("Circle %d %d\n",cx,cy); */
}
}
@@ -1012,7 +1012,7 @@ gcode_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
linewidth = 0;
gdImageFilledPolygon (gcode_im, points, n_coords, gc->color->c);
free (points);
-// printf("FillPoly\n");
+/* printf("FillPoly\n"); */
}
static void
@@ -1098,3 +1098,4 @@ hid_gcode_init ()
#include "gcode_lists.h"
}
+
commit 073463e605095692e2cf8d4238df0c817e68e3c3
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Fix nroff error. Noted in sf patch #2889227 by Ahmed El-Mahmoudy.
diff --git a/doc/pcb.1 b/doc/pcb.1
index 3dd9867..b84c653 100644
--- a/doc/pcb.1
+++ b/doc/pcb.1
@@ -1,4 +1,3 @@
-.\" $Id$
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
@@ -36,8 +35,8 @@ The texinfo version of the manual is typically viewed with the
program or alternatively with
.B emacs
or a graphical info viewer such as
-.B tkinfo
-. The PDF and HTML documentation is typically installed as
+.B tkinfo.
+The PDF and HTML documentation is typically installed as
/usr/local/share/pcb/pcb.html and /usr/local/share/pcb/pcb.pdf.
The prefix "/usr/local" may vary at your site.
commit ca738957694927538dad15f037d5622571fd3173
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
add the gcode exporter to the export hid list
diff --git a/configure.ac b/configure.ac
index d5578fb..356e02e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -395,7 +395,7 @@ esac
AC_MSG_CHECKING([for which exporters to use])
AC_ARG_WITH([exporters],
-[ --with-exporters= Enable export devices: bom gerber nelma png ps [[default=bom gerber nelma png ps]]],
+[ --with-exporters= Enable export devices: bom gerber gcode nelma png ps [[default=bom gerber gcode nelma png ps]]],
[],[with_exporters=$hid_exporters])
AC_MSG_RESULT([$with_exporters])
for e in `echo $with_exporters | sed 's/,/ /g'`; do
commit 7467c8b2cedb80ee32e2ff19662d6894a6d7f345
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
add notes about what libs may be needed (none) for the gcode exporter.
diff --git a/INSTALL b/INSTALL
index 1dfa0f8..db27639 100644
--- a/INSTALL
+++ b/INSTALL
@@ -59,6 +59,9 @@ Export HID's:
formats hopefully it will avoid suprises when the
disabled formats are not available at runtime.
+ gcode -- CNC G-CODE output (experimental). No
+ additional libraries are needed for this.
+
The choice of which export HID's to compile is indicated with:
--with-exporters="ps gerber bom png"
commit 19f7443c3249a9cc40efd04c1895b89445add385
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
indent to conform to the coding style used by pcb.
diff --git a/src/hid/gcode/auxiliary.h b/src/hid/gcode/auxiliary.h
index 7baab85..254e4c0 100644
--- a/src/hid/gcode/auxiliary.h
+++ b/src/hid/gcode/auxiliary.h
@@ -17,7 +17,8 @@
#include "potracelib.h"
-struct point_s {
+struct point_s
+{
long x;
long y;
};
@@ -26,7 +27,9 @@ typedef struct point_s point_t;
typedef potrace_dpoint_t dpoint_t;
/* convert point_t to dpoint_t */
-static inline dpoint_t dpoint(point_t p) {
+static inline dpoint_t
+dpoint (point_t p)
+{
dpoint_t res;
res.x = p.x;
res.y = p.y;
@@ -34,7 +37,9 @@ static inline dpoint_t dpoint(point_t p) {
}
/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
-static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
+static inline dpoint_t
+interval (double lambda, dpoint_t a, dpoint_t b)
+{
dpoint_t res;
res.x = a.x + lambda * (b.x - a.x);
@@ -53,12 +58,16 @@ static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
/* integer arithmetic */
-static inline int mod(int a, int n) {
- return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
+static inline int
+mod (int a, int n)
+{
+ return a >= n ? a % n : a >= 0 ? a : n - 1 - (-1 - a) % n;
}
-static inline int floordiv(int a, int n) {
- return a>=0 ? a/n : -1-(-1-a)/n;
+static inline int
+floordiv (int a, int n)
+{
+ return a >= 0 ? a / n : -1 - (-1 - a) / n;
}
/* Note: the following work for integers and other numeric types. */
diff --git a/src/hid/gcode/bitmap.h b/src/hid/gcode/bitmap.h
index 2a172b1..589b80b 100644
--- a/src/hid/gcode/bitmap.h
+++ b/src/hid/gcode/bitmap.h
@@ -48,54 +48,69 @@
#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
/* free the given bitmap. Leaves errno untouched. */
-static inline void bm_free(potrace_bitmap_t *bm) {
- if (bm) {
- free(bm->map);
- }
- free(bm);
+static inline void
+bm_free (potrace_bitmap_t * bm)
+{
+ if (bm)
+ {
+ free (bm->map);
+ }
+ free (bm);
}
/* return new un-initialized bitmap. NULL with errno on error */
-static inline potrace_bitmap_t *bm_new(int w, int h) {
+static inline potrace_bitmap_t *
+bm_new (int w, int h)
+{
potrace_bitmap_t *bm;
int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
- bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
- if (!bm) {
- return NULL;
- }
+ bm = (potrace_bitmap_t *) malloc (sizeof (potrace_bitmap_t));
+ if (!bm)
+ {
+ return NULL;
+ }
bm->w = w;
bm->h = h;
bm->dy = dy;
- bm->map = (potrace_word *) malloc(dy * h * BM_WORDSIZE);
- if (!bm->map) {
- free(bm);
- return NULL;
- }
+ bm->map = (potrace_word *) malloc (dy * h * BM_WORDSIZE);
+ if (!bm->map)
+ {
+ free (bm);
+ return NULL;
+ }
return bm;
}
/* clear the given bitmap. Set all bits to c. */
-static inline void bm_clear(potrace_bitmap_t *bm, int c) {
- memset(bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE);
+static inline void
+bm_clear (potrace_bitmap_t * bm, int c)
+{
+ memset (bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE);
}
/* duplicate the given bitmap. Return NULL on error with errno set. */
-static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
- potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
- if (!bm1) {
- return NULL;
- }
- memcpy(bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE);
+static inline potrace_bitmap_t *
+bm_dup (const potrace_bitmap_t * bm)
+{
+ potrace_bitmap_t *bm1 = bm_new (bm->w, bm->h);
+ if (!bm1)
+ {
+ return NULL;
+ }
+ memcpy (bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE);
return bm1;
}
/* invert the given bitmap. */
-static inline void bm_invert(potrace_bitmap_t *bm) {
+static inline void
+bm_invert (potrace_bitmap_t * bm)
+{
int i;
- for (i = 0; i < bm->dy * bm->h; i++) {
- bm->map[i] ^= BM_ALLBITS;
- }
+ for (i = 0; i < bm->dy * bm->h; i++)
+ {
+ bm->map[i] ^= BM_ALLBITS;
+ }
}
#endif /* BITMAP_H */
diff --git a/src/hid/gcode/curve.c b/src/hid/gcode/curve.c
index 0dc1005..abf85d7 100644
--- a/src/hid/gcode/curve.c
+++ b/src/hid/gcode/curve.c
@@ -14,61 +14,72 @@
#include "curve.h"
#define SAFE_MALLOC(var, n, typ) \
- if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+ if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
/* ---------------------------------------------------------------------- */
/* allocate and free path objects */
-path_t *path_new(void) {
+path_t *
+path_new (void)
+{
path_t *p = NULL;
privpath_t *priv = NULL;
- SAFE_MALLOC(p, 1, path_t);
- memset(p, 0, sizeof(path_t));
- SAFE_MALLOC(priv, 1, privpath_t);
- memset(priv, 0, sizeof(privpath_t));
+ SAFE_MALLOC (p, 1, path_t);
+ memset (p, 0, sizeof (path_t));
+ SAFE_MALLOC (priv, 1, privpath_t);
+ memset (priv, 0, sizeof (privpath_t));
p->priv = priv;
return p;
- malloc_error:
- free(p);
- free(priv);
+malloc_error:
+ free (p);
+ free (priv);
return NULL;
}
/* free the members of the given curve structure. Leave errno unchanged. */
-static void privcurve_free_members(privcurve_t *curve) {
- free(curve->tag);
- free(curve->c);
- free(curve->vertex);
- free(curve->alpha);
- free(curve->alpha0);
- free(curve->beta);
+static void
+privcurve_free_members (privcurve_t * curve)
+{
+ free (curve->tag);
+ free (curve->c);
+ free (curve->vertex);
+ free (curve->alpha);
+ free (curve->alpha0);
+ free (curve->beta);
}
/* free a path. Leave errno untouched. */
-void path_free(path_t *p) {
- if (p) {
- if (p->priv) {
- free(p->priv->pt);
- free(p->priv->lon);
- free(p->priv->sums);
- free(p->priv->po);
- privcurve_free_members(&p->priv->curve);
- privcurve_free_members(&p->priv->ocurve);
+void
+path_free (path_t * p)
+{
+ if (p)
+ {
+ if (p->priv)
+ {
+ free (p->priv->pt);
+ free (p->priv->lon);
+ free (p->priv->sums);
+ free (p->priv->po);
+ privcurve_free_members (&p->priv->curve);
+ privcurve_free_members (&p->priv->ocurve);
+ }
+ free (p->priv);
+ /* do not free p->fcurve ! */
}
- free(p->priv);
- /* do not free p->fcurve ! */
- }
- free(p);
-}
+ free (p);
+}
/* free a pathlist, leaving errno untouched. */
-void pathlist_free(path_t *plist) {
+void
+pathlist_free (path_t * plist)
+{
path_t *p;
- list_forall_unlink(p, plist) {
- path_free(p);
+ list_forall_unlink (p, plist)
+ {
+ path_free (p);
}
}
@@ -79,31 +90,34 @@ typedef dpoint_t dpoint3_t[3];
/* initialize the members of the given curve structure to size m.
Return 0 on success, 1 on error with errno set. */
-int privcurve_init(privcurve_t *curve, int n) {
- memset(curve, 0, sizeof(privcurve_t));
+int
+privcurve_init (privcurve_t * curve, int n)
+{
+ memset (curve, 0, sizeof (privcurve_t));
curve->n = n;
- SAFE_MALLOC(curve->tag, n, int);
- SAFE_MALLOC(curve->c, n, dpoint3_t);
- SAFE_MALLOC(curve->vertex, n, dpoint_t);
- SAFE_MALLOC(curve->alpha, n, double);
- SAFE_MALLOC(curve->alpha0, n, double);
- SAFE_MALLOC(curve->beta, n, double);
+ SAFE_MALLOC (curve->tag, n, int);
+ SAFE_MALLOC (curve->c, n, dpoint3_t);
+ SAFE_MALLOC (curve->vertex, n, dpoint_t);
+ SAFE_MALLOC (curve->alpha, n, double);
+ SAFE_MALLOC (curve->alpha0, n, double);
+ SAFE_MALLOC (curve->beta, n, double);
return 0;
- malloc_error:
- free(curve->tag);
- free(curve->c);
- free(curve->vertex);
- free(curve->alpha);
- free(curve->alpha0);
- free(curve->beta);
+malloc_error:
+ free (curve->tag);
+ free (curve->c);
+ free (curve->vertex);
+ free (curve->alpha);
+ free (curve->alpha0);
+ free (curve->beta);
return 1;
}
/* copy private to public curve structure */
-void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) {
+void
+privcurve_to_curve (privcurve_t * pc, potrace_curve_t * c)
+{
c->n = pc->n;
c->tag = pc->tag;
c->c = pc->c;
}
-
diff --git a/src/hid/gcode/curve.h b/src/hid/gcode/curve.h
index 45c0790..6f7e8a1 100644
--- a/src/hid/gcode/curve.h
+++ b/src/hid/gcode/curve.h
@@ -15,23 +15,25 @@
Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
*/
-struct privcurve_s {
- int n; /* number of segments */
- int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
- dpoint_t (*c)[3]; /* c[n][i]: control points.
- c[n][0] is unused for tag[n]=POTRACE_CORNER */
+struct privcurve_s
+{
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
+ dpoint_t (*c)[3]; /* c[n][i]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
/* the remainder of this structure is special to privcurve, and is
used in EPS debug output and special EPS "short coding". These
fields are valid only if "alphacurve" is set. */
- int alphacurve; /* have the following fields been initialized? */
- dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
- double *alpha; /* only for POTRACE_CURVETO */
- double *alpha0; /* "uncropped" alpha parameter - for debug output only */
+ int alphacurve; /* have the following fields been initialized? */
+ dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
+ double *alpha; /* only for POTRACE_CURVETO */
+ double *alpha0; /* "uncropped" alpha parameter - for debug output only */
double *beta;
};
typedef struct privcurve_s privcurve_t;
-struct sums_s {
+struct sums_s
+{
double x;
double y;
double x2;
@@ -45,21 +47,22 @@ typedef struct sums_s sums_t;
Potrace algorithm. Backends only need to read the fcurve and fm
fields of this data structure, but debugging backends may read
other fields. */
-struct potrace_privpath_s {
+struct potrace_privpath_s
+{
int len;
- point_t *pt; /* pt[len]: path as extracted from bitmap */
- int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
+ point_t *pt; /* pt[len]: path as extracted from bitmap */
+ int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
- int x0, y0; /* origin for sums */
- sums_t *sums; /* sums[len+1]: cache for fast summing */
+ int x0, y0; /* origin for sums */
+ sums_t *sums; /* sums[len+1]: cache for fast summing */
- int m; /* length of optimal polygon */
- int *po; /* po[m]: optimal polygon */
+ int m; /* length of optimal polygon */
+ int *po; /* po[m]: optimal polygon */
- privcurve_t curve; /* curve[m]: array of curve elements */
- privcurve_t ocurve; /* ocurve[om]: array of curve elements */
- privcurve_t *fcurve; /* final curve: this points to either curve or
- ocurve. Do not free this separately. */
+ privcurve_t curve; /* curve[m]: array of curve elements */
+ privcurve_t ocurve; /* ocurve[om]: array of curve elements */
+ privcurve_t *fcurve; /* final curve: this points to either curve or
+ ocurve. Do not free this separately. */
};
typedef struct potrace_privpath_s potrace_privpath_t;
@@ -67,11 +70,10 @@ typedef struct potrace_privpath_s potrace_privpath_t;
typedef potrace_privpath_t privpath_t;
typedef potrace_path_t path_t;
-path_t *path_new(void);
-void path_free(path_t *p);
-void pathlist_free(path_t *plist);
-int privcurve_init(privcurve_t *curve, int n);
-void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c);
+path_t *path_new (void);
+void path_free (path_t * p);
+void pathlist_free (path_t * plist);
+int privcurve_init (privcurve_t * curve, int n);
+void privcurve_to_curve (privcurve_t * pc, potrace_curve_t * c);
#endif /* CURVE_H */
-
diff --git a/src/hid/gcode/decompose.c b/src/hid/gcode/decompose.c
index abc5e0a..0b42882 100644
--- a/src/hid/gcode/decompose.c
+++ b/src/hid/gcode/decompose.c
@@ -21,85 +21,105 @@
/* auxiliary bitmap manipulations */
/* set the excess padding to 0 */
-static void bm_clearexcess(potrace_bitmap_t *bm) {
+static void
+bm_clearexcess (potrace_bitmap_t * bm)
+{
potrace_word mask;
int y;
- if (bm->w % BM_WORDBITS != 0) {
- mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
- for (y=0; y<bm->h; y++) {
- *bm_index(bm, bm->w, y) &= mask;
+ if (bm->w % BM_WORDBITS != 0)
+ {
+ mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
+ for (y = 0; y < bm->h; y++)
+ {
+ *bm_index (bm, bm->w, y) &= mask;
+ }
}
- }
}
-struct bbox_s {
- int x0, x1, y0, y1; /* bounding box */
+struct bbox_s
+{
+ int x0, x1, y0, y1; /* bounding box */
};
typedef struct bbox_s bbox_t;
/* clear the bm, assuming the bounding box is set correctly (faster
than clearing the whole bitmap) */
-static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
+static void
+clear_bm_with_bbox (potrace_bitmap_t * bm, bbox_t * bbox)
+{
int imin = (bbox->x0 / BM_WORDBITS);
- int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
+ int imax = ((bbox->x1 + BM_WORDBITS - 1) / BM_WORDBITS);
int i, y;
- for (y=bbox->y0; y<bbox->y1; y++) {
- for (i=imin; i<imax; i++) {
- bm_scanline(bm, y)[i] = 0;
+ for (y = bbox->y0; y < bbox->y1; y++)
+ {
+ for (i = imin; i < imax; i++)
+ {
+ bm_scanline (bm, y)[i] = 0;
+ }
}
- }
}
/* ---------------------------------------------------------------------- */
/* auxiliary functions */
/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
-static inline int detrand(int x, int y) {
+static inline int
+detrand (int x, int y)
+{
unsigned int z;
- static const unsigned char t[256] = {
+ static const unsigned char t[256] = {
/* non-linear sequence: constant term of inverse in GF(8),
mod x^8+x^4+x^3+x+1 */
- 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
- 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
- 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
- 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
- 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
- 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
- 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
+ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
};
/* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
5-bit sequence */
z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
- z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
+ z =
+ t[z & 0xff] ^ t[(z >> 8) & 0xff] ^ t[(z >> 16) & 0xff] ^ t[(z >> 24) &
+ 0xff];
return z & 1;
}
/* return the "majority" value of bitmap bm at intersection (x,y). We
assume that the bitmap is balanced at "radius" 1. */
-static int majority(potrace_bitmap_t *bm, int x, int y) {
+static int
+majority (potrace_bitmap_t * bm, int x, int y)
+{
int i, a, ct;
- for (i=2; i<5; i++) { /* check at "radius" i */
- ct = 0;
- for (a=-i+1; a<=i-1; a++) {
- ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
- ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
- ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
- ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
- }
- if (ct>0) {
- return 1;
- } else if (ct<0) {
- return 0;
+ for (i = 2; i < 5; i++)
+ { /* check at "radius" i */
+ ct = 0;
+ for (a = -i + 1; a <= i - 1; a++)
+ {
+ ct += BM_GET (bm, x + a, y + i - 1) ? 1 : -1;
+ ct += BM_GET (bm, x + i - 1, y + a - 1) ? 1 : -1;
+ ct += BM_GET (bm, x + a - 1, y - i) ? 1 : -1;
+ ct += BM_GET (bm, x - i, y + a) ? 1 : -1;
+ }
+ if (ct > 0)
+ {
+ return 1;
+ }
+ else if (ct < 0)
+ {
+ return 0;
+ }
}
- }
return 0;
}
@@ -108,25 +128,33 @@ static int majority(potrace_bitmap_t *bm, int x, int y) {
/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
must be a multiple of BM_WORDBITS. */
-static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
+static void
+xor_to_ref (potrace_bitmap_t * bm, int x, int y, int xa)
+{
int xhi = x & -BM_WORDBITS;
- int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */
+ int xlo = x & (BM_WORDBITS - 1); /* = x % BM_WORDBITS */
int i;
-
- if (xhi<xa) {
- for (i = xhi; i < xa; i+=BM_WORDBITS) {
- *bm_index(bm, i, y) ^= BM_ALLBITS;
+
+ if (xhi < xa)
+ {
+ for (i = xhi; i < xa; i += BM_WORDBITS)
+ {
+ *bm_index (bm, i, y) ^= BM_ALLBITS;
+ }
}
- } else {
- for (i = xa; i < xhi; i+=BM_WORDBITS) {
- *bm_index(bm, i, y) ^= BM_ALLBITS;
+ else
+ {
+ for (i = xa; i < xhi; i += BM_WORDBITS)
+ {
+ *bm_index (bm, i, y) ^= BM_ALLBITS;
+ }
}
- }
/* note: the following "if" is needed because x86 treats a<<b as
a<<(b&31). I spent hours looking for this bug. */
- if (xlo) {
- *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
- }
+ if (xlo)
+ {
+ *bm_index (bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
+ }
}
/* a path is represented as an array of points, which are thought to
@@ -137,31 +165,38 @@ static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
/* xor the given pixmap with the interior of the given path. Note: the
path must be within the dimensions of the pixmap. */
-static void xor_path(potrace_bitmap_t *bm, path_t *p) {
+static void
+xor_path (potrace_bitmap_t * bm, path_t * p)
+{
int xa, x, y, k, y1;
- if (p->priv->len <= 0) { /* a path of length 0 is silly, but legal */
- return;
- }
+ if (p->priv->len <= 0)
+ { /* a path of length 0 is silly, but legal */
+ return;
+ }
- y1 = p->priv->pt[p->priv->len-1].y;
+ y1 = p->priv->pt[p->priv->len - 1].y;
xa = p->priv->pt[0].x & -BM_WORDBITS;
- for (k=0; k<p->priv->len; k++) {
- x = p->priv->pt[k].x;
- y = p->priv->pt[k].y;
-
- if (y != y1) {
- /* efficiently invert the rectangle [x,xa] x [y,y1] */
- xor_to_ref(bm, x, min(y,y1), xa);
- y1 = y;
+ for (k = 0; k < p->priv->len; k++)
+ {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
+
+ if (y != y1)
+ {
+ /* efficiently invert the rectangle [x,xa] x [y,y1] */
+ xor_to_ref (bm, x, min (y, y1), xa);
+ y1 = y;
+ }
}
- }
}
/* Find the bounding box of a given path. Path is assumed to be of
non-zero length. */
-static void setbbox_path(bbox_t *bbox, path_t *p) {
+static void
+setbbox_path (bbox_t * bbox, path_t * p)
+{
int x, y;
int k;
@@ -170,23 +205,28 @@ static void setbbox_path(bbox_t *bbox, path_t *p) {
bbox->x0 = INT_MAX;
bbox->x1 = 0;
- for (k=0; k<p->priv->len; k++) {
- x = p->priv->pt[k].x;
- y = p->priv->pt[k].y;
+ for (k = 0; k < p->priv->len; k++)
+ {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
- if (x < bbox->x0) {
- bbox->x0 = x;
- }
- if (x > bbox->x1) {
- bbox->x1 = x;
- }
- if (y < bbox->y0) {
- bbox->y0 = y;
- }
- if (y > bbox->y1) {
- bbox->y1 = y;
+ if (x < bbox->x0)
+ {
+ bbox->x0 = x;
+ }
+ if (x > bbox->x1)
+ {
+ bbox->x1 = x;
+ }
+ if (y < bbox->y0)
+ {
+ bbox->y0 = y;
+ }
+ if (y > bbox->y1)
+ {
+ bbox->y1 = y;
+ }
}
- }
}
/* compute a path in the given pixmap, separating black from white.
@@ -195,7 +235,9 @@ static void setbbox_path(bbox_t *bbox, path_t *p) {
new path_t object, or NULL on error (note that a legitimate path
cannot have length 0). Sign is required for correct interpretation
of turnpolicies. */
-static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
+static path_t *
+findpath (potrace_bitmap_t * bm, int x0, int y0, int sign, int turnpolicy)
+{
int x, y, dirx, diry, len, size, area;
int c, d, tmp;
point_t *pt, *pt1;
@@ -209,67 +251,82 @@ static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turn
len = size = 0;
pt = NULL;
area = 0;
-
- while (1) {
- /* add point to path */
- if (len>=size) {
- size += 100;
- size = (int)(1.3 * size);
- pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
- if (!pt1) {
- goto error;
- }
- pt = pt1;
- }
- pt[len].x = x;
- pt[len].y = y;
- len++;
-
- /* move to next point */
- x += dirx;
- y += diry;
- area += x*diry;
-
- /* path complete? */
- if (x==x0 && y==y0) {
- break;
- }
-
- /* determine next direction */
- c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
- d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
-
- if (c && !d) { /* ambiguous turn */
- if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
- || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
- || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
- || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
- || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
- || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
- tmp = dirx; /* right turn */
- dirx = diry;
- diry = -tmp;
- } else {
- tmp = dirx; /* left turn */
- dirx = -diry;
- diry = tmp;
- }
- } else if (c) { /* right turn */
- tmp = dirx;
- dirx = diry;
- diry = -tmp;
- } else if (!d) { /* left turn */
- tmp = dirx;
- dirx = -diry;
- diry = tmp;
- }
- } /* while this path */
+
+ while (1)
+ {
+ /* add point to path */
+ if (len >= size)
+ {
+ size += 100;
+ size = (int) (1.3 * size);
+ pt1 = (point_t *) realloc (pt, size * sizeof (point_t));
+ if (!pt1)
+ {
+ goto error;
+ }
+ pt = pt1;
+ }
+ pt[len].x = x;
+ pt[len].y = y;
+ len++;
+
+ /* move to next point */
+ x += dirx;
+ y += diry;
+ area += x * diry;
+
+ /* path complete? */
+ if (x == x0 && y == y0)
+ {
+ break;
+ }
+
+ /* determine next direction */
+ c = BM_GET (bm, x + (dirx + diry - 1) / 2, y + (diry - dirx - 1) / 2);
+ d = BM_GET (bm, x + (dirx - diry - 1) / 2, y + (diry + dirx - 1) / 2);
+
+ if (c && !d)
+ { /* ambiguous turn */
+ if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
+ || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
+ || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
+ || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand (x, y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY
+ && majority (bm, x, y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MINORITY
+ && !majority (bm, x, y)))
+ {
+ tmp = dirx; /* right turn */
+ dirx = diry;
+ diry = -tmp;
+ }
+ else
+ {
+ tmp = dirx; /* left turn */
+ dirx = -diry;
+ diry = tmp;
+ }
+ }
+ else if (c)
+ { /* right turn */
+ tmp = dirx;
+ dirx = diry;
+ diry = -tmp;
+ }
+ else if (!d)
+ { /* left turn */
+ tmp = dirx;
+ dirx = -diry;
+ diry = tmp;
+ }
+ } /* while this path */
/* allocate new path object */
- p = path_new();
- if (!p) {
- goto error;
- }
+ p = path_new ();
+ if (!p)
+ {
+ goto error;
+ }
p->priv->pt = pt;
p->priv->len = len;
@@ -277,10 +334,10 @@ static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turn
p->sign = sign;
return p;
-
- error:
- free(pt);
- return NULL;
+
+error:
+ free (pt);
+ return NULL;
}
/* Give a tree structure to the given path list, based on "insideness"
@@ -299,22 +356,25 @@ static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turn
and will be used as scratch space. Return 0 on success or -1 on
error with errno set. */
-static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
+static void
+pathlist_to_tree (path_t * plist, potrace_bitmap_t * bm)
+{
path_t *p, *p1;
path_t *heap, *heap1;
path_t *cur;
path_t *head;
- path_t **hook, **hook_in, **hook_out; /* for fast appending to linked list */
+ path_t **hook, **hook_in, **hook_out; /* for fast appending to linked list */
bbox_t bbox;
-
- bm_clear(bm, 0);
+
+ bm_clear (bm, 0);
/* save original "next" pointers */
- list_forall(p, plist) {
+ list_forall (p, plist)
+ {
p->sibling = p->next;
p->childlist = NULL;
}
-
+
heap = plist;
/* the heap holds a list of lists of paths. Use "childlist" field
@@ -324,62 +384,71 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
heap to get a tail recursive algorithm: the heap holds a list of
pathlists which still need to be transformed. */
- while (heap) {
- /* unlink first sublist */
- cur = heap;
- heap = heap->childlist;
- cur->childlist = NULL;
-
- /* unlink first path */
- head = cur;
- cur = cur->next;
- head->next = NULL;
-
- /* render path */
- xor_path(bm, head);
- setbbox_path(&bbox, head);
-
- /* now do insideness test for each element of cur; append it to
- head->childlist if it's inside head, else append it to
- head->next. */
- hook_in=&head->childlist;
- hook_out=&head->next;
- list_forall_unlink(p, cur) {
- if (p->priv->pt[0].y <= bbox.y0) {
- list_insert_beforehook(p, hook_out);
- /* append the remainder of the list to hook_out */
- *hook_out = cur;
- break;
- }
- if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
- list_insert_beforehook(p, hook_in);
- } else {
- list_insert_beforehook(p, hook_out);
+ while (heap)
+ {
+ /* unlink first sublist */
+ cur = heap;
+ heap = heap->childlist;
+ cur->childlist = NULL;
+
+ /* unlink first path */
+ head = cur;
+ cur = cur->next;
+ head->next = NULL;
+
+ /* render path */
+ xor_path (bm, head);
+ setbbox_path (&bbox, head);
+
+ /* now do insideness test for each element of cur; append it to
+ head->childlist if it's inside head, else append it to
+ head->next. */
+ hook_in = &head->childlist;
+ hook_out = &head->next;
+ list_forall_unlink (p, cur)
+ {
+ if (p->priv->pt[0].y <= bbox.y0)
+ {
+ list_insert_beforehook (p, hook_out);
+ /* append the remainder of the list to hook_out */
+ *hook_out = cur;
+ break;
+ }
+ if (BM_GET (bm, p->priv->pt[0].x, p->priv->pt[0].y - 1))
+ {
+ list_insert_beforehook (p, hook_in);
+ }
+ else
+ {
+ list_insert_beforehook (p, hook_out);
+ }
}
- }
- /* clear bm */
- clear_bm_with_bbox(bm, &bbox);
+ /* clear bm */
+ clear_bm_with_bbox (bm, &bbox);
- /* now schedule head->childlist and head->next for further
- processing */
- if (head->next) {
- head->next->childlist = heap;
- heap = head->next;
- }
- if (head->childlist) {
- head->childlist->childlist = heap;
- heap = head->childlist;
+ /* now schedule head->childlist and head->next for further
+ processing */
+ if (head->next)
+ {
+ head->next->childlist = heap;
+ heap = head->next;
+ }
+ if (head->childlist)
+ {
+ head->childlist->childlist = heap;
+ heap = head->childlist;
+ }
}
- }
-
+
/* copy sibling structure from "next" to "sibling" component */
p = plist;
- while (p) {
- p1 = p->sibling;
- p->sibling = p->next;
- p = p1;
- }
+ while (p)
+ {
+ p1 = p->sibling;
+ p->sibling = p->next;
+ p = p1;
+ }
/* reconstruct a new linked list ("next") structure from tree
("childlist", "sibling") structure. This code is slightly messy,
@@ -387,30 +456,35 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
contains a list of childlists which still need to be
processed. */
heap = plist;
- if (heap) {
- heap->next = NULL; /* heap is a linked list of childlists */
- }
+ if (heap)
+ {
+ heap->next = NULL; /* heap is a linked list of childlists */
+ }
plist = NULL;
hook = &plist;
- while (heap) {
- heap1 = heap->next;
- for (p=heap; p; p=p->sibling) {
- /* p is a positive path */
- /* append to linked list */
- list_insert_beforehook(p, hook);
-
- /* go through its children */
- for (p1=p->childlist; p1; p1=p1->sibling) {
- /* append to linked list */
- list_insert_beforehook(p1, hook);
- /* append its childlist to heap, if non-empty */
- if (p1->childlist) {
- list_append(path_t, heap1, p1->childlist);
+ while (heap)
+ {
+ heap1 = heap->next;
+ for (p = heap; p; p = p->sibling)
+ {
+ /* p is a positive path */
+ /* append to linked list */
+ list_insert_beforehook (p, hook);
+
+ /* go through its children */
+ for (p1 = p->childlist; p1; p1 = p1->sibling)
+ {
+ /* append to linked list */
+ list_insert_beforehook (p1, hook);
+ /* append its childlist to heap, if non-empty */
+ if (p1->childlist)
+ {
+ list_append (path_t, heap1, p1->childlist);
+ }
+ }
}
- }
+ heap = heap1;
}
- heap = heap1;
- }
return;
}
@@ -420,23 +494,29 @@ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
or y=y' and x<x'. If found, return 0 and store pixel in
(*xp,*yp). Else return 1. Note that this function assumes that
excess bytes have been cleared with bm_clearexcess. */
-static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
+static int
+findnext (potrace_bitmap_t * bm, int *xp, int *yp)
+{
int x;
int y;
- for (y=*yp; y>=0; y--) {
- for (x=0; x<bm->w; x+=BM_WORDBITS) {
- if (*bm_index(bm, x, y)) {
- while (!BM_GET(bm, x, y)) {
- x++;
+ for (y = *yp; y >= 0; y--)
+ {
+ for (x = 0; x < bm->w; x += BM_WORDBITS)
+ {
+ if (*bm_index (bm, x, y))
+ {
+ while (!BM_GET (bm, x, y))
+ {
+ x++;
+ }
+ /* found */
+ *xp = x;
+ *yp = y;
+ return 0;
+ }
}
- /* found */
- *xp = x;
- *yp = y;
- return 0;
- }
}
- }
/* not found */
return 1;
}
@@ -446,63 +526,74 @@ static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
in. Returns 0 on success with plistp set, or -1 on error with errno
set. */
-int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param) {
+int
+bm_to_pathlist (const potrace_bitmap_t * bm, path_t ** plistp,
+ const potrace_param_t * param)
+{
int x;
int y;
path_t *p;
- path_t *plist = NULL; /* linked list of path objects */
- path_t **hook = &plist; /* used to speed up appending to linked list */
+ path_t *plist = NULL; /* linked list of path objects */
+ path_t **hook = &plist; /* used to speed up appending to linked list */
potrace_bitmap_t *bm1 = NULL;
int sign;
- bm1 = bm_dup(bm);
- if (!bm1) {
- goto error;
- }
+ bm1 = bm_dup (bm);
+ if (!bm1)
+ {
+ goto error;
+ }
/* be sure the byte padding on the right is set to 0, as the fast
pixel search below relies on it */
- bm_clearexcess(bm1);
+ bm_clearexcess (bm1);
/* iterate through components */
y = bm1->h - 1;
- while (findnext(bm1, &x, &y) == 0) {
- /* calculate the sign by looking at the original */
- sign = BM_GET(bm, x, y) ? '+' : '-';
-
- /* calculate the path */
- p = findpath(bm1, x, y+1, sign, param->turnpolicy);
- if (p==NULL) {
- goto error;
- }
+ while (findnext (bm1, &x, &y) == 0)
+ {
+ /* calculate the sign by looking at the original */
+ sign = BM_GET (bm, x, y) ? '+' : '-';
+
+ /* calculate the path */
+ p = findpath (bm1, x, y + 1, sign, param->turnpolicy);
+ if (p == NULL)
+ {
+ goto error;
+ }
- /* update buffered image */
- xor_path(bm1, p);
+ /* update buffered image */
+ xor_path (bm1, p);
- /* if it's a turd, eliminate it, else append it to the list */
- if (p->area <= param->turdsize) {
- path_free(p);
- } else {
- list_insert_beforehook(p, hook);
- }
+ /* if it's a turd, eliminate it, else append it to the list */
+ if (p->area <= param->turdsize)
+ {
+ path_free (p);
+ }
+ else
+ {
+ list_insert_beforehook (p, hook);
+ }
- if (bm1->h > 0) { /* to be sure */
- //progress_update(1-y/(double)bm1->h, progress);
+ if (bm1->h > 0)
+ { /* to be sure */
+ //progress_update(1-y/(double)bm1->h, progress);
+ }
}
- }
- pathlist_to_tree(plist, bm1);
- bm_free(bm1);
+ pathlist_to_tree (plist, bm1);
+ bm_free (bm1);
*plistp = plist;
// progress_update(1.0, progress);
return 0;
- error:
- bm_free(bm1);
- list_forall_unlink(p, plist) {
- path_free(p);
+error:
+ bm_free (bm1);
+ list_forall_unlink (p, plist)
+ {
+ path_free (p);
}
return -1;
}
diff --git a/src/hid/gcode/decompose.h b/src/hid/gcode/decompose.h
index d5be99c..333003e 100644
--- a/src/hid/gcode/decompose.h
+++ b/src/hid/gcode/decompose.h
@@ -10,7 +10,7 @@
#include "potracelib.h"
//#include "progress.h"
-int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param);
+int bm_to_pathlist (const potrace_bitmap_t * bm, path_t ** plistp,
+ const potrace_param_t * param);
#endif /* DECOMPOSE_H */
-
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
index 5792d0c..e8c38db 100644
--- a/src/hid/gcode/gcode.c
+++ b/src/hid/gcode/gcode.c
@@ -64,925 +64,1037 @@
#include <dmalloc.h>
#endif
-RCSID("$Id: gcode.c, v 0.1 2010/2/8 14:00:00 Alberto Maccioni Exp $");
+RCSID ("$Id: gcode.c, v 0.1 2010/2/8 14:00:00 Alberto Maccioni Exp $");
#define CRASH fprintf(stderr, "HID error: pcb called unimplemented GCODE function %s.\n", __FUNCTION__); abort()
-#define pcb_unit 100000.0 //pcb internal units per inch
-struct color_struct {
- /* the descriptor used by the gd library */
- int c;
+#define pcb_unit 100000.0 //pcb internal units per inch
+struct color_struct
+{
+ /* the descriptor used by the gd library */
+ int c;
- /* so I can figure out what rgb value c refers to */
- unsigned int r, g, b;
+ /* so I can figure out what rgb value c refers to */
+ unsigned int r, g, b;
};
-struct hid_gc_struct {
- HID *me_pointer;
- EndCapStyle cap;
- int width;
- unsigned char r, g, b;
- int erase;
- int faded;
- struct color_struct *color;
- gdImagePtr brush;
+struct hid_gc_struct
+{
+ HID *me_pointer;
+ EndCapStyle cap;
+ int width;
+ unsigned char r, g, b;
+ int erase;
+ int faded;
+ struct color_struct *color;
+ gdImagePtr brush;
};
static struct color_struct *black = NULL, *white = NULL;
-static int linewidth = -1;
-static int lastgroup = -1;
+static int linewidth = -1;
+static int lastgroup = -1;
static gdImagePtr lastbrush = (void *) -1;
-static int lastcap = -1;
-static int lastcolor = -1;
+static int lastcap = -1;
+static int lastcolor = -1;
/* gd image and file for PNG export */
static gdImagePtr gcode_im = NULL;
-static FILE *gcode_f = NULL,*gcode_f2 = NULL;
+static FILE *gcode_f = NULL, *gcode_f2 = NULL;
-static int is_mask;
-static int is_drill;
-static int is_solder;
+static int is_mask;
+static int is_drill;
+static int is_solder;
/*
* Which groups of layers to export into PNG layer masks. 1 means export, 0
* means do not export.
*/
-static int gcode_export_group[MAX_LAYER];
+static int gcode_export_group[MAX_LAYER];
/* Group that is currently exported. */
-static int gcode_cur_group;
+static int gcode_cur_group;
/* Filename prefix that will be used when saving files. */
-static char *gcode_basename = NULL;
+static char *gcode_basename = NULL;
/* Horizontal DPI (grid points per inch) */
-static int gcode_dpi = -1;
-
-static double gcode_cutdepth = 0; //milling depth (inch)
-static double gcode_drilldepth = 0; //drilling depth (inch)
-static double gcode_safeZ = 100; //safe Z (inch)
-static double gcode_toolradius = 0; //tool radius(inch)
-static int save_drill=0;
-static int n_drill=0;
-static int nmax_drill=0;
-struct drill_struct {
- double x;
- double y;
+static int gcode_dpi = -1;
+
+static double gcode_cutdepth = 0; //milling depth (inch)
+static double gcode_drilldepth = 0; //drilling depth (inch)
+static double gcode_safeZ = 100; //safe Z (inch)
+static double gcode_toolradius = 0; //tool radius(inch)
+static int save_drill = 0;
+static int n_drill = 0;
+static int nmax_drill = 0;
+struct drill_struct
+{
+ double x;
+ double y;
};
-static struct drill_struct *drill=0;
+static struct drill_struct *drill = 0;
static const char *units[] = {
- "mm",
- "mil",
- "um",
- "inch",
- NULL
+ "mm",
+ "mil",
+ "um",
+ "inch",
+ NULL
};
-HID_Attribute gcode_attribute_list[] = {
- /* other HIDs expect this to be first. */
- {"basename", "File name prefix",
- HID_String, 0, 0, {0, 0, 0}, 0, 0},
+HID_Attribute gcode_attribute_list[] = {
+ /* other HIDs expect this to be first. */
+ {"basename", "File name prefix",
+ HID_String, 0, 0, {0, 0, 0}, 0, 0},
#define HA_basename 0
- {"dpi", "Resolution of intermediate image (pixels/inch).",
- HID_Integer, 0, 2000, {600, 0, 0}, 0, 0},
+ {"dpi", "Resolution of intermediate image (pixels/inch).",
+ HID_Integer, 0, 2000, {600, 0, 0}, 0, 0},
#define HA_dpi 1
-
- {"mill depth", "Milling depth.",
- HID_Real, -1000, 1000, {0, 0, -0.05}, 0, 0},
+
+ {"mill depth", "Milling depth.",
+ HID_Real, -1000, 1000, {0, 0, -0.05}, 0, 0},
#define HA_cutdepth 2
-
- {"safe Z", "Safe Z for traverse move.",
- HID_Real, -1000, 10000, {0, 0, 2}, 0, 0},
+
+ {"safe Z", "Safe Z for traverse move.",
+ HID_Real, -1000, 10000, {0, 0, 2}, 0, 0},
#define HA_safeZ 3
-
- {"tool radius", "Milling tool radius compensation.",
- HID_Real, 0, 10000, {0, 0, 0.1}, 0, 0},
+
+ {"tool radius", "Milling tool radius compensation.",
+ HID_Real, 0, 10000, {0, 0, 0.1}, 0, 0},
#define HA_toolradius 4
- {"drill depth", "Drilling depth.",
- HID_Real, -10000, 10000, {0, 0, -2}, 0, 0},
+ {"drill depth", "Drilling depth.",
+ HID_Real, -10000, 10000, {0, 0, -2}, 0, 0},
#define HA_drilldepth 5
-
- {"measurement unit", "Measurement unit",
- HID_Enum, 0, 0, {0, 0, 0}, units, 0},
+
+ {"measurement unit", "Measurement unit",
+ HID_Enum, 0, 0, {0, 0, 0}, units, 0},
#define HA_unit 6
};
#define NUM_OPTIONS (sizeof(gcode_attribute_list)/sizeof(gcode_attribute_list[0]))
-REGISTER_ATTRIBUTES(gcode_attribute_list)
- static HID_Attr_Val gcode_values[NUM_OPTIONS];
+REGISTER_ATTRIBUTES (gcode_attribute_list)
+ static HID_Attr_Val gcode_values[NUM_OPTIONS];
/* *** Utility funcions **************************************************** */
/* convert from default PCB units (1/100 mil) to gcode units */
- static int pcb_to_gcode(int pcb)
+ static int pcb_to_gcode (int pcb)
{
- int gcode;
+ int gcode;
- gcode = (pcb * gcode_dpi) / pcb_unit; //100000;
+ gcode = (pcb * gcode_dpi) / pcb_unit; //100000;
- return gcode;
+ return gcode;
}
-static char *
-gcode_get_png_name(const char *basename, const char *suffix)
+static char *
+gcode_get_png_name (const char *basename, const char *suffix)
{
- char *buf;
- int len;
+ char *buf;
+ int len;
- len = strlen(basename) + strlen(suffix) + 6;
- buf = malloc(sizeof(*buf) * len);
+ len = strlen (basename) + strlen (suffix) + 6;
+ buf = malloc (sizeof (*buf) * len);
- sprintf(buf, "%s.%s.png", basename, suffix);
+ sprintf (buf, "%s.%s.png", basename, suffix);
- return buf;
+ return buf;
}
//Sorts drills in order of distance from the origin
-struct drill_struct* sort_drill(struct drill_struct *drill,int n_drill){
- int i,j,imin;
- double dmin,d;
- struct drill_struct p={0,0};
- struct drill_struct* temp=malloc(n_drill*sizeof(struct drill_struct));
- for(j=0;j<n_drill;j++){
- dmin=1e20;
- for(i=0;i<n_drill-j;i++){
- d=(drill[i].x-p.x)*(drill[i].x-p.x)+(drill[i].y-p.y)*(drill[i].y-p.y);
- if(d<dmin){
- imin=i;
- dmin=d;
- }
- }
- //printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y);
- temp[j]=drill[imin];
- drill[imin]=drill[n_drill-j-1];
- p=temp[j];
+struct drill_struct *
+sort_drill (struct drill_struct *drill, int n_drill)
+{
+ int i, j, imin;
+ double dmin, d;
+ struct drill_struct p = { 0, 0 };
+ struct drill_struct *temp = malloc (n_drill * sizeof (struct drill_struct));
+ for (j = 0; j < n_drill; j++)
+ {
+ dmin = 1e20;
+ for (i = 0; i < n_drill - j; i++)
+ {
+ d =
+ (drill[i].x - p.x) * (drill[i].x - p.x) + (drill[i].y -
+ p.y) * (drill[i].y -
+ p.y);
+ if (d < dmin)
+ {
+ imin = i;
+ dmin = d;
+ }
}
- free(drill);
- return temp;
+ //printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y);
+ temp[j] = drill[imin];
+ drill[imin] = drill[n_drill - j - 1];
+ p = temp[j];
+ }
+ free (drill);
+ return temp;
}
/* *** Main export callback ************************************************ */
-extern void hid_parse_command_line(int *argc, char ***argv);
+extern void hid_parse_command_line (int *argc, char ***argv);
-static void
-gcode_parse_arguments(int *argc, char ***argv)
+static void
+gcode_parse_arguments (int *argc, char ***argv)
{
- hid_register_attributes(gcode_attribute_list,
- sizeof(gcode_attribute_list) /
- sizeof(gcode_attribute_list[0]));
- hid_parse_command_line(argc, argv);
+ hid_register_attributes (gcode_attribute_list,
+ sizeof (gcode_attribute_list) /
+ sizeof (gcode_attribute_list[0]));
+ hid_parse_command_line (argc, argv);
}
static HID_Attribute *
-gcode_get_export_options(int *n)
+gcode_get_export_options (int *n)
{
- static char *last_made_filename = 0;
-
- if (PCB) {
- derive_default_filename(PCB->Filename,
- &gcode_attribute_list[HA_basename],
- ".gcode",
- &last_made_filename);
- }
- if (n) {
- *n = NUM_OPTIONS;
- }
- return gcode_attribute_list;
+ static char *last_made_filename = 0;
+
+ if (PCB)
+ {
+ derive_default_filename (PCB->Filename,
+ &gcode_attribute_list[HA_basename],
+ ".gcode", &last_made_filename);
+ }
+ if (n)
+ {
+ *n = NUM_OPTIONS;
+ }
+ return gcode_attribute_list;
}
/* Populates gcode_export_group array */
-void
-gcode_choose_groups()
+void
+gcode_choose_groups ()
{
- int n, m;
- LayerType *layer;
+ int n, m;
+ LayerType *layer;
- /* Set entire array to 0 (don't export any layer groups by default */
- memset(gcode_export_group, 0, sizeof(gcode_export_group));
+ /* Set entire array to 0 (don't export any layer groups by default */
+ memset (gcode_export_group, 0, sizeof (gcode_export_group));
- for (n = 0; n < max_layer; n++) {
- layer = &PCB->Data->Layer[n];
+ for (n = 0; n < max_layer; n++)
+ {
+ layer = &PCB->Data->Layer[n];
- if (layer->LineN || layer->TextN || layer->ArcN ||
- layer->PolygonN) {
- /* layer isn't empty */
+ if (layer->LineN || layer->TextN || layer->ArcN || layer->PolygonN)
+ {
+ /* layer isn't empty */
- /*
- * is this check necessary? It seems that special
- * layers have negative indexes?
- */
+ /*
+ * is this check necessary? It seems that special
+ * layers have negative indexes?
+ */
- if (SL_TYPE(n) == 0) {
- /* layer is a copper layer */
- m = GetLayerGroupNumberByNumber(n);
+ if (SL_TYPE (n) == 0)
+ {
+ /* layer is a copper layer */
+ m = GetLayerGroupNumberByNumber (n);
- /* the export layer */
- gcode_export_group[m] = 1;
- }
- }
+ /* the export layer */
+ gcode_export_group[m] = 1;
+ }
}
+ }
}
-static void
-gcode_alloc_colors()
+static void
+gcode_alloc_colors ()
{
- /*
- * Allocate white and black -- the first color allocated becomes the
- * background color
- */
-
- white = (struct color_struct *) malloc(sizeof(*white));
- white->r = white->g = white->b = 255;
- white->c = gdImageColorAllocate(gcode_im, white->r, white->g, white->b);
-
- black = (struct color_struct *) malloc(sizeof(*black));
- black->r = black->g = black->b = 0;
- black->c = gdImageColorAllocate(gcode_im, black->r, black->g, black->b);
+ /*
+ * Allocate white and black -- the first color allocated becomes the
+ * background color
+ */
+
+ white = (struct color_struct *) malloc (sizeof (*white));
+ white->r = white->g = white->b = 255;
+ white->c = gdImageColorAllocate (gcode_im, white->r, white->g, white->b);
+
+ black = (struct color_struct *) malloc (sizeof (*black));
+ black->r = black->g = black->b = 0;
+ black->c = gdImageColorAllocate (gcode_im, black->r, black->g, black->b);
}
-static void
-gcode_start_png(const char *basename, const char *suffix)
+static void
+gcode_start_png (const char *basename, const char *suffix)
{
- int h, w;
- char *buf;
+ int h, w;
+ char *buf;
- buf = gcode_get_png_name(basename, suffix);
+ buf = gcode_get_png_name (basename, suffix);
- h = pcb_to_gcode(PCB->MaxHeight);
- w = pcb_to_gcode(PCB->MaxWidth);
+ h = pcb_to_gcode (PCB->MaxHeight);
+ w = pcb_to_gcode (PCB->MaxWidth);
- /* Nelma only works with true color images */
- gcode_im = gdImageCreate(w, h);
- gcode_f = fopen(buf, "wb");
+ /* Nelma only works with true color images */
+ gcode_im = gdImageCreate (w, h);
+ gcode_f = fopen (buf, "wb");
- gcode_alloc_colors();
+ gcode_alloc_colors ();
- free(buf);
+ free (buf);
}
-static void
-gcode_finish_png()
+static void
+gcode_finish_png ()
{
#ifdef HAVE_GDIMAGEPNG
- gdImagePng(gcode_im, gcode_f);
+ gdImagePng (gcode_im, gcode_f);
#else
- Message("GCODE: PNG not supported by gd. Can't write layer mask.\n");
+ Message ("GCODE: PNG not supported by gd. Can't write layer mask.\n");
#endif
- gdImageDestroy(gcode_im);
- fclose(gcode_f);
+ gdImageDestroy (gcode_im);
+ fclose (gcode_f);
- free(white);
- free(black);
+ free (white);
+ free (black);
- gcode_im = NULL;
- gcode_f = NULL;
+ gcode_im = NULL;
+ gcode_f = NULL;
}
-void
-gcode_start_png_export()
+void
+gcode_start_png_export ()
{
- BoxType region;
+ BoxType region;
- region.X1 = 0;
- region.Y1 = 0;
- region.X2 = PCB->MaxWidth;
- region.Y2 = PCB->MaxHeight;
+ region.X1 = 0;
+ region.Y1 = 0;
+ region.X2 = PCB->MaxWidth;
+ region.Y2 = PCB->MaxHeight;
- linewidth = -1;
- lastbrush = (void *) -1;
- lastcap = -1;
- lastgroup = -1;
- lastcolor = -1;
- lastgroup = -1;
+ linewidth = -1;
+ lastbrush = (void *) -1;
+ lastcap = -1;
+ lastgroup = -1;
+ lastcolor = -1;
+ lastgroup = -1;
- hid_expose_callback(&gcode_hid, ®ion, 0);
+ hid_expose_callback (&gcode_hid, ®ion, 0);
}
-static void
-gcode_do_export(HID_Attr_Val * options)
-{
- int save_ons[MAX_LAYER + 2];
- int i, idx;
- time_t t;
- double scale=0,d=0,Bx,By;
- int r,c,v,p,metric;
- char* filename;
- path_t *plist = NULL;
- potrace_bitmap_t *bm = NULL;
- potrace_param_t param_default = {
- 2, // turdsize
- POTRACE_TURNPOLICY_MINORITY, // turnpolicy
- 1.0, // alphamax
- 1, // opticurve
- 0.2, // opttolerance
- {
- NULL, // callback function
- NULL, // callback data
- 0.0, 1.0, // progress range
- 0.0, // granularity
- },
- };
-
- Bx=PCB->MaxWidth/pcb_unit;
- By=PCB->MaxHeight/pcb_unit;
- if (!options) {
- gcode_get_export_options(0);
- for (i = 0; i < NUM_OPTIONS; i++) {
- gcode_values[i] = gcode_attribute_list[i].default_val;
- }
- options = gcode_values;
- }
- gcode_basename = options[HA_basename].str_value;
- if (!gcode_basename) {
- gcode_basename = "pcb-out";
- }
- gcode_dpi = options[HA_dpi].int_value;
- if (gcode_dpi < 0) {
- fprintf(stderr, "ERROR: dpi may not be < 0\n");
- return;
- }
- switch(options[HA_unit].int_value){
- case 0:
- scale=1.0; //mm
- metric=1;
- break;
- case 1:
- scale=0.001; //mil
- metric=0;
- break;
- case 2:
- scale=0.001; //um
- metric=1;
- break;
- default:
- scale=1.0; //inch
- metric=0;
+static void
+gcode_do_export (HID_Attr_Val * options)
+{
+ int save_ons[MAX_LAYER + 2];
+ int i, idx;
+ time_t t;
+ double scale = 0, d = 0, Bx, By;
+ int r, c, v, p, metric;
+ char *filename;
+ path_t *plist = NULL;
+ potrace_bitmap_t *bm = NULL;
+ potrace_param_t param_default = {
+ 2, // turdsize
+ POTRACE_TURNPOLICY_MINORITY, // turnpolicy
+ 1.0, // alphamax
+ 1, // opticurve
+ 0.2, // opttolerance
+ {
+ NULL, // callback function
+ NULL, // callback data
+ 0.0, 1.0, // progress range
+ 0.0, // granularity
+ },
+ };
+
+ Bx = PCB->MaxWidth / pcb_unit;
+ By = PCB->MaxHeight / pcb_unit;
+ if (!options)
+ {
+ gcode_get_export_options (0);
+ for (i = 0; i < NUM_OPTIONS; i++)
+ {
+ gcode_values[i] = gcode_attribute_list[i].default_val;
}
- gcode_cutdepth = options[HA_cutdepth].real_value*scale;
- gcode_drilldepth = options[HA_drilldepth].real_value*scale;
- gcode_safeZ = options[HA_safeZ].real_value*scale;
- gcode_toolradius = options[HA_toolradius].real_value*scale*pcb_unit; //in PCB units (1/100 mil)
- if(metric) gcode_toolradius*=1/25.4;
- gcode_choose_groups();
-
- for (i = 0; i < MAX_LAYER; i++) {
- if (gcode_export_group[i]) {
-
- gcode_cur_group = i;
-
- /* magic */
- idx = (i >= 0 && i < max_layer) ?
- PCB->LayerGroups.Entries[i][0] : i;
- printf("idx=%d %s\n",idx,layer_type_to_file_name(idx));
- is_solder=(GetLayerGroupNumberByNumber(idx)==GetLayerGroupNumberByNumber(max_layer+SOLDER_LAYER))?1:0;
- save_drill=is_solder; //save drills for one layer only
- gcode_start_png(gcode_basename,layer_type_to_file_name(idx));
- hid_save_and_show_layer_ons(save_ons);
- gcode_start_png_export();
- hid_restore_layer_ons(save_ons);
+ options = gcode_values;
+ }
+ gcode_basename = options[HA_basename].str_value;
+ if (!gcode_basename)
+ {
+ gcode_basename = "pcb-out";
+ }
+ gcode_dpi = options[HA_dpi].int_value;
+ if (gcode_dpi < 0)
+ {
+ fprintf (stderr, "ERROR: dpi may not be < 0\n");
+ return;
+ }
+ switch (options[HA_unit].int_value)
+ {
+ case 0:
+ scale = 1.0; //mm
+ metric = 1;
+ break;
+ case 1:
+ scale = 0.001; //mil
+ metric = 0;
+ break;
+ case 2:
+ scale = 0.001; //um
+ metric = 1;
+ break;
+ default:
+ scale = 1.0; //inch
+ metric = 0;
+ }
+ gcode_cutdepth = options[HA_cutdepth].real_value * scale;
+ gcode_drilldepth = options[HA_drilldepth].real_value * scale;
+ gcode_safeZ = options[HA_safeZ].real_value * scale;
+ gcode_toolradius = options[HA_toolradius].real_value * scale * pcb_unit; //in PCB units (1/100 mil)
+ if (metric)
+ gcode_toolradius *= 1 / 25.4;
+ gcode_choose_groups ();
+
+ for (i = 0; i < MAX_LAYER; i++)
+ {
+ if (gcode_export_group[i])
+ {
+
+ gcode_cur_group = i;
+
+ /* magic */
+ idx = (i >= 0 && i < max_layer) ?
+ PCB->LayerGroups.Entries[i][0] : i;
+ printf ("idx=%d %s\n", idx, layer_type_to_file_name (idx));
+ is_solder =
+ (GetLayerGroupNumberByNumber (idx) ==
+ GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER)) ? 1 : 0;
+ save_drill = is_solder; //save drills for one layer only
+ gcode_start_png (gcode_basename, layer_type_to_file_name (idx));
+ hid_save_and_show_layer_ons (save_ons);
+ gcode_start_png_export ();
+ hid_restore_layer_ons (save_ons);
//***************** gcode conversion ***************************
// potrace uses a different kind of bitmap; for simplicity gcode_im is copied to this format
- bm = bm_new(gdImageSX(gcode_im),gdImageSY(gcode_im));
- filename=malloc(512);
- plist = NULL;
- if(is_solder){ //only for back layer
- gdImagePtr temp_im=gdImageCreate(gdImageSX(gcode_im), gdImageSY(gcode_im));
- gdImageCopy(temp_im,gcode_im,0,0,0,0,gdImageSX(gcode_im),gdImageSY(gcode_im));
- for(r=0;r<gdImageSX(gcode_im);r++){
- for(c=0;c<gdImageSY(gcode_im);c++){
- gdImageSetPixel(gcode_im,r,c,gdImageGetPixel(temp_im,gdImageSX(gcode_im)-1-r,c));
- }
- }
- gdImageDestroy(temp_im);
- }
- sprintf(filename,"%s.%s.cnc",gcode_basename,layer_type_to_file_name(idx));
- for(r=0;r<gdImageSX(gcode_im);r++){
- for(c=0;c<gdImageSY(gcode_im);c++){
- v=gdImageGetPixel(gcode_im,r,gdImageSY(gcode_im)-1-c);
- p=(gcode_im->red[v]||gcode_im->green[v]||gcode_im->blue[v])?0:0xFFFFFF;
- BM_PUT(bm, r, c, p);
- }
- }
- gcode_f2 = fopen (filename, "wb");
- if (!gcode_f2)
- {
- perror (filename);
- return;
- }
- fprintf(gcode_f2,"(Created by G-code exporter)\n");
- t = time(NULL);
- sprintf(filename,"%s", ctime(&t));
- filename[strlen(filename)-1]=0;
- fprintf(gcode_f2,"( %s )\n", filename);
- fprintf(gcode_f2,"(%d dpi)\n",gcode_dpi);
- fprintf(gcode_f2,"(Unit: %s)\n",metric?"mm":"inch");
- if(metric) fprintf(gcode_f2,"(Board size: %.2fx%.2f mm)\n",Bx*25.4,By*25.4);
- else fprintf(gcode_f2,"(Board size: %.2fx%.2f inches)\n",Bx,By);
- fprintf(gcode_f2,"#100=%f (safe Z)\n",gcode_safeZ);
- fprintf(gcode_f2,"#101=%f (cutting depth)\n",gcode_cutdepth);
- fprintf(gcode_f2,"(---------------------------------)\n");
- fprintf(gcode_f2,"G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",metric?21:20,metric?25:1);
- fprintf(gcode_f2,"G0 Z#100\n");
- //extract contour points from image
- r = bm_to_pathlist(bm, &plist, ¶m_default);
- if (r) {
- fprintf(stderr, "ERROR: pathlist function failed\n");
- return;
- }
- //generate best polygon and write vertices in g-code format
- d=process_path(plist,¶m_default,bm,gcode_f2,metric?25.4/gcode_dpi:1.0/gcode_dpi);
- if (d<0) {
- fprintf(stderr, "ERROR: path process function failed\n");
- return;
- }
- if(metric) fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",d,d*1/25.4);
- else fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",25.4*d,d);
- fprintf(gcode_f2,"M5 M9 M2\n");
- pathlist_free(plist);
- bm_free(bm);
- fclose (gcode_f2);
- if(save_drill){
- d=0;
- drill=sort_drill(drill,n_drill);
- sprintf(filename,"%s.drill.cnc",gcode_basename);
- gcode_f2 = fopen (filename, "wb");
- if (!gcode_f2)
- {
- perror (filename);
- return;
- }
- fprintf(gcode_f2,"(Created by G-code exporter)\n");
- fprintf(gcode_f2,"(drill file: %d drills)\n",n_drill);
- sprintf(filename,"%s", ctime(&t));
- filename[strlen(filename)-1]=0;
- fprintf(gcode_f2,"( %s )\n", filename);
- fprintf(gcode_f2,"(Unit: %s)\n",metric?"mm":"inch");
- if(metric) fprintf(gcode_f2,"(Board size: %.2fx%.2f mm)\n",Bx*25.4,By*25.4);
- else fprintf(gcode_f2,"(Board size: %.2fx%.2f inches)\n",Bx,By);
- fprintf(gcode_f2,"#100=%f (safe Z)\n",gcode_safeZ);
- fprintf(gcode_f2,"#101=%f (drill depth)\n",gcode_drilldepth);
- fprintf(gcode_f2,"(---------------------------------)\n");
- fprintf(gcode_f2,"G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",metric?21:20,metric?25:1);
-// fprintf(gcode_f2,"G0 Z#100\n");
- for(r=0;r<n_drill;r++){
-// if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4);
-// else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y);
- if(metric) fprintf(gcode_f2,"G81 X%f Y%f Z#101 R#100\n",drill[r].x*25.4,drill[r].y*25.4);
- else fprintf(gcode_f2,"G81 X%f Y%f Z#101 R#100\n",drill[r].x,drill[r].y);
-// fprintf(gcode_f2,"G1 Z#101\n");
-// fprintf(gcode_f2,"G0 Z#100\n");
- if(r>0) d+=sqrt((drill[r].x-drill[r-1].x)*(drill[r].x-drill[r-1].x)+\
- (drill[r].y-drill[r-1].y)*(drill[r].y-drill[r-1].y));
- }
- fprintf(gcode_f2,"M5 M9 M2\n");
- fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",25.4*d,d);
- fclose (gcode_f2);
- free(drill);
- drill=NULL;
- n_drill=nmax_drill=0;
- }
- free(filename);
- system("unix2dos *.cnc");
-//******************* end gcode conversion ****************************
- gcode_finish_png();
+ bm = bm_new (gdImageSX (gcode_im), gdImageSY (gcode_im));
+ filename = malloc (512);
+ plist = NULL;
+ if (is_solder)
+ { //only for back layer
+ gdImagePtr temp_im =
+ gdImageCreate (gdImageSX (gcode_im), gdImageSY (gcode_im));
+ gdImageCopy (temp_im, gcode_im, 0, 0, 0, 0,
+ gdImageSX (gcode_im), gdImageSY (gcode_im));
+ for (r = 0; r < gdImageSX (gcode_im); r++)
+ {
+ for (c = 0; c < gdImageSY (gcode_im); c++)
+ {
+ gdImageSetPixel (gcode_im, r, c,
+ gdImageGetPixel (temp_im,
+ gdImageSX (gcode_im) -
+ 1 - r, c));
+ }
+ }
+ gdImageDestroy (temp_im);
+ }
+ sprintf (filename, "%s.%s.cnc", gcode_basename,
+ layer_type_to_file_name (idx));
+ for (r = 0; r < gdImageSX (gcode_im); r++)
+ {
+ for (c = 0; c < gdImageSY (gcode_im); c++)
+ {
+ v =
+ gdImageGetPixel (gcode_im, r,
+ gdImageSY (gcode_im) - 1 - c);
+ p = (gcode_im->red[v] || gcode_im->green[v]
+ || gcode_im->blue[v]) ? 0 : 0xFFFFFF;
+ BM_PUT (bm, r, c, p);
}
+ }
+ gcode_f2 = fopen (filename, "wb");
+ if (!gcode_f2)
+ {
+ perror (filename);
+ return;
+ }
+ fprintf (gcode_f2, "(Created by G-code exporter)\n");
+ t = time (NULL);
+ sprintf (filename, "%s", ctime (&t));
+ filename[strlen (filename) - 1] = 0;
+ fprintf (gcode_f2, "( %s )\n", filename);
+ fprintf (gcode_f2, "(%d dpi)\n", gcode_dpi);
+ fprintf (gcode_f2, "(Unit: %s)\n", metric ? "mm" : "inch");
+ if (metric)
+ fprintf (gcode_f2, "(Board size: %.2fx%.2f mm)\n", Bx * 25.4,
+ By * 25.4);
+ else
+ fprintf (gcode_f2, "(Board size: %.2fx%.2f inches)\n", Bx, By);
+ fprintf (gcode_f2, "#100=%f (safe Z)\n", gcode_safeZ);
+ fprintf (gcode_f2, "#101=%f (cutting depth)\n", gcode_cutdepth);
+ fprintf (gcode_f2, "(---------------------------------)\n");
+ fprintf (gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",
+ metric ? 21 : 20, metric ? 25 : 1);
+ fprintf (gcode_f2, "G0 Z#100\n");
+ //extract contour points from image
+ r = bm_to_pathlist (bm, &plist, ¶m_default);
+ if (r)
+ {
+ fprintf (stderr, "ERROR: pathlist function failed\n");
+ return;
+ }
+ //generate best polygon and write vertices in g-code format
+ d =
+ process_path (plist, ¶m_default, bm, gcode_f2,
+ metric ? 25.4 / gcode_dpi : 1.0 / gcode_dpi);
+ if (d < 0)
+ {
+ fprintf (stderr, "ERROR: path process function failed\n");
+ return;
+ }
+ if (metric)
+ fprintf (gcode_f2, "(end, total distance %.2fmm = %.2fin)\n", d,
+ d * 1 / 25.4);
+ else
+ fprintf (gcode_f2, "(end, total distance %.2fmm = %.2fin)\n",
+ 25.4 * d, d);
+ fprintf (gcode_f2, "M5 M9 M2\n");
+ pathlist_free (plist);
+ bm_free (bm);
+ fclose (gcode_f2);
+ if (save_drill)
+ {
+ d = 0;
+ drill = sort_drill (drill, n_drill);
+ sprintf (filename, "%s.drill.cnc", gcode_basename);
+ gcode_f2 = fopen (filename, "wb");
+ if (!gcode_f2)
+ {
+ perror (filename);
+ return;
+ }
+ fprintf (gcode_f2, "(Created by G-code exporter)\n");
+ fprintf (gcode_f2, "(drill file: %d drills)\n", n_drill);
+ sprintf (filename, "%s", ctime (&t));
+ filename[strlen (filename) - 1] = 0;
+ fprintf (gcode_f2, "( %s )\n", filename);
+ fprintf (gcode_f2, "(Unit: %s)\n", metric ? "mm" : "inch");
+ if (metric)
+ fprintf (gcode_f2, "(Board size: %.2fx%.2f mm)\n", Bx * 25.4,
+ By * 25.4);
+ else
+ fprintf (gcode_f2, "(Board size: %.2fx%.2f inches)\n", Bx,
+ By);
+ fprintf (gcode_f2, "#100=%f (safe Z)\n", gcode_safeZ);
+ fprintf (gcode_f2, "#101=%f (drill depth)\n",
+ gcode_drilldepth);
+ fprintf (gcode_f2, "(---------------------------------)\n");
+ fprintf (gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",
+ metric ? 21 : 20, metric ? 25 : 1);
+// fprintf(gcode_f2,"G0 Z#100\n");
+ for (r = 0; r < n_drill; r++)
+ {
+// if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4);
+// else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y);
+ if (metric)
+ fprintf (gcode_f2, "G81 X%f Y%f Z#101 R#100\n",
+ drill[r].x * 25.4, drill[r].y * 25.4);
+ else
+ fprintf (gcode_f2, "G81 X%f Y%f Z#101 R#100\n",
+ drill[r].x, drill[r].y);
+// fprintf(gcode_f2,"G1 Z#101\n");
+// fprintf(gcode_f2,"G0 Z#100\n");
+ if (r > 0)
+ d +=
+ sqrt ((drill[r].x - drill[r - 1].x) * (drill[r].x -
+ drill[r - 1].x) +
+ (drill[r].y - drill[r - 1].y) * (drill[r].y -
+ drill[r - 1].y));
+ }
+ fprintf (gcode_f2, "M5 M9 M2\n");
+ fprintf (gcode_f2, "(end, total distance %.2fmm = %.2fin)\n",
+ 25.4 * d, d);
+ fclose (gcode_f2);
+ free (drill);
+ drill = NULL;
+ n_drill = nmax_drill = 0;
+ }
+ free (filename);
+ system ("unix2dos *.cnc");
+//******************* end gcode conversion ****************************
+ gcode_finish_png ();
}
+ }
}
/* *** PNG export (slightly modified code from PNG export HID) ************* */
-static int
-gcode_set_layer(const char *name, int group)
+static int
+gcode_set_layer (const char *name, int group)
{
- int idx = (group >= 0 && group < max_layer) ?
- PCB->LayerGroups.Entries[group][0] : group;
-
- if (name == 0) {
- name = PCB->Data->Layer[idx].Name;
- }
- if (strcmp(name, "invisible") == 0) {
- return 0;
- }
- is_drill = (SL_TYPE(idx) == SL_PDRILL || SL_TYPE(idx) == SL_UDRILL);
- is_mask = (SL_TYPE(idx) == SL_MASK);
-
- if (is_mask) {
- /* Don't print masks */
- return 0;
- }
- if (is_drill) {
- /*
- * Print 'holes', so that we can fill gaps in the copper
- * layer
- */
- return 1;
- }
- if (group == gcode_cur_group) {
- return 1;
- }
- return 0;
+ int idx = (group >= 0 && group < max_layer) ?
+ PCB->LayerGroups.Entries[group][0] : group;
+
+ if (name == 0)
+ {
+ name = PCB->Data->Layer[idx].Name;
+ }
+ if (strcmp (name, "invisible") == 0)
+ {
+ return 0;
+ }
+ is_drill = (SL_TYPE (idx) == SL_PDRILL || SL_TYPE (idx) == SL_UDRILL);
+ is_mask = (SL_TYPE (idx) == SL_MASK);
+
+ if (is_mask)
+ {
+ /* Don't print masks */
+ return 0;
+ }
+ if (is_drill)
+ {
+ /*
+ * Print 'holes', so that we can fill gaps in the copper
+ * layer
+ */
+ return 1;
+ }
+ if (group == gcode_cur_group)
+ {
+ return 1;
+ }
+ return 0;
}
-static hidGC
-gcode_make_gc(void)
-{
- hidGC rv = (hidGC) malloc(sizeof(struct hid_gc_struct));
- rv->me_pointer = &gcode_hid;
- rv->cap = Trace_Cap;
- rv->width = 1;
- rv->color = (struct color_struct *) malloc(sizeof(*rv->color));
- rv->color->r = rv->color->g = rv->color->b = 0;
- rv->color->c = 0;
- return rv;
+static hidGC
+gcode_make_gc (void)
+{
+ hidGC rv = (hidGC) malloc (sizeof (struct hid_gc_struct));
+ rv->me_pointer = &gcode_hid;
+ rv->cap = Trace_Cap;
+ rv->width = 1;
+ rv->color = (struct color_struct *) malloc (sizeof (*rv->color));
+ rv->color->r = rv->color->g = rv->color->b = 0;
+ rv->color->c = 0;
+ return rv;
}
-static void
-gcode_destroy_gc(hidGC gc)
+static void
+gcode_destroy_gc (hidGC gc)
{
- free(gc);
+ free (gc);
}
-static void
-gcode_use_mask(int use_it)
+static void
+gcode_use_mask (int use_it)
{
- /* does nothing */
+ /* does nothing */
}
-static void
-gcode_set_color(hidGC gc, const char *name)
+static void
+gcode_set_color (hidGC gc, const char *name)
{
- if (gcode_im == NULL) {
- return;
- }
- if (name == NULL) {
- name = "#ff0000";
- }
- if (!strcmp(name, "drill")) {
- gc->color = black;
- gc->erase = 0;
- return;
- }
- if (!strcmp(name, "erase")) {
- /* FIXME -- should be background, not white */
- gc->color = white;
- gc->erase = 1;
- return;
- }
- gc->color = black;
- gc->erase = 0;
- return;
+ if (gcode_im == NULL)
+ {
+ return;
+ }
+ if (name == NULL)
+ {
+ name = "#ff0000";
+ }
+ if (!strcmp (name, "drill"))
+ {
+ gc->color = black;
+ gc->erase = 0;
+ return;
+ }
+ if (!strcmp (name, "erase"))
+ {
+ /* FIXME -- should be background, not white */
+ gc->color = white;
+ gc->erase = 1;
+ return;
+ }
+ gc->color = black;
+ gc->erase = 0;
+ return;
}
static void
-gcode_set_line_cap(hidGC gc, EndCapStyle style)
+gcode_set_line_cap (hidGC gc, EndCapStyle style)
{
- gc->cap = style;
+ gc->cap = style;
}
static void
-gcode_set_line_width(hidGC gc, int width)
+gcode_set_line_width (hidGC gc, int width)
{
- gc->width = width;
+ gc->width = width;
}
static void
-gcode_set_draw_xor(hidGC gc, int xor)
+gcode_set_draw_xor (hidGC gc, int xor)
{
- ;
+ ;
}
static void
-gcode_set_draw_faded(hidGC gc, int faded)
+gcode_set_draw_faded (hidGC gc, int faded)
{
- gc->faded = faded;
+ gc->faded = faded;
}
static void
-gcode_set_line_cap_angle(hidGC gc, int x1, int y1, int x2, int y2)
+gcode_set_line_cap_angle (hidGC gc, int x1, int y1, int x2, int y2)
{
- CRASH;
+ CRASH;
}
static void
-use_gc(hidGC gc)
+use_gc (hidGC gc)
{
- int need_brush = 0;
+ int need_brush = 0;
+
+ if (gc->me_pointer != &gcode_hid)
+ {
+ fprintf (stderr, "Fatal: GC from another HID passed to gcode HID\n");
+ abort ();
+ }
+ if (linewidth != gc->width)
+ {
+ /* Make sure the scaling doesn't erase lines completely */
+ /*
+ if (SCALE (gc->width) == 0 && gc->width > 0)
+ gdImageSetThickness (im, 1);
+ else
+ */
+ gdImageSetThickness (gcode_im,
+ pcb_to_gcode (gc->width + 2 * gcode_toolradius));
+ linewidth = gc->width;
+ need_brush = 1;
+ }
+ if (lastbrush != gc->brush || need_brush)
+ {
+ static void *bcache = 0;
+ hidval bval;
+ char name[256];
+ char type;
+ int r;
+
+ switch (gc->cap)
+ {
+ case Round_Cap:
+ case Trace_Cap:
+ type = 'C';
+ r = pcb_to_gcode (gc->width / 2 + gcode_toolradius);
+ break;
+ default:
+ case Square_Cap:
+ r = pcb_to_gcode (gc->width + gcode_toolradius * 2);
+ type = 'S';
+ break;
+ }
+ sprintf (name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g,
+ gc->color->b, type, r);
- if (gc->me_pointer != &gcode_hid) {
- fprintf(stderr, "Fatal: GC from another HID passed to gcode HID\n");
- abort();
+ if (hid_cache_color (0, name, &bval, &bcache))
+ {
+ gc->brush = bval.ptr;
}
- if (linewidth != gc->width) {
- /* Make sure the scaling doesn't erase lines completely */
- /*
- if (SCALE (gc->width) == 0 && gc->width > 0)
- gdImageSetThickness (im, 1);
- else
- */
- gdImageSetThickness(gcode_im, pcb_to_gcode(gc->width + 2*gcode_toolradius));
- linewidth = gc->width;
- need_brush = 1;
+ else
+ {
+ int bg, fg;
+ if (type == 'C')
+ gc->brush = gdImageCreate (2 * r + 1, 2 * r + 1);
+ else
+ gc->brush = gdImageCreate (r + 1, r + 1);
+ bg = gdImageColorAllocate (gc->brush, 255, 255, 255);
+ fg =
+ gdImageColorAllocate (gc->brush, gc->color->r, gc->color->g,
+ gc->color->b);
+ gdImageColorTransparent (gc->brush, bg);
+
+ /*
+ * if we shrunk to a radius/box width of zero, then just use
+ * a single pixel to draw with.
+ */
+ if (r == 0)
+ gdImageFilledRectangle (gc->brush, 0, 0, 0, 0, fg);
+ else
+ {
+ if (type == 'C')
+ gdImageFilledEllipse (gc->brush, r, r, 2 * r, 2 * r, fg);
+ else
+ gdImageFilledRectangle (gc->brush, 0, 0, r, r, fg);
+ }
+ bval.ptr = gc->brush;
+ hid_cache_color (1, name, &bval, &bcache);
}
- if (lastbrush != gc->brush || need_brush) {
- static void *bcache = 0;
- hidval bval;
- char name[256];
- char type;
- int r;
-
- switch (gc->cap) {
- case Round_Cap:
- case Trace_Cap:
- type = 'C';
- r = pcb_to_gcode(gc->width / 2 + gcode_toolradius);
- break;
- default:
- case Square_Cap:
- r = pcb_to_gcode(gc->width+gcode_toolradius*2);
- type = 'S';
- break;
- }
- sprintf(name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g,
- gc->color->b, type, r);
-
- if (hid_cache_color(0, name, &bval, &bcache)) {
- gc->brush = bval.ptr;
- } else {
- int bg, fg;
- if (type == 'C')
- gc->brush = gdImageCreate(2 * r + 1, 2 * r + 1);
- else
- gc->brush = gdImageCreate(r + 1, r + 1);
- bg = gdImageColorAllocate(gc->brush, 255, 255, 255);
- fg =
- gdImageColorAllocate(gc->brush, gc->color->r, gc->color->g,
- gc->color->b);
- gdImageColorTransparent(gc->brush, bg);
-
- /*
- * if we shrunk to a radius/box width of zero, then just use
- * a single pixel to draw with.
- */
- if (r == 0)
- gdImageFilledRectangle(gc->brush, 0, 0, 0, 0, fg);
- else {
- if (type == 'C')
- gdImageFilledEllipse(gc->brush, r, r, 2 * r, 2 * r, fg);
- else
- gdImageFilledRectangle(gc->brush, 0, 0, r, r, fg);
- }
- bval.ptr = gc->brush;
- hid_cache_color(1, name, &bval, &bcache);
- }
- gdImageSetBrush(gcode_im, gc->brush);
- lastbrush = gc->brush;
+ gdImageSetBrush (gcode_im, gc->brush);
+ lastbrush = gc->brush;
- }
+ }
#define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded))
- if (lastcolor != CBLEND(gc)) {
- if (is_drill || is_mask) {
+ if (lastcolor != CBLEND (gc))
+ {
+ if (is_drill || is_mask)
+ {
#ifdef FIXME
- fprintf(f, "%d gray\n", gc->erase ? 0 : 1);
+ fprintf (f, "%d gray\n", gc->erase ? 0 : 1);
#endif
- lastcolor = 0;
- } else {
- double r, g, b;
- r = gc->r;
- g = gc->g;
- b = gc->b;
- if (gc->faded) {
- r = 0.8 * 255 + 0.2 * r;
- g = 0.8 * 255 + 0.2 * g;
- b = 0.8 * 255 + 0.2 * b;
- }
+ lastcolor = 0;
+ }
+ else
+ {
+ double r, g, b;
+ r = gc->r;
+ g = gc->g;
+ b = gc->b;
+ if (gc->faded)
+ {
+ r = 0.8 * 255 + 0.2 * r;
+ g = 0.8 * 255 + 0.2 * g;
+ b = 0.8 * 255 + 0.2 * b;
+ }
#ifdef FIXME
- if (gc->r == gc->g && gc->g == gc->b)
- fprintf(f, "%g gray\n", r / 255.0);
- else
- fprintf(f, "%g %g %g rgb\n", r / 255.0, g / 255.0, b / 255.0);
+ if (gc->r == gc->g && gc->g == gc->b)
+ fprintf (f, "%g gray\n", r / 255.0);
+ else
+ fprintf (f, "%g %g %g rgb\n", r / 255.0, g / 255.0, b / 255.0);
#endif
- lastcolor = CBLEND(gc);
- }
+ lastcolor = CBLEND (gc);
}
+ }
}
static void
-gcode_draw_rect(hidGC gc, int x1, int y1, int x2, int y2)
+gcode_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
{
- use_gc(gc);
- gdImageRectangle(gcode_im,
- pcb_to_gcode(x1-gcode_toolradius), pcb_to_gcode(y1-gcode_toolradius),
- pcb_to_gcode(x2+gcode_toolradius), pcb_to_gcode(y2+gcode_toolradius), gc->color->c);
-// printf("Rect %d %d %d %d\n",x1,y1,x2,y2);
+ use_gc (gc);
+ gdImageRectangle (gcode_im,
+ pcb_to_gcode (x1 - gcode_toolradius),
+ pcb_to_gcode (y1 - gcode_toolradius),
+ pcb_to_gcode (x2 + gcode_toolradius),
+ pcb_to_gcode (y2 + gcode_toolradius), gc->color->c);
+// printf("Rect %d %d %d %d\n",x1,y1,x2,y2);
}
static void
-gcode_fill_rect(hidGC gc, int x1, int y1, int x2, int y2)
-{
- use_gc(gc);
- gdImageSetThickness(gcode_im, 0);
- linewidth = 0;
- gdImageFilledRectangle(gcode_im,
- pcb_to_gcode(x1-gcode_toolradius), pcb_to_gcode(y1-gcode_toolradius),
- pcb_to_gcode(x2+gcode_toolradius), pcb_to_gcode(y2+gcode_toolradius), gc->color->c);
-// printf("FillRect %d %d %d %d\n",x1,y1,x2,y2);
+gcode_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
+{
+ use_gc (gc);
+ gdImageSetThickness (gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledRectangle (gcode_im,
+ pcb_to_gcode (x1 - gcode_toolradius),
+ pcb_to_gcode (y1 - gcode_toolradius),
+ pcb_to_gcode (x2 + gcode_toolradius),
+ pcb_to_gcode (y2 + gcode_toolradius), gc->color->c);
+// printf("FillRect %d %d %d %d\n",x1,y1,x2,y2);
}
static void
-gcode_draw_line(hidGC gc, int x1, int y1, int x2, int y2)
+gcode_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
{
- if (x1 == x2 && y1 == y2) {
- int w = gc->width / 2;
- gcode_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w);
- return;
- }
- use_gc(gc);
-
- gdImageSetThickness(gcode_im, 0);
- linewidth = 0;
- gdImageLine(gcode_im, pcb_to_gcode(x1), pcb_to_gcode(y1),
- pcb_to_gcode(x2), pcb_to_gcode(y2), gdBrushed);
+ if (x1 == x2 && y1 == y2)
+ {
+ int w = gc->width / 2;
+ gcode_fill_rect (gc, x1 - w, y1 - w, x1 + w, y1 + w);
+ return;
+ }
+ use_gc (gc);
+
+ gdImageSetThickness (gcode_im, 0);
+ linewidth = 0;
+ gdImageLine (gcode_im, pcb_to_gcode (x1), pcb_to_gcode (y1),
+ pcb_to_gcode (x2), pcb_to_gcode (y2), gdBrushed);
}
static void
-gcode_draw_arc(hidGC gc, int cx, int cy, int width, int height,
- int start_angle, int delta_angle)
-{
- int sa, ea;
-
- /*
- * in gdImageArc, 0 degrees is to the right and +90 degrees is down
- * in pcb, 0 degrees is to the left and +90 degrees is down
- */
- start_angle = 180 - start_angle;
- delta_angle = -delta_angle;
- if (delta_angle > 0) {
- sa = start_angle;
- ea = start_angle + delta_angle;
- } else {
- sa = start_angle + delta_angle;
- ea = start_angle;
- }
-
- /*
- * make sure we start between 0 and 360 otherwise gd does strange
- * things
- */
- while (sa < 0) {
- sa += 360;
- ea += 360;
- }
- while (sa >= 360) {
- sa -= 360;
- ea -= 360;
- }
+gcode_draw_arc (hidGC gc, int cx, int cy, int width, int height,
+ int start_angle, int delta_angle)
+{
+ int sa, ea;
+
+ /*
+ * in gdImageArc, 0 degrees is to the right and +90 degrees is down
+ * in pcb, 0 degrees is to the left and +90 degrees is down
+ */
+ start_angle = 180 - start_angle;
+ delta_angle = -delta_angle;
+ if (delta_angle > 0)
+ {
+ sa = start_angle;
+ ea = start_angle + delta_angle;
+ }
+ else
+ {
+ sa = start_angle + delta_angle;
+ ea = start_angle;
+ }
+
+ /*
+ * make sure we start between 0 and 360 otherwise gd does strange
+ * things
+ */
+ while (sa < 0)
+ {
+ sa += 360;
+ ea += 360;
+ }
+ while (sa >= 360)
+ {
+ sa -= 360;
+ ea -= 360;
+ }
#if 0
- printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
- cx, cy, width, height, start_angle, delta_angle, sa, ea);
- printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n",
- im, SCALE_X(cx), SCALE_Y(cy),
- SCALE(width), SCALE(height), sa, ea, gc->color->c);
+ printf ("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
+ cx, cy, width, height, start_angle, delta_angle, sa, ea);
+ printf ("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n",
+ im, SCALE_X (cx), SCALE_Y (cy),
+ SCALE (width), SCALE (height), sa, ea, gc->color->c);
#endif
- use_gc(gc);
- gdImageSetThickness(gcode_im, 0);
- linewidth = 0;
- gdImageArc(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy),
- pcb_to_gcode(2 * width + gcode_toolradius*2), pcb_to_gcode(2 * height + gcode_toolradius*2), sa, ea, gdBrushed);
+ use_gc (gc);
+ gdImageSetThickness (gcode_im, 0);
+ linewidth = 0;
+ gdImageArc (gcode_im, pcb_to_gcode (cx), pcb_to_gcode (cy),
+ pcb_to_gcode (2 * width + gcode_toolradius * 2),
+ pcb_to_gcode (2 * height + gcode_toolradius * 2), sa, ea,
+ gdBrushed);
}
static void
-gcode_fill_circle(hidGC gc, int cx, int cy, int radius)
-{
- use_gc(gc);
-
- gdImageSetThickness(gcode_im, 0);
- linewidth = 0;
- gdImageFilledEllipse(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy),
- pcb_to_gcode(2 * radius + gcode_toolradius*2), pcb_to_gcode(2 * radius + gcode_toolradius*2), gc->color->c);
- if(save_drill&&is_drill){
- if(n_drill==nmax_drill){
- drill=(struct drill_struct*) realloc(drill,(nmax_drill+100)*sizeof(struct drill_struct));
- nmax_drill+=100;
- }
- drill[n_drill].x=(PCB->MaxWidth-cx)/pcb_unit; //convert to inch, flip: will drill from bottom side
- drill[n_drill].y=(PCB->MaxHeight-cy)/pcb_unit; //PCB reverses y axis
- n_drill++;
-// printf("Circle %d %d\n",cx,cy);
+gcode_fill_circle (hidGC gc, int cx, int cy, int radius)
+{
+ use_gc (gc);
+
+ gdImageSetThickness (gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledEllipse (gcode_im, pcb_to_gcode (cx), pcb_to_gcode (cy),
+ pcb_to_gcode (2 * radius + gcode_toolradius * 2),
+ pcb_to_gcode (2 * radius + gcode_toolradius * 2),
+ gc->color->c);
+ if (save_drill && is_drill)
+ {
+ if (n_drill == nmax_drill)
+ {
+ drill =
+ (struct drill_struct *) realloc (drill,
+ (nmax_drill +
+ 100) *
+ sizeof (struct drill_struct));
+ nmax_drill += 100;
}
+ drill[n_drill].x = (PCB->MaxWidth - cx) / pcb_unit; //convert to inch, flip: will drill from bottom side
+ drill[n_drill].y = (PCB->MaxHeight - cy) / pcb_unit; //PCB reverses y axis
+ n_drill++;
+// printf("Circle %d %d\n",cx,cy);
+ }
}
static void
-gcode_fill_polygon(hidGC gc, int n_coords, int *x, int *y)
+gcode_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
{
- int i;
- gdPoint *points;
-
- points = (gdPoint *) malloc(n_coords * sizeof(gdPoint));
- if (points == NULL) {
- fprintf(stderr, "ERROR: gcode_fill_polygon(): malloc failed\n");
- exit(1);
- }
- use_gc(gc);
- for (i = 0; i < n_coords; i++) {
- points[i].x = pcb_to_gcode(x[i]);
- points[i].y = pcb_to_gcode(y[i]);
- }
- gdImageSetThickness(gcode_im, 0);
- linewidth = 0;
- gdImageFilledPolygon(gcode_im, points, n_coords, gc->color->c);
- free(points);
-// printf("FillPoly\n");
+ int i;
+ gdPoint *points;
+
+ points = (gdPoint *) malloc (n_coords * sizeof (gdPoint));
+ if (points == NULL)
+ {
+ fprintf (stderr, "ERROR: gcode_fill_polygon(): malloc failed\n");
+ exit (1);
+ }
+ use_gc (gc);
+ for (i = 0; i < n_coords; i++)
+ {
+ points[i].x = pcb_to_gcode (x[i]);
+ points[i].y = pcb_to_gcode (y[i]);
+ }
+ gdImageSetThickness (gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledPolygon (gcode_im, points, n_coords, gc->color->c);
+ free (points);
+// printf("FillPoly\n");
}
static void
-gcode_calibrate(double xval, double yval)
+gcode_calibrate (double xval, double yval)
{
- CRASH;
+ CRASH;
}
static void
-gcode_set_crosshair(int x, int y, int a)
+gcode_set_crosshair (int x, int y, int a)
{
}
/* *** Miscellaneous ******************************************************* */
-HID gcode_hid = {
- sizeof(HID),
- "gcode",
- "G-CODE export.",
- 0, /* gui */
- 0, /* printer */
- 1, /* exporter */
- 1, /* poly before */
- 0, /* poly after */
- 0, /* poly dicer */
- gcode_get_export_options,
- gcode_do_export,
- gcode_parse_arguments,
- 0 /* gcode_invalidate_wh */ ,
- 0 /* gcode_invalidate_lr */ ,
- 0 /* gcode_invalidate_all */ ,
- gcode_set_layer,
- gcode_make_gc,
- gcode_destroy_gc,
- gcode_use_mask,
- gcode_set_color,
- gcode_set_line_cap,
- gcode_set_line_width,
- gcode_set_draw_xor,
- gcode_set_draw_faded,
- gcode_set_line_cap_angle,
- gcode_draw_line,
- gcode_draw_arc,
- gcode_draw_rect,
- gcode_fill_circle,
- gcode_fill_polygon,
- common_fill_pcb_polygon,
- 0 /* nelma_thindraw_pcb_polygon */ ,
- gcode_fill_rect,
- gcode_calibrate,
- 0 /* gcode_shift_is_pressed */ ,
- 0 /* gcode_control_is_pressed */ ,
- 0 /* gcode_mod1_is_pressed */ ,
- 0 /* gcode_get_coords */ ,
- gcode_set_crosshair,
- 0 /* gcode_add_timer */ ,
- 0 /* gcode_stop_timer */ ,
- 0 /* gcode_watch_file */ ,
- 0 /* gcode_unwatch_file */ ,
- 0 /* gcode_add_block_hook */ ,
- 0 /* gcode_stop_block_hook */ ,
- 0 /* gcode_log */ ,
- 0 /* gcode_logv */ ,
- 0 /* gcode_confirm_dialog */ ,
- 0 /* gcode_close_confirm_dialog */ ,
- 0 /* gcode_report_dialog */ ,
- 0 /* gcode_prompt_for */ ,
- 0 /* gcode_fileselect */ ,
- 0 /* gcode_attribute_dialog */ ,
- 0 /* gcode_show_item */ ,
- 0 /* gcode_beep */ ,
- 0 /* gcode_progress */ ,
- 0 /* gcode_drc_gui */
+HID gcode_hid = {
+ sizeof (HID),
+ "gcode",
+ "G-CODE export.",
+ 0, /* gui */
+ 0, /* printer */
+ 1, /* exporter */
+ 1, /* poly before */
+ 0, /* poly after */
+ 0, /* poly dicer */
+ gcode_get_export_options,
+ gcode_do_export,
+ gcode_parse_arguments,
+ 0 /* gcode_invalidate_wh */ ,
+ 0 /* gcode_invalidate_lr */ ,
+ 0 /* gcode_invalidate_all */ ,
+ gcode_set_layer,
+ gcode_make_gc,
+ gcode_destroy_gc,
+ gcode_use_mask,
+ gcode_set_color,
+ gcode_set_line_cap,
+ gcode_set_line_width,
+ gcode_set_draw_xor,
+ gcode_set_draw_faded,
+ gcode_set_line_cap_angle,
+ gcode_draw_line,
+ gcode_draw_arc,
+ gcode_draw_rect,
+ gcode_fill_circle,
+ gcode_fill_polygon,
+ common_fill_pcb_polygon,
+ 0 /* nelma_thindraw_pcb_polygon */ ,
+ gcode_fill_rect,
+ gcode_calibrate,
+ 0 /* gcode_shift_is_pressed */ ,
+ 0 /* gcode_control_is_pressed */ ,
+ 0 /* gcode_mod1_is_pressed */ ,
+ 0 /* gcode_get_coords */ ,
+ gcode_set_crosshair,
+ 0 /* gcode_add_timer */ ,
+ 0 /* gcode_stop_timer */ ,
+ 0 /* gcode_watch_file */ ,
+ 0 /* gcode_unwatch_file */ ,
+ 0 /* gcode_add_block_hook */ ,
+ 0 /* gcode_stop_block_hook */ ,
+ 0 /* gcode_log */ ,
+ 0 /* gcode_logv */ ,
+ 0 /* gcode_confirm_dialog */ ,
+ 0 /* gcode_close_confirm_dialog */ ,
+ 0 /* gcode_report_dialog */ ,
+ 0 /* gcode_prompt_for */ ,
+ 0 /* gcode_fileselect */ ,
+ 0 /* gcode_attribute_dialog */ ,
+ 0 /* gcode_show_item */ ,
+ 0 /* gcode_beep */ ,
+ 0 /* gcode_progress */ ,
+ 0 /* gcode_drc_gui */
};
#include "dolists.h"
void
-hid_gcode_init()
+hid_gcode_init ()
{
- apply_default_hid(&gcode_hid, 0);
- hid_register_hid(&gcode_hid);
+ apply_default_hid (&gcode_hid, 0);
+ hid_register_hid (&gcode_hid);
#include "gcode_lists.h"
}
diff --git a/src/hid/gcode/gcode.h b/src/hid/gcode/gcode.h
index 352cbd9..ae9d7a0 100644
--- a/src/hid/gcode/gcode.h
+++ b/src/hid/gcode/gcode.h
@@ -1,3 +1,3 @@
/* $Id: nelma.h,v 1.2 2007/04/20 11:31:15 danmc Exp $ */
-extern HID gcode_hid;
+extern HID gcode_hid;
diff --git a/src/hid/gcode/lists.h b/src/hid/gcode/lists.h
index 931cbb0..2a2353f 100644
--- a/src/hid/gcode/lists.h
+++ b/src/hid/gcode/lists.h
@@ -283,4 +283,3 @@
MACRO_END
#endif /* _PS_LISTS_H */
-
diff --git a/src/hid/gcode/potracelib.h b/src/hid/gcode/potracelib.h
index 0b93d65..2456c01 100644
--- a/src/hid/gcode/potracelib.h
+++ b/src/hid/gcode/potracelib.h
@@ -21,22 +21,24 @@
#define POTRACE_TURNPOLICY_RANDOM 6
/* structure to hold progress bar callback data */
-struct potrace_progress_s {
- void (*callback)(double progress, void *privdata); /* callback fn */
- void *data; /* callback function's private data */
- double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
- double epsilon; /* granularity: can skip smaller increments */
+struct potrace_progress_s
+{
+ void (*callback) (double progress, void *privdata); /* callback fn */
+ void *data; /* callback function's private data */
+ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
+ double epsilon; /* granularity: can skip smaller increments */
};
typedef struct potrace_progress_s potrace_progress_t;
/* structure to hold tracing parameters */
-struct potrace_param_s {
- int turdsize; /* area of largest path to be ignored */
- int turnpolicy; /* resolves ambiguous turns in path decomposition */
- double alphamax; /* corner threshold */
- int opticurve; /* use curve optimization? */
- double opttolerance; /* curve optimization tolerance */
- potrace_progress_t progress; /* progress callback function */
+struct potrace_param_s
+{
+ int turdsize; /* area of largest path to be ignored */
+ int turnpolicy; /* resolves ambiguous turns in path decomposition */
+ double alphamax; /* corner threshold */
+ int opticurve; /* use curve optimization? */
+ double opttolerance; /* curve optimization tolerance */
+ potrace_progress_t progress; /* progress callback function */
};
typedef struct potrace_param_s potrace_param_t;
@@ -50,10 +52,11 @@ typedef unsigned long potrace_word;
(map + n*dy). Raster data is stored as a sequence of potrace_words
(NOT bytes). The leftmost bit of scanline n is the most significant
bit of scanline(n)[0]. */
-struct potrace_bitmap_s {
- int w, h; /* width and height, in pixels */
- int dy; /* words per scanline (not bytes) */
- potrace_word *map; /* raw data, dy*h words */
+struct potrace_bitmap_s
+{
+ int w, h; /* width and height, in pixels */
+ int dy; /* words per scanline (not bytes) */
+ potrace_word *map; /* raw data, dy*h words */
};
typedef struct potrace_bitmap_s potrace_bitmap_t;
@@ -61,7 +64,8 @@ typedef struct potrace_bitmap_s potrace_bitmap_t;
/* curves */
/* point */
-struct potrace_dpoint_s {
+struct potrace_dpoint_s
+{
double x, y;
};
typedef struct potrace_dpoint_s potrace_dpoint_t;
@@ -71,28 +75,30 @@ typedef struct potrace_dpoint_s potrace_dpoint_t;
#define POTRACE_CORNER 2
/* closed curve segment */
-struct potrace_curve_s {
- int n; /* number of segments */
- int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
- potrace_dpoint_t (*c)[3]; /* c[n][3]: control points.
- c[n][0] is unused for tag[n]=POTRACE_CORNER */
+struct potrace_curve_s
+{
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
+ potrace_dpoint_t (*c)[3]; /* c[n][3]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
};
typedef struct potrace_curve_s potrace_curve_t;
/* Linked list of signed curve segments. Also carries a tree structure. */
-struct potrace_path_s {
- int area; /* area of the bitmap path */
- int sign; /* '+' or '-', depending on orientation */
- potrace_curve_t curve; /* this path's vector data */
+struct potrace_path_s
+{
+ int area; /* area of the bitmap path */
+ int sign; /* '+' or '-', depending on orientation */
+ potrace_curve_t curve; /* this path's vector data */
- struct potrace_path_s *next; /* linked list structure */
+ struct potrace_path_s *next; /* linked list structure */
- struct potrace_path_s *childlist; /* tree structure */
- struct potrace_path_s *sibling; /* tree structure */
+ struct potrace_path_s *childlist; /* tree structure */
+ struct potrace_path_s *sibling; /* tree structure */
- struct potrace_privpath_s *priv; /* private state */
+ struct potrace_privpath_s *priv; /* private state */
};
-typedef struct potrace_path_s potrace_path_t;
+typedef struct potrace_path_s potrace_path_t;
/* ---------------------------------------------------------------------- */
/* Potrace state */
@@ -100,11 +106,12 @@ typedef struct potrace_path_s potrace_path_t;
#define POTRACE_STATUS_OK 0
#define POTRACE_STATUS_INCOMPLETE 1
-struct potrace_state_s {
- int status;
- potrace_path_t *plist; /* vector data */
+struct potrace_state_s
+{
+ int status;
+ potrace_path_t *plist; /* vector data */
- struct potrace_privstate_s *priv; /* private state */
+ struct potrace_privstate_s *priv; /* private state */
};
typedef struct potrace_state_s potrace_state_t;
@@ -112,20 +119,20 @@ typedef struct potrace_state_s potrace_state_t;
/* API functions */
/* get default parameters */
-potrace_param_t *potrace_param_default(void);
+potrace_param_t *potrace_param_default (void);
/* free parameter set */
-void potrace_param_free(potrace_param_t *p);
+void potrace_param_free (potrace_param_t * p);
/* trace a bitmap*/
-potrace_state_t *potrace_trace(const potrace_param_t *param,
- const potrace_bitmap_t *bm);
+potrace_state_t *potrace_trace (const potrace_param_t * param,
+ const potrace_bitmap_t * bm);
/* free a Potrace state */
-void potrace_state_free(potrace_state_t *st);
+void potrace_state_free (potrace_state_t * st);
/* return a static plain text version string identifying this version
of potracelib */
-char *potrace_version(void);
+char *potrace_version (void);
#endif /* POTRACELIB_H */
diff --git a/src/hid/gcode/trace.c b/src/hid/gcode/trace.c
index 2c615e6..5f1c48e 100644
--- a/src/hid/gcode/trace.c
+++ b/src/hid/gcode/trace.c
@@ -19,60 +19,73 @@
#include "trace.h"
//#include "progress.h"
-#define INFTY 10000000 /* it suffices that this is longer than any
- path; it need not be really infinite */
-#define COS179 -0.999847695156 /* the cosine of 179 degrees */
+#define INFTY 10000000 /* it suffices that this is longer than any
+ path; it need not be really infinite */
+#define COS179 -0.999847695156 /* the cosine of 179 degrees */
/* ---------------------------------------------------------------------- */
#define SAFE_MALLOC(var, n, typ) \
- if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+ if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
/* ---------------------------------------------------------------------- */
/* auxiliary functions */
/* return a direction that is 90 degrees counterclockwise from p2-p0,
but then restricted to one of the major wind directions (n, nw, w, etc) */
-static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
+static inline point_t
+dorth_infty (dpoint_t p0, dpoint_t p2)
+{
point_t r;
-
- r.y = sign(p2.x-p0.x);
- r.x = -sign(p2.y-p0.y);
+
+ r.y = sign (p2.x - p0.x);
+ r.x = -sign (p2.y - p0.y);
return r;
}
/* return (p1-p0)x(p2-p0), the area of the parallelogram */
-static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+static inline double
+dpara (dpoint_t p0, dpoint_t p1, dpoint_t p2)
+{
double x1, y1, x2, y2;
- x1 = p1.x-p0.x;
- y1 = p1.y-p0.y;
- x2 = p2.x-p0.x;
- y2 = p2.y-p0.y;
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p2.x - p0.x;
+ y2 = p2.y - p0.y;
- return x1*y2 - x2*y1;
+ return x1 * y2 - x2 * y1;
}
/* ddenom/dpara have the property that the square of radius 1 centered
at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
-static inline double ddenom(dpoint_t p0, dpoint_t p2) {
- point_t r = dorth_infty(p0, p2);
+static inline double
+ddenom (dpoint_t p0, dpoint_t p2)
+{
+ point_t r = dorth_infty (p0, p2);
- return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
+ return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y);
}
/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
-static inline int cyclic(int a, int b, int c) {
- if (a<=c) {
- return (a<=b && b<c);
- } else {
- return (a<=b || b<c);
- }
+static inline int
+cyclic (int a, int b, int c)
+{
+ if (a <= c)
+ {
+ return (a <= b && b < c);
+ }
+ else
+ {
+ return (a <= b || b < c);
+ }
}
/* determine the center and slope of the line i..j. Assume i<j. Needs
"sum" components of p to be set. */
-static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
+static void
+pointslope (privpath_t * pp, int i, int j, dpoint_t * ctr, dpoint_t * dir)
+{
/* assume i<j */
int n = pp->len;
@@ -81,62 +94,72 @@ static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *di
double x, y, x2, xy, y2;
double k;
double a, b, c, lambda2, l;
- int r=0; /* rotations from i to j */
+ int r = 0; /* rotations from i to j */
- while (j>=n) {
- j-=n;
- r+=1;
- }
- while (i>=n) {
- i-=n;
- r-=1;
- }
- while (j<0) {
- j+=n;
- r-=1;
- }
- while (i<0) {
- i+=n;
- r+=1;
- }
-
- x = sums[j+1].x-sums[i].x+r*sums[n].x;
- y = sums[j+1].y-sums[i].y+r*sums[n].y;
- x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
- xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
- y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
- k = j+1-i+r*n;
-
- ctr->x = x/k;
- ctr->y = y/k;
-
- a = (x2-(double)x*x/k)/k;
- b = (xy-(double)x*y/k)/k;
- c = (y2-(double)y*y/k)/k;
-
- lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
+ while (j >= n)
+ {
+ j -= n;
+ r += 1;
+ }
+ while (i >= n)
+ {
+ i -= n;
+ r -= 1;
+ }
+ while (j < 0)
+ {
+ j += n;
+ r -= 1;
+ }
+ while (i < 0)
+ {
+ i += n;
+ r += 1;
+ }
+
+ x = sums[j + 1].x - sums[i].x + r * sums[n].x;
+ y = sums[j + 1].y - sums[i].y + r * sums[n].y;
+ x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2;
+ xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy;
+ y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2;
+ k = j + 1 - i + r * n;
+
+ ctr->x = x / k;
+ ctr->y = y / k;
+
+ a = (x2 - (double) x * x / k) / k;
+ b = (xy - (double) x * y / k) / k;
+ c = (y2 - (double) y * y / k) / k;
+
+ lambda2 = (a + c + sqrt ((a - c) * (a - c) + 4 * b * b)) / 2; /* larger e.value */
/* now find e.vector for lambda2 */
a -= lambda2;
c -= lambda2;
- if (fabs(a) >= fabs(c)) {
- l = sqrt(a*a+b*b);
- if (l!=0) {
- dir->x = -b/l;
- dir->y = a/l;
+ if (fabs (a) >= fabs (c))
+ {
+ l = sqrt (a * a + b * b);
+ if (l != 0)
+ {
+ dir->x = -b / l;
+ dir->y = a / l;
+ }
}
- } else {
- l = sqrt(c*c+b*b);
- if (l!=0) {
- dir->x = -c/l;
- dir->y = b/l;
+ else
+ {
+ l = sqrt (c * c + b * b);
+ if (l != 0)
+ {
+ dir->x = -c / l;
+ dir->y = b / l;
+ }
+ }
+ if (l == 0)
+ {
+ dir->x = dir->y = 0; /* sometimes this can happen when k=4:
+ the two eigenvalues coincide */
}
- }
- if (l==0) {
- dir->x = dir->y = 0; /* sometimes this can happen when k=4:
- the two eigenvalues coincide */
- }
}
/* the type of (affine) quadratic forms, represented as symmetric 3x3
@@ -145,7 +168,9 @@ static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *di
typedef double quadform_t[3][3];
/* Apply quadratic form Q to vector w = (w.x,w.y) */
-static inline double quadform(quadform_t Q, dpoint_t w) {
+static inline double
+quadform (quadform_t Q, dpoint_t w)
+{
double v[3];
int i, j;
double sum;
@@ -155,21 +180,27 @@ static inline double quadform(quadform_t Q, dpoint_t w) {
v[2] = 1;
sum = 0.0;
- for (i=0; i<3; i++) {
- for (j=0; j<3; j++) {
- sum += v[i] * Q[i][j] * v[j];
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ sum += v[i] * Q[i][j] * v[j];
+ }
}
- }
return sum;
}
/* calculate p1 x p2 */
-static inline int xprod(point_t p1, point_t p2) {
- return p1.x*p2.y - p1.y*p2.x;
+static inline int
+xprod (point_t p1, point_t p2)
+{
+ return p1.x * p2.y - p1.y * p2.x;
}
/* calculate (p1-p0)x(p3-p2) */
-static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+static inline double
+cprod (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
+{
double x1, y1, x2, y2;
x1 = p1.x - p0.x;
@@ -177,11 +208,13 @@ static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
x2 = p3.x - p2.x;
y2 = p3.y - p2.y;
- return x1*y2 - x2*y1;
+ return x1 * y2 - x2 * y1;
}
/* calculate (p1-p0)*(p2-p0) */
-static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+static inline double
+iprod (dpoint_t p0, dpoint_t p1, dpoint_t p2)
+{
double x1, y1, x2, y2;
x1 = p1.x - p0.x;
@@ -189,11 +222,13 @@ static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
x2 = p2.x - p0.x;
y2 = p2.y - p0.y;
- return x1*x2 + y1*y2;
+ return x1 * x2 + y1 * y2;
}
/* calculate (p1-p0)*(p3-p2) */
-static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+static inline double
+iprod1 (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
+{
double x1, y1, x2, y2;
x1 = p1.x - p0.x;
@@ -201,25 +236,33 @@ static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
x2 = p3.x - p2.x;
y2 = p3.y - p2.y;
- return x1*x2 + y1*y2;
+ return x1 * x2 + y1 * y2;
}
/* calculate distance between two points */
-static inline double ddist(dpoint_t p, dpoint_t q) {
- return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
+static inline double
+ddist (dpoint_t p, dpoint_t q)
+{
+ return sqrt (sq (p.x - q.x) + sq (p.y - q.y));
}
/* calculate point of a bezier curve */
-static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
- double s = 1-t;
+static inline dpoint_t
+bezier (double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
+{
+ double s = 1 - t;
dpoint_t res;
/* Note: a good optimizing compiler (such as gcc-3) reduces the
following to 16 multiplications, using common subexpression
elimination. */
- res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
- res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
+ res.x =
+ s * s * s * p0.x + 3 * (s * s * t) * p1.x + 3 * (t * t * s) * p2.x +
+ t * t * t * p3.x;
+ res.y =
+ s * s * s * p0.y + 3 * (s * s * t) * p1.y + 3 * (t * t * s) * p2.y +
+ t * t * t * p3.y;
return res;
}
@@ -227,67 +270,80 @@ static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, d
/* calculate the point t in [0..1] on the (convex) bezier curve
(p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
solution in [0..1]. */
-static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
- double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
- double a, b, c; /* a t^2 + b t + c = 0 */
+static double
+tangent (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0,
+ dpoint_t q1)
+{
+ double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
+ double a, b, c; /* a t^2 + b t + c = 0 */
double d, s, r1, r2;
- A = cprod(p0, p1, q0, q1);
- B = cprod(p1, p2, q0, q1);
- C = cprod(p2, p3, q0, q1);
+ A = cprod (p0, p1, q0, q1);
+ B = cprod (p1, p2, q0, q1);
+ C = cprod (p2, p3, q0, q1);
- a = A - 2*B + C;
- b = -2*A + 2*B;
+ a = A - 2 * B + C;
+ b = -2 * A + 2 * B;
c = A;
-
- d = b*b - 4*a*c;
- if (a==0 || d<0) {
- return -1.0;
- }
+ d = b * b - 4 * a * c;
- s = sqrt(d);
+ if (a == 0 || d < 0)
+ {
+ return -1.0;
+ }
+
+ s = sqrt (d);
r1 = (-b + s) / (2 * a);
r2 = (-b - s) / (2 * a);
- if (r1 >= 0 && r1 <= 1) {
- return r1;
- } else if (r2 >= 0 && r2 <= 1) {
- return r2;
- } else {
- return -1.0;
- }
+ if (r1 >= 0 && r1 <= 1)
+ {
+ return r1;
+ }
+ else if (r2 >= 0 && r2 <= 1)
+ {
+ return r2;
+ }
+ else
+ {
+ return -1.0;
+ }
}
/* ---------------------------------------------------------------------- */
/* Preparation: fill in the sum* fields of a path (used for later
rapid summing). Return 0 on success, 1 with errno set on
failure. */
-static int calc_sums(privpath_t *pp) {
+static int
+calc_sums (privpath_t * pp)
+{
int i, x, y;
int n = pp->len;
- SAFE_MALLOC(pp->sums, pp->len+1, sums_t);
+ SAFE_MALLOC (pp->sums, pp->len + 1, sums_t);
/* origin */
pp->x0 = pp->pt[0].x;
pp->y0 = pp->pt[0].y;
/* preparatory computation for later fast summing */
- pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
- for (i=0; i<n; i++) {
- x = pp->pt[i].x - pp->x0;
- y = pp->pt[i].y - pp->y0;
- pp->sums[i+1].x = pp->sums[i].x + x;
- pp->sums[i+1].y = pp->sums[i].y + y;
- pp->sums[i+1].x2 = pp->sums[i].x2 + x*x;
- pp->sums[i+1].xy = pp->sums[i].xy + x*y;
- pp->sums[i+1].y2 = pp->sums[i].y2 + y*y;
- }
- return 0;
+ pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x =
+ pp->sums[0].y = 0;
+ for (i = 0; i < n; i++)
+ {
+ x = pp->pt[i].x - pp->x0;
+ y = pp->pt[i].y - pp->y0;
+ pp->sums[i + 1].x = pp->sums[i].x + x;
+ pp->sums[i + 1].y = pp->sums[i].y + y;
+ pp->sums[i + 1].x2 = pp->sums[i].x2 + x * x;
+ pp->sums[i + 1].xy = pp->sums[i].xy + x * y;
+ pp->sums[i + 1].y2 = pp->sums[i].y2 + y * y;
+ }
+ return 0;
- malloc_error:
+malloc_error:
return 1;
}
@@ -321,7 +377,9 @@ static int calc_sums(privpath_t *pp) {
substantial. */
/* returns 0 on success, 1 on error with errno set */
-static int calc_lon(privpath_t *pp) {
+static int
+calc_lon (privpath_t * pp)
+{
point_t *pt = pp->pt;
int n = pp->len;
int i, j, k, k1;
@@ -329,13 +387,13 @@ static int calc_lon(privpath_t *pp) {
point_t constraint[2];
point_t cur;
point_t off;
- int *pivk = NULL; /* pivk[n] */
- int *nc = NULL; /* nc[n]: next corner */
- point_t dk; /* direction of k-k1 */
+ int *pivk = NULL; /* pivk[n] */
+ int *nc = NULL; /* nc[n]: next corner */
+ point_t dk; /* direction of k-k1 */
int a, b, c, d;
- SAFE_MALLOC(pivk, n, int);
- SAFE_MALLOC(nc, n, int);
+ SAFE_MALLOC (pivk, n, int);
+ SAFE_MALLOC (nc, n, int);
/* initialize the nc data structure. Point from each point to the
furthest future point to which it is connected by a vertical or
@@ -345,136 +403,164 @@ static int calc_lon(privpath_t *pp) {
in practice, correctness does not depend on the word "furthest"
above. */
k = 0;
- for (i=n-1; i>=0; i--) {
- if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
- k = i+1; /* necessarily i<n-1 in this case */
+ for (i = n - 1; i >= 0; i--)
+ {
+ if (pt[i].x != pt[k].x && pt[i].y != pt[k].y)
+ {
+ k = i + 1; /* necessarily i<n-1 in this case */
+ }
+ nc[i] = k;
}
- nc[i] = k;
- }
- SAFE_MALLOC(pp->lon, n, int);
+ SAFE_MALLOC (pp->lon, n, int);
/* determine pivot points: for each i, let pivk[i] be the furthest k
such that all j with i<j<k lie on a line connecting i,k. */
-
- for (i=n-1; i>=0; i--) {
- ct[0] = ct[1] = ct[2] = ct[3] = 0;
-
- /* keep track of "directions" that have occurred */
- dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
- ct[dir]++;
-
- constraint[0].x = 0;
- constraint[0].y = 0;
- constraint[1].x = 0;
- constraint[1].y = 0;
-
- /* find the next k such that no straight line from i to k */
- k = nc[i];
- k1 = i;
- while (1) {
-
- dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
+
+ for (i = n - 1; i >= 0; i--)
+ {
+ ct[0] = ct[1] = ct[2] = ct[3] = 0;
+
+ /* keep track of "directions" that have occurred */
+ dir =
+ (3 + 3 * (pt[mod (i + 1, n)].x - pt[i].x) +
+ (pt[mod (i + 1, n)].y - pt[i].y)) / 2;
ct[dir]++;
- /* if all four "directions" have occurred, cut this path */
- if (ct[0] && ct[1] && ct[2] && ct[3]) {
- pivk[i] = k1;
- goto foundk;
- }
-
- cur.x = pt[k].x - pt[i].x;
- cur.y = pt[k].y - pt[i].y;
-
- /* see if current constraint is violated */
- if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
- goto constraint_viol;
- }
-
- /* else, update constraint */
- if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
- /* no constraint */
- } else {
- off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
- off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
- if (xprod(constraint[0], off) >= 0) {
- constraint[0] = off;
+ constraint[0].x = 0;
+ constraint[0].y = 0;
+ constraint[1].x = 0;
+ constraint[1].y = 0;
+
+ /* find the next k such that no straight line from i to k */
+ k = nc[i];
+ k1 = i;
+ while (1)
+ {
+
+ dir =
+ (3 + 3 * sign (pt[k].x - pt[k1].x) +
+ sign (pt[k].y - pt[k1].y)) / 2;
+ ct[dir]++;
+
+ /* if all four "directions" have occurred, cut this path */
+ if (ct[0] && ct[1] && ct[2] && ct[3])
+ {
+ pivk[i] = k1;
+ goto foundk;
+ }
+
+ cur.x = pt[k].x - pt[i].x;
+ cur.y = pt[k].y - pt[i].y;
+
+ /* see if current constraint is violated */
+ if (xprod (constraint[0], cur) < 0
+ || xprod (constraint[1], cur) > 0)
+ {
+ goto constraint_viol;
+ }
+
+ /* else, update constraint */
+ if (abs (cur.x) <= 1 && abs (cur.y) <= 1)
+ {
+ /* no constraint */
+ }
+ else
+ {
+ off.x =
+ cur.x + ((cur.y >= 0 && (cur.y > 0 || cur.x < 0)) ? 1 : -1);
+ off.y =
+ cur.y + ((cur.x <= 0 && (cur.x < 0 || cur.y < 0)) ? 1 : -1);
+ if (xprod (constraint[0], off) >= 0)
+ {
+ constraint[0] = off;
+ }
+ off.x =
+ cur.x + ((cur.y <= 0 && (cur.y < 0 || cur.x < 0)) ? 1 : -1);
+ off.y =
+ cur.y + ((cur.x >= 0 && (cur.x > 0 || cur.y < 0)) ? 1 : -1);
+ if (xprod (constraint[1], off) <= 0)
+ {
+ constraint[1] = off;
+ }
+ }
+ k1 = k;
+ k = nc[k1];
+ if (!cyclic (k, i, k1))
+ {
+ break;
+ }
}
- off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
- off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
- if (xprod(constraint[1], off) <= 0) {
- constraint[1] = off;
+ constraint_viol:
+ /* k1 was the last "corner" satisfying the current constraint, and
+ k is the first one violating it. We now need to find the last
+ point along k1..k which satisfied the constraint. */
+ dk.x = sign (pt[k].x - pt[k1].x);
+ dk.y = sign (pt[k].y - pt[k1].y);
+ cur.x = pt[k1].x - pt[i].x;
+ cur.y = pt[k1].y - pt[i].y;
+ /* find largest integer j such that xprod(constraint[0], cur+j*dk)
+ >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
+ of xprod. */
+ a = xprod (constraint[0], cur);
+ b = xprod (constraint[0], dk);
+ c = xprod (constraint[1], cur);
+ d = xprod (constraint[1], dk);
+ /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
+ can be solved with integer arithmetic. */
+ j = INFTY;
+ if (b < 0)
+ {
+ j = floordiv (a, -b);
}
- }
- k1 = k;
- k = nc[k1];
- if (!cyclic(k,i,k1)) {
- break;
- }
- }
- constraint_viol:
- /* k1 was the last "corner" satisfying the current constraint, and
- k is the first one violating it. We now need to find the last
- point along k1..k which satisfied the constraint. */
- dk.x = sign(pt[k].x-pt[k1].x);
- dk.y = sign(pt[k].y-pt[k1].y);
- cur.x = pt[k1].x - pt[i].x;
- cur.y = pt[k1].y - pt[i].y;
- /* find largest integer j such that xprod(constraint[0], cur+j*dk)
- >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
- of xprod. */
- a = xprod(constraint[0], cur);
- b = xprod(constraint[0], dk);
- c = xprod(constraint[1], cur);
- d = xprod(constraint[1], dk);
- /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
- can be solved with integer arithmetic. */
- j = INFTY;
- if (b<0) {
- j = floordiv(a,-b);
- }
- if (d>0) {
- j = min(j, floordiv(-c,d));
- }
- pivk[i] = mod(k1+j,n);
- foundk:
- ;
- } /* for i */
+ if (d > 0)
+ {
+ j = min (j, floordiv (-c, d));
+ }
+ pivk[i] = mod (k1 + j, n);
+ foundk:
+ ;
+ } /* for i */
/* clean up: for each i, let lon[i] be the largest k such that for
all i' with i<=i'<k, i'<k<=pivk[i']. */
- j=pivk[n-1];
- pp->lon[n-1]=j;
- for (i=n-2; i>=0; i--) {
- if (cyclic(i+1,pivk[i],j)) {
- j=pivk[i];
+ j = pivk[n - 1];
+ pp->lon[n - 1] = j;
+ for (i = n - 2; i >= 0; i--)
+ {
+ if (cyclic (i + 1, pivk[i], j))
+ {
+ j = pivk[i];
+ }
+ pp->lon[i] = j;
}
- pp->lon[i]=j;
- }
- for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
- pp->lon[i] = j;
- }
+ for (i = n - 1; cyclic (mod (i + 1, n), j, pp->lon[i]); i--)
+ {
+ pp->lon[i] = j;
+ }
- free(pivk);
- free(nc);
+ free (pivk);
+ free (nc);
return 0;
- malloc_error:
- free(pivk);
- free(nc);
+malloc_error:
+ free (pivk);
+ free (nc);
return 1;
}
/* ---------------------------------------------------------------------- */
-/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
+/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
/* Auxiliary function: calculate the penalty of an edge from i to j in
the given path. This needs the "lon" and "sum*" data. */
-static double penalty3(privpath_t *pp, int i, int j) {
+static double
+penalty3 (privpath_t * pp, int i, int j)
+{
int n = pp->len;
point_t *pt = pp->pt;
sums_t *sums = pp->sums;
@@ -485,141 +571,157 @@ static double penalty3(privpath_t *pp, int i, int j) {
double a, b, c, s;
double px, py, ex, ey;
- int r=0; /* rotations from i to j */
+ int r = 0; /* rotations from i to j */
- if (j>=n) {
- j-=n;
- r+=1;
- }
-
- x = sums[j+1].x-sums[i].x+r*sums[n].x;
- y = sums[j+1].y-sums[i].y+r*sums[n].y;
- x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
- xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
- y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
- k = j+1-i+r*n;
-
- px = (pt[i].x+pt[j].x)/2.0-pt[0].x;
- py = (pt[i].y+pt[j].y)/2.0-pt[0].y;
- ey = (pt[j].x-pt[i].x);
- ex = -(pt[j].y-pt[i].y);
-
- a = ((x2-2*x*px)/k+px*px);
- b = ((xy-x*py-y*px)/k+px*py);
- c = ((y2-2*y*py)/k+py*py);
-
- s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
-
- return sqrt(s);
+ if (j >= n)
+ {
+ j -= n;
+ r += 1;
+ }
+
+ x = sums[j + 1].x - sums[i].x + r * sums[n].x;
+ y = sums[j + 1].y - sums[i].y + r * sums[n].y;
+ x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2;
+ xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy;
+ y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2;
+ k = j + 1 - i + r * n;
+
+ px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
+ py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
+ ey = (pt[j].x - pt[i].x);
+ ex = -(pt[j].y - pt[i].y);
+
+ a = ((x2 - 2 * x * px) / k + px * px);
+ b = ((xy - x * py - y * px) / k + px * py);
+ c = ((y2 - 2 * y * py) / k + py * py);
+
+ s = ex * ex * a + 2 * ex * ey * b + ey * ey * c;
+
+ return sqrt (s);
}
/* find the optimal polygon. Fill in the m and po components. Return 1
on failure with errno set, else 0. Non-cyclic version: assumes i=0
is in the polygon. Fixme: ### implement cyclic version. */
-static int bestpolygon(privpath_t *pp)
+static int
+bestpolygon (privpath_t * pp)
{
- int i, j, m, k;
+ int i, j, m, k;
int n = pp->len;
- double *pen = NULL; /* pen[n+1]: penalty vector */
- int *prev = NULL; /* prev[n+1]: best path pointer vector */
- int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */
- int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */
- int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */
- int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */
+ double *pen = NULL; /* pen[n+1]: penalty vector */
+ int *prev = NULL; /* prev[n+1]: best path pointer vector */
+ int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */
+ int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */
+ int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */
+ int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */
double thispen;
double best;
int c;
- SAFE_MALLOC(pen, n+1, double);
- SAFE_MALLOC(prev, n+1, int);
- SAFE_MALLOC(clip0, n, int);
- SAFE_MALLOC(clip1, n+1, int);
- SAFE_MALLOC(seg0, n+1, int);
- SAFE_MALLOC(seg1, n+1, int);
+ SAFE_MALLOC (pen, n + 1, double);
+ SAFE_MALLOC (prev, n + 1, int);
+ SAFE_MALLOC (clip0, n, int);
+ SAFE_MALLOC (clip1, n + 1, int);
+ SAFE_MALLOC (seg0, n + 1, int);
+ SAFE_MALLOC (seg1, n + 1, int);
/* calculate clipped paths */
- for (i=0; i<n; i++) {
- c = mod(pp->lon[mod(i-1,n)]-1,n);
- if (c == i) {
- c = mod(i+1,n);
- }
- if (c < i) {
- clip0[i] = n;
- } else {
- clip0[i] = c;
+ for (i = 0; i < n; i++)
+ {
+ c = mod (pp->lon[mod (i - 1, n)] - 1, n);
+ if (c == i)
+ {
+ c = mod (i + 1, n);
+ }
+ if (c < i)
+ {
+ clip0[i] = n;
+ }
+ else
+ {
+ clip0[i] = c;
+ }
}
- }
/* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
clip1[j] <= i, for i,j=0..n. */
j = 1;
- for (i=0; i<n; i++) {
- while (j <= clip0[i]) {
- clip1[j] = i;
- j++;
+ for (i = 0; i < n; i++)
+ {
+ while (j <= clip0[i])
+ {
+ clip1[j] = i;
+ j++;
+ }
}
- }
/* calculate seg0[j] = longest path from 0 with j segments */
i = 0;
- for (j=0; i<n; j++) {
- seg0[j] = i;
- i = clip0[i];
- }
+ for (j = 0; i < n; j++)
+ {
+ seg0[j] = i;
+ i = clip0[i];
+ }
seg0[j] = n;
m = j;
/* calculate seg1[j] = longest path to n with m-j segments */
i = n;
- for (j=m; j>0; j--) {
- seg1[j] = i;
- i = clip1[i];
- }
+ for (j = m; j > 0; j--)
+ {
+ seg1[j] = i;
+ i = clip1[i];
+ }
seg1[0] = 0;
/* now find the shortest path with m segments, based on penalty3 */
/* note: the outer 2 loops jointly have at most n interations, thus
the worst-case behavior here is quadratic. In practice, it is
close to linear since the inner loop tends to be short. */
- pen[0]=0;
- for (j=1; j<=m; j++) {
- for (i=seg1[j]; i<=seg0[j]; i++) {
- best = -1;
- for (k=seg0[j-1]; k>=clip1[i]; k--) {
- thispen = penalty3(pp, k, i) + pen[k];
- if (best < 0 || thispen < best) {
- prev[i] = k;
- best = thispen;
+ pen[0] = 0;
+ for (j = 1; j <= m; j++)
+ {
+ for (i = seg1[j]; i <= seg0[j]; i++)
+ {
+ best = -1;
+ for (k = seg0[j - 1]; k >= clip1[i]; k--)
+ {
+ thispen = penalty3 (pp, k, i) + pen[k];
+ if (best < 0 || thispen < best)
+ {
+ prev[i] = k;
+ best = thispen;
+ }
+ }
+ pen[i] = best;
}
- }
- pen[i] = best;
}
- }
pp->m = m;
- SAFE_MALLOC(pp->po, m, int);
+ SAFE_MALLOC (pp->po, m, int);
/* read off shortest path */
- for (i=n, j=m-1; i>0; j--) {
- i = prev[i];
- pp->po[j] = i;
- }
+ for (i = n, j = m - 1; i > 0; j--)
+ {
+ i = prev[i];
+ pp->po[j] = i;
+ }
- free(pen);
- free(prev);
- free(clip0);
- free(clip1);
- free(seg0);
- free(seg1);
+ free (pen);
+ free (prev);
+ free (clip0);
+ free (clip1);
+ free (seg0);
+ free (seg1);
return 0;
-
- malloc_error:
- free(pen);
- free(prev);
- free(clip0);
- free(clip1);
- free(seg0);
- free(seg1);
+
+malloc_error:
+ free (pen);
+ free (prev);
+ free (clip0);
+ free (clip1);
+ free (seg0);
+ free (seg1);
return 1;
}
@@ -631,7 +733,9 @@ static int bestpolygon(privpath_t *pp)
if it lies outside. Return 1 with errno set on error; 0 on
success. */
-static int adjust_vertices(privpath_t *pp) {
+static int
+adjust_vertices (privpath_t * pp)
+{
int m = pp->m;
int *po = pp->po;
int n = pp->len;
@@ -639,191 +743,223 @@ static int adjust_vertices(privpath_t *pp) {
int x0 = pp->x0;
int y0 = pp->y0;
- dpoint_t *ctr = NULL; /* ctr[m] */
- dpoint_t *dir = NULL; /* dir[m] */
- quadform_t *q = NULL; /* q[m] */
+ dpoint_t *ctr = NULL; /* ctr[m] */
+ dpoint_t *dir = NULL; /* dir[m] */
+ quadform_t *q = NULL; /* q[m] */
double v[3];
double d;
int i, j, k, l;
dpoint_t s;
int r;
- SAFE_MALLOC(ctr, m, dpoint_t);
- SAFE_MALLOC(dir, m, dpoint_t);
- SAFE_MALLOC(q, m, quadform_t);
+ SAFE_MALLOC (ctr, m, dpoint_t);
+ SAFE_MALLOC (dir, m, dpoint_t);
+ SAFE_MALLOC (q, m, quadform_t);
+
+ r = privcurve_init (&pp->curve, m);
+ if (r)
+ {
+ goto malloc_error;
+ }
- r = privcurve_init(&pp->curve, m);
- if (r) {
- goto malloc_error;
- }
-
/* calculate "optimal" point-slope representation for each line
segment */
- for (i=0; i<m; i++) {
- j = po[mod(i+1,m)];
- j = mod(j-po[i],n)+po[i];
- pointslope(pp, po[i], j, &ctr[i], &dir[i]);
- }
+ for (i = 0; i < m; i++)
+ {
+ j = po[mod (i + 1, m)];
+ j = mod (j - po[i], n) + po[i];
+ pointslope (pp, po[i], j, &ctr[i], &dir[i]);
+ }
/* represent each line segment as a singular quadratic form; the
distance of a point (x,y) from the line segment will be
(x,y,1)Q(x,y,1)^t, where Q=q[i]. */
- for (i=0; i<m; i++) {
- d = sq(dir[i].x) + sq(dir[i].y);
- if (d == 0.0) {
- for (j=0; j<3; j++) {
- for (k=0; k<3; k++) {
- q[i][j][k] = 0;
+ for (i = 0; i < m; i++)
+ {
+ d = sq (dir[i].x) + sq (dir[i].y);
+ if (d == 0.0)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ q[i][j][k] = 0;
+ }
+ }
}
- }
- } else {
- v[0] = dir[i].y;
- v[1] = -dir[i].x;
- v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
- for (l=0; l<3; l++) {
- for (k=0; k<3; k++) {
- q[i][l][k] = v[l] * v[k] / d;
+ else
+ {
+ v[0] = dir[i].y;
+ v[1] = -dir[i].x;
+ v[2] = -v[1] * ctr[i].y - v[0] * ctr[i].x;
+ for (l = 0; l < 3; l++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ q[i][l][k] = v[l] * v[k] / d;
+ }
+ }
}
- }
}
- }
/* now calculate the "intersections" of consecutive segments.
Instead of using the actual intersection, we find the point
within a given unit square which minimizes the square distance to
the two lines. */
- for (i=0; i<m; i++) {
- quadform_t Q;
- dpoint_t w;
- double dx, dy;
- double det;
- double min, cand; /* minimum and candidate for minimum of quad. form */
- double xmin, ymin; /* coordinates of minimum */
- int z;
-
- /* let s be the vertex, in coordinates relative to x0/y0 */
- s.x = pt[po[i]].x-x0;
- s.y = pt[po[i]].y-y0;
-
- /* intersect segments i-1 and i */
-
- j = mod(i-1,m);
-
- /* add quadratic forms */
- for (l=0; l<3; l++) {
- for (k=0; k<3; k++) {
- Q[l][k] = q[j][l][k] + q[i][l][k];
- }
- }
-
- while(1) {
- /* minimize the quadratic form Q on the unit square */
- /* find intersection */
+ for (i = 0; i < m; i++)
+ {
+ quadform_t Q;
+ dpoint_t w;
+ double dx, dy;
+ double det;
+ double min, cand; /* minimum and candidate for minimum of quad. form */
+ double xmin, ymin; /* coordinates of minimum */
+ int z;
+
+ /* let s be the vertex, in coordinates relative to x0/y0 */
+ s.x = pt[po[i]].x - x0;
+ s.y = pt[po[i]].y - y0;
+
+ /* intersect segments i-1 and i */
+
+ j = mod (i - 1, m);
+
+ /* add quadratic forms */
+ for (l = 0; l < 3; l++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ Q[l][k] = q[j][l][k] + q[i][l][k];
+ }
+ }
+
+ while (1)
+ {
+ /* minimize the quadratic form Q on the unit square */
+ /* find intersection */
#ifdef HAVE_GCC_LOOP_BUG
- /* work around gcc bug #12243 */
- free(NULL);
+ /* work around gcc bug #12243 */
+ free (NULL);
#endif
-
- det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
- if (det != 0.0) {
- w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
- w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
- break;
- }
-
- /* matrix is singular - lines are parallel. Add another,
- orthogonal axis, through the center of the unit square */
- if (Q[0][0]>Q[1][1]) {
- v[0] = -Q[0][1];
- v[1] = Q[0][0];
- } else if (Q[1][1]) {
- v[0] = -Q[1][1];
- v[1] = Q[1][0];
- } else {
- v[0] = 1;
- v[1] = 0;
- }
- d = sq(v[0]) + sq(v[1]);
- v[2] = - v[1] * s.y - v[0] * s.x;
- for (l=0; l<3; l++) {
- for (k=0; k<3; k++) {
- Q[l][k] += v[l] * v[k] / d;
+
+ det = Q[0][0] * Q[1][1] - Q[0][1] * Q[1][0];
+ if (det != 0.0)
+ {
+ w.x = (-Q[0][2] * Q[1][1] + Q[1][2] * Q[0][1]) / det;
+ w.y = (Q[0][2] * Q[1][0] - Q[1][2] * Q[0][0]) / det;
+ break;
+ }
+
+ /* matrix is singular - lines are parallel. Add another,
+ orthogonal axis, through the center of the unit square */
+ if (Q[0][0] > Q[1][1])
+ {
+ v[0] = -Q[0][1];
+ v[1] = Q[0][0];
+ }
+ else if (Q[1][1])
+ {
+ v[0] = -Q[1][1];
+ v[1] = Q[1][0];
+ }
+ else
+ {
+ v[0] = 1;
+ v[1] = 0;
+ }
+ d = sq (v[0]) + sq (v[1]);
+ v[2] = -v[1] * s.y - v[0] * s.x;
+ for (l = 0; l < 3; l++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ Q[l][k] += v[l] * v[k] / d;
+ }
+ }
+ }
+ dx = fabs (w.x - s.x);
+ dy = fabs (w.y - s.y);
+ if (dx <= .5 && dy <= .5)
+ {
+ pp->curve.vertex[i].x = w.x + x0;
+ pp->curve.vertex[i].y = w.y + y0;
+ continue;
}
- }
- }
- dx = fabs(w.x-s.x);
- dy = fabs(w.y-s.y);
- if (dx <= .5 && dy <= .5) {
- pp->curve.vertex[i].x = w.x+x0;
- pp->curve.vertex[i].y = w.y+y0;
- continue;
- }
- /* the minimum was not in the unit square; now minimize quadratic
- on boundary of square */
- min = quadform(Q, s);
- xmin = s.x;
- ymin = s.y;
+ /* the minimum was not in the unit square; now minimize quadratic
+ on boundary of square */
+ min = quadform (Q, s);
+ xmin = s.x;
+ ymin = s.y;
- if (Q[0][0] == 0.0) {
- goto fixx;
- }
- for (z=0; z<2; z++) { /* value of the y-coordinate */
- w.y = s.y-0.5+z;
- w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
- dx = fabs(w.x-s.x);
- cand = quadform(Q, w);
- if (dx <= .5 && cand < min) {
- min = cand;
- xmin = w.x;
- ymin = w.y;
- }
- }
- fixx:
- if (Q[1][1] == 0.0) {
- goto corners;
- }
- for (z=0; z<2; z++) { /* value of the x-coordinate */
- w.x = s.x-0.5+z;
- w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
- dy = fabs(w.y-s.y);
- cand = quadform(Q, w);
- if (dy <= .5 && cand < min) {
- min = cand;
- xmin = w.x;
- ymin = w.y;
- }
- }
- corners:
- /* check four corners */
- for (l=0; l<2; l++) {
- for (k=0; k<2; k++) {
- w.x = s.x-0.5+l;
- w.y = s.y-0.5+k;
- cand = quadform(Q, w);
- if (cand < min) {
- min = cand;
- xmin = w.x;
- ymin = w.y;
+ if (Q[0][0] == 0.0)
+ {
+ goto fixx;
+ }
+ for (z = 0; z < 2; z++)
+ { /* value of the y-coordinate */
+ w.y = s.y - 0.5 + z;
+ w.x = -(Q[0][1] * w.y + Q[0][2]) / Q[0][0];
+ dx = fabs (w.x - s.x);
+ cand = quadform (Q, w);
+ if (dx <= .5 && cand < min)
+ {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ fixx:
+ if (Q[1][1] == 0.0)
+ {
+ goto corners;
+ }
+ for (z = 0; z < 2; z++)
+ { /* value of the x-coordinate */
+ w.x = s.x - 0.5 + z;
+ w.y = -(Q[1][0] * w.x + Q[1][2]) / Q[1][1];
+ dy = fabs (w.y - s.y);
+ cand = quadform (Q, w);
+ if (dy <= .5 && cand < min)
+ {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ corners:
+ /* check four corners */
+ for (l = 0; l < 2; l++)
+ {
+ for (k = 0; k < 2; k++)
+ {
+ w.x = s.x - 0.5 + l;
+ w.y = s.y - 0.5 + k;
+ cand = quadform (Q, w);
+ if (cand < min)
+ {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
}
- }
- }
- pp->curve.vertex[i].x = xmin + x0;
- pp->curve.vertex[i].y = ymin + y0;
- continue;
- }
+ pp->curve.vertex[i].x = xmin + x0;
+ pp->curve.vertex[i].y = ymin + y0;
+ continue;
+ }
- free(ctr);
- free(dir);
- free(q);
+ free (ctr);
+ free (dir);
+ free (q);
return 0;
- malloc_error:
- free(ctr);
- free(dir);
- free(q);
+malloc_error:
+ free (ctr);
+ free (dir);
+ free (q);
return 1;
}
@@ -831,60 +967,76 @@ static int adjust_vertices(privpath_t *pp) {
/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
/* Always succeeds and returns 0 */
-static int smooth(privcurve_t *curve, int sign, double alphamax) {
+static int
+smooth (privcurve_t * curve, int sign, double alphamax)
+{
int m = curve->n;
int i, j, k;
double dd, denom, alpha;
dpoint_t p2, p3, p4;
- if (sign == '-') {
- /* reverse orientation of negative paths */
- for (i=0, j=m-1; i<j; i++, j--) {
- dpoint_t tmp;
- tmp = curve->vertex[i];
- curve->vertex[i] = curve->vertex[j];
- curve->vertex[j] = tmp;
+ if (sign == '-')
+ {
+ /* reverse orientation of negative paths */
+ for (i = 0, j = m - 1; i < j; i++, j--)
+ {
+ dpoint_t tmp;
+ tmp = curve->vertex[i];
+ curve->vertex[i] = curve->vertex[j];
+ curve->vertex[j] = tmp;
+ }
}
- }
/* examine each vertex and find its best fit */
- for (i=0; i<m; i++) {
- j = mod(i+1, m);
- k = mod(i+2, m);
- p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
-
- denom = ddenom(curve->vertex[i], curve->vertex[k]);
- if (denom != 0.0) {
- dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
- dd = fabs(dd);
- alpha = dd>1 ? (1 - 1.0/dd) : 0;
- alpha = alpha / 0.75;
- } else {
- alpha = 4/3.0;
- }
- curve->alpha0[j] = alpha; /* remember "original" value of alpha */
+ for (i = 0; i < m; i++)
+ {
+ j = mod (i + 1, m);
+ k = mod (i + 2, m);
+ p4 = interval (1 / 2.0, curve->vertex[k], curve->vertex[j]);
+
+ denom = ddenom (curve->vertex[i], curve->vertex[k]);
+ if (denom != 0.0)
+ {
+ dd =
+ dpara (curve->vertex[i], curve->vertex[j],
+ curve->vertex[k]) / denom;
+ dd = fabs (dd);
+ alpha = dd > 1 ? (1 - 1.0 / dd) : 0;
+ alpha = alpha / 0.75;
+ }
+ else
+ {
+ alpha = 4 / 3.0;
+ }
+ curve->alpha0[j] = alpha; /* remember "original" value of alpha */
- if (alpha > alphamax) { /* pointed corner */
- curve->tag[j] = POTRACE_CORNER;
- curve->c[j][1] = curve->vertex[j];
- curve->c[j][2] = p4;
- } else {
- if (alpha < 0.55) {
- alpha = 0.55;
- } else if (alpha > 1) {
- alpha = 1;
- }
- p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
- p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
- curve->tag[j] = POTRACE_CURVETO;
- curve->c[j][0] = p2;
- curve->c[j][1] = p3;
- curve->c[j][2] = p4;
+ if (alpha > alphamax)
+ { /* pointed corner */
+ curve->tag[j] = POTRACE_CORNER;
+ curve->c[j][1] = curve->vertex[j];
+ curve->c[j][2] = p4;
+ }
+ else
+ {
+ if (alpha < 0.55)
+ {
+ alpha = 0.55;
+ }
+ else if (alpha > 1)
+ {
+ alpha = 1;
+ }
+ p2 = interval (.5 + .5 * alpha, curve->vertex[i], curve->vertex[j]);
+ p3 = interval (.5 + .5 * alpha, curve->vertex[k], curve->vertex[j]);
+ curve->tag[j] = POTRACE_CURVETO;
+ curve->c[j][0] = p2;
+ curve->c[j][1] = p3;
+ curve->c[j][2] = p4;
+ }
+ curve->alpha[j] = alpha; /* store the "cropped" value of alpha */
+ curve->beta[j] = 0.5;
}
- curve->alpha[j] = alpha; /* store the "cropped" value of alpha */
- curve->beta[j] = 0.5;
- }
curve->alphacurve = 1;
return 0;
@@ -894,18 +1046,22 @@ static int smooth(privcurve_t *curve, int sign, double alphamax) {
/* Stage 5: Curve optimization (Sec. 2.4) */
/* a private type for the result of opti_penalty */
-struct opti_s {
- double pen; /* penalty */
- dpoint_t c[2]; /* curve parameters */
- double t, s; /* curve parameters */
- double alpha; /* curve parameter */
+struct opti_s
+{
+ double pen; /* penalty */
+ dpoint_t c[2]; /* curve parameters */
+ double t, s; /* curve parameters */
+ double alpha; /* curve parameter */
};
typedef struct opti_s opti_t;
/* calculate best fit from i+.5 to j+.5. Assume i<j (cyclically).
Return 0 and set badness and parameters (alpha, beta), if
possible. Return 1 if impossible. */
-static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
+static int
+opti_penalty (privpath_t * pp, int i, int j, opti_t * res,
+ double opttolerance, int *convc, double *areac)
+{
int m = pp->curve.n;
int k, k1, k2, conv, i1;
double area, alpha, d, d1, d2;
@@ -915,130 +1071,160 @@ static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttol
/* check convexity, corner-freeness, and maximum bend < 179 degrees */
- if (i==j) { /* sanity - a full loop can never be an opticurve */
- return 1;
- }
+ if (i == j)
+ { /* sanity - a full loop can never be an opticurve */
+ return 1;
+ }
k = i;
- i1 = mod(i+1, m);
- k1 = mod(k+1, m);
+ i1 = mod (i + 1, m);
+ k1 = mod (k + 1, m);
conv = convc[k1];
- if (conv == 0) {
- return 1;
- }
- d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
- for (k=k1; k!=j; k=k1) {
- k1 = mod(k+1, m);
- k2 = mod(k+2, m);
- if (convc[k1] != conv) {
- return 1;
- }
- if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
+ if (conv == 0)
+ {
return 1;
}
- 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) {
- return 1;
+ d = ddist (pp->curve.vertex[i], pp->curve.vertex[i1]);
+ for (k = k1; k != j; k = k1)
+ {
+ k1 = mod (k + 1, m);
+ k2 = mod (k + 2, m);
+ if (convc[k1] != conv)
+ {
+ return 1;
+ }
+ if (sign
+ (cprod
+ (pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
+ pp->curve.vertex[k2])) != conv)
+ {
+ return 1;
+ }
+ 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)
+ {
+ return 1;
+ }
}
- }
/* the curve we're working in: */
- p0 = pp->curve.c[mod(i,m)][2];
- p1 = pp->curve.vertex[mod(i+1,m)];
- p2 = pp->curve.vertex[mod(j,m)];
- p3 = pp->curve.c[mod(j,m)][2];
+ p0 = pp->curve.c[mod (i, m)][2];
+ p1 = pp->curve.vertex[mod (i + 1, m)];
+ p2 = pp->curve.vertex[mod (j, m)];
+ p3 = pp->curve.c[mod (j, m)][2];
/* determine its area */
area = areac[j] - areac[i];
- area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
- if (i>=j) {
- area += areac[m];
- }
+ area -=
+ dpara (pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2]) / 2;
+ if (i >= j)
+ {
+ area += areac[m];
+ }
/* find intersection o of p0p1 and p2p3. Let t,s such that o =
interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
triangle (p0,o,p3). */
- A1 = dpara(p0, p1, p2);
- A2 = dpara(p0, p1, p3);
- A3 = dpara(p0, p2, p3);
+ A1 = dpara (p0, p1, p2);
+ A2 = dpara (p0, p1, p3);
+ A3 = dpara (p0, p2, p3);
/* A4 = dpara(p1, p2, p3); */
- A4 = A1+A3-A2;
-
- if (A2 == A1) { /* this should never happen */
- return 1;
- }
+ A4 = A1 + A3 - A2;
+
+ if (A2 == A1)
+ { /* this should never happen */
+ return 1;
+ }
- t = A3/(A3-A4);
- s = A2/(A2-A1);
+ t = A3 / (A3 - A4);
+ s = A2 / (A2 - A1);
A = A2 * t / 2.0;
-
- if (A == 0.0) { /* this should never happen */
- return 1;
- }
- R = area / A; /* relative area */
- alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */
+ if (A == 0.0)
+ { /* this should never happen */
+ return 1;
+ }
- res->c[0] = interval(t * alpha, p0, p1);
- res->c[1] = interval(s * alpha, p3, p2);
+ R = area / A; /* relative area */
+ alpha = 2 - sqrt (4 - R / 0.3); /* overall alpha for p0-o-p3 curve */
+
+ res->c[0] = interval (t * alpha, p0, p1);
+ res->c[1] = interval (s * alpha, p3, p2);
res->alpha = alpha;
res->t = t;
res->s = s;
p1 = res->c[0];
- p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */
+ p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */
res->pen = 0;
/* calculate penalty */
/* check tangency with edges */
- for (k=mod(i+1,m); k!=j; k=k1) {
- k1 = mod(k+1,m);
- t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
- if (t<-.5) {
- return 1;
- }
- pt = bezier(t, p0, p1, p2, p3);
- d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
- if (d == 0.0) { /* this should never happen */
- return 1;
- }
- d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
- if (fabs(d1) > opttolerance) {
- return 1;
- }
- if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
- return 1;
+ for (k = mod (i + 1, m); k != j; k = k1)
+ {
+ k1 = mod (k + 1, m);
+ t = tangent (p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (t < -.5)
+ {
+ return 1;
+ }
+ pt = bezier (t, p0, p1, p2, p3);
+ d = ddist (pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (d == 0.0)
+ { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara (pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
+ if (fabs (d1) > opttolerance)
+ {
+ return 1;
+ }
+ if (iprod (pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0
+ || iprod (pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0)
+ {
+ return 1;
+ }
+ res->pen += sq (d1);
}
- res->pen += sq(d1);
- }
/* check corners */
- for (k=i; k!=j; k=k1) {
- k1 = mod(k+1,m);
- t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
- if (t<-.5) {
- return 1;
- }
- pt = bezier(t, p0, p1, p2, p3);
- d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
- if (d == 0.0) { /* this should never happen */
- return 1;
- }
- d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
- d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
- d2 *= 0.75 * pp->curve.alpha[k1];
- if (d2 < 0) {
- d1 = -d1;
- d2 = -d2;
- }
- if (d1 < d2 - opttolerance) {
- return 1;
- }
- if (d1 < d2) {
- res->pen += sq(d1 - d2);
+ for (k = i; k != j; k = k1)
+ {
+ k1 = mod (k + 1, m);
+ t = tangent (p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (t < -.5)
+ {
+ return 1;
+ }
+ pt = bezier (t, p0, p1, p2, p3);
+ d = ddist (pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (d == 0.0)
+ { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara (pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
+ d2 =
+ dpara (pp->curve.c[k][2], pp->curve.c[k1][2],
+ pp->curve.vertex[k1]) / d;
+ d2 *= 0.75 * pp->curve.alpha[k1];
+ if (d2 < 0)
+ {
+ d1 = -d1;
+ d2 = -d2;
+ }
+ if (d1 < d2 - opttolerance)
+ {
+ return 1;
+ }
+ if (d1 < d2)
+ {
+ res->pen += sq (d1 - d2);
+ }
}
- }
return 0;
}
@@ -1046,14 +1232,16 @@ static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttol
/* optimize the path p, replacing sequences of Bezier segments by a
single segment when possible. Return 0 on success, 1 with errno set
on failure. */
-static int opticurve(privpath_t *pp, double opttolerance) {
+static int
+opticurve (privpath_t * pp, double opttolerance)
+{
int m = pp->curve.n;
- int *pt = NULL; /* pt[m+1] */
- double *pen = NULL; /* pen[m+1] */
- int *len = NULL; /* len[m+1] */
- opti_t *opt = NULL; /* opt[m+1] */
+ int *pt = NULL; /* pt[m+1] */
+ double *pen = NULL; /* pen[m+1] */
+ int *len = NULL; /* len[m+1] */
+ opti_t *opt = NULL; /* opt[m+1] */
int om;
- int i,j,r;
+ int i, j, r;
opti_t o;
dpoint_t p0;
int i1;
@@ -1062,38 +1250,50 @@ static int opticurve(privpath_t *pp, double opttolerance) {
double *s = NULL;
double *t = NULL;
- int *convc = NULL; /* conv[m]: pre-computed convexities */
- double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
+ int *convc = NULL; /* conv[m]: pre-computed convexities */
+ double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
- SAFE_MALLOC(pt, m+1, int);
- SAFE_MALLOC(pen, m+1, double);
- SAFE_MALLOC(len, m+1, int);
- SAFE_MALLOC(opt, m+1, opti_t);
- SAFE_MALLOC(convc, m, int);
- SAFE_MALLOC(areac, m+1, double);
+ SAFE_MALLOC (pt, m + 1, int);
+ SAFE_MALLOC (pen, m + 1, double);
+ SAFE_MALLOC (len, m + 1, int);
+ SAFE_MALLOC (opt, m + 1, opti_t);
+ SAFE_MALLOC (convc, m, int);
+ SAFE_MALLOC (areac, m + 1, double);
/* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
- for (i=0; i<m; i++) {
- if (pp->curve.tag[i] == POTRACE_CURVETO) {
- convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
- } else {
- convc[i] = 0;
+ for (i = 0; i < m; i++)
+ {
+ if (pp->curve.tag[i] == POTRACE_CURVETO)
+ {
+ convc[i] =
+ sign (dpara
+ (pp->curve.vertex[mod (i - 1, m)], pp->curve.vertex[i],
+ pp->curve.vertex[mod (i + 1, m)]));
+ }
+ else
+ {
+ convc[i] = 0;
+ }
}
- }
/* pre-calculate areas */
area = 0.0;
areac[0] = 0.0;
p0 = pp->curve.vertex[0];
- for (i=0; i<m; i++) {
- i1 = mod(i+1, m);
- if (pp->curve.tag[i1] == POTRACE_CURVETO) {
- alpha = pp->curve.alpha[i1];
- area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
- area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
+ for (i = 0; i < m; i++)
+ {
+ i1 = mod (i + 1, m);
+ if (pp->curve.tag[i1] == POTRACE_CURVETO)
+ {
+ alpha = pp->curve.alpha[i1];
+ area +=
+ 0.3 * alpha * (4 - alpha) * dpara (pp->curve.c[i][2],
+ pp->curve.vertex[i1],
+ pp->curve.c[i1][2]) / 2;
+ area += dpara (p0, pp->curve.c[i][2], pp->curve.c[i1][2]) / 2;
+ }
+ areac[i + 1] = area;
}
- areac[i+1] = area;
- }
pt[0] = -1;
pen[0] = 0;
@@ -1102,132 +1302,163 @@ static int opticurve(privpath_t *pp, double opttolerance) {
/* Fixme: we always start from a fixed point -- should find the best
curve cyclically ### */
- for (j=1; j<=m; j++) {
- /* calculate best path from 0 to j */
- pt[j] = j-1;
- pen[j] = pen[j-1];
- len[j] = len[j-1]+1;
-
- for (i=j-2; i>=0; i--) {
- r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
- if (r) {
- break;
- }
- if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
- pt[j] = i;
- pen[j] = pen[i] + o.pen;
- len[j] = len[i] + 1;
- opt[j] = o;
- }
+ for (j = 1; j <= m; j++)
+ {
+ /* calculate best path from 0 to j */
+ pt[j] = j - 1;
+ pen[j] = pen[j - 1];
+ len[j] = len[j - 1] + 1;
+
+ for (i = j - 2; i >= 0; i--)
+ {
+ r =
+ opti_penalty (pp, i, mod (j, m), &o, opttolerance, convc, areac);
+ if (r)
+ {
+ break;
+ }
+ if (len[j] > len[i] + 1
+ || (len[j] == len[i] + 1 && pen[j] > pen[i] + o.pen))
+ {
+ pt[j] = i;
+ pen[j] = pen[i] + o.pen;
+ len[j] = len[i] + 1;
+ opt[j] = o;
+ }
+ }
}
- }
om = len[m];
- r = privcurve_init(&pp->ocurve, om);
- if (r) {
- goto malloc_error;
- }
- SAFE_MALLOC(s, om, double);
- SAFE_MALLOC(t, om, double);
+ r = privcurve_init (&pp->ocurve, om);
+ if (r)
+ {
+ goto malloc_error;
+ }
+ SAFE_MALLOC (s, om, double);
+ SAFE_MALLOC (t, om, double);
j = m;
- for (i=om-1; i>=0; i--) {
- if (pt[j]==j-1) {
- pp->ocurve.tag[i] = pp->curve.tag[mod(j,m)];
- pp->ocurve.c[i][0] = pp->curve.c[mod(j,m)][0];
- pp->ocurve.c[i][1] = pp->curve.c[mod(j,m)][1];
- pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
- pp->ocurve.vertex[i] = pp->curve.vertex[mod(j,m)];
- pp->ocurve.alpha[i] = pp->curve.alpha[mod(j,m)];
- pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j,m)];
- pp->ocurve.beta[i] = pp->curve.beta[mod(j,m)];
- s[i] = t[i] = 1.0;
- } else {
- pp->ocurve.tag[i] = POTRACE_CURVETO;
- pp->ocurve.c[i][0] = opt[j].c[0];
- pp->ocurve.c[i][1] = opt[j].c[1];
- pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
- pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
- pp->ocurve.alpha[i] = opt[j].alpha;
- pp->ocurve.alpha0[i] = opt[j].alpha;
- s[i] = opt[j].s;
- t[i] = opt[j].t;
+ for (i = om - 1; i >= 0; i--)
+ {
+ if (pt[j] == j - 1)
+ {
+ pp->ocurve.tag[i] = pp->curve.tag[mod (j, m)];
+ pp->ocurve.c[i][0] = pp->curve.c[mod (j, m)][0];
+ pp->ocurve.c[i][1] = pp->curve.c[mod (j, m)][1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod (j, m)][2];
+ pp->ocurve.vertex[i] = pp->curve.vertex[mod (j, m)];
+ pp->ocurve.alpha[i] = pp->curve.alpha[mod (j, m)];
+ pp->ocurve.alpha0[i] = pp->curve.alpha0[mod (j, m)];
+ pp->ocurve.beta[i] = pp->curve.beta[mod (j, m)];
+ s[i] = t[i] = 1.0;
+ }
+ else
+ {
+ pp->ocurve.tag[i] = POTRACE_CURVETO;
+ pp->ocurve.c[i][0] = opt[j].c[0];
+ pp->ocurve.c[i][1] = opt[j].c[1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod (j, m)][2];
+ pp->ocurve.vertex[i] =
+ interval (opt[j].s, pp->curve.c[mod (j, m)][2],
+ pp->curve.vertex[mod (j, m)]);
+ pp->ocurve.alpha[i] = opt[j].alpha;
+ pp->ocurve.alpha0[i] = opt[j].alpha;
+ s[i] = opt[j].s;
+ t[i] = opt[j].t;
+ }
+ j = pt[j];
}
- j = pt[j];
- }
/* calculate beta parameters */
- for (i=0; i<om; i++) {
- i1 = mod(i+1,om);
- pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
- }
+ for (i = 0; i < om; i++)
+ {
+ i1 = mod (i + 1, om);
+ pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
+ }
pp->ocurve.alphacurve = 1;
- free(pt);
- free(pen);
- free(len);
- free(opt);
- free(s);
- free(t);
- free(convc);
- free(areac);
+ free (pt);
+ free (pen);
+ free (len);
+ free (opt);
+ free (s);
+ free (t);
+ free (convc);
+ free (areac);
return 0;
- malloc_error:
- free(pt);
- free(pen);
- free(len);
- free(opt);
- free(s);
- free(t);
- free(convc);
- free(areac);
+malloc_error:
+ free (pt);
+ free (pen);
+ free (len);
+ free (opt);
+ free (s);
+ free (t);
+ free (convc);
+ free (areac);
return 1;
}
/* ---------------------------------------------------------------------- */
-double plotpolygon(privpath_t *pp,FILE* f,double scale)
+double
+plotpolygon (privpath_t * pp, FILE * f, double scale)
{
- int i;
+ int i;
int m = pp->m;
- if(!m) return 0;
+ if (!m)
+ return 0;
int *po = pp->po;
int n = pp->len;
point_t *pt = pp->pt;
int x0 = pp->x0;
int y0 = pp->y0;
- //double scale=1.0/dpi;
- double dm=0;
- fprintf(f,"G0 X%f Y%f (start point)\n",pt[po[0]].x*scale,pt[po[0]].y*scale);
- fprintf(f,"G1 Z#101\n");
- for (i=1; i<m; i++) {
- fprintf(f,"G1 X%f Y%f\n",pt[po[i]].x*scale,pt[po[i]].y*scale);
- dm+=sqrt((pt[po[i]].x-pt[po[i-1]].x)*scale*(pt[po[i]].x-pt[po[i-1]].x)*scale+\
- (pt[po[i]].y-pt[po[i-1]].y)*scale*(pt[po[i]].y-pt[po[i-1]].y)*scale);
- }
- fprintf(f,"G1 X%f Y%f\n",pt[po[0]].x*scale,pt[po[0]].y*scale);
- fprintf(f,"G0 Z#100\n");
- dm+=sqrt((pt[po[m-1]].x-pt[po[0]].x)*scale*(pt[po[m-1]].x-pt[po[0]].x)*scale+\
- (pt[po[m-1]].y-pt[po[0]].y)*scale*(pt[po[m-1]].y-pt[po[0]].y)*scale);
- fprintf(f,"(polygon end, distance %.2f)\n",dm);
- return dm;
+ //double scale=1.0/dpi;
+ double dm = 0;
+ fprintf (f, "G0 X%f Y%f (start point)\n", pt[po[0]].x * scale,
+ pt[po[0]].y * scale);
+ fprintf (f, "G1 Z#101\n");
+ for (i = 1; i < m; i++)
+ {
+ fprintf (f, "G1 X%f Y%f\n", pt[po[i]].x * scale, pt[po[i]].y * scale);
+ dm +=
+ sqrt ((pt[po[i]].x - pt[po[i - 1]].x) * scale * (pt[po[i]].x -
+ pt[po[i - 1]].x) *
+ scale + (pt[po[i]].y - pt[po[i - 1]].y) * scale * (pt[po[i]].y -
+ pt[po
+ [i -
+ 1]].y) *
+ scale);
+ }
+ fprintf (f, "G1 X%f Y%f\n", pt[po[0]].x * scale, pt[po[0]].y * scale);
+ fprintf (f, "G0 Z#100\n");
+ dm +=
+ sqrt ((pt[po[m - 1]].x - pt[po[0]].x) * scale * (pt[po[m - 1]].x -
+ pt[po[0]].x) * scale +
+ (pt[po[m - 1]].y - pt[po[0]].y) * scale * (pt[po[m - 1]].y -
+ pt[po[0]].y) * scale);
+ fprintf (f, "(polygon end, distance %.2f)\n", dm);
+ return dm;
}
#define TRY(x) if (x) goto try_error
/* return distance on success, -1 on error with errno set. */
-double process_path(path_t *plist, const potrace_param_t *param,const potrace_bitmap_t *bm,FILE *f,double scale) {
+double
+process_path (path_t * plist, const potrace_param_t * param,
+ const potrace_bitmap_t * bm, FILE * f, double scale)
+{
path_t *p;
double nn = 0, cn = 0;
- double dm=0;
- int n=0;
+ double dm = 0;
+ int n = 0;
/* call downstream function with each path */
- list_forall (p, plist) {
- TRY(calc_sums(p->priv));
- TRY(calc_lon(p->priv));
- TRY(bestpolygon(p->priv));
- TRY(adjust_vertices(p->priv));
- fprintf(f,"(polygon %d)\n",++n);
- dm+=plotpolygon(p->priv,f,scale);
+ list_forall (p, plist)
+ {
+ TRY (calc_sums (p->priv));
+ TRY (calc_lon (p->priv));
+ TRY (bestpolygon (p->priv));
+ TRY (adjust_vertices (p->priv));
+ fprintf (f, "(polygon %d)\n", ++n);
+ dm += plotpolygon (p->priv, f, scale);
/* No need to extract curves
TRY(smooth(&p->priv->curve, p->sign, param->alphamax));
if (param->opticurve) {
@@ -1238,9 +1469,9 @@ double process_path(path_t *plist, const potrace_param_t *param,const potrace_bi
}
privcurve_to_curve(p->priv->fcurve, &p->curve);*/
}
-// fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm);
+// fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm);
return dm;
- try_error:
+try_error:
return -1;
}
diff --git a/src/hid/gcode/trace.h b/src/hid/gcode/trace.h
index 4a9683c..2a07e61 100644
--- a/src/hid/gcode/trace.h
+++ b/src/hid/gcode/trace.h
@@ -9,6 +9,7 @@
#include "potracelib.h"
-double process_path(path_t *plist, const potrace_param_t *param,const potrace_bitmap_t *bm,FILE *f,double scale);
+double process_path (path_t * plist, const potrace_param_t * param,
+ const potrace_bitmap_t * bm, FILE * f, double scale);
#endif /* TRACE_H */
commit 47edc12beab88ea5a6d7608e5741131eb5c0e8d4
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
gcode_lists.h should depend on gcode sources, not png sources.
diff --git a/src/Makefile.am b/src/Makefile.am
index 371173a..a5441d6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,7 +12,8 @@ HIDLIST = @HIDLIST@
noinst_LIBRARIES = @HIDLIBS@
EXTRA_LIBRARIES = \
libgtk.a liblesstif.a libbatch.a \
- liblpr.a libgerber.a libbom.a libpng.a libps.a libnelma.a libgts.a
+ liblpr.a libgerber.a libbom.a libpng.a libps.a libnelma.a libgts.a \
+ libgcode.a
pcblib_DATA= \
default_font \
@@ -163,6 +164,7 @@ BUILT_SOURCES = \
hid/lesstif/lesstif_lists.h \
hid/batch/batch_lists.h \
hid/png/png_lists.h \
+ hid/gcode/gcode_lists.h \
hid/nelma/nelma_lists.h \
hid/ps/ps_lists.h \
parse_y.h \
@@ -206,6 +208,7 @@ EXTRA_DIST= \
$(srcdir)/hid/lesstif/hid.conf \
$(srcdir)/hid/lpr/hid.conf \
$(srcdir)/hid/png/hid.conf \
+ $(srcdir)/hid/gcode/gcode.conf \
$(srcdir)/hid/nelma/hid.conf \
$(srcdir)/hid/ps/hid.conf \
gpcb-menu.res \
@@ -413,6 +416,29 @@ hid/png/png_lists.h : ${LIBPNG_SRCS} Makefile
(for f in ${LIBPNG_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
mv $@.tmp $@
+libgcode_a_CPPFLAGS = -I./hid/gcode
+LIBGCODE_SRCS = \
+ dolists.h \
+ hid/hidint.h \
+ hid/gcode/gcode.c \
+ hid/gcode/gcode.h \
+ hid/gcode/decompose.c \
+ hid/gcode/decompose.h \
+ hid/gcode/trace.c \
+ hid/gcode/trace.h \
+ hid/gcode/curve.c \
+ hid/gcode/curve.h \
+ hid/gcode/auxiliary.h \
+ hid/gcode/bitmap.h \
+ hid/gcode/lists.h \
+ hid/gcode/potracelib.h
+libgcode_a_SOURCES = ${LIBGCODE_SRCS} hid/gcode/gcode_lists.h
+
+hid/gcode/gcode_lists.h : ${LIBGCODE_SRCS} Makefile
+ true > $@
+ (for f in ${LIBGCODE_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
+ mv $@.tmp $@
+
libnelma_a_CPPFLAGS = -I./hid/nelma
LIBNELMA_SRCS = \
dolists.h \
@@ -436,6 +462,7 @@ DISTCLEANFILES= pcbtest.sh gpcb-menu.h pcb-menu.h \
hid/gtk/gtk_lists.h \
hid/lesstif/lesstif_lists.h \
hid/png/png_lists.h \
+ hid/gcode/gcode_lists.h \
hid/nelma/nelma_lists.h \
hid/ps/ps_lists.h \
gts/gts_lists.h \
commit e402b491c199d1df9808e129461d585346a03c9e
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
Apply sf patch 2948711 from Alberto Maccioni which adds a g-code
exporter.
diff --git a/src/hid/gcode/auxiliary.h b/src/hid/gcode/auxiliary.h
new file mode 100644
index 0000000..7baab85
--- /dev/null
+++ b/src/hid/gcode/auxiliary.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* This header file collects some general-purpose macros (and static
+ inline functions) that are used in various places. */
+
+#ifndef AUXILIARY_H
+#define AUXILIARY_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* point arithmetic */
+
+#include "potracelib.h"
+
+struct point_s {
+ long x;
+ long y;
+};
+typedef struct point_s point_t;
+
+typedef potrace_dpoint_t dpoint_t;
+
+/* convert point_t to dpoint_t */
+static inline dpoint_t dpoint(point_t p) {
+ dpoint_t res;
+ res.x = p.x;
+ res.y = p.y;
+ return res;
+}
+
+/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
+static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
+ dpoint_t res;
+
+ res.x = a.x + lambda * (b.x - a.x);
+ res.y = a.y + lambda * (b.y - a.y);
+ return res;
+}
+
+/* ---------------------------------------------------------------------- */
+/* some useful macros. Note: the "mod" macro works correctly for
+ negative a. Also note that the test for a>=n, while redundant,
+ speeds up the mod function by 70% in the average case (significant
+ since the program spends about 16% of its time here - or 40%
+ without the test). The "floordiv" macro returns the largest integer
+ <= a/n, and again this works correctly for negative a, as long as
+ a,n are integers and n>0. */
+
+/* integer arithmetic */
+
+static inline int mod(int a, int n) {
+ return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
+}
+
+static inline int floordiv(int a, int n) {
+ return a>=0 ? a/n : -1-(-1-a)/n;
+}
+
+/* Note: the following work for integers and other numeric types. */
+#undef sign
+#undef abs
+#undef min
+#undef max
+#undef sq
+#undef cu
+#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0)
+#define abs(a) ((a)>0 ? (a) : -(a))
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#define sq(a) ((a)*(a))
+#define cu(a) ((a)*(a)*(a))
+
+#endif /* AUXILIARY_H */
diff --git a/src/hid/gcode/bitmap.h b/src/hid/gcode/bitmap.h
new file mode 100644
index 0000000..2a172b1
--- /dev/null
+++ b/src/hid/gcode/bitmap.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+/* The bitmap type is defined in potracelib.h */
+#include "potracelib.h"
+
+/* The present file defines some convenient macros and static inline
+ functions for accessing bitmaps. Since they only produce inline
+ code, they can be conveniently shared by the library and frontends,
+ if desired */
+
+/* ---------------------------------------------------------------------- */
+/* some measurements */
+
+#define BM_WORDSIZE ((int)sizeof(potrace_word))
+#define BM_WORDBITS (8*BM_WORDSIZE)
+#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
+#define BM_ALLBITS (~(potrace_word)0)
+
+/* macros for accessing pixel at index (x,y). U* macros omit the
+ bounds check. */
+
+#define bm_scanline(bm, y) ((bm)->map + (y)*(bm)->dy)
+#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
+#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
+#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
+#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
+#define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0)
+#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
+#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
+#define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x))
+#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
+#define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0)
+#define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0)
+#define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0)
+#define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0)
+#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
+
+/* free the given bitmap. Leaves errno untouched. */
+static inline void bm_free(potrace_bitmap_t *bm) {
+ if (bm) {
+ free(bm->map);
+ }
+ free(bm);
+}
+
+/* return new un-initialized bitmap. NULL with errno on error */
+static inline potrace_bitmap_t *bm_new(int w, int h) {
+ potrace_bitmap_t *bm;
+ int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
+
+ bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
+ if (!bm) {
+ return NULL;
+ }
+ bm->w = w;
+ bm->h = h;
+ bm->dy = dy;
+ bm->map = (potrace_word *) malloc(dy * h * BM_WORDSIZE);
+ if (!bm->map) {
+ free(bm);
+ return NULL;
+ }
+ return bm;
+}
+
+/* clear the given bitmap. Set all bits to c. */
+static inline void bm_clear(potrace_bitmap_t *bm, int c) {
+ memset(bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE);
+}
+
+/* duplicate the given bitmap. Return NULL on error with errno set. */
+static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
+ potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
+ if (!bm1) {
+ return NULL;
+ }
+ memcpy(bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE);
+ return bm1;
+}
+
+/* invert the given bitmap. */
+static inline void bm_invert(potrace_bitmap_t *bm) {
+ int i;
+ for (i = 0; i < bm->dy * bm->h; i++) {
+ bm->map[i] ^= BM_ALLBITS;
+ }
+}
+
+#endif /* BITMAP_H */
diff --git a/src/hid/gcode/curve.c b/src/hid/gcode/curve.c
new file mode 100644
index 0000000..0dc1005
--- /dev/null
+++ b/src/hid/gcode/curve.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: curve.c 147 2007-04-09 00:44:09Z selinger $ */
+/* private part of the path and curve data structures */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "lists.h"
+#include "curve.h"
+
+#define SAFE_MALLOC(var, n, typ) \
+ if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+
+/* ---------------------------------------------------------------------- */
+/* allocate and free path objects */
+
+path_t *path_new(void) {
+ path_t *p = NULL;
+ privpath_t *priv = NULL;
+
+ SAFE_MALLOC(p, 1, path_t);
+ memset(p, 0, sizeof(path_t));
+ SAFE_MALLOC(priv, 1, privpath_t);
+ memset(priv, 0, sizeof(privpath_t));
+ p->priv = priv;
+ return p;
+
+ malloc_error:
+ free(p);
+ free(priv);
+ return NULL;
+}
+
+/* free the members of the given curve structure. Leave errno unchanged. */
+static void privcurve_free_members(privcurve_t *curve) {
+ free(curve->tag);
+ free(curve->c);
+ free(curve->vertex);
+ free(curve->alpha);
+ free(curve->alpha0);
+ free(curve->beta);
+}
+
+/* free a path. Leave errno untouched. */
+void path_free(path_t *p) {
+ if (p) {
+ if (p->priv) {
+ free(p->priv->pt);
+ free(p->priv->lon);
+ free(p->priv->sums);
+ free(p->priv->po);
+ privcurve_free_members(&p->priv->curve);
+ privcurve_free_members(&p->priv->ocurve);
+ }
+ free(p->priv);
+ /* do not free p->fcurve ! */
+ }
+ free(p);
+}
+
+/* free a pathlist, leaving errno untouched. */
+void pathlist_free(path_t *plist) {
+ path_t *p;
+
+ list_forall_unlink(p, plist) {
+ path_free(p);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* initialize and finalize curve structures */
+
+typedef dpoint_t dpoint3_t[3];
+
+/* initialize the members of the given curve structure to size m.
+ Return 0 on success, 1 on error with errno set. */
+int privcurve_init(privcurve_t *curve, int n) {
+ memset(curve, 0, sizeof(privcurve_t));
+ curve->n = n;
+ SAFE_MALLOC(curve->tag, n, int);
+ SAFE_MALLOC(curve->c, n, dpoint3_t);
+ SAFE_MALLOC(curve->vertex, n, dpoint_t);
+ SAFE_MALLOC(curve->alpha, n, double);
+ SAFE_MALLOC(curve->alpha0, n, double);
+ SAFE_MALLOC(curve->beta, n, double);
+ return 0;
+
+ malloc_error:
+ free(curve->tag);
+ free(curve->c);
+ free(curve->vertex);
+ free(curve->alpha);
+ free(curve->alpha0);
+ free(curve->beta);
+ return 1;
+}
+
+/* copy private to public curve structure */
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) {
+ c->n = pc->n;
+ c->tag = pc->tag;
+ c->c = pc->c;
+}
+
diff --git a/src/hid/gcode/curve.h b/src/hid/gcode/curve.h
new file mode 100644
index 0000000..45c0790
--- /dev/null
+++ b/src/hid/gcode/curve.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef CURVE_H
+#define CURVE_H
+
+#include "auxiliary.h"
+
+/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
+ .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
+ defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve:
+ .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and
+ c[2]..c[1] = alpha*(c[2]..vertex).
+ Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
+*/
+
+struct privcurve_s {
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
+ dpoint_t (*c)[3]; /* c[n][i]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
+ /* the remainder of this structure is special to privcurve, and is
+ used in EPS debug output and special EPS "short coding". These
+ fields are valid only if "alphacurve" is set. */
+ int alphacurve; /* have the following fields been initialized? */
+ dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
+ double *alpha; /* only for POTRACE_CURVETO */
+ double *alpha0; /* "uncropped" alpha parameter - for debug output only */
+ double *beta;
+};
+typedef struct privcurve_s privcurve_t;
+
+struct sums_s {
+ double x;
+ double y;
+ double x2;
+ double xy;
+ double y2;
+};
+typedef struct sums_s sums_t;
+
+/* the path structure is filled in with information about a given path
+ as it is accumulated and passed through the different stages of the
+ Potrace algorithm. Backends only need to read the fcurve and fm
+ fields of this data structure, but debugging backends may read
+ other fields. */
+struct potrace_privpath_s {
+ int len;
+ point_t *pt; /* pt[len]: path as extracted from bitmap */
+ int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
+
+ int x0, y0; /* origin for sums */
+ sums_t *sums; /* sums[len+1]: cache for fast summing */
+
+ int m; /* length of optimal polygon */
+ int *po; /* po[m]: optimal polygon */
+
+ privcurve_t curve; /* curve[m]: array of curve elements */
+ privcurve_t ocurve; /* ocurve[om]: array of curve elements */
+ privcurve_t *fcurve; /* final curve: this points to either curve or
+ ocurve. Do not free this separately. */
+};
+typedef struct potrace_privpath_s potrace_privpath_t;
+
+/* shorter names */
+typedef potrace_privpath_t privpath_t;
+typedef potrace_path_t path_t;
+
+path_t *path_new(void);
+void path_free(path_t *p);
+void pathlist_free(path_t *plist);
+int privcurve_init(privcurve_t *curve, int n);
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c);
+
+#endif /* CURVE_H */
+
diff --git a/src/hid/gcode/decompose.c b/src/hid/gcode/decompose.c
new file mode 100644
index 0000000..abc5e0a
--- /dev/null
+++ b/src/hid/gcode/decompose.c
@@ -0,0 +1,508 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: decompose.c 146 2007-04-09 00:43:46Z selinger $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "bitmap.h"
+#include "decompose.h"
+//#include "progress.h"
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary bitmap manipulations */
+
+/* set the excess padding to 0 */
+static void bm_clearexcess(potrace_bitmap_t *bm) {
+ potrace_word mask;
+ int y;
+
+ if (bm->w % BM_WORDBITS != 0) {
+ mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
+ for (y=0; y<bm->h; y++) {
+ *bm_index(bm, bm->w, y) &= mask;
+ }
+ }
+}
+
+struct bbox_s {
+ int x0, x1, y0, y1; /* bounding box */
+};
+typedef struct bbox_s bbox_t;
+
+/* clear the bm, assuming the bounding box is set correctly (faster
+ than clearing the whole bitmap) */
+static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
+ int imin = (bbox->x0 / BM_WORDBITS);
+ int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
+ int i, y;
+
+ for (y=bbox->y0; y<bbox->y1; y++) {
+ for (i=imin; i<imax; i++) {
+ bm_scanline(bm, y)[i] = 0;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
+static inline int detrand(int x, int y) {
+ unsigned int z;
+ static const unsigned char t[256] = {
+ /* non-linear sequence: constant term of inverse in GF(8),
+ mod x^8+x^4+x^3+x+1 */
+ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
+ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ };
+
+ /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
+ 5-bit sequence */
+ z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
+ z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
+ return z & 1;
+}
+
+/* return the "majority" value of bitmap bm at intersection (x,y). We
+ assume that the bitmap is balanced at "radius" 1. */
+static int majority(potrace_bitmap_t *bm, int x, int y) {
+ int i, a, ct;
+
+ for (i=2; i<5; i++) { /* check at "radius" i */
+ ct = 0;
+ for (a=-i+1; a<=i-1; a++) {
+ ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
+ ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
+ ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
+ ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
+ }
+ if (ct>0) {
+ return 1;
+ } else if (ct<0) {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* decompose image into paths */
+
+/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
+ must be a multiple of BM_WORDBITS. */
+static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
+ int xhi = x & -BM_WORDBITS;
+ int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */
+ int i;
+
+ if (xhi<xa) {
+ for (i = xhi; i < xa; i+=BM_WORDBITS) {
+ *bm_index(bm, i, y) ^= BM_ALLBITS;
+ }
+ } else {
+ for (i = xa; i < xhi; i+=BM_WORDBITS) {
+ *bm_index(bm, i, y) ^= BM_ALLBITS;
+ }
+ }
+ /* note: the following "if" is needed because x86 treats a<<b as
+ a<<(b&31). I spent hours looking for this bug. */
+ if (xlo) {
+ *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
+ }
+}
+
+/* a path is represented as an array of points, which are thought to
+ lie on the corners of pixels (not on their centers). The path point
+ (x,y) is the lower left corner of the pixel (x,y). Paths are
+ represented by the len/pt components of a path_t object (which
+ also stores other information about the path) */
+
+/* xor the given pixmap with the interior of the given path. Note: the
+ path must be within the dimensions of the pixmap. */
+static void xor_path(potrace_bitmap_t *bm, path_t *p) {
+ int xa, x, y, k, y1;
+
+ if (p->priv->len <= 0) { /* a path of length 0 is silly, but legal */
+ return;
+ }
+
+ y1 = p->priv->pt[p->priv->len-1].y;
+
+ xa = p->priv->pt[0].x & -BM_WORDBITS;
+ for (k=0; k<p->priv->len; k++) {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
+
+ if (y != y1) {
+ /* efficiently invert the rectangle [x,xa] x [y,y1] */
+ xor_to_ref(bm, x, min(y,y1), xa);
+ y1 = y;
+ }
+ }
+}
+
+/* Find the bounding box of a given path. Path is assumed to be of
+ non-zero length. */
+static void setbbox_path(bbox_t *bbox, path_t *p) {
+ int x, y;
+ int k;
+
+ bbox->y0 = INT_MAX;
+ bbox->y1 = 0;
+ bbox->x0 = INT_MAX;
+ bbox->x1 = 0;
+
+ for (k=0; k<p->priv->len; k++) {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
+
+ if (x < bbox->x0) {
+ bbox->x0 = x;
+ }
+ if (x > bbox->x1) {
+ bbox->x1 = x;
+ }
+ if (y < bbox->y0) {
+ bbox->y0 = y;
+ }
+ if (y > bbox->y1) {
+ bbox->y1 = y;
+ }
+ }
+}
+
+/* compute a path in the given pixmap, separating black from white.
+ Start path at the point (x0,x1), which must be an upper left corner
+ of the path. Also compute the area enclosed by the path. Return a
+ new path_t object, or NULL on error (note that a legitimate path
+ cannot have length 0). Sign is required for correct interpretation
+ of turnpolicies. */
+static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
+ int x, y, dirx, diry, len, size, area;
+ int c, d, tmp;
+ point_t *pt, *pt1;
+ path_t *p = NULL;
+
+ x = x0;
+ y = y0;
+ dirx = 0;
+ diry = -1;
+
+ len = size = 0;
+ pt = NULL;
+ area = 0;
+
+ while (1) {
+ /* add point to path */
+ if (len>=size) {
+ size += 100;
+ size = (int)(1.3 * size);
+ pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
+ if (!pt1) {
+ goto error;
+ }
+ pt = pt1;
+ }
+ pt[len].x = x;
+ pt[len].y = y;
+ len++;
+
+ /* move to next point */
+ x += dirx;
+ y += diry;
+ area += x*diry;
+
+ /* path complete? */
+ if (x==x0 && y==y0) {
+ break;
+ }
+
+ /* determine next direction */
+ c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
+ d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
+
+ if (c && !d) { /* ambiguous turn */
+ if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
+ || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
+ || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
+ || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
+ tmp = dirx; /* right turn */
+ dirx = diry;
+ diry = -tmp;
+ } else {
+ tmp = dirx; /* left turn */
+ dirx = -diry;
+ diry = tmp;
+ }
+ } else if (c) { /* right turn */
+ tmp = dirx;
+ dirx = diry;
+ diry = -tmp;
+ } else if (!d) { /* left turn */
+ tmp = dirx;
+ dirx = -diry;
+ diry = tmp;
+ }
+ } /* while this path */
+
+ /* allocate new path object */
+ p = path_new();
+ if (!p) {
+ goto error;
+ }
+
+ p->priv->pt = pt;
+ p->priv->len = len;
+ p->area = area;
+ p->sign = sign;
+
+ return p;
+
+ error:
+ free(pt);
+ return NULL;
+}
+
+/* Give a tree structure to the given path list, based on "insideness"
+ testing. I.e., path A is considered "below" path B if it is inside
+ path B. The input pathlist is assumed to be ordered so that "outer"
+ paths occur before "inner" paths. The tree structure is stored in
+ the "childlist" and "sibling" components of the path_t
+ structure. The linked list structure is also changed so that
+ negative path components are listed immediately after their
+ positive parent. Note: some backends may ignore the tree
+ structure, others may use it e.g. to group path components. We
+ assume that in the input, point 0 of each path is an "upper left"
+ corner of the path, as returned by bm_to_pathlist. This makes it
+ easy to find an "interior" point. The bm argument should be a
+ bitmap of the correct size (large enough to hold all the paths),
+ and will be used as scratch space. Return 0 on success or -1 on
+ error with errno set. */
+
+static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
+ path_t *p, *p1;
+ path_t *heap, *heap1;
+ path_t *cur;
+ path_t *head;
+ path_t **hook, **hook_in, **hook_out; /* for fast appending to linked list */
+ bbox_t bbox;
+
+ bm_clear(bm, 0);
+
+ /* save original "next" pointers */
+ list_forall(p, plist) {
+ p->sibling = p->next;
+ p->childlist = NULL;
+ }
+
+ heap = plist;
+
+ /* the heap holds a list of lists of paths. Use "childlist" field
+ for outer list, "next" field for inner list. Each of the sublists
+ is to be turned into a tree. This code is messy, but it is
+ actually fast. Each path is rendered exactly once. We use the
+ heap to get a tail recursive algorithm: the heap holds a list of
+ pathlists which still need to be transformed. */
+
+ while (heap) {
+ /* unlink first sublist */
+ cur = heap;
+ heap = heap->childlist;
+ cur->childlist = NULL;
+
+ /* unlink first path */
+ head = cur;
+ cur = cur->next;
+ head->next = NULL;
+
+ /* render path */
+ xor_path(bm, head);
+ setbbox_path(&bbox, head);
+
+ /* now do insideness test for each element of cur; append it to
+ head->childlist if it's inside head, else append it to
+ head->next. */
+ hook_in=&head->childlist;
+ hook_out=&head->next;
+ list_forall_unlink(p, cur) {
+ if (p->priv->pt[0].y <= bbox.y0) {
+ list_insert_beforehook(p, hook_out);
+ /* append the remainder of the list to hook_out */
+ *hook_out = cur;
+ break;
+ }
+ if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
+ list_insert_beforehook(p, hook_in);
+ } else {
+ list_insert_beforehook(p, hook_out);
+ }
+ }
+
+ /* clear bm */
+ clear_bm_with_bbox(bm, &bbox);
+
+ /* now schedule head->childlist and head->next for further
+ processing */
+ if (head->next) {
+ head->next->childlist = heap;
+ heap = head->next;
+ }
+ if (head->childlist) {
+ head->childlist->childlist = heap;
+ heap = head->childlist;
+ }
+ }
+
+ /* copy sibling structure from "next" to "sibling" component */
+ p = plist;
+ while (p) {
+ p1 = p->sibling;
+ p->sibling = p->next;
+ p = p1;
+ }
+
+ /* reconstruct a new linked list ("next") structure from tree
+ ("childlist", "sibling") structure. This code is slightly messy,
+ because we use a heap to make it tail recursive: the heap
+ contains a list of childlists which still need to be
+ processed. */
+ heap = plist;
+ if (heap) {
+ heap->next = NULL; /* heap is a linked list of childlists */
+ }
+ plist = NULL;
+ hook = &plist;
+ while (heap) {
+ heap1 = heap->next;
+ for (p=heap; p; p=p->sibling) {
+ /* p is a positive path */
+ /* append to linked list */
+ list_insert_beforehook(p, hook);
+
+ /* go through its children */
+ for (p1=p->childlist; p1; p1=p1->sibling) {
+ /* append to linked list */
+ list_insert_beforehook(p1, hook);
+ /* append its childlist to heap, if non-empty */
+ if (p1->childlist) {
+ list_append(path_t, heap1, p1->childlist);
+ }
+ }
+ }
+ heap = heap1;
+ }
+
+ return;
+}
+
+/* find the next set pixel in a row <= y. Pixels are searched first
+ left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y'
+ or y=y' and x<x'. If found, return 0 and store pixel in
+ (*xp,*yp). Else return 1. Note that this function assumes that
+ excess bytes have been cleared with bm_clearexcess. */
+static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
+ int x;
+ int y;
+
+ for (y=*yp; y>=0; y--) {
+ for (x=0; x<bm->w; x+=BM_WORDBITS) {
+ if (*bm_index(bm, x, y)) {
+ while (!BM_GET(bm, x, y)) {
+ x++;
+ }
+ /* found */
+ *xp = x;
+ *yp = y;
+ return 0;
+ }
+ }
+ }
+ /* not found */
+ return 1;
+}
+
+/* Decompose the given bitmap into paths. Returns a linked list of
+ path_t objects with the fields len, pt, area, sign filled
+ in. Returns 0 on success with plistp set, or -1 on error with errno
+ set. */
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param) {
+ int x;
+ int y;
+ path_t *p;
+ path_t *plist = NULL; /* linked list of path objects */
+ path_t **hook = &plist; /* used to speed up appending to linked list */
+ potrace_bitmap_t *bm1 = NULL;
+ int sign;
+
+ bm1 = bm_dup(bm);
+ if (!bm1) {
+ goto error;
+ }
+
+ /* be sure the byte padding on the right is set to 0, as the fast
+ pixel search below relies on it */
+ bm_clearexcess(bm1);
+
+ /* iterate through components */
+ y = bm1->h - 1;
+ while (findnext(bm1, &x, &y) == 0) {
+ /* calculate the sign by looking at the original */
+ sign = BM_GET(bm, x, y) ? '+' : '-';
+
+ /* calculate the path */
+ p = findpath(bm1, x, y+1, sign, param->turnpolicy);
+ if (p==NULL) {
+ goto error;
+ }
+
+ /* update buffered image */
+ xor_path(bm1, p);
+
+ /* if it's a turd, eliminate it, else append it to the list */
+ if (p->area <= param->turdsize) {
+ path_free(p);
+ } else {
+ list_insert_beforehook(p, hook);
+ }
+
+ if (bm1->h > 0) { /* to be sure */
+ //progress_update(1-y/(double)bm1->h, progress);
+ }
+ }
+
+ pathlist_to_tree(plist, bm1);
+ bm_free(bm1);
+ *plistp = plist;
+
+// progress_update(1.0, progress);
+
+ return 0;
+
+ error:
+ bm_free(bm1);
+ list_forall_unlink(p, plist) {
+ path_free(p);
+ }
+ return -1;
+}
diff --git a/src/hid/gcode/decompose.h b/src/hid/gcode/decompose.h
new file mode 100644
index 0000000..d5be99c
--- /dev/null
+++ b/src/hid/gcode/decompose.h
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: decompose.h 147 2007-04-09 00:44:09Z selinger $ */
+
+#ifndef DECOMPOSE_H
+#define DECOMPOSE_H
+
+#include "potracelib.h"
+//#include "progress.h"
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param);
+
+#endif /* DECOMPOSE_H */
+
diff --git a/src/hid/gcode/gcode.c b/src/hid/gcode/gcode.c
new file mode 100644
index 0000000..5792d0c
--- /dev/null
+++ b/src/hid/gcode/gcode.c
@@ -0,0 +1,988 @@
+/*
+ * COPYRIGHT
+ *
+ * PCB, interactive printed circuit board design
+ *
+ * GCODE export HID
+ * Copyright (C) 2010 Alberto Maccioni
+ * this code is based on the NELMA export HID, the PNG export HID,
+ * and potrace, a tracing program by Peter Selinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * This HID exports a PCB layout into:
+ * one layer mask file (PNG format) per copper layer,
+ * one G-CODE CNC drill file.
+ * one G-CODE CNC file per copper layer.
+ * The latter is used by a CNC milling machine to mill the pcb.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include "global.h"
+#include "data.h"
+#include "misc.h"
+#include "rats.h"
+
+#include "hid.h"
+#include "../hidint.h"
+#include <gd.h>
+#include "hid/common/draw_helpers.h"
+#include "gcode.h"
+#include "bitmap.h"
+#include "curve.h"
+#include "potracelib.h"
+#include "trace.h"
+#include "decompose.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+RCSID("$Id: gcode.c, v 0.1 2010/2/8 14:00:00 Alberto Maccioni Exp $");
+
+#define CRASH fprintf(stderr, "HID error: pcb called unimplemented GCODE function %s.\n", __FUNCTION__); abort()
+#define pcb_unit 100000.0 //pcb internal units per inch
+struct color_struct {
+ /* the descriptor used by the gd library */
+ int c;
+
+ /* so I can figure out what rgb value c refers to */
+ unsigned int r, g, b;
+};
+
+struct hid_gc_struct {
+ HID *me_pointer;
+ EndCapStyle cap;
+ int width;
+ unsigned char r, g, b;
+ int erase;
+ int faded;
+ struct color_struct *color;
+ gdImagePtr brush;
+};
+
+static struct color_struct *black = NULL, *white = NULL;
+static int linewidth = -1;
+static int lastgroup = -1;
+static gdImagePtr lastbrush = (void *) -1;
+static int lastcap = -1;
+static int lastcolor = -1;
+
+/* gd image and file for PNG export */
+static gdImagePtr gcode_im = NULL;
+static FILE *gcode_f = NULL,*gcode_f2 = NULL;
+
+static int is_mask;
+static int is_drill;
+static int is_solder;
+
+/*
+ * Which groups of layers to export into PNG layer masks. 1 means export, 0
+ * means do not export.
+ */
+static int gcode_export_group[MAX_LAYER];
+
+/* Group that is currently exported. */
+static int gcode_cur_group;
+
+/* Filename prefix that will be used when saving files. */
+static char *gcode_basename = NULL;
+
+/* Horizontal DPI (grid points per inch) */
+static int gcode_dpi = -1;
+
+static double gcode_cutdepth = 0; //milling depth (inch)
+static double gcode_drilldepth = 0; //drilling depth (inch)
+static double gcode_safeZ = 100; //safe Z (inch)
+static double gcode_toolradius = 0; //tool radius(inch)
+static int save_drill=0;
+static int n_drill=0;
+static int nmax_drill=0;
+struct drill_struct {
+ double x;
+ double y;
+};
+
+static struct drill_struct *drill=0;
+
+static const char *units[] = {
+ "mm",
+ "mil",
+ "um",
+ "inch",
+ NULL
+};
+
+HID_Attribute gcode_attribute_list[] = {
+ /* other HIDs expect this to be first. */
+ {"basename", "File name prefix",
+ HID_String, 0, 0, {0, 0, 0}, 0, 0},
+#define HA_basename 0
+
+ {"dpi", "Resolution of intermediate image (pixels/inch).",
+ HID_Integer, 0, 2000, {600, 0, 0}, 0, 0},
+#define HA_dpi 1
+
+ {"mill depth", "Milling depth.",
+ HID_Real, -1000, 1000, {0, 0, -0.05}, 0, 0},
+#define HA_cutdepth 2
+
+ {"safe Z", "Safe Z for traverse move.",
+ HID_Real, -1000, 10000, {0, 0, 2}, 0, 0},
+#define HA_safeZ 3
+
+ {"tool radius", "Milling tool radius compensation.",
+ HID_Real, 0, 10000, {0, 0, 0.1}, 0, 0},
+#define HA_toolradius 4
+
+ {"drill depth", "Drilling depth.",
+ HID_Real, -10000, 10000, {0, 0, -2}, 0, 0},
+#define HA_drilldepth 5
+
+ {"measurement unit", "Measurement unit",
+ HID_Enum, 0, 0, {0, 0, 0}, units, 0},
+#define HA_unit 6
+
+};
+
+#define NUM_OPTIONS (sizeof(gcode_attribute_list)/sizeof(gcode_attribute_list[0]))
+
+REGISTER_ATTRIBUTES(gcode_attribute_list)
+ static HID_Attr_Val gcode_values[NUM_OPTIONS];
+
+/* *** Utility funcions **************************************************** */
+
+/* convert from default PCB units (1/100 mil) to gcode units */
+ static int pcb_to_gcode(int pcb)
+{
+ int gcode;
+
+ gcode = (pcb * gcode_dpi) / pcb_unit; //100000;
+
+ return gcode;
+}
+
+static char *
+gcode_get_png_name(const char *basename, const char *suffix)
+{
+ char *buf;
+ int len;
+
+ len = strlen(basename) + strlen(suffix) + 6;
+ buf = malloc(sizeof(*buf) * len);
+
+ sprintf(buf, "%s.%s.png", basename, suffix);
+
+ return buf;
+}
+
+//Sorts drills in order of distance from the origin
+struct drill_struct* sort_drill(struct drill_struct *drill,int n_drill){
+ int i,j,imin;
+ double dmin,d;
+ struct drill_struct p={0,0};
+ struct drill_struct* temp=malloc(n_drill*sizeof(struct drill_struct));
+ for(j=0;j<n_drill;j++){
+ dmin=1e20;
+ for(i=0;i<n_drill-j;i++){
+ d=(drill[i].x-p.x)*(drill[i].x-p.x)+(drill[i].y-p.y)*(drill[i].y-p.y);
+ if(d<dmin){
+ imin=i;
+ dmin=d;
+ }
+ }
+ //printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y);
+ temp[j]=drill[imin];
+ drill[imin]=drill[n_drill-j-1];
+ p=temp[j];
+ }
+ free(drill);
+ return temp;
+}
+
+/* *** Main export callback ************************************************ */
+
+extern void hid_parse_command_line(int *argc, char ***argv);
+
+static void
+gcode_parse_arguments(int *argc, char ***argv)
+{
+ hid_register_attributes(gcode_attribute_list,
+ sizeof(gcode_attribute_list) /
+ sizeof(gcode_attribute_list[0]));
+ hid_parse_command_line(argc, argv);
+}
+
+static HID_Attribute *
+gcode_get_export_options(int *n)
+{
+ static char *last_made_filename = 0;
+
+ if (PCB) {
+ derive_default_filename(PCB->Filename,
+ &gcode_attribute_list[HA_basename],
+ ".gcode",
+ &last_made_filename);
+ }
+ if (n) {
+ *n = NUM_OPTIONS;
+ }
+ return gcode_attribute_list;
+}
+
+/* Populates gcode_export_group array */
+void
+gcode_choose_groups()
+{
+ int n, m;
+ LayerType *layer;
+
+ /* Set entire array to 0 (don't export any layer groups by default */
+ memset(gcode_export_group, 0, sizeof(gcode_export_group));
+
+ for (n = 0; n < max_layer; n++) {
+ layer = &PCB->Data->Layer[n];
+
+ if (layer->LineN || layer->TextN || layer->ArcN ||
+ layer->PolygonN) {
+ /* layer isn't empty */
+
+ /*
+ * is this check necessary? It seems that special
+ * layers have negative indexes?
+ */
+
+ if (SL_TYPE(n) == 0) {
+ /* layer is a copper layer */
+ m = GetLayerGroupNumberByNumber(n);
+
+ /* the export layer */
+ gcode_export_group[m] = 1;
+ }
+ }
+ }
+}
+
+static void
+gcode_alloc_colors()
+{
+ /*
+ * Allocate white and black -- the first color allocated becomes the
+ * background color
+ */
+
+ white = (struct color_struct *) malloc(sizeof(*white));
+ white->r = white->g = white->b = 255;
+ white->c = gdImageColorAllocate(gcode_im, white->r, white->g, white->b);
+
+ black = (struct color_struct *) malloc(sizeof(*black));
+ black->r = black->g = black->b = 0;
+ black->c = gdImageColorAllocate(gcode_im, black->r, black->g, black->b);
+}
+
+static void
+gcode_start_png(const char *basename, const char *suffix)
+{
+ int h, w;
+ char *buf;
+
+ buf = gcode_get_png_name(basename, suffix);
+
+ h = pcb_to_gcode(PCB->MaxHeight);
+ w = pcb_to_gcode(PCB->MaxWidth);
+
+ /* Nelma only works with true color images */
+ gcode_im = gdImageCreate(w, h);
+ gcode_f = fopen(buf, "wb");
+
+ gcode_alloc_colors();
+
+ free(buf);
+}
+
+static void
+gcode_finish_png()
+{
+#ifdef HAVE_GDIMAGEPNG
+ gdImagePng(gcode_im, gcode_f);
+#else
+ Message("GCODE: PNG not supported by gd. Can't write layer mask.\n");
+#endif
+ gdImageDestroy(gcode_im);
+ fclose(gcode_f);
+
+ free(white);
+ free(black);
+
+ gcode_im = NULL;
+ gcode_f = NULL;
+}
+
+void
+gcode_start_png_export()
+{
+ BoxType region;
+
+ region.X1 = 0;
+ region.Y1 = 0;
+ region.X2 = PCB->MaxWidth;
+ region.Y2 = PCB->MaxHeight;
+
+ linewidth = -1;
+ lastbrush = (void *) -1;
+ lastcap = -1;
+ lastgroup = -1;
+ lastcolor = -1;
+ lastgroup = -1;
+
+ hid_expose_callback(&gcode_hid, ®ion, 0);
+}
+
+static void
+gcode_do_export(HID_Attr_Val * options)
+{
+ int save_ons[MAX_LAYER + 2];
+ int i, idx;
+ time_t t;
+ double scale=0,d=0,Bx,By;
+ int r,c,v,p,metric;
+ char* filename;
+ path_t *plist = NULL;
+ potrace_bitmap_t *bm = NULL;
+ potrace_param_t param_default = {
+ 2, // turdsize
+ POTRACE_TURNPOLICY_MINORITY, // turnpolicy
+ 1.0, // alphamax
+ 1, // opticurve
+ 0.2, // opttolerance
+ {
+ NULL, // callback function
+ NULL, // callback data
+ 0.0, 1.0, // progress range
+ 0.0, // granularity
+ },
+ };
+
+ Bx=PCB->MaxWidth/pcb_unit;
+ By=PCB->MaxHeight/pcb_unit;
+ if (!options) {
+ gcode_get_export_options(0);
+ for (i = 0; i < NUM_OPTIONS; i++) {
+ gcode_values[i] = gcode_attribute_list[i].default_val;
+ }
+ options = gcode_values;
+ }
+ gcode_basename = options[HA_basename].str_value;
+ if (!gcode_basename) {
+ gcode_basename = "pcb-out";
+ }
+ gcode_dpi = options[HA_dpi].int_value;
+ if (gcode_dpi < 0) {
+ fprintf(stderr, "ERROR: dpi may not be < 0\n");
+ return;
+ }
+ switch(options[HA_unit].int_value){
+ case 0:
+ scale=1.0; //mm
+ metric=1;
+ break;
+ case 1:
+ scale=0.001; //mil
+ metric=0;
+ break;
+ case 2:
+ scale=0.001; //um
+ metric=1;
+ break;
+ default:
+ scale=1.0; //inch
+ metric=0;
+ }
+ gcode_cutdepth = options[HA_cutdepth].real_value*scale;
+ gcode_drilldepth = options[HA_drilldepth].real_value*scale;
+ gcode_safeZ = options[HA_safeZ].real_value*scale;
+ gcode_toolradius = options[HA_toolradius].real_value*scale*pcb_unit; //in PCB units (1/100 mil)
+ if(metric) gcode_toolradius*=1/25.4;
+ gcode_choose_groups();
+
+ for (i = 0; i < MAX_LAYER; i++) {
+ if (gcode_export_group[i]) {
+
+ gcode_cur_group = i;
+
+ /* magic */
+ idx = (i >= 0 && i < max_layer) ?
+ PCB->LayerGroups.Entries[i][0] : i;
+ printf("idx=%d %s\n",idx,layer_type_to_file_name(idx));
+ is_solder=(GetLayerGroupNumberByNumber(idx)==GetLayerGroupNumberByNumber(max_layer+SOLDER_LAYER))?1:0;
+ save_drill=is_solder; //save drills for one layer only
+ gcode_start_png(gcode_basename,layer_type_to_file_name(idx));
+ hid_save_and_show_layer_ons(save_ons);
+ gcode_start_png_export();
+ hid_restore_layer_ons(save_ons);
+
+//***************** gcode conversion ***************************
+// potrace uses a different kind of bitmap; for simplicity gcode_im is copied to this format
+ bm = bm_new(gdImageSX(gcode_im),gdImageSY(gcode_im));
+ filename=malloc(512);
+ plist = NULL;
+ if(is_solder){ //only for back layer
+ gdImagePtr temp_im=gdImageCreate(gdImageSX(gcode_im), gdImageSY(gcode_im));
+ gdImageCopy(temp_im,gcode_im,0,0,0,0,gdImageSX(gcode_im),gdImageSY(gcode_im));
+ for(r=0;r<gdImageSX(gcode_im);r++){
+ for(c=0;c<gdImageSY(gcode_im);c++){
+ gdImageSetPixel(gcode_im,r,c,gdImageGetPixel(temp_im,gdImageSX(gcode_im)-1-r,c));
+ }
+ }
+ gdImageDestroy(temp_im);
+ }
+ sprintf(filename,"%s.%s.cnc",gcode_basename,layer_type_to_file_name(idx));
+ for(r=0;r<gdImageSX(gcode_im);r++){
+ for(c=0;c<gdImageSY(gcode_im);c++){
+ v=gdImageGetPixel(gcode_im,r,gdImageSY(gcode_im)-1-c);
+ p=(gcode_im->red[v]||gcode_im->green[v]||gcode_im->blue[v])?0:0xFFFFFF;
+ BM_PUT(bm, r, c, p);
+ }
+ }
+ gcode_f2 = fopen (filename, "wb");
+ if (!gcode_f2)
+ {
+ perror (filename);
+ return;
+ }
+ fprintf(gcode_f2,"(Created by G-code exporter)\n");
+ t = time(NULL);
+ sprintf(filename,"%s", ctime(&t));
+ filename[strlen(filename)-1]=0;
+ fprintf(gcode_f2,"( %s )\n", filename);
+ fprintf(gcode_f2,"(%d dpi)\n",gcode_dpi);
+ fprintf(gcode_f2,"(Unit: %s)\n",metric?"mm":"inch");
+ if(metric) fprintf(gcode_f2,"(Board size: %.2fx%.2f mm)\n",Bx*25.4,By*25.4);
+ else fprintf(gcode_f2,"(Board size: %.2fx%.2f inches)\n",Bx,By);
+ fprintf(gcode_f2,"#100=%f (safe Z)\n",gcode_safeZ);
+ fprintf(gcode_f2,"#101=%f (cutting depth)\n",gcode_cutdepth);
+ fprintf(gcode_f2,"(---------------------------------)\n");
+ fprintf(gcode_f2,"G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",metric?21:20,metric?25:1);
+ fprintf(gcode_f2,"G0 Z#100\n");
+ //extract contour points from image
+ r = bm_to_pathlist(bm, &plist, ¶m_default);
+ if (r) {
+ fprintf(stderr, "ERROR: pathlist function failed\n");
+ return;
+ }
+ //generate best polygon and write vertices in g-code format
+ d=process_path(plist,¶m_default,bm,gcode_f2,metric?25.4/gcode_dpi:1.0/gcode_dpi);
+ if (d<0) {
+ fprintf(stderr, "ERROR: path process function failed\n");
+ return;
+ }
+ if(metric) fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",d,d*1/25.4);
+ else fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",25.4*d,d);
+ fprintf(gcode_f2,"M5 M9 M2\n");
+ pathlist_free(plist);
+ bm_free(bm);
+ fclose (gcode_f2);
+ if(save_drill){
+ d=0;
+ drill=sort_drill(drill,n_drill);
+ sprintf(filename,"%s.drill.cnc",gcode_basename);
+ gcode_f2 = fopen (filename, "wb");
+ if (!gcode_f2)
+ {
+ perror (filename);
+ return;
+ }
+ fprintf(gcode_f2,"(Created by G-code exporter)\n");
+ fprintf(gcode_f2,"(drill file: %d drills)\n",n_drill);
+ sprintf(filename,"%s", ctime(&t));
+ filename[strlen(filename)-1]=0;
+ fprintf(gcode_f2,"( %s )\n", filename);
+ fprintf(gcode_f2,"(Unit: %s)\n",metric?"mm":"inch");
+ if(metric) fprintf(gcode_f2,"(Board size: %.2fx%.2f mm)\n",Bx*25.4,By*25.4);
+ else fprintf(gcode_f2,"(Board size: %.2fx%.2f inches)\n",Bx,By);
+ fprintf(gcode_f2,"#100=%f (safe Z)\n",gcode_safeZ);
+ fprintf(gcode_f2,"#101=%f (drill depth)\n",gcode_drilldepth);
+ fprintf(gcode_f2,"(---------------------------------)\n");
+ fprintf(gcode_f2,"G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n",metric?21:20,metric?25:1);
+// fprintf(gcode_f2,"G0 Z#100\n");
+ for(r=0;r<n_drill;r++){
+// if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4);
+// else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y);
+ if(metric) fprintf(gcode_f2,"G81 X%f Y%f Z#101 R#100\n",drill[r].x*25.4,drill[r].y*25.4);
+ else fprintf(gcode_f2,"G81 X%f Y%f Z#101 R#100\n",drill[r].x,drill[r].y);
+// fprintf(gcode_f2,"G1 Z#101\n");
+// fprintf(gcode_f2,"G0 Z#100\n");
+ if(r>0) d+=sqrt((drill[r].x-drill[r-1].x)*(drill[r].x-drill[r-1].x)+\
+ (drill[r].y-drill[r-1].y)*(drill[r].y-drill[r-1].y));
+ }
+ fprintf(gcode_f2,"M5 M9 M2\n");
+ fprintf(gcode_f2,"(end, total distance %.2fmm = %.2fin)\n",25.4*d,d);
+ fclose (gcode_f2);
+ free(drill);
+ drill=NULL;
+ n_drill=nmax_drill=0;
+ }
+ free(filename);
+ system("unix2dos *.cnc");
+//******************* end gcode conversion ****************************
+ gcode_finish_png();
+ }
+ }
+}
+
+/* *** PNG export (slightly modified code from PNG export HID) ************* */
+
+static int
+gcode_set_layer(const char *name, int group)
+{
+ int idx = (group >= 0 && group < max_layer) ?
+ PCB->LayerGroups.Entries[group][0] : group;
+
+ if (name == 0) {
+ name = PCB->Data->Layer[idx].Name;
+ }
+ if (strcmp(name, "invisible") == 0) {
+ return 0;
+ }
+ is_drill = (SL_TYPE(idx) == SL_PDRILL || SL_TYPE(idx) == SL_UDRILL);
+ is_mask = (SL_TYPE(idx) == SL_MASK);
+
+ if (is_mask) {
+ /* Don't print masks */
+ return 0;
+ }
+ if (is_drill) {
+ /*
+ * Print 'holes', so that we can fill gaps in the copper
+ * layer
+ */
+ return 1;
+ }
+ if (group == gcode_cur_group) {
+ return 1;
+ }
+ return 0;
+}
+
+static hidGC
+gcode_make_gc(void)
+{
+ hidGC rv = (hidGC) malloc(sizeof(struct hid_gc_struct));
+ rv->me_pointer = &gcode_hid;
+ rv->cap = Trace_Cap;
+ rv->width = 1;
+ rv->color = (struct color_struct *) malloc(sizeof(*rv->color));
+ rv->color->r = rv->color->g = rv->color->b = 0;
+ rv->color->c = 0;
+ return rv;
+}
+
+static void
+gcode_destroy_gc(hidGC gc)
+{
+ free(gc);
+}
+
+static void
+gcode_use_mask(int use_it)
+{
+ /* does nothing */
+}
+
+static void
+gcode_set_color(hidGC gc, const char *name)
+{
+ if (gcode_im == NULL) {
+ return;
+ }
+ if (name == NULL) {
+ name = "#ff0000";
+ }
+ if (!strcmp(name, "drill")) {
+ gc->color = black;
+ gc->erase = 0;
+ return;
+ }
+ if (!strcmp(name, "erase")) {
+ /* FIXME -- should be background, not white */
+ gc->color = white;
+ gc->erase = 1;
+ return;
+ }
+ gc->color = black;
+ gc->erase = 0;
+ return;
+}
+
+static void
+gcode_set_line_cap(hidGC gc, EndCapStyle style)
+{
+ gc->cap = style;
+}
+
+static void
+gcode_set_line_width(hidGC gc, int width)
+{
+ gc->width = width;
+}
+
+static void
+gcode_set_draw_xor(hidGC gc, int xor)
+{
+ ;
+}
+
+static void
+gcode_set_draw_faded(hidGC gc, int faded)
+{
+ gc->faded = faded;
+}
+
+static void
+gcode_set_line_cap_angle(hidGC gc, int x1, int y1, int x2, int y2)
+{
+ CRASH;
+}
+
+static void
+use_gc(hidGC gc)
+{
+ int need_brush = 0;
+
+ if (gc->me_pointer != &gcode_hid) {
+ fprintf(stderr, "Fatal: GC from another HID passed to gcode HID\n");
+ abort();
+ }
+ if (linewidth != gc->width) {
+ /* Make sure the scaling doesn't erase lines completely */
+ /*
+ if (SCALE (gc->width) == 0 && gc->width > 0)
+ gdImageSetThickness (im, 1);
+ else
+ */
+ gdImageSetThickness(gcode_im, pcb_to_gcode(gc->width + 2*gcode_toolradius));
+ linewidth = gc->width;
+ need_brush = 1;
+ }
+ if (lastbrush != gc->brush || need_brush) {
+ static void *bcache = 0;
+ hidval bval;
+ char name[256];
+ char type;
+ int r;
+
+ switch (gc->cap) {
+ case Round_Cap:
+ case Trace_Cap:
+ type = 'C';
+ r = pcb_to_gcode(gc->width / 2 + gcode_toolradius);
+ break;
+ default:
+ case Square_Cap:
+ r = pcb_to_gcode(gc->width+gcode_toolradius*2);
+ type = 'S';
+ break;
+ }
+ sprintf(name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g,
+ gc->color->b, type, r);
+
+ if (hid_cache_color(0, name, &bval, &bcache)) {
+ gc->brush = bval.ptr;
+ } else {
+ int bg, fg;
+ if (type == 'C')
+ gc->brush = gdImageCreate(2 * r + 1, 2 * r + 1);
+ else
+ gc->brush = gdImageCreate(r + 1, r + 1);
+ bg = gdImageColorAllocate(gc->brush, 255, 255, 255);
+ fg =
+ gdImageColorAllocate(gc->brush, gc->color->r, gc->color->g,
+ gc->color->b);
+ gdImageColorTransparent(gc->brush, bg);
+
+ /*
+ * if we shrunk to a radius/box width of zero, then just use
+ * a single pixel to draw with.
+ */
+ if (r == 0)
+ gdImageFilledRectangle(gc->brush, 0, 0, 0, 0, fg);
+ else {
+ if (type == 'C')
+ gdImageFilledEllipse(gc->brush, r, r, 2 * r, 2 * r, fg);
+ else
+ gdImageFilledRectangle(gc->brush, 0, 0, r, r, fg);
+ }
+ bval.ptr = gc->brush;
+ hid_cache_color(1, name, &bval, &bcache);
+ }
+
+ gdImageSetBrush(gcode_im, gc->brush);
+ lastbrush = gc->brush;
+
+ }
+#define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded))
+ if (lastcolor != CBLEND(gc)) {
+ if (is_drill || is_mask) {
+#ifdef FIXME
+ fprintf(f, "%d gray\n", gc->erase ? 0 : 1);
+#endif
+ lastcolor = 0;
+ } else {
+ double r, g, b;
+ r = gc->r;
+ g = gc->g;
+ b = gc->b;
+ if (gc->faded) {
+ r = 0.8 * 255 + 0.2 * r;
+ g = 0.8 * 255 + 0.2 * g;
+ b = 0.8 * 255 + 0.2 * b;
+ }
+#ifdef FIXME
+ if (gc->r == gc->g && gc->g == gc->b)
+ fprintf(f, "%g gray\n", r / 255.0);
+ else
+ fprintf(f, "%g %g %g rgb\n", r / 255.0, g / 255.0, b / 255.0);
+#endif
+ lastcolor = CBLEND(gc);
+ }
+ }
+}
+
+static void
+gcode_draw_rect(hidGC gc, int x1, int y1, int x2, int y2)
+{
+ use_gc(gc);
+ gdImageRectangle(gcode_im,
+ pcb_to_gcode(x1-gcode_toolradius), pcb_to_gcode(y1-gcode_toolradius),
+ pcb_to_gcode(x2+gcode_toolradius), pcb_to_gcode(y2+gcode_toolradius), gc->color->c);
+// printf("Rect %d %d %d %d\n",x1,y1,x2,y2);
+}
+
+static void
+gcode_fill_rect(hidGC gc, int x1, int y1, int x2, int y2)
+{
+ use_gc(gc);
+ gdImageSetThickness(gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledRectangle(gcode_im,
+ pcb_to_gcode(x1-gcode_toolradius), pcb_to_gcode(y1-gcode_toolradius),
+ pcb_to_gcode(x2+gcode_toolradius), pcb_to_gcode(y2+gcode_toolradius), gc->color->c);
+// printf("FillRect %d %d %d %d\n",x1,y1,x2,y2);
+}
+
+static void
+gcode_draw_line(hidGC gc, int x1, int y1, int x2, int y2)
+{
+ if (x1 == x2 && y1 == y2) {
+ int w = gc->width / 2;
+ gcode_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w);
+ return;
+ }
+ use_gc(gc);
+
+ gdImageSetThickness(gcode_im, 0);
+ linewidth = 0;
+ gdImageLine(gcode_im, pcb_to_gcode(x1), pcb_to_gcode(y1),
+ pcb_to_gcode(x2), pcb_to_gcode(y2), gdBrushed);
+}
+
+static void
+gcode_draw_arc(hidGC gc, int cx, int cy, int width, int height,
+ int start_angle, int delta_angle)
+{
+ int sa, ea;
+
+ /*
+ * in gdImageArc, 0 degrees is to the right and +90 degrees is down
+ * in pcb, 0 degrees is to the left and +90 degrees is down
+ */
+ start_angle = 180 - start_angle;
+ delta_angle = -delta_angle;
+ if (delta_angle > 0) {
+ sa = start_angle;
+ ea = start_angle + delta_angle;
+ } else {
+ sa = start_angle + delta_angle;
+ ea = start_angle;
+ }
+
+ /*
+ * make sure we start between 0 and 360 otherwise gd does strange
+ * things
+ */
+ while (sa < 0) {
+ sa += 360;
+ ea += 360;
+ }
+ while (sa >= 360) {
+ sa -= 360;
+ ea -= 360;
+ }
+
+#if 0
+ printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
+ cx, cy, width, height, start_angle, delta_angle, sa, ea);
+ printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n",
+ im, SCALE_X(cx), SCALE_Y(cy),
+ SCALE(width), SCALE(height), sa, ea, gc->color->c);
+#endif
+ use_gc(gc);
+ gdImageSetThickness(gcode_im, 0);
+ linewidth = 0;
+ gdImageArc(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy),
+ pcb_to_gcode(2 * width + gcode_toolradius*2), pcb_to_gcode(2 * height + gcode_toolradius*2), sa, ea, gdBrushed);
+}
+
+static void
+gcode_fill_circle(hidGC gc, int cx, int cy, int radius)
+{
+ use_gc(gc);
+
+ gdImageSetThickness(gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledEllipse(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy),
+ pcb_to_gcode(2 * radius + gcode_toolradius*2), pcb_to_gcode(2 * radius + gcode_toolradius*2), gc->color->c);
+ if(save_drill&&is_drill){
+ if(n_drill==nmax_drill){
+ drill=(struct drill_struct*) realloc(drill,(nmax_drill+100)*sizeof(struct drill_struct));
+ nmax_drill+=100;
+ }
+ drill[n_drill].x=(PCB->MaxWidth-cx)/pcb_unit; //convert to inch, flip: will drill from bottom side
+ drill[n_drill].y=(PCB->MaxHeight-cy)/pcb_unit; //PCB reverses y axis
+ n_drill++;
+// printf("Circle %d %d\n",cx,cy);
+ }
+}
+
+static void
+gcode_fill_polygon(hidGC gc, int n_coords, int *x, int *y)
+{
+ int i;
+ gdPoint *points;
+
+ points = (gdPoint *) malloc(n_coords * sizeof(gdPoint));
+ if (points == NULL) {
+ fprintf(stderr, "ERROR: gcode_fill_polygon(): malloc failed\n");
+ exit(1);
+ }
+ use_gc(gc);
+ for (i = 0; i < n_coords; i++) {
+ points[i].x = pcb_to_gcode(x[i]);
+ points[i].y = pcb_to_gcode(y[i]);
+ }
+ gdImageSetThickness(gcode_im, 0);
+ linewidth = 0;
+ gdImageFilledPolygon(gcode_im, points, n_coords, gc->color->c);
+ free(points);
+// printf("FillPoly\n");
+}
+
+static void
+gcode_calibrate(double xval, double yval)
+{
+ CRASH;
+}
+
+static void
+gcode_set_crosshair(int x, int y, int a)
+{
+}
+
+/* *** Miscellaneous ******************************************************* */
+
+HID gcode_hid = {
+ sizeof(HID),
+ "gcode",
+ "G-CODE export.",
+ 0, /* gui */
+ 0, /* printer */
+ 1, /* exporter */
+ 1, /* poly before */
+ 0, /* poly after */
+ 0, /* poly dicer */
+ gcode_get_export_options,
+ gcode_do_export,
+ gcode_parse_arguments,
+ 0 /* gcode_invalidate_wh */ ,
+ 0 /* gcode_invalidate_lr */ ,
+ 0 /* gcode_invalidate_all */ ,
+ gcode_set_layer,
+ gcode_make_gc,
+ gcode_destroy_gc,
+ gcode_use_mask,
+ gcode_set_color,
+ gcode_set_line_cap,
+ gcode_set_line_width,
+ gcode_set_draw_xor,
+ gcode_set_draw_faded,
+ gcode_set_line_cap_angle,
+ gcode_draw_line,
+ gcode_draw_arc,
+ gcode_draw_rect,
+ gcode_fill_circle,
+ gcode_fill_polygon,
+ common_fill_pcb_polygon,
+ 0 /* nelma_thindraw_pcb_polygon */ ,
+ gcode_fill_rect,
+ gcode_calibrate,
+ 0 /* gcode_shift_is_pressed */ ,
+ 0 /* gcode_control_is_pressed */ ,
+ 0 /* gcode_mod1_is_pressed */ ,
+ 0 /* gcode_get_coords */ ,
+ gcode_set_crosshair,
+ 0 /* gcode_add_timer */ ,
+ 0 /* gcode_stop_timer */ ,
+ 0 /* gcode_watch_file */ ,
+ 0 /* gcode_unwatch_file */ ,
+ 0 /* gcode_add_block_hook */ ,
+ 0 /* gcode_stop_block_hook */ ,
+ 0 /* gcode_log */ ,
+ 0 /* gcode_logv */ ,
+ 0 /* gcode_confirm_dialog */ ,
+ 0 /* gcode_close_confirm_dialog */ ,
+ 0 /* gcode_report_dialog */ ,
+ 0 /* gcode_prompt_for */ ,
+ 0 /* gcode_fileselect */ ,
+ 0 /* gcode_attribute_dialog */ ,
+ 0 /* gcode_show_item */ ,
+ 0 /* gcode_beep */ ,
+ 0 /* gcode_progress */ ,
+ 0 /* gcode_drc_gui */
+};
+
+#include "dolists.h"
+
+void
+hid_gcode_init()
+{
+ apply_default_hid(&gcode_hid, 0);
+ hid_register_hid(&gcode_hid);
+
+#include "gcode_lists.h"
+}
diff --git a/src/hid/gcode/gcode.h b/src/hid/gcode/gcode.h
new file mode 100644
index 0000000..352cbd9
--- /dev/null
+++ b/src/hid/gcode/gcode.h
@@ -0,0 +1,3 @@
+/* $Id: nelma.h,v 1.2 2007/04/20 11:31:15 danmc Exp $ */
+
+extern HID gcode_hid;
diff --git a/src/hid/gcode/hid.conf b/src/hid/gcode/hid.conf
new file mode 100644
index 0000000..7be6c4c
--- /dev/null
+++ b/src/hid/gcode/hid.conf
@@ -0,0 +1 @@
+type=export
diff --git a/src/hid/gcode/lists.h b/src/hid/gcode/lists.h
new file mode 100644
index 0000000..931cbb0
--- /dev/null
+++ b/src/hid/gcode/lists.h
@@ -0,0 +1,286 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: lists.h 147 2007-04-09 00:44:09Z selinger $ */
+
+#ifndef _PS_LISTS_H
+#define _PS_LISTS_H
+
+/* here we define some general list macros. Because they are macros,
+ they should work on any datatype with a "->next" component. Some of
+ them use a "hook". If elt and list are of type t* then hook is of
+ type t**. A hook stands for an insertion point in the list, i.e.,
+ either before the first element, or between two elements, or after
+ the last element. If an operation "sets the hook" for an element,
+ then the hook is set to just before the element. One can insert
+ something at a hook. One can also unlink at a hook: this means,
+ unlink the element just after the hook. By "to unlink", we mean the
+ element is removed from the list, but not deleted. Thus, it and its
+ components still need to be freed. */
+
+/* Note: these macros are somewhat experimental. Only the ones that
+ are actually *used* have been tested. So be careful to test any
+ that you use. Looking at the output of the preprocessor, "gcc -E"
+ (possibly piped though "indent"), might help too. Also: these
+ macros define some internal (local) variables that start with
+ "_". */
+
+/* we enclose macro definitions whose body consists of more than one
+ statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The
+ reason is that we want to be able to use the macro in a context
+ such as "if (...) macro(...); else ...". If we didn't use this obscure
+ trick, we'd have to omit the ";" in such cases. */
+
+#define MACRO_BEGIN do {
+#define MACRO_END } while (0)
+
+/* ---------------------------------------------------------------------- */
+/* macros for singly-linked lists */
+
+/* traverse list. At the end, elt is set to NULL. */
+#define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next)
+
+/* set elt to the first element of list satisfying boolean condition
+ c, or NULL if not found */
+#define list_find(elt, list, c) \
+ MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
+
+/* like forall, except also set hook for elt. */
+#define list_forall2(elt, list, hook) \
+ for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
+
+/* same as list_find, except also set hook for elt. */
+#define list_find2(elt, list, c, hook) \
+ MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
+
+/* same, except only use hook. */
+#define _list_forall_hook(list, hook) \
+ for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
+
+/* same, except only use hook. Note: c may only refer to *hook, not elt. */
+#define _list_find_hook(list, c, hook) \
+ MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
+
+/* insert element after hook */
+#define list_insert_athook(elt, hook) \
+ MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
+
+/* insert element before hook */
+#define list_insert_beforehook(elt, hook) \
+ MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
+
+/* unlink element after hook, let elt be unlinked element, or NULL.
+ hook remains. */
+#define list_unlink_athook(list, elt, hook) \
+ MACRO_BEGIN \
+ elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
+ MACRO_END
+
+/* unlink the specific element, if it is in the list. Otherwise, set
+ elt to NULL */
+#define list_unlink(listtype, list, elt) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_find_hook(list, *_hook==elt, _hook); \
+ list_unlink_athook(list, elt, _hook); \
+ MACRO_END
+
+/* prepend elt to list */
+#define list_prepend(list, elt) \
+ MACRO_BEGIN elt->next = list; list = elt; MACRO_END
+
+/* append elt to list. */
+#define list_append(listtype, list, elt) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_forall_hook(list, _hook) {} \
+ list_insert_athook(elt, _hook); \
+ MACRO_END
+
+/* unlink the first element that satisfies the condition. */
+#define list_unlink_cond(listtype, list, elt, c) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ list_find2(elt, list, c, _hook); \
+ list_unlink_athook(list, elt, _hook); \
+ MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+ Return NULL if out of bounds. */
+#define list_nth(elt, list, n) \
+ MACRO_BEGIN \
+ int _x; /* only evaluate n once */ \
+ for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \
+ MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+ Return NULL if out of bounds. */
+#define list_nth_hook(elt, list, n, hook) \
+ MACRO_BEGIN \
+ int _x; /* only evaluate n once */ \
+ for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \
+ MACRO_END
+
+/* set n to the length of the list */
+#define list_length(listtype, list, n) \
+ MACRO_BEGIN \
+ listtype *_elt; \
+ n=0; \
+ list_forall(_elt, list) \
+ n++; \
+ MACRO_END
+
+/* set n to the index of the first element satisfying cond, or -1 if
+ none found. Also set elt to the element, or NULL if none found. */
+#define list_index(list, n, elt, c) \
+ MACRO_BEGIN \
+ n=0; \
+ list_forall(elt, list) { \
+ if (c) break; \
+ n++; \
+ } \
+ if (!elt) \
+ n=-1; \
+ MACRO_END
+
+/* set n to the number of elements in the list that satisfy condition c */
+#define list_count(list, n, elt, c) \
+ MACRO_BEGIN \
+ n=0; \
+ list_forall(elt, list) { \
+ if (c) n++; \
+ } \
+ MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define list_forall_unlink(elt, list) \
+ for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
+
+/* reverse a list (efficient) */
+#define list_reverse(listtype, list) \
+ MACRO_BEGIN \
+ listtype *_list1=NULL, *elt; \
+ list_forall_unlink(elt, list) \
+ list_prepend(_list1, elt); \
+ list = _list1; \
+ MACRO_END
+
+/* insert the element ELT just before the first element TMP of the
+ list for which COND holds. Here COND must be a condition of ELT and
+ TMP. Typical usage is to insert an element into an ordered list:
+ for instance, list_insert_ordered(listtype, list, elt, tmp,
+ elt->size <= tmp->size). Note: if we give a "less than or equal"
+ condition, the new element will be inserted just before a sequence
+ of equal elements. If we give a "less than" condition, the new
+ element will be inserted just after a list of equal elements.
+ Note: it is much more efficient to construct a list with
+ list_prepend and then order it with list_merge_sort, than to
+ construct it with list_insert_ordered. */
+#define list_insert_ordered(listtype, list, elt, tmp, cond) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \
+ list_insert_athook(elt, _hook); \
+ MACRO_END
+
+/* sort the given list, according to the comparison condition.
+ Typical usage is list_sort(listtype, list, a, b, a->size <
+ b->size). Note: if we give "less than or equal" condition, each
+ segment of equal elements will be reversed in order. If we give a
+ "less than" condition, each segment of equal elements will retain
+ the original order. The latter is slower but sometimes
+ prettier. Average running time: n*n/2. */
+#define list_sort(listtype, list, a, b, cond) \
+ MACRO_BEGIN \
+ listtype *_newlist=NULL; \
+ list_forall_unlink(a, list) \
+ list_insert_ordered(listtype, _newlist, a, b, cond); \
+ list = _newlist; \
+ MACRO_END
+
+/* a much faster sort algorithm (merge sort, n log n worst case). It
+ is required that the list type has an additional, unused next1
+ component. Note there is no curious reversal of order of equal
+ elements as for list_sort. */
+
+#define list_mergesort(listtype, list, a, b, cond) \
+ MACRO_BEGIN \
+ listtype *_elt, **_hook1; \
+ \
+ for (_elt=list; _elt; _elt=_elt->next1) { \
+ _elt->next1 = _elt->next; \
+ _elt->next = NULL; \
+ } \
+ do { \
+ _hook1 = &(list); \
+ while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
+ _elt = b->next1; \
+ _list_merge_cond(listtype, a, b, cond, *_hook1); \
+ _hook1 = &((*_hook1)->next1); \
+ *_hook1 = _elt; \
+ } \
+ } while (_hook1 != &(list)); \
+ MACRO_END
+
+/* merge two sorted lists. Store result at &result */
+#define _list_merge_cond(listtype, a, b, cond, result) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _hook = &(result); \
+ while (1) { \
+ if (a==NULL) { \
+ *_hook = b; \
+ break; \
+ } else if (b==NULL) { \
+ *_hook = a; \
+ break; \
+ } else if (cond) { \
+ *_hook = a; \
+ _hook = &(a->next); \
+ a = a->next; \
+ } else { \
+ *_hook = b; \
+ _hook = &(b->next); \
+ b = b->next; \
+ } \
+ } \
+ MACRO_END
+
+/* ---------------------------------------------------------------------- */
+/* macros for doubly-linked lists */
+
+#define dlist_append(head, end, elt) \
+ MACRO_BEGIN \
+ elt->prev = end; \
+ elt->next = NULL; \
+ if (end) { \
+ end->next = elt; \
+ } else { \
+ head = elt; \
+ } \
+ end = elt; \
+ MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define dlist_forall_unlink(elt, head, end) \
+ for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
+
+/* unlink the first element of the list */
+#define dlist_unlink_first(head, end, elt) \
+ MACRO_BEGIN \
+ elt = head; \
+ if (head) { \
+ head = head->next; \
+ if (head) { \
+ head->prev = NULL; \
+ } else { \
+ end = NULL; \
+ } \
+ elt->prev = NULL; \
+ elt->next = NULL; \
+ } \
+ MACRO_END
+
+#endif /* _PS_LISTS_H */
+
diff --git a/src/hid/gcode/potracelib.h b/src/hid/gcode/potracelib.h
new file mode 100644
index 0000000..0b93d65
--- /dev/null
+++ b/src/hid/gcode/potracelib.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef POTRACELIB_H
+#define POTRACELIB_H
+
+/* this file defines the API for the core Potrace library. For a more
+ detailed description of the API, see doc/potracelib.txt */
+
+/* ---------------------------------------------------------------------- */
+/* tracing parameters */
+
+/* turn policies */
+#define POTRACE_TURNPOLICY_BLACK 0
+#define POTRACE_TURNPOLICY_WHITE 1
+#define POTRACE_TURNPOLICY_LEFT 2
+#define POTRACE_TURNPOLICY_RIGHT 3
+#define POTRACE_TURNPOLICY_MINORITY 4
+#define POTRACE_TURNPOLICY_MAJORITY 5
+#define POTRACE_TURNPOLICY_RANDOM 6
+
+/* structure to hold progress bar callback data */
+struct potrace_progress_s {
+ void (*callback)(double progress, void *privdata); /* callback fn */
+ void *data; /* callback function's private data */
+ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
+ double epsilon; /* granularity: can skip smaller increments */
+};
+typedef struct potrace_progress_s potrace_progress_t;
+
+/* structure to hold tracing parameters */
+struct potrace_param_s {
+ int turdsize; /* area of largest path to be ignored */
+ int turnpolicy; /* resolves ambiguous turns in path decomposition */
+ double alphamax; /* corner threshold */
+ int opticurve; /* use curve optimization? */
+ double opttolerance; /* curve optimization tolerance */
+ potrace_progress_t progress; /* progress callback function */
+};
+typedef struct potrace_param_s potrace_param_t;
+
+/* ---------------------------------------------------------------------- */
+/* bitmaps */
+
+/* native word size */
+typedef unsigned long potrace_word;
+
+/* Internal bitmap format. The n-th scanline starts at scanline(n) =
+ (map + n*dy). Raster data is stored as a sequence of potrace_words
+ (NOT bytes). The leftmost bit of scanline n is the most significant
+ bit of scanline(n)[0]. */
+struct potrace_bitmap_s {
+ int w, h; /* width and height, in pixels */
+ int dy; /* words per scanline (not bytes) */
+ potrace_word *map; /* raw data, dy*h words */
+};
+typedef struct potrace_bitmap_s potrace_bitmap_t;
+
+/* ---------------------------------------------------------------------- */
+/* curves */
+
+/* point */
+struct potrace_dpoint_s {
+ double x, y;
+};
+typedef struct potrace_dpoint_s potrace_dpoint_t;
+
+/* segment tags */
+#define POTRACE_CURVETO 1
+#define POTRACE_CORNER 2
+
+/* closed curve segment */
+struct potrace_curve_s {
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
+ potrace_dpoint_t (*c)[3]; /* c[n][3]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
+};
+typedef struct potrace_curve_s potrace_curve_t;
+
+/* Linked list of signed curve segments. Also carries a tree structure. */
+struct potrace_path_s {
+ int area; /* area of the bitmap path */
+ int sign; /* '+' or '-', depending on orientation */
+ potrace_curve_t curve; /* this path's vector data */
+
+ struct potrace_path_s *next; /* linked list structure */
+
+ struct potrace_path_s *childlist; /* tree structure */
+ struct potrace_path_s *sibling; /* tree structure */
+
+ struct potrace_privpath_s *priv; /* private state */
+};
+typedef struct potrace_path_s potrace_path_t;
+
+/* ---------------------------------------------------------------------- */
+/* Potrace state */
+
+#define POTRACE_STATUS_OK 0
+#define POTRACE_STATUS_INCOMPLETE 1
+
+struct potrace_state_s {
+ int status;
+ potrace_path_t *plist; /* vector data */
+
+ struct potrace_privstate_s *priv; /* private state */
+};
+typedef struct potrace_state_s potrace_state_t;
+
+/* ---------------------------------------------------------------------- */
+/* API functions */
+
+/* get default parameters */
+potrace_param_t *potrace_param_default(void);
+
+/* free parameter set */
+void potrace_param_free(potrace_param_t *p);
+
+/* trace a bitmap*/
+potrace_state_t *potrace_trace(const potrace_param_t *param,
+ const potrace_bitmap_t *bm);
+
+/* free a Potrace state */
+void potrace_state_free(potrace_state_t *st);
+
+/* return a static plain text version string identifying this version
+ of potracelib */
+char *potrace_version(void);
+
+#endif /* POTRACELIB_H */
diff --git a/src/hid/gcode/trace.c b/src/hid/gcode/trace.c
new file mode 100644
index 0000000..2c615e6
--- /dev/null
+++ b/src/hid/gcode/trace.c
@@ -0,0 +1,1246 @@
+/* This file was slightly modified by Alberto Maccioni to be used with PCB G-CODE exporter*/
+
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: trace.c 147 2007-04-09 00:44:09Z selinger $ */
+/* transform jaggy paths into smooth curves */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trace.h"
+//#include "progress.h"
+
+#define INFTY 10000000 /* it suffices that this is longer than any
+ path; it need not be really infinite */
+#define COS179 -0.999847695156 /* the cosine of 179 degrees */
+
+/* ---------------------------------------------------------------------- */
+#define SAFE_MALLOC(var, n, typ) \
+ if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* return a direction that is 90 degrees counterclockwise from p2-p0,
+ but then restricted to one of the major wind directions (n, nw, w, etc) */
+static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
+ point_t r;
+
+ r.y = sign(p2.x-p0.x);
+ r.x = -sign(p2.y-p0.y);
+
+ return r;
+}
+
+/* return (p1-p0)x(p2-p0), the area of the parallelogram */
+static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x-p0.x;
+ y1 = p1.y-p0.y;
+ x2 = p2.x-p0.x;
+ y2 = p2.y-p0.y;
+
+ return x1*y2 - x2*y1;
+}
+
+/* ddenom/dpara have the property that the square of radius 1 centered
+ at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
+static inline double ddenom(dpoint_t p0, dpoint_t p2) {
+ point_t r = dorth_infty(p0, p2);
+
+ return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
+}
+
+/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
+static inline int cyclic(int a, int b, int c) {
+ if (a<=c) {
+ return (a<=b && b<c);
+ } else {
+ return (a<=b || b<c);
+ }
+}
+
+/* determine the center and slope of the line i..j. Assume i<j. Needs
+ "sum" components of p to be set. */
+static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
+ /* assume i<j */
+
+ int n = pp->len;
+ sums_t *sums = pp->sums;
+
+ double x, y, x2, xy, y2;
+ double k;
+ double a, b, c, lambda2, l;
+ int r=0; /* rotations from i to j */
+
+ while (j>=n) {
+ j-=n;
+ r+=1;
+ }
+ while (i>=n) {
+ i-=n;
+ r-=1;
+ }
+ while (j<0) {
+ j+=n;
+ r-=1;
+ }
+ while (i<0) {
+ i+=n;
+ r+=1;
+ }
+
+ x = sums[j+1].x-sums[i].x+r*sums[n].x;
+ y = sums[j+1].y-sums[i].y+r*sums[n].y;
+ x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
+ xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
+ y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
+ k = j+1-i+r*n;
+
+ ctr->x = x/k;
+ ctr->y = y/k;
+
+ a = (x2-(double)x*x/k)/k;
+ b = (xy-(double)x*y/k)/k;
+ c = (y2-(double)y*y/k)/k;
+
+ lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
+
+ /* now find e.vector for lambda2 */
+ a -= lambda2;
+ c -= lambda2;
+
+ if (fabs(a) >= fabs(c)) {
+ l = sqrt(a*a+b*b);
+ if (l!=0) {
+ dir->x = -b/l;
+ dir->y = a/l;
+ }
+ } else {
+ l = sqrt(c*c+b*b);
+ if (l!=0) {
+ dir->x = -c/l;
+ dir->y = b/l;
+ }
+ }
+ if (l==0) {
+ dir->x = dir->y = 0; /* sometimes this can happen when k=4:
+ the two eigenvalues coincide */
+ }
+}
+
+/* the type of (affine) quadratic forms, represented as symmetric 3x3
+ matrices. The value of the quadratic form at a vector (x,y) is v^t
+ Q v, where v = (x,y,1)^t. */
+typedef double quadform_t[3][3];
+
+/* Apply quadratic form Q to vector w = (w.x,w.y) */
+static inline double quadform(quadform_t Q, dpoint_t w) {
+ double v[3];
+ int i, j;
+ double sum;
+
+ v[0] = w.x;
+ v[1] = w.y;
+ v[2] = 1;
+ sum = 0.0;
+
+ for (i=0; i<3; i++) {
+ for (j=0; j<3; j++) {
+ sum += v[i] * Q[i][j] * v[j];
+ }
+ }
+ return sum;
+}
+
+/* calculate p1 x p2 */
+static inline int xprod(point_t p1, point_t p2) {
+ return p1.x*p2.y - p1.y*p2.x;
+}
+
+/* calculate (p1-p0)x(p3-p2) */
+static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p3.x - p2.x;
+ y2 = p3.y - p2.y;
+
+ return x1*y2 - x2*y1;
+}
+
+/* calculate (p1-p0)*(p2-p0) */
+static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p2.x - p0.x;
+ y2 = p2.y - p0.y;
+
+ return x1*x2 + y1*y2;
+}
+
+/* calculate (p1-p0)*(p3-p2) */
+static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p3.x - p2.x;
+ y2 = p3.y - p2.y;
+
+ return x1*x2 + y1*y2;
+}
+
+/* calculate distance between two points */
+static inline double ddist(dpoint_t p, dpoint_t q) {
+ return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
+}
+
+/* calculate point of a bezier curve */
+static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double s = 1-t;
+ dpoint_t res;
+
+ /* Note: a good optimizing compiler (such as gcc-3) reduces the
+ following to 16 multiplications, using common subexpression
+ elimination. */
+
+ res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
+ res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
+
+ return res;
+}
+
+/* calculate the point t in [0..1] on the (convex) bezier curve
+ (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
+ solution in [0..1]. */
+static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
+ double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
+ double a, b, c; /* a t^2 + b t + c = 0 */
+ double d, s, r1, r2;
+
+ A = cprod(p0, p1, q0, q1);
+ B = cprod(p1, p2, q0, q1);
+ C = cprod(p2, p3, q0, q1);
+
+ a = A - 2*B + C;
+ b = -2*A + 2*B;
+ c = A;
+
+ d = b*b - 4*a*c;
+
+ if (a==0 || d<0) {
+ return -1.0;
+ }
+
+ s = sqrt(d);
+
+ r1 = (-b + s) / (2 * a);
+ r2 = (-b - s) / (2 * a);
+
+ if (r1 >= 0 && r1 <= 1) {
+ return r1;
+ } else if (r2 >= 0 && r2 <= 1) {
+ return r2;
+ } else {
+ return -1.0;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Preparation: fill in the sum* fields of a path (used for later
+ rapid summing). Return 0 on success, 1 with errno set on
+ failure. */
+static int calc_sums(privpath_t *pp) {
+ int i, x, y;
+ int n = pp->len;
+
+ SAFE_MALLOC(pp->sums, pp->len+1, sums_t);
+
+ /* origin */
+ pp->x0 = pp->pt[0].x;
+ pp->y0 = pp->pt[0].y;
+
+ /* preparatory computation for later fast summing */
+ pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
+ for (i=0; i<n; i++) {
+ x = pp->pt[i].x - pp->x0;
+ y = pp->pt[i].y - pp->y0;
+ pp->sums[i+1].x = pp->sums[i].x + x;
+ pp->sums[i+1].y = pp->sums[i].y + y;
+ pp->sums[i+1].x2 = pp->sums[i].x2 + x*x;
+ pp->sums[i+1].xy = pp->sums[i].xy + x*y;
+ pp->sums[i+1].y2 = pp->sums[i].y2 + y*y;
+ }
+ return 0;
+
+ malloc_error:
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the
+ "lon" component of a path object (based on pt/len). For each i,
+ lon[i] is the furthest index such that a straight line can be drawn
+ from i to lon[i]. Return 1 on error with errno set, else 0. */
+
+/* this algorithm depends on the fact that the existence of straight
+ subpaths is a triplewise property. I.e., there exists a straight
+ line through squares i0,...,in iff there exists a straight line
+ through i,j,k, for all i0<=i<j<k<=in. (Proof?) */
+
+/* this implementation of calc_lon is O(n^2). It replaces an older
+ O(n^3) version. A "constraint" means that future points must
+ satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1],
+ cur) <= 0. */
+
+/* Remark for Potrace 1.1: the current implementation of calc_lon is
+ more complex than the implementation found in Potrace 1.0, but it
+ is considerably faster. The introduction of the "nc" data structure
+ means that we only have to test the constraints for "corner"
+ points. On a typical input file, this speeds up the calc_lon
+ function by a factor of 31.2, thereby decreasing its time share
+ within the overall Potrace algorithm from 72.6% to 7.82%, and
+ speeding up the overall algorithm by a factor of 3.36. On another
+ input file, calc_lon was sped up by a factor of 6.7, decreasing its
+ time share from 51.4% to 13.61%, and speeding up the overall
+ algorithm by a factor of 1.78. In any case, the savings are
+ substantial. */
+
+/* returns 0 on success, 1 on error with errno set */
+static int calc_lon(privpath_t *pp) {
+ point_t *pt = pp->pt;
+ int n = pp->len;
+ int i, j, k, k1;
+ int ct[4], dir;
+ point_t constraint[2];
+ point_t cur;
+ point_t off;
+ int *pivk = NULL; /* pivk[n] */
+ int *nc = NULL; /* nc[n]: next corner */
+ point_t dk; /* direction of k-k1 */
+ int a, b, c, d;
+
+ SAFE_MALLOC(pivk, n, int);
+ SAFE_MALLOC(nc, n, int);
+
+ /* initialize the nc data structure. Point from each point to the
+ furthest future point to which it is connected by a vertical or
+ horizontal segment. We take advantage of the fact that there is
+ always a direction change at 0 (due to the path decomposition
+ algorithm). But even if this were not so, there is no harm, as
+ in practice, correctness does not depend on the word "furthest"
+ above. */
+ k = 0;
+ for (i=n-1; i>=0; i--) {
+ if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
+ k = i+1; /* necessarily i<n-1 in this case */
+ }
+ nc[i] = k;
+ }
+
+ SAFE_MALLOC(pp->lon, n, int);
+
+ /* determine pivot points: for each i, let pivk[i] be the furthest k
+ such that all j with i<j<k lie on a line connecting i,k. */
+
+ for (i=n-1; i>=0; i--) {
+ ct[0] = ct[1] = ct[2] = ct[3] = 0;
+
+ /* keep track of "directions" that have occurred */
+ dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
+ ct[dir]++;
+
+ constraint[0].x = 0;
+ constraint[0].y = 0;
+ constraint[1].x = 0;
+ constraint[1].y = 0;
+
+ /* find the next k such that no straight line from i to k */
+ k = nc[i];
+ k1 = i;
+ while (1) {
+
+ dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
+ ct[dir]++;
+
+ /* if all four "directions" have occurred, cut this path */
+ if (ct[0] && ct[1] && ct[2] && ct[3]) {
+ pivk[i] = k1;
+ goto foundk;
+ }
+
+ cur.x = pt[k].x - pt[i].x;
+ cur.y = pt[k].y - pt[i].y;
+
+ /* see if current constraint is violated */
+ if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
+ goto constraint_viol;
+ }
+
+ /* else, update constraint */
+ if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
+ /* no constraint */
+ } else {
+ off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
+ off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
+ if (xprod(constraint[0], off) >= 0) {
+ constraint[0] = off;
+ }
+ off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
+ off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
+ if (xprod(constraint[1], off) <= 0) {
+ constraint[1] = off;
+ }
+ }
+ k1 = k;
+ k = nc[k1];
+ if (!cyclic(k,i,k1)) {
+ break;
+ }
+ }
+ constraint_viol:
+ /* k1 was the last "corner" satisfying the current constraint, and
+ k is the first one violating it. We now need to find the last
+ point along k1..k which satisfied the constraint. */
+ dk.x = sign(pt[k].x-pt[k1].x);
+ dk.y = sign(pt[k].y-pt[k1].y);
+ cur.x = pt[k1].x - pt[i].x;
+ cur.y = pt[k1].y - pt[i].y;
+ /* find largest integer j such that xprod(constraint[0], cur+j*dk)
+ >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
+ of xprod. */
+ a = xprod(constraint[0], cur);
+ b = xprod(constraint[0], dk);
+ c = xprod(constraint[1], cur);
+ d = xprod(constraint[1], dk);
+ /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
+ can be solved with integer arithmetic. */
+ j = INFTY;
+ if (b<0) {
+ j = floordiv(a,-b);
+ }
+ if (d>0) {
+ j = min(j, floordiv(-c,d));
+ }
+ pivk[i] = mod(k1+j,n);
+ foundk:
+ ;
+ } /* for i */
+
+ /* clean up: for each i, let lon[i] be the largest k such that for
+ all i' with i<=i'<k, i'<k<=pivk[i']. */
+
+ j=pivk[n-1];
+ pp->lon[n-1]=j;
+ for (i=n-2; i>=0; i--) {
+ if (cyclic(i+1,pivk[i],j)) {
+ j=pivk[i];
+ }
+ pp->lon[i]=j;
+ }
+
+ for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
+ pp->lon[i] = j;
+ }
+
+ free(pivk);
+ free(nc);
+ return 0;
+
+ malloc_error:
+ free(pivk);
+ free(nc);
+ return 1;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
+
+/* Auxiliary function: calculate the penalty of an edge from i to j in
+ the given path. This needs the "lon" and "sum*" data. */
+
+static double penalty3(privpath_t *pp, int i, int j) {
+ int n = pp->len;
+ point_t *pt = pp->pt;
+ sums_t *sums = pp->sums;
+
+ /* assume 0<=i<j<=n */
+ double x, y, x2, xy, y2;
+ double k;
+ double a, b, c, s;
+ double px, py, ex, ey;
+
+ int r=0; /* rotations from i to j */
+
+ if (j>=n) {
+ j-=n;
+ r+=1;
+ }
+
+ x = sums[j+1].x-sums[i].x+r*sums[n].x;
+ y = sums[j+1].y-sums[i].y+r*sums[n].y;
+ x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
+ xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
+ y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
+ k = j+1-i+r*n;
+
+ px = (pt[i].x+pt[j].x)/2.0-pt[0].x;
+ py = (pt[i].y+pt[j].y)/2.0-pt[0].y;
+ ey = (pt[j].x-pt[i].x);
+ ex = -(pt[j].y-pt[i].y);
+
+ a = ((x2-2*x*px)/k+px*px);
+ b = ((xy-x*py-y*px)/k+px*py);
+ c = ((y2-2*y*py)/k+py*py);
+
+ s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
+
+ return sqrt(s);
+}
+
+/* find the optimal polygon. Fill in the m and po components. Return 1
+ on failure with errno set, else 0. Non-cyclic version: assumes i=0
+ is in the polygon. Fixme: ### implement cyclic version. */
+static int bestpolygon(privpath_t *pp)
+{
+ int i, j, m, k;
+ int n = pp->len;
+ double *pen = NULL; /* pen[n+1]: penalty vector */
+ int *prev = NULL; /* prev[n+1]: best path pointer vector */
+ int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */
+ int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */
+ int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */
+ int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */
+ double thispen;
+ double best;
+ int c;
+
+ SAFE_MALLOC(pen, n+1, double);
+ SAFE_MALLOC(prev, n+1, int);
+ SAFE_MALLOC(clip0, n, int);
+ SAFE_MALLOC(clip1, n+1, int);
+ SAFE_MALLOC(seg0, n+1, int);
+ SAFE_MALLOC(seg1, n+1, int);
+
+ /* calculate clipped paths */
+ for (i=0; i<n; i++) {
+ c = mod(pp->lon[mod(i-1,n)]-1,n);
+ if (c == i) {
+ c = mod(i+1,n);
+ }
+ if (c < i) {
+ clip0[i] = n;
+ } else {
+ clip0[i] = c;
+ }
+ }
+
+ /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
+ clip1[j] <= i, for i,j=0..n. */
+ j = 1;
+ for (i=0; i<n; i++) {
+ while (j <= clip0[i]) {
+ clip1[j] = i;
+ j++;
+ }
+ }
+
+ /* calculate seg0[j] = longest path from 0 with j segments */
+ i = 0;
+ for (j=0; i<n; j++) {
+ seg0[j] = i;
+ i = clip0[i];
+ }
+ seg0[j] = n;
+ m = j;
+
+ /* calculate seg1[j] = longest path to n with m-j segments */
+ i = n;
+ for (j=m; j>0; j--) {
+ seg1[j] = i;
+ i = clip1[i];
+ }
+ seg1[0] = 0;
+
+ /* now find the shortest path with m segments, based on penalty3 */
+ /* note: the outer 2 loops jointly have at most n interations, thus
+ the worst-case behavior here is quadratic. In practice, it is
+ close to linear since the inner loop tends to be short. */
+ pen[0]=0;
+ for (j=1; j<=m; j++) {
+ for (i=seg1[j]; i<=seg0[j]; i++) {
+ best = -1;
+ for (k=seg0[j-1]; k>=clip1[i]; k--) {
+ thispen = penalty3(pp, k, i) + pen[k];
+ if (best < 0 || thispen < best) {
+ prev[i] = k;
+ best = thispen;
+ }
+ }
+ pen[i] = best;
+ }
+ }
+
+ pp->m = m;
+ SAFE_MALLOC(pp->po, m, int);
+
+ /* read off shortest path */
+ for (i=n, j=m-1; i>0; j--) {
+ i = prev[i];
+ pp->po[j] = i;
+ }
+
+ free(pen);
+ free(prev);
+ free(clip0);
+ free(clip1);
+ free(seg0);
+ free(seg1);
+ return 0;
+
+ malloc_error:
+ free(pen);
+ free(prev);
+ free(clip0);
+ free(clip1);
+ free(seg0);
+ free(seg1);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 3: vertex adjustment (Sec. 2.3.1). */
+
+/* Adjust vertices of optimal polygon: calculate the intersection of
+ the two "optimal" line segments, then move it into the unit square
+ if it lies outside. Return 1 with errno set on error; 0 on
+ success. */
+
+static int adjust_vertices(privpath_t *pp) {
+ int m = pp->m;
+ int *po = pp->po;
+ int n = pp->len;
+ point_t *pt = pp->pt;
+ int x0 = pp->x0;
+ int y0 = pp->y0;
+
+ dpoint_t *ctr = NULL; /* ctr[m] */
+ dpoint_t *dir = NULL; /* dir[m] */
+ quadform_t *q = NULL; /* q[m] */
+ double v[3];
+ double d;
+ int i, j, k, l;
+ dpoint_t s;
+ int r;
+
+ SAFE_MALLOC(ctr, m, dpoint_t);
+ SAFE_MALLOC(dir, m, dpoint_t);
+ SAFE_MALLOC(q, m, quadform_t);
+
+ r = privcurve_init(&pp->curve, m);
+ if (r) {
+ goto malloc_error;
+ }
+
+ /* calculate "optimal" point-slope representation for each line
+ segment */
+ for (i=0; i<m; i++) {
+ j = po[mod(i+1,m)];
+ j = mod(j-po[i],n)+po[i];
+ pointslope(pp, po[i], j, &ctr[i], &dir[i]);
+ }
+
+ /* represent each line segment as a singular quadratic form; the
+ distance of a point (x,y) from the line segment will be
+ (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
+ for (i=0; i<m; i++) {
+ d = sq(dir[i].x) + sq(dir[i].y);
+ if (d == 0.0) {
+ for (j=0; j<3; j++) {
+ for (k=0; k<3; k++) {
+ q[i][j][k] = 0;
+ }
+ }
+ } else {
+ v[0] = dir[i].y;
+ v[1] = -dir[i].x;
+ v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ q[i][l][k] = v[l] * v[k] / d;
+ }
+ }
+ }
+ }
+
+ /* now calculate the "intersections" of consecutive segments.
+ Instead of using the actual intersection, we find the point
+ within a given unit square which minimizes the square distance to
+ the two lines. */
+ for (i=0; i<m; i++) {
+ quadform_t Q;
+ dpoint_t w;
+ double dx, dy;
+ double det;
+ double min, cand; /* minimum and candidate for minimum of quad. form */
+ double xmin, ymin; /* coordinates of minimum */
+ int z;
+
+ /* let s be the vertex, in coordinates relative to x0/y0 */
+ s.x = pt[po[i]].x-x0;
+ s.y = pt[po[i]].y-y0;
+
+ /* intersect segments i-1 and i */
+
+ j = mod(i-1,m);
+
+ /* add quadratic forms */
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ Q[l][k] = q[j][l][k] + q[i][l][k];
+ }
+ }
+
+ while(1) {
+ /* minimize the quadratic form Q on the unit square */
+ /* find intersection */
+
+#ifdef HAVE_GCC_LOOP_BUG
+ /* work around gcc bug #12243 */
+ free(NULL);
+#endif
+
+ det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
+ if (det != 0.0) {
+ w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
+ w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
+ break;
+ }
+
+ /* matrix is singular - lines are parallel. Add another,
+ orthogonal axis, through the center of the unit square */
+ if (Q[0][0]>Q[1][1]) {
+ v[0] = -Q[0][1];
+ v[1] = Q[0][0];
+ } else if (Q[1][1]) {
+ v[0] = -Q[1][1];
+ v[1] = Q[1][0];
+ } else {
+ v[0] = 1;
+ v[1] = 0;
+ }
+ d = sq(v[0]) + sq(v[1]);
+ v[2] = - v[1] * s.y - v[0] * s.x;
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ Q[l][k] += v[l] * v[k] / d;
+ }
+ }
+ }
+ dx = fabs(w.x-s.x);
+ dy = fabs(w.y-s.y);
+ if (dx <= .5 && dy <= .5) {
+ pp->curve.vertex[i].x = w.x+x0;
+ pp->curve.vertex[i].y = w.y+y0;
+ continue;
+ }
+
+ /* the minimum was not in the unit square; now minimize quadratic
+ on boundary of square */
+ min = quadform(Q, s);
+ xmin = s.x;
+ ymin = s.y;
+
+ if (Q[0][0] == 0.0) {
+ goto fixx;
+ }
+ for (z=0; z<2; z++) { /* value of the y-coordinate */
+ w.y = s.y-0.5+z;
+ w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
+ dx = fabs(w.x-s.x);
+ cand = quadform(Q, w);
+ if (dx <= .5 && cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ fixx:
+ if (Q[1][1] == 0.0) {
+ goto corners;
+ }
+ for (z=0; z<2; z++) { /* value of the x-coordinate */
+ w.x = s.x-0.5+z;
+ w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
+ dy = fabs(w.y-s.y);
+ cand = quadform(Q, w);
+ if (dy <= .5 && cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ corners:
+ /* check four corners */
+ for (l=0; l<2; l++) {
+ for (k=0; k<2; k++) {
+ w.x = s.x-0.5+l;
+ w.y = s.y-0.5+k;
+ cand = quadform(Q, w);
+ if (cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ }
+
+ pp->curve.vertex[i].x = xmin + x0;
+ pp->curve.vertex[i].y = ymin + y0;
+ continue;
+ }
+
+ free(ctr);
+ free(dir);
+ free(q);
+ return 0;
+
+ malloc_error:
+ free(ctr);
+ free(dir);
+ free(q);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
+
+/* Always succeeds and returns 0 */
+static int smooth(privcurve_t *curve, int sign, double alphamax) {
+ int m = curve->n;
+
+ int i, j, k;
+ double dd, denom, alpha;
+ dpoint_t p2, p3, p4;
+
+ if (sign == '-') {
+ /* reverse orientation of negative paths */
+ for (i=0, j=m-1; i<j; i++, j--) {
+ dpoint_t tmp;
+ tmp = curve->vertex[i];
+ curve->vertex[i] = curve->vertex[j];
+ curve->vertex[j] = tmp;
+ }
+ }
+
+ /* examine each vertex and find its best fit */
+ for (i=0; i<m; i++) {
+ j = mod(i+1, m);
+ k = mod(i+2, m);
+ p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
+
+ denom = ddenom(curve->vertex[i], curve->vertex[k]);
+ if (denom != 0.0) {
+ dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
+ dd = fabs(dd);
+ alpha = dd>1 ? (1 - 1.0/dd) : 0;
+ alpha = alpha / 0.75;
+ } else {
+ alpha = 4/3.0;
+ }
+ curve->alpha0[j] = alpha; /* remember "original" value of alpha */
+
+ if (alpha > alphamax) { /* pointed corner */
+ curve->tag[j] = POTRACE_CORNER;
+ curve->c[j][1] = curve->vertex[j];
+ curve->c[j][2] = p4;
+ } else {
+ if (alpha < 0.55) {
+ alpha = 0.55;
+ } else if (alpha > 1) {
+ alpha = 1;
+ }
+ p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
+ p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
+ curve->tag[j] = POTRACE_CURVETO;
+ curve->c[j][0] = p2;
+ curve->c[j][1] = p3;
+ curve->c[j][2] = p4;
+ }
+ curve->alpha[j] = alpha; /* store the "cropped" value of alpha */
+ curve->beta[j] = 0.5;
+ }
+ curve->alphacurve = 1;
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 5: Curve optimization (Sec. 2.4) */
+
+/* a private type for the result of opti_penalty */
+struct opti_s {
+ double pen; /* penalty */
+ dpoint_t c[2]; /* curve parameters */
+ double t, s; /* curve parameters */
+ double alpha; /* curve parameter */
+};
+typedef struct opti_s opti_t;
+
+/* calculate best fit from i+.5 to j+.5. Assume i<j (cyclically).
+ Return 0 and set badness and parameters (alpha, beta), if
+ possible. Return 1 if impossible. */
+static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
+ int m = pp->curve.n;
+ int k, k1, k2, conv, i1;
+ double area, alpha, d, d1, d2;
+ dpoint_t p0, p1, p2, p3, pt;
+ double A, R, A1, A2, A3, A4;
+ double s, t;
+
+ /* check convexity, corner-freeness, and maximum bend < 179 degrees */
+
+ if (i==j) { /* sanity - a full loop can never be an opticurve */
+ return 1;
+ }
+
+ k = i;
+ i1 = mod(i+1, m);
+ k1 = mod(k+1, m);
+ conv = convc[k1];
+ if (conv == 0) {
+ return 1;
+ }
+ d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
+ for (k=k1; k!=j; k=k1) {
+ k1 = mod(k+1, m);
+ k2 = mod(k+2, m);
+ if (convc[k1] != conv) {
+ return 1;
+ }
+ if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
+ return 1;
+ }
+ 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) {
+ return 1;
+ }
+ }
+
+ /* the curve we're working in: */
+ p0 = pp->curve.c[mod(i,m)][2];
+ p1 = pp->curve.vertex[mod(i+1,m)];
+ p2 = pp->curve.vertex[mod(j,m)];
+ p3 = pp->curve.c[mod(j,m)][2];
+
+ /* determine its area */
+ area = areac[j] - areac[i];
+ area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
+ if (i>=j) {
+ area += areac[m];
+ }
+
+ /* find intersection o of p0p1 and p2p3. Let t,s such that o =
+ interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
+ triangle (p0,o,p3). */
+
+ A1 = dpara(p0, p1, p2);
+ A2 = dpara(p0, p1, p3);
+ A3 = dpara(p0, p2, p3);
+ /* A4 = dpara(p1, p2, p3); */
+ A4 = A1+A3-A2;
+
+ if (A2 == A1) { /* this should never happen */
+ return 1;
+ }
+
+ t = A3/(A3-A4);
+ s = A2/(A2-A1);
+ A = A2 * t / 2.0;
+
+ if (A == 0.0) { /* this should never happen */
+ return 1;
+ }
+
+ R = area / A; /* relative area */
+ alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */
+
+ res->c[0] = interval(t * alpha, p0, p1);
+ res->c[1] = interval(s * alpha, p3, p2);
+ res->alpha = alpha;
+ res->t = t;
+ res->s = s;
+
+ p1 = res->c[0];
+ p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */
+
+ res->pen = 0;
+
+ /* calculate penalty */
+ /* check tangency with edges */
+ for (k=mod(i+1,m); k!=j; k=k1) {
+ k1 = mod(k+1,m);
+ t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (t<-.5) {
+ return 1;
+ }
+ pt = bezier(t, p0, p1, p2, p3);
+ d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (d == 0.0) { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
+ if (fabs(d1) > opttolerance) {
+ return 1;
+ }
+ if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
+ return 1;
+ }
+ res->pen += sq(d1);
+ }
+
+ /* check corners */
+ for (k=i; k!=j; k=k1) {
+ k1 = mod(k+1,m);
+ t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (t<-.5) {
+ return 1;
+ }
+ pt = bezier(t, p0, p1, p2, p3);
+ d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (d == 0.0) { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
+ d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
+ d2 *= 0.75 * pp->curve.alpha[k1];
+ if (d2 < 0) {
+ d1 = -d1;
+ d2 = -d2;
+ }
+ if (d1 < d2 - opttolerance) {
+ return 1;
+ }
+ if (d1 < d2) {
+ res->pen += sq(d1 - d2);
+ }
+ }
+
+ return 0;
+}
+
+/* optimize the path p, replacing sequences of Bezier segments by a
+ single segment when possible. Return 0 on success, 1 with errno set
+ on failure. */
+static int opticurve(privpath_t *pp, double opttolerance) {
+ int m = pp->curve.n;
+ int *pt = NULL; /* pt[m+1] */
+ double *pen = NULL; /* pen[m+1] */
+ int *len = NULL; /* len[m+1] */
+ opti_t *opt = NULL; /* opt[m+1] */
+ int om;
+ int i,j,r;
+ opti_t o;
+ dpoint_t p0;
+ int i1;
+ double area;
+ double alpha;
+ double *s = NULL;
+ double *t = NULL;
+
+ int *convc = NULL; /* conv[m]: pre-computed convexities */
+ double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
+
+ SAFE_MALLOC(pt, m+1, int);
+ SAFE_MALLOC(pen, m+1, double);
+ SAFE_MALLOC(len, m+1, int);
+ SAFE_MALLOC(opt, m+1, opti_t);
+ SAFE_MALLOC(convc, m, int);
+ SAFE_MALLOC(areac, m+1, double);
+
+ /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
+ for (i=0; i<m; i++) {
+ if (pp->curve.tag[i] == POTRACE_CURVETO) {
+ convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
+ } else {
+ convc[i] = 0;
+ }
+ }
+
+ /* pre-calculate areas */
+ area = 0.0;
+ areac[0] = 0.0;
+ p0 = pp->curve.vertex[0];
+ for (i=0; i<m; i++) {
+ i1 = mod(i+1, m);
+ if (pp->curve.tag[i1] == POTRACE_CURVETO) {
+ alpha = pp->curve.alpha[i1];
+ area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
+ area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
+ }
+ areac[i+1] = area;
+ }
+
+ pt[0] = -1;
+ pen[0] = 0;
+ len[0] = 0;
+
+ /* Fixme: we always start from a fixed point -- should find the best
+ curve cyclically ### */
+
+ for (j=1; j<=m; j++) {
+ /* calculate best path from 0 to j */
+ pt[j] = j-1;
+ pen[j] = pen[j-1];
+ len[j] = len[j-1]+1;
+
+ for (i=j-2; i>=0; i--) {
+ r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
+ if (r) {
+ break;
+ }
+ if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
+ pt[j] = i;
+ pen[j] = pen[i] + o.pen;
+ len[j] = len[i] + 1;
+ opt[j] = o;
+ }
+ }
+ }
+ om = len[m];
+ r = privcurve_init(&pp->ocurve, om);
+ if (r) {
+ goto malloc_error;
+ }
+ SAFE_MALLOC(s, om, double);
+ SAFE_MALLOC(t, om, double);
+
+ j = m;
+ for (i=om-1; i>=0; i--) {
+ if (pt[j]==j-1) {
+ pp->ocurve.tag[i] = pp->curve.tag[mod(j,m)];
+ pp->ocurve.c[i][0] = pp->curve.c[mod(j,m)][0];
+ pp->ocurve.c[i][1] = pp->curve.c[mod(j,m)][1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
+ pp->ocurve.vertex[i] = pp->curve.vertex[mod(j,m)];
+ pp->ocurve.alpha[i] = pp->curve.alpha[mod(j,m)];
+ pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j,m)];
+ pp->ocurve.beta[i] = pp->curve.beta[mod(j,m)];
+ s[i] = t[i] = 1.0;
+ } else {
+ pp->ocurve.tag[i] = POTRACE_CURVETO;
+ pp->ocurve.c[i][0] = opt[j].c[0];
+ pp->ocurve.c[i][1] = opt[j].c[1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
+ pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
+ pp->ocurve.alpha[i] = opt[j].alpha;
+ pp->ocurve.alpha0[i] = opt[j].alpha;
+ s[i] = opt[j].s;
+ t[i] = opt[j].t;
+ }
+ j = pt[j];
+ }
+
+ /* calculate beta parameters */
+ for (i=0; i<om; i++) {
+ i1 = mod(i+1,om);
+ pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
+ }
+ pp->ocurve.alphacurve = 1;
+
+ free(pt);
+ free(pen);
+ free(len);
+ free(opt);
+ free(s);
+ free(t);
+ free(convc);
+ free(areac);
+ return 0;
+
+ malloc_error:
+ free(pt);
+ free(pen);
+ free(len);
+ free(opt);
+ free(s);
+ free(t);
+ free(convc);
+ free(areac);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+double plotpolygon(privpath_t *pp,FILE* f,double scale)
+{
+ int i;
+ int m = pp->m;
+ if(!m) return 0;
+ int *po = pp->po;
+ int n = pp->len;
+ point_t *pt = pp->pt;
+ int x0 = pp->x0;
+ int y0 = pp->y0;
+ //double scale=1.0/dpi;
+ double dm=0;
+ fprintf(f,"G0 X%f Y%f (start point)\n",pt[po[0]].x*scale,pt[po[0]].y*scale);
+ fprintf(f,"G1 Z#101\n");
+ for (i=1; i<m; i++) {
+ fprintf(f,"G1 X%f Y%f\n",pt[po[i]].x*scale,pt[po[i]].y*scale);
+ dm+=sqrt((pt[po[i]].x-pt[po[i-1]].x)*scale*(pt[po[i]].x-pt[po[i-1]].x)*scale+\
+ (pt[po[i]].y-pt[po[i-1]].y)*scale*(pt[po[i]].y-pt[po[i-1]].y)*scale);
+ }
+ fprintf(f,"G1 X%f Y%f\n",pt[po[0]].x*scale,pt[po[0]].y*scale);
+ fprintf(f,"G0 Z#100\n");
+ dm+=sqrt((pt[po[m-1]].x-pt[po[0]].x)*scale*(pt[po[m-1]].x-pt[po[0]].x)*scale+\
+ (pt[po[m-1]].y-pt[po[0]].y)*scale*(pt[po[m-1]].y-pt[po[0]].y)*scale);
+ fprintf(f,"(polygon end, distance %.2f)\n",dm);
+ return dm;
+}
+
+#define TRY(x) if (x) goto try_error
+
+/* return distance on success, -1 on error with errno set. */
+double process_path(path_t *plist, const potrace_param_t *param,const potrace_bitmap_t *bm,FILE *f,double scale) {
+ path_t *p;
+ double nn = 0, cn = 0;
+ double dm=0;
+ int n=0;
+ /* call downstream function with each path */
+ list_forall (p, plist) {
+ TRY(calc_sums(p->priv));
+ TRY(calc_lon(p->priv));
+ TRY(bestpolygon(p->priv));
+ TRY(adjust_vertices(p->priv));
+ fprintf(f,"(polygon %d)\n",++n);
+ dm+=plotpolygon(p->priv,f,scale);
+/* No need to extract curves
+ TRY(smooth(&p->priv->curve, p->sign, param->alphamax));
+ if (param->opticurve) {
+ TRY(opticurve(p->priv, param->opttolerance));
+ p->priv->fcurve = &p->priv->ocurve;
+ } else {
+ p->priv->fcurve = &p->priv->curve;
+ }
+ privcurve_to_curve(p->priv->fcurve, &p->curve);*/
+ }
+// fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm);
+ return dm;
+
+ try_error:
+ return -1;
+}
diff --git a/src/hid/gcode/trace.h b/src/hid/gcode/trace.h
new file mode 100644
index 0000000..4a9683c
--- /dev/null
+++ b/src/hid/gcode/trace.h
@@ -0,0 +1,14 @@
+/* Copyright (C) 2001-2007 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* $Id: trace.h 147 2007-04-09 00:44:09Z selinger $ */
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include "potracelib.h"
+
+double process_path(path_t *plist, const potrace_param_t *param,const potrace_bitmap_t *bm,FILE *f,double scale);
+
+#endif /* TRACE_H */
commit b4ca96d312884a8bc2314e490c2c957ab590b427
Author: Dan McMahill <dan@xxxxxxxxxxxx>
Commit: Dan McMahill <dan@xxxxxxxxxxxx>
When building the docs have configure check for epsf.tex being in the TeX
installation. Problem noted by Kai-Martin Knaak and the method for checking
suggested by Peter Clifton.
diff --git a/configure.ac b/configure.ac
index 415c400..d5578fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -224,6 +224,31 @@ Alternatively, you can disable building the documentation with
--disable-doc.
])
fi
+
+
+ AC_PATH_PROG([KPSEWHICH], [kpsewhich], [no])
+ if test "X$KPSEWHICH" = "Xno"; then
+ AC_MSG_ERROR([You have requested a build
+of the documentation. For this to work, you must have a functional install of
+TeX and LaTeX. kpsewhich is part of TeX.
+Alternatively, you can disable building the documentation with
+--disable-doc.])
+ fi
+
+ AC_MSG_CHECKING([If your TeX installation contains epsf.tex])
+ f=`$KPSEWHICH epsf.tex`
+ if test $? -eq 0 ; then
+ AC_MSG_RESULT([yes ($f)])
+ else
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([You have requested a build
+of the documentation. For this to work, you must have a functional install of
+TeX and LaTeX that includes epsf.tex. On some linux distributions this is
+part of the texlive-generic-recommended package.
+Alternatively, you can disable building the documentation with
+--disable-doc.])
+ fi
+
fi
##########################################################################
commit 5c7cc398ffc8f646d68eada8d6cd74dff4bceb85
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix test for whether to rebuild the shipped pcblib-newlib library
${top_srcdir} is a Makefile variable, we need $srcdir in configure.ac
diff --git a/configure.ac b/configure.ac
index 9c14582..415c400 100644
--- a/configure.ac
+++ b/configure.ac
@@ -857,7 +857,7 @@ AM_CONDITIONAL(PNG_PREVIEW, test x$enable_m4lib_png = xyes)
build_pcblib_newlib=no
if test "$pcb_sources" = "tarball" ; then
AC_MSG_CHECKING([If pcblib-newlib was built with png previews])
- stamp=${top_srcdir}/lib/pcblib-newlib.stamp
+ stamp=$srcdir/lib/pcblib-newlib.stamp
if test ! -f ${stamp} ; then
AC_MSG_RESULT([unknown, missing ${stamp}])
build_pcblib_newlib=yes
commit ca1af54230754bde0cda442a6d966a4aa1a3e6b4
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix make distcheck by removing regenerated newlib footprints
The generated newlib files need to be removed by make distclean
if they are being updated by the build process. If the files aren't
being updated, we should not delete them as they were originally
distributed with the source tarball.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 95be997..ae1b485 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -57,6 +57,11 @@ ${NEWLIB}.stamp : footprint.pcb ${NEWLIB_DEPS}
${PREVIEW} --pcb "${PCB}" --awk "${AWK}"
echo '${PREVIEW_MSG}' > $@
+# Remove any rebuilt footprints
+if BUILD_PCBLIB_NEWLIB
+distclean-local:
+ rm -fr ${NEWLIB}
+endif
install-data-local: ${NEWLIB}.stamp
if test -d ${NEWLIB} ; then \
commit 2eb25f8f7cc9584528b2caa54a6097fc17fcec8b
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>
Fix distribution of gnet-pcbfwd.scm in the dist tarball
Use the dist_ prefix to make this simple, so our installed
targets are now listed in dist_..._DATA, rather than ..._DATA
and EXTRA_DIST.
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 002fecc..d9665a9 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -5,12 +5,10 @@
## in ${exec_prefix}/bin (by bin_SCRIPTS and bin_PROGRAMS)
toolsdir= $(pkgdatadir)/tools
-tools_DATA= ${TOOLS}
+dist_tools_DATA= ${TOOLS}
scmdatadir = $(datadir)/gEDA/scheme
-scmdata_DATA = $(DIST_SCM)
-
-EXTRA_DIST= ${TOOLS}
+dist_scmdata_DATA = $(DIST_SCM)
bin_SCRIPTS= \
MergePCBPS \
commit d2a7382d1fcecd85a1feee399543a3e89fe1ef6b
Author: DJ Delorie <dj@xxxxxxxxxxx>
Commit: DJ Delorie <dj@xxxxxxxxxxx>
Allow empty attribute values.
The STRING token is NULL when an empty string is indicated, but
empty attributes are different than missing attributes, so if a STRING
is NULL, store an empty string instead.
diff --git a/src/parse_y.y b/src/parse_y.y
index 646ef77..bbb7255 100644
--- a/src/parse_y.y
+++ b/src/parse_y.y
@@ -1878,7 +1878,7 @@ attributes : attribute
attribute
: T_ATTRIBUTE '(' STRING STRING ')'
{
- CreateNewAttribute (attr_list, $3, $4);
+ CreateNewAttribute (attr_list, $3, $4 ? $4 : "");
SaveFree ($3);
SaveFree ($4);
}
_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs