From b2eb56076d47af08a11e10fa53446a00b849a13c Mon Sep 17 00:00:00 2001
From: jaseg <git@jaseg.net>
Date: Thu, 26 Sep 2019 19:45:54 +0200
Subject: Pogojig mostly done: KiCAD export works

---
 support/inkscape/__init__.py        |   0
 support/inkscape/__main__.py        |  64 ----
 support/inkscape/bezmisc.py         | 273 -----------------
 support/inkscape/cspsubdiv.py       |  37 ---
 support/inkscape/cubicsuperpath.py  | 174 -----------
 support/inkscape/dxf_footer.txt     |  62 ----
 support/inkscape/dxf_header.txt     | 580 ------------------------------------
 support/inkscape/effect.py          | 280 -----------------
 support/inkscape/ffgeom.py          | 141 ---------
 support/inkscape/inkex.py           | 370 -----------------------
 support/inkscape/inkscape.py        | 136 ---------
 support/inkscape/simplepath.py      | 212 -------------
 support/inkscape/simpletransform.py | 241 ---------------
 13 files changed, 2570 deletions(-)
 delete mode 100644 support/inkscape/__init__.py
 delete mode 100644 support/inkscape/__main__.py
 delete mode 100755 support/inkscape/bezmisc.py
 delete mode 100755 support/inkscape/cspsubdiv.py
 delete mode 100755 support/inkscape/cubicsuperpath.py
 delete mode 100644 support/inkscape/dxf_footer.txt
 delete mode 100644 support/inkscape/dxf_header.txt
 delete mode 100644 support/inkscape/effect.py
 delete mode 100755 support/inkscape/ffgeom.py
 delete mode 100755 support/inkscape/inkex.py
 delete mode 100644 support/inkscape/inkscape.py
 delete mode 100755 support/inkscape/simplepath.py
 delete mode 100755 support/inkscape/simpletransform.py

(limited to 'support/inkscape')

diff --git a/support/inkscape/__init__.py b/support/inkscape/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/support/inkscape/__main__.py b/support/inkscape/__main__.py
deleted file mode 100644
index 29ac745..0000000
--- a/support/inkscape/__main__.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import os, shutil
-from lib import util
-from . import effect, inkscape
-
-
-def _unfuck_svg_document(temp_svg_path):
-    """
-    Unfucks an SVG document so is can be processed by the better_dxf_export
-    plugin (or what's left of it).
-    """
-    command_line = inkscape.InkscapeCommandLine(temp_svg_path)
-    layers = command_line.layers
-    
-    command_line.apply_to_document('LayerUnlockAll', 'LayerShowAll')
-    
-    layer_copies = []
-    
-    for i in layers:
-        layer_copy = command_line.duplicate_layer(i)
-        layer_copies.append(layer_copy)
-        
-        command_line.apply_to_layer_content(layer_copy, 'ObjectToPath')
-        command_line.apply_to_layer_content(layer_copy, 'SelectionUnGroup')
-        
-        if not i.use_paths:
-            command_line.apply_to_layer_content(layer_copy, 'StrokeToPath')
-            command_line.apply_to_layer_content(layer_copy, 'SelectionUnion')
-    
-    for original, copy in zip(layers, layer_copies):
-        command_line.clear_layer(original)
-        command_line.move_content(copy, original)
-        command_line.delete_layer(copy)
-    
-    command_line.apply_to_document('FileSave', 'FileClose', 'FileQuit')
-    
-    command_line.run()
-
-
-@util.main
-def main(in_path, out_path):
-    try:
-        _, out_suffix = os.path.splitext(out_path)
-        
-        effect.ExportEffect.check_document_units(in_path)
-        
-        with util.TemporaryDirectory() as temp_dir:
-            temp_svg_path = os.path.join(temp_dir, os.path.basename(in_path))
-            
-            shutil.copyfile(in_path, temp_svg_path)
-            
-            _unfuck_svg_document(temp_svg_path)
-            
-            export_effect = effect.ExportEffect()
-            export_effect.affect(args=[temp_svg_path], output=False)
-            
-        with open(out_path, 'w') as file:
-            if out_suffix == '.dxf':
-                export_effect.write_dxf(file)
-            elif out_suffix == '.asy':
-                export_effect.write_asy(file)
-            else:
-                raise Exception('Unknown file type: {}'.format(out_suffix))
-    except util.UserError as e:
-        raise util.UserError('While processing {}: {}', in_path, e)
diff --git a/support/inkscape/bezmisc.py b/support/inkscape/bezmisc.py
deleted file mode 100755
index b7f5429..0000000
--- a/support/inkscape/bezmisc.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/env python
-'''
-Copyright (C) 2010 Nick Drobchenko, nick@cnc-club.ru
-Copyright (C) 2005 Aaron Spike, aaron@ekips.org
-
-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-'''
-
-import math, cmath
-
-def rootWrapper(a,b,c,d):
-    if a:
-        # Monics formula see http://en.wikipedia.org/wiki/Cubic_function#Monic_formula_of_roots
-        a,b,c = (b/a, c/a, d/a)
-        m = 2.0*a**3 - 9.0*a*b + 27.0*c
-        k = a**2 - 3.0*b
-        n = m**2 - 4.0*k**3
-        w1 = -.5 + .5*cmath.sqrt(-3.0)
-        w2 = -.5 - .5*cmath.sqrt(-3.0)
-        if n < 0:
-            m1 = pow(complex((m+cmath.sqrt(n))/2),1./3)
-            n1 = pow(complex((m-cmath.sqrt(n))/2),1./3)
-        else:
-            if m+math.sqrt(n) < 0:
-                m1 = -pow(-(m+math.sqrt(n))/2,1./3)
-            else:
-                m1 = pow((m+math.sqrt(n))/2,1./3)
-            if m-math.sqrt(n) < 0:
-                n1 = -pow(-(m-math.sqrt(n))/2,1./3)
-            else:
-                n1 = pow((m-math.sqrt(n))/2,1./3)
-        x1 = -1./3 * (a + m1 + n1)
-        x2 = -1./3 * (a + w1*m1 + w2*n1)
-        x3 = -1./3 * (a + w2*m1 + w1*n1)
-        return (x1,x2,x3)
-    elif b:
-        det=c**2.0-4.0*b*d
-        if det:
-            return (-c+cmath.sqrt(det))/(2.0*b),(-c-cmath.sqrt(det))/(2.0*b)
-        else:
-            return -c/(2.0*b),
-    elif c:
-        return 1.0*(-d/c),
-    return ()
-
-def bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
-    #parametric bezier
-    x0=bx0
-    y0=by0
-    cx=3*(bx1-x0)
-    bx=3*(bx2-bx1)-cx
-    ax=bx3-x0-cx-bx
-    cy=3*(by1-y0)
-    by=3*(by2-by1)-cy
-    ay=by3-y0-cy-by
-
-    return ax,ay,bx,by,cx,cy,x0,y0
-    #ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-
-def linebezierintersect(((lx1,ly1),(lx2,ly2)),((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3))):
-    #parametric line
-    dd=lx1
-    cc=lx2-lx1
-    bb=ly1
-    aa=ly2-ly1
-
-    if aa:
-        coef1=cc/aa
-        coef2=1
-    else:
-        coef1=1
-        coef2=aa/cc
-
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    #cubic intersection coefficients
-    a=coef1*ay-coef2*ax
-    b=coef1*by-coef2*bx
-    c=coef1*cy-coef2*cx
-    d=coef1*(y0-bb)-coef2*(x0-dd)
-
-    roots = rootWrapper(a,b,c,d)
-    retval = []
-    for i in roots:
-        if type(i) is complex and i.imag==0:
-            i = i.real
-        if type(i) is not complex and 0<=i<=1:
-            retval.append(bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),i))
-    return retval
-
-def bezierpointatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    x=ax*(t**3)+bx*(t**2)+cx*t+x0
-    y=ay*(t**3)+by*(t**2)+cy*t+y0
-    return x,y
-
-def bezierslopeatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    dx=3*ax*(t**2)+2*bx*t+cx
-    dy=3*ay*(t**2)+2*by*t+cy
-    return dx,dy
-
-def beziertatslope(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),(dy,dx)):
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    #quadratic coefficents of slope formula
-    if dx:
-        slope = 1.0*(dy/dx)
-        a=3*ay-3*ax*slope
-        b=2*by-2*bx*slope
-        c=cy-cx*slope
-    elif dy:
-        slope = 1.0*(dx/dy)
-        a=3*ax-3*ay*slope
-        b=2*bx-2*by*slope
-        c=cx-cy*slope
-    else:
-        return []
-
-    roots = rootWrapper(0,a,b,c)
-    retval = []
-    for i in roots:
-        if type(i) is complex and i.imag==0:
-            i = i.real
-        if type(i) is not complex and 0<=i<=1:
-            retval.append(i)
-    return retval
-
-def tpoint((x1,y1),(x2,y2),t):
-    return x1+t*(x2-x1),y1+t*(y2-y1)
-def beziersplitatt(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)),t):
-    m1=tpoint((bx0,by0),(bx1,by1),t)
-    m2=tpoint((bx1,by1),(bx2,by2),t)
-    m3=tpoint((bx2,by2),(bx3,by3),t)
-    m4=tpoint(m1,m2,t)
-    m5=tpoint(m2,m3,t)
-    m=tpoint(m4,m5,t)
-    
-    return ((bx0,by0),m1,m4,m),(m,m5,m3,(bx3,by3))
-
-'''
-Approximating the arc length of a bezier curve
-according to <http://www.cit.gu.edu.au/~anthony/info/graphics/bezier.curves>
-
-if:
-    L1 = |P0 P1| +|P1 P2| +|P2 P3| 
-    L0 = |P0 P3|
-then: 
-    L = 1/2*L0 + 1/2*L1
-    ERR = L1-L0
-ERR approaches 0 as the number of subdivisions (m) increases
-    2^-4m
-
-Reference:
-Jens Gravesen <gravesen@mat.dth.dk>
-"Adaptive subdivision and the length of Bezier curves"
-mat-report no. 1992-10, Mathematical Institute, The Technical
-University of Denmark. 
-'''
-def pointdistance((x1,y1),(x2,y2)):
-    return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
-def Gravesen_addifclose(b, len, error = 0.001):
-    box = 0
-    for i in range(1,4):
-        box += pointdistance(b[i-1], b[i])
-    chord = pointdistance(b[0], b[3])
-    if (box - chord) > error:
-        first, second = beziersplitatt(b, 0.5)
-        Gravesen_addifclose(first, len, error)
-        Gravesen_addifclose(second, len, error)
-    else:
-        len[0] += (box / 2.0) + (chord / 2.0)
-def bezierlengthGravesen(b, error = 0.001):
-    len = [0]
-    Gravesen_addifclose(b, len, error)
-    return len[0]
-
-# balf = Bezier Arc Length Function
-balfax,balfbx,balfcx,balfay,balfby,balfcy = 0,0,0,0,0,0
-def balf(t):
-    retval = (balfax*(t**2) + balfbx*t + balfcx)**2 + (balfay*(t**2) + balfby*t + balfcy)**2
-    return math.sqrt(retval)
-
-def Simpson(f, a, b, n_limit, tolerance):
-    n = 2
-    multiplier = (b - a)/6.0
-    endsum = f(a) + f(b)
-    interval = (b - a)/2.0
-    asum = 0.0
-    bsum = f(a + interval)
-    est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum))
-    est0 = 2.0 * est1
-    #print multiplier, endsum, interval, asum, bsum, est1, est0
-    while n < n_limit and abs(est1 - est0) > tolerance:
-        n *= 2
-        multiplier /= 2.0
-        interval /= 2.0
-        asum += bsum
-        bsum = 0.0
-        est0 = est1
-        for i in xrange(1, n, 2):
-            bsum += f(a + (i * interval))
-            est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum))
-    #print multiplier, endsum, interval, asum, bsum, est1, est0
-    return est1
-
-def bezierlengthSimpson(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), tolerance = 0.001):
-    global balfax,balfbx,balfcx,balfay,balfby,balfcy
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
-    return Simpson(balf, 0.0, 1.0, 4096, tolerance)
-
-def beziertatlength(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), l = 0.5, tolerance = 0.001):
-    global balfax,balfbx,balfcx,balfay,balfby,balfcy
-    ax,ay,bx,by,cx,cy,x0,y0=bezierparameterize(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)))
-    balfax,balfbx,balfcx,balfay,balfby,balfcy = 3*ax,2*bx,cx,3*ay,2*by,cy
-    t = 1.0
-    tdiv = t
-    curlen = Simpson(balf, 0.0, t, 4096, tolerance)
-    targetlen = l * curlen
-    diff = curlen - targetlen
-    while abs(diff) > tolerance:
-        tdiv /= 2.0
-        if diff < 0:
-            t += tdiv
-        else:
-            t -= tdiv            
-        curlen = Simpson(balf, 0.0, t, 4096, tolerance)
-        diff = curlen - targetlen
-    return t
-
-#default bezier length method
-bezierlength = bezierlengthSimpson
-
-if __name__ == '__main__':
-    #print linebezierintersect(((,),(,)),((,),(,),(,),(,)))
-    #print linebezierintersect(((0,1),(0,-1)),((-1,0),(-.5,0),(.5,0),(1,0)))
-    tol = 0.00000001
-    curves = [((0,0),(1,5),(4,5),(5,5)),
-            ((0,0),(0,0),(5,0),(10,0)),
-            ((0,0),(0,0),(5,1),(10,0)),
-            ((-10,0),(0,0),(10,0),(10,10)),
-            ((15,10),(0,0),(10,0),(-5,10))]
-    '''
-    for curve in curves:
-        timing.start()
-        g = bezierlengthGravesen(curve,tol)
-        timing.finish()
-        gt = timing.micro()
-
-        timing.start()
-        s = bezierlengthSimpson(curve,tol)
-        timing.finish()
-        st = timing.micro()
-
-        print g, gt
-        print s, st
-    '''
-    for curve in curves:
-        print beziertatlength(curve,0.5)
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/cspsubdiv.py b/support/inkscape/cspsubdiv.py
deleted file mode 100755
index c34236a..0000000
--- a/support/inkscape/cspsubdiv.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-from bezmisc import *
-from ffgeom import *
-
-def maxdist(((p0x,p0y),(p1x,p1y),(p2x,p2y),(p3x,p3y))):
-    p0 = Point(p0x,p0y)
-    p1 = Point(p1x,p1y)
-    p2 = Point(p2x,p2y)
-    p3 = Point(p3x,p3y)
-
-    s1 = Segment(p0,p3)
-    return max(s1.distanceToPoint(p1),s1.distanceToPoint(p2))
-    
-
-def cspsubdiv(csp,flat):
-    for sp in csp:
-        subdiv(sp,flat)
-
-def subdiv(sp,flat,i=1):
-    while i < len(sp):
-        p0 = sp[i-1][1]
-        p1 = sp[i-1][2]
-        p2 = sp[i][0]
-        p3 = sp[i][1]
-        
-        b = (p0,p1,p2,p3)
-        m = maxdist(b)
-        if m <= flat:
-            i += 1
-        else:
-            one, two = beziersplitatt(b,0.5)
-            sp[i-1][2] = one[1]
-            sp[i][0] = two[2]
-            p = [one[2],one[3],two[1]]
-            sp[i:1] = [p]
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/cubicsuperpath.py b/support/inkscape/cubicsuperpath.py
deleted file mode 100755
index 861b9da..0000000
--- a/support/inkscape/cubicsuperpath.py
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/usr/bin/env python
-"""
-cubicsuperpath.py
-
-Copyright (C) 2005 Aaron Spike, aaron@ekips.org
-
-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-"""
-import simplepath 
-from math import *
-
-def matprod(mlist):
-    prod=mlist[0]
-    for m in mlist[1:]:
-        a00=prod[0][0]*m[0][0]+prod[0][1]*m[1][0]
-        a01=prod[0][0]*m[0][1]+prod[0][1]*m[1][1]
-        a10=prod[1][0]*m[0][0]+prod[1][1]*m[1][0]
-        a11=prod[1][0]*m[0][1]+prod[1][1]*m[1][1]
-        prod=[[a00,a01],[a10,a11]]
-    return prod
-def rotmat(teta):
-    return [[cos(teta),-sin(teta)],[sin(teta),cos(teta)]]
-def applymat(mat, pt):
-    x=mat[0][0]*pt[0]+mat[0][1]*pt[1]
-    y=mat[1][0]*pt[0]+mat[1][1]*pt[1]
-    pt[0]=x
-    pt[1]=y
-def norm(pt):
-    return sqrt(pt[0]*pt[0]+pt[1]*pt[1])
-
-def ArcToPath(p1,params):
-    A=p1[:]
-    rx,ry,teta,longflag,sweepflag,x2,y2=params[:]
-    teta = teta*pi/180.0
-    B=[x2,y2]
-    if rx==0 or ry==0 or A==B:
-        return([[A[:],A[:],A[:]],[B[:],B[:],B[:]]])
-    mat=matprod((rotmat(teta),[[1/rx,0],[0,1/ry]],rotmat(-teta)))
-    applymat(mat, A)
-    applymat(mat, B)
-    k=[-(B[1]-A[1]),B[0]-A[0]]
-    d=k[0]*k[0]+k[1]*k[1]
-    k[0]/=sqrt(d)
-    k[1]/=sqrt(d)
-    d=sqrt(max(0,1-d/4))
-    if longflag==sweepflag:
-        d*=-1
-    O=[(B[0]+A[0])/2+d*k[0],(B[1]+A[1])/2+d*k[1]]
-    OA=[A[0]-O[0],A[1]-O[1]]
-    OB=[B[0]-O[0],B[1]-O[1]]
-    start=acos(OA[0]/norm(OA))
-    if OA[1]<0:
-        start*=-1
-    end=acos(OB[0]/norm(OB))
-    if OB[1]<0:
-        end*=-1
-
-    if sweepflag and start>end:
-        end +=2*pi
-    if (not sweepflag) and start<end:
-        end -=2*pi
-
-    NbSectors=int(abs(start-end)*2/pi)+1
-    dTeta=(end-start)/NbSectors
-    #v=dTeta*2/pi*0.552
-    #v=dTeta*2/pi*4*(sqrt(2)-1)/3
-    v = 4*tan(dTeta/4)/3
-    #if not sweepflag:
-    #    v*=-1
-    p=[]
-    for i in range(0,NbSectors+1,1):
-        angle=start+i*dTeta
-        v1=[O[0]+cos(angle)-(-v)*sin(angle),O[1]+sin(angle)+(-v)*cos(angle)]
-        pt=[O[0]+cos(angle)                ,O[1]+sin(angle)                ]
-        v2=[O[0]+cos(angle)-  v *sin(angle),O[1]+sin(angle)+  v *cos(angle)]
-        p.append([v1,pt,v2])
-
-    mat=matprod((rotmat(teta),[[rx,0],[0,ry]],rotmat(-teta)))
-    for pts in p:
-        applymat(mat, pts[0])
-        applymat(mat, pts[1])
-        applymat(mat, pts[2])
-    
-    # Use exact coordinates for the endpoints. This prevents small drifts when relative coordinates are used and guarantees that a path ending with a z command closes perfectly.
-    p[0][0] = p1[:]
-    p[0][1] = p1[:]
-    p[-1][1] = [x2, y2]
-    p[-1][2] = [x2, y2]
-    
-    return p
-    
-def CubicSuperPath(simplepath):
-    csp = []
-    subpath = -1
-    subpathstart = []
-    last = []
-    lastctrl = []
-    for s in simplepath:
-        cmd, params = s        
-        if cmd == 'M':
-            if last:
-                csp[subpath].append([lastctrl[:],last[:],last[:]])
-            subpath += 1
-            csp.append([])
-            subpathstart =  params[:]
-            last = params[:]
-            lastctrl = params[:]
-        elif cmd == 'L':
-            csp[subpath].append([lastctrl[:],last[:],last[:]])
-            last = params[:]
-            lastctrl = params[:]
-        elif cmd == 'C':
-            csp[subpath].append([lastctrl[:],last[:],params[:2]])
-            last = params[-2:]
-            lastctrl = params[2:4]
-        elif cmd == 'Q':
-            q0=last[:]
-            q1=params[0:2]
-            q2=params[2:4]
-            x0=     q0[0]
-            x1=1./3*q0[0]+2./3*q1[0]
-            x2=           2./3*q1[0]+1./3*q2[0]
-            x3=                           q2[0]
-            y0=     q0[1]
-            y1=1./3*q0[1]+2./3*q1[1]
-            y2=           2./3*q1[1]+1./3*q2[1]
-            y3=                           q2[1]
-            csp[subpath].append([lastctrl[:],[x0,y0],[x1,y1]])
-            last = [x3,y3]
-            lastctrl = [x2,y2]
-        elif cmd == 'A':
-            arcp=ArcToPath(last[:],params[:])
-            arcp[ 0][0]=lastctrl[:]
-            last=arcp[-1][1]
-            lastctrl = arcp[-1][0]
-            csp[subpath]+=arcp[:-1]
-        elif cmd == 'Z':
-            csp[subpath].append([lastctrl[:],last[:],last[:]])
-            last = subpathstart[:]
-            lastctrl = subpathstart[:]
-    #append final superpoint
-    csp[subpath].append([lastctrl[:],last[:],last[:]])
-    return csp    
-
-def unCubicSuperPath(csp):
-    a = []
-    for subpath in csp:
-        if subpath:
-            a.append(['M',subpath[0][1][:]])
-            for i in range(1,len(subpath)):
-                a.append(['C',subpath[i-1][2][:] + subpath[i][0][:] + subpath[i][1][:]])
-    return a
-
-def parsePath(d):
-    return CubicSuperPath(simplepath.parsePath(d))
-
-def formatPath(p):
-    return simplepath.formatPath(unCubicSuperPath(p))
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/dxf_footer.txt b/support/inkscape/dxf_footer.txt
deleted file mode 100644
index a225dd7..0000000
--- a/support/inkscape/dxf_footer.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-0
-ENDSEC
-0
-SECTION
-2
-OBJECTS
-0
-DICTIONARY
-5
-C
-330
-0
-100
-AcDbDictionary
-3
-ACAD_GROUP
-350
-D
-3
-ACAD_MLINESTYLE
-350
-17
-0
-DICTIONARY
-5
-D
-330
-C
-100
-AcDbDictionary
-0
-DICTIONARY
-5
-1A
-330
-C
-100
-AcDbDictionary
-0
-DICTIONARY
-5
-17
-330
-C
-100
-AcDbDictionary
-3
-STANDARD
-350
-18
-0
-DICTIONARY
-5
-19
-330
-C
-100
-AcDbDictionary
-0
-ENDSEC
-0
-EOF
diff --git a/support/inkscape/dxf_header.txt b/support/inkscape/dxf_header.txt
deleted file mode 100644
index 341cb1b..0000000
--- a/support/inkscape/dxf_header.txt
+++ /dev/null
@@ -1,580 +0,0 @@
-0
-SECTION
-2
-HEADER
-9
-$ACADVER
-1
-AC1014
-9
-$HANDSEED
-5
-FFFF
-0
-ENDSEC
-0
-SECTION
-2
-TABLES
-0
-TABLE
-2
-VPORT
-5
-8
-330
-0
-100
-AcDbSymbolTable
-70
-4
-0
-VPORT
-5
-2E
-330
-8
-100
-AcDbSymbolTableRecord
-100
-AcDbViewportTableRecord
-2
-*ACTIVE
-70
-0
-10
-0.0
-20
-0.0
-11
-1.0
-21
-1.0
-12
-4.25
-22
-5.5
-13
-0.0
-23
-0.0
-14
-10.0
-24
-10.0
-15
-10.0
-25
-10.0
-16
-0.0
-26
-0.0
-36
-1.0
-17
-0.0
-27
-0.0
-37
-0.0
-40
-11
-41
-1.24
-42
-50.0
-43
-0.0
-44
-0.0
-50
-0.0
-51
-0.0
-71
-0
-72
-100
-73
-1
-74
-3
-75
-0
-76
-0
-77
-0
-78
-0
-0
-ENDTAB
-0
-TABLE
-2
-LTYPE
-5
-5
-330
-0
-100
-AcDbSymbolTable
-70
-1
-0
-LTYPE
-5
-14
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
-2
-BYBLOCK
-70
-0
-3
-
-72
-65
-73
-0
-40
-0.0
-0
-LTYPE
-5
-15
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
-2
-BYLAYER
-70
-0
-3
-
-72
-65
-73
-0
-40
-0.0
-0
-LTYPE
-5
-16
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
-2
-CONTINUOUS
-70
-0
-3
-Solid line
-72
-65
-73
-0
-40
-0.0
-0
-ENDTAB
-0
-TABLE
-2
-LAYER
-5
-2
-330
-0
-100
-AcDbSymbolTable
-70
-1
-0
-LAYER
-5
-10
-330
-2
-100
-AcDbSymbolTableRecord
-100
-AcDbLayerTableRecord
-2
-0
-70
-0
-62
-7
-6
-CONTINUOUS
-0
-ENDTAB
-0
-TABLE
-2
-STYLE
-5
-3
-330
-0
-100
-AcDbSymbolTable
-70
-1
-0
-STYLE
-5
-11
-330
-3
-100
-AcDbSymbolTableRecord
-100
-AcDbTextStyleTableRecord
-2
-STANDARD
-70
-0
-40
-0.0
-41
-1.0
-50
-0.0
-71
-0
-42
-2.5
-3
-txt
-4
-
-0
-ENDTAB
-0
-TABLE
-2
-VIEW
-5
-6
-330
-0
-100
-AcDbSymbolTable
-70
-0
-0
-ENDTAB
-0
-TABLE
-2
-UCS
-5
-7
-330
-0
-100
-AcDbSymbolTable
-70
-0
-0
-ENDTAB
-0
-TABLE
-2
-APPID
-5
-9
-330
-0
-100
-AcDbSymbolTable
-70
-2
-0
-APPID
-5
-12
-330
-9
-100
-AcDbSymbolTableRecord
-100
-AcDbRegAppTableRecord
-2
-ACAD
-70
-0
-0
-ENDTAB
-0
-TABLE
-2
-DIMSTYLE
-5
-A
-330
-0
-100
-AcDbSymbolTable
-70
-1
-0
-DIMSTYLE
-105
-27
-330
-A
-100
-AcDbSymbolTableRecord
-100
-AcDbDimStyleTableRecord
-2
-ISO-25
-70
-0
-3
-
-4
-
-5
-
-6
-
-7
-
-40
-1.0
-41
-2.5
-42
-0.625
-43
-3.75
-44
-1.25
-45
-0.0
-46
-0.0
-47
-0.0
-48
-0.0
-140
-2.5
-141
-2.5
-142
-0.0
-143
-0.03937007874016
-144
-1.0
-145
-0.0
-146
-1.0
-147
-0.625
-71
-0
-72
-0
-73
-0
-74
-0
-75
-0
-76
-0
-77
-1
-78
-8
-170
-0
-171
-3
-172
-1
-173
-0
-174
-0
-175
-0
-176
-0
-177
-0
-178
-0
-270
-2
-271
-2
-272
-2
-273
-2
-274
-3
-340
-11
-275
-0
-280
-0
-281
-0
-282
-0
-283
-0
-284
-8
-285
-0
-286
-0
-287
-3
-288
-0
-0
-ENDTAB
-0
-TABLE
-2
-BLOCK_RECORD
-5
-1
-330
-0
-100
-AcDbSymbolTable
-70
-1
-0
-BLOCK_RECORD
-5
-1F
-330
-1
-100
-AcDbSymbolTableRecord
-100
-AcDbBlockTableRecord
-2
-*MODEL_SPACE
-0
-BLOCK_RECORD
-5
-1B
-330
-1
-100
-AcDbSymbolTableRecord
-100
-AcDbBlockTableRecord
-2
-*PAPER_SPACE
-0
-ENDTAB
-0
-ENDSEC
-0
-SECTION
-2
-BLOCKS
-0
-BLOCK
-5
-20
-330
-1F
-100
-AcDbEntity
-8
-0
-100
-AcDbBlockBegin
-2
-*MODEL_SPACE
-70
-0
-10
-0.0
-20
-0.0
-30
-0.0
-3
-*MODEL_SPACE
-1
-
-0
-ENDBLK
-5
-21
-330
-1F
-100
-AcDbEntity
-8
-0
-100
-AcDbBlockEnd
-0
-BLOCK
-5
-1C
-330
-1B
-100
-AcDbEntity
-67
-1
-8
-0
-100
-AcDbBlockBegin
-2
-*PAPER_SPACE
-1
-
-0
-ENDBLK
-5
-1D
-330
-1B
-100
-AcDbEntity
-67
-1
-8
-0
-100
-AcDbBlockEnd
-0
-ENDSEC
-0
-SECTION
-2
-ENTITIES
diff --git a/support/inkscape/effect.py b/support/inkscape/effect.py
deleted file mode 100644
index 313032c..0000000
--- a/support/inkscape/effect.py
+++ /dev/null
@@ -1,280 +0,0 @@
-"""
-Based on code from Aaron Spike. See
-http://www.bobcookdev.com/inkscape/inkscape-dxf.html
-"""
-
-import collections
-import itertools
-import os
-import pkgutil
-import re
-from lxml import etree
-
-from lib import util
-from . import inkex, simpletransform, cubicsuperpath, cspsubdiv, inkscape
-
-
-def _get_unit_factors_map():
-    # Fluctuates somewhat between Inkscape releases _and_ between SVG version.
-    pixels_per_inch = 96.
-    pixels_per_mm = pixels_per_inch / 25.4
-    
-    return {
-        'px': 1.0,
-        'mm': pixels_per_mm,
-        'cm': pixels_per_mm * 10,
-        'm': pixels_per_mm * 1e3,
-        'km': pixels_per_mm * 1e6,
-        'pt': pixels_per_inch / 72,
-        'pc': pixels_per_inch / 6,
-        'in': pixels_per_inch,
-        'ft': pixels_per_inch * 12,
-        'yd': pixels_per_inch * 36}
-
-
-class ExportEffect(inkex.Effect):
-    _unit_factors = _get_unit_factors_map()
-    _asymptote_all_paths_name = 'all'
-    
-    def __init__(self):
-        inkex.Effect.__init__(self)
-        
-        self._flatness = float(os.environ['DXF_FLATNESS'])
-        
-        self._layers = None
-        self._paths = None
-    
-    def _get_document_scale(self):
-        """
-        Return scaling factor applied to the document because of a viewBox
-        setting. This currently ignores any setting of a preserveAspectRatio
-        attribute (like Inkscape).
-        """
-        document_height = self._get_height()
-        view_box = self._get_view_box()
-        
-        if view_box is None or document_height is None:
-            return 1
-        else:
-            _, _, _, view_box_height = view_box
-            
-            return document_height / view_box_height
-    
-    def _get_document_height(self):
-        """
-        Get the height of the document in pixels in the document coordinate
-        system as it is interpreted by Inkscape.
-        """
-        view_box = self._get_view_box()
-        document_height = self._get_height()
-        
-        if view_box is not None:
-            _, _, _, view_box_height = view_box
-            
-            return view_box_height
-        elif document_height is not None:
-            return document_height
-        else:
-            return 0
-    
-    def _get_height(self):
-        height_attr = self.document.getroot().get('height')
-        
-        if height_attr is None:
-            return None
-        else:
-            return self._measure_to_pixels(height_attr)
-    
-    def _get_view_box(self):
-        view_box_attr = self.document.getroot().get('viewBox')
-        
-        if view_box_attr is None:
-            return None
-        else:
-            return [float(i) for i in view_box_attr.split()]
-    
-    def _get_shape_paths(self, node, transform):
-        shape = cubicsuperpath.parsePath(node.get('d'))
-        
-        transform = simpletransform.composeTransform(
-            transform,
-            simpletransform.composeParents(node, [[1, 0, 0], [0, 1, 0]]))
-        
-        simpletransform.applyTransformToPath(transform, shape)
-        
-        def iter_paths():
-            for path in shape:
-                cspsubdiv.subdiv(path, self._flatness)
-
-                # path contains two control point coordinates and the actual
-                # coordinates per point.
-                yield [i for _, i, _ in path]
-        
-        return list(iter_paths())
-    
-    def effect(self):
-        document_height = self._get_document_height()
-        document_scale = self._get_document_scale()
-        
-        transform = simpletransform.composeTransform(
-            [[document_scale, 0, 0], [0, document_scale, 0]],
-            [[1, 0, 0], [0, -1, document_height]])
-        
-        layers = inkscape.get_inkscape_layers(self.svg_file)
-        layers_by_inkscape_name = {i.inkscape_name: i for i in layers}
-        
-        def iter_paths():
-            for node in self.document.getroot().xpath('//svg:path', namespaces=inkex.NSS):
-                layer = layers_by_inkscape_name.get(self._get_inkscape_layer_name(node))
-                
-                for path in self._get_shape_paths(node, transform):
-                    yield layer, path
-        
-        self._layers = layers
-        self._paths = list(iter_paths())
-    
-    def write_dxf(self, file):
-        # Scales pixels to millimeters. This is the predominant unit in CAD.
-        unit_factor = self._unit_factors['mm']
-        
-        layer_indices = {l: i for i, l in enumerate(self._layers)}
-        
-        file.write(pkgutil.get_data(__name__, 'dxf_header.txt'))
-        
-        def write_instruction(code, value):
-            print >> file, code
-            print >> file, value
-        
-        handle_iter = itertools.count(256)
-        
-        for layer, path in self._paths:
-            for (x1, y1), (x2, y2) in zip(path, path[1:]):
-                write_instruction(0, 'LINE')
-                
-                if layer is not None:
-                    write_instruction(8, layer.export_name)
-                    write_instruction(62, layer_indices.get(layer, 0))
-                
-                write_instruction(5, '{:x}'.format(next(handle_iter)))
-                write_instruction(100, 'AcDbEntity')
-                write_instruction(100, 'AcDbLine')
-                write_instruction(10, repr(x1 / unit_factor))
-                write_instruction(20, repr(y1 / unit_factor))
-                write_instruction(30, 0.0)
-                write_instruction(11, repr(x2 / unit_factor))
-                write_instruction(21, repr(y2 / unit_factor))
-                write_instruction(31, 0.0)
-        
-        file.write(pkgutil.get_data(__name__, 'dxf_footer.txt'))
-    
-    def write_asy(self, file):
-        def write_line(format, *args):
-            print >> file, format.format(*args) + ';'
-
-        # Scales pixels to points. Asymptote uses PostScript points (1 / 72
-        # inch) by default.
-        unit_factor = self._unit_factors['pt']
-        
-        paths_by_layer = collections.defaultdict(list)
-        variable_names = []
-        
-        for layer, path in self._paths:
-            paths_by_layer[layer].append(path)
-        
-        for layer in self._layers + [None]:
-            paths = paths_by_layer[layer]
-            variable_name = self._asymptote_identifier_from_layer(layer)
-            write_line('path[] {}', variable_name)
-            
-            variable_names.append(variable_name)
-            
-            for path in paths:
-                point_strs = ['({}, {})'.format(x / unit_factor, y / unit_factor) for x, y in path]
-
-                # Hack. We should determine this from whether Z or z was used
-                #  to close the path in the SVG document.
-                if path[0] == path[-1]:
-                    point_strs[-1] = 'cycle'
-                
-                write_line('{}.push({})', variable_name, ' -- '.join(point_strs))
-        
-        if self._asymptote_all_paths_name not in variable_names:
-            write_line('path[] {}', self._asymptote_all_paths_name)
-            
-            for i in variable_names:
-                write_line('{}.append({})', self._asymptote_all_paths_name, i)
-    
-    @classmethod
-    def _parse_measure(cls, string):
-        value_match = re.match(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)', string)
-        unit_match = re.search('(%s)$' % '|'.join(cls._unit_factors.keys()), string)    
-        
-        value = float(string[value_match.start():value_match.end()])
-        
-        if unit_match:
-            unit = string[unit_match.start():unit_match.end()]
-        else:
-            unit = None
-        
-        return value, unit
-    
-    @classmethod
-    def _measure_to_pixels(cls, string):
-        """
-        Parse a string containing a measure and return it's value converted
-        to pixels.
-        """
-        value, unit = cls._parse_measure(string)
-        
-        return value * cls._get_unit_factor(unit)
-    
-    @classmethod
-    def _get_inkscape_layer_name(cls, node):
-        while node is not None:
-            layer = node.get(inkex.addNS('label', 'inkscape'))
-            
-            if layer is not None:
-                return layer
-            
-            node = node.getparent()
-        
-        return None
-    
-    @classmethod
-    def _get_unit_factor(cls, unit):
-        if unit is None:
-            return 1
-        else:
-            return cls._unit_factors[unit]
-    
-    @classmethod
-    def _asymptote_identifier_from_layer(cls, layer):
-        if layer is None:
-            return '_'
-        else:
-            return re.sub('[^a-zA-Z0-9]', '_', layer.export_name)
-    
-    @classmethod
-    def check_document_units(cls, path):
-        with open(path, 'r') as file:
-            p = etree.XMLParser(huge_tree = True)
-            document = etree.parse(file, parser = p)
-        
-        height_attr = document.getroot().get('height')
-        
-        if height_attr is None:
-            raise util.UserError(
-                'SVG document has no height attribute. See '
-                'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
-        
-        _, height_unit = cls._parse_measure(height_attr)
-        
-        if height_unit is None or height_unit == 'px':
-            raise util.UserError(
-                'Height of SVG document is not an absolute measure. See '
-                'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
-        
-        if document.getroot().get('viewBox') is None:
-            raise util.UserError(
-                'SVG document has no viewBox attribute. See '
-                'https://github.com/Feuermurmel/openscad-template/wiki/Absolute-Measurements')
diff --git a/support/inkscape/ffgeom.py b/support/inkscape/ffgeom.py
deleted file mode 100755
index ef8799b..0000000
--- a/support/inkscape/ffgeom.py
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env python
-"""
-    ffgeom.py
-    Copyright (C) 2005 Aaron Cyril Spike, aaron@ekips.org
-
-    This file is part of FretFind 2-D.
-
-    FretFind 2-D 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.
-
-    FretFind 2-D 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 FretFind 2-D; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-"""
-import math
-try:
-    NaN = float('NaN')
-except ValueError:
-    PosInf = 1e300000
-    NaN = PosInf/PosInf
-
-class Point:
-    precision = 5
-    def __init__(self, x, y):
-        self.__coordinates = {'x' : float(x), 'y' : float(y)}
-    def __getitem__(self, key):
-        return self.__coordinates[key]
-    def __setitem__(self, key, value):
-        self.__coordinates[key] = float(value)
-    def __repr__(self):
-        return '(%s, %s)' % (round(self['x'],self.precision),round(self['y'],self.precision))
-    def copy(self):
-        return Point(self['x'],self['y'])
-    def translate(self, x, y):
-        self['x'] += x
-        self['y'] += y
-    def move(self, x, y):
-        self['x'] = float(x)
-        self['y'] = float(y)
-
-class Segment:
-    def __init__(self, e0, e1):
-        self.__endpoints = [e0, e1]
-    def __getitem__(self, key):
-        return self.__endpoints[key]
-    def __setitem__(self, key, value):
-        self.__endpoints[key] = value
-    def __repr__(self):
-        return repr(self.__endpoints)
-    def copy(self):
-        return Segment(self[0],self[1])
-    def translate(self, x, y):
-        self[0].translate(x,y)
-        self[1].translate(x,y)
-    def move(self,e0,e1):
-        self[0] = e0
-        self[1] = e1
-    def delta_x(self):
-        return self[1]['x'] - self[0]['x']
-    def delta_y(self):
-        return self[1]['y'] - self[0]['y']
-    #alias functions
-    run = delta_x
-    rise = delta_y
-    def slope(self):
-        if self.delta_x() != 0:
-            return self.delta_x() / self.delta_y()
-        return NaN
-    def intercept(self):
-        if self.delta_x() != 0:
-            return self[1]['y'] - (self[0]['x'] * self.slope())
-        return NaN
-    def distanceToPoint(self, p):
-        s2 = Segment(self[0],p)
-        c1 = dot(s2,self)
-        if c1 <= 0:
-            return Segment(p,self[0]).length()
-        c2 = dot(self,self)
-        if c2 <= c1:
-            return Segment(p,self[1]).length()
-        return self.perpDistanceToPoint(p)
-    def perpDistanceToPoint(self, p):
-        len = self.length()
-        if len == 0: return NaN
-        return math.fabs(((self[1]['x'] - self[0]['x']) * (self[0]['y'] - p['y'])) - \
-            ((self[0]['x'] - p['x']) * (self[1]['y'] - self[0]['y']))) / len
-    def angle(self):
-        return math.pi * (math.atan2(self.delta_y(), self.delta_x())) / 180
-    def length(self):
-        return math.sqrt((self.delta_x() ** 2) + (self.delta_y() ** 2))
-    def pointAtLength(self, len):
-        if self.length() == 0: return Point(NaN, NaN)
-        ratio = len / self.length()
-        x = self[0]['x'] + (ratio * self.delta_x())
-        y = self[0]['y'] + (ratio * self.delta_y())
-        return Point(x, y)
-    def pointAtRatio(self, ratio):
-        if self.length() == 0: return Point(NaN, NaN)
-        x = self[0]['x'] + (ratio * self.delta_x())
-        y = self[0]['y'] + (ratio * self.delta_y())
-        return Point(x, y)
-    def createParallel(self, p):
-        return Segment(Point(p['x'] + self.delta_x(), p['y'] + self.delta_y()), p)
-    def intersect(self, s):
-        return intersectSegments(self, s)
-
-def intersectSegments(s1, s2):
-    x1 = s1[0]['x']
-    x2 = s1[1]['x']
-    x3 = s2[0]['x']
-    x4 = s2[1]['x']
-    
-    y1 = s1[0]['y']
-    y2 = s1[1]['y']
-    y3 = s2[0]['y']
-    y4 = s2[1]['y']
-    
-    denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1))
-    num1 = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3))
-    num2 = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3))
-
-    num = num1
-
-    if denom != 0: 
-        x = x1 + ((num / denom) * (x2 - x1))
-        y = y1 + ((num / denom) * (y2 - y1))
-        return Point(x, y)
-    return Point(NaN, NaN)
-
-def dot(s1, s2):
-    return s1.delta_x() * s2.delta_x() + s1.delta_y() * s2.delta_y()
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/inkex.py b/support/inkscape/inkex.py
deleted file mode 100755
index 19e860b..0000000
--- a/support/inkscape/inkex.py
+++ /dev/null
@@ -1,370 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-inkex.py
-A helper module for creating Inkscape extensions
-
-Copyright (C) 2005,2010 Aaron Spike <aaron@ekips.org> and contributors
-
-Contributors:
-  Aurélio A. Heckert <aurium(a)gmail.com>
-  Bulia Byak <buliabyak@users.sf.net>
-  Nicolas Dufour, nicoduf@yahoo.fr
-  Peter J. R. Moulder <pjrm@users.sourceforge.net>
-
-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-"""
-import copy
-import gettext
-import optparse
-import os
-import random
-import re
-import sys
-from math import *
-
-#a dictionary of all of the xmlns prefixes in a standard inkscape doc
-NSS = {
-u'sodipodi' :u'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
-u'cc'       :u'http://creativecommons.org/ns#',
-u'ccOLD'    :u'http://web.resource.org/cc/',
-u'svg'      :u'http://www.w3.org/2000/svg',
-u'dc'       :u'http://purl.org/dc/elements/1.1/',
-u'rdf'      :u'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
-u'inkscape' :u'http://www.inkscape.org/namespaces/inkscape',
-u'xlink'    :u'http://www.w3.org/1999/xlink',
-u'xml'      :u'http://www.w3.org/XML/1998/namespace'
-}
-
-def localize():
-    domain = 'inkscape'
-    if sys.platform.startswith('win'):
-        import locale
-        current_locale, encoding = locale.getdefaultlocale()
-        os.environ['LANG'] = current_locale
-        try:
-            localdir = os.environ['INKSCAPE_LOCALEDIR'];
-            trans = gettext.translation(domain, localdir, [current_locale], fallback=True)
-        except KeyError:
-            trans = gettext.translation(domain, fallback=True)
-    elif sys.platform.startswith('darwin'):
-        try:
-            localdir = os.environ['INKSCAPE_LOCALEDIR'];
-            trans = gettext.translation(domain, localdir, fallback=True)
-        except KeyError:
-            try:
-                localdir = os.environ['PACKAGE_LOCALE_DIR'];
-                trans = gettext.translation(domain, localdir, fallback=True)
-            except KeyError:
-                trans = gettext.translation(domain, fallback=True)
-    else:
-        try:
-            localdir = os.environ['PACKAGE_LOCALE_DIR'];
-            trans = gettext.translation(domain, localdir, fallback=True)
-        except KeyError:
-            trans = gettext.translation(domain, fallback=True)
-    #sys.stderr.write(str(localdir) + "\n")
-    trans.install()
-
-def debug(what):
-    sys.stderr.write(str(what) + "\n")
-    return what
-
-def errormsg(msg):
-    """Intended for end-user-visible error messages.
-    
-       (Currently just writes to stderr with an appended newline, but could do
-       something better in future: e.g. could add markup to distinguish error
-       messages from status messages or debugging output.)
-      
-       Note that this should always be combined with translation:
-
-         import inkex
-         inkex.localize()
-         ...
-         inkex.errormsg(_("This extension requires two selected paths."))
-    """
-    if isinstance(msg, unicode):
-        sys.stderr.write(msg.encode("UTF-8") + "\n")
-    else:
-        sys.stderr.write((unicode(msg, "utf-8", errors='replace') + "\n").encode("UTF-8"))
-
-def are_near_relative(a, b, eps):
-    if (a-b <= a*eps) and (a-b >= -a*eps):
-        return True
-    else:
-        return False
-
-
-# third party library
-try:
-    from lxml import etree
-except Exception, e:
-    localize()
-    errormsg(_("The fantastic lxml wrapper for libxml2 is required by inkex.py and therefore this extension. Please download and install the latest version from http://cheeseshop.python.org/pypi/lxml/, or install it through your package manager by a command like: sudo apt-get install python-lxml\n\nTechnical details:\n%s" % (e,)))
-    sys.exit()
-    
-def check_inkbool(option, opt, value):
-    if str(value).capitalize() == 'True':
-        return True
-    elif str(value).capitalize() == 'False':
-        return False
-    else:
-        raise optparse.OptionValueError("option %s: invalid inkbool value: %s" % (opt, value))
-
-def addNS(tag, ns=None):
-    val = tag
-    if ns!=None and len(ns)>0 and NSS.has_key(ns) and len(tag)>0 and tag[0]!='{':
-        val = "{%s}%s" % (NSS[ns], tag)
-    return val
-
-class InkOption(optparse.Option):
-    TYPES = optparse.Option.TYPES + ("inkbool",)
-    TYPE_CHECKER = copy.copy(optparse.Option.TYPE_CHECKER)
-    TYPE_CHECKER["inkbool"] = check_inkbool
-
-class Effect:
-    """A class for creating Inkscape SVG Effects"""
-
-    def __init__(self, *args, **kwargs):
-        self.document=None
-        self.original_document=None
-        self.ctx=None
-        self.selected={}
-        self.doc_ids={}
-        self.options=None
-        self.args=None
-        self.OptionParser = optparse.OptionParser(usage="usage: %prog [options] SVGfile",option_class=InkOption)
-        self.OptionParser.add_option("--id",
-                        action="append", type="string", dest="ids", default=[], 
-                        help="id attribute of object to manipulate")
-
-    def effect(self):
-        pass
-
-    def getoptions(self,args=sys.argv[1:]):
-        """Collect command line arguments"""
-        self.options, self.args = self.OptionParser.parse_args(args)
-
-    def parse(self, filename=None):
-        """Parse document in specified file or on stdin"""
-
-        # First try to open the file from the function argument
-        if filename != None:
-            try:
-                stream = open(filename, 'r')
-            except Exception:
-                errormsg(_("Unable to open specified file: %s") % filename)
-                sys.exit()
-
-        # If it wasn't specified, try to open the file specified as
-        # an object member
-        elif self.svg_file != None:
-            try:
-                stream = open(self.svg_file, 'r')
-            except Exception:
-                errormsg(_("Unable to open object member file: %s") % self.svg_file)
-                sys.exit()
-
-        # Finally, if the filename was not specified anywhere, use
-        # standard input stream
-        else:
-            stream = sys.stdin
-
-        p = etree.XMLParser(huge_tree=True)
-        self.document = etree.parse(stream, parser=p)
-        self.original_document = copy.deepcopy(self.document)
-        stream.close()
-
-    # defines view_center in terms of document units
-    def getposinlayer(self):
-        #defaults
-        self.current_layer = self.document.getroot()
-        self.view_center = (0.0,0.0)
-
-        layerattr = self.document.xpath('//sodipodi:namedview/@inkscape:current-layer', namespaces=NSS)
-        if layerattr:
-            layername = layerattr[0]
-            layer = self.document.xpath('//svg:g[@id="%s"]' % layername, namespaces=NSS)
-            if layer:
-                self.current_layer = layer[0]
-
-        xattr = self.document.xpath('//sodipodi:namedview/@inkscape:cx', namespaces=NSS)
-        yattr = self.document.xpath('//sodipodi:namedview/@inkscape:cy', namespaces=NSS)
-        if xattr and yattr:
-            x = self.unittouu( xattr[0] + 'px' )
-            y = self.unittouu( yattr[0] + 'px')
-            doc_height = self.unittouu(self.document.getroot().get('height'))
-            if x and y:
-                self.view_center = (float(x), doc_height - float(y)) # FIXME: y-coordinate flip, eliminate it when it's gone in Inkscape
-
-    def getselected(self):
-        """Collect selected nodes"""
-        for i in self.options.ids:
-            path = '//*[@id="%s"]' % i
-            for node in self.document.xpath(path, namespaces=NSS):
-                self.selected[i] = node
-
-    def getElementById(self, id):
-        path = '//*[@id="%s"]' % id
-        el_list = self.document.xpath(path, namespaces=NSS)
-        if el_list:
-          return el_list[0]
-        else:
-          return None
-
-    def getParentNode(self, node):
-        for parent in self.document.getiterator():
-            if node in parent.getchildren():
-                return parent
-                break
-
-
-    def getdocids(self):
-        docIdNodes = self.document.xpath('//@id', namespaces=NSS)
-        for m in docIdNodes:
-            self.doc_ids[m] = 1
-
-    def getNamedView(self):
-        return self.document.xpath('//sodipodi:namedview', namespaces=NSS)[0]
-
-    def createGuide(self, posX, posY, angle):
-        atts = {
-          'position': str(posX)+','+str(posY),
-          'orientation': str(sin(radians(angle)))+','+str(-cos(radians(angle)))
-          }
-        guide = etree.SubElement(
-                  self.getNamedView(),
-                  addNS('guide','sodipodi'), atts )
-        return guide
-
-    def output(self):
-        """Serialize document into XML on stdout"""
-        original = etree.tostring(self.original_document)        
-        result = etree.tostring(self.document)        
-        if original != result:
-            self.document.write(sys.stdout)
-
-    def affect(self, args=sys.argv[1:], output=True):
-        """Affect an SVG document with a callback effect"""
-        self.svg_file = args[-1]
-        self.getoptions(args)
-        self.parse()
-        self.getposinlayer()
-        self.getselected()
-        self.getdocids()
-        self.effect()
-        if output: self.output()
-
-    def uniqueId(self, old_id, make_new_id = True):
-        new_id = old_id
-        if make_new_id:
-            while new_id in self.doc_ids:
-                new_id += random.choice('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
-            self.doc_ids[new_id] = 1
-        return new_id
-
-    def xpathSingle(self, path):
-        try:
-            retval = self.document.xpath(path, namespaces=NSS)[0]
-        except:
-            errormsg(_("No matching node for expression: %s") % path)
-            retval = None
-        return retval
-
-    #a dictionary of unit to user unit conversion factors
-    __uuconv = {'in':96.0, 'pt':1.33333333333, 'px':1.0, 'mm':3.77952755913, 'cm':37.7952755913,
-                'm':3779.52755913, 'km':3779527.55913, 'pc':16.0, 'yd':3456.0 , 'ft':1152.0}
-
-    # Function returns the unit used for the values in SVG.
-    # For lack of an attribute in SVG that explicitly defines what units are used for SVG coordinates,
-    # try to calculate the unit from the SVG width and SVG viewbox.
-    # Defaults to 'px' units.
-    def getDocumentUnit(self):
-        svgunit = 'px' #default to pixels
-
-        svgwidth = self.document.getroot().get('width')
-        viewboxstr = self.document.getroot().get('viewBox')
-        if viewboxstr:
-            unitmatch = re.compile('(%s)$' % '|'.join(self.__uuconv.keys()))
-            param = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
-
-            p = param.match(svgwidth)
-            u = unitmatch.search(svgwidth)    
-            
-            width = 100 #default
-            viewboxwidth = 100 #default
-            svgwidthunit = 'px' #default assume 'px' unit
-            if p:
-                width = float(p.string[p.start():p.end()])
-            else:
-                errormsg(_("SVG Width not set correctly! Assuming width = 100"))
-            if u:
-                svgwidthunit = u.string[u.start():u.end()]
-
-            viewboxnumbers = []
-            for t in viewboxstr.split():
-                try:
-                    viewboxnumbers.append(float(t))
-                except ValueError:
-                    pass
-            if len(viewboxnumbers) == 4:  #check for correct number of numbers
-                viewboxwidth = viewboxnumbers[2]
-
-            svgunitfactor = self.__uuconv[svgwidthunit] * width / viewboxwidth
-
-            # try to find the svgunitfactor in the list of units known. If we don't find something, ...
-            eps = 0.01 #allow 1% error in factor
-            for key in self.__uuconv:
-                if are_near_relative(self.__uuconv[key], svgunitfactor, eps):
-                    #found match!
-                    svgunit = key;
-
-        return svgunit
-
-
-    def unittouu(self, string):
-        '''Returns userunits given a string representation of units in another system'''
-        unit = re.compile('(%s)$' % '|'.join(self.__uuconv.keys()))
-        param = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
-
-        p = param.match(string)
-        u = unit.search(string)    
-        if p:
-            retval = float(p.string[p.start():p.end()])
-        else:
-            retval = 0.0
-        if u:
-            try:
-                return retval * (self.__uuconv[u.string[u.start():u.end()]] / self.__uuconv[self.getDocumentUnit()])
-            except KeyError:
-                pass
-        else: # default assume 'px' unit
-            return retval / self.__uuconv[self.getDocumentUnit()]
-
-        return retval
-
-    def uutounit(self, val, unit):
-        return val / (self.__uuconv[unit] / self.__uuconv[self.getDocumentUnit()])
-
-    def addDocumentUnit(self, value):
-        ''' Add document unit when no unit is specified in the string '''
-        try:
-            float(value)
-            return value + self.getDocumentUnit()
-        except ValueError:
-            return value
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/inkscape.py b/support/inkscape/inkscape.py
deleted file mode 100644
index 9fd9528..0000000
--- a/support/inkscape/inkscape.py
+++ /dev/null
@@ -1,136 +0,0 @@
-import os
-import xml.etree.ElementTree as etree
-
-from lib import util
-
-
-def get_inkscape_layers(svg_path):
-    document = etree.parse(svg_path)
-    
-    def iter_layers():
-        nodes = document.findall(
-            '{http://www.w3.org/2000/svg}g[@{http://www.inkscape.org/namespaces/inkscape}groupmode="layer"]')
-        
-        for i in nodes:
-            inkscape_name = i.get('{http://www.inkscape.org/namespaces/inkscape}label').strip()
-            
-            if inkscape_name.endswith(']'):
-                export_name, args = inkscape_name[:-1].rsplit('[', 1)
-                
-                export_name = export_name.strip()
-                args = args.strip()
-                
-                use_paths = 'p' in args
-            else:
-                use_paths = False
-                export_name = inkscape_name
-            
-            yield Layer(inkscape_name, export_name, use_paths)
-    
-    return list(iter_layers())
-
-
-def _inkscape(svg_path, verbs):
-    def iter_args():
-        yield os.environ['INKSCAPE']
-        
-        for i in verbs:
-            yield '--verb'
-            yield i
-        
-        yield svg_path
-    
-    util.command(list(iter_args()))
-
-
-class Layer(object):
-    def __init__(self, inkscape_name, export_name, use_paths):
-        self.inkscape_name = inkscape_name
-        self.export_name = export_name
-        self.use_paths = use_paths
-
-
-class InkscapeCommandLine(object):
-    def __init__(self, path):
-        self._path = path
-        self._layers = get_inkscape_layers(path)
-        self._current_layer_index = None
-        self._verbs = []
-    
-    def apply_to_document(self, *verb):
-        self._verbs.extend(verb)
-    
-    def apply_to_layer(self, layer, *verb):
-        self._go_to_layer(layer)
-        self.apply_to_document(*verb)
-    
-    def select_all_in_layer(self, layer):
-        self.apply_to_layer(layer, 'EditSelectAll')
-    
-    def apply_to_layer_content(self, layer, *verbs):
-        self.select_all_in_layer(layer)
-        self.apply_to_document(*verbs)
-    
-    def _go_to_layer(self, layer, with_selection=False):
-        if self._current_layer_index is None:
-            # Initialize to a known state. We cannot assume that any layer is
-            #  selected and thus we need as many LayerPrev as we have layers.
-            self._current_layer_index = len(self._layers)
-            self._go_to_layer(self._layers[0])
-        
-        target_index = self._layers.index(layer)
-        
-        if with_selection:
-            next_command = 'LayerMoveToNext'
-            previous_command = 'LayerMoveToPrev'
-        else:
-            next_command = 'LayerNext'
-            previous_command = 'LayerPrev'
-        
-        while self._current_layer_index != target_index:
-            if self._current_layer_index < target_index:
-                self.apply_to_document(next_command)
-                self._current_layer_index += 1
-            else:
-                self.apply_to_document(previous_command)
-                self._current_layer_index -= 1
-        
-        if with_selection:
-            # When using LayerMoveToNext and LayerMoveToPrev, inkscape does
-            # not reliably select the next/previous layer.
-            self._current_layer_index = None
-    
-    def duplicate_layer(self, layer):
-        self.apply_to_layer(layer, 'LayerDuplicate')
-
-        # Inkscape 0.91 places a duplicated layer above (after) the selected
-        # one and selects the new layer.
-        new_layer = Layer(layer.inkscape_name + ' copy', layer.export_name, layer.use_paths)
-        self._layers.insert(self._current_layer_index + 1, new_layer)
-        
-        # Whether the original or the new layer is selected after the operation
-        # fluctuates between Inkscape versions.
-        self._current_layer_index = None
-        
-        return new_layer
-    
-    def delete_layer(self, layer):
-        self.apply_to_layer(layer, 'LayerDelete')
-        
-        # Inkscape 0.91 selects the layer above (after) the deleted layer.
-        del self._layers[self._current_layer_index]
-    
-    def clear_layer(self, layer):
-        self.select_all_in_layer(layer)
-        self.apply_to_document('EditDelete')
-    
-    def move_content(self, source_layer, target_layer):
-        self.select_all_in_layer(source_layer)
-        self._go_to_layer(target_layer, True)
-    
-    def run(self):
-        _inkscape(self._path, self._verbs)
-    
-    @property
-    def layers(self):
-        return list(self._layers)
diff --git a/support/inkscape/simplepath.py b/support/inkscape/simplepath.py
deleted file mode 100755
index 94ab092..0000000
--- a/support/inkscape/simplepath.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/env python
-"""
-simplepath.py
-functions for digesting paths into a simple list structure
-
-Copyright (C) 2005 Aaron Spike, aaron@ekips.org
-
-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-"""
-import re, math
-
-def lexPath(d):
-    """
-    returns and iterator that breaks path data 
-    identifies command and parameter tokens
-    """
-    offset = 0
-    length = len(d)
-    delim = re.compile(r'[ \t\r\n,]+')
-    command = re.compile(r'[MLHVCSQTAZmlhvcsqtaz]')
-    parameter = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
-    while 1:
-        m = delim.match(d, offset)
-        if m:
-            offset = m.end()
-        if offset >= length:
-            break
-        m = command.match(d, offset)
-        if m:
-            yield [d[offset:m.end()], True]
-            offset = m.end()
-            continue
-        m = parameter.match(d, offset)
-        if m:
-            yield [d[offset:m.end()], False]
-            offset = m.end()
-            continue
-        #TODO: create new exception
-        raise Exception, 'Invalid path data!'
-'''
-pathdefs = {commandfamily:
-    [
-    implicitnext,
-    #params,
-    [casts,cast,cast],
-    [coord type,x,y,0]
-    ]}
-'''
-pathdefs = {
-    'M':['L', 2, [float, float], ['x','y']], 
-    'L':['L', 2, [float, float], ['x','y']], 
-    'H':['H', 1, [float], ['x']], 
-    'V':['V', 1, [float], ['y']], 
-    'C':['C', 6, [float, float, float, float, float, float], ['x','y','x','y','x','y']], 
-    'S':['S', 4, [float, float, float, float], ['x','y','x','y']], 
-    'Q':['Q', 4, [float, float, float, float], ['x','y','x','y']], 
-    'T':['T', 2, [float, float], ['x','y']], 
-    'A':['A', 7, [float, float, float, int, int, float, float], ['r','r','a',0,'s','x','y']], 
-    'Z':['L', 0, [], []]
-    }
-def parsePath(d):
-    """
-    Parse SVG path and return an array of segments.
-    Removes all shorthand notation.
-    Converts coordinates to absolute.
-    """
-    retval = []
-    lexer = lexPath(d)
-
-    pen = (0.0,0.0)
-    subPathStart = pen
-    lastControl = pen
-    lastCommand = ''
-    
-    while 1:
-        try:
-            token, isCommand = lexer.next()
-        except StopIteration:
-            break
-        params = []
-        needParam = True
-        if isCommand:
-            if not lastCommand and token.upper() != 'M':
-                raise Exception, 'Invalid path, must begin with moveto.'    
-            else:                
-                command = token
-        else:
-            #command was omited
-            #use last command's implicit next command
-            needParam = False
-            if lastCommand:
-                if lastCommand.isupper():
-                    command = pathdefs[lastCommand][0]
-                else:
-                    command = pathdefs[lastCommand.upper()][0].lower()
-            else:
-                raise Exception, 'Invalid path, no initial command.'    
-        numParams = pathdefs[command.upper()][1]
-        while numParams > 0:
-            if needParam:
-                try: 
-                    token, isCommand = lexer.next()
-                    if isCommand:
-                        raise Exception, 'Invalid number of parameters'
-                except StopIteration:
-                    raise Exception, 'Unexpected end of path'
-            cast = pathdefs[command.upper()][2][-numParams]
-            param = cast(token)
-            if command.islower():
-                if pathdefs[command.upper()][3][-numParams]=='x':
-                    param += pen[0]
-                elif pathdefs[command.upper()][3][-numParams]=='y':
-                    param += pen[1]
-            params.append(param)
-            needParam = True
-            numParams -= 1
-        #segment is now absolute so
-        outputCommand = command.upper()
-    
-        #Flesh out shortcut notation    
-        if outputCommand in ('H','V'):
-            if outputCommand == 'H':
-                params.append(pen[1])
-            if outputCommand == 'V':
-                params.insert(0,pen[0])
-            outputCommand = 'L'
-        if outputCommand in ('S','T'):
-            params.insert(0,pen[1]+(pen[1]-lastControl[1]))
-            params.insert(0,pen[0]+(pen[0]-lastControl[0]))
-            if outputCommand == 'S':
-                outputCommand = 'C'
-            if outputCommand == 'T':
-                outputCommand = 'Q'
-
-        #current values become "last" values
-        if outputCommand == 'M':
-            subPathStart = tuple(params[0:2])
-            pen = subPathStart
-        if outputCommand == 'Z':
-            pen = subPathStart
-        else:
-            pen = tuple(params[-2:])
-
-        if outputCommand in ('Q','C'):
-            lastControl = tuple(params[-4:-2])
-        else:
-            lastControl = pen
-        lastCommand = command
-
-        retval.append([outputCommand,params])
-    return retval
-
-def formatPath(a):
-    """Format SVG path data from an array"""
-    return "".join([cmd + " ".join([str(p) for p in params]) for cmd, params in a])
-
-def translatePath(p, x, y):
-    for cmd,params in p:
-        defs = pathdefs[cmd]
-        for i in range(defs[1]):
-            if defs[3][i] == 'x':
-                params[i] += x
-            elif defs[3][i] == 'y':
-                params[i] += y
-
-def scalePath(p, x, y):
-    for cmd,params in p:
-        defs = pathdefs[cmd]
-        for i in range(defs[1]):
-            if defs[3][i] == 'x':
-                params[i] *= x
-            elif defs[3][i] == 'y':
-                params[i] *= y
-            elif defs[3][i] == 'r':         # radius parameter
-                params[i] *= x
-            elif defs[3][i] == 's':         # sweep-flag parameter
-                if x*y < 0:
-                    params[i] = 1 - params[i]
-            elif defs[3][i] == 'a':         # x-axis-rotation angle
-                if y < 0:
-                    params[i] = - params[i]
-
-def rotatePath(p, a, cx = 0, cy = 0):
-    if a == 0:
-        return p
-    for cmd,params in p:
-        defs = pathdefs[cmd]
-        for i in range(defs[1]):
-            if defs[3][i] == 'x':
-                x = params[i] - cx
-                y = params[i + 1] - cy
-                r = math.sqrt((x**2) + (y**2))
-                if r != 0:
-                    theta = math.atan2(y, x) + a
-                    params[i] = (r * math.cos(theta)) + cx
-                    params[i + 1] = (r * math.sin(theta)) + cy
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/inkscape/simpletransform.py b/support/inkscape/simpletransform.py
deleted file mode 100755
index 55082ed..0000000
--- a/support/inkscape/simpletransform.py
+++ /dev/null
@@ -1,241 +0,0 @@
-#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-Copyright (C) 2010 Alvin Penner, penner@vaxxine.com
-
-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-barraud@math.univ-lille1.fr
-
-This code defines several functions to make handling of transform
-attribute easier.
-'''
-import inkex, cubicsuperpath
-import math, re
-
-def parseTransform(transf,mat=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
-    if transf=="" or transf==None:
-        return(mat)
-    stransf = transf.strip()
-    result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\s*\(([^)]*)\)\s*,?",stransf)
-#-- translate --
-    if result.group(1)=="translate":
-        args=result.group(2).replace(',',' ').split()
-        dx=float(args[0])
-        if len(args)==1:
-            dy=0.0
-        else:
-            dy=float(args[1])
-        matrix=[[1,0,dx],[0,1,dy]]
-#-- scale --
-    if result.group(1)=="scale":
-        args=result.group(2).replace(',',' ').split()
-        sx=float(args[0])
-        if len(args)==1:
-            sy=sx
-        else:
-            sy=float(args[1])
-        matrix=[[sx,0,0],[0,sy,0]]
-#-- rotate --
-    if result.group(1)=="rotate":
-        args=result.group(2).replace(',',' ').split()
-        a=float(args[0])*math.pi/180
-        if len(args)==1:
-            cx,cy=(0.0,0.0)
-        else:
-            cx,cy=map(float,args[1:])
-        matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]]
-        matrix=composeTransform(matrix,[[1,0,-cx],[0,1,-cy]])
-#-- skewX --
-    if result.group(1)=="skewX":
-        a=float(result.group(2))*math.pi/180
-        matrix=[[1,math.tan(a),0],[0,1,0]]
-#-- skewY --
-    if result.group(1)=="skewY":
-        a=float(result.group(2))*math.pi/180
-        matrix=[[1,0,0],[math.tan(a),1,0]]
-#-- matrix --
-    if result.group(1)=="matrix":
-        a11,a21,a12,a22,v1,v2=result.group(2).replace(',',' ').split()
-        matrix=[[float(a11),float(a12),float(v1)], [float(a21),float(a22),float(v2)]]
-
-    matrix=composeTransform(mat,matrix)
-    if result.end() < len(stransf):
-        return(parseTransform(stransf[result.end():], matrix))
-    else:
-        return matrix
-
-def formatTransform(mat):
-    return ("matrix(%f,%f,%f,%f,%f,%f)" % (mat[0][0], mat[1][0], mat[0][1], mat[1][1], mat[0][2], mat[1][2]))
-
-def composeTransform(M1,M2):
-    a11 = M1[0][0]*M2[0][0] + M1[0][1]*M2[1][0]
-    a12 = M1[0][0]*M2[0][1] + M1[0][1]*M2[1][1]
-    a21 = M1[1][0]*M2[0][0] + M1[1][1]*M2[1][0]
-    a22 = M1[1][0]*M2[0][1] + M1[1][1]*M2[1][1]
-
-    v1 = M1[0][0]*M2[0][2] + M1[0][1]*M2[1][2] + M1[0][2]
-    v2 = M1[1][0]*M2[0][2] + M1[1][1]*M2[1][2] + M1[1][2]
-    return [[a11,a12,v1],[a21,a22,v2]]
-
-def composeParents(node, mat):
-    trans = node.get('transform')
-    if trans:
-        mat = composeTransform(parseTransform(trans), mat)
-    if node.getparent().tag == inkex.addNS('g','svg'):
-        mat = composeParents(node.getparent(), mat)
-    return mat
-
-def applyTransformToNode(mat,node):
-    m=parseTransform(node.get("transform"))
-    newtransf=formatTransform(composeTransform(mat,m))
-    node.set("transform", newtransf)
-
-def applyTransformToPoint(mat,pt):
-    x = mat[0][0]*pt[0] + mat[0][1]*pt[1] + mat[0][2]
-    y = mat[1][0]*pt[0] + mat[1][1]*pt[1] + mat[1][2]
-    pt[0]=x
-    pt[1]=y
-
-def applyTransformToPath(mat,path):
-    for comp in path:
-        for ctl in comp:
-            for pt in ctl:
-                applyTransformToPoint(mat,pt)
-
-def fuseTransform(node):
-    if node.get('d')==None:
-        #FIXME: how do you raise errors?
-        raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'
-    t = node.get("transform")
-    if t == None:
-        return
-    m = parseTransform(t)
-    d = node.get('d')
-    p = cubicsuperpath.parsePath(d)
-    applyTransformToPath(m,p)
-    node.set('d', cubicsuperpath.formatPath(p))
-    del node.attrib["transform"]
-
-####################################################################
-##-- Some functions to compute a rough bbox of a given list of objects.
-##-- this should be shipped out in an separate file...
-
-def boxunion(b1,b2):
-    if b1 is None:
-        return b2
-    elif b2 is None:
-        return b1    
-    else:
-        return((min(b1[0],b2[0]), max(b1[1],b2[1]), min(b1[2],b2[2]), max(b1[3],b2[3])))
-
-def roughBBox(path):
-    xmin,xMax,ymin,yMax = path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1]
-    for pathcomp in path:
-        for ctl in pathcomp:
-            for pt in ctl:
-                xmin = min(xmin,pt[0])
-                xMax = max(xMax,pt[0])
-                ymin = min(ymin,pt[1])
-                yMax = max(yMax,pt[1])
-    return xmin,xMax,ymin,yMax
-
-def refinedBBox(path):
-    xmin,xMax,ymin,yMax = path[0][0][1][0],path[0][0][1][0],path[0][0][1][1],path[0][0][1][1]
-    for pathcomp in path:
-        for i in range(1, len(pathcomp)):
-            cmin, cmax = cubicExtrema(pathcomp[i-1][1][0], pathcomp[i-1][2][0], pathcomp[i][0][0], pathcomp[i][1][0])
-            xmin = min(xmin, cmin)
-            xMax = max(xMax, cmax)
-            cmin, cmax = cubicExtrema(pathcomp[i-1][1][1], pathcomp[i-1][2][1], pathcomp[i][0][1], pathcomp[i][1][1])
-            ymin = min(ymin, cmin)
-            yMax = max(yMax, cmax)
-    return xmin,xMax,ymin,yMax
-
-def cubicExtrema(y0, y1, y2, y3):
-    cmin = min(y0, y3)
-    cmax = max(y0, y3)
-    d1 = y1 - y0
-    d2 = y2 - y1
-    d3 = y3 - y2
-    if (d1 - 2*d2 + d3):
-        if (d2*d2 > d1*d3):
-            t = (d1 - d2 + math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3)
-            if (t > 0) and (t < 1):
-                y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
-                cmin = min(cmin, y)
-                cmax = max(cmax, y)
-            t = (d1 - d2 - math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3)
-            if (t > 0) and (t < 1):
-                y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
-                cmin = min(cmin, y)
-                cmax = max(cmax, y)
-    elif (d3 - d1):
-        t = -d1/(d3 - d1)
-        if (t > 0) and (t < 1):
-            y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
-            cmin = min(cmin, y)
-            cmax = max(cmax, y)
-    return cmin, cmax
-
-def computeBBox(aList,mat=[[1,0,0],[0,1,0]]):
-    bbox=None
-    for node in aList:
-        m = parseTransform(node.get('transform'))
-        m = composeTransform(mat,m)
-        #TODO: text not supported!
-        d = None
-        if node.get("d"):
-            d = node.get('d')
-        elif node.get('points'):
-            d = 'M' + node.get('points')
-        elif node.tag in [ inkex.addNS('rect','svg'), 'rect', inkex.addNS('image','svg'), 'image' ]:
-            d = 'M' + node.get('x', '0') + ',' + node.get('y', '0') + \
-                'h' + node.get('width') + 'v' + node.get('height') + \
-                'h-' + node.get('width')
-        elif node.tag in [ inkex.addNS('line','svg'), 'line' ]:
-            d = 'M' + node.get('x1') + ',' + node.get('y1') + \
-                ' ' + node.get('x2') + ',' + node.get('y2')
-        elif node.tag in [ inkex.addNS('circle','svg'), 'circle', \
-                            inkex.addNS('ellipse','svg'), 'ellipse' ]:
-            rx = node.get('r')
-            if rx is not None:
-                ry = rx
-            else:
-                rx = node.get('rx')
-                ry = node.get('ry')
-            cx = float(node.get('cx', '0'))
-            cy = float(node.get('cy', '0'))
-            x1 = cx - float(rx)
-            x2 = cx + float(rx)
-            d = 'M %f %f ' % (x1, cy) + \
-                'A' + rx + ',' + ry + ' 0 1 0 %f,%f' % (x2, cy) + \
-                'A' + rx + ',' + ry + ' 0 1 0 %f,%f' % (x1, cy)
- 
-        if d is not None:
-            p = cubicsuperpath.parsePath(d)
-            applyTransformToPath(m,p)
-            bbox=boxunion(refinedBBox(p),bbox)
-
-        elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
-            refid=node.get(inkex.addNS('href','xlink'))
-            path = '//*[@id="%s"]' % refid[1:]
-            refnode = node.xpath(path)
-            bbox=boxunion(computeBBox(refnode,m),bbox)
-            
-        bbox=boxunion(computeBBox(node,m),bbox)
-    return bbox
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
-- 
cgit