summaryrefslogtreecommitdiffstats
path: root/share/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions')
-rw-r--r--share/extensions/Barcode/Base.py3
-rw-r--r--share/extensions/Makefile.am350
-rwxr-xr-xshare/extensions/dimension.py21
-rwxr-xr-xshare/extensions/dots.py2
-rwxr-xr-xshare/extensions/draw_from_triangle.py10
-rwxr-xr-xshare/extensions/foldablebox.py2
-rwxr-xr-xshare/extensions/grid_cartesian.py12
-rwxr-xr-xshare/extensions/grid_isometric.py6
-rwxr-xr-xshare/extensions/grid_polar.py11
-rwxr-xr-xshare/extensions/guides_creator.py4
-rwxr-xr-xshare/extensions/hershey.py5
-rw-r--r--share/extensions/hpgl_decoder.py1
-rw-r--r--share/extensions/hpgl_encoder.py165
-rw-r--r--share/extensions/hpgl_input.inx4
-rw-r--r--share/extensions/hpgl_input.py1
-rw-r--r--share/extensions/hpgl_output.inx32
-rwxr-xr-xshare/extensions/hpgl_output.py19
-rwxr-xr-xshare/extensions/ink2canvas.py2
-rw-r--r--share/extensions/ink2canvas/canvas.py5
-rwxr-xr-xshare/extensions/inkex.py35
-rwxr-xr-xshare/extensions/interp.py14
-rwxr-xr-xshare/extensions/lindenmayer.py3
-rwxr-xr-xshare/extensions/measure.py5
-rw-r--r--share/extensions/merge_styles.inx21
-rwxr-xr-xshare/extensions/merge_styles.py134
-rwxr-xr-xshare/extensions/perspective.py5
-rw-r--r--share/extensions/plotter.inx41
-rw-r--r--share/extensions/plotter.py91
-rwxr-xr-xshare/extensions/polyhedron_3d.py3
-rwxr-xr-xshare/extensions/printing_marks.py17
-rwxr-xr-xshare/extensions/render_alphabetsoup.py2
-rwxr-xr-xshare/extensions/render_barcode.py39
-rwxr-xr-xshare/extensions/render_barcode_datamatrix.py3
-rwxr-xr-xshare/extensions/render_barcode_qrcode.py3
-rw-r--r--share/extensions/render_gear_rack.py6
-rw-r--r--share/extensions/render_gears.py6
-rwxr-xr-xshare/extensions/rtree.py4
-rwxr-xr-xshare/extensions/spirograph.py5
-rwxr-xr-xshare/extensions/summersnight.py5
-rw-r--r--share/extensions/tar_layers.inx19
-rwxr-xr-xshare/extensions/tar_layers.py121
-rwxr-xr-xshare/extensions/test/hpgl_output.test.py4
-rwxr-xr-xshare/extensions/text_extract.py27
-rw-r--r--share/extensions/text_merge.inx2
-rw-r--r--share/extensions/text_merge.py3
-rwxr-xr-xshare/extensions/triangle.py20
-rwxr-xr-xshare/extensions/voronoi2svg.py12
-rwxr-xr-xshare/extensions/webslicer_create_rect.py9
-rwxr-xr-xshare/extensions/wireframe_sphere.py16
49 files changed, 694 insertions, 636 deletions
diff --git a/share/extensions/Barcode/Base.py b/share/extensions/Barcode/Base.py
index 8fee6a996..b86185388 100644
--- a/share/extensions/Barcode/Base.py
+++ b/share/extensions/Barcode/Base.py
@@ -39,6 +39,7 @@ class Barcode(object):
self.document = param.get('document', None)
self.x = int(param.get('x', 0))
self.y = int(param.get('y', 0))
+ self.scale = param.get('scale', 1)
self.height = param.get('height', 30)
self.label = param.get('text', None)
self.string = self.encode( self.label )
@@ -77,7 +78,7 @@ class Barcode(object):
barcode = etree.Element('{%s}%s' % (svg_uri,'g'))
barcode.set('id', name)
barcode.set('style', 'fill: black;')
- barcode.set('transform', 'translate(%d,%d)' % (self.x, self.y))
+ barcode.set('transform', 'translate(%d,%d) scale(%f)' % (self.x, self.y, self.scale))
bar_offset = 0
bar_id = 1
diff --git a/share/extensions/Makefile.am b/share/extensions/Makefile.am
index b53446999..2c1e23954 100644
--- a/share/extensions/Makefile.am
+++ b/share/extensions/Makefile.am
@@ -13,177 +13,9 @@ otherstuffdir = $(datadir)/inkscape/extensions
moduledir = $(datadir)/inkscape/extensions
-# If you remove an extension from here, either add it to EXTRA_DIST
-# below, or remove all mention of it from po/inkscape.pot as well.
-extensions = \
- addnodes.py \
- bezmisc.py \
- chardataeffect.py\
- color_blackandwhite.py\
- color_brighter.py\
- color_custom.py\
- color_darker.py\
- color_desaturate.py\
- coloreffect.py\
- color_grayscale.py\
- color_HSL_adjust.py\
- color_lesshue.py\
- color_lesslight.py\
- color_lesssaturation.py\
- color_morehue.py\
- color_morelight.py\
- color_moresaturation.py\
- color_negative.py\
- color_randomize.py\
- color_removeblue.py\
- color_removegreen.py\
- color_removered.py\
- color_rgbbarrel.py\
- color_replace.py\
- convert2dashes.py\
- cspsubdiv.py \
- cubicsuperpath.py \
- dia2svg.sh \
- dimension.py \
- dm2svg.py \
- dots.py \
- draw_from_triangle.py \
- dxf_input.py \
- dxf_outlines.py \
- dxf_templates.py \
- edge3d.py \
- embedimage.py \
- embed_raster_in_svg.pl \
- empty_page.py \
- eqtexsvg.py \
- export_gimp_palette.py \
- extractimage.py \
- extrude.py \
- ffgeom.py\
- fig2dev-ext.py \
- flatten.py \
- foldablebox.py \
- fractalize.py \
- funcplot.py \
- render_gears.py \
- render_gear_rack.py \
- gcodetools.py\
- generate_voronoi.py \
- gimp_xcf.py \
- grid_cartesian.py \
- grid_isometric.py \
- grid_polar.py \
- guides_creator.py \
- guillotine.py \
- handles.py \
- hershey.py \
- hersheydata.py \
- hpgl_decoder.py \
- hpgl_encoder.py \
- hpgl_input.py \
- hpgl_output.py \
- ink2canvas.py \
- inkex.py \
- inkscape_follow_link.py \
- inkwebeffect.py \
- interp.py \
- interp_att_g.py \
- jessyInk_autoTexts.py \
- jessyInk_effects.py \
- jessyInk_export.py \
- jessyInk_install.py \
- jessyInk_keyBindings.py \
- jessyInk_masterSlide.py \
- jessyInk_mouseHandler.py \
- jessyInk_summary.py \
- jessyInk_transitions.py \
- jessyInk_uninstall.py \
- jessyInk_video.py \
- jessyInk_view.py \
- launch_webbrowser.py \
- layers2svgfont.py \
- svgfont2layers.py \
- layout_nup.py \
- layout_nup_pageframe.py \
- lindenmayer.py \
- lorem_ipsum.py \
- markers_strokepaint.py \
- measure.py \
- motion.py \
- new_glyph_layer.py \
- next_glyph_layer.py \
- previous_glyph_layer.py \
- param_curves.py \
- pathalongpath.py\
- pathscatter.py\
- pathmodifier.py\
- perfectboundcover.py \
- perspective.py \
- pixelsnap.py \
- plotter.py \
- plt_output.py \
- polyhedron_3d.py \
- printing_marks.py \
- ps2dxf.sh \
- ps2pdf-ext.py \
- pturtle.py \
- radiusrand.py \
- replace_font.py \
- restack.py \
- render_barcode.py \
- render_barcode_datamatrix.py \
- render_barcode_qrcode.py \
- render_alphabetsoup.py \
- render_alphabetsoup_config.py \
- rtree.py \
- rubberstretch.py\
- run_command.py \
- scour.py \
- scour.inkscape.py \
- setup_typography_canvas.py \
- simplepath.py \
- simplepath.rb \
- simplestyle.py \
- simpletransform.py \
- sk1_output.py \
- sk2svg.sh \
- spirograph.py\
- split.py \
- straightseg.py \
- summersnight.py \
- svgcalendar.py \
- svg_regex.py \
- svg_and_media_zip_output.py \
- synfig_fileformat.py \
- synfig_output.py \
- synfig_prepare.py \
- text_extract.py \
- svg_transform.py \
- text_uppercase.py \
- text_lowercase.py \
- text_sentencecase.py \
- text_titlecase.py \
- text_flipcase.py \
- text_randomcase.py \
- text_braille.py \
- text_merge.py \
- triangle.py \
- uniconv-ext.py \
- uniconv_output.py \
- voronoi.py \
- voronoi2svg.py \
- webslicer_create_group.py \
- webslicer_create_rect.py \
- webslicer_effect.py \
- webslicer_export.py \
- web-set-att.py \
- web-transmit-att.py \
- whirl.py \
- wireframe_sphere.py \
- wmf_output.py \
- yocto_css.py
+extension_SCRIPTS = $(wildcard $(srcdir)/*.py)
-otherstuff = \
+otherstuff_DATA = \
fontfix.conf \
inkweb.js \
jessyInk.js \
@@ -196,183 +28,7 @@ otherstuff = \
svg2xaml.xsl \
xaml2svg.xsl
-modules = \
- addnodes.inx \
- ai_input.inx \
- aisvg.inx \
- ccx_input.inx \
- cdr_input.inx \
- cdt_input.inx \
- cgm_input.inx \
- cmx_input.inx \
- color_blackandwhite.inx\
- color_brighter.inx\
- color_custom.inx \
- color_darker.inx\
- color_desaturate.inx\
- color_grayscale.inx\
- color_HSL_adjust.inx\
- color_lesshue.inx\
- color_lesslight.inx\
- color_lesssaturation.inx\
- color_morehue.inx\
- color_morelight.inx\
- color_moresaturation.inx\
- color_negative.inx\
- color_randomize.inx\
- color_removeblue.inx\
- color_removegreen.inx\
- color_removered.inx\
- color_rgbbarrel.inx\
- color_replace.inx\
- convert2dashes.inx\
- dhw_input.inx \
- dia.inx \
- dimension.inx \
- dots.inx \
- draw_from_triangle.inx \
- dxf_input.inx \
- dxf_outlines.inx \
- dxf_output.inx \
- edge3d.inx \
- embedimage.inx \
- embedselectedimages.inx \
- empty_page.inx \
- eps_input.inx \
- eqtexsvg.inx \
- export_gimp_palette.inx \
- extractimage.inx \
- extrude.inx \
- fig_input.inx \
- flatten.inx \
- foldablebox.inx \
- fractalize.inx \
- funcplot.inx \
- render_gears.inx \
- render_gear_rack.inx \
- gcodetools_about.inx\
- gcodetools_area.inx\
- gcodetools_check_for_updates.inx\
- gcodetools_dxf_points.inx\
- gcodetools_engraving.inx\
- gcodetools_graffiti.inx\
- gcodetools_lathe.inx\
- gcodetools_orientation_points.inx\
- gcodetools_path_to_gcode.inx\
- gcodetools_prepare_path_for_plasma.inx\
- gcodetools_tools_library.inx\
- generate_voronoi.inx \
- gimp_xcf.inx \
- grid_cartesian.inx \
- grid_isometric.inx \
- grid_polar.inx \
- guides_creator.inx \
- guillotine.inx \
- handles.inx \
- hershey.inx \
- hpgl_input.inx \
- hpgl_output.inx \
- ink2canvas.inx \
- inkscape_follow_link.inx \
- inkscape_help_askaquestion.inx \
- inkscape_help_commandline.inx \
- inkscape_help_faq.inx\
- inkscape_help_manual.inx \
- inkscape_help_relnotes.inx \
- inkscape_help_reportabug.inx \
- inkscape_help_svgspec.inx \
- inkscape_help_keys.inx \
- interp.inx \
- interp_att_g.inx \
- jessyInk_autoTexts.inx \
- jessyInk_effects.inx \
- jessyInk_export.inx \
- jessyInk_install.inx \
- jessyInk_keyBindings.inx \
- jessyInk_masterSlide.inx \
- jessyInk_mouseHandler.inx \
- jessyInk_summary.inx \
- jessyInk_transitions.inx \
- jessyInk_uninstall.inx \
- jessyInk_video.inx \
- jessyInk_view.inx \
- layers2svgfont.inx \
- svgfont2layers.inx \
- layout_nup.inx \
- lindenmayer.inx \
- lorem_ipsum.inx \
- markers_strokepaint.inx \
- measure.inx \
- motion.inx \
- new_glyph_layer.inx \
- next_glyph_layer.inx \
- previous_glyph_layer.inx \
- param_curves.inx \
- pathalongpath.inx\
- pathscatter.inx\
- perfectboundcover.inx \
- perspective.inx \
- pixelsnap.inx \
- plotter.inx \
- plt_input.inx \
- plt_output.inx \
- polyhedron_3d.inx \
- printing_marks.inx \
- ps_input.inx \
- radiusrand.inx \
- render_barcode.inx \
- render_barcode_datamatrix.inx \
- render_barcode_qrcode.inx \
- render_alphabetsoup.inx \
- replace_font.inx \
- restack.inx \
- rubberstretch.inx \
- rtree.inx \
- scour.inx \
- setup_typography_canvas.inx \
- sk_input.inx \
- sk1_input.inx \
- sk1_output.inx \
- spirograph.inx \
- split.inx \
- straightseg.inx \
- summersnight.inx \
- svg2fxg.inx \
- svg2xaml.inx \
- svg_and_media_zip_output.inx \
- svgcalendar.inx \
- synfig_output.inx \
- text_extract.inx \
- text_uppercase.inx\
- text_lowercase.inx \
- text_sentencecase.inx \
- text_titlecase.inx \
- text_flipcase.inx \
- text_randomcase.inx \
- text_braille.inx \
- text_merge.inx \
- triangle.inx \
- voronoi2svg.inx \
- webslicer_create_group.inx \
- webslicer_create_rect.inx \
- webslicer_export.inx \
- web-set-att.inx \
- web-transmit-att.inx \
- whirl.inx \
- wireframe_sphere.inx \
- wmf_input.inx \
- wmf_output.inx \
- xaml2svg.inx
-
-
-extension_SCRIPTS = \
- $(extensions)
-
-otherstuff_DATA = \
- $(otherstuff)
-
-module_DATA = \
- $(modules)
+module_DATA = $(wildcard $(srcdir)/*.inx)
EXTRA_DIST = \
$(extension_SCRIPTS) $(otherstuff_DATA) $(module_DATA)
diff --git a/share/extensions/dimension.py b/share/extensions/dimension.py
index 4285effeb..30b674201 100755
--- a/share/extensions/dimension.py
+++ b/share/extensions/dimension.py
@@ -100,8 +100,9 @@ class Dimension(pathmodifier.PathModifier):
return line
def effect(self):
- self.xoffset = self.options.xoffset
- self.yoffset = self.options.yoffset
+ scale = self.unittouu('1px') # convert to document units
+ self.xoffset = scale*self.options.xoffset
+ self.yoffset = scale*self.options.yoffset
# query inkscape about the bounding box
if len(self.options.ids) == 0:
@@ -117,11 +118,11 @@ class Dimension(pathmodifier.PathModifier):
if bsubprocess:
p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE)
rc = p.wait()
- q[query] = float(p.stdout.read())
+ q[query] = scale*float(p.stdout.read())
err = p.stderr.read()
else:
f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:]
- q[query] = float(f.read())
+ q[query] = scale*float(f.read())
f.close()
err.close()
self.bbox = (q['x'], q['x']+q['width'], q['y'], q['y']+q['height'])
@@ -146,29 +147,29 @@ class Dimension(pathmodifier.PathModifier):
line = self.dimHLine(self.bbox[2], [0, 1])
line.set('marker-start', 'url(#Arrow1Lstart)')
line.set('marker-end', 'url(#Arrow1Lend)')
- line.set('stroke-width', '1')
+ line.set('stroke-width', str(scale))
group.append(line)
line = self.dimVLine(self.bbox[0], [0, 2])
- line.set('stroke-width', '0.5')
+ line.set('stroke-width', str(0.5*scale))
group.append(line)
line = self.dimVLine(self.bbox[1], [0, 2])
- line.set('stroke-width', '0.5')
+ line.set('stroke-width', str(0.5*scale))
group.append(line)
line = self.dimVLine(self.bbox[0], [1, 0])
line.set('marker-start', 'url(#Arrow1Lstart)')
line.set('marker-end', 'url(#Arrow1Lend)')
- line.set('stroke-width', '1')
+ line.set('stroke-width', str(scale))
group.append(line)
line = self.dimHLine(self.bbox[2], [2, 0])
- line.set('stroke-width', '0.5')
+ line.set('stroke-width', str(0.5*scale))
group.append(line)
line = self.dimHLine(self.bbox[3], [2, 0])
- line.set('stroke-width', '0.5')
+ line.set('stroke-width', str(0.5*scale))
group.append(line)
for id, node in self.selected.iteritems():
diff --git a/share/extensions/dots.py b/share/extensions/dots.py
index 33ead21e7..dc533ffb6 100755
--- a/share/extensions/dots.py
+++ b/share/extensions/dots.py
@@ -112,7 +112,7 @@ class Dots(inkex.Effect):
def addText(self,node,x,y,text):
new = inkex.etree.SubElement(node,inkex.addNS('text','svg'))
- s = {'font-size': self.options.fontsize, 'fill-opacity': '1.0', 'stroke': 'none',
+ s = {'font-size': self.unittouu(self.options.fontsize), 'fill-opacity': '1.0', 'stroke': 'none',
'font-weight': 'normal', 'font-style': 'normal', 'fill': '#999'}
new.set('style', simplestyle.formatStyle(s))
new.set('x', str(x))
diff --git a/share/extensions/draw_from_triangle.py b/share/extensions/draw_from_triangle.py
index 414363e86..42cda7035 100755
--- a/share/extensions/draw_from_triangle.py
+++ b/share/extensions/draw_from_triangle.py
@@ -148,6 +148,8 @@ def get_n_points_from_path( node, n):#returns a list of first n points (x,y) in
if len(xi) == n and len(yi) == n:
points = [] # returned pairs of points
for i in range(n):
+ xi[i] = Draw_From_Triangle.unittouu(e, str(xi[i]) + 'px')
+ yi[i] = Draw_From_Triangle.unittouu(e, str(yi[i]) + 'px')
points.append( [ xi[i], yi[i] ] )
else:
#inkex.errormsg(_('Error: Not enough nodes to gather coordinates.')) #fail silently and exit, rather than invoke an error console
@@ -190,17 +192,17 @@ class Style(object): #container for style information
def __init__(self, options):
#dot markers
self.d_rad = 4 #dot marker radius
- self.d_th = 2 #stroke width
+ self.d_th = Draw_From_Triangle.unittouu(e, '2px') #stroke width
self.d_fill= '#aaaaaa' #fill colour
self.d_col = '#000000' #stroke colour
#lines
- self.l_th = 2
+ self.l_th = Draw_From_Triangle.unittouu(e, '2px')
self.l_fill= 'none'
self.l_col = '#000000'
#circles
- self.c_th = 2
+ self.c_th = Draw_From_Triangle.unittouu(e, '2px')
self.c_fill= 'none'
self.c_col = '#000000'
@@ -314,7 +316,7 @@ class Draw_From_Triangle(inkex.Effect):
if len(pts) == 3: #if we have right number of nodes, else skip and end program
st = Style(so)#style for dots, lines and circles
-
+
#CREATE A GROUP TO HOLD ALL GENERATED ELEMENTS IN
#Hold relative to point A (pt[0])
group_translation = 'translate(' + str( pts[0][0] ) + ','+ str( pts[0][1] ) + ')'
diff --git a/share/extensions/foldablebox.py b/share/extensions/foldablebox.py
index 5d5945dd9..b504de89f 100755
--- a/share/extensions/foldablebox.py
+++ b/share/extensions/foldablebox.py
@@ -70,7 +70,7 @@ class FoldableBox(inkex.Effect):
box_id = self.uniqueId('box')
self.box = g = inkex.etree.SubElement(self.current_layer, 'g', {'id':box_id})
- line_style = simplestyle.formatStyle({ 'stroke': '#000000', 'fill': 'none' })
+ line_style = simplestyle.formatStyle({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) })
#self.createGuide( 0, docH, 0 );
diff --git a/share/extensions/grid_cartesian.py b/share/extensions/grid_cartesian.py
index 85716a6fd..23df0ff84 100755
--- a/share/extensions/grid_cartesian.py
+++ b/share/extensions/grid_cartesian.py
@@ -122,7 +122,17 @@ class Grid_Polar(inkex.Effect):
def effect(self):
-
+
+ self.options.border_th = self.unittouu(str(self.options.border_th) + 'px')
+ self.options.dx = self.unittouu(str(self.options.dx) + 'px')
+ self.options.x_divs_th = self.unittouu(str(self.options.x_divs_th) + 'px')
+ self.options.x_subdivs_th = self.unittouu(str(self.options.x_subdivs_th) + 'px')
+ self.options.x_subsubdivs_th = self.unittouu(str(self.options.x_subsubdivs_th) + 'px')
+ self.options.dy = self.unittouu(str(self.options.dy) + 'px')
+ self.options.y_divs_th = self.unittouu(str(self.options.y_divs_th) + 'px')
+ self.options.y_subdivs_th = self.unittouu(str(self.options.y_subdivs_th) + 'px')
+ self.options.y_subsubdivs_th = self.unittouu(str(self.options.y_subsubdivs_th) + 'px')
+
#find the pixel dimensions of the overall grid
ymax = self.options.dy * self.options.y_divs
xmax = self.options.dx * self.options.x_divs
diff --git a/share/extensions/grid_isometric.py b/share/extensions/grid_isometric.py
index 27951a0a8..8ac407613 100755
--- a/share/extensions/grid_isometric.py
+++ b/share/extensions/grid_isometric.py
@@ -84,6 +84,12 @@ class Grid_Polar(inkex.Effect):
def effect(self):
+ self.options.dx = self.unittouu(str(self.options.dx) + 'px')
+ self.options.divs_th = self.unittouu(str(self.options.divs_th) + 'px')
+ self.options.subdivs_th = self.unittouu(str(self.options.subdivs_th) + 'px')
+ self.options.subsubdivs_th = self.unittouu(str(self.options.subsubdivs_th) + 'px')
+ self.options.border_th = self.unittouu(str(self.options.border_th) + 'px')
+
#Can't generate a grid too flat
#If the Y dimension is smallest than half the X dimension, fix it.
if self.options.y_divs<((self.options.x_divs+1)/2):
diff --git a/share/extensions/grid_polar.py b/share/extensions/grid_polar.py
index 3ae3fac34..17c3499cb 100755
--- a/share/extensions/grid_polar.py
+++ b/share/extensions/grid_polar.py
@@ -119,7 +119,16 @@ class Grid_Polar(inkex.Effect):
help="The radial outset of the circumferential labels")
def effect(self):
-
+
+ self.options.dr = self.unittouu(str(self.options.dr) + 'px')
+ self.options.r_divs_th = self.unittouu(str(self.options.r_divs_th) + 'px')
+ self.options.r_subdivs_th = self.unittouu(str(self.options.r_subdivs_th) + 'px')
+ self.options.a_divs_th = self.unittouu(str(self.options.a_divs_th) + 'px')
+ self.options.a_subdivs_th = self.unittouu(str(self.options.a_subdivs_th) + 'px')
+ self.options.c_dot_dia = self.unittouu(str(self.options.c_dot_dia) + 'px')
+ self.options.a_label_size = self.unittouu(str(self.options.a_label_size) + 'px')
+ self.options.a_label_outset = self.unittouu(str(self.options.a_label_outset) + 'px')
+
# Embed grid in group
#Put in in the centre of the current view
t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
diff --git a/share/extensions/guides_creator.py b/share/extensions/guides_creator.py
index abd41c6fc..21df1cd50 100755
--- a/share/extensions/guides_creator.py
+++ b/share/extensions/guides_creator.py
@@ -297,8 +297,8 @@ class Guides_Creator(inkex.Effect):
svg = self.document.getroot()
# getting the width and height attributes of the canvas
- width = self.unittouu(svg.get('width'))
- height = self.unittouu(svg.attrib['height'])
+ width = float(svg.get('width'))
+ height = float(svg.get('height'))
# getting edges coordinates
h_orientation = '0,' + str(round(width,4))
diff --git a/share/extensions/hershey.py b/share/extensions/hershey.py
index 931e5f337..1ddabfbe0 100755
--- a/share/extensions/hershey.py
+++ b/share/extensions/hershey.py
@@ -63,6 +63,7 @@ class Hershey( inkex.Effect ):
g_attribs = {inkex.addNS('label','inkscape'):'Hershey Text' }
g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
+ scale = self.unittouu('1px') # convert to document units
font = eval('hersheydata.' + str(self.options.fontface))
clearfont = hersheydata.futural
#Baseline: modernized roman simplex from JHF distribution.
@@ -97,7 +98,9 @@ class Hershey( inkex.Effect ):
w = wmax
# Translate group to center of view, approximately
- t = 'translate(' + str( self.view_center[0] - w/2) + ',' + str( self.view_center[1] ) + ')'
+ t = 'translate(' + str( self.view_center[0] - scale*w/2) + ',' + str( self.view_center[1] ) + ')'
+ if scale != 1:
+ t += ' scale(' + str(scale) + ')'
g.set( 'transform',t)
diff --git a/share/extensions/hpgl_decoder.py b/share/extensions/hpgl_decoder.py
index 2401a5612..c195b21e3 100644
--- a/share/extensions/hpgl_decoder.py
+++ b/share/extensions/hpgl_decoder.py
@@ -25,7 +25,6 @@ from StringIO import StringIO
import inkex
-# TODO: Unittests
class hpglDecoder:
def __init__(self, hpglString, options):
diff --git a/share/extensions/hpgl_encoder.py b/share/extensions/hpgl_encoder.py
index 98993cd79..a16561e97 100644
--- a/share/extensions/hpgl_encoder.py
+++ b/share/extensions/hpgl_encoder.py
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import math
import re
import string
+#from StringIO import StringIO
# local libraries
import bezmisc
import cspsubdiv
@@ -32,15 +33,9 @@ import simplestyle
import simpletransform
-# TODO: Unittests
class hpglEncoder:
PI = math.pi
TWO_PI = PI * 2
- # a dictionary of arbitrary unit to user unit conversion factors
- # in = Inch; pt = PostScript Point; px = Pixel; mm = Millimeter; cm = Centimeter;
- # km = Kilometer; pc = PostScript Pica; yd = Yard; ft = Feet; m = Meter
- __USER_UNIT_CONVERSION = {'in':90.0, 'pt':1.25, 'px':1, 'mm':3.5433070866, 'cm':35.433070866,
- 'km':3543307.0866, 'pc':15.0, 'yd':3240 , 'ft':1080, 'm':3543.3070866}
def __init__(self, effect):
''' options:
@@ -54,37 +49,35 @@ class hpglEncoder:
"mirrorY":bool
"center":bool
"flat":float
- "useOvercut":bool
"overcut":float
- "useToolOffset":bool
"toolOffset":float
"precut":bool
- "offsetX":float
- "offsetY":float
+ "autoAlign":bool
"debug":bool
'''
- self.doc = effect.document.getroot()
self.options = effect.options
- self.documentUnit = self.doc.xpath('//sodipodi:namedview/@inkscape:document-units', namespaces=inkex.NSS)
- if self.documentUnit:
- self.documentUnit = self.documentUnit[0]
- else:
- self.documentUnit = 'px'
+ self.doc = effect.document.getroot()
+ self.docWidth = effect.unittouu(self.doc.get('width'))
+ self.docHeight = effect.unittouu(self.doc.get('height'))
+ self.hpgl = ''
self.divergenceX = 'False'
self.divergenceY = 'False'
self.sizeX = 'False'
self.sizeY = 'False'
self.dryRun = True
self.lastPoint = [0, 0, 0]
- self.scaleX = self.options.resolutionX / self.unitToUserUnit("1.0in") # dots per inch to dots per user unit
- self.scaleY = self.options.resolutionY / self.unitToUserUnit("1.0in") # dots per inch to dots per user unit
+ self.offsetX = 0
+ self.offsetY = 0
+ self.scaleX = self.options.resolutionX / effect.unittouu("1.0in") # dots per inch to dots per user unit
+ self.scaleY = self.options.resolutionY / effect.unittouu("1.0in") # dots per inch to dots per user unit
scaleXY = (self.scaleX + self.scaleY) / 2
- self.offsetX = self.unitToUserUnit(str(self.options.offsetX) + "mm") * self.scaleX # mm to dots (plotter coordinate system)
- self.offsetY = self.unitToUserUnit(str(self.options.offsetY) + "mm") * self.scaleY # mm to dots
- self.overcut = self.unitToUserUnit(str(self.options.overcut) + "mm") * scaleXY # mm to dots
- self.toolOffset = self.unitToUserUnit(str(self.options.toolOffset) + "mm") * scaleXY # mm to dots
+ self.overcut = effect.unittouu(str(self.options.overcut) + "mm") * scaleXY # mm to dots (plotter coordinate system)
+ self.toolOffset = effect.unittouu(str(self.options.toolOffset) + "mm") * scaleXY # mm to dots
self.flat = self.options.flat / (1016 / ((self.options.resolutionX + self.options.resolutionY) / 2)) # scale flatness to resolution
- self.toolOffsetFlat = self.flat / self.toolOffset * 4.5 # scale flatness to offset
+ if self.toolOffset > 0.0:
+ self.toolOffsetFlat = self.flat / self.toolOffset * 4.5 # scale flatness to offset
+ else:
+ self.toolOffsetFlat = 0.0
self.mirrorX = 1.0
if self.options.mirrorX:
self.mirrorX = -1.0
@@ -92,24 +85,25 @@ class hpglEncoder:
if self.options.mirrorY:
self.mirrorY = 1.0
if self.options.debug:
- self.debugValues = [0, 0, 0, 0, 0, 0, 0, 0]
+ self.debugValues = {}
+ self.debugValues['docWidth'] = self.docWidth
+ self.debugValues['docHeight'] = self.docHeight
# process viewBox attribute to correct page scaling
- viewBox = self.doc.get('viewBox')
self.viewBoxTransformX = 1
self.viewBoxTransformY = 1
if self.options.debug:
- self.debugValues[0] = self.unitToUserUnit(self.doc.get('width'), True)
- self.debugValues[1] = self.unitToUserUnit(self.doc.get('height'), True)
+ self.debugValues['viewBoxWidth'] = "-"
+ self.debugValues['viewBoxHeight'] = "-"
+ viewBox = self.doc.get('viewBox')
if viewBox:
- viewBox = string.split(viewBox, ' ')
- if viewBox[2] and viewBox[3]:
- viewBox[0] = viewBox[2]
- viewBox[1] = viewBox[3]
+ viewBox2 = string.split(viewBox, ',')
+ if len(viewBox2) < 4:
+ viewBox2 = string.split(viewBox, ' ')
if self.options.debug:
- self.debugValues[2] = self.unitToUserUnit(viewBox[0])
- self.debugValues[3] = self.unitToUserUnit(viewBox[1])
- self.viewBoxTransformX = self.unitToUserUnit(self.doc.get('width'), True) / self.unitToUserUnit(viewBox[0])
- self.viewBoxTransformY = self.unitToUserUnit(self.doc.get('height'), True) / self.unitToUserUnit(viewBox[1])
+ self.debugValues['viewBoxWidth'] = viewBox2[2]
+ self.debugValues['viewBoxHeight'] = viewBox2[3]
+ self.viewBoxTransformX = self.docWidth / effect.unittouu(effect.addDocumentUnit(viewBox2[2]))
+ self.viewBoxTransformY = self.docHeight / effect.unittouu(effect.addDocumentUnit(viewBox2[3]))
def getHpgl(self):
# dryRun to find edges
@@ -122,55 +116,77 @@ class hpglEncoder:
# live run
self.dryRun = False
if self.options.debug:
- self.debugValues[4] = self.sizeX - self.divergenceX
- self.debugValues[5] = self.sizeY - self.divergenceY
- self.debugValues[6] = self.unitToUserUnit(str(self.debugValues[4] / self.scaleX))
- self.debugValues[7] = self.unitToUserUnit(str(self.debugValues[5] / self.scaleY))
- if self.options.center:
- self.divergenceX += (self.sizeX - self.divergenceX) / 2
- self.divergenceY += (self.sizeY - self.divergenceY) / 2
- elif self.options.useToolOffset:
+ self.debugValues['drawingWidth'] = self.sizeX - self.divergenceX
+ self.debugValues['drawingHeight'] = self.sizeY - self.divergenceY
+ self.debugValues['drawingWidthUU'] = self.debugValues['drawingWidth'] / self.scaleX
+ self.debugValues['drawingHeightUU'] = self.debugValues['drawingHeight'] / self.scaleY
+ # move drawing according to various modifiers
+ if self.options.autoAlign:
+ if self.options.center:
+ self.offsetX -= (self.sizeX - self.divergenceX) / 2
+ self.offsetY -= (self.sizeY - self.divergenceY) / 2
+ else:
+ self.divergenceX = 0.0
+ self.divergenceY = 0.0
+ if self.options.center:
+ if self.options.orientation == '0':
+ self.offsetX -= (self.docWidth * self.scaleX) / 2
+ self.offsetY += (self.docHeight * self.scaleY) / 2
+ if self.options.orientation == '90':
+ self.offsetY += (self.docWidth * self.scaleX) / 2
+ self.offsetX += (self.docHeight * self.scaleY) / 2
+ if self.options.orientation == '180':
+ self.offsetX += (self.docWidth * self.scaleX) / 2
+ self.offsetY -= (self.docHeight * self.scaleY) / 2
+ if self.options.orientation == '270':
+ self.offsetY -= (self.docWidth * self.scaleX) / 2
+ self.offsetX -= (self.docHeight * self.scaleY) / 2
+ else:
+ if self.options.orientation == '0':
+ self.offsetY += self.docHeight * self.scaleY
+ if self.options.orientation == '90':
+ self.offsetY += self.docWidth * self.scaleX
+ self.offsetX += self.docHeight * self.scaleY
+ if self.options.orientation == '180':
+ self.offsetX += self.docWidth * self.scaleX
+ if not self.options.center and self.toolOffset > 0.0:
self.offsetX += self.toolOffset
self.offsetY += self.toolOffset
- groupmat = [[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, - self.divergenceX + self.offsetX],
- [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, - self.divergenceY + self.offsetY]]
+ # initialize transformation matrix and cache
+ groupmat = [[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, -self.divergenceX + self.offsetX],
+ [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, -self.divergenceY + self.offsetY]]
groupmat = simpletransform.composeTransform(groupmat, simpletransform.parseTransform('rotate(' + self.options.orientation + ')'))
self.vData = [['', -1.0, -1.0], ['', -1.0, -1.0], ['', -1.0, -1.0], ['', -1.0, -1.0]]
- # store first hpgl commands
- self.hpgl = 'IN;SP%d' % self.options.pen
- if self.options.force > 0:
- self.hpgl += ';FS%d' % self.options.force
- if self.options.speed > 0:
- self.hpgl += ';VS%d' % self.options.speed
- # add precut
- if self.options.useToolOffset and self.options.precut:
+ # add move to zero point and precut
+ if self.toolOffset > 0.0 and self.options.precut:
+ if self.options.center:
+ # position precut outside of drawing plus one times the tooloffset
+ if self.offsetX >= 0.0:
+ precutX = self.offsetX + self.toolOffset
+ else:
+ precutX = self.offsetX - self.toolOffset
+ if self.offsetY >= 0.0:
+ precutY = self.offsetY + self.toolOffset
+ else:
+ precutY = self.offsetY - self.toolOffset
+ self.processOffset('PU', precutX, precutY)
+ self.processOffset('PD', precutX, precutY + self.toolOffset * 8)
+ else:
+ self.processOffset('PU', 0, 0)
+ self.processOffset('PD', 0, self.toolOffset * 8)
+ else:
self.processOffset('PU', 0, 0)
- self.processOffset('PD', 0, self.toolOffset * 8)
# start conversion
self.processGroups(self.doc, groupmat)
# shift an empty node in in order to process last node in cache
self.processOffset('PU', 0, 0)
- # add return to zero point
- self.hpgl += ';PU0,0;'
if self.options.debug:
return self.hpgl, self
else:
return self.hpgl, ""
- def unitToUserUnit(self, string, isPixels=False):
- '''Returns userunits given a string representation of units in another system'''
- matches = re.match('^(.*?)(in|pt|px|mm|cm|km|pc|yd|ft|m)?$', string.strip())
- value = float(matches.group(1))
- unit = matches.group(2)
- if unit is None:
- if isPixels:
- unit = "px"
- else:
- unit = self.documentUnit
- return value * self.__USER_UNIT_CONVERSION[unit] / self.__USER_UNIT_CONVERSION[self.documentUnit]
-
def processGroups(self, doc, groupmat):
- # flatten groups to avoid recursion
+ # flatten layers and groups to avoid recursion
paths = []
for node in doc:
if (node.tag == inkex.addNS('g', 'svg') and self.isGroupVisible(node)) or node.tag == inkex.addNS('path', 'svg'):
@@ -217,7 +233,6 @@ class hpglEncoder:
# path to HPGL commands
oldPosX = 0.0
oldPosY = 0.0
- # TODO: Plot smallest parts first to avid plotter dragging parts of foil around (on text)
for singlePath in path:
cmd = 'PU'
for singlePathPoint in singlePath:
@@ -229,7 +244,7 @@ class hpglEncoder:
oldPosX = posX
oldPosY = posY
# perform overcut
- if self.options.useOvercut and not self.dryRun:
+ if self.overcut > 0.0 and not self.dryRun:
# check if last and first points are the same, otherwise the path is not closed and no overcut can be performed
if int(round(oldPosX)) == int(round(singlePath[0][1][0])) and int(round(oldPosY)) == int(round(singlePath[0][1][1])):
overcutLength = 0
@@ -262,15 +277,9 @@ class hpglEncoder:
y = y2 + (y2 - y1) / self.getLength(x1, y1, x2, y2, False) * offset
return [x, y]
- def getAlpha(self, x1, y1, x2, y2, x3, y3):
- # get alpha of point 2
- temp1 = (x1 - x2) ** 2 + (y1 - y2) ** 2 + (x3 - x2) ** 2 + (y3 - y2) ** 2 - (x1 - x3) ** 2 - (y1 - y3) ** 2
- temp2 = 2 * math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) * math.sqrt((x3 - x2) ** 2 + (y3 - y2) ** 2)
- return math.acos(max(min(temp1 / temp2, 1.0), -1.0))
-
def processOffset(self, cmd, posX, posY):
# calculate offset correction (or dont)
- if not self.options.useToolOffset or self.dryRun:
+ if self.toolOffset == 0.0 or self.dryRun:
self.storePoint(cmd, posX, posY)
else:
# insert data into cache
diff --git a/share/extensions/hpgl_input.inx b/share/extensions/hpgl_input.inx
index aba7a9308..f40fd4ec0 100644
--- a/share/extensions/hpgl_input.inx
+++ b/share/extensions/hpgl_input.inx
@@ -7,8 +7,8 @@
<dependency type="executable" location="extensions">inkex.py</dependency>
<_param name="introduction" type="description">Please note that you can only open HPGL files written by Inkscape, to open other HPGL files please change their file extension to .plt, make sure you have UniConverter installed and open them again.</_param>
<param name="space" type="description">&#xa0;</param>
- <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps in one inch on the X axis. (Default: 1016.0)">1016.0</param>
- <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps in one inch on the Y axis. (Default: 1016.0)">1016.0</param>
+ <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the X axis. (Default: 1016.0)">1016.0</param>
+ <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the Y axis. (Default: 1016.0)">1016.0</param>
<param name="showMovements" type="boolean" _gui-text="Show movements between paths" _gui-description="Check this to show movements between paths. (Default: Unchecked)">false</param>
<input>
<extension>.hpgl</extension>
diff --git a/share/extensions/hpgl_input.py b/share/extensions/hpgl_input.py
index 93dd5a6c2..d85a5edd6 100644
--- a/share/extensions/hpgl_input.py
+++ b/share/extensions/hpgl_input.py
@@ -28,7 +28,6 @@ import sys
inkex.localize()
-# TODO: Unittests
# parse options
parser = inkex.optparse.OptionParser(usage='usage: %prog [options] HPGLfile', option_class=inkex.InkOption)
parser.add_option('--resolutionX', action='store', type='float', dest='resolutionX', default=1016.0, help='Resolution X (dpi)')
diff --git a/share/extensions/hpgl_output.inx b/share/extensions/hpgl_output.inx
index a0ba6e364..d16cc55e5 100644
--- a/share/extensions/hpgl_output.inx
+++ b/share/extensions/hpgl_output.inx
@@ -6,15 +6,15 @@
<dependency type="executable" location="extensions">hpgl_output.py</dependency>
<dependency type="executable" location="extensions">hpgl_encoder.py</dependency>
<dependency type="executable" location="extensions">inkex.py</dependency>
- <_param name="introduction" type="description">Please make sure that all objects you want to save are converted to paths. The drawing will be automatically aligned to the zero point. Please use the plotter extension (Extensions menu) to plot directly on a plotter.</_param>
+ <_param name="introduction" type="description">Please make sure that all objects you want to save are converted to paths. Please use the plotter extension (Extensions menu) to plot directly over a serial connection.</_param>
<param name="tab" type="notebook">
- <page name="plotter" _gui-text="Plotter Settings">
- <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps the cutter moves if it moves for 1 inch on the X axis. (Default: 1016.0)">1016.0</param>
- <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps the cutter moves if it moves for 1 inch on the Y axis. (Default: 1016.0)">1016.0</param>
+ <page name="plotter" _gui-text="Plotter Settings ">
+ <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the X axis. (Default: 1016.0)">1016.0</param>
+ <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the Y axis. (Default: 1016.0)">1016.0</param>
<param name="pen" type="int" min="0" max="99" _gui-text="Pen number" _gui-description="The number of the pen (tool) to use. (Standard: '1')">1</param>
- <param name="force" type="int" min="0" max="1000" _gui-text="Pen force (g)" _gui-description="The amount of force pushing down the pen in grams, set to 0 to omit command. Most plotters ignore this command. (Default: 24)">24</param>
- <param name="speed" type="int" min="0" max="1000" _gui-text="Pen speed (cm/s)" _gui-description="The speed the pen will move with in centimetres per second, set to 0 to omit command. Most plotters ignore this command. (Default: 20)">20</param>
- <param name="orientation" type="optiongroup" appearance="minimal" _gui-text="Rotation (Clockwise)" _gui-description="Rotation of the plot. (Default: 0°)">
+ <param name="force" type="int" min="0" max="1000" _gui-text="Pen force (g)" _gui-description="The amount of force pushing down the pen in grams, set to 0 to omit command. Most plotters ignore this command. (Default: 0)">0</param>
+ <param name="speed" type="int" min="0" max="10000" _gui-text="Pen speed (cm/s or mm/s)" _gui-description="The speed the pen will move with in centimeters or millimeters per second (depending on your plotter model), set to 0 to omit command. Most plotters ignore this command. (Default: 0)">0</param>
+ <param name="orientation" type="optiongroup" appearance="minimal" _gui-text="Rotation (Clockwise)" _gui-description="Rotation of the drawing. (Default: 0°)">
<option value="0">0°</option>
<option value="90">90°</option>
<option value="180">180°</option>
@@ -24,20 +24,12 @@
<param name="mirrorY" type="boolean" _gui-text="Mirror Y axis" _gui-description="Check this to mirror the Y axis. (Default: Unchecked)">false</param>
<param name="center" type="boolean" _gui-text="Center zero point" _gui-description="Check this if your plotter uses a centered zero point. (Default: Unchecked)">false</param>
</page>
- <page name="overcutToolOffset" _gui-text="Overcut &#x26; Tool Offset">
- <param name="useOvercut" type="boolean" _gui-text="Use overcut" _gui-description="Check this to use overcut, if not checked the 'Overcut' parameter is unused. (Default: Checked)">true</param>
- <param name="overcut" type="float" min="0.0" max="100.0" precision="2" _gui-text="Overcut (mm)" _gui-description="The distance in mm that will be cut over the starting point of the path to prevent open paths. (Default: 1.00)">1.00</param>
- <param name="space" type="description">&#xa0;</param>
- <param name="useToolOffset" type="boolean" _gui-text="Use tool offset correction" _gui-description="Check this to use the tool offset correction, if not checked the 'Tool offset' and 'Precut' parameters are unused. (Default: Checked)">true</param>
- <param name="toolOffset" type="float" min="0.0" max="20.0" precision="2" _gui-text="Tool offset (mm)" _gui-description="The offset from the tool tip to the tool axis in mm. (Default: 0.25)">0.25</param>
- <param name="precut" type="boolean" _gui-text="Use precut" _gui-description="Check this to plot a small line before the real plot to align the tool orientation for the first real plot. (Default: Checked)">true</param>
- <param name="space" type="description">&#xa0;</param>
- <_param name="offsetNote" type="description">Please note that using the tool offset correction will move your plot away from the zero point by one tool offset length.</_param>
- </page>
- <page name="misc" _gui-text="Miscellaneous">
+ <page name="overcutToolOffset" _gui-text="Plot Features ">
+ <param name="overcut" type="float" min="0.0" max="100.0" precision="2" _gui-text="Overcut (mm)" _gui-description="The distance in mm that will be cut over the starting point of the path to prevent open paths, set to 0.0 to omit command. (Default: 1.00)">1.00</param>
+ <param name="toolOffset" type="float" min="0.0" max="20.0" precision="2" _gui-text="Tool offset (mm)" _gui-description="The offset from the tool tip to the tool axis in mm, set to 0.0 to omit command. (Default: 0.25)">0.25</param>
+ <param name="precut" type="boolean" _gui-text="Use precut" _gui-description="Check this to cut a small line before the real drawing starts to correctly align the tool orientation. (Default: Checked)">true</param>
<param name="flat" type="float" min="0.1" max="10.0" precision="1" _gui-text="Curve flatness" _gui-description="Curves are divided into lines, this number controls how fine the curves will be reproduced, the smaller the finer. (Default: '1.2')">1.2</param>
- <param name="offsetX" type="float" min="-10000.0" max="10000.0" precision="2" _gui-text="X offset (mm)" _gui-description="The offset to move your plot away from the zero point on the X axis in mm. (Default: '0.00')">0.00</param>
- <param name="offsetY" type="float" min="-10000.0" max="10000.0" precision="2" _gui-text="Y offset (mm)" _gui-description="The offset to move your plot away from the zero point on the Y axis in mm. (Default: '0.00')">0.00</param>
+ <param name="autoAlign" type="boolean" _gui-text="Auto align" _gui-description="Check this to auto align the drawing to the zero point (Plus the tool offset if used). If unchecked you have to make sure that all parts of your drawing are within the document border! (Default: Checked)">true</param>
</page>
</param>
<_param name="settingsHelp" type="description">All these settings depend on the plotter you use, for more information please consult the manual or homepage for your plotter.</_param>
diff --git a/share/extensions/hpgl_output.py b/share/extensions/hpgl_output.py
index d6f6b8eec..c6713cb65 100755
--- a/share/extensions/hpgl_output.py
+++ b/share/extensions/hpgl_output.py
@@ -26,8 +26,7 @@ import inkex
inkex.localize()
-# TODO: Unittests
-class MyEffect(inkex.Effect):
+class HpglOutput(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
@@ -41,14 +40,11 @@ class MyEffect(inkex.Effect):
self.OptionParser.add_option('--mirrorX', action='store', type='inkbool', dest='mirrorX', default='FALSE', help='Mirror X axis')
self.OptionParser.add_option('--mirrorY', action='store', type='inkbool', dest='mirrorY', default='FALSE', help='Mirror Y axis')
self.OptionParser.add_option('--center', action='store', type='inkbool', dest='center', default='FALSE', help='Center zero point')
- self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness')
- self.OptionParser.add_option('--useOvercut', action='store', type='inkbool', dest='useOvercut', default='TRUE', help='Use overcut')
self.OptionParser.add_option('--overcut', action='store', type='float', dest='overcut', default=1.0, help='Overcut (mm)')
- self.OptionParser.add_option('--useToolOffset', action='store', type='inkbool', dest='useToolOffset', default='TRUE', help='Correct tool offset')
self.OptionParser.add_option('--toolOffset', action='store', type='float', dest='toolOffset', default=0.25, help='Tool offset (mm)')
self.OptionParser.add_option('--precut', action='store', type='inkbool', dest='precut', default='TRUE', help='Use precut')
- self.OptionParser.add_option('--offsetX', action='store', type='float', dest='offsetX', default=0.0, help='X offset (mm)')
- self.OptionParser.add_option('--offsetY', action='store', type='float', dest='offsetY', default=0.0, help='Y offset (mm)')
+ self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness')
+ self.OptionParser.add_option('--autoAlign', action='store', type='inkbool', dest='autoAlign', default='TRUE', help='Auto align')
def effect(self):
self.options.debug = False
@@ -65,6 +61,13 @@ class MyEffect(inkex.Effect):
else:
type, value, traceback = sys.exc_info()
raise ValueError, ("", type, value), traceback
+ # convert raw HPGL to HPGL
+ hpglInit = 'IN;SP%d' % self.options.pen
+ if self.options.force > 0:
+ hpglInit += ';FS%d' % self.options.force
+ if self.options.speed > 0:
+ hpglInit += ';VS%d' % self.options.speed
+ self.hpgl = hpglInit + self.hpgl + ';PU0,0;SP0;IN;'
def output(self):
# print to file
@@ -73,7 +76,7 @@ class MyEffect(inkex.Effect):
if __name__ == '__main__':
# start extension
- e = MyEffect()
+ e = HpglOutput()
e.affect()
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 \ No newline at end of file
diff --git a/share/extensions/ink2canvas.py b/share/extensions/ink2canvas.py
index 51b75d846..d1e11a7c2 100755
--- a/share/extensions/ink2canvas.py
+++ b/share/extensions/ink2canvas.py
@@ -80,7 +80,7 @@ class Ink2Canvas(inkex.Effect):
svg_root = self.document.getroot()
width = self.unittouu(svg_root.get("width"))
height = self.unittouu(svg_root.get("height"))
- self.canvas = Canvas(width, height)
+ self.canvas = Canvas(self, width, height)
self.walk_tree(svg_root)
diff --git a/share/extensions/ink2canvas/canvas.py b/share/extensions/ink2canvas/canvas.py
index 80ec4fd43..1f574a63e 100644
--- a/share/extensions/ink2canvas/canvas.py
+++ b/share/extensions/ink2canvas/canvas.py
@@ -23,11 +23,12 @@ import simplestyle
class Canvas:
"""Canvas API helper class"""
- def __init__(self, width, height, context = "ctx"):
+ def __init__(self, parent, width, height, context = "ctx"):
self.obj = context
self.code = [] #stores the code
self.style = {}
self.styleCache = {} #stores the previous style applied
+ self.parent = parent
self.width = width
self.height = height
@@ -117,7 +118,7 @@ class Canvas:
self.write("ctx.strokeStyle = %s;" % self.getColor(value, alpha))
def setStrokeWidth(self, value):
- self.write("ctx.lineWidth = %f;" % inkex.unittouu(value))
+ self.write("ctx.lineWidth = %f;" % self.parent.unittouu(value))
def setStrokeLinecap(self, value):
self.write("ctx.lineCap = '%s';" % value)
diff --git a/share/extensions/inkex.py b/share/extensions/inkex.py
index 5333ef52b..d71b7d7e7 100755
--- a/share/extensions/inkex.py
+++ b/share/extensions/inkex.py
@@ -151,15 +151,31 @@ 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 specified 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)
@@ -295,5 +311,12 @@ class Effect:
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/share/extensions/interp.py b/share/extensions/interp.py
index c69dd4a73..459190c0e 100755
--- a/share/extensions/interp.py
+++ b/share/extensions/interp.py
@@ -60,10 +60,6 @@ def tweenstylefloat(property, start, end, time):
sp = float(start[property])
ep = float(end[property])
return str(sp + (time * (ep - sp)))
-def tweenstyleunit(property, start, end, time):
- sp = self.unittouu(start[property])
- ep = self.unittouu(end[property])
- return str(sp + (time * (ep - sp)))
def tweenstylecolor(property, start, end, time):
sr,sg,sb = parsecolor(start[property])
er,eg,eb = parsecolor(end[property])
@@ -107,6 +103,12 @@ class Interp(inkex.Effect):
action="store", type="inkbool",
dest="style", default=True,
help="try interpolation of some style properties")
+
+ def tweenstyleunit(self, property, start, end, time): # moved here so we can call 'unittouu'
+ sp = self.unittouu(start[property])
+ ep = self.unittouu(end[property])
+ return str(sp + (time * (ep - sp)))
+
def effect(self):
exponent = self.options.exponent
if exponent>= 0:
@@ -137,6 +139,8 @@ class Interp(inkex.Effect):
sst = copy.deepcopy(styles[self.options.ids[i-1]])
est = copy.deepcopy(styles[self.options.ids[i]])
basestyle = copy.deepcopy(sst)
+ if basestyle.has_key('stroke-width'):
+ basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,0)
#prepare for experimental style tweening
if self.options.style:
@@ -303,7 +307,7 @@ class Interp(inkex.Effect):
basestyle['opacity'] = tweenstylefloat('opacity',sst,est,time)
if dostroke:
basestyle['stroke-opacity'] = tweenstylefloat('stroke-opacity',sst,est,time)
- basestyle['stroke-width'] = tweenstyleunit('stroke-width',sst,est,time)
+ basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,time)
basestyle['stroke'] = tweenstylecolor('stroke',sst,est,time)
if dofill:
basestyle['fill-opacity'] = tweenstylefloat('fill-opacity',sst,est,time)
diff --git a/share/extensions/lindenmayer.py b/share/extensions/lindenmayer.py
index f9abce3ec..2e058f541 100755
--- a/share/extensions/lindenmayer.py
+++ b/share/extensions/lindenmayer.py
@@ -104,7 +104,8 @@ class LSystem(inkex.Effect):
return level_string
def effect(self):
- s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px',
+ self.options.step = self.unittouu(str(self.options.step) + 'px')
+ s = {'stroke-linejoin': 'miter', 'stroke-width': str(self.unittouu('1px')),
'stroke-opacity': '1.0', 'fill-opacity': '1.0',
'stroke': '#000000', 'stroke-linecap': 'butt',
'fill': 'none'}
diff --git a/share/extensions/measure.py b/share/extensions/measure.py
index 68cce0334..ca471816f 100755
--- a/share/extensions/measure.py
+++ b/share/extensions/measure.py
@@ -121,7 +121,7 @@ class Length(inkex.Effect):
self.OptionParser.add_option("-s", "--scale",
action="store", type="float",
dest="scale", default=1,
- help="The distance above the curve")
+ help="Scale Factor (Drawing:Real Length)")
self.OptionParser.add_option("-r", "--orient",
action="store", type="inkbool",
dest="orient", default=True,
@@ -138,6 +138,7 @@ class Length(inkex.Effect):
def effect(self):
# get number of digits
prec = int(self.options.precision)
+ self.options.offset *= self.unittouu('1px')
factor = 1.0
doc = self.document.getroot()
if doc.get('viewBox'):
@@ -154,7 +155,7 @@ class Length(inkex.Effect):
mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
p = cubicsuperpath.parsePath(node.get('d'))
simpletransform.applyTransformToPath(mat, p)
- factor = factor/self.unittouu('1'+self.options.unit)
+ factor *= self.unittouu('1px')/self.unittouu('1'+self.options.unit)
if self.options.type == "length":
slengths, stotal = csplength(p)
else:
diff --git a/share/extensions/merge_styles.inx b/share/extensions/merge_styles.inx
new file mode 100644
index 000000000..02da12221
--- /dev/null
+++ b/share/extensions/merge_styles.inx
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <_name>Merge Styles into CSS</_name>
+ <id>org.inkscape.stylesheet.merge</id>
+ <dependency type="executable" location="extensions">inkex.py</dependency>
+ <dependency type="executable" location="extensions">merge_styles.py</dependency>
+
+ <_param name="introduction" type="description">All selected nodes will be grouped together and their common style attributes will create a new class, this class will replace the existing inline style attributes. Please use a name which best describes the kinds of objects and their common context for best effect.</_param>
+
+ <param name="name" type="string" _gui-text="New Class Name:">class1</param>
+
+ <effect needs-live-preview="false">
+ <object-type>all</object-type>
+ <effects-menu>
+ <submenu _name="Stylesheet"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command reldir="extensions" interpreter="python">merge_styles.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/merge_styles.py b/share/extensions/merge_styles.py
new file mode 100755
index 000000000..f028bf4ce
--- /dev/null
+++ b/share/extensions/merge_styles.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2014 Martin Owens
+#
+# 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
+#
+"""
+Merges styles into class based styles and removes.
+"""
+
+import inkex
+import sys
+
+from collections import defaultdict
+
+class Style(dict):
+ """Controls the style/css mechanics for this effect"""
+ def __init__(self, attr=None):
+ self.weights = defaultdict(int)
+ self.total = []
+ if attr:
+ self.parse(attr)
+
+ def parse(self, attr):
+ for name,value in [ a.split(':',1) for a in attr.split(';') if ':' in a ]:
+ self[name.strip()] = value.strip()
+
+ def entries(self):
+ return [ "%s:%s;" % (n,v) for (n,v) in self.iteritems() ]
+
+ def to_str(self, sep="\n "):
+ return " " + "\n ".join(self.entries())
+
+ def __str__(self):
+ return self.to_str()
+
+ def css(self, cls):
+ return ".%s {\n%s\n}" % (cls, str(self))
+
+ def remove(self, keys):
+ for key in keys:
+ self.pop(key, None)
+
+ def add(self, c, el):
+ self.total.append( (c, el) )
+ for name,value in c.iteritems():
+ if not self.has_key(name):
+ self[name] = value
+ if self[name] == value:
+ self.weights[name] += 1
+
+ def clean(self, threshold):
+ """Removes any elements that aren't the same using a weighted threshold"""
+ for attr in self.keys():
+ if self.weights[attr] < len(self.total) - threshold:
+ self.pop(attr)
+
+ def all_matches(self):
+ """Returns an iter for each added element who's style matches this style"""
+ for (c, el) in self.total:
+ if self == c:
+ yield (c, el)
+
+ def __eq__(self, o):
+ """Not equals, prefer to overload 'in' but that doesn't seem possible"""
+ for arg in self.keys():
+ if o.has_key(arg) and self[arg] != o[arg]:
+ return False
+ return True
+
+
+def get_styles(document):
+ nodes = []
+ for node in document.getroot().iterchildren():
+ if node.tag == inkex.addNS('style', 'svg'):
+ return node
+ nodes.append(node)
+ ret = inkex.etree.SubElement(document.getroot(), 'style', {})
+ # Reorder to make the style element FIRST
+ for node in nodes:
+ document.getroot().append(node)
+ return ret
+
+
+class MergeStyles(inkex.Effect):
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ self.OptionParser.add_option("-n", "--name",
+ action="store", type="string",
+ dest="name", default='',
+ help="Name of selected element's common class")
+
+ def effect(self):
+ newclass = self.options.name
+ elements = self.selected.values()
+ common = Style()
+ threshold = 1
+
+ for el in elements:
+ common.add(Style(el.attrib['style']), el)
+ common.clean(threshold)
+
+ if not common:
+ raise KeyError("There are no common styles between these elements.")
+
+ styles = get_styles(self.document)
+ styles.text = (styles.text or "") + "\n" + common.css( newclass )
+
+ for (st, el) in common.all_matches():
+ st.remove(common.keys())
+ el.attrib['style'] = st.to_str("")
+
+ olds = el.attrib.has_key('class') and el.attrib['class'].split() or []
+ if newclass not in olds:
+ olds.append(newclass)
+ el.attrib['class'] = ' '.join(olds)
+
+
+if __name__ == '__main__':
+ e = MergeStyles()
+ e.affect()
+
diff --git a/share/extensions/perspective.py b/share/extensions/perspective.py
index 8a0ffeb0b..044257ae8 100755
--- a/share/extensions/perspective.py
+++ b/share/extensions/perspective.py
@@ -54,6 +54,7 @@ class Project(inkex.Effect):
exit()
#obj is selected second
+ scale = self.unittouu('1px') # convert to document units
obj = self.selected[self.options.ids[0]]
envelope = self.selected[self.options.ids[1]]
if obj.get(inkex.addNS('type','sodipodi')):
@@ -80,11 +81,11 @@ class Project(inkex.Effect):
if bsubprocess:
p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE)
rc = p.wait()
- q[query] = float(p.stdout.read())
+ q[query] = scale*float(p.stdout.read())
err = p.stderr.read()
else:
f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:]
- q[query] = float(f.read())
+ q[query] = scale*float(f.read())
f.close()
err.close()
sp = array([[q['x'], q['y']+q['height']],[q['x'], q['y']],[q['x']+q['width'], q['y']],[q['x']+q['width'], q['y']+q['height']]], dtype=float64)
diff --git a/share/extensions/plotter.inx b/share/extensions/plotter.inx
index e69099e1a..fc620f8a3 100644
--- a/share/extensions/plotter.inx
+++ b/share/extensions/plotter.inx
@@ -6,9 +6,9 @@
<dependency type="executable" location="extensions">hpgl_decoder.py</dependency>
<dependency type="executable" location="extensions">hpgl_encoder.py</dependency>
<dependency type="executable" location="extensions">inkex.py</dependency>
- <_param name="introduction" type="description">Please make sure that all objects you want to plot are converted to paths. The plot will automatically be aligned to the zero point.</_param>
+ <_param name="introduction" type="description">Please make sure that all objects you want to plot are converted to paths.</_param>
<param name="tab" type="notebook">
- <page name="misc" _gui-text="Connection">
+ <page name="misc" _gui-text="Connection Settings ">
<param name="serialPort" type="string" _gui-text="Serial port" _gui-description="The port of your serial connection, on Windows something like 'COM1', on Linux something like: '/dev/ttyUSB0'. (Default: COM1)">COM1</param>
<param name="serialBaudRate" type="optiongroup" appearance="minimal" _gui-text="Serial baud rate" _gui-description="The Baud rate of your serial connection. (Default: 9600)">
<option value="9600">9600</option>
@@ -39,17 +39,17 @@
<option value="ZING">KNK Zing (HPGL variant)</option>
</param>
<param name="space" type="description">&#xa0;</param>
- <_param name="freezeHelp" type="description">Using wrong settings can under certain circumstances cause Inkscape to freeze. Always save your work before plotting.</_param>
+ <_param name="freezeHelp" type="description">Using wrong settings can under certain circumstances cause Inkscape to freeze. Always save your work before plotting!</_param>
<_param name="serialHelp" type="description">This can be a physical serial connection or a USB-to-Serial bridge. Ask your plotter manufacturer for drivers if needed.</_param>
<_param name="parallelHelp" type="description">Parallel (LPT) connections are not supported.</_param>
</page>
- <page name="plotter" _gui-text="Plotter Settings">
- <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps the cutter moves if it moves for 1 inch on the X axis. (Default: 1016.0)">1016.0</param>
- <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps the cutter moves if it moves for 1 inch on the Y axis. (Default: 1016.0)">1016.0</param>
+ <page name="plotter" _gui-text="Plotter Settings ">
+ <param name="resolutionX" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution X (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the X axis. (Default: 1016.0)">1016.0</param>
+ <param name="resolutionY" type="float" min="1.0" max="4096.0" precision="1" _gui-text="Resolution Y (dpi)" _gui-description="The amount of steps the plotter moves if it moves for 1 inch on the Y axis. (Default: 1016.0)">1016.0</param>
<param name="pen" type="int" min="0" max="99" _gui-text="Pen number" _gui-description="The number of the pen (tool) to use. (Standard: '1')">1</param>
- <param name="force" type="int" min="0" max="1000" _gui-text="Pen force (g)" _gui-description="The amount of force pushing down the pen in grams, set to 0 to omit command. Most plotters ignore this command. (Default: 24)">24</param>
- <param name="speed" type="int" min="0" max="1000" _gui-text="Pen speed (cm/s)" _gui-description="The speed the pen will move with in centimetres per second, set to 0 to omit command. Most plotters ignore this command. (Default: 20)">20</param>
- <param name="orientation" type="optiongroup" appearance="minimal" _gui-text="Rotation (Clockwise)" _gui-description="Rotation of the plot. (Default: 0°)">
+ <param name="force" type="int" min="0" max="1000" _gui-text="Pen force (g)" _gui-description="The amount of force pushing down the pen in grams, set to 0 to omit command. Most plotters ignore this command. (Default: 0)">0</param>
+ <param name="speed" type="int" min="0" max="10000" _gui-text="Pen speed (cm/s or mm/s)" _gui-description="The speed the pen will move with in centimeters or millimeters per second (depending on your plotter model), set to 0 to omit command. Most plotters ignore this command. (Default: 0)">0</param>
+ <param name="orientation" type="optiongroup" appearance="minimal" _gui-text="Rotation (Clockwise)" _gui-description="Rotation of the drawing. (Default: 0°)">
<option value="0">0°</option>
<option value="90">90°</option>
<option value="180">180°</option>
@@ -59,28 +59,21 @@
<param name="mirrorY" type="boolean" _gui-text="Mirror Y axis" _gui-description="Check this to mirror the Y axis. (Default: Unchecked)">false</param>
<param name="center" type="boolean" _gui-text="Center zero point" _gui-description="Check this if your plotter uses a centered zero point. (Default: Unchecked)">false</param>
</page>
- <page name="overcutToolOffset" _gui-text="Overcut &#x26; Tool Offset">
- <param name="useOvercut" type="boolean" _gui-text="Use overcut" _gui-description="Check this to use overcut, if not checked the 'Overcut' parameter is unused. (Default: Checked)">true</param>
- <param name="overcut" type="float" min="0.0" max="100.0" precision="2" _gui-text="Overcut (mm)" _gui-description="The distance in mm that will be cut over the starting point of the path to prevent open paths. (Default: 1.00)">1.00</param>
- <param name="space" type="description">&#xa0;</param>
- <param name="useToolOffset" type="boolean" _gui-text="Use tool offset correction" _gui-description="Check this to use the tool offset correction, if not checked the 'Tool offset' and 'Precut' parameters are unused. (Default: Checked)">true</param>
- <param name="toolOffset" type="float" min="0.0" max="20.0" precision="2" _gui-text="Tool offset (mm)" _gui-description="The offset from the tool tip to the tool axis in mm. (Default: 0.25)">0.25</param>
- <param name="precut" type="boolean" _gui-text="Use precut" _gui-description="Check this to plot a small line before the real plot to align the tool orientation for the first real plot. (Default: Checked)">true</param>
- <param name="space" type="description">&#xa0;</param>
- <_param name="offsetNote" type="description">Please note that using the tool offset correction will move your plot away from the zero point by one tool offset length.</_param>
- </page>
- <page name="misc" _gui-text="Miscellaneous">
+ <page name="misc" _gui-text="Plot Features ">
+ <param name="overcut" type="float" min="0.0" max="100.0" precision="2" _gui-text="Overcut (mm)" _gui-description="The distance in mm that will be cut over the starting point of the path to prevent open paths, set to 0.0 to omit command. (Default: 1.00)">1.00</param>
+ <param name="toolOffset" type="float" min="0.0" max="20.0" precision="2" _gui-text="Tool offset (mm)" _gui-description="The offset from the tool tip to the tool axis in mm, set to 0.0 to omit command. (Default: 0.25)">0.25</param>
+ <param name="precut" type="boolean" _gui-text="Use precut" _gui-description="Check this to cut a small line before the real drawing starts to correctly align the tool orientation. (Default: Checked)">true</param>
<param name="flat" type="float" min="0.1" max="10.0" precision="1" _gui-text="Curve flatness" _gui-description="Curves are divided into lines, this number controls how fine the curves will be reproduced, the smaller the finer. (Default: '1.2')">1.2</param>
- <param name="offsetX" type="float" min="-10000.0" max="10000.0" precision="2" _gui-text="X offset (mm)" _gui-description="The offset to move your plot away from the zero point on the X axis in mm. (Default: '0.00')">0.00</param>
- <param name="offsetY" type="float" min="-10000.0" max="10000.0" precision="2" _gui-text="Y offset (mm)" _gui-description="The offset to move your plot away from the zero point on the Y axis in mm. (Default: '0.00')">0.00</param>
+ <param name="autoAlign" type="boolean" _gui-text="Auto align" _gui-description="Check this to auto align the drawing to the zero point (Plus the tool offset if used). If unchecked you have to make sure that all parts of your drawing are within the document border! (Default: Checked)">true</param>
+ <param name="space" type="description">&#xa0;</param>
<param name="debug" type="boolean" _gui-text="Show debug information" _gui-description="Check this to get verbose information about the plot without actually sending something to the plotter (A.k.a. data dump). (Default: Unchecked)">false</param>
</page>
</param>
<_param name="settingsHelp" type="description">All these settings depend on the plotter you use, for more information please consult the manual or homepage for your plotter.</_param>
- <effect needs-live-preview="false">
+ <effect needs-live-preview="false" needs-document="true">
<object-type>path</object-type>
<effects-menu>
- <submenu _name="Plotter"/>
+ <submenu _name="Export"/>
</effects-menu>
</effect>
<script>
diff --git a/share/extensions/plotter.py b/share/extensions/plotter.py
index 394f83786..398ab683e 100644
--- a/share/extensions/plotter.py
+++ b/share/extensions/plotter.py
@@ -30,12 +30,15 @@ import inkex
inkex.localize()
-# TODO: Unittests
-class MyEffect(inkex.Effect):
+class Plot(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
self.OptionParser.add_option('--tab', action='store', type='string', dest='tab')
+ self.OptionParser.add_option('--serialPort', action='store', type='string', dest='serialPort', default='COM1', help='Serial port')
+ self.OptionParser.add_option('--serialBaudRate', action='store', type='string', dest='serialBaudRate', default='9600', help='Serial Baud rate')
+ self.OptionParser.add_option('--flowControl', action='store', type='string', dest='flowControl', default='0', help='Flow control')
+ self.OptionParser.add_option('--commandLanguage', action='store', type='string', dest='commandLanguage', default='hpgl', help='Command Language')
self.OptionParser.add_option('--resolutionX', action='store', type='float', dest='resolutionX', default=1016.0, help='Resolution X (dpi)')
self.OptionParser.add_option('--resolutionY', action='store', type='float', dest='resolutionY', default=1016.0, help='Resolution Y (dpi)')
self.OptionParser.add_option('--pen', action='store', type='int', dest='pen', default=1, help='Pen number')
@@ -45,18 +48,11 @@ class MyEffect(inkex.Effect):
self.OptionParser.add_option('--mirrorX', action='store', type='inkbool', dest='mirrorX', default='FALSE', help='Mirror X axis')
self.OptionParser.add_option('--mirrorY', action='store', type='inkbool', dest='mirrorY', default='FALSE', help='Mirror Y axis')
self.OptionParser.add_option('--center', action='store', type='inkbool', dest='center', default='FALSE', help='Center zero point')
- self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness')
- self.OptionParser.add_option('--useOvercut', action='store', type='inkbool', dest='useOvercut', default='TRUE', help='Use overcut')
self.OptionParser.add_option('--overcut', action='store', type='float', dest='overcut', default=1.0, help='Overcut (mm)')
- self.OptionParser.add_option('--useToolOffset', action='store', type='inkbool', dest='useToolOffset', default='TRUE', help='Correct tool offset')
self.OptionParser.add_option('--toolOffset', action='store', type='float', dest='toolOffset', default=0.25, help='Tool offset (mm)')
self.OptionParser.add_option('--precut', action='store', type='inkbool', dest='precut', default='TRUE', help='Use precut')
- self.OptionParser.add_option('--offsetX', action='store', type='float', dest='offsetX', default=0.0, help='X offset (mm)')
- self.OptionParser.add_option('--offsetY', action='store', type='float', dest='offsetY', default=0.0, help='Y offset (mm)')
- self.OptionParser.add_option('--serialPort', action='store', type='string', dest='serialPort', default='COM1', help='Serial port')
- self.OptionParser.add_option('--serialBaudRate', action='store', type='string', dest='serialBaudRate', default='9600', help='Serial Baud rate')
- self.OptionParser.add_option('--flowControl', action='store', type='string', dest='flowControl', default='0', help='Flow control')
- self.OptionParser.add_option('--commandLanguage', action='store', type='string', dest='commandLanguage', default='hpgl', help='Command Language')
+ self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness')
+ self.OptionParser.add_option('--autoAlign', action='store', type='inkbool', dest='autoAlign', default='TRUE', help='Auto align')
self.OptionParser.add_option('--debug', action='store', type='inkbool', dest='debug', default='FALSE', help='Show debug information')
def effect(self):
@@ -74,18 +70,21 @@ class MyEffect(inkex.Effect):
raise ValueError, ('', type, value), traceback
# TODO: Get preview to work. This requires some work on the C++ side to be able to determine if it is
# a preview or a final run. (Remember to set <effect needs-live-preview='false'> to true)
- # This outcommented code has a user unit issue (getSvg produces px, docWidth could be mm or something else)
'''
- # reparse data for preview
- self.options.showMovements = True
- self.options.docWidth = float(self.unittouu(self.document.getroot().get('width')))
- self.options.docHeight = float(self.unittouu(self.document.getroot().get('height')))
- myHpglDecoder = hpgl_decoder.hpglDecoder(self.hpgl, self.options)
- doc, warnings = myHpglDecoder.getSvg()
- # deliver document to inkscape
- self.document = doc
+ if MAGIC:
+ # reparse data for preview
+ self.options.showMovements = True
+ self.options.docWidth = self.uutounit(self.unittouu(self.document.getroot().get('width')), "px")
+ self.options.docHeight = self.uutounit(self.unittouu(self.document.getroot().get('height')), "px")
+ myHpglDecoder = hpgl_decoder.hpglDecoder(self.hpgl, self.options)
+ doc, warnings = myHpglDecoder.getSvg()
+ # deliver document to inkscape
+ self.document = doc
+ else:
'''
# convert to other formats
+ if self.options.commandLanguage == 'HPGL':
+ self.convertToHpgl()
if self.options.commandLanguage == 'DMPL':
self.convertToDmpl()
if self.options.commandLanguage == 'ZING':
@@ -96,6 +95,15 @@ class MyEffect(inkex.Effect):
else:
self.sendHpglToSerial()
+ def convertToHpgl(self):
+ # convert raw HPGL to HPGL
+ hpglInit = 'IN;SP%d' % self.options.pen
+ if self.options.force > 0:
+ hpglInit += ';FS%d' % self.options.force
+ if self.options.speed > 0:
+ hpglInit += ';VS%d' % self.options.speed
+ self.hpgl = hpglInit + self.hpgl + ';PU0,0;SP0;IN;'
+
def convertToDmpl(self):
# convert HPGL to DMPL
# ;: = Initialise plotter
@@ -112,16 +120,20 @@ class MyEffect(inkex.Effect):
self.hpgl = self.hpgl.replace(';', ',')
self.hpgl = self.hpgl.replace('PU', 'U')
self.hpgl = self.hpgl.replace('PD', 'D')
- velocity = ''
+ dmplInit = ';:HAL0P%d' % self.options.pen
if self.options.speed > 0:
- velocity = 'V' + str(self.options.speed)
- self.hpgl = re.sub(r'IN,SP[0-9]+(,FS[0-9]+)?(,VS[0-9]+)?,', r';:HAL0P' + str(self.options.pen) + velocity + 'EC1', self.hpgl)
- self.hpgl += 'Z'
+ dmplInit += 'V%d' % self.options.speed
+ dmplInit += 'EC1'
+ self.hpgl = dmplInit + self.hpgl[1:] + ',U0,0,P0Z'
def convertToZing(self):
# convert HPGL to Zing
- self.hpgl = self.hpgl.replace('IN;', 'ZG;')
- self.hpgl += '@'
+ hpglInit = 'ZG;SP%d' % self.options.pen
+ if self.options.force > 0:
+ hpglInit += ';FS%d' % self.options.force
+ if self.options.speed > 0:
+ hpglInit += ';VS%d' % self.options.speed
+ self.hpgl = hpglInit + self.hpgl + ';PU0,0;SP0;@'
def sendHpglToSerial(self):
# gracefully exit script when pySerial is missing
@@ -173,14 +185,11 @@ class MyEffect(inkex.Effect):
inkex.errormsg(' Mirror X axis: ' + str(self.options.mirrorX))
inkex.errormsg(' Mirror Y axis: ' + str(self.options.mirrorY))
inkex.errormsg(' Center zero point: ' + str(self.options.center))
- inkex.errormsg(' Use overcut: ' + str(self.options.useOvercut))
inkex.errormsg(' Overcut (mm): ' + str(self.options.overcut))
- inkex.errormsg(' Use tool offset correction: ' + str(self.options.useToolOffset))
inkex.errormsg(' Tool offset (mm): ' + str(self.options.toolOffset))
inkex.errormsg(' Use precut: ' + str(self.options.precut))
inkex.errormsg(' Curve flatness: ' + str(self.options.flat))
- inkex.errormsg(' X offset (mm): ' + str(self.options.offsetX))
- inkex.errormsg(' Y offset (mm): ' + str(self.options.offsetY))
+ inkex.errormsg(' Auto align: ' + str(self.options.autoAlign))
inkex.errormsg(' Show debug information: ' + str(self.options.debug))
inkex.errormsg("\nDocument properties:\n")
version = self.document.getroot().xpath('//@inkscape:version', namespaces=inkex.NSS)
@@ -189,20 +198,20 @@ class MyEffect(inkex.Effect):
fileName = self.document.getroot().xpath('//@sodipodi:docname', namespaces=inkex.NSS)
if fileName:
inkex.errormsg(' Filename: ' + fileName[0])
- inkex.errormsg(' Document unit: ' + debugObject.documentUnit)
- inkex.errormsg(' Width: ' + str(debugObject.debugValues[0]) + ' ' + debugObject.documentUnit)
- inkex.errormsg(' Height: ' + str(debugObject.debugValues[1]) + ' ' + debugObject.documentUnit)
- if debugObject.debugValues[2] == 0:
+ inkex.errormsg(' Document unit: ' + self.getDocumentUnit())
+ inkex.errormsg(' Width: ' + str(debugObject.debugValues['docWidth']) + ' ' + self.getDocumentUnit())
+ inkex.errormsg(' Height: ' + str(debugObject.debugValues['docHeight']) + ' ' + self.getDocumentUnit())
+ if debugObject.debugValues['viewBoxWidth'] == "-":
inkex.errormsg(' Viewbox Width: -')
inkex.errormsg(' Viewbox Height: -')
else:
- inkex.errormsg(' Viewbox Width: ' + str(debugObject.debugValues[2]) + ' ' + debugObject.documentUnit)
- inkex.errormsg(' Viewbox Height: ' + str(debugObject.debugValues[3]) + ' ' + debugObject.documentUnit)
+ inkex.errormsg(' Viewbox Width: ' + str(self.unittouu(self.addDocumentUnit(debugObject.debugValues['viewBoxWidth']))) + ' ' + self.getDocumentUnit())
+ inkex.errormsg(' Viewbox Height: ' + str(self.unittouu(self.addDocumentUnit(debugObject.debugValues['viewBoxHeight']))) + ' ' + self.getDocumentUnit())
inkex.errormsg("\n" + self.options.commandLanguage + " properties:\n")
- inkex.errormsg(' Drawing width: ' + str(debugObject.debugValues[6]) + ' ' + debugObject.documentUnit)
- inkex.errormsg(' Drawing height: ' + str(debugObject.debugValues[7]) + ' ' + debugObject.documentUnit)
- inkex.errormsg(' Drawing width: ' + str(debugObject.debugValues[4]) + ' plotter steps')
- inkex.errormsg(' Drawing height: ' + str(debugObject.debugValues[5]) + ' plotter steps')
+ inkex.errormsg(' Drawing width: ' + str(self.unittouu(self.addDocumentUnit(str(debugObject.debugValues['drawingWidthUU'])))) + ' ' + self.getDocumentUnit())
+ inkex.errormsg(' Drawing height: ' + str(self.unittouu(self.addDocumentUnit(str(debugObject.debugValues['drawingHeightUU'])))) + ' ' + self.getDocumentUnit())
+ inkex.errormsg(' Drawing width: ' + str(debugObject.debugValues['drawingWidth']) + ' plotter steps')
+ inkex.errormsg(' Drawing height: ' + str(debugObject.debugValues['drawingHeight']) + ' plotter steps')
inkex.errormsg(' Offset X: ' + str(debugObject.offsetX) + ' plotter steps')
inkex.errormsg(' Offset Y: ' + str(debugObject.offsetX) + ' plotter steps')
inkex.errormsg(' Overcut: ' + str(debugObject.overcut) + ' plotter steps')
@@ -214,7 +223,7 @@ class MyEffect(inkex.Effect):
if __name__ == '__main__':
# start extension
- e = MyEffect()
+ e = Plot()
e.affect()
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 \ No newline at end of file
diff --git a/share/extensions/polyhedron_3d.py b/share/extensions/polyhedron_3d.py
index d1d6adc0f..f191d7f89 100755
--- a/share/extensions/polyhedron_3d.py
+++ b/share/extensions/polyhedron_3d.py
@@ -459,6 +459,7 @@ class Poly_3D(inkex.Effect):
get_obj_data(obj, file)#load data from the obj file
obj.set_type(so)#set the type (face or edge) as per the settings
+ scale = self.unittouu('1px') # convert to document units
st = Style(so) #initialise style
fill_col = (so.f_r, so.f_g, so.f_b) #colour tuple for the face fill
lighting = normalise( (so.lv_x,-so.lv_y,so.lv_z) ) #unit light vector
@@ -467,6 +468,8 @@ class Poly_3D(inkex.Effect):
#Put in in the centre of the current view
poly_transform = 'translate(' + str( self.view_center[0]) + ',' + str( self.view_center[1]) + ')'
+ if scale != 1:
+ poly_transform += ' scale(' + str(scale) + ')'
#we will put all the rotations in the object name, so it can be repeated in
poly_name = obj.name+':'+make_rotation_log(so)
poly_attribs = {inkex.addNS('label','inkscape'):poly_name,
diff --git a/share/extensions/printing_marks.py b/share/extensions/printing_marks.py
index 5c6ac3a61..0306048d6 100755
--- a/share/extensions/printing_marks.py
+++ b/share/extensions/printing_marks.py
@@ -191,20 +191,21 @@ class Printing_Marks (inkex.Effect):
i += 0.1
def get_selection_area(self):
+ scale = self.unittouu('1px') # convert to document units
sel_area = {}
min_x, min_y, max_x, max_y = False, False, False, False
for id in self.options.ids:
sel_area[id] = {}
for att in [ "x", "y", "width", "height" ]:
args = [ "inkscape", "-I", id, "--query-"+att, self.svg_file ]
- sel_area[id][att] = \
- Popen(args, stdout=PIPE, stderr=PIPE).communicate()[0]
- current_min_x = float( sel_area[id]["x"] )
- current_min_y = float( sel_area[id]["y"] )
- current_max_x = float( sel_area[id]["x"] ) + \
- float( sel_area[id]["width"] )
- current_max_y = float( sel_area[id]["y"] ) + \
- float( sel_area[id]["height"] )
+ sel_area[id][att] = scale* \
+ float(Popen(args, stdout=PIPE, stderr=PIPE).communicate()[0])
+ current_min_x = sel_area[id]["x"]
+ current_min_y = sel_area[id]["y"]
+ current_max_x = sel_area[id]["x"] + \
+ sel_area[id]["width"]
+ current_max_y = sel_area[id]["y"] + \
+ sel_area[id]["height"]
if not min_x: min_x = current_min_x
if not min_y: min_y = current_min_y
if not max_x: max_x = current_max_x
diff --git a/share/extensions/render_alphabetsoup.py b/share/extensions/render_alphabetsoup.py
index ad43163e4..083f03af9 100755
--- a/share/extensions/render_alphabetsoup.py
+++ b/share/extensions/render_alphabetsoup.py
@@ -514,7 +514,7 @@ class AlphabetSoup(inkex.Effect):
help="Generate random (unreadable) text")
def effect(self):
- zoom = self.options.zoom
+ zoom = self.unittouu( str(self.options.zoom) + 'px')
if self.options.randomize:
imagelist = generate_random_string(self.options.text, zoom)
diff --git a/share/extensions/render_barcode.py b/share/extensions/render_barcode.py
index ecfe215aa..c3b809c9e 100755
--- a/share/extensions/render_barcode.py
+++ b/share/extensions/render_barcode.py
@@ -1,21 +1,25 @@
#!/usr/bin/env python
-'''
-Copyright (C) 2007 Martin Owens
-
-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
-'''
+#
+# Copyright (C) 2007 Martin Owens
+#
+# 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
+#
+"""
+Inkscape's general barcode extension. Run from within inkscape or use the
+Barcode module provided for outside or scripting.
+"""
import inkex
import sys
@@ -45,6 +49,7 @@ class InsertBarcode(inkex.Effect):
'document' : self.document,
'x' : x,
'y' : y,
+ 'scale' : self.unittouu('1px'),
} )
if bargen is not None:
barcode = bargen.generate()
diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py
index 2d28bb433..bca1d2241 100755
--- a/share/extensions/render_barcode_datamatrix.py
+++ b/share/extensions/render_barcode_datamatrix.py
@@ -665,6 +665,7 @@ class DataMatrix(inkex.Effect):
def effect(self):
+ scale = self.unittouu('1px') # convert to document units
so = self.options
rows = so.ROWS
@@ -680,7 +681,7 @@ class DataMatrix(inkex.Effect):
#INKSCAPE GROUP TO CONTAIN EVERYTHING
centre = self.view_center #Put in in the centre of the current view
- grp_transform = 'translate' + str( centre )
+ grp_transform = 'translate' + str( centre ) + ' scale(%f)' % scale
grp_name = 'DataMatrix'
grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
'transform':grp_transform }
diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py
index 8147d49a6..7b4895195 100755
--- a/share/extensions/render_barcode_qrcode.py
+++ b/share/extensions/render_barcode_qrcode.py
@@ -1047,6 +1047,7 @@ class QRCodeInkscape(inkex.Effect):
def effect(self):
+ scale = self.unittouu('1px') # convert to document units
so = self.options
if so.TEXT == '': #abort if converting blank text
@@ -1057,7 +1058,7 @@ class QRCodeInkscape(inkex.Effect):
so.TEXT = unicode(so.TEXT, so.input_encode)
centre = self.view_center #Put in in the centre of the current view
- grp_transform = 'translate' + str( centre )
+ grp_transform = 'translate' + str( centre ) + ' scale(%f)' % scale
grp_name = 'QR Code: '+so.TEXT
grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
'transform':grp_transform }
diff --git a/share/extensions/render_gear_rack.py b/share/extensions/render_gear_rack.py
index 13eaf1017..68c5d050e 100644
--- a/share/extensions/render_gear_rack.py
+++ b/share/extensions/render_gear_rack.py
@@ -65,8 +65,8 @@ class RackGear(inkex.Effect):
help="Contact Angle")
def effect(self):
- length = self.options.length
- spacing = self.options.spacing
+ length = self.unittouu(str(self.options.length) + 'px')
+ spacing = self.unittouu(str(self.options.spacing) + 'px')
angle = radians(self.options.angle)
# generate points: list of (x, y) pairs
@@ -93,7 +93,7 @@ class RackGear(inkex.Effect):
g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
# Create SVG Path for gear
- style = {'stroke': '#000000', 'fill': 'none'}
+ style = {'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px'))}
gear_attribs = {
'style': simplestyle.formatStyle(style),
'd': path}
diff --git a/share/extensions/render_gears.py b/share/extensions/render_gears.py
index 5201e553b..5fdb0d4f6 100644
--- a/share/extensions/render_gears.py
+++ b/share/extensions/render_gears.py
@@ -35,9 +35,9 @@ def point_on_circle(radius, angle):
def points_to_svgd(p):
f = p[0]
p = p[1:]
- svgd = 'M%.3f,%.3f' % f
+ svgd = 'M%.5f,%.5f' % f
for x in p:
- svgd += 'L%.3f,%.3f' % x
+ svgd += ' L%.5f,%.5f' % x
svgd += 'z'
return svgd
@@ -164,7 +164,7 @@ class Gears(inkex.Effect):
g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs)
# Create SVG Path for gear
- style = { 'stroke': '#000000', 'fill': 'none' }
+ style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) }
gear_attribs = {'style':simplestyle.formatStyle(style), 'd':path}
gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs )
if(centerdiameter > 0.0):
diff --git a/share/extensions/rtree.py b/share/extensions/rtree.py
index 3231d284e..db677d0d5 100755
--- a/share/extensions/rtree.py
+++ b/share/extensions/rtree.py
@@ -44,7 +44,9 @@ class RTreeTurtle(inkex.Effect):
dest="minimum", default=4.0,
help="minimum branch size")
def effect(self):
- s = {'stroke-linejoin': 'miter', 'stroke-width': '1.0px',
+ self.options.size = self.unittouu(str(self.options.size) + 'px')
+ self.options.minimum = self.unittouu(str(self.options.minimum) + 'px')
+ s = {'stroke-linejoin': 'miter', 'stroke-width': str(self.unittouu('1px')),
'stroke-opacity': '1.0', 'fill-opacity': '1.0',
'stroke': '#000000', 'stroke-linecap': 'butt',
'fill': 'none'}
diff --git a/share/extensions/spirograph.py b/share/extensions/spirograph.py
index cb9d1ac24..77a258d5f 100755
--- a/share/extensions/spirograph.py
+++ b/share/extensions/spirograph.py
@@ -47,6 +47,9 @@ class Spirograph(inkex.Effect):
help="The quality of the calculated output")
def effect(self):
+ self.options.primaryr = self.unittouu(str(self.options.primaryr) + 'px')
+ self.options.secondaryr = self.unittouu(str(self.options.secondaryr) + 'px')
+ self.options.penr = self.unittouu(str(self.options.penr) + 'px')
if self.options.secondaryr == 0:
return
@@ -68,7 +71,7 @@ class Spirograph(inkex.Effect):
rotation = - math.pi * self.options.rotation / 180;
new = inkex.etree.Element(inkex.addNS('path','svg'))
- s = { 'stroke': '#000000', 'fill': 'none' }
+ s = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.unittouu('1px')) }
new.set('style', simplestyle.formatStyle(s))
pathString = ''
diff --git a/share/extensions/summersnight.py b/share/extensions/summersnight.py
index aea5cea55..67413a05c 100755
--- a/share/extensions/summersnight.py
+++ b/share/extensions/summersnight.py
@@ -45,6 +45,7 @@ class Project(inkex.Effect):
exit()
#obj is selected second
+ scale = self.unittouu('1px') # convert to document units
obj = self.selected[self.options.ids[0]]
trafo = self.selected[self.options.ids[1]]
if obj.get(inkex.addNS('type','sodipodi')):
@@ -75,11 +76,11 @@ class Project(inkex.Effect):
if bsubprocess:
p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE)
rc = p.wait()
- self.q[query] = float(p.stdout.read())
+ self.q[query] = scale*float(p.stdout.read())
err = p.stderr.read()
else:
f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:]
- self.q[query] = float(f.read())
+ self.q[query] = scale*float(f.read())
f.close()
err.close()
diff --git a/share/extensions/tar_layers.inx b/share/extensions/tar_layers.inx
new file mode 100644
index 000000000..d70fb3ae9
--- /dev/null
+++ b/share/extensions/tar_layers.inx
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <_name>Collection of SVG files One per root layer</_name>
+ <id>org.inkscape.output.LAYERS</id>
+ <dependency type="extension">org.inkscape.output.svg.inkscape</dependency>
+ <dependency type="executable" location="extensions">tar_layers.py</dependency>
+ <dependency type="executable" location="extensions">inkex.py</dependency>
+ <output>
+ <extension>.tar</extension>
+ <mimetype>application/tar</mimetype>
+ <_filetypename>Layers as Separate SVG (*.tar)</_filetypename>
+ <_filetypetooltip>Each layer split into it's own svg file and collected as a tape archive (tar file)</_filetypetooltip>
+ <dataloss>false</dataloss>
+ </output>
+ <script>
+ <command reldir="extensions" interpreter="python">tar_layers.py</command>
+ <helper_extension>org.inkscape.output.svg.inkscape</helper_extension>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/tar_layers.py b/share/extensions/tar_layers.py
new file mode 100755
index 000000000..3707af1f8
--- /dev/null
+++ b/share/extensions/tar_layers.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2014 Martin Owens, email@doctormo.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
+#
+"""
+An extension to export multiple svg files from a single svg file containing layers.
+
+Each defs is duplicated for each svg outputed.
+"""
+import os
+import sys
+import copy
+import tarfile
+import StringIO
+import calendar
+import time
+
+# Inkscape Libraries
+import inkex
+import simplestyle
+
+GROUP = "{http://www.w3.org/2000/svg}g"
+LABEL = "{http://www.inkscape.org/namespaces/inkscape}label"
+GROUPMODE = "{http://www.inkscape.org/namespaces/inkscape}groupmode"
+
+
+def oprint(item):
+ """DEBUG print an object"""
+ for name in dir(item):
+ value = getattr(item, name)
+ if callable(value):
+ yield "%s()" % name
+ else:
+ yield "%s = %s" % (name, str(value))
+
+def fprint(data):
+ """DEBUG print something"""
+ if isinstance(data, basestring):
+ sys.stderr.write("DEBUG: %s\n" % data)
+ else:
+ return fprint("%s(%s)\n " % (str(data), type(data).__name__) \
+ + "\n ".join(oprint(data)))
+
+
+class LayersOutput(inkex.Effect):
+ """Entry point to our layers export"""
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ if os.name == 'nt':
+ self.encoding = "cp437"
+ else:
+ self.encoding = "latin-1"
+
+ def make_template(self):
+ """Returns the current document as a new empty document with the same defs"""
+ newdoc = copy.deepcopy(self.document)
+ for (name, layer) in self.layers(newdoc):
+ layer.getparent().remove(layer)
+ return newdoc
+
+ def layers(self, document):
+ for node in document.getroot().iterchildren():
+ if self.is_layer(node):
+ name = node.attrib.get(LABEL, None)
+ if name:
+ yield (name, node)
+
+ def is_layer(self, node):
+ return node.tag == GROUP and node.attrib.get(GROUPMODE,'').lower() == 'layer'
+
+ def io_document(self, name, doc):
+ string = StringIO.StringIO()
+ doc.write(string)
+ string.seek(0)
+ info = tarfile.TarInfo(name=name+'.svg')
+ info.mtime = calendar.timegm(time.gmtime())
+ info.size = len(string.buf)
+ return dict(tarinfo=info, fileobj=string)
+
+ def effect(self):
+ # open output tar file as a stream (to stdout)
+ tar = tarfile.open(fileobj=sys.stdout, mode='w|')
+
+ # Switch stdout to binary on Windows.
+ if sys.platform == "win32":
+ import msvcrt
+ msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
+
+ template = self.make_template()
+
+ previous = None
+ for (name, _layer) in self.layers(self.document):
+ layer = copy.deepcopy(_layer)
+ if previous != None:
+ template.getroot().replace(previous, layer)
+ else:
+ template.getroot().append(layer)
+ previous = layer
+
+ tar.addfile(**self.io_document(name, template))
+
+
+if __name__ == '__main__': #pragma: no cover
+ e = LayersOutput()
+ e.affect()
+
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
diff --git a/share/extensions/test/hpgl_output.test.py b/share/extensions/test/hpgl_output.test.py
index 4d9500b1e..19fdeb661 100755
--- a/share/extensions/test/hpgl_output.test.py
+++ b/share/extensions/test/hpgl_output.test.py
@@ -12,13 +12,13 @@ sys.path.append('..') # this line allows to import the extension code
import unittest
from hpgl_output import *
-class MyEffectBasicTest(unittest.TestCase):
+class HPGLOuputBasicTest(unittest.TestCase):
#def setUp(self):
def test_run_without_parameters(self):
args = [ 'minimal-blank.svg' ]
- e = MyEffect()
+ e = HpglOutput()
e.affect( args, False )
#self.assertEqual( e.something, 'some value', 'A commentary about that.' )
diff --git a/share/extensions/text_extract.py b/share/extensions/text_extract.py
index a27cfff50..bf263ef39 100755
--- a/share/extensions/text_extract.py
+++ b/share/extensions/text_extract.py
@@ -22,14 +22,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
-import inkex, os, csv, math, chardataeffect, string
-
+# standard library
+import chardataeffect
+from copy import deepcopy
+import csv
+import math
+import os
+import string
try:
from subprocess import Popen, PIPE
bsubprocess = True
except:
bsubprocess = False
+# local library
+import inkex
+
class Extract(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
@@ -137,14 +145,19 @@ class Extract(inkex.Effect):
objlist.sort()
#move them to the top of the object stack in this order.
for item in objlist:
- self.recurse(self.selected[item[1]])
+ self.recurse(deepcopy(self.selected[item[1]]))
def recurse(self, node):
istext = (node.tag == '{http://www.w3.org/2000/svg}flowPara' or node.tag == '{http://www.w3.org/2000/svg}flowDiv' or node.tag == '{http://www.w3.org/2000/svg}text')
- if node.text != None:
- inkex.errormsg(node.text)
- for child in node:
- self.recurse(child)
+ if node.text != None or node.tail != None:
+ for child in node:
+ if child.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role'):
+ child.tail = "\n"
+ inkex.errormsg(inkex.etree.tostring(node, method='text').strip())
+ else:
+ for child in node:
+ self.recurse(child)
+
if __name__ == '__main__':
e = Extract()
diff --git a/share/extensions/text_merge.inx b/share/extensions/text_merge.inx
index c871f52c0..fbbe7e857 100644
--- a/share/extensions/text_merge.inx
+++ b/share/extensions/text_merge.inx
@@ -20,7 +20,7 @@
<_item value="m">Middle</_item>
<_item value="b">Bottom</_item>
</param>
- <param name="flowtext" type="boolean" _gui-text="Flow text">false</param>
+<!-- <param name="flowtext" type="boolean" _gui-text="Flow text">false</param> -->
<param name="keepstyle" type="boolean" _gui-text="Keep style">true</param>
<effect>
<object-type>all</object-type>
diff --git a/share/extensions/text_merge.py b/share/extensions/text_merge.py
index 8cd8b751d..dc6ee331c 100644
--- a/share/extensions/text_merge.py
+++ b/share/extensions/text_merge.py
@@ -191,6 +191,9 @@ class Merge(inkex.Effect):
newspan.text = node.text
for child in node:
self.recurse(child, newspan)
+ if (node.tail and node.tag != '{http://www.w3.org/2000/svg}text'):
+ newspan.tail = node.tail
+
if __name__ == '__main__':
e = Merge()
diff --git a/share/extensions/triangle.py b/share/extensions/triangle.py
index 81945f370..019db3147 100755
--- a/share/extensions/triangle.py
+++ b/share/extensions/triangle.py
@@ -69,7 +69,7 @@ def is_valid_tri_from_sides(a,b,c):#check whether triangle with sides a,b,c is v
return (a+b)>c and (a+c)>b and (b+c)>a and a > 0 and b> 0 and c>0#two sides must always be greater than the third
#no zero-length sides, no degenerate case
-def draw_tri_from_3_sides(s_a, s_b, s_c, offset, parent): #draw a triangle from three sides (with a given offset
+def draw_tri_from_3_sides(s_a, s_b, s_c, offset, width, parent): #draw a triangle from three sides (with a given offset
if is_valid_tri_from_sides(s_a,s_b,s_c):
a_b = angle_from_3_sides(s_a, s_c, s_b)
@@ -82,7 +82,7 @@ def draw_tri_from_3_sides(s_a, s_b, s_c, offset, parent): #draw a triangle from
offy = c[1]/2 #c is the highest point
offset = ( offset[0]-offx , offset[1]-offy ) #add the centre of the triangle to the offset
- draw_SVG_tri(a, b, c , offset, 2, 'Triangle', parent)
+ draw_SVG_tri(a, b, c , offset, width, 'Triangle', parent)
else:
sys.stderr.write('Error:Invalid Triangle Specifications.\n')
@@ -122,12 +122,16 @@ class Grid_Polar(inkex.Effect):
tri = self.current_layer
offset = (self.view_center[0],self.view_center[1]) #the offset require to centre the triangle
+ self.options.s_a = self.unittouu(str(self.options.s_a) + 'px')
+ self.options.s_b = self.unittouu(str(self.options.s_b) + 'px')
+ self.options.s_c = self.unittouu(str(self.options.s_c) + 'px')
+ stroke_width = self.unittouu('2px')
if self.options.mode == '3_sides':
s_a = self.options.s_a
s_b = self.options.s_b
s_c = self.options.s_c
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
elif self.options.mode == 's_ab_a_c':
s_a = self.options.s_a
@@ -135,7 +139,7 @@ class Grid_Polar(inkex.Effect):
a_c = self.options.a_c*pi/180 #in rad
s_c = third_side_from_enclosed_angle(s_a,s_b,a_c)
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
elif self.options.mode == 's_ab_a_a':
s_a = self.options.s_a
@@ -159,13 +163,13 @@ class Grid_Polar(inkex.Effect):
if not(error) and (a_b < pi) and (a_c < pi): #check that the solution is valid, if so draw acute solution
s_c = third_side_from_enclosed_angle(s_a,s_b,a_c)
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
if not(error) and ((a_b > pi) or (a_c > pi) or ambiguous):#we want the obtuse solution
a_b = pi - a_b
a_c = pi - a_a - a_b
s_c = third_side_from_enclosed_angle(s_a,s_b,a_c)
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
elif self.options.mode == 's_a_a_ab':
s_a = self.options.s_a
@@ -176,7 +180,7 @@ class Grid_Polar(inkex.Effect):
s_b = s_a*sin(a_b)/sin(a_a)
s_c = s_a*sin(a_c)/sin(a_a)
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
elif self.options.mode == 's_c_a_ab':
s_c = self.options.s_c
@@ -187,7 +191,7 @@ class Grid_Polar(inkex.Effect):
s_a = s_c*sin(a_a)/sin(a_c)
s_b = s_c*sin(a_b)/sin(a_c)
- draw_tri_from_3_sides(s_a, s_b, s_c, offset, tri)
+ draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri)
if __name__ == '__main__':
e = Grid_Polar()
diff --git a/share/extensions/voronoi2svg.py b/share/extensions/voronoi2svg.py
index c5b8a511f..289c352e3 100755
--- a/share/extensions/voronoi2svg.py
+++ b/share/extensions/voronoi2svg.py
@@ -220,15 +220,15 @@ class Voronoi2svg(inkex.Effect):
#{{{ Drawing styles
linestyle = {
- 'stroke' : '#000000',
- 'linewidth' : '1',
- 'fill' : 'none'
+ 'stroke' : '#000000',
+ 'stroke-width' : str(self.unittouu('1px')),
+ 'fill' : 'none'
}
facestyle = {
- 'stroke' : '#ff0000',
- 'linewidth' : '1',
- 'fill' : 'none'
+ 'stroke' : '#ff0000',
+ 'stroke-width' : str(self.unittouu('1px')),
+ 'fill' : 'none'
}
#}}}
diff --git a/share/extensions/webslicer_create_rect.py b/share/extensions/webslicer_create_rect.py
index 7c04e8706..b4e6858af 100755
--- a/share/extensions/webslicer_create_rect.py
+++ b/share/extensions/webslicer_create_rect.py
@@ -100,6 +100,7 @@ class WebSlicer_CreateRect(WebSlicer_Effect):
self.options.dimension
def effect(self):
+ scale = self.unittouu('1px') # convert to document units
self.validate_options()
layer = self.get_slicer_layer(True)
#TODO: get selected elements to define location and size
@@ -110,10 +111,10 @@ class WebSlicer_CreateRect(WebSlicer_Effect):
rect.set('id', self.options.name)
rect.set('fill', 'red')
rect.set('opacity', '0.5')
- rect.set('x', '-100')
- rect.set('y', '-100')
- rect.set('width', '200')
- rect.set('height', '200')
+ rect.set('x', str(-scale*100))
+ rect.set('y', str(-scale*100))
+ rect.set('width', str(scale*200))
+ rect.set('height', str(scale*200))
desc = inkex.etree.SubElement(rect, 'desc')
conf_txt = "format:"+ self.options.format +"\n"
if not is_empty(self.options.dpi):
diff --git a/share/extensions/wireframe_sphere.py b/share/extensions/wireframe_sphere.py
index 5804a1b45..bcd676dc4 100755
--- a/share/extensions/wireframe_sphere.py
+++ b/share/extensions/wireframe_sphere.py
@@ -63,10 +63,10 @@ import simplestyle
inkex.localize()
#SVG OUTPUT FUNCTIONS ================================================
-def draw_SVG_ellipse((rx, ry), (cx, cy), parent, start_end=(0,2*pi),transform='' ):
+def draw_SVG_ellipse((rx, ry), (cx, cy), width, parent, start_end=(0,2*pi),transform='' ):
style = { 'stroke' : '#000000',
- 'stroke-width' : '1',
+ 'stroke-width' : str(width),
'fill' : 'none' }
circ_attribs = {'style':simplestyle.formatStyle(style),
inkex.addNS('cx','sodipodi') :str(cx),
@@ -120,8 +120,10 @@ class Wireframe_Sphere(inkex.Effect):
else:
flip = '' #no flip
+ so.RADIUS = self.unittouu(str(so.RADIUS) + 'px')
so.TILT = abs(so.TILT)*(pi/180) #Convert to radians
so.ROT_OFFSET = so.ROT_OFFSET*(pi/180) #Convert to radians
+ stroke_width = self.unittouu('1px')
EPSILON = 0.001 #add a tiny value to the ellipse radii, so that if we get a zero radius, the ellipse still shows up as a line
@@ -174,7 +176,7 @@ class Wireframe_Sphere(inkex.Effect):
#finally, draw the line of longitude
#the centre is always at the centre of the sphere
- draw_SVG_ellipse( ( minorRad, so.RADIUS ), (0,0), grp_long , start_end,transform)
+ draw_SVG_ellipse( ( minorRad, so.RADIUS ), (0,0), stroke_width, grp_long , start_end,transform)
# LINES OF LATITUDE
if so.NUM_LAT > 0:
@@ -201,18 +203,18 @@ class Wireframe_Sphere(inkex.Effect):
if so.HIDE_BACK:
if lat_angle > so.TILT: #this LoLat is partially or fully visible
if lat_angle > pi-so.TILT: #this LoLat is fully visible
- draw_SVG_ellipse((majorRad, minorRad), (cx,cy), grp_lat)
+ draw_SVG_ellipse((majorRad, minorRad), (cx,cy), stroke_width, grp_lat)
else: #this LoLat is partially visible
proportion = -(acos( tan(lat_angle - pi/2)/tan(pi/2 - so.TILT)) )/pi + 1
start_end = ( pi/2 - proportion*pi, pi/2 + proportion*pi ) #make the start and end angles (mirror image around pi/2)
- draw_SVG_ellipse((majorRad, minorRad), (cx,cy), grp_lat, start_end)
+ draw_SVG_ellipse((majorRad, minorRad), (cx,cy), stroke_width, grp_lat, start_end)
else: #just draw the full lines of latitude
- draw_SVG_ellipse((majorRad, minorRad), (cx,cy), grp_lat)
+ draw_SVG_ellipse((majorRad, minorRad), (cx,cy), stroke_width, grp_lat)
#THE HORIZON CIRCLE
- draw_SVG_ellipse((so.RADIUS, so.RADIUS), (0,0), grp) #circle, centred on the sphere centre
+ draw_SVG_ellipse((so.RADIUS, so.RADIUS), (0,0), stroke_width, grp) #circle, centred on the sphere centre
if __name__ == '__main__':
e = Wireframe_Sphere()