chiark / gitweb /
sleepphone-cable-box: reinforce keeper
[reprap-play.git] / svg-prep-dxf
1 #!/bin/bash
2 us=svg-prep-dxf
3 usage () { cat <<END
4 usage: $us [--flatness=VALUE] IN.svg OUT.dxf
5
6 Turns a stroked path into its outline path; "union"s it (so that it
7 does not self-intersect); approximates its bezier curves with line
8 segments; and produces a dxf for openscad.
9 END
10 }
11 # Copyright 2016 Ian Jackson
12 #
13 # This program is free software; you can redistribute it and/or modify it
14 # under the terms of the GNU General Public License as published by the Free
15 # Software Foundation; either version 2 of the License, or (at your option)
16 # any later version.
17 #
18 # As a special exception, you have permission to link this program
19 # with the CGAL library and distribute executables, as long as you
20 # follow the requirements of the GNU GPL in regard to all of the
21 # software in the executable aside from CGAL.
22 #
23 # This program is distributed in the hope that it will be useful, but WITHOUT
24 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
26 # more details.
27
28 set -e
29
30 fail () { echo >&2 "svg-dxf-prep: $*"; exit 1; }
31 badusage () { usage >&2; exit 1; }
32
33 flatness=0.01
34 # ^ this number seems to work reasonably well
35 #   although maybe it should be adjusted?
36
37 while true; do
38     case "$1" in
39     --flatness=*)
40         flatness="${1#*=}"
41         ;;
42     -*)
43         badusage
44         ;;
45     *)
46         break
47         ;;
48     esac
49     shift
50 done
51
52 case "$#" in
53 2)  ;;
54 *)  badusage ;;
55 esac
56
57 source=$1
58 dest=$2
59
60 case "$source" in
61 *.svg) ;;
62 *)  badusage ;;
63 esac
64
65 case "$dest" in
66 *.dxf) ;;
67 *)  badusage ;;
68 esac
69
70 tmpdir="$(dirname "$dest")/.$(basename "$dest").tmpdir"
71 rm -rf -- "$tmpdir"
72 mkdir -- "$tmpdir"
73
74 case "$tmpdir" in
75 /*)  abstmpdir="$tmpdir" ;;
76 *)   abstmpdir="$PWD/$tmpdir" ;;
77 esac
78
79 cp -- "$source" "$tmpdir/t.svg"
80
81 # startx seems to send "client" stdout/stderr somewhere hopeless
82 exec 4>&2
83
84 baseextdir=$(inkscape -x)
85 ourid=uk.org.greenend.chiark.ijackson.swirly.flatten
86
87 # inkscape doesn't provide a way to specify a per-invocation
88 # extension directory, but it does look in $HOME.
89 # Anyway, we're going to want a fresh HOME for startx.
90 ourxd="$tmpdir"/.config/inkscape/extensions
91 mkdir -p "$ourxd"
92 mkdir -p "$tmpdir/.local/share" # inkscape complains otherwise, wtf
93
94 # Putting the absolute path in the XML doesn't seem to work:
95 # inkscape complains that this "dependency" (implicit, apparently)
96 # is not satisfied.
97 # I'm not sure why this is, but this does work:
98 ln -s -- "$baseextdir/flatten.py" "$ourxd"
99
100 xmlstarlet \
101 ed \
102  -N ie=http://www.inkscape.org/namespace/inkscape/extension \
103  -u "/ie:inkscape-extension/ie:_name" -v "Our Flatten Beziers" \
104  -u "/ie:inkscape-extension/ie:id" -v $ourid \
105  -d '/ie:inkscape-extension/ie:dependency' \
106  -u '/ie:inkscape-extension/ie:param[@name="flatness"]' -v $flatness \
107  "$baseextdir"/flatten.inx \
108  >"$ourxd"/our-flatten.inx
109 # known bugs with this approach:
110 #  - we rely on the .inx filename
111 #  - we rely on flatten.py being in the extensions/ directory
112 #    and called exactly that
113 #  - we drop the dependencies rather than editing them
114
115 cat <<'END' >"$tmpdir/run-inkscape"
116 #!/bin/sh
117 exec >&4 2>&4
118 echo
119 printf "running inkscape to transform and clean up..."
120 cd "$HOME"
121 inkscape \
122  --with-gui \
123  t.svg \
124  --verb=ToolNode \
125  --verb=EditSelectAll \
126  --verb=SelectionUnGroup \
127  --verb=EditSelectAll \
128  --verb=StrokeToPath \
129  --verb=ToolNode \
130  --verb=EditSelectAll \
131  --verb=SelectionUnion \
132  --verb=EditSelectAll \
133  --verb=uk.org.greenend.chiark.ijackson.swirly.flatten.noprefs \
134  --verb=FileSave \
135  --verb=FileQuit \
136
137 echo done.
138 echo
139 END
140 chmod +x "$tmpdir"/run-inkscape
141
142 cat <<END
143
144 Expect some complaints from xinit, for example
145   about XFree86_VT property
146   lost connection
147   file descriptors for console
148 END
149
150 HOME="$abstmpdir" \
151 /usr/bin/startx \
152  "$abstmpdir"/run-inkscape \
153  -- \
154  `type -p Xvfb`
155
156 # It's awkward to get inkscape to save as DXF noninteractively.
157 # And inkscape doesn't seem to like to exit if I try to export
158 # from the "interactive" one.
159
160 # But anyway inkscape DXF is just made with pstoedit.  So save as SVG,
161 # and then do a separate inkscape run to convert EPS, and run pstoedit
162 # to make the DXF.
163
164 inkscape --export-area-page \
165  -f "$tmpdir"/t.svg \
166  -E "$tmpdir"/t.eps \
167
168 pstoedit -dt -f 'dxf:-polyaslines -mm' \
169  "$tmpdir"/t.eps \
170  "$tmpdir/"t.dxf
171
172 mv -- "$tmpdir"/t.dxf "$dest"
173
174 echo
175 printf "$us: success, wrote %s\n" "$dest"
176 echo
177
178 exit 0