chiark / gitweb /
svg-prep-dxf: copy from private repo f0cc4e6f4db54b4c59660d46330ecb3e735ce009
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 26 Feb 2018 23:34:24 +0000 (23:34 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 26 Feb 2018 23:34:24 +0000 (23:34 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
svg-prep-dxf [new file with mode: 0755]

diff --git a/svg-prep-dxf b/svg-prep-dxf
new file mode 100755 (executable)
index 0000000..9f101f3
--- /dev/null
@@ -0,0 +1,175 @@
+#!/bin/bash
+us=svg-prep-dxf
+usage () { cat <<END
+usage: $us [--flatness=VALUE] IN.svg OUT.dxf
+
+Turns a stroked path into its outline path; "union"s it (so that it
+does not self-intersect); approximates its bezier curves with line
+segments; and produces a dxf for openscad.
+END
+}
+# Copyright 2016 Ian Jackson
+#
+# 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.
+#
+# As a special exception, you have permission to link this program
+# with the CGAL library and distribute executables, as long as you
+# follow the requirements of the GNU GPL in regard to all of the
+# software in the executable aside from CGAL.
+#
+# 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.
+
+set -e
+
+fail () { echo >&2 "svg-dxf-prep: $*"; exit 1; }
+badusage () { usage >&2; exit 1; }
+
+flatness=0.01
+# ^ this number seems to work reasonably well
+#   although maybe it should be adjusted?
+
+while true; do
+    case "$1" in
+    --flatness=*)
+       flatness="${1#*=}"
+       ;;
+    -*)
+       badusage
+       ;;
+    *)
+       break
+       ;;
+    esac
+    shift
+done
+
+case "$#" in
+2)  ;;
+*)  badusage ;;
+esac
+
+source=$1
+dest=$2
+
+case "$source" in
+*.svg) ;;
+*)  badusage ;;
+esac
+
+case "$dest" in
+*.dxf) ;;
+*)  badusage ;;
+esac
+
+tmpdir="$(dirname "$dest")/.$(basename "$dest").tmpdir"
+rm -rf -- "$tmpdir"
+mkdir -- "$tmpdir"
+
+case "$tmpdir" in
+/*)  abstmpdir="$tmpdir" ;;
+*)   abstmpdir="$PWD/$tmpdir" ;;
+esac
+
+cp -- "$source" "$tmpdir/t.svg"
+
+# startx seems to send "client" stdout/stderr somewhere hopeless
+exec 4>&2
+
+baseextdir=$(inkscape -x)
+ourid=uk.org.greenend.chiark.ijackson.swirly.flatten
+
+# inkscape doesn't provide a way to specify a per-invocation
+# extension directory, but it does look in $HOME.
+# Anyway, we're going to want a fresh HOME for startx.
+ourxd="$tmpdir"/.config/inkscape/extensions
+mkdir -p "$ourxd"
+mkdir -p "$tmpdir/.local/share" # inkscape complains otherwise, wtf
+
+# Putting the absolute path in the XML doesn't seem to work:
+# inkscape complains that this "dependency" (implicit, apparently)
+# is not satisfied.
+# I'm not sure why this is, but this does work:
+ln -s -- "$baseextdir/flatten.py" "$ourxd"
+
+xmlstarlet \
+ed \
+ -N ie=http://www.inkscape.org/namespace/inkscape/extension \
+ -u "/ie:inkscape-extension/ie:_name" -v "Our Flatten Beziers" \
+ -u "/ie:inkscape-extension/ie:id" -v $ourid \
+ -d '/ie:inkscape-extension/ie:dependency' \
+ -u '/ie:inkscape-extension/ie:param[@name="flatness"]' -v $flatness \
+ "$baseextdir"/flatten.inx \
+ >"$ourxd"/our-flatten.inx
+# known bugs with this approach:
+#  - we rely on the .inx filename
+#  - we rely on flatten.py being in the extensions/ directory
+#    and called exactly that
+#  - we drop the dependencies rather than editing them
+
+cat <<'END' >"$tmpdir/run-inkscape"
+#!/bin/sh
+exec >&4 2>&4
+echo
+printf "running inkscape to transform and clean up..."
+cd "$HOME"
+inkscape \
+ --with-gui \
+ t.svg \
+ --verb=EditSelectAll \
+ --verb=StrokeToPath \
+ --verb=ToolNode \
+ --verb=EditSelectAll \
+ --verb=SelectionUnion \
+ --verb=EditSelectAll \
+ --verb=uk.org.greenend.chiark.ijackson.swirly.flatten.noprefs \
+ --verb=FileSave \
+ --verb=FileQuit \
+
+echo done.
+echo
+END
+chmod +x "$tmpdir"/run-inkscape
+
+cat <<END
+
+Expect some complaints from xinit, for example
+  about XFree86_VT property
+  lost connection
+  file descriptors for console
+END
+
+HOME="$abstmpdir" \
+/usr/bin/startx \
+ "$abstmpdir"/run-inkscape \
+ -- \
+ `type -p Xvfb`
+
+# It's awkward to get inkscape to save as DXF noninteractively.
+# And inkscape doesn't seem to like to exit if I try to export
+# from the "interactive" one.
+
+# But anyway inkscape DXF is just made with pstoedit.  So save as SVG,
+# and then do a separate inkscape run to convert EPS, and run pstoedit
+# to make the DXF.
+
+inkscape \
+ -f "$tmpdir"/t.svg \
+ -E "$tmpdir"/t.eps \
+
+pstoedit -dt -f 'dxf:-polyaslines -mm' \
+ "$tmpdir"/t.eps \
+ "$tmpdir/"t.dxf
+
+mv -- "$tmpdir"/t.dxf "$dest"
+
+echo
+printf "$us: success, wrote %s\n" "$dest"
+echo
+
+exit 0