summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rw-r--r--support/dxf_export/__main__.py14
-rwxr-xr-xsupport/dxf_export/better_dxf_outlines.py123
-rwxr-xr-xsupport/dxf_export/bezmisc.py3
-rwxr-xr-xsupport/dxf_export/cubicsuperpath.py6
-rw-r--r--support/dxf_export/dxf_footer.txt62
-rw-r--r--support/dxf_export/dxf_header.txt580
-rwxr-xr-xsupport/dxf_export/dxf_templates.py645
-rw-r--r--support/dxf_export/effect.py175
-rwxr-xr-xsupport/dxf_export/ffgeom.py2
-rwxr-xr-xsupport/dxf_export/inkex.py211
-rwxr-xr-xsupport/dxf_export/simplepath.py2
-rwxr-xr-xsupport/dxf_export/simplestyle.py244
-rwxr-xr-xsupport/dxf_export/simpletransform.py4
-rw-r--r--support/lib/util.py7
-rw-r--r--support/openscad/__main__.py21
15 files changed, 1029 insertions, 1070 deletions
diff --git a/support/dxf_export/__main__.py b/support/dxf_export/__main__.py
index 76c2121..c770a0e 100644
--- a/support/dxf_export/__main__.py
+++ b/support/dxf_export/__main__.py
@@ -1,14 +1,14 @@
import sys, os, xml.etree.ElementTree, shutil
from lib import util
-from . import better_dxf_outlines
+from . import effect
def _export_dxf(in_path, out_path):
- dxf_export = better_dxf_outlines.MyEffect()
+ dxf_export = effect.DXFExportEffect()
dxf_export.affect(args = [in_path], output = False)
with open(out_path, 'w') as file:
- file.write(dxf_export.dxf)
+ dxf_export.write(file)
def _get_inkscape_layer_count(svg_path):
@@ -76,4 +76,10 @@ def main(in_path, out_path):
_export_dxf(temp_svg_path, out_path)
-main(*sys.argv[1:])
+try:
+ main(*sys.argv[1:])
+except util.UserError as e:
+ print 'Error:', e
+ sys.exit(1)
+except KeyboardInterrupt:
+ sys.exit(2)
diff --git a/support/dxf_export/better_dxf_outlines.py b/support/dxf_export/better_dxf_outlines.py
deleted file mode 100755
index 19ec6c8..0000000
--- a/support/dxf_export/better_dxf_outlines.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python
-'''
-Copyright (C) 2005,2007 Aaron Spike, aaron@ekips.org
-- template dxf_outlines.dxf added Feb 2008 by Alvin Penner, penner@vaxxine.com
-- layers, transformation, flattening added April 2008 by Bob Cook, bob@bobcookdev.com
-- bug fix for xpath() calls added February 2009 by Bob Cook, bob@bobcookdev.com
-- max value of 10 on path flattening, August 2011 by Bob Cook, bob@bobcookdev.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
-'''
-import inkex, simplepath, simpletransform, cubicsuperpath, cspsubdiv, dxf_templates, re
-
-class MyEffect(inkex.Effect):
-
- def __init__(self):
-
- inkex.Effect.__init__(self)
- self.dxf = ''
- self.handle = 255
- self.flatness = 0.1
-
- def output(self):
- print self.dxf
-
- def dxf_add(self, str):
- self.dxf += str
-
- def dxf_insert_code(self, code, value):
- self.dxf += code + "\n" + value + "\n"
-
- def dxf_line(self,layer,csp):
- self.dxf_insert_code( '0', 'LINE' )
- self.dxf_insert_code( '8', layer )
- self.dxf_insert_code( '62', '4' )
- self.dxf_insert_code( '5', '%x' % self.handle )
- self.dxf_insert_code( '100', 'AcDbEntity' )
- self.dxf_insert_code( '100', 'AcDbLine' )
- self.dxf_insert_code( '10', '%f' % csp[0][0] )
- self.dxf_insert_code( '20', '%f' % csp[0][1] )
- self.dxf_insert_code( '30', '0.0' )
- self.dxf_insert_code( '11', '%f' % csp[1][0] )
- self.dxf_insert_code( '21', '%f' % csp[1][1] )
- self.dxf_insert_code( '31', '0.0' )
-
- def dxf_point(self,layer,x,y):
- self.dxf_insert_code( '0', 'POINT' )
- self.dxf_insert_code( '8', layer )
- self.dxf_insert_code( '62', '4' )
- self.dxf_insert_code( '5', '%x' % self.handle )
- self.dxf_insert_code( '100', 'AcDbEntity' )
- self.dxf_insert_code( '100', 'AcDbPoint' )
- self.dxf_insert_code( '10', '%f' % x )
- self.dxf_insert_code( '20', '%f' % y )
- self.dxf_insert_code( '30', '0.0' )
-
- def dxf_path_to_lines(self,layer,p):
- f = self.flatness
- is_flat = 0
- while is_flat < 1:
- if f > 10:
- break
- try:
- cspsubdiv.cspsubdiv(p, f)
- is_flat = 1
- except:
- f += 0.1
-
- for sub in p:
- for i in range(len(sub)-1):
- self.handle += 1
- s = sub[i]
- e = sub[i+1]
- self.dxf_line(layer,[s[1],e[1]])
-
- def dxf_path_to_point(self,layer,p):
- bbox = simpletransform.roughBBox(p)
- x = (bbox[0] + bbox[1]) / 2
- y = (bbox[2] + bbox[3]) / 2
- self.dxf_point(layer,x,y)
-
- def effect(self):
- self.dxf_insert_code( '999', 'Inkscape export via "Better DXF Output" (bob@bobcookdev.com)' )
- self.dxf_add( dxf_templates.r14_header )
-
- scale = 25.4/90.0
- h = inkex.unittouu(self.document.getroot().xpath('@height',namespaces=inkex.NSS)[0])
-
- path = '//svg:path'
- for node in self.document.getroot().xpath(path,namespaces=inkex.NSS):
-
- layer = node.getparent().get(inkex.addNS('label','inkscape'))
- if layer == None:
- layer = 'Layer 1'
-
- d = node.get('d')
- p = cubicsuperpath.parsePath(d)
-
- t = node.get('transform')
- if t != None:
- m = simpletransform.parseTransform(t)
- simpletransform.applyTransformToPath(m,p)
-
- m = [[scale,0,0],[0,-scale,h*scale]]
- simpletransform.applyTransformToPath(m,p)
-
- if re.search('drill$',layer,re.I) == None:
- self.dxf_path_to_lines(layer,p)
- else:
- self.dxf_path_to_point(layer,p)
-
- self.dxf_add( dxf_templates.r14_footer )
diff --git a/support/dxf_export/bezmisc.py b/support/dxf_export/bezmisc.py
index e663fa6..b7f5429 100755
--- a/support/dxf_export/bezmisc.py
+++ b/support/dxf_export/bezmisc.py
@@ -243,7 +243,6 @@ def beziertatlength(((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)), l = 0.5, toleranc
bezierlength = bezierlengthSimpson
if __name__ == '__main__':
- import timing
#print linebezierintersect(((,),(,)),((,),(,),(,),(,)))
#print linebezierintersect(((0,1),(0,-1)),((-1,0),(-.5,0),(.5,0),(1,0)))
tol = 0.00000001
@@ -271,4 +270,4 @@ if __name__ == '__main__':
print beziertatlength(curve,0.5)
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/dxf_export/cubicsuperpath.py b/support/dxf_export/cubicsuperpath.py
index af61acb..925efdb 100755
--- a/support/dxf_export/cubicsuperpath.py
+++ b/support/dxf_export/cubicsuperpath.py
@@ -46,8 +46,8 @@ def ArcToPath(p1,params):
rx,ry,teta,longflag,sweepflag,x2,y2=params[:]
teta = teta*pi/180.0
B=[x2,y2]
- if rx==0 or ry==0:
- return([[A,A,A],[B,B,B]])
+ 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)
@@ -166,4 +166,4 @@ def formatPath(p):
return simplepath.formatPath(unCubicSuperPath(p))
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/dxf_export/dxf_footer.txt b/support/dxf_export/dxf_footer.txt
new file mode 100644
index 0000000..a225dd7
--- /dev/null
+++ b/support/dxf_export/dxf_footer.txt
@@ -0,0 +1,62 @@
+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/dxf_export/dxf_header.txt b/support/dxf_export/dxf_header.txt
new file mode 100644
index 0000000..341cb1b
--- /dev/null
+++ b/support/dxf_export/dxf_header.txt
@@ -0,0 +1,580 @@
+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/dxf_export/dxf_templates.py b/support/dxf_export/dxf_templates.py
deleted file mode 100755
index fb26632..0000000
--- a/support/dxf_export/dxf_templates.py
+++ /dev/null
@@ -1,645 +0,0 @@
-r14_header = ''' 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
-'''
-
-
-r14_footer = ''' 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/dxf_export/effect.py b/support/dxf_export/effect.py
new file mode 100644
index 0000000..206ce9d
--- /dev/null
+++ b/support/dxf_export/effect.py
@@ -0,0 +1,175 @@
+"""
+Based on code from Aaron Spike. See http://www.bobcookdev.com/inkscape/inkscape-dxf.html
+"""
+
+import pkgutil, re
+from . import inkex, simpletransform, cubicsuperpath, cspsubdiv
+
+
+def _get_unit_factors_map():
+ # Fluctuates somewhat between Inkscape releases.
+ 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 DXFExportEffect(inkex.Effect):
+ _unit_factors = _get_unit_factors_map()
+
+ def __init__(self):
+ inkex.Effect.__init__(self)
+
+ self._dxf_instructions = []
+ self._handle = 255
+ self._flatness = 0.1
+
+ def _get_user_unit(self):
+ """
+ Return the size in pixels of the unit used for measures without an explicit unit.
+ """
+
+ document_height = self._measure_to_pixels(self._get_document_height_attr())
+ view_box_attr = self.document.getroot().get('viewBox')
+
+ if view_box_attr:
+ _, _, _, view_box_height = map(float, view_box_attr.split())
+ else:
+ view_box_height = document_height
+
+ return document_height / view_box_height
+
+ def _get_document_unit(self):
+ """
+ Return the size in pixels that the user is working with in Inkscape.
+ """
+
+ inkscape_unit_attrs = self.document.getroot().xpath('./sodipodi:namedview/@inkscape:document-units', namespaces = inkex.NSS)
+
+ if inkscape_unit_attrs:
+ unit = inkscape_unit_attrs[0]
+ else:
+ _, unit = self._parse_measure(self._get_document_height_attr())
+
+ return self._get_unit_factor(unit)
+
+ def _get_document_height_attr(self):
+ return self.document.getroot().xpath('@height', namespaces = inkex.NSS)[0]
+
+ def _add_instruction(self, code, value):
+ self._dxf_instructions.append((code, str(value)))
+
+ def _add_dxf_line(self, layer, csp):
+ self._add_instruction(0, 'LINE')
+ self._add_instruction(8, layer)
+ self._add_instruction(62, 4)
+ self._add_instruction(5, '{:x}'.format(self._handle))
+ self._add_instruction(100, 'AcDbEntity')
+ self._add_instruction(100, 'AcDbLine')
+ self._add_instruction(10, repr(csp[0][0]))
+ self._add_instruction(20, repr(csp[0][1]))
+ self._add_instruction(30, 0.0)
+ self._add_instruction(11, repr(csp[1][0]))
+ self._add_instruction(21, repr(csp[1][1]))
+ self._add_instruction(31, 0.0)
+
+ def _add_dxf_path(self, layer, path):
+ cspsubdiv.cspsubdiv(path, self._flatness)
+
+ for sub in path:
+ for i in range(len(sub) - 1):
+ self._handle += 1
+ s = sub[i]
+ e = sub[i + 1]
+ self._add_dxf_line(layer, [s[1], e[1]])
+
+ def _add_dxf_shape(self, node, document_transform, element_transform):
+ layer = self._get_inkscape_layer(node)
+ path = cubicsuperpath.parsePath(node.get('d'))
+
+ transform = simpletransform.composeTransform(
+ document_transform,
+ simpletransform.composeParents(node, element_transform))
+
+ simpletransform.applyTransformToPath(transform, path)
+
+ self._add_dxf_path(layer, path)
+
+ def effect(self):
+ user_unit = self._get_user_unit()
+ document_unit = self._get_document_unit()
+ height = self._measure_to_pixels(self._get_document_height_attr())
+
+ document_transform = simpletransform.composeTransform(
+ [[1 / document_unit, 0, 0], [0, 1 / document_unit, 0]],
+ [[1, 0, 0], [0, -1, height]])
+
+ element_transform = [[user_unit, 0, 0], [0, user_unit, 0]]
+
+ for node in self.document.getroot().xpath('//svg:path', namespaces = inkex.NSS):
+ self._add_dxf_shape(node, document_transform, element_transform)
+
+ def write(self, file):
+ file.write(pkgutil.get_data(__name__, 'dxf_header.txt'))
+
+ for code, value in self._dxf_instructions:
+ print >> file, code
+ print >> file, value
+
+ file.write(pkgutil.get_data(__name__, 'dxf_footer.txt'))
+
+ @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, default_unit_factor = None):
+ """
+ Parse a string containing a measure and return it's value converted to pixels. If the measure has no unit, it will be assumed that the unit has the size of the specified number of pixels.
+ """
+
+ value, unit = cls._parse_measure(string)
+
+ return value * cls._get_unit_factor(unit, default_unit_factor)
+
+ @classmethod
+ def _get_inkscape_layer(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 ''
+
+ @classmethod
+ def _get_unit_factor(cls, unit, default = None):
+ if unit is None:
+ if default is None:
+ default = 1
+
+ return default
+ else:
+ return cls._unit_factors[unit]
diff --git a/support/dxf_export/ffgeom.py b/support/dxf_export/ffgeom.py
index 1983586..ef8799b 100755
--- a/support/dxf_export/ffgeom.py
+++ b/support/dxf_export/ffgeom.py
@@ -138,4 +138,4 @@ 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 encoding=utf-8 textwidth=99
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/dxf_export/inkex.py b/support/dxf_export/inkex.py
index e487822..19e860b 100755
--- a/support/dxf_export/inkex.py
+++ b/support/dxf_export/inkex.py
@@ -1,9 +1,16 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
"""
inkex.py
A helper module for creating Inkscape extensions
-Copyright (C) 2005,2007 Aaron Spike, aaron@ekips.org
+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
@@ -19,10 +26,14 @@ 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 sys, copy, optparse, random, re
+import copy
import gettext
+import optparse
+import os
+import random
+import re
+import sys
from math import *
-_ = gettext.gettext
#a dictionary of all of the xmlns prefixes in a standard inkscape doc
NSS = {
@@ -37,34 +48,35 @@ u'xlink' :u'http://www.w3.org/1999/xlink',
u'xml' :u'http://www.w3.org/XML/1998/namespace'
}
-#a dictionary of unit to user unit conversion factors
-uuconv = {'in':90.0, 'pt':1.25, 'px':1, 'mm':3.5433070866, 'cm':35.433070866, 'm':3543.3070866,
- 'km':3543307.0866, 'pc':15.0, 'yd':3240 , 'ft':1080}
-def unittouu(string):
- '''Returns userunits given a string representation of units in another system'''
- unit = re.compile('(%s)$' % '|'.join(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()])
+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:
- retval = 0.0
- if u:
try:
- return retval * uuconv[u.string[u.start():u.end()]]
+ localdir = os.environ['PACKAGE_LOCALE_DIR'];
+ trans = gettext.translation(domain, localdir, fallback=True)
except KeyError:
- pass
- return retval
-
-def uutounit(val, unit):
- return val/uuconv[unit]
-
-try:
- from lxml import etree
-except:
- sys.exit(_('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'))
+ trans = gettext.translation(domain, fallback=True)
+ #sys.stderr.write(str(localdir) + "\n")
+ trans.install()
def debug(what):
sys.stderr.write(str(what) + "\n")
@@ -79,13 +91,31 @@ def errormsg(msg):
Note that this should always be combined with translation:
- import gettext
- _ = gettext.gettext
+ import inkex
+ inkex.localize()
...
inkex.errormsg(_("This extension requires two selected paths."))
"""
- sys.stderr.write((unicode(msg) + "\n").encode("UTF-8"))
+ 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
@@ -128,20 +158,37 @@ class Effect:
"""Collect command line arguments"""
self.options, self.args = self.OptionParser.parse_args(args)
- def parse(self,file=None):
+ def parse(self, filename=None):
"""Parse document in specified file or on stdin"""
- try:
+
+ # First try to open the file from the function argument
+ if filename != None:
try:
- stream = open(file,'r')
- except:
- stream = open(self.svg_file,'r')
- except:
+ 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()
@@ -156,10 +203,10 @@ class Effect:
xattr = self.document.xpath('//sodipodi:namedview/@inkscape:cx', namespaces=NSS)
yattr = self.document.xpath('//sodipodi:namedview/@inkscape:cy', namespaces=NSS)
- doc_height = unittouu(self.document.getroot().get('height'))
if xattr and yattr:
- x = xattr[0]
- y = yattr[0]
+ 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
@@ -236,6 +283,88 @@ class Effect:
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 encoding=utf-8 textwidth=99
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/dxf_export/simplepath.py b/support/dxf_export/simplepath.py
index f62b1b4..94ab092 100755
--- a/support/dxf_export/simplepath.py
+++ b/support/dxf_export/simplepath.py
@@ -209,4 +209,4 @@ def rotatePath(p, a, cx = 0, cy = 0):
params[i + 1] = (r * math.sin(theta)) + cy
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/support/dxf_export/simplestyle.py b/support/dxf_export/simplestyle.py
deleted file mode 100755
index 3ec971e..0000000
--- a/support/dxf_export/simplestyle.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/usr/bin/env python
-"""
-simplestyle.py
-Two simple functions for working with inline css
-and some color handling on top.
-
-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
-"""
-
-svgcolors={
- 'aliceblue':'#f0f8ff',
- 'antiquewhite':'#faebd7',
- 'aqua':'#00ffff',
- 'aquamarine':'#7fffd4',
- 'azure':'#f0ffff',
- 'beige':'#f5f5dc',
- 'bisque':'#ffe4c4',
- 'black':'#000000',
- 'blanchedalmond':'#ffebcd',
- 'blue':'#0000ff',
- 'blueviolet':'#8a2be2',
- 'brown':'#a52a2a',
- 'burlywood':'#deb887',
- 'cadetblue':'#5f9ea0',
- 'chartreuse':'#7fff00',
- 'chocolate':'#d2691e',
- 'coral':'#ff7f50',
- 'cornflowerblue':'#6495ed',
- 'cornsilk':'#fff8dc',
- 'crimson':'#dc143c',
- 'cyan':'#00ffff',
- 'darkblue':'#00008b',
- 'darkcyan':'#008b8b',
- 'darkgoldenrod':'#b8860b',
- 'darkgray':'#a9a9a9',
- 'darkgreen':'#006400',
- 'darkgrey':'#a9a9a9',
- 'darkkhaki':'#bdb76b',
- 'darkmagenta':'#8b008b',
- 'darkolivegreen':'#556b2f',
- 'darkorange':'#ff8c00',
- 'darkorchid':'#9932cc',
- 'darkred':'#8b0000',
- 'darksalmon':'#e9967a',
- 'darkseagreen':'#8fbc8f',
- 'darkslateblue':'#483d8b',
- 'darkslategray':'#2f4f4f',
- 'darkslategrey':'#2f4f4f',
- 'darkturquoise':'#00ced1',
- 'darkviolet':'#9400d3',
- 'deeppink':'#ff1493',
- 'deepskyblue':'#00bfff',
- 'dimgray':'#696969',
- 'dimgrey':'#696969',
- 'dodgerblue':'#1e90ff',
- 'firebrick':'#b22222',
- 'floralwhite':'#fffaf0',
- 'forestgreen':'#228b22',
- 'fuchsia':'#ff00ff',
- 'gainsboro':'#dcdcdc',
- 'ghostwhite':'#f8f8ff',
- 'gold':'#ffd700',
- 'goldenrod':'#daa520',
- 'gray':'#808080',
- 'grey':'#808080',
- 'green':'#008000',
- 'greenyellow':'#adff2f',
- 'honeydew':'#f0fff0',
- 'hotpink':'#ff69b4',
- 'indianred':'#cd5c5c',
- 'indigo':'#4b0082',
- 'ivory':'#fffff0',
- 'khaki':'#f0e68c',
- 'lavender':'#e6e6fa',
- 'lavenderblush':'#fff0f5',
- 'lawngreen':'#7cfc00',
- 'lemonchiffon':'#fffacd',
- 'lightblue':'#add8e6',
- 'lightcoral':'#f08080',
- 'lightcyan':'#e0ffff',
- 'lightgoldenrodyellow':'#fafad2',
- 'lightgray':'#d3d3d3',
- 'lightgreen':'#90ee90',
- 'lightgrey':'#d3d3d3',
- 'lightpink':'#ffb6c1',
- 'lightsalmon':'#ffa07a',
- 'lightseagreen':'#20b2aa',
- 'lightskyblue':'#87cefa',
- 'lightslategray':'#778899',
- 'lightslategrey':'#778899',
- 'lightsteelblue':'#b0c4de',
- 'lightyellow':'#ffffe0',
- 'lime':'#00ff00',
- 'limegreen':'#32cd32',
- 'linen':'#faf0e6',
- 'magenta':'#ff00ff',
- 'maroon':'#800000',
- 'mediumaquamarine':'#66cdaa',
- 'mediumblue':'#0000cd',
- 'mediumorchid':'#ba55d3',
- 'mediumpurple':'#9370db',
- 'mediumseagreen':'#3cb371',
- 'mediumslateblue':'#7b68ee',
- 'mediumspringgreen':'#00fa9a',
- 'mediumturquoise':'#48d1cc',
- 'mediumvioletred':'#c71585',
- 'midnightblue':'#191970',
- 'mintcream':'#f5fffa',
- 'mistyrose':'#ffe4e1',
- 'moccasin':'#ffe4b5',
- 'navajowhite':'#ffdead',
- 'navy':'#000080',
- 'oldlace':'#fdf5e6',
- 'olive':'#808000',
- 'olivedrab':'#6b8e23',
- 'orange':'#ffa500',
- 'orangered':'#ff4500',
- 'orchid':'#da70d6',
- 'palegoldenrod':'#eee8aa',
- 'palegreen':'#98fb98',
- 'paleturquoise':'#afeeee',
- 'palevioletred':'#db7093',
- 'papayawhip':'#ffefd5',
- 'peachpuff':'#ffdab9',
- 'peru':'#cd853f',
- 'pink':'#ffc0cb',
- 'plum':'#dda0dd',
- 'powderblue':'#b0e0e6',
- 'purple':'#800080',
- 'red':'#ff0000',
- 'rosybrown':'#bc8f8f',
- 'royalblue':'#4169e1',
- 'saddlebrown':'#8b4513',
- 'salmon':'#fa8072',
- 'sandybrown':'#f4a460',
- 'seagreen':'#2e8b57',
- 'seashell':'#fff5ee',
- 'sienna':'#a0522d',
- 'silver':'#c0c0c0',
- 'skyblue':'#87ceeb',
- 'slateblue':'#6a5acd',
- 'slategray':'#708090',
- 'slategrey':'#708090',
- 'snow':'#fffafa',
- 'springgreen':'#00ff7f',
- 'steelblue':'#4682b4',
- 'tan':'#d2b48c',
- 'teal':'#008080',
- 'thistle':'#d8bfd8',
- 'tomato':'#ff6347',
- 'turquoise':'#40e0d0',
- 'violet':'#ee82ee',
- 'wheat':'#f5deb3',
- 'white':'#ffffff',
- 'whitesmoke':'#f5f5f5',
- 'yellow':'#ffff00',
- 'yellowgreen':'#9acd32'
-}
-
-def parseStyle(s):
- """Create a dictionary from the value of an inline style attribute"""
- if s is None:
- return {}
- else:
- return dict([[x.strip() for x in i.split(":")] for i in s.split(";") if len(i.strip())])
-
-def formatStyle(a):
- """Format an inline style attribute from a dictionary"""
- return ";".join([att+":"+str(val) for att,val in a.iteritems()])
-
-def isColor(c):
- """Determine if its a color we can use. If not, leave it unchanged."""
- if c.startswith('#') and (len(c)==4 or len(c)==7):
- return True
- if c.lower() in svgcolors.keys():
- return True
- #might be "none" or some undefined color constant or rgb()
- #however, rgb() shouldnt occur at this point
- return False
-
-def parseColor(c):
- """Creates a rgb int array"""
- tmp = svgcolors.get(c.lower())
- if tmp is not None:
- c = tmp
- elif c.startswith('#') and len(c)==4:
- c='#'+c[1:2]+c[1:2]+c[2:3]+c[2:3]+c[3:]+c[3:]
- elif c.startswith('rgb('):
- # remove the rgb(...) stuff
- tmp = c.strip()[4:-1]
- numbers = [number.strip() for number in tmp.split(',')]
- converted_numbers = []
- if len(numbers) == 3:
- for num in numbers:
- if num.endswith(r'%'):
- converted_numbers.append(int(float(num[0:-1])*255/100))
- else:
- converted_numbers.append(int(num))
- return tuple(converted_numbers)
- else:
- return (0,0,0)
- try:
- r=int(c[1:3],16)
- g=int(c[3:5],16)
- b=int(c[5:],16)
- except:
- # unknown color ...
- # Return a default color. Maybe not the best thing to do but probably
- # better than raising an exception.
- return(0,0,0)
- return (r,g,b)
-
-def formatColoria(a):
- """int array to #rrggbb"""
- return '#%02x%02x%02x' % (a[0],a[1],a[2])
-
-def formatColorfa(a):
- """float array to #rrggbb"""
- return '#%02x%02x%02x' % (int(round(a[0]*255)),int(round(a[1]*255)),int(round(a[2]*255)))
-
-def formatColor3i(r,g,b):
- """3 ints to #rrggbb"""
- return '#%02x%02x%02x' % (r,g,b)
-
-def formatColor3f(r,g,b):
- """3 floats to #rrggbb"""
- return '#%02x%02x%02x' % (int(round(r*255)),int(round(g*255)),int(round(b*255)))
-
-
-# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
diff --git a/support/dxf_export/simpletransform.py b/support/dxf_export/simpletransform.py
index 47cc61e..55082ed 100755
--- a/support/dxf_export/simpletransform.py
+++ b/support/dxf_export/simpletransform.py
@@ -21,8 +21,8 @@ barraud@math.univ-lille1.fr
This code defines several functions to make handling of transform
attribute easier.
'''
-import inkex, cubicsuperpath, bezmisc, simplestyle
-import copy, math, re
+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:
diff --git a/support/lib/util.py b/support/lib/util.py
index bede240..8b65e58 100644
--- a/support/lib/util.py
+++ b/support/lib/util.py
@@ -1,6 +1,10 @@
import contextlib, subprocess, tempfile, shutil, re, os
+class UserError(Exception):
+ pass
+
+
@contextlib.contextmanager
def TemporaryDirectory():
dir = tempfile.mkdtemp()
@@ -15,7 +19,8 @@ def command(args):
process = subprocess.Popen(args)
process.wait()
- assert not process.returncode
+ if process.returncode:
+ raise UserError('Command failed: {}'.format(' '.join(args)))
def bash_escape_string(string):
diff --git a/support/openscad/__main__.py b/support/openscad/__main__.py
index 08b2ab6..3c103e5 100644
--- a/support/openscad/__main__.py
+++ b/support/openscad/__main__.py
@@ -21,17 +21,32 @@ def main(in_path, out_path, deps_path):
temp_mk_path = os.path.join(temp_dir, 'mk')
temp_files_path = os.path.join(temp_dir, 'files')
- _openscad(in_path, out_path, temp_deps_path)
+ # OpenSCAD requires the output file name to end in .stl
+ temp_stl_path = os.path.join(temp_dir, 'out.stl')
+
+ _openscad(in_path, temp_stl_path, temp_deps_path)
mk_content = '%:; echo "$@" >> {}'.format(util.bash_escape_string(temp_files_path))
+ # Use make to parse the dependency makefile written by OpenSCAD
util.write_file(temp_mk_path, mk_content.encode())
util.command(['make', '-s', '-B', '-f', temp_mk_path, '-f', temp_deps_path])
+ # All dependencies as paths relative to the project root.
deps = set(map(relpath, util.read_file(temp_files_path).decode().splitlines()))
- ignored_files = set(map(relpath, [temp_deps_path, temp_mk_path, in_path, out_path]))
+ # Relative paths to all files that should not appear in the dependency makefile.
+ ignored_files = set(map(relpath, [in_path, temp_deps_path, temp_mk_path, temp_stl_path]))
+
+ # Write output files.
_write_dependencies(deps_path, relpath(out_path), deps - ignored_files)
+ os.rename(temp_stl_path, out_path)
-main(*sys.argv[1:])
+try:
+ main(*sys.argv[1:])
+except util.UserError as e:
+ print 'Error:', e
+ sys.exit(1)
+except KeyboardInterrupt:
+ sys.exit(2)