diff options
| author | Peter Moulder <peter.moulder@monash.edu> | 2008-03-29 10:21:03 +0000 |
|---|---|---|
| committer | pjrm <pjrm@users.sourceforge.net> | 2008-03-29 10:21:03 +0000 |
| commit | 48cfa43e90e580b90d9d8ce37524cf79a06d56be (patch) | |
| tree | 6c323130b2f0c2fb32503513474fb36d84fc7ab9 | |
| parent | svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packa... (diff) | |
| download | inkscape-48cfa43e90e580b90d9d8ce37524cf79a06d56be.tar.gz inkscape-48cfa43e90e580b90d9d8ce37524cf79a06d56be.zip | |
svn propset svn:eol-style native *.py
(bzr r5228)
44 files changed, 3198 insertions, 3198 deletions
diff --git a/share/extensions/Barcode/Base.py b/share/extensions/Barcode/Base.py index 866d80e9e..4ba89d2d6 100644 --- a/share/extensions/Barcode/Base.py +++ b/share/extensions/Barcode/Base.py @@ -15,10 +15,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ''' -
+ import itertools import sys -from lxml import etree
+from lxml import etree class Barcode: def __init__(self, param={}): @@ -46,7 +46,7 @@ class Barcode: self.width = len(self.string) self.data = self.graphicalArray(self.string) - def generate(self):
+ def generate(self): svg_uri = u'http://www.w3.org/2000/svg' if not self.string or not self.data: return @@ -60,12 +60,12 @@ class Barcode: if not self.document: sys.stderr.write("No document defined to add barcode to\n") return -
- # Collect document ids
- doc_ids = {}
- docIdNodes = self.document.xpath('//@id')
- for m in docIdNodes:
- doc_ids[m] = 1
+ + # Collect document ids + doc_ids = {} + docIdNodes = self.document.xpath('//@id') + for m in docIdNodes: + doc_ids[m] = 1 # We don't have svg documents so lets do something raw: name = 'barcode' diff --git a/share/extensions/chardataeffect.py b/share/extensions/chardataeffect.py index 5b72030b6..a1758c890 100644 --- a/share/extensions/chardataeffect.py +++ b/share/extensions/chardataeffect.py @@ -1,59 +1,59 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jos Hirth, kaioa.com
-Copyright (C) 2007 bulia byak
-Copyright (C) 2007 Aaron C. Spike
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-'''
-import sys, optparse, inkex
-
-class CharDataEffect(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.visited = []
-
- newline = True
- newpar = True
-
- def effect(self):
- if len(self.selected)==0:
- self.recurse(self.document.getroot())
- else:
- for id,node in self.selected.iteritems():
- self.recurse(node)
-
- def recurse(self,node):
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jos Hirth, kaioa.com +Copyright (C) 2007 bulia byak +Copyright (C) 2007 Aaron C. Spike + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +import sys, optparse, inkex + +class CharDataEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.visited = [] + + newline = True + newpar = True + + def effect(self): + if len(self.selected)==0: + self.recurse(self.document.getroot()) + else: + for id,node in self.selected.iteritems(): + self.recurse(node) + + 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.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role') == 'line':
- self.newline = True
- elif istext:
- self.newline = True
- self.newpar = True
- - if node.text != None:
- node.text = self.process_chardata(node.text, self.newline, self.newpar)
- self.newline = False
- self.newpar = False
- - for child in node:
- self.recurse(child)
- - if node.tail != None:
- node.tail = self.process_chardata(node.tail, self.newline, self.newpar)
-
- def process_chardata(self,text, line, par):
- pass
-
+ if node.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role') == 'line': + self.newline = True + elif istext: + self.newline = True + self.newpar = True + + if node.text != None: + node.text = self.process_chardata(node.text, self.newline, self.newpar) + self.newline = False + self.newpar = False + + for child in node: + self.recurse(child) + + if node.tail != None: + node.tail = self.process_chardata(node.tail, self.newline, self.newpar) + + def process_chardata(self,text, line, par): + pass + diff --git a/share/extensions/color_brighter.py b/share/extensions/color_brighter.py index d7a52ee70..741473839 100644 --- a/share/extensions/color_brighter.py +++ b/share/extensions/color_brighter.py @@ -1,24 +1,24 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): FACTOR=0.9 -
- i=int(1.0/(1.0-FACTOR))
- if r==0 and g==0 and b==0:
- return '%02x%02x%02x' % (i,i,i)
- if r>0 and r<i:
- r=i
- if g>0 and g<i:
- g=i
- if b>0 and b<i:
- b=i;
-
- r=min(int(round((r/FACTOR))), 255)
- g=min(int(round((g/FACTOR))), 255)
- b=min(int(round((b/FACTOR))), 255)
-
- return '%02x%02x%02x' % (r,g,b)
-
-c = C()
-c.affect()
\ No newline at end of file + + i=int(1.0/(1.0-FACTOR)) + if r==0 and g==0 and b==0: + return '%02x%02x%02x' % (i,i,i) + if r>0 and r<i: + r=i + if g>0 and g<i: + g=i + if b>0 and b<i: + b=i; + + r=min(int(round((r/FACTOR))), 255) + g=min(int(round((g/FACTOR))), 255) + b=min(int(round((b/FACTOR))), 255) + + return '%02x%02x%02x' % (r,g,b) + +c = C() +c.affect() diff --git a/share/extensions/color_custom.py b/share/extensions/color_custom.py index 8d66a1668..1b866f684 100644 --- a/share/extensions/color_custom.py +++ b/share/extensions/color_custom.py @@ -1,25 +1,25 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def __init__(self):
- coloreffect.ColorEffect.__init__(self)
- self.OptionParser.add_option("--r", action="store", type="string", dest="rFunction", default="r",help="red channel function")
- self.OptionParser.add_option("--g", action="store", type="string", dest="gFunction", default="g",help="green channel function")
- self.OptionParser.add_option("--b", action="store", type="string", dest="bFunction", default="b",help="blue channel function")
- def normalize(self, v):
- if v<0:
- return 0.0
- if v>1:
- return 1.0
- return v
- def colmod(self,_r,_g,_b):
- r=float(_r)/255
- g=float(_g)/255
- b=float(_b)/255
- r2=self.normalize(eval(self.options.rFunction))
- g2=self.normalize(eval(self.options.gFunction))
- b2=self.normalize(eval(self.options.bFunction))
- return '%02x%02x%02x' % (int(round(r2*255)),int(round(g2*255)),int(round(b2*255)))
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def __init__(self): + coloreffect.ColorEffect.__init__(self) + self.OptionParser.add_option("--r", action="store", type="string", dest="rFunction", default="r",help="red channel function") + self.OptionParser.add_option("--g", action="store", type="string", dest="gFunction", default="g",help="green channel function") + self.OptionParser.add_option("--b", action="store", type="string", dest="bFunction", default="b",help="blue channel function") + def normalize(self, v): + if v<0: + return 0.0 + if v>1: + return 1.0 + return v + def colmod(self,_r,_g,_b): + r=float(_r)/255 + g=float(_g)/255 + b=float(_b)/255 + r2=self.normalize(eval(self.options.rFunction)) + g2=self.normalize(eval(self.options.gFunction)) + b2=self.normalize(eval(self.options.bFunction)) + return '%02x%02x%02x' % (int(round(r2*255)),int(round(g2*255)),int(round(b2*255))) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_darker.py b/share/extensions/color_darker.py index ce8899444..40bfb19e6 100644 --- a/share/extensions/color_darker.py +++ b/share/extensions/color_darker.py @@ -1,12 +1,12 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): FACTOR=0.9 - r=int(round(max(r*FACTOR,0)))
- g=int(round(max(g*FACTOR,0)))
- b=int(round(max(b*FACTOR,0)))
- return '%02x%02x%02x' % (r,g,b)
-
-c = C()
-c.affect()
\ No newline at end of file + r=int(round(max(r*FACTOR,0))) + g=int(round(max(g*FACTOR,0))) + b=int(round(max(b*FACTOR,0))) + return '%02x%02x%02x' % (r,g,b) + +c = C() +c.affect() diff --git a/share/extensions/color_desaturate.py b/share/extensions/color_desaturate.py index efdf2658a..28f747889 100644 --- a/share/extensions/color_desaturate.py +++ b/share/extensions/color_desaturate.py @@ -1,10 +1,10 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- l = (max(r,g,b)+min(r,g,b))/2
- ig=int(round(l))
- return '%02x%02x%02x' % (ig,ig,ig)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + l = (max(r,g,b)+min(r,g,b))/2 + ig=int(round(l)) + return '%02x%02x%02x' % (ig,ig,ig) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_grayscale.py b/share/extensions/color_grayscale.py index e8c44459a..ce354b167 100644 --- a/share/extensions/color_grayscale.py +++ b/share/extensions/color_grayscale.py @@ -1,14 +1,14 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- #ITU-R Recommendation BT.709
- #l = 0.2125 * r + 0.7154 * g + 0.0721 * b
- #NTSC and PAL
- l = 0.299 * r + 0.587 * g + 0.114 * b
- ig=int(round(l))
- #coloreffect.debug('gs '+hex(r)+' '+hex(g)+' '+hex(b)+'%02x%02x%02x' % (ig,ig,ig))
- return '%02x%02x%02x' % (ig,ig,ig)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + #ITU-R Recommendation BT.709 + #l = 0.2125 * r + 0.7154 * g + 0.0721 * b + #NTSC and PAL + l = 0.299 * r + 0.587 * g + 0.114 * b + ig=int(round(l)) + #coloreffect.debug('gs '+hex(r)+' '+hex(g)+' '+hex(b)+'%02x%02x%02x' % (ig,ig,ig)) + return '%02x%02x%02x' % (ig,ig,ig) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_lesshue.py b/share/extensions/color_lesshue.py index 74ac5ae28..ec4445641 100644 --- a/share/extensions/color_lesshue.py +++ b/share/extensions/color_lesshue.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[0] = hsl[0] - 0.05 - if hsl[0] < 0.0:
- hsl[0] = 1.0 + hsl[0]
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[0] < 0.0: + hsl[0] = 1.0 + hsl[0] + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_lesslight.py b/share/extensions/color_lesslight.py index 6f912f0ea..8841490ce 100644 --- a/share/extensions/color_lesslight.py +++ b/share/extensions/color_lesslight.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[2] = hsl[2] - 0.05 - if hsl[2] < 0.0:
- hsl[2] = 0.0
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[2] < 0.0: + hsl[2] = 0.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_lesssaturation.py b/share/extensions/color_lesssaturation.py index 422a01994..7b06f98f5 100644 --- a/share/extensions/color_lesssaturation.py +++ b/share/extensions/color_lesssaturation.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[1] = hsl[1] - 0.05 - if hsl[1] < 0.0:
- hsl[1] = 0.0
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[1] < 0.0: + hsl[1] = 0.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_morehue.py b/share/extensions/color_morehue.py index bc25274ac..816a94c12 100644 --- a/share/extensions/color_morehue.py +++ b/share/extensions/color_morehue.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[0] = hsl[0] + 0.05 - if hsl[0] > 1.0:
- hsl[0] = hsl[0] - 1.0
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[0] > 1.0: + hsl[0] = hsl[0] - 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_morelight.py b/share/extensions/color_morelight.py index 483af7fa0..b930a86df 100644 --- a/share/extensions/color_morelight.py +++ b/share/extensions/color_morelight.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[2] = hsl[2] + 0.05 - if hsl[2] > 1.0:
- hsl[2] = 1.0
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[2] > 1.0: + hsl[2] = 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_moresaturation.py b/share/extensions/color_moresaturation.py index 2ae7f33b7..5f3ab814f 100644 --- a/share/extensions/color_moresaturation.py +++ b/share/extensions/color_moresaturation.py @@ -1,14 +1,14 @@ -import coloreffect, inkex
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2]))
+import coloreffect, inkex + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + #inkex.debug("hsl: " + str(hsl[0]) + ", " + str(hsl[1]) + ", " + str(hsl[2])) hsl[1] = hsl[1] + 0.05 - if hsl[1] > 1.0:
- hsl[1] = 1.0
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
-c.affect()
+ if hsl[1] > 1.0: + hsl[1] = 1.0 + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() +c.affect() diff --git a/share/extensions/color_negative.py b/share/extensions/color_negative.py index 0fb2fcecb..065586dcf 100644 --- a/share/extensions/color_negative.py +++ b/share/extensions/color_negative.py @@ -1,8 +1,8 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- return '%02x%02x%02x' % (255-r,255-g,255-b)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + return '%02x%02x%02x' % (255-r,255-g,255-b) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_randomize.py b/share/extensions/color_randomize.py index 4591675b5..9bad74893 100644 --- a/share/extensions/color_randomize.py +++ b/share/extensions/color_randomize.py @@ -1,31 +1,31 @@ -import coloreffect,random,inkex
-
-class C(coloreffect.ColorEffect):
- def __init__(self):
- coloreffect.ColorEffect.__init__(self)
- self.OptionParser.add_option("-x", "--hue",
- action="store", type="inkbool",
- dest="hue", default=True,
- help="randomize hue")
- self.OptionParser.add_option("-s", "--saturation",
- action="store", type="inkbool",
- dest="saturation", default=True,
- help="randomize saturation")
- self.OptionParser.add_option("-l", "--lightness",
- action="store", type="inkbool",
- dest="lightness", default=True,
- help="randomize lightness")
-
- def colmod(self,r,g,b):
- hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0)
- if(self.options.hue):
- hsl[0]=random.random()
- if(self.options.saturation):
- hsl[1]=random.random()
- if(self.options.lightness):
- hsl[2]=random.random()
- rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2])
- return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255)
-
-c = C()
+import coloreffect,random,inkex + +class C(coloreffect.ColorEffect): + def __init__(self): + coloreffect.ColorEffect.__init__(self) + self.OptionParser.add_option("-x", "--hue", + action="store", type="inkbool", + dest="hue", default=True, + help="randomize hue") + self.OptionParser.add_option("-s", "--saturation", + action="store", type="inkbool", + dest="saturation", default=True, + help="randomize saturation") + self.OptionParser.add_option("-l", "--lightness", + action="store", type="inkbool", + dest="lightness", default=True, + help="randomize lightness") + + def colmod(self,r,g,b): + hsl = self.rgb_to_hsl(r/255.0, g/255.0, b/255.0) + if(self.options.hue): + hsl[0]=random.random() + if(self.options.saturation): + hsl[1]=random.random() + if(self.options.lightness): + hsl[2]=random.random() + rgb = self.hsl_to_rgb(hsl[0], hsl[1], hsl[2]) + return '%02x%02x%02x' % (rgb[0]*255, rgb[1]*255, rgb[2]*255) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_removeblue.py b/share/extensions/color_removeblue.py index 90d3fe7c2..abba6ba5f 100644 --- a/share/extensions/color_removeblue.py +++ b/share/extensions/color_removeblue.py @@ -1,8 +1,8 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- return '%02x%02x%02x' % (r,g,0)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + return '%02x%02x%02x' % (r,g,0) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_removegreen.py b/share/extensions/color_removegreen.py index 87722df54..09ba4d5d1 100644 --- a/share/extensions/color_removegreen.py +++ b/share/extensions/color_removegreen.py @@ -1,8 +1,8 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- return '%02x%02x%02x' % (r,0,b)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + return '%02x%02x%02x' % (r,0,b) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_removered.py b/share/extensions/color_removered.py index 54d071e3f..5963af426 100644 --- a/share/extensions/color_removered.py +++ b/share/extensions/color_removered.py @@ -1,8 +1,8 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- return '%02x%02x%02x' % (0,g,b)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + return '%02x%02x%02x' % (0,g,b) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/color_replace.py b/share/extensions/color_replace.py index 8db10e0b9..118a67d58 100644 --- a/share/extensions/color_replace.py +++ b/share/extensions/color_replace.py @@ -1,24 +1,24 @@ -import coloreffect
-
-import inkex
-
-class C(coloreffect.ColorEffect):
- def __init__(self):
- coloreffect.ColorEffect.__init__(self)
- self.OptionParser.add_option("-f", "--from_color", action="store", type="string", dest="from_color", default="000000", help="Replace color")
- self.OptionParser.add_option("-t", "--to_color", action="store", type="string", dest="to_color", default="000000", help="By color")
-
- def colmod(self,r,g,b):
- this_color = '%02x%02x%02x' % (r, g, b)
-
- fr = self.options.from_color.strip('"').replace('#', '')
- to = self.options.to_color.strip('"').replace('#', '')
-
- #inkex.debug(this_color+"|"+fr+"|"+to)
- if this_color == fr:
- return to
- else:
- return this_color
-
-c = C()
-c.affect()
+import coloreffect + +import inkex + +class C(coloreffect.ColorEffect): + def __init__(self): + coloreffect.ColorEffect.__init__(self) + self.OptionParser.add_option("-f", "--from_color", action="store", type="string", dest="from_color", default="000000", help="Replace color") + self.OptionParser.add_option("-t", "--to_color", action="store", type="string", dest="to_color", default="000000", help="By color") + + def colmod(self,r,g,b): + this_color = '%02x%02x%02x' % (r, g, b) + + fr = self.options.from_color.strip('"').replace('#', '') + to = self.options.to_color.strip('"').replace('#', '') + + #inkex.debug(this_color+"|"+fr+"|"+to) + if this_color == fr: + return to + else: + return this_color + +c = C() +c.affect() diff --git a/share/extensions/color_rgbbarrel.py b/share/extensions/color_rgbbarrel.py index 41a0a4e1b..3cac39ac5 100644 --- a/share/extensions/color_rgbbarrel.py +++ b/share/extensions/color_rgbbarrel.py @@ -1,8 +1,8 @@ -import coloreffect
-
-class C(coloreffect.ColorEffect):
- def colmod(self,r,g,b):
- return '%02x%02x%02x' % (b,r,g)
-
-c = C()
+import coloreffect + +class C(coloreffect.ColorEffect): + def colmod(self,r,g,b): + return '%02x%02x%02x' % (b,r,g) + +c = C() c.affect()
\ No newline at end of file diff --git a/share/extensions/coloreffect.py b/share/extensions/coloreffect.py index 77f3c8d6c..5c0c93b4b 100644 --- a/share/extensions/coloreffect.py +++ b/share/extensions/coloreffect.py @@ -1,162 +1,162 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jos Hirth, kaioa.com
-Copyright (C) 2007 Aaron C. Spike
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-'''
-import sys, copy, optparse, simplestyle, inkex, copy
-
-import random
-
-color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:')
-color_props_stroke=('stroke:',)
-color_props = color_props_fill + color_props_stroke
-
-
-class ColorEffect(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.visited = []
-
- def effect(self):
- if len(self.selected)==0:
- self.getAttribs(self.document.getroot())
- else:
- for id,node in self.selected.iteritems():
- self.getAttribs(node)
-
- def getAttribs(self,node):
- self.changeStyle(node)
- for child in node:
- self.getAttribs(child)
-
- def changeStyle(self,node):
- if node.attrib.has_key('style'):
- style=node.get('style') # fixme: this will break for presentation attributes!
- if style!='':
- #inkex.debug('old style:'+style)
- styles=style.split(';')
- for i in range(len(styles)):
- for c in range(len(color_props)):
- if styles[i].startswith(color_props[c]):
- styles[i]=color_props[c]+self.process_prop(styles[i][len(color_props[c]):])
- #inkex.debug('new style:'+';'.join(styles))
- node.set('style',';'.join(styles))
-
- def process_prop(self,col):
- #debug('got:'+col)
- if simplestyle.isColor(col):
- c=simplestyle.parseColor(col)
- col='#'+self.colmod(c[0],c[1],c[2])
- #debug('made:'+col)
- if col.startswith('url(#'):
- id = col[len('url(#'):col.find(')')]
- newid = '%s-%d' % (id, int(random.random() * 1000))
- #inkex.debug('ID:' + id )
- path = '//*[@id="%s"]' % id
- for node in self.document.xpath(path, namespaces=inkex.NSS):
- self.process_gradient(node, newid)
- col = 'url(#%s)' % newid
- return col
-
- def process_gradient(self, node, newid):
- #if node.hasAttributes():
- #this_id=node.getAttribute('id')
- #if this_id in self.visited:
- ## prevent multiple processing of the same gradient if it is used by more than one selected object
- ##inkex.debug("already had: " + this_id)
- #return
- #self.visited.append(this_id)
- #inkex.debug("visited: " + str(self.visited))
- newnode = copy.deepcopy(node)
- newnode.set('id', newid)
- node.getparent().append(newnode)
- self.changeStyle(newnode)
- for child in newnode:
- self.changeStyle(child)
- xlink = inkex.addNS('href','xlink')
- if newnode.attrib.has_key(xlink):
- href=newnode.get(xlink)
- if href.startswith('#'):
- id = href[len('#'):len(href)]
- #inkex.debug('ID:' + id )
- newhref = '%s-%d' % (id, int(random.random() * 1000))
- newnode.set(xlink, '#%s' % newhref)
- path = '//*[@id="%s"]' % id
- for node in self.document.xpath(path, namespaces=inkex.NSS):
- self.process_gradient(node, newhref)
-
- def colmod(self,r,g,b):
- pass
-
- def rgb_to_hsl(self,r, g, b):
- rgb_max = max (max (r, g), b)
- rgb_min = min (min (r, g), b)
- delta = rgb_max - rgb_min
- hsl = [0.0, 0.0, 0.0]
- hsl[2] = (rgb_max + rgb_min)/2.0
- if delta == 0:
- hsl[0] = 0.0
- hsl[1] = 0.0
- else:
- if hsl[2] <= 0.5:
- hsl[1] = delta / (rgb_max + rgb_min)
- else:
- hsl[1] = delta / (2 - rgb_max - rgb_min)
- if r == rgb_max:
- hsl[0] = (g - b) / delta
- else:
- if g == rgb_max:
- hsl[0] = 2.0 + (b - r) / delta
- else:
- if b == rgb_max:
- hsl[0] = 4.0 + (r - g) / delta
- hsl[0] = hsl[0] / 6.0
- if hsl[0] < 0:
- hsl[0] = hsl[0] + 1
- if hsl[0] > 1:
- hsl[0] = hsl[0] - 1
- return hsl
-
- def hue_2_rgb (self, v1, v2, h):
- if h < 0:
- h += 6.0
- if h > 6:
- h -= 6.0
- if h < 1:
- return v1 + (v2 - v1) * h
- if h < 3:
- return v2
- if h < 4:
- return v1 + (v2 - v1) * (4 - h)
- return v1
-
- def hsl_to_rgb (self,h, s, l):
- rgb = [0, 0, 0]
- if s == 0:
- rgb[0] = l
- rgb[1] = l
- rgb[2] = l
- else:
- if l < 0.5:
- v2 = l * (1 + s)
- else:
- v2 = l + s - l*s
- v1 = 2*l - v2
- rgb[0] = self.hue_2_rgb (v1, v2, h*6 + 2.0)
- rgb[1] = self.hue_2_rgb (v1, v2, h*6)
- rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0)
- return rgb
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jos Hirth, kaioa.com +Copyright (C) 2007 Aaron C. Spike + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +import sys, copy, optparse, simplestyle, inkex, copy + +import random + +color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:') +color_props_stroke=('stroke:',) +color_props = color_props_fill + color_props_stroke + + +class ColorEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.visited = [] + + def effect(self): + if len(self.selected)==0: + self.getAttribs(self.document.getroot()) + else: + for id,node in self.selected.iteritems(): + self.getAttribs(node) + + def getAttribs(self,node): + self.changeStyle(node) + for child in node: + self.getAttribs(child) + + def changeStyle(self,node): + if node.attrib.has_key('style'): + style=node.get('style') # fixme: this will break for presentation attributes! + if style!='': + #inkex.debug('old style:'+style) + styles=style.split(';') + for i in range(len(styles)): + for c in range(len(color_props)): + if styles[i].startswith(color_props[c]): + styles[i]=color_props[c]+self.process_prop(styles[i][len(color_props[c]):]) + #inkex.debug('new style:'+';'.join(styles)) + node.set('style',';'.join(styles)) + + def process_prop(self,col): + #debug('got:'+col) + if simplestyle.isColor(col): + c=simplestyle.parseColor(col) + col='#'+self.colmod(c[0],c[1],c[2]) + #debug('made:'+col) + if col.startswith('url(#'): + id = col[len('url(#'):col.find(')')] + newid = '%s-%d' % (id, int(random.random() * 1000)) + #inkex.debug('ID:' + id ) + path = '//*[@id="%s"]' % id + for node in self.document.xpath(path, namespaces=inkex.NSS): + self.process_gradient(node, newid) + col = 'url(#%s)' % newid + return col + + def process_gradient(self, node, newid): + #if node.hasAttributes(): + #this_id=node.getAttribute('id') + #if this_id in self.visited: + ## prevent multiple processing of the same gradient if it is used by more than one selected object + ##inkex.debug("already had: " + this_id) + #return + #self.visited.append(this_id) + #inkex.debug("visited: " + str(self.visited)) + newnode = copy.deepcopy(node) + newnode.set('id', newid) + node.getparent().append(newnode) + self.changeStyle(newnode) + for child in newnode: + self.changeStyle(child) + xlink = inkex.addNS('href','xlink') + if newnode.attrib.has_key(xlink): + href=newnode.get(xlink) + if href.startswith('#'): + id = href[len('#'):len(href)] + #inkex.debug('ID:' + id ) + newhref = '%s-%d' % (id, int(random.random() * 1000)) + newnode.set(xlink, '#%s' % newhref) + path = '//*[@id="%s"]' % id + for node in self.document.xpath(path, namespaces=inkex.NSS): + self.process_gradient(node, newhref) + + def colmod(self,r,g,b): + pass + + def rgb_to_hsl(self,r, g, b): + rgb_max = max (max (r, g), b) + rgb_min = min (min (r, g), b) + delta = rgb_max - rgb_min + hsl = [0.0, 0.0, 0.0] + hsl[2] = (rgb_max + rgb_min)/2.0 + if delta == 0: + hsl[0] = 0.0 + hsl[1] = 0.0 + else: + if hsl[2] <= 0.5: + hsl[1] = delta / (rgb_max + rgb_min) + else: + hsl[1] = delta / (2 - rgb_max - rgb_min) + if r == rgb_max: + hsl[0] = (g - b) / delta + else: + if g == rgb_max: + hsl[0] = 2.0 + (b - r) / delta + else: + if b == rgb_max: + hsl[0] = 4.0 + (r - g) / delta + hsl[0] = hsl[0] / 6.0 + if hsl[0] < 0: + hsl[0] = hsl[0] + 1 + if hsl[0] > 1: + hsl[0] = hsl[0] - 1 + return hsl + + def hue_2_rgb (self, v1, v2, h): + if h < 0: + h += 6.0 + if h > 6: + h -= 6.0 + if h < 1: + return v1 + (v2 - v1) * h + if h < 3: + return v2 + if h < 4: + return v1 + (v2 - v1) * (4 - h) + return v1 + + def hsl_to_rgb (self,h, s, l): + rgb = [0, 0, 0] + if s == 0: + rgb[0] = l + rgb[1] = l + rgb[2] = l + else: + if l < 0.5: + v2 = l * (1 + s) + else: + v2 = l + s - l*s + v1 = 2*l - v2 + rgb[0] = self.hue_2_rgb (v1, v2, h*6 + 2.0) + rgb[1] = self.hue_2_rgb (v1, v2, h*6) + rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0) + return rgb diff --git a/share/extensions/dxf_templates.py b/share/extensions/dxf_templates.py index fb266329d..9956fdfed 100644 --- a/share/extensions/dxf_templates.py +++ b/share/extensions/dxf_templates.py @@ -1,645 +1,645 @@ -r14_header = ''' 0
-SECTION
- 2
-HEADER
- 9
-$ACADVER
- 1
-AC1014
- 9
-$HANDSEED
- 5
-FFFF
- 0
-ENDSEC
- 0
-SECTION
- 2
-TABLES
- 0
-TABLE
- 2
-VPORT
- 5
-8
-330
-0
-100
-AcDbSymbolTable
- 70
- 4
- 0
-VPORT
- 5
-2E
-330
-8
-100
-AcDbSymbolTableRecord
-100
-AcDbViewportTableRecord
- 2
-*ACTIVE
- 70
- 0
- 10
-0.0
- 20
-0.0
- 11
-1.0
- 21
-1.0
- 12
-4.25
- 22
-5.5
- 13
-0.0
- 23
-0.0
- 14
-10.0
- 24
-10.0
- 15
-10.0
- 25
-10.0
- 16
-0.0
- 26
-0.0
- 36
-1.0
- 17
-0.0
- 27
-0.0
- 37
-0.0
- 40
-11
- 41
-1.24
- 42
-50.0
- 43
-0.0
- 44
-0.0
- 50
-0.0
- 51
-0.0
- 71
- 0
- 72
- 100
- 73
- 1
- 74
- 3
- 75
- 0
- 76
- 0
- 77
- 0
- 78
- 0
- 0
-ENDTAB
- 0
-TABLE
- 2
-LTYPE
- 5
-5
-330
-0
-100
-AcDbSymbolTable
- 70
- 1
- 0
-LTYPE
- 5
-14
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
- 2
-BYBLOCK
- 70
- 0
- 3
-
- 72
- 65
- 73
- 0
- 40
-0.0
- 0
-LTYPE
- 5
-15
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
- 2
-BYLAYER
- 70
- 0
- 3
-
- 72
- 65
- 73
- 0
- 40
-0.0
- 0
-LTYPE
- 5
-16
-330
-5
-100
-AcDbSymbolTableRecord
-100
-AcDbLinetypeTableRecord
- 2
-CONTINUOUS
- 70
- 0
- 3
-Solid line
- 72
- 65
- 73
- 0
- 40
-0.0
- 0
-ENDTAB
- 0
-TABLE
- 2
-LAYER
- 5
-2
-330
-0
-100
-AcDbSymbolTable
- 70
-1
- 0
-LAYER
- 5
-10
-330
-2
-100
-AcDbSymbolTableRecord
-100
-AcDbLayerTableRecord
- 2
-0
- 70
- 0
- 62
- 7
- 6
-CONTINUOUS
- 0
-ENDTAB
- 0
-TABLE
- 2
-STYLE
- 5
-3
-330
-0
-100
-AcDbSymbolTable
- 70
- 1
- 0
-STYLE
- 5
-11
-330
-3
-100
-AcDbSymbolTableRecord
-100
-AcDbTextStyleTableRecord
- 2
-STANDARD
- 70
- 0
- 40
-0.0
- 41
-1.0
- 50
-0.0
- 71
- 0
- 42
-2.5
- 3
-txt
- 4
-
- 0
-ENDTAB
- 0
-TABLE
- 2
-VIEW
- 5
-6
-330
-0
-100
-AcDbSymbolTable
- 70
- 0
- 0
-ENDTAB
- 0
-TABLE
- 2
-UCS
- 5
-7
-330
-0
-100
-AcDbSymbolTable
- 70
- 0
- 0
-ENDTAB
- 0
-TABLE
- 2
-APPID
- 5
-9
-330
-0
-100
-AcDbSymbolTable
- 70
- 2
- 0
-APPID
- 5
-12
-330
-9
-100
-AcDbSymbolTableRecord
-100
-AcDbRegAppTableRecord
- 2
-ACAD
- 70
- 0
- 0
-ENDTAB
- 0
-TABLE
- 2
-DIMSTYLE
- 5
-A
-330
-0
-100
-AcDbSymbolTable
- 70
- 1
- 0
-DIMSTYLE
-105
-27
-330
-A
-100
-AcDbSymbolTableRecord
-100
-AcDbDimStyleTableRecord
- 2
-ISO-25
- 70
- 0
- 3
-
- 4
-
- 5
-
- 6
-
- 7
-
- 40
-1.0
- 41
-2.5
- 42
-0.625
- 43
-3.75
- 44
-1.25
- 45
-0.0
- 46
-0.0
- 47
-0.0
- 48
-0.0
-140
-2.5
-141
-2.5
-142
-0.0
-143
-0.03937007874016
-144
-1.0
-145
-0.0
-146
-1.0
-147
-0.625
- 71
- 0
- 72
- 0
- 73
- 0
- 74
- 0
- 75
- 0
- 76
- 0
- 77
- 1
- 78
- 8
-170
- 0
-171
- 3
-172
- 1
-173
- 0
-174
- 0
-175
- 0
-176
- 0
-177
- 0
-178
- 0
-270
- 2
-271
- 2
-272
- 2
-273
- 2
-274
- 3
-340
-11
-275
- 0
-280
- 0
-281
- 0
-282
- 0
-283
- 0
-284
- 8
-285
- 0
-286
- 0
-287
- 3
-288
- 0
- 0
-ENDTAB
- 0
-TABLE
- 2
-BLOCK_RECORD
- 5
-1
-330
-0
-100
-AcDbSymbolTable
- 70
- 1
- 0
-BLOCK_RECORD
- 5
-1F
-330
-1
-100
-AcDbSymbolTableRecord
-100
-AcDbBlockTableRecord
- 2
-*MODEL_SPACE
- 0
-BLOCK_RECORD
- 5
-1B
-330
-1
-100
-AcDbSymbolTableRecord
-100
-AcDbBlockTableRecord
- 2
-*PAPER_SPACE
- 0
-ENDTAB
- 0
-ENDSEC
- 0
-SECTION
- 2
-BLOCKS
- 0
-BLOCK
- 5
-20
-330
-1F
-100
-AcDbEntity
- 8
-0
-100
-AcDbBlockBegin
- 2
-*MODEL_SPACE
- 70
- 0
- 10
-0.0
- 20
-0.0
- 30
-0.0
- 3
-*MODEL_SPACE
- 1
-
- 0
-ENDBLK
- 5
-21
-330
-1F
-100
-AcDbEntity
- 8
-0
-100
-AcDbBlockEnd
- 0
-BLOCK
- 5
-1C
-330
-1B
-100
-AcDbEntity
- 67
- 1
- 8
-0
-100
-AcDbBlockBegin
- 2
-*PAPER_SPACE
- 1
-
- 0
-ENDBLK
- 5
-1D
-330
-1B
-100
-AcDbEntity
- 67
- 1
- 8
-0
-100
-AcDbBlockEnd
- 0
-ENDSEC
- 0
-SECTION
- 2
-ENTITIES
-'''
-
-
-r14_footer = ''' 0
-ENDSEC
- 0
-SECTION
- 2
-OBJECTS
- 0
-DICTIONARY
- 5
-C
-330
-0
-100
-AcDbDictionary
- 3
-ACAD_GROUP
-350
-D
- 3
-ACAD_MLINESTYLE
-350
-17
- 0
-DICTIONARY
- 5
-D
-330
-C
-100
-AcDbDictionary
- 0
-DICTIONARY
- 5
-1A
-330
-C
-100
-AcDbDictionary
- 0
-DICTIONARY
- 5
-17
-330
-C
-100
-AcDbDictionary
- 3
-STANDARD
-350
-18
- 0
-DICTIONARY
- 5
-19
-330
-C
-100
-AcDbDictionary
- 0
-ENDSEC
- 0
-EOF'''
+r14_header = ''' 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +4.25 + 22 +5.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +11 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 +1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +''' + + +r14_footer = ''' 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF''' diff --git a/share/extensions/edge3d.py b/share/extensions/edge3d.py index 5a77a1a46..1984e5ff5 100644 --- a/share/extensions/edge3d.py +++ b/share/extensions/edge3d.py @@ -39,7 +39,7 @@ class Edge3d(inkex.Effect): ] for o in opts: self.OptionParser.add_option(o[0], o[1], action="store", type=o[2], - dest=o[3], default=o[4], help=o[5])
+ dest=o[3], default=o[4], help=o[5]) self.filtId = '' def angleBetween(self, start, end, angle): @@ -108,12 +108,12 @@ class Edge3d(inkex.Effect): col = 255 - int(255. * level) a = 'fill:none;stroke:#%02x%02x%02x;stroke-opacity:1;stroke-width:10;%s' % ((col,)*3 + (self.filtId,)) - nn.set('style',a)
+ nn.set('style',a) g.append(nn) def getGroup(self, node): defs = self.document.getroot().xpath('//svg:defs', namespaces=inkex.NSS) - if defs:
+ if defs: defs = defs[0] # make a clipped group, clip with clone of original, clipped group # include original and group of paths @@ -126,7 +126,7 @@ class Edge3d(inkex.Effect): clipG.set('clip-path', 'url(#'+clipId+')') # make a blur filter reference by the style of each path filt = inkex.etree.SubElement(defs,inkex.addNS('filter','svg')) - filtId = self.uniqueId('filter')
+ filtId = self.uniqueId('filter') self.filtId = 'filter:url(#%s);' % filtId for k, v in [('id', filtId), ('height', str(self.options.blurheight)), ('width', str(self.options.blurwidth)), @@ -136,7 +136,7 @@ class Edge3d(inkex.Effect): fe.set('stdDeviation', str(self.options.stddev)) else: # can't find defs, just group paths - g = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg'))
+ g = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg')) g.append(node) return g diff --git a/share/extensions/export_gimp_palette.py b/share/extensions/export_gimp_palette.py index 886ef6c87..3a9d227cf 100644 --- a/share/extensions/export_gimp_palette.py +++ b/share/extensions/export_gimp_palette.py @@ -1,47 +1,47 @@ -#!/usr/bin/env python
-'''
-Author: Jos Hirth, kaioa.com
-License: GNU General Public License - http://www.gnu.org/licenses/gpl.html
-Warranty: see above
-'''
-
-DOCNAME='sodipodi:docname'
-
-import sys, simplestyle
-try:
- from xml.dom.minidom import parse
-except:
- sys.exit('The export_gpl.py module requires PyXML. Please download the latest version from <http://pyxml.sourceforge.net/>.')
-
-colortags=(u'fill',u'stroke',u'stop-color',u'flood-color',u'lighting-color')
-colors={}
-
-def walk(node):
- checkStyle(node)
- if node.hasChildNodes():
- childs=node.childNodes
- for child in childs:
- walk(child)
-
-def checkStyle(node):
- if node.hasAttributes():
- sa=node.getAttribute('style')
- if sa!='':
- styles=simplestyle.parseStyle(sa)
- for c in range(len(colortags)):
- if colortags[c] in styles.keys():
- addColor(styles[colortags[c]])
-
-def addColor(col):
- if simplestyle.isColor(col):
- c=simplestyle.parseColor(col)
- colors['%3i %3i %3i ' % (c[0],c[1],c[2])]=simplestyle.formatColoria(c).upper()
-
-stream = open(sys.argv[-1:][0],'r')
-dom = parse(stream)
-stream.close()
-walk(dom)
-print 'GIMP Palette\nName: %s\n#' % (dom.getElementsByTagName('svg')[0].getAttribute(DOCNAME).split('.')[0])
-
-for k,v in sorted(colors.items()):
+#!/usr/bin/env python +''' +Author: Jos Hirth, kaioa.com +License: GNU General Public License - http://www.gnu.org/licenses/gpl.html +Warranty: see above +''' + +DOCNAME='sodipodi:docname' + +import sys, simplestyle +try: + from xml.dom.minidom import parse +except: + sys.exit('The export_gpl.py module requires PyXML. Please download the latest version from <http://pyxml.sourceforge.net/>.') + +colortags=(u'fill',u'stroke',u'stop-color',u'flood-color',u'lighting-color') +colors={} + +def walk(node): + checkStyle(node) + if node.hasChildNodes(): + childs=node.childNodes + for child in childs: + walk(child) + +def checkStyle(node): + if node.hasAttributes(): + sa=node.getAttribute('style') + if sa!='': + styles=simplestyle.parseStyle(sa) + for c in range(len(colortags)): + if colortags[c] in styles.keys(): + addColor(styles[colortags[c]]) + +def addColor(col): + if simplestyle.isColor(col): + c=simplestyle.parseColor(col) + colors['%3i %3i %3i ' % (c[0],c[1],c[2])]=simplestyle.formatColoria(c).upper() + +stream = open(sys.argv[-1:][0],'r') +dom = parse(stream) +stream.close() +walk(dom) +print 'GIMP Palette\nName: %s\n#' % (dom.getElementsByTagName('svg')[0].getAttribute(DOCNAME).split('.')[0]) + +for k,v in sorted(colors.items()): print k+v
\ No newline at end of file diff --git a/share/extensions/fractalize.py b/share/extensions/fractalize.py index e0611d75c..2ebd96365 100755 --- a/share/extensions/fractalize.py +++ b/share/extensions/fractalize.py @@ -1,94 +1,94 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2005 Carsten Goetze c.goetze@tu-bs.de
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-'''
-import random, math, inkex, simplepath
-
-def calculateSubdivision(x1,y1,x2,y2,smoothness):
- """ Calculate the vector from (x1,y1) to (x2,y2) """
- x3 = x2 - x1
- y3 = y2 - y1
- """ Calculate the point half-way between the two points """
- hx = x1 + x3/2
- hy = y1 + y3/2
- """ Calculate normalized vector perpendicular to the vector (x3,y3) """
- length = math.sqrt(x3*x3 + y3*y3)
- if length != 0:
- nx = -y3/length
- ny = x3/length
- else:
- nx = 1
- ny = 0
- """ Scale perpendicular vector by random factor """
- r = random.uniform(-length/(1+smoothness),length/(1+smoothness))
- nx = nx * r
- ny = ny * r
- """ add scaled perpendicular vector to the half-way point to get the final
- displaced subdivision point """
- x = hx + nx
- y = hy + ny
- return [x, y]
-
-class PathFractalize(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.OptionParser.add_option("-s", "--subdivs",
- action="store", type="int",
- dest="subdivs", default="6",
- help="Number of subdivisons")
- self.OptionParser.add_option("-f", "--smooth",
- action="store", type="float",
- dest="smooth", default="4.0",
- help="Smoothness of the subdivision")
- def effect(self):
- for id, node in self.selected.iteritems():
- if node.tag == inkex.addNS('path','svg'):
- d = node.get('d')
- p = simplepath.parsePath(d)
-
- a = []
- first = 1
- for cmd,params in p:
- if cmd != 'Z':
- if first == 1:
- x1 = params[-2]
- y1 = params[-1]
- a.append(['M',params[-2:]])
- first = 2
- else :
- x2 = params[-2]
- y2 = params[-1]
- self.fractalize(a,x1,y1,x2,y2,self.options.subdivs,self.options.smooth)
- x1 = x2
- y1 = y2
- a.append(['L',params[-2:]])
-
- node.set('d', simplepath.formatPath(a))
-
- def fractalize(self,a,x1,y1,x2,y2,s,f):
- subdivPoint = calculateSubdivision(x1,y1,x2,y2,f)
-
- if s > 0 :
- """ recursively subdivide the segment left of the subdivision point """
- self.fractalize(a,x1,y1,subdivPoint[-2],subdivPoint[-1],s-1,f)
- a.append(['L',subdivPoint])
- """ recursively subdivide the segment right of the subdivision point """
- self.fractalize(a,subdivPoint[-2],subdivPoint[-1],x2,y2,s-1,f)
-
-e = PathFractalize()
-e.affect()
-
+#!/usr/bin/env python +''' +Copyright (C) 2005 Carsten Goetze c.goetze@tu-bs.de + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +import random, math, inkex, simplepath + +def calculateSubdivision(x1,y1,x2,y2,smoothness): + """ Calculate the vector from (x1,y1) to (x2,y2) """ + x3 = x2 - x1 + y3 = y2 - y1 + """ Calculate the point half-way between the two points """ + hx = x1 + x3/2 + hy = y1 + y3/2 + """ Calculate normalized vector perpendicular to the vector (x3,y3) """ + length = math.sqrt(x3*x3 + y3*y3) + if length != 0: + nx = -y3/length + ny = x3/length + else: + nx = 1 + ny = 0 + """ Scale perpendicular vector by random factor """ + r = random.uniform(-length/(1+smoothness),length/(1+smoothness)) + nx = nx * r + ny = ny * r + """ add scaled perpendicular vector to the half-way point to get the final + displaced subdivision point """ + x = hx + nx + y = hy + ny + return [x, y] + +class PathFractalize(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("-s", "--subdivs", + action="store", type="int", + dest="subdivs", default="6", + help="Number of subdivisons") + self.OptionParser.add_option("-f", "--smooth", + action="store", type="float", + dest="smooth", default="4.0", + help="Smoothness of the subdivision") + def effect(self): + for id, node in self.selected.iteritems(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = simplepath.parsePath(d) + + a = [] + first = 1 + for cmd,params in p: + if cmd != 'Z': + if first == 1: + x1 = params[-2] + y1 = params[-1] + a.append(['M',params[-2:]]) + first = 2 + else : + x2 = params[-2] + y2 = params[-1] + self.fractalize(a,x1,y1,x2,y2,self.options.subdivs,self.options.smooth) + x1 = x2 + y1 = y2 + a.append(['L',params[-2:]]) + + node.set('d', simplepath.formatPath(a)) + + def fractalize(self,a,x1,y1,x2,y2,s,f): + subdivPoint = calculateSubdivision(x1,y1,x2,y2,f) + + if s > 0 : + """ recursively subdivide the segment left of the subdivision point """ + self.fractalize(a,x1,y1,subdivPoint[-2],subdivPoint[-1],s-1,f) + a.append(['L',subdivPoint]) + """ recursively subdivide the segment right of the subdivision point """ + self.fractalize(a,subdivPoint[-2],subdivPoint[-1],x2,y2,s-1,f) + +e = PathFractalize() +e.affect() + diff --git a/share/extensions/funcplot.py b/share/extensions/funcplot.py index 3a64e4e95..0b7c77ec9 100644 --- a/share/extensions/funcplot.py +++ b/share/extensions/funcplot.py @@ -1,273 +1,273 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2007 Tavmjong Bah, tavmjong@free.fr
-Copyright (C) 2006 Georg Wiora, xorx@quarkbox.de
-Copyright (C) 2006 Johan Engelen, johan@shouraizou.nl
-Copyright (C) 2005 Aaron Spike, aaron@ekips.org
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Changes:
- * This program is a modified version of wavy.py by Aaron Spike.
- * 22-Dec-2006: Wiora : Added axis and isotropic scaling
- * 21-Jun-2007: Tavmjong: Added polar coordinates
-
-'''
-import inkex, simplepath, simplestyle
-from math import *
-from random import *
-
-def drawfunction(xstart, xend, ybottom, ytop, samples, width, height, left, bottom,
- fx = "sin(x)", fpx = "cos(x)", fponum = True, times2pi = False, polar = False, isoscale = True, drawaxis = True):
-
- if times2pi == True:
- xstart = 2 * pi * xstart
- xend = 2 * pi * xend
-
- # coords and scales based on the source rect
- scalex = width / (xend - xstart)
- xoff = left
- coordx = lambda x: (x - xstart) * scalex + xoff #convert x-value to coordinate
- if polar : # Set scale so that left side of rectangle is -1, right side is +1.
- # (We can't use xscale for both range and scale.)
- centerx = left + width/2.0
- polar_scalex = width/2.0
- coordx = lambda x: x * polar_scalex + centerx #convert x-value to coordinate
-
- scaley = height / (ytop - ybottom)
- yoff = bottom
- coordy = lambda y: (ybottom - y) * scaley + yoff #convert y-value to coordinate
-
- # Check for isotropic scaling and use smaller of the two scales, correct ranges
- if isoscale and not polar:
- if scaley<scalex:
- # compute zero location
- xzero = coordx(0)
- # set scale
- scalex = scaley
- # correct x-offset
- xstart = (left-xzero)/scalex
- xend = (left+width-xzero)/scalex
- else :
- # compute zero location
- yzero = coordy(0)
- # set scale
- scaley = scalex
- # correct x-offset
- ybottom = (yzero-bottom)/scaley
- ytop = (bottom+height-yzero)/scaley
-
- # functions specified by the user
- if fx != "":
- f = eval('lambda x: ' + fx.strip('"'))
- if fpx != "":
- fp = eval('lambda x: ' + fpx.strip('"'))
-
- # step is the distance between nodes on x
- step = (xend - xstart) / (samples-1)
- third = step / 3.0
- ds = step * 0.001 # Step used in calculating derivatives
-
- a = [] # path array
- # add axis
- if drawaxis :
- # check for visibility of x-axis
- if ybottom<=0 and ytop>=0:
- # xaxis
- a.append(['M ',[left, coordy(0)]])
- a.append([' l ',[width, 0]])
- # check for visibility of y-axis
- if xstart<=0 and xend>=0:
- # xaxis
- a.append([' M ',[coordx(0),bottom]])
- a.append([' l ',[0, -height]])
-
- # initialize function and derivative for 0;
- # they are carried over from one iteration to the next, to avoid extra function calculations.
- x0 = xstart
- y0 = f(xstart)
- if polar :
- xp0 = y0 * cos( x0 )
- yp0 = y0 * sin( x0 )
- x0 = xp0
- y0 = yp0
- if fponum or polar: # numerical derivative, using 0.001*step as the small differential
- x1 = xstart + ds # Second point AFTER first point (Good for first point)
- y1 = f(x1)
- if polar :
- xp1 = y1 * cos( x1 )
- yp1 = y1 * sin( x1 )
- x1 = xp1
- y1 = yp1
- dx0 = (x1 - x0)/ds
- dy0 = (y1 - y0)/ds
- else: # derivative given by the user
- dx0 = 0 # Only works for rectangular coordinates
- dy0 = fp(xstart)
-
- # Start curve
- a.append([' M ',[coordx(x0), coordy(y0)]]) # initial moveto
-
- for i in range(int(samples-1)):
- x1 = (i+1) * step + xstart
- x2 = x1 - ds # Second point BEFORE first point (Good for last point)
- y1 = f(x1)
- y2 = f(x2)
- if polar :
- xp1 = y1 * cos( x1 )
- yp1 = y1 * sin( x1 )
- xp2 = y2 * cos( x2 )
- yp2 = y2 * sin( x2 )
- x1 = xp1
- y1 = yp1
- x2 = xp2
- y2 = yp2
- if fponum or polar: # numerical derivative
- dx1 = (x1 - x2)/ds
- dy1 = (y1 - y2)/ds
- else: # derivative given by the user
- dx1 = 0 # Only works for rectangular coordinates
- dy1 = fp(x1)
- # create curve
- a.append([' C ',
- [coordx(x0 + (dx0 * third)), coordy(y0 + (dy0 * third)),
- coordx(x1 - (dx1 * third)), coordy(y1 - (dy1 * third)),
- coordx(x1), coordy(y1)]
- ])
- x0 = x1 # Next segment's start is this segments end
- y0 = y1
- dx0 = dx1 # Assume the function is smooth everywhere, so carry over the derivative too
- dy0 = dy1
- return a
-
-class FuncPlot(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.OptionParser.add_option("--xstart",
- action="store", type="float",
- dest="xstart", default=0.0,
- help="Start x-value")
- self.OptionParser.add_option("--xend",
- action="store", type="float",
- dest="xend", default=1.0,
- help="End x-value")
- self.OptionParser.add_option("--times2pi",
- action="store", type="inkbool",
- dest="times2pi", default=True,
- help="Multiply x-range by 2*pi")
- self.OptionParser.add_option("--polar",
- action="store", type="inkbool",
- dest="polar", default=False,
- help="Plot using polar coordinates")
- self.OptionParser.add_option("--ybottom",
- action="store", type="float",
- dest="ybottom", default=-1.0,
- help="y-value of rectangle's bottom")
- self.OptionParser.add_option("--ytop",
- action="store", type="float",
- dest="ytop", default=1.0,
- help="y-value of rectangle's top")
- self.OptionParser.add_option("-s", "--samples",
- action="store", type="int",
- dest="samples", default=8,
- help="Samples")
- self.OptionParser.add_option("--fofx",
- action="store", type="string",
- dest="fofx", default="sin(x)",
- help="f(x) for plotting")
- self.OptionParser.add_option("--fponum",
- action="store", type="inkbool",
- dest="fponum", default=True,
- help="Calculate the first derivative numerically")
- self.OptionParser.add_option("--fpofx",
- action="store", type="string",
- dest="fpofx", default="cos(x)",
- help="f'(x) for plotting")
- self.OptionParser.add_option("--remove",
- action="store", type="inkbool",
- dest="remove", default=True,
- help="If True, source rectangle is removed")
- self.OptionParser.add_option("--isoscale",
- action="store", type="inkbool",
- dest="isoscale", default=True,
- help="If True, isotropic scaling is used")
- self.OptionParser.add_option("--drawaxis",
- action="store", type="inkbool",
- dest="drawaxis", default=True,
- help="If True, axis are drawn")
- self.OptionParser.add_option("--tab",
- action="store", type="string",
- dest="tab", default="sampling",
- help="The selected UI-tab when OK was pressed")
- self.OptionParser.add_option("--funcplotuse",
- action="store", type="string",
- dest="funcplotuse", default="",
- help="dummy")
- self.OptionParser.add_option("--pythonfunctions",
- action="store", type="string",
- dest="pythonfunctions", default="",
- help="dummy")
-
- def effect(self):
- for id, node in self.selected.iteritems():
- if node.tag == inkex.addNS('rect','svg'):
- # create new path with basic dimensions of selected rectangle
- newpath = inkex.etree.Element(inkex.addNS('path','svg'))
- x = float(node.get('x'))
- y = float(node.get('y'))
- w = float(node.get('width'))
- h = float(node.get('height'))
-
- #copy attributes of rect
- s = node.get('style')
- if s:
- newpath.set('style', s)
-
- t = node.get('transform')
- if t:
- newpath.set('transform', t)
-
- # top and bottom were exchanged
- newpath.set('d', simplepath.formatPath(
- drawfunction(self.options.xstart,
- self.options.xend,
- self.options.ybottom,
- self.options.ytop,
- self.options.samples,
- w,h,x,y+h,
- self.options.fofx,
- self.options.fpofx,
- self.options.fponum,
- self.options.times2pi,
- self.options.polar,
- self.options.isoscale,
- self.options.drawaxis)))
- newpath.set('title', self.options.fofx)
-
- #newpath.setAttribute('desc', '!func;' + self.options.fofx + ';'
- # + self.options.fpofx + ';'
- # + `self.options.fponum` + ';'
- # + `self.options.xstart` + ';'
- # + `self.options.xend` + ';'
- # + `self.options.samples`)
-
- # add path into SVG structure
- node.getparent().append(newpath)
- # option wether to remove the rectangle or not.
- if self.options.remove:
- node.getparent().remove(node)
-
-e = FuncPlot()
-e.affect()
+#!/usr/bin/env python +''' +Copyright (C) 2007 Tavmjong Bah, tavmjong@free.fr +Copyright (C) 2006 Georg Wiora, xorx@quarkbox.de +Copyright (C) 2006 Johan Engelen, johan@shouraizou.nl +Copyright (C) 2005 Aaron Spike, aaron@ekips.org + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Changes: + * This program is a modified version of wavy.py by Aaron Spike. + * 22-Dec-2006: Wiora : Added axis and isotropic scaling + * 21-Jun-2007: Tavmjong: Added polar coordinates + +''' +import inkex, simplepath, simplestyle +from math import * +from random import * + +def drawfunction(xstart, xend, ybottom, ytop, samples, width, height, left, bottom, + fx = "sin(x)", fpx = "cos(x)", fponum = True, times2pi = False, polar = False, isoscale = True, drawaxis = True): + + if times2pi == True: + xstart = 2 * pi * xstart + xend = 2 * pi * xend + + # coords and scales based on the source rect + scalex = width / (xend - xstart) + xoff = left + coordx = lambda x: (x - xstart) * scalex + xoff #convert x-value to coordinate + if polar : # Set scale so that left side of rectangle is -1, right side is +1. + # (We can't use xscale for both range and scale.) + centerx = left + width/2.0 + polar_scalex = width/2.0 + coordx = lambda x: x * polar_scalex + centerx #convert x-value to coordinate + + scaley = height / (ytop - ybottom) + yoff = bottom + coordy = lambda y: (ybottom - y) * scaley + yoff #convert y-value to coordinate + + # Check for isotropic scaling and use smaller of the two scales, correct ranges + if isoscale and not polar: + if scaley<scalex: + # compute zero location + xzero = coordx(0) + # set scale + scalex = scaley + # correct x-offset + xstart = (left-xzero)/scalex + xend = (left+width-xzero)/scalex + else : + # compute zero location + yzero = coordy(0) + # set scale + scaley = scalex + # correct x-offset + ybottom = (yzero-bottom)/scaley + ytop = (bottom+height-yzero)/scaley + + # functions specified by the user + if fx != "": + f = eval('lambda x: ' + fx.strip('"')) + if fpx != "": + fp = eval('lambda x: ' + fpx.strip('"')) + + # step is the distance between nodes on x + step = (xend - xstart) / (samples-1) + third = step / 3.0 + ds = step * 0.001 # Step used in calculating derivatives + + a = [] # path array + # add axis + if drawaxis : + # check for visibility of x-axis + if ybottom<=0 and ytop>=0: + # xaxis + a.append(['M ',[left, coordy(0)]]) + a.append([' l ',[width, 0]]) + # check for visibility of y-axis + if xstart<=0 and xend>=0: + # xaxis + a.append([' M ',[coordx(0),bottom]]) + a.append([' l ',[0, -height]]) + + # initialize function and derivative for 0; + # they are carried over from one iteration to the next, to avoid extra function calculations. + x0 = xstart + y0 = f(xstart) + if polar : + xp0 = y0 * cos( x0 ) + yp0 = y0 * sin( x0 ) + x0 = xp0 + y0 = yp0 + if fponum or polar: # numerical derivative, using 0.001*step as the small differential + x1 = xstart + ds # Second point AFTER first point (Good for first point) + y1 = f(x1) + if polar : + xp1 = y1 * cos( x1 ) + yp1 = y1 * sin( x1 ) + x1 = xp1 + y1 = yp1 + dx0 = (x1 - x0)/ds + dy0 = (y1 - y0)/ds + else: # derivative given by the user + dx0 = 0 # Only works for rectangular coordinates + dy0 = fp(xstart) + + # Start curve + a.append([' M ',[coordx(x0), coordy(y0)]]) # initial moveto + + for i in range(int(samples-1)): + x1 = (i+1) * step + xstart + x2 = x1 - ds # Second point BEFORE first point (Good for last point) + y1 = f(x1) + y2 = f(x2) + if polar : + xp1 = y1 * cos( x1 ) + yp1 = y1 * sin( x1 ) + xp2 = y2 * cos( x2 ) + yp2 = y2 * sin( x2 ) + x1 = xp1 + y1 = yp1 + x2 = xp2 + y2 = yp2 + if fponum or polar: # numerical derivative + dx1 = (x1 - x2)/ds + dy1 = (y1 - y2)/ds + else: # derivative given by the user + dx1 = 0 # Only works for rectangular coordinates + dy1 = fp(x1) + # create curve + a.append([' C ', + [coordx(x0 + (dx0 * third)), coordy(y0 + (dy0 * third)), + coordx(x1 - (dx1 * third)), coordy(y1 - (dy1 * third)), + coordx(x1), coordy(y1)] + ]) + x0 = x1 # Next segment's start is this segments end + y0 = y1 + dx0 = dx1 # Assume the function is smooth everywhere, so carry over the derivative too + dy0 = dy1 + return a + +class FuncPlot(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("--xstart", + action="store", type="float", + dest="xstart", default=0.0, + help="Start x-value") + self.OptionParser.add_option("--xend", + action="store", type="float", + dest="xend", default=1.0, + help="End x-value") + self.OptionParser.add_option("--times2pi", + action="store", type="inkbool", + dest="times2pi", default=True, + help="Multiply x-range by 2*pi") + self.OptionParser.add_option("--polar", + action="store", type="inkbool", + dest="polar", default=False, + help="Plot using polar coordinates") + self.OptionParser.add_option("--ybottom", + action="store", type="float", + dest="ybottom", default=-1.0, + help="y-value of rectangle's bottom") + self.OptionParser.add_option("--ytop", + action="store", type="float", + dest="ytop", default=1.0, + help="y-value of rectangle's top") + self.OptionParser.add_option("-s", "--samples", + action="store", type="int", + dest="samples", default=8, + help="Samples") + self.OptionParser.add_option("--fofx", + action="store", type="string", + dest="fofx", default="sin(x)", + help="f(x) for plotting") + self.OptionParser.add_option("--fponum", + action="store", type="inkbool", + dest="fponum", default=True, + help="Calculate the first derivative numerically") + self.OptionParser.add_option("--fpofx", + action="store", type="string", + dest="fpofx", default="cos(x)", + help="f'(x) for plotting") + self.OptionParser.add_option("--remove", + action="store", type="inkbool", + dest="remove", default=True, + help="If True, source rectangle is removed") + self.OptionParser.add_option("--isoscale", + action="store", type="inkbool", + dest="isoscale", default=True, + help="If True, isotropic scaling is used") + self.OptionParser.add_option("--drawaxis", + action="store", type="inkbool", + dest="drawaxis", default=True, + help="If True, axis are drawn") + self.OptionParser.add_option("--tab", + action="store", type="string", + dest="tab", default="sampling", + help="The selected UI-tab when OK was pressed") + self.OptionParser.add_option("--funcplotuse", + action="store", type="string", + dest="funcplotuse", default="", + help="dummy") + self.OptionParser.add_option("--pythonfunctions", + action="store", type="string", + dest="pythonfunctions", default="", + help="dummy") + + def effect(self): + for id, node in self.selected.iteritems(): + if node.tag == inkex.addNS('rect','svg'): + # create new path with basic dimensions of selected rectangle + newpath = inkex.etree.Element(inkex.addNS('path','svg')) + x = float(node.get('x')) + y = float(node.get('y')) + w = float(node.get('width')) + h = float(node.get('height')) + + #copy attributes of rect + s = node.get('style') + if s: + newpath.set('style', s) + + t = node.get('transform') + if t: + newpath.set('transform', t) + + # top and bottom were exchanged + newpath.set('d', simplepath.formatPath( + drawfunction(self.options.xstart, + self.options.xend, + self.options.ybottom, + self.options.ytop, + self.options.samples, + w,h,x,y+h, + self.options.fofx, + self.options.fpofx, + self.options.fponum, + self.options.times2pi, + self.options.polar, + self.options.isoscale, + self.options.drawaxis))) + newpath.set('title', self.options.fofx) + + #newpath.setAttribute('desc', '!func;' + self.options.fofx + ';' + # + self.options.fpofx + ';' + # + `self.options.fponum` + ';' + # + `self.options.xstart` + ';' + # + `self.options.xend` + ';' + # + `self.options.samples`) + + # add path into SVG structure + node.getparent().append(newpath) + # option wether to remove the rectangle or not. + if self.options.remove: + node.getparent().remove(node) + +e = FuncPlot() +e.affect() diff --git a/share/extensions/gears.py b/share/extensions/gears.py index c60f63b83..17fea40f8 100644 --- a/share/extensions/gears.py +++ b/share/extensions/gears.py @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -'''
+''' import inkex import simplestyle, sys @@ -147,16 +147,16 @@ class Gears(inkex.Effect): path = points_to_svgd( points ) # Embed gear in group to make animation easier: - # Translate group, Rotate path.
- t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')'
- g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ),
+ # Translate group, Rotate path. + t = 'translate(' + str( self.view_center[0] ) + ',' + str( self.view_center[1] ) + ')' + g_attribs = {inkex.addNS('label','inkscape'):'Gear' + str( teeth ), 'transform':t } g = inkex.etree.SubElement(self.current_layer, 'g', g_attribs) - # Create SVG Path for gear
- style = { 'stroke': '#000000', 'fill': 'none' }
+ # Create SVG Path for gear + style = { 'stroke': '#000000', 'fill': 'none' } gear_attribs = {'style':simplestyle.formatStyle(style), 'd':path} - gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs )
+ gear = inkex.etree.SubElement(g, inkex.addNS('path','svg'), gear_attribs ) e = Gears() e.affect() diff --git a/share/extensions/lorem_ipsum.py b/share/extensions/lorem_ipsum.py index 115ac4ace..938d63e0b 100644 --- a/share/extensions/lorem_ipsum.py +++ b/share/extensions/lorem_ipsum.py @@ -1,232 +1,232 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jos Hirth, kaioa.com
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-'''
-'''
-Example filltext sentences generated over at http://lipsum.com/
-'''
-
-import inkex
-import random
-
-foo=[
-'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ',
-'Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. ',
-'Phasellus at purus sed purus cursus iaculis. ',
-'Suspendisse fermentum. ',
-'Pellentesque et arcu. ',
-'Maecenas viverra. ',
-'In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. ',
-'Sed non ipsum. ',
-'Nullam venenatis gravida orci. ',
-'Curabitur nunc ante, ullamcorper vel, auctor a, aliquam at, tortor. ',
-'Etiam sodales orci nec ligula. ',
-'Sed at turpis vitae velit euismod aliquet. ',
-'Fusce venenatis ligula in pede. ',
-'Pellentesque viverra dolor non nunc. ',
-'Donec interdum vestibulum libero. ',
-'Morbi volutpat. ',
-'Phasellus hendrerit. ',
-'Quisque dictum quam vel neque. ',
-'Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. ',
-'Nam pharetra. ',
-'Nam rhoncus, lectus vel hendrerit congue, nisl lorem feugiat ante, in fermentum erat nulla tristique arcu. ',
-'Mauris et dolor. ',
-'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta est, eget sollicitudin lectus lectus eget lacus. ',
-'Praesent a lacus vitae turpis consequat semper. ',
-'In commodo, dolor quis fermentum ullamcorper, urna massa volutpat massa, vitae mattis purus arcu nec nulla. ',
-'In hac habitasse platea dictumst. ',
-'Praesent scelerisque. ',
-'Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. ',
-'Vestibulum non arcu a ante feugiat vestibulum. ',
-'Nam laoreet dui sed magna. ',
-'Proin diam augue, semper vitae, varius et, viverra id, felis. ',
-'Pellentesque sit amet dui vel justo gravida auctor. ',
-'Aenean scelerisque metus eget sem. ',
-'Maecenas rhoncus rhoncus ipsum. ',
-'Donec nonummy lacinia leo. ',
-'Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. ',
-'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. ',
-'Mauris tempus diam. ',
-'Maecenas justo. ',
-'Sed a lorem ut est tincidunt consectetuer. ',
-'Ut eu metus id lectus vestibulum ultrices. ',
-'Suspendisse lectus. ',
-'Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. ',
-'Suspendisse potenti. ',
-'Integer fringilla. ',
-'Morbi urna. ',
-'Morbi pulvinar nulla sit amet nisl. ',
-'Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. ',
-'Morbi a mauris. ',
-'Pellentesque suscipit accumsan massa. ',
-'Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. ',
-'Quisque facilisis, urna sit amet pulvinar mollis, purus arcu adipiscing velit, non condimentum diam purus eu massa. ',
-'Suspendisse potenti. ',
-'Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. ',
-'Aliquam metus. ',
-'Nam a nunc. ',
-'Vivamus feugiat. ',
-'Nunc metus. ',
-'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. ',
-'Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales sapien, sit amet posuere quam purus at lacus. ',
-'Curabitur tincidunt tellus nec purus. ',
-'Nam consectetuer mollis dolor. ',
-'Sed quis elit. ',
-'Aenean luctus vulputate turpis. ',
-'Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. ',
-'Nulla facilisi. ',
-'Aliquam vel nibh. ',
-'Vivamus nisi elit, nonummy id, facilisis non, blandit ac, dolor. ',
-'Etiam cursus purus interdum libero. ',
-'Nam id neque. ',
-'Etiam pede nunc, vestibulum vel, rutrum et, tincidunt eu, enim. ',
-'Aenean id purus. ',
-'Aenean ultrices turpis. ',
-'Mauris et pede. ',
-'Suspendisse potenti. ',
-'Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. ',
-'Maecenas convallis dui. ',
-'In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. ',
-'Mauris ac massa vestibulum nisl facilisis viverra. ',
-'Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. ',
-'Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. ',
-'Praesent semper, neque vel condimentum hendrerit, lectus elit pretium ligula, nec consequat nisl velit at dui. ',
-'Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. ',
-'Aenean ligula. ',
-'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. ',
-'Etiam pharetra lacus sed velit imperdiet bibendum. ',
-'Nunc in turpis ac lacus eleifend sagittis. ',
-'Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. ',
-'In tempus urna. ',
-'Quisque vehicula porttitor odio. ',
-'Aliquam sed erat. ',
-'Vestibulum viverra varius enim. ',
-'Donec ut purus. ',
-'Pellentesque convallis dolor vel libero. ',
-'Integer tempus malesuada pede. ',
-'Integer porta. ',
-'Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. ',
-'Nulla blandit justo a metus. ',
-'Curabitur accumsan felis in erat. ',
-'Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. ',
-'Nulla sagittis condimentum ligula. ',
-'Aliquam imperdiet lobortis metus. ',
-'Suspendisse molestie sem. ',
-'Ut venenatis. ',
-'Pellentesque condimentum felis a sem. ',
-'Fusce nonummy commodo dui. ',
-'Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. ',
-'Etiam fermentum. ',
-'Phasellus auctor enim eget sem. ',
-'Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. ',
-'Sed fringilla. ',
-'Nam malesuada sapien eu nibh. ',
-'Pellentesque ac turpis. ',
-'Nulla sed lacus. ',
-'Mauris sed nulla quis nisi interdum tempor. ',
-'Quisque pretium rutrum ligula. ',
-'Mauris tempor ultrices justo. ',
-'In hac habitasse platea dictumst. ',
-'Donec sit amet enim. ',
-'Suspendisse venenatis. ',
-'Nam nisl quam, posuere non, volutpat sed, semper vitae, magna. ',
-'Donec ut urna. ',
-'Integer risus velit, facilisis eget, viverra et, venenatis id, leo. ',
-'Cras facilisis felis sit amet lorem. ',
-'Nam molestie nisl at metus. ',
-'Suspendisse viverra placerat tortor. ',
-'Phasellus lacinia iaculis mi. ',
-'Sed dolor. ',
-'Quisque malesuada nulla sed pede volutpat pulvinar. ',
-'Cras gravida. ',
-'Mauris tincidunt aliquam ante. ',
-'Fusce consectetuer tellus ut nisl. ',
-'Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. ',
-'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. ',
-'Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac pretium nisl lectus at magna. ',
-'Vivamus quis mi. ',
-'Nam sed nisl nec elit suscipit ullamcorper. ',
-'Donec tempus quam quis neque. ',
-'Donec rutrum venenatis dui. ',
-'Praesent a eros. ',
-'Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. ',
-'Etiam non neque ac mi vestibulum placerat. ',
-'Donec at diam a tellus dignissim vestibulum. ',
-'Integer accumsan. ',
-'Cras ac enim vel dui vestibulum suscipit. ',
-'Pellentesque tempor. ',
-'Praesent lacus. '
-]
-
-class MyEffect(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.OptionParser.add_option("--title")
- self.OptionParser.add_option("-n", "--numberofparagraphs",
- action="store", type="int",
- dest="num", default=5,
- help="Number of paragraphs to generate")
- self.OptionParser.add_option("-c", "--sentencecount",
- action="store", type="int",
- dest="sentencecount", default=16,
- help="Number of Sentences")
- self.OptionParser.add_option("-f", "--fluctuation",
- action="store", type="int",
- dest="fluctuation", default=4,
- help="+/-")
- self.first_sentence = 1
-
- def makePara(self):
- _min=max(1,self.options.sentencecount-self.options.fluctuation)
- _max=max(2,self.options.sentencecount+self.options.fluctuation)
- scount=random.randint(_min,_max)
- text=''
- for i in range(scount):
- if self.first_sentence == 1:
- text+=foo[0]
- self.first_sentence = 0
- else:
- text+=foo[random.randint(0,len(foo)-1)]
- return text
-
- def addText(self, node):
- for i in range(self.options.num):
- para=inkex.etree.SubElement(node,inkex.addNS('flowPara','svg'))
- para.text = self.makePara()
- inkex.etree.SubElement(node,inkex.addNS('flowPara','svg'))
-
- def effect(self):
- found=0
- for id, node in self.selected.iteritems():
- if node.tag == inkex.addNS('flowRoot','svg'):
- found+=1
- if found==1:
- self.addText(node)
- if found==0:
- #inkex.debug('No "flowRoot" elements selected. Unable to add text.')
- svg=self.document.getroot()
- gattribs = {inkex.addNS('label','inkscape'):'lorem ipsum',inkex.addNS('groupmode','inkscape'):'layer'}
- g=inkex.etree.SubElement(svg,inkex.addNS('g','svg'),gattribs)
- flowRoot=inkex.etree.SubElement(g,inkex.addNS('flowRoot','svg'),{inkex.addNS('space','xml'):'preserve'})
- flowRegion=inkex.etree.SubElement(flowRoot,inkex.addNS('flowRegion','svg'))
- rattribs = {'x':'0','y':'0','width':svg.get('width'),'height':svg.get('height')}
- rect=inkex.etree.SubElement(flowRegion,inkex.addNS('rect','svg'),rattribs)
- self.addText(flowRoot)
-
-e = MyEffect()
-e.affect()
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jos Hirth, kaioa.com + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +''' +Example filltext sentences generated over at http://lipsum.com/ +''' + +import inkex +import random + +foo=[ +'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ', +'Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. ', +'Phasellus at purus sed purus cursus iaculis. ', +'Suspendisse fermentum. ', +'Pellentesque et arcu. ', +'Maecenas viverra. ', +'In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. ', +'Sed non ipsum. ', +'Nullam venenatis gravida orci. ', +'Curabitur nunc ante, ullamcorper vel, auctor a, aliquam at, tortor. ', +'Etiam sodales orci nec ligula. ', +'Sed at turpis vitae velit euismod aliquet. ', +'Fusce venenatis ligula in pede. ', +'Pellentesque viverra dolor non nunc. ', +'Donec interdum vestibulum libero. ', +'Morbi volutpat. ', +'Phasellus hendrerit. ', +'Quisque dictum quam vel neque. ', +'Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. ', +'Nam pharetra. ', +'Nam rhoncus, lectus vel hendrerit congue, nisl lorem feugiat ante, in fermentum erat nulla tristique arcu. ', +'Mauris et dolor. ', +'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta est, eget sollicitudin lectus lectus eget lacus. ', +'Praesent a lacus vitae turpis consequat semper. ', +'In commodo, dolor quis fermentum ullamcorper, urna massa volutpat massa, vitae mattis purus arcu nec nulla. ', +'In hac habitasse platea dictumst. ', +'Praesent scelerisque. ', +'Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. ', +'Vestibulum non arcu a ante feugiat vestibulum. ', +'Nam laoreet dui sed magna. ', +'Proin diam augue, semper vitae, varius et, viverra id, felis. ', +'Pellentesque sit amet dui vel justo gravida auctor. ', +'Aenean scelerisque metus eget sem. ', +'Maecenas rhoncus rhoncus ipsum. ', +'Donec nonummy lacinia leo. ', +'Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. ', +'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. ', +'Mauris tempus diam. ', +'Maecenas justo. ', +'Sed a lorem ut est tincidunt consectetuer. ', +'Ut eu metus id lectus vestibulum ultrices. ', +'Suspendisse lectus. ', +'Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. ', +'Suspendisse potenti. ', +'Integer fringilla. ', +'Morbi urna. ', +'Morbi pulvinar nulla sit amet nisl. ', +'Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. ', +'Morbi a mauris. ', +'Pellentesque suscipit accumsan massa. ', +'Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. ', +'Quisque facilisis, urna sit amet pulvinar mollis, purus arcu adipiscing velit, non condimentum diam purus eu massa. ', +'Suspendisse potenti. ', +'Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. ', +'Aliquam metus. ', +'Nam a nunc. ', +'Vivamus feugiat. ', +'Nunc metus. ', +'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. ', +'Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales sapien, sit amet posuere quam purus at lacus. ', +'Curabitur tincidunt tellus nec purus. ', +'Nam consectetuer mollis dolor. ', +'Sed quis elit. ', +'Aenean luctus vulputate turpis. ', +'Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. ', +'Nulla facilisi. ', +'Aliquam vel nibh. ', +'Vivamus nisi elit, nonummy id, facilisis non, blandit ac, dolor. ', +'Etiam cursus purus interdum libero. ', +'Nam id neque. ', +'Etiam pede nunc, vestibulum vel, rutrum et, tincidunt eu, enim. ', +'Aenean id purus. ', +'Aenean ultrices turpis. ', +'Mauris et pede. ', +'Suspendisse potenti. ', +'Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. ', +'Maecenas convallis dui. ', +'In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. ', +'Mauris ac massa vestibulum nisl facilisis viverra. ', +'Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. ', +'Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. ', +'Praesent semper, neque vel condimentum hendrerit, lectus elit pretium ligula, nec consequat nisl velit at dui. ', +'Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. ', +'Aenean ligula. ', +'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. ', +'Etiam pharetra lacus sed velit imperdiet bibendum. ', +'Nunc in turpis ac lacus eleifend sagittis. ', +'Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. ', +'In tempus urna. ', +'Quisque vehicula porttitor odio. ', +'Aliquam sed erat. ', +'Vestibulum viverra varius enim. ', +'Donec ut purus. ', +'Pellentesque convallis dolor vel libero. ', +'Integer tempus malesuada pede. ', +'Integer porta. ', +'Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. ', +'Nulla blandit justo a metus. ', +'Curabitur accumsan felis in erat. ', +'Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. ', +'Nulla sagittis condimentum ligula. ', +'Aliquam imperdiet lobortis metus. ', +'Suspendisse molestie sem. ', +'Ut venenatis. ', +'Pellentesque condimentum felis a sem. ', +'Fusce nonummy commodo dui. ', +'Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. ', +'Etiam fermentum. ', +'Phasellus auctor enim eget sem. ', +'Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. ', +'Sed fringilla. ', +'Nam malesuada sapien eu nibh. ', +'Pellentesque ac turpis. ', +'Nulla sed lacus. ', +'Mauris sed nulla quis nisi interdum tempor. ', +'Quisque pretium rutrum ligula. ', +'Mauris tempor ultrices justo. ', +'In hac habitasse platea dictumst. ', +'Donec sit amet enim. ', +'Suspendisse venenatis. ', +'Nam nisl quam, posuere non, volutpat sed, semper vitae, magna. ', +'Donec ut urna. ', +'Integer risus velit, facilisis eget, viverra et, venenatis id, leo. ', +'Cras facilisis felis sit amet lorem. ', +'Nam molestie nisl at metus. ', +'Suspendisse viverra placerat tortor. ', +'Phasellus lacinia iaculis mi. ', +'Sed dolor. ', +'Quisque malesuada nulla sed pede volutpat pulvinar. ', +'Cras gravida. ', +'Mauris tincidunt aliquam ante. ', +'Fusce consectetuer tellus ut nisl. ', +'Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. ', +'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. ', +'Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac pretium nisl lectus at magna. ', +'Vivamus quis mi. ', +'Nam sed nisl nec elit suscipit ullamcorper. ', +'Donec tempus quam quis neque. ', +'Donec rutrum venenatis dui. ', +'Praesent a eros. ', +'Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. ', +'Etiam non neque ac mi vestibulum placerat. ', +'Donec at diam a tellus dignissim vestibulum. ', +'Integer accumsan. ', +'Cras ac enim vel dui vestibulum suscipit. ', +'Pellentesque tempor. ', +'Praesent lacus. ' +] + +class MyEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("--title") + self.OptionParser.add_option("-n", "--numberofparagraphs", + action="store", type="int", + dest="num", default=5, + help="Number of paragraphs to generate") + self.OptionParser.add_option("-c", "--sentencecount", + action="store", type="int", + dest="sentencecount", default=16, + help="Number of Sentences") + self.OptionParser.add_option("-f", "--fluctuation", + action="store", type="int", + dest="fluctuation", default=4, + help="+/-") + self.first_sentence = 1 + + def makePara(self): + _min=max(1,self.options.sentencecount-self.options.fluctuation) + _max=max(2,self.options.sentencecount+self.options.fluctuation) + scount=random.randint(_min,_max) + text='' + for i in range(scount): + if self.first_sentence == 1: + text+=foo[0] + self.first_sentence = 0 + else: + text+=foo[random.randint(0,len(foo)-1)] + return text + + def addText(self, node): + for i in range(self.options.num): + para=inkex.etree.SubElement(node,inkex.addNS('flowPara','svg')) + para.text = self.makePara() + inkex.etree.SubElement(node,inkex.addNS('flowPara','svg')) + + def effect(self): + found=0 + for id, node in self.selected.iteritems(): + if node.tag == inkex.addNS('flowRoot','svg'): + found+=1 + if found==1: + self.addText(node) + if found==0: + #inkex.debug('No "flowRoot" elements selected. Unable to add text.') + svg=self.document.getroot() + gattribs = {inkex.addNS('label','inkscape'):'lorem ipsum',inkex.addNS('groupmode','inkscape'):'layer'} + g=inkex.etree.SubElement(svg,inkex.addNS('g','svg'),gattribs) + flowRoot=inkex.etree.SubElement(g,inkex.addNS('flowRoot','svg'),{inkex.addNS('space','xml'):'preserve'}) + flowRegion=inkex.etree.SubElement(flowRoot,inkex.addNS('flowRegion','svg')) + rattribs = {'x':'0','y':'0','width':svg.get('width'),'height':svg.get('height')} + rect=inkex.etree.SubElement(flowRegion,inkex.addNS('rect','svg'),rattribs) + self.addText(flowRoot) + +e = MyEffect() +e.affect() diff --git a/share/extensions/markers_strokepaint.py b/share/extensions/markers_strokepaint.py index 5442cfa48..350c87f28 100644 --- a/share/extensions/markers_strokepaint.py +++ b/share/extensions/markers_strokepaint.py @@ -1,75 +1,75 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Aaron Spike, aaron@ekips.org
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-'''
-import random, inkex, simplestyle, copy
-
-class MyEffect(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
- self.OptionParser.add_option("-m", "--modify",
- action="store", type="inkbool",
- dest="modify", default=False,
- help="do not create a copy, modify the markers")
-
- def effect(self):
- defs = self.xpathSingle('/svg:svg//svg:defs')
- if not defs:
- defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg'))
-
- for id, node in self.selected.iteritems():
- mprops = ['marker','marker-start','marker-mid','marker-end']
- try:
- style = simplestyle.parseStyle(node.get('style'))
- except:
- inkex.debug("No style attribute found for id: %s" % id)
- continue
-
- stroke = style.get('stroke', '#000000')
-
- for mprop in mprops:
- if style.has_key(mprop) and style[mprop] != 'none'and style[mprop][:5] == 'url(#':
- marker_id = style[mprop][5:-1]
- try:
- old_mnode = self.xpathSingle('/svg:svg//svg:marker[@id="%s"]' % marker_id)
- if not self.options.modify:
- mnode = copy.deepcopy(old_mnode)
- else:
- mnode = old_mnode
- except:
- inkex.debug("unable to locate marker: %s" % marker_id)
- continue
-
- new_id = self.uniqueId(marker_id, not self.options.modify)
-
- style[mprop] = "url(#%s)" % new_id
- mnode.set('id', new_id)
- mnode.set(inkex.addNS('stockid','inkscape'), new_id)
- defs.append(mnode)
-
- children = mnode.xpath('.//*[@style]', namespaces=inkex.NSS)
- for child in children:
- cstyle = simplestyle.parseStyle(child.get('style'))
- if ('stroke' in cstyle and cstyle['stroke'] != 'none') or 'stroke' not in cstyle:
- cstyle['stroke'] = stroke
- if ('fill' in cstyle and cstyle['fill'] != 'none') or 'fill' not in cstyle:
- cstyle['fill'] = stroke
- child.set('style',simplestyle.formatStyle(cstyle))
- node.set('style',simplestyle.formatStyle(style))
-
-e = MyEffect()
-e.affect()
+#!/usr/bin/env python +''' +Copyright (C) 2006 Aaron Spike, aaron@ekips.org + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' +import random, inkex, simplestyle, copy + +class MyEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("-m", "--modify", + action="store", type="inkbool", + dest="modify", default=False, + help="do not create a copy, modify the markers") + + def effect(self): + defs = self.xpathSingle('/svg:svg//svg:defs') + if not defs: + defs = inkex.etree.SubElement(self.document.getroot(),inkex.addNS('defs','svg')) + + for id, node in self.selected.iteritems(): + mprops = ['marker','marker-start','marker-mid','marker-end'] + try: + style = simplestyle.parseStyle(node.get('style')) + except: + inkex.debug("No style attribute found for id: %s" % id) + continue + + stroke = style.get('stroke', '#000000') + + for mprop in mprops: + if style.has_key(mprop) and style[mprop] != 'none'and style[mprop][:5] == 'url(#': + marker_id = style[mprop][5:-1] + try: + old_mnode = self.xpathSingle('/svg:svg//svg:marker[@id="%s"]' % marker_id) + if not self.options.modify: + mnode = copy.deepcopy(old_mnode) + else: + mnode = old_mnode + except: + inkex.debug("unable to locate marker: %s" % marker_id) + continue + + new_id = self.uniqueId(marker_id, not self.options.modify) + + style[mprop] = "url(#%s)" % new_id + mnode.set('id', new_id) + mnode.set(inkex.addNS('stockid','inkscape'), new_id) + defs.append(mnode) + + children = mnode.xpath('.//*[@style]', namespaces=inkex.NSS) + for child in children: + cstyle = simplestyle.parseStyle(child.get('style')) + if ('stroke' in cstyle and cstyle['stroke'] != 'none') or 'stroke' not in cstyle: + cstyle['stroke'] = stroke + if ('fill' in cstyle and cstyle['fill'] != 'none') or 'fill' not in cstyle: + cstyle['fill'] = stroke + child.set('style',simplestyle.formatStyle(cstyle)) + node.set('style',simplestyle.formatStyle(style)) + +e = MyEffect() +e.affect() diff --git a/share/extensions/measure.py b/share/extensions/measure.py index b37303f1b..483a4a66a 100644 --- a/share/extensions/measure.py +++ b/share/extensions/measure.py @@ -115,7 +115,7 @@ class Length(inkex.Effect): if node.tag == inkex.addNS('path','svg'): self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg')) - t = node.get('transform')
+ t = node.get('transform') if t: self.group.set('transform', t) @@ -162,8 +162,8 @@ class Length(inkex.Effect): new.set('startOffset', "50%") new.set('dy', str(dy)) # dubious merit #new.append(tp) - new.text = str(text)
- #node.set('transform','rotate(180,'+str(-x)+','+str(-y)+')')
+ new.text = str(text) + #node.set('transform','rotate(180,'+str(-x)+','+str(-y)+')') node.set('x', str(x)) node.set('y', str(y)) diff --git a/share/extensions/pathalongpath.py b/share/extensions/pathalongpath.py index a8285b9f8..5bac2550b 100644 --- a/share/extensions/pathalongpath.py +++ b/share/extensions/pathalongpath.py @@ -1,278 +1,278 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-barraud@math.univ-lille1.fr
-
-Quick description:
-This script deforms an object (the pattern) along other paths (skeletons)...
-The first selected object is the pattern
-the last selected ones are the skeletons.
-
-Imagine a straight horizontal line L in the middle of the bounding box of the pattern.
-Consider the normal bundle of L: the collection of all the vertical lines meeting L.
-Consider this as the initial state of the plane; in particular, think of the pattern
-as painted on these lines.
-
-Now move and bend L to make it fit a skeleton, and see what happens to the normals:
-they move and rotate, deforming the pattern.
-'''
-
-import inkex, cubicsuperpath, bezmisc
-import pathmodifier,simpletransform
-
-import copy, math, re, random
-
-def flipxy(path):
- for pathcomp in path:
- for ctl in pathcomp:
- for pt in ctl:
- tmp=pt[0]
- pt[0]=-pt[1]
- pt[1]=-tmp
-
-def offset(pathcomp,dx,dy):
- for ctl in pathcomp:
- for pt in ctl:
- pt[0]+=dx
- pt[1]+=dy
-
-def stretch(pathcomp,xscale,yscale,org):
- for ctl in pathcomp:
- for pt in ctl:
- pt[0]=org[0]+(pt[0]-org[0])*xscale
- pt[1]=org[1]+(pt[1]-org[1])*yscale
-
-def linearize(p,tolerance=0.001):
- '''
- This function recieves a component of a 'cubicsuperpath' and returns two things:
- The path subdivided in many straight segments, and an array containing the length of each segment.
-
- We could work with bezier path as well, but bezier arc lengths are (re)computed for each point
- in the deformed object. For complex paths, this might take a while.
- '''
- zero=0.000001
- i=0
- d=0
- lengths=[]
- while i<len(p)-1:
- box = bezmisc.pointdistance(p[i ][1],p[i ][2])
- box += bezmisc.pointdistance(p[i ][2],p[i+1][0])
- box += bezmisc.pointdistance(p[i+1][0],p[i+1][1])
- chord = bezmisc.pointdistance(p[i][1], p[i+1][1])
- if (box - chord) > tolerance:
- b1, b2 = bezmisc.beziersplitatt([p[i][1],p[i][2],p[i+1][0],p[i+1][1]], 0.5)
- p[i ][2][0],p[i ][2][1]=b1[1]
- p[i+1][0][0],p[i+1][0][1]=b2[2]
- p.insert(i+1,[[b1[2][0],b1[2][1]],[b1[3][0],b1[3][1]],[b2[1][0],b2[1][1]]])
- else:
- d=(box+chord)/2
- lengths.append(d)
- i+=1
- new=[p[i][1] for i in range(0,len(p)-1) if lengths[i]>zero]
- new.append(p[-1][1])
- lengths=[l for l in lengths if l>zero]
- return(new,lengths)
-
-class PathAlongPath(pathmodifier.Diffeo):
- def __init__(self):
- pathmodifier.Diffeo.__init__(self)
- self.OptionParser.add_option("--title")
- self.OptionParser.add_option("-n", "--noffset",
- action="store", type="float",
- dest="noffset", default=0.0, help="normal offset")
- self.OptionParser.add_option("-t", "--toffset",
- action="store", type="float",
- dest="toffset", default=0.0, help="tangential offset")
- self.OptionParser.add_option("-k", "--kind",
- action="store", type="string",
- dest="kind", default=True,
- help="choose between wave or snake effect")
- self.OptionParser.add_option("-c", "--copymode",
- action="store", type="string",
- dest="copymode", default=True,
- help="repeat the path to fit deformer's length")
- self.OptionParser.add_option("-p", "--space",
- action="store", type="float",
- dest="space", default=0.0)
- self.OptionParser.add_option("-v", "--vertical",
- action="store", type="inkbool",
- dest="vertical", default=False,
- help="reference path is vertical")
- self.OptionParser.add_option("-d", "--duplicate",
- action="store", type="inkbool",
- dest="duplicate", default=False,
- help="duplicate pattern before deformation")
-
- def prepareSelectionList(self):
-
- idList=self.options.ids
- idList=pathmodifier.zSort(self.document.getroot(),idList)
- id = idList[-1]
- self.patterns={id:self.selected[id]}
-
-## ##first selected->pattern, all but first selected-> skeletons
-## id = self.options.ids[-1]
-## self.patterns={id:self.selected[id]}
-
- if self.options.duplicate:
- self.patterns=self.duplicateNodes(self.patterns)
- self.expandGroupsUnlinkClones(self.patterns, True, True)
- self.objectsToPaths(self.patterns)
- del self.selected[id]
-
- self.skeletons=self.selected
- self.expandGroupsUnlinkClones(self.skeletons, True, False)
- self.objectsToPaths(self.skeletons)
-
- def lengthtotime(self,l):
- '''
- Recieves an arc length l, and returns the index of the segment in self.skelcomp
- containing the coresponding point, to gether with the position of the point on this segment.
-
- If the deformer is closed, do computations modulo the toal length.
- '''
- if self.skelcompIsClosed:
- l=l % sum(self.lengths)
- if l<=0:
- return 0,l/self.lengths[0]
- i=0
- while (i<len(self.lengths)) and (self.lengths[i]<=l):
- l-=self.lengths[i]
- i+=1
- t=l/self.lengths[min(i,len(self.lengths)-1)]
- return i, t
-
- def applyDiffeo(self,bpt,vects=()):
- '''
- The kernel of this stuff:
- bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt.
- '''
- s=bpt[0]-self.skelcomp[0][0]
- i,t=self.lengthtotime(s)
- if i==len(self.skelcomp)-1:
- x,y=bezmisc.tpoint(self.skelcomp[i-1],self.skelcomp[i],1+t)
- dx=(self.skelcomp[i][0]-self.skelcomp[i-1][0])/self.lengths[-1]
- dy=(self.skelcomp[i][1]-self.skelcomp[i-1][1])/self.lengths[-1]
- else:
- x,y=bezmisc.tpoint(self.skelcomp[i],self.skelcomp[i+1],t)
- dx=(self.skelcomp[i+1][0]-self.skelcomp[i][0])/self.lengths[i]
- dy=(self.skelcomp[i+1][1]-self.skelcomp[i][1])/self.lengths[i]
-
- vx=0
- vy=bpt[1]-self.skelcomp[0][1]
- if self.options.wave:
- bpt[0]=x+vx*dx
- bpt[1]=y+vy+vx*dy
- else:
- bpt[0]=x+vx*dx-vy*dy
- bpt[1]=y+vx*dy+vy*dx
-
- for v in vects:
- vx=v[0]-self.skelcomp[0][0]-s
- vy=v[1]-self.skelcomp[0][1]
- if self.options.wave:
- v[0]=x+vx*dx
- v[1]=y+vy+vx*dy
- else:
- v[0]=x+vx*dx-vy*dy
- v[1]=y+vx*dy+vy*dx
-
- def effect(self):
- if len(self.options.ids)<2:
- inkex.debug("This extension requires that you select two paths.")
- return
- self.prepareSelectionList()
- self.options.wave = (self.options.kind=="Ribbon")
- if self.options.copymode=="Single":
- self.options.repeat =False
- self.options.stretch=False
- elif self.options.copymode=="Repeated":
- self.options.repeat =True
- self.options.stretch=False
- elif self.options.copymode=="Single, stretched":
- self.options.repeat =False
- self.options.stretch=True
- elif self.options.copymode=="Repeated, stretched":
- self.options.repeat =True
- self.options.stretch=True
-
- bbox=simpletransform.computeBBox(self.patterns.values())
-
- if self.options.vertical:
- #flipxy(bbox)...
- bbox=(-bbox[3],-bbox[2],-bbox[1],-bbox[0])
-
- width=bbox[1]-bbox[0]
- dx=width+self.options.space
-
- for id, node in self.patterns.iteritems():
- if node.tag == inkex.addNS('path','svg') or node.tag=='path':
- d = node.get('d')
- p0 = cubicsuperpath.parsePath(d)
- if self.options.vertical:
- flipxy(p0)
-
- newp=[]
- for skelnode in self.skeletons.itervalues():
- self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d'))
- if self.options.vertical:
- flipxy(self.curSekeleton)
- for comp in self.curSekeleton:
- p=copy.deepcopy(p0)
- self.skelcomp,self.lengths=linearize(comp)
- #!!!!>----> TODO: really test if path is closed! end point==start point is not enough!
- self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1])
-
- length=sum(self.lengths)
- xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset
- yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset
-
-
- if self.options.repeat:
- NbCopies=max(1,int(round((length+self.options.space)/dx)))
- width=dx*NbCopies
- if not self.skelcompIsClosed:
- width-=self.options.space
- bbox=bbox[0],bbox[0]+width, bbox[2],bbox[3]
- new=[]
- for sub in p:
- for i in range(0,NbCopies,1):
- new.append(copy.deepcopy(sub))
- offset(sub,dx,0)
- p=new
-
- for sub in p:
- offset(sub,xoffset,yoffset)
-
- if self.options.stretch:
- for sub in p:
- stretch(sub,length/width,1,self.skelcomp[0])
-
- for sub in p:
- for ctlpt in sub:
- self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2]))
-
- if self.options.vertical:
- flipxy(p)
- newp+=p
-
- node.set('d', cubicsuperpath.formatPath(newp))
-
-e = PathAlongPath()
-e.affect()
-
-
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +barraud@math.univ-lille1.fr + +Quick description: +This script deforms an object (the pattern) along other paths (skeletons)... +The first selected object is the pattern +the last selected ones are the skeletons. + +Imagine a straight horizontal line L in the middle of the bounding box of the pattern. +Consider the normal bundle of L: the collection of all the vertical lines meeting L. +Consider this as the initial state of the plane; in particular, think of the pattern +as painted on these lines. + +Now move and bend L to make it fit a skeleton, and see what happens to the normals: +they move and rotate, deforming the pattern. +''' + +import inkex, cubicsuperpath, bezmisc +import pathmodifier,simpletransform + +import copy, math, re, random + +def flipxy(path): + for pathcomp in path: + for ctl in pathcomp: + for pt in ctl: + tmp=pt[0] + pt[0]=-pt[1] + pt[1]=-tmp + +def offset(pathcomp,dx,dy): + for ctl in pathcomp: + for pt in ctl: + pt[0]+=dx + pt[1]+=dy + +def stretch(pathcomp,xscale,yscale,org): + for ctl in pathcomp: + for pt in ctl: + pt[0]=org[0]+(pt[0]-org[0])*xscale + pt[1]=org[1]+(pt[1]-org[1])*yscale + +def linearize(p,tolerance=0.001): + ''' + This function recieves a component of a 'cubicsuperpath' and returns two things: + The path subdivided in many straight segments, and an array containing the length of each segment. + + We could work with bezier path as well, but bezier arc lengths are (re)computed for each point + in the deformed object. For complex paths, this might take a while. + ''' + zero=0.000001 + i=0 + d=0 + lengths=[] + while i<len(p)-1: + box = bezmisc.pointdistance(p[i ][1],p[i ][2]) + box += bezmisc.pointdistance(p[i ][2],p[i+1][0]) + box += bezmisc.pointdistance(p[i+1][0],p[i+1][1]) + chord = bezmisc.pointdistance(p[i][1], p[i+1][1]) + if (box - chord) > tolerance: + b1, b2 = bezmisc.beziersplitatt([p[i][1],p[i][2],p[i+1][0],p[i+1][1]], 0.5) + p[i ][2][0],p[i ][2][1]=b1[1] + p[i+1][0][0],p[i+1][0][1]=b2[2] + p.insert(i+1,[[b1[2][0],b1[2][1]],[b1[3][0],b1[3][1]],[b2[1][0],b2[1][1]]]) + else: + d=(box+chord)/2 + lengths.append(d) + i+=1 + new=[p[i][1] for i in range(0,len(p)-1) if lengths[i]>zero] + new.append(p[-1][1]) + lengths=[l for l in lengths if l>zero] + return(new,lengths) + +class PathAlongPath(pathmodifier.Diffeo): + def __init__(self): + pathmodifier.Diffeo.__init__(self) + self.OptionParser.add_option("--title") + self.OptionParser.add_option("-n", "--noffset", + action="store", type="float", + dest="noffset", default=0.0, help="normal offset") + self.OptionParser.add_option("-t", "--toffset", + action="store", type="float", + dest="toffset", default=0.0, help="tangential offset") + self.OptionParser.add_option("-k", "--kind", + action="store", type="string", + dest="kind", default=True, + help="choose between wave or snake effect") + self.OptionParser.add_option("-c", "--copymode", + action="store", type="string", + dest="copymode", default=True, + help="repeat the path to fit deformer's length") + self.OptionParser.add_option("-p", "--space", + action="store", type="float", + dest="space", default=0.0) + self.OptionParser.add_option("-v", "--vertical", + action="store", type="inkbool", + dest="vertical", default=False, + help="reference path is vertical") + self.OptionParser.add_option("-d", "--duplicate", + action="store", type="inkbool", + dest="duplicate", default=False, + help="duplicate pattern before deformation") + + def prepareSelectionList(self): + + idList=self.options.ids + idList=pathmodifier.zSort(self.document.getroot(),idList) + id = idList[-1] + self.patterns={id:self.selected[id]} + +## ##first selected->pattern, all but first selected-> skeletons +## id = self.options.ids[-1] +## self.patterns={id:self.selected[id]} + + if self.options.duplicate: + self.patterns=self.duplicateNodes(self.patterns) + self.expandGroupsUnlinkClones(self.patterns, True, True) + self.objectsToPaths(self.patterns) + del self.selected[id] + + self.skeletons=self.selected + self.expandGroupsUnlinkClones(self.skeletons, True, False) + self.objectsToPaths(self.skeletons) + + def lengthtotime(self,l): + ''' + Recieves an arc length l, and returns the index of the segment in self.skelcomp + containing the coresponding point, to gether with the position of the point on this segment. + + If the deformer is closed, do computations modulo the toal length. + ''' + if self.skelcompIsClosed: + l=l % sum(self.lengths) + if l<=0: + return 0,l/self.lengths[0] + i=0 + while (i<len(self.lengths)) and (self.lengths[i]<=l): + l-=self.lengths[i] + i+=1 + t=l/self.lengths[min(i,len(self.lengths)-1)] + return i, t + + def applyDiffeo(self,bpt,vects=()): + ''' + The kernel of this stuff: + bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. + ''' + s=bpt[0]-self.skelcomp[0][0] + i,t=self.lengthtotime(s) + if i==len(self.skelcomp)-1: + x,y=bezmisc.tpoint(self.skelcomp[i-1],self.skelcomp[i],1+t) + dx=(self.skelcomp[i][0]-self.skelcomp[i-1][0])/self.lengths[-1] + dy=(self.skelcomp[i][1]-self.skelcomp[i-1][1])/self.lengths[-1] + else: + x,y=bezmisc.tpoint(self.skelcomp[i],self.skelcomp[i+1],t) + dx=(self.skelcomp[i+1][0]-self.skelcomp[i][0])/self.lengths[i] + dy=(self.skelcomp[i+1][1]-self.skelcomp[i][1])/self.lengths[i] + + vx=0 + vy=bpt[1]-self.skelcomp[0][1] + if self.options.wave: + bpt[0]=x+vx*dx + bpt[1]=y+vy+vx*dy + else: + bpt[0]=x+vx*dx-vy*dy + bpt[1]=y+vx*dy+vy*dx + + for v in vects: + vx=v[0]-self.skelcomp[0][0]-s + vy=v[1]-self.skelcomp[0][1] + if self.options.wave: + v[0]=x+vx*dx + v[1]=y+vy+vx*dy + else: + v[0]=x+vx*dx-vy*dy + v[1]=y+vx*dy+vy*dx + + def effect(self): + if len(self.options.ids)<2: + inkex.debug("This extension requires that you select two paths.") + return + self.prepareSelectionList() + self.options.wave = (self.options.kind=="Ribbon") + if self.options.copymode=="Single": + self.options.repeat =False + self.options.stretch=False + elif self.options.copymode=="Repeated": + self.options.repeat =True + self.options.stretch=False + elif self.options.copymode=="Single, stretched": + self.options.repeat =False + self.options.stretch=True + elif self.options.copymode=="Repeated, stretched": + self.options.repeat =True + self.options.stretch=True + + bbox=simpletransform.computeBBox(self.patterns.values()) + + if self.options.vertical: + #flipxy(bbox)... + bbox=(-bbox[3],-bbox[2],-bbox[1],-bbox[0]) + + width=bbox[1]-bbox[0] + dx=width+self.options.space + + for id, node in self.patterns.iteritems(): + if node.tag == inkex.addNS('path','svg') or node.tag=='path': + d = node.get('d') + p0 = cubicsuperpath.parsePath(d) + if self.options.vertical: + flipxy(p0) + + newp=[] + for skelnode in self.skeletons.itervalues(): + self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) + if self.options.vertical: + flipxy(self.curSekeleton) + for comp in self.curSekeleton: + p=copy.deepcopy(p0) + self.skelcomp,self.lengths=linearize(comp) + #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! + self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1]) + + length=sum(self.lengths) + xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset + yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset + + + if self.options.repeat: + NbCopies=max(1,int(round((length+self.options.space)/dx))) + width=dx*NbCopies + if not self.skelcompIsClosed: + width-=self.options.space + bbox=bbox[0],bbox[0]+width, bbox[2],bbox[3] + new=[] + for sub in p: + for i in range(0,NbCopies,1): + new.append(copy.deepcopy(sub)) + offset(sub,dx,0) + p=new + + for sub in p: + offset(sub,xoffset,yoffset) + + if self.options.stretch: + for sub in p: + stretch(sub,length/width,1,self.skelcomp[0]) + + for sub in p: + for ctlpt in sub: + self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2])) + + if self.options.vertical: + flipxy(p) + newp+=p + + node.set('d', cubicsuperpath.formatPath(newp)) + +e = PathAlongPath() +e.affect() + + diff --git a/share/extensions/pathmodifier.py b/share/extensions/pathmodifier.py index 76b9d77b1..bfc72f074 100644 --- a/share/extensions/pathmodifier.py +++ b/share/extensions/pathmodifier.py @@ -1,307 +1,307 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-barraud@math.univ-lille1.fr
-
-This code defines a basic class (PathModifier) of effects whose purpose is
-to somehow deform given objects: one common tasks for all such effect is to
-convert shapes, groups, clones to paths. The class has several functions to
-make this (more or less!) easy.
-As an exemple, a second class (Diffeo) is derived from it,
-to implement deformations of the form X=f(x,y), Y=g(x,y)...
-
-TODO: Several handy functions are defined, that might in fact be of general
-interest and that should be shipped out in separate files...
-'''
-import inkex, cubicsuperpath, bezmisc, simplestyle
-from simpletransform import *
-import copy, math, re, random
-
-####################################################################
-##-- zOrder computation...
-##-- this should be shipped out in a separate file. inkex.py?
-
-def zSort(inNode,idList):
- sortedList=[]
- theid = inNode.get("id")
- if theid in idList:
- sortedList.append(theid)
- for child in inNode:
- if len(sortedList)==len(idList):
- break
- sortedList+=zSort(child,idList)
- return sortedList
-
-
-class PathModifier(inkex.Effect):
- def __init__(self):
- inkex.Effect.__init__(self)
-
-##################################
-#-- Selectionlists manipulation --
-##################################
-
- def duplicateNodes(self, aList):
- clones={}
- for id,node in aList.iteritems():
- clone=copy.deepcopy(node)
- #!!!--> should it be given an id?
- #seems to work without this!?!
- myid = node.tag.split('}')[-1]
- clone.set("id", self.uniqueId(myid))
- node.getparent().append(clone)
- clones[clone.get("id")]=clone
- return(clones)
-
- def uniqueId(self, prefix):
- id="%s%04i"%(prefix,random.randint(0,9999))
- while len(self.document.getroot().xpath('//*[@id="%s"]' % id,namespaces=inkex.NSS)):
- id="%s%04i"%(prefix,random.randint(0,9999))
- return(id)
-
- def expandGroups(self,aList,transferTransform=True):
- for id, node in aList.items():
- if node.tag == inkex.addNS('g','svg') or node.tag=='g':
- mat=parseTransform(node.get("transform"))
- for child in node:
- if transferTransform:
- applyTransformToNode(mat,child)
- aList.update(self.expandGroups({child.get('id'):child}))
- if transferTransform and node.get("transform"):
- del node.attrib["transform"]
- del aList[id]
- return(aList)
-
- def expandGroupsUnlinkClones(self,aList,transferTransform=True,doReplace=True):
- for id in aList.keys()[:]:
- node=aList[id]
- if node.tag == inkex.addNS('g','svg') or node.tag=='g':
- self.expandGroups(aList,transferTransform)
- self.expandGroupsUnlinkClones(aList,transferTransform,doReplace)
- #Hum... not very efficient if there are many clones of groups...
-
- elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
- refnode=self.refNode(node)
- newnode=self.unlinkClone(node,doReplace)
- del aList[id]
-
- style = simplestyle.parseStyle(node.get('style') or "")
- refstyle=simplestyle.parseStyle(refnode.get('style') or "")
- style.update(refstyle)
- newnode.set('style',simplestyle.formatStyle(style))
-
- newid=newnode.get('id')
- aList.update(self.expandGroupsUnlinkClones({newid:newnode},transferTransform,doReplace))
- return aList
-
- def recursNewIds(self,node):
- if node.get('id'):
- node.set('id',self.uniqueId(node.tag))
- for child in node:
- self.recursNewIds(child)
-
- def refNode(self,node):
- if node.get(inkex.addNS('href','xlink')):
- refid=node.get(inkex.addNS('href','xlink'))
- path = '//*[@id="%s"]' % refid[1:]
- newNode = self.document.getroot().xpath(path, namespaces=inkex.NSS)[0]
- return newNode
- else:
- raise AssertionError, "Trying to follow empty xlink.href attribute."
-
- def unlinkClone(self,node,doReplace):
- if node.tag == inkex.addNS('use','svg') or node.tag=='use':
- newNode = copy.deepcopy(self.refNode(node))
- self.recursNewIds(newNode)
- applyTransformToNode(parseTransform(node.get('transform')),newNode)
-
- if doReplace:
- parent=node.getparent()
- parent.insert(parent.index(node),newNode)
- parent.remove(node)
-
- return newNode
- else:
- raise AssertionError, "Only clones can be unlinked..."
-
-
-
-################################
-#-- Object conversion ----------
-################################
-
- def rectToPath(self,node,doReplace=True):
- if node.tag == inkex.addNS('rect','svg'):
- x =float(node.get('x'))
- y =float(node.get('y'))
- #FIXME: no exception anymore and sometimes just one
- try:
- rx=float(node.get('rx'))
- ry=float(node.get('ry'))
- except:
- rx=0
- ry=0
- w =float(node.get('width' ))
- h =float(node.get('height'))
- d ='M %f,%f '%(x+rx,y)
- d+='L %f,%f '%(x+w-rx,y)
- d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w,y+ry)
- d+='L %f,%f '%(x+w,y+h-ry)
- d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w-rx,y+h)
- d+='L %f,%f '%(x+rx,y+h)
- d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x,y+h-ry)
- d+='L %f,%f '%(x,y+ry)
- d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+rx,y)
-
- newnode=inkex.etree.Element('path')
- newnode.set('d',d)
- newnode.set('id', self.uniqueId('path'))
- newnode.set('style',node.get('style'))
- nnt = node.get('transform')
- if nnt:
- newnode.set('transform',nnt)
- fuseTransform(newnode)
- if doReplace:
- parent=node.getparent()
- parent.insert(parent.index(node),newnode)
- parent.remove(node)
- return newnode
-
- def groupToPath(self,node,doReplace=True):
- if node.tag == inkex.addNS('g','svg'):
- newNode = inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg'))
-
- newstyle = simplestyle.parseStyle(node.get('style') or "")
- newp = []
- for child in node:
- childstyle = simplestyle.parseStyle(child.get('style') or "")
- childstyle.update(newstyle)
- newstyle.update(childstyle)
- childAsPath = self.objectToPath(child,False)
- newp += cubicsuperpath.parsePath(childAsPath.get('d'))
- newNode.set('d',cubicsuperpath.formatPath(newp))
- newNode.set('style',simplestyle.formatStyle(newstyle))
-
- self.current_layer.remove(newNode)
- if doReplace:
- parent=node.getparent()
- parent.insert(parent.index(node),newNode)
- parent.remove(node)
-
- return newNode
- else:
- raise AssertionError
-
- def objectToPath(self,node,doReplace=True):
- #--TODO: support other object types!!!!
- #--TODO: make sure cubicsuperpath supports A and Q commands...
- if node.tag == inkex.addNS('rect','svg'):
- return(self.rectToPath(node,doReplace))
- if node.tag == inkex.addNS('g','svg'):
- return(self.groupToPath(node,doReplace))
- elif node.tag == inkex.addNS('path','svg') or node.tag == 'path':
- #remove inkscape attributes, otherwise any modif of 'd' will be discarded!
- for attName in node.attrib.keys():
- if ("sodipodi" in attName) or ("inkscape" in attName):
- del node.attrib[attName]
- fuseTransform(node)
- return node
- elif node.tag == inkex.addNS('use','svg') or node.tag == 'use':
- newNode = self.unlinkClone(node,doReplace)
- return self.objectToPath(newNode,doReplace)
- else:
- inkex.debug("Please first convert objects to paths!...(got '%s')"%node.tag)
- return None
-
- def objectsToPaths(self,aList,doReplace=True):
- newSelection={}
- for id,node in aList.items():
- newnode=self.objectToPath(node,doReplace)
- del aList[id]
- aList[newnode.get('id')]=newnode
-
-
-################################
-#-- Action ----------
-################################
-
- #-- overwrite this method in subclasses...
- def effect(self):
- #self.duplicateNodes(self.selected)
- #self.expandGroupsUnlinkClones(self.selected, True)
- self.objectsToPaths(self.selected, True)
- self.bbox=computeBBox(self.selected.values())
- for id, node in self.selected.iteritems():
- if node.tag == inkex.addNS('path','svg'):
- d = node.get('d')
- p = cubicsuperpath.parsePath(d)
-
- #do what ever you want with p!
-
- node.set('d',cubicsuperpath.formatPath(p))
-
-
-class Diffeo(PathModifier):
- def __init__(self):
- inkex.Effect.__init__(self)
-
- def applyDiffeo(self,bpt,vects=()):
- '''
- bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt.
- Defaults to identity!
- '''
- for v in vects:
- v[0]-=bpt[0]
- v[1]-=bpt[1]
-
- #-- your transformations go here:
- #x,y=bpt
- #bpt[0]=f(x,y)
- #bpt[1]=g(x,y)
- #for v in vects:
- # vx,vy=v
- # v[0]=df/dx(x,y)*vx+df/dy(x,y)*vy
- # v[1]=dg/dx(x,y)*vx+dg/dy(x,y)*vy
- #
- #-- !caution! y-axis is pointing downward!
-
- for v in vects:
- v[0]+=bpt[0]
- v[1]+=bpt[1]
-
-
- def effect(self):
- #self.duplicateNodes(self.selected)
- self.expandGroupsUnlinkClones(self.selected, True)
- self.expandGroups(self.selected, True)
- self.objectsToPaths(self.selected, True)
- self.bbox=computeBBox(self.selected.values())
- for id, node in self.selected.iteritems():
- if node.tag == inkex.addNS('path','svg') or node.tag=='path':
- d = node.get('d')
- p = cubicsuperpath.parsePath(d)
-
- for sub in p:
- for ctlpt in sub:
- self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2]))
-
- node.set('d',cubicsuperpath.formatPath(p))
-
-#e = Diffeo()
-#e.affect()
-
-
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +barraud@math.univ-lille1.fr + +This code defines a basic class (PathModifier) of effects whose purpose is +to somehow deform given objects: one common tasks for all such effect is to +convert shapes, groups, clones to paths. The class has several functions to +make this (more or less!) easy. +As an exemple, a second class (Diffeo) is derived from it, +to implement deformations of the form X=f(x,y), Y=g(x,y)... + +TODO: Several handy functions are defined, that might in fact be of general +interest and that should be shipped out in separate files... +''' +import inkex, cubicsuperpath, bezmisc, simplestyle +from simpletransform import * +import copy, math, re, random + +#################################################################### +##-- zOrder computation... +##-- this should be shipped out in a separate file. inkex.py? + +def zSort(inNode,idList): + sortedList=[] + theid = inNode.get("id") + if theid in idList: + sortedList.append(theid) + for child in inNode: + if len(sortedList)==len(idList): + break + sortedList+=zSort(child,idList) + return sortedList + + +class PathModifier(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + +################################## +#-- Selectionlists manipulation -- +################################## + + def duplicateNodes(self, aList): + clones={} + for id,node in aList.iteritems(): + clone=copy.deepcopy(node) + #!!!--> should it be given an id? + #seems to work without this!?! + myid = node.tag.split('}')[-1] + clone.set("id", self.uniqueId(myid)) + node.getparent().append(clone) + clones[clone.get("id")]=clone + return(clones) + + def uniqueId(self, prefix): + id="%s%04i"%(prefix,random.randint(0,9999)) + while len(self.document.getroot().xpath('//*[@id="%s"]' % id,namespaces=inkex.NSS)): + id="%s%04i"%(prefix,random.randint(0,9999)) + return(id) + + def expandGroups(self,aList,transferTransform=True): + for id, node in aList.items(): + if node.tag == inkex.addNS('g','svg') or node.tag=='g': + mat=parseTransform(node.get("transform")) + for child in node: + if transferTransform: + applyTransformToNode(mat,child) + aList.update(self.expandGroups({child.get('id'):child})) + if transferTransform and node.get("transform"): + del node.attrib["transform"] + del aList[id] + return(aList) + + def expandGroupsUnlinkClones(self,aList,transferTransform=True,doReplace=True): + for id in aList.keys()[:]: + node=aList[id] + if node.tag == inkex.addNS('g','svg') or node.tag=='g': + self.expandGroups(aList,transferTransform) + self.expandGroupsUnlinkClones(aList,transferTransform,doReplace) + #Hum... not very efficient if there are many clones of groups... + + elif node.tag == inkex.addNS('use','svg') or node.tag=='use': + refnode=self.refNode(node) + newnode=self.unlinkClone(node,doReplace) + del aList[id] + + style = simplestyle.parseStyle(node.get('style') or "") + refstyle=simplestyle.parseStyle(refnode.get('style') or "") + style.update(refstyle) + newnode.set('style',simplestyle.formatStyle(style)) + + newid=newnode.get('id') + aList.update(self.expandGroupsUnlinkClones({newid:newnode},transferTransform,doReplace)) + return aList + + def recursNewIds(self,node): + if node.get('id'): + node.set('id',self.uniqueId(node.tag)) + for child in node: + self.recursNewIds(child) + + def refNode(self,node): + if node.get(inkex.addNS('href','xlink')): + refid=node.get(inkex.addNS('href','xlink')) + path = '//*[@id="%s"]' % refid[1:] + newNode = self.document.getroot().xpath(path, namespaces=inkex.NSS)[0] + return newNode + else: + raise AssertionError, "Trying to follow empty xlink.href attribute." + + def unlinkClone(self,node,doReplace): + if node.tag == inkex.addNS('use','svg') or node.tag=='use': + newNode = copy.deepcopy(self.refNode(node)) + self.recursNewIds(newNode) + applyTransformToNode(parseTransform(node.get('transform')),newNode) + + if doReplace: + parent=node.getparent() + parent.insert(parent.index(node),newNode) + parent.remove(node) + + return newNode + else: + raise AssertionError, "Only clones can be unlinked..." + + + +################################ +#-- Object conversion ---------- +################################ + + def rectToPath(self,node,doReplace=True): + if node.tag == inkex.addNS('rect','svg'): + x =float(node.get('x')) + y =float(node.get('y')) + #FIXME: no exception anymore and sometimes just one + try: + rx=float(node.get('rx')) + ry=float(node.get('ry')) + except: + rx=0 + ry=0 + w =float(node.get('width' )) + h =float(node.get('height')) + d ='M %f,%f '%(x+rx,y) + d+='L %f,%f '%(x+w-rx,y) + d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w,y+ry) + d+='L %f,%f '%(x+w,y+h-ry) + d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w-rx,y+h) + d+='L %f,%f '%(x+rx,y+h) + d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x,y+h-ry) + d+='L %f,%f '%(x,y+ry) + d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+rx,y) + + newnode=inkex.etree.Element('path') + newnode.set('d',d) + newnode.set('id', self.uniqueId('path')) + newnode.set('style',node.get('style')) + nnt = node.get('transform') + if nnt: + newnode.set('transform',nnt) + fuseTransform(newnode) + if doReplace: + parent=node.getparent() + parent.insert(parent.index(node),newnode) + parent.remove(node) + return newnode + + def groupToPath(self,node,doReplace=True): + if node.tag == inkex.addNS('g','svg'): + newNode = inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg')) + + newstyle = simplestyle.parseStyle(node.get('style') or "") + newp = [] + for child in node: + childstyle = simplestyle.parseStyle(child.get('style') or "") + childstyle.update(newstyle) + newstyle.update(childstyle) + childAsPath = self.objectToPath(child,False) + newp += cubicsuperpath.parsePath(childAsPath.get('d')) + newNode.set('d',cubicsuperpath.formatPath(newp)) + newNode.set('style',simplestyle.formatStyle(newstyle)) + + self.current_layer.remove(newNode) + if doReplace: + parent=node.getparent() + parent.insert(parent.index(node),newNode) + parent.remove(node) + + return newNode + else: + raise AssertionError + + def objectToPath(self,node,doReplace=True): + #--TODO: support other object types!!!! + #--TODO: make sure cubicsuperpath supports A and Q commands... + if node.tag == inkex.addNS('rect','svg'): + return(self.rectToPath(node,doReplace)) + if node.tag == inkex.addNS('g','svg'): + return(self.groupToPath(node,doReplace)) + elif node.tag == inkex.addNS('path','svg') or node.tag == 'path': + #remove inkscape attributes, otherwise any modif of 'd' will be discarded! + for attName in node.attrib.keys(): + if ("sodipodi" in attName) or ("inkscape" in attName): + del node.attrib[attName] + fuseTransform(node) + return node + elif node.tag == inkex.addNS('use','svg') or node.tag == 'use': + newNode = self.unlinkClone(node,doReplace) + return self.objectToPath(newNode,doReplace) + else: + inkex.debug("Please first convert objects to paths!...(got '%s')"%node.tag) + return None + + def objectsToPaths(self,aList,doReplace=True): + newSelection={} + for id,node in aList.items(): + newnode=self.objectToPath(node,doReplace) + del aList[id] + aList[newnode.get('id')]=newnode + + +################################ +#-- Action ---------- +################################ + + #-- overwrite this method in subclasses... + def effect(self): + #self.duplicateNodes(self.selected) + #self.expandGroupsUnlinkClones(self.selected, True) + self.objectsToPaths(self.selected, True) + self.bbox=computeBBox(self.selected.values()) + for id, node in self.selected.iteritems(): + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + p = cubicsuperpath.parsePath(d) + + #do what ever you want with p! + + node.set('d',cubicsuperpath.formatPath(p)) + + +class Diffeo(PathModifier): + def __init__(self): + inkex.Effect.__init__(self) + + def applyDiffeo(self,bpt,vects=()): + ''' + bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. + Defaults to identity! + ''' + for v in vects: + v[0]-=bpt[0] + v[1]-=bpt[1] + + #-- your transformations go here: + #x,y=bpt + #bpt[0]=f(x,y) + #bpt[1]=g(x,y) + #for v in vects: + # vx,vy=v + # v[0]=df/dx(x,y)*vx+df/dy(x,y)*vy + # v[1]=dg/dx(x,y)*vx+dg/dy(x,y)*vy + # + #-- !caution! y-axis is pointing downward! + + for v in vects: + v[0]+=bpt[0] + v[1]+=bpt[1] + + + def effect(self): + #self.duplicateNodes(self.selected) + self.expandGroupsUnlinkClones(self.selected, True) + self.expandGroups(self.selected, True) + self.objectsToPaths(self.selected, True) + self.bbox=computeBBox(self.selected.values()) + for id, node in self.selected.iteritems(): + if node.tag == inkex.addNS('path','svg') or node.tag=='path': + d = node.get('d') + p = cubicsuperpath.parsePath(d) + + for sub in p: + for ctlpt in sub: + self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2])) + + node.set('d',cubicsuperpath.formatPath(p)) + +#e = Diffeo() +#e.affect() + + diff --git a/share/extensions/pathscatter.py b/share/extensions/pathscatter.py index 26df9553a..4e41eff65 100644 --- a/share/extensions/pathscatter.py +++ b/share/extensions/pathscatter.py @@ -1,261 +1,261 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-barraud@math.univ-lille1.fr
-
-Quick description:
-This script deforms an object (the pattern) along other paths (skeletons)...
-The first selected object is the pattern
-the last selected ones are the skeletons.
-
-Imagine a straight horizontal line L in the middle of the bounding box of the pattern.
-Consider the normal bundle of L: the collection of all the vertical lines meeting L.
-Consider this as the initial state of the plane; in particular, think of the pattern
-as painted on these lines.
-
-Now move and bend L to make it fit a skeleton, and see what happens to the normals:
-they move and rotate, deforming the pattern.
-'''
-
-import inkex, cubicsuperpath, bezmisc
-import pathmodifier, simpletransform
-from lxml import etree
-
-import copy, math, re, random
-
-def zSort(inNode,idList):
- sortedList=[]
- theid = inNode.get("id")
- if theid in idList:
- sortedList.append(theid)
- for child in inNode:
- if len(sortedList)==len(idList):
- break
- sortedList+=zSort(child,idList)
- return sortedList
-
-
-def flipxy(path):
- for pathcomp in path:
- for ctl in pathcomp:
- for pt in ctl:
- tmp=pt[0]
- pt[0]=-pt[1]
- pt[1]=-tmp
-
-def offset(pathcomp,dx,dy):
- for ctl in pathcomp:
- for pt in ctl:
- pt[0]+=dx
- pt[1]+=dy
-
-def stretch(pathcomp,xscale,yscale,org):
- for ctl in pathcomp:
- for pt in ctl:
- pt[0]=org[0]+(pt[0]-org[0])*xscale
- pt[1]=org[1]+(pt[1]-org[1])*yscale
-
-def linearize(p,tolerance=0.001):
- '''
- This function recieves a component of a 'cubicsuperpath' and returns two things:
- The path subdivided in many straight segments, and an array containing the length of each segment.
-
- We could work with bezier path as well, but bezier arc lengths are (re)computed for each point
- in the deformed object. For complex paths, this might take a while.
- '''
- zero=0.000001
- i=0
- d=0
- lengths=[]
- while i<len(p)-1:
- box = bezmisc.pointdistance(p[i ][1],p[i ][2])
- box += bezmisc.pointdistance(p[i ][2],p[i+1][0])
- box += bezmisc.pointdistance(p[i+1][0],p[i+1][1])
- chord = bezmisc.pointdistance(p[i][1], p[i+1][1])
- if (box - chord) > tolerance:
- b1, b2 = bezmisc.beziersplitatt([p[i][1],p[i][2],p[i+1][0],p[i+1][1]], 0.5)
- p[i ][2][0],p[i ][2][1]=b1[1]
- p[i+1][0][0],p[i+1][0][1]=b2[2]
- p.insert(i+1,[[b1[2][0],b1[2][1]],[b1[3][0],b1[3][1]],[b2[1][0],b2[1][1]]])
- else:
- d=(box+chord)/2
- lengths.append(d)
- i+=1
- new=[p[i][1] for i in range(0,len(p)-1) if lengths[i]>zero]
- new.append(p[-1][1])
- lengths=[l for l in lengths if l>zero]
- return(new,lengths)
-
-class PathScatter(pathmodifier.Diffeo):
- def __init__(self):
- pathmodifier.Diffeo.__init__(self)
- self.OptionParser.add_option("--title")
- self.OptionParser.add_option("-n", "--noffset",
- action="store", type="float",
- dest="noffset", default=0.0, help="normal offset")
- self.OptionParser.add_option("-t", "--toffset",
- action="store", type="float",
- dest="toffset", default=0.0, help="tangential offset")
- self.OptionParser.add_option("-f", "--follow",
- action="store", type="inkbool",
- dest="follow", default=True,
- help="choose between wave or snake effect")
- self.OptionParser.add_option("-s", "--stretch",
- action="store", type="inkbool",
- dest="stretch", default=True,
- help="repeat the path to fit deformer's length")
- self.OptionParser.add_option("-p", "--space",
- action="store", type="float",
- dest="space", default=0.0)
- self.OptionParser.add_option("-v", "--vertical",
- action="store", type="inkbool",
- dest="vertical", default=False,
- help="reference path is vertical")
- self.OptionParser.add_option("-d", "--duplicate",
- action="store", type="inkbool",
- dest="duplicate", default=False,
- help="duplicate pattern before deformation")
- self.OptionParser.add_option("-c", "--copymode",
- action="store", type="string",
- dest="copymode", default="clone",
- help="duplicate pattern before deformation")
-
- def prepareSelectionList(self):
-
- idList=self.options.ids
- idList=zSort(self.document.getroot(),idList)
-
- ##first selected->pattern, all but first selected-> skeletons
- #id = self.options.ids[-1]
- id = idList[-1]
- self.patternNode=self.selected[id]
-
- self.gNode = etree.Element('{http://www.w3.org/2000/svg}g')
- self.patternNode.getparent().append(self.gNode)
-
- if self.options.copymode=="copy":
- duplist=self.duplicateNodes({id:self.patternNode})
- self.patternNode = duplist.values()[0]
-
- #TODO: allow 4th option: duplicate the first copy and clone the next ones.
- if "%s"%self.options.copymode=="clone":
- self.patternNode = etree.Element('{http://www.w3.org/2000/svg}use')
- self.patternNode.set('{http://www.w3.org/1999/xlink}href',"#%s"%id)
- self.gNode.append(self.patternNode)
-
- self.skeletons=self.selected
- del self.skeletons[id]
- self.expandGroupsUnlinkClones(self.skeletons, True, False)
- self.objectsToPaths(self.skeletons,False)
-
- def lengthtotime(self,l):
- '''
- Recieves an arc length l, and returns the index of the segment in self.skelcomp
- containing the coresponding point, to gether with the position of the point on this segment.
-
- If the deformer is closed, do computations modulo the toal length.
- '''
- if self.skelcompIsClosed:
- l=l % sum(self.lengths)
- if l<=0:
- return 0,l/self.lengths[0]
- i=0
- while (i<len(self.lengths)) and (self.lengths[i]<=l):
- l-=self.lengths[i]
- i+=1
- t=l/self.lengths[min(i,len(self.lengths)-1)]
- return i, t
-
- def localTransformAt(self,s,follow=True):
- '''
- recieves a length, and returns the coresponding point and tangent of self.skelcomp
- if follow is set to false, returns only the translation
- '''
- i,t=self.lengthtotime(s)
- if i==len(self.skelcomp)-1:
- x,y=bezmisc.tpoint(self.skelcomp[i-1],self.skelcomp[i],1+t)
- dx=(self.skelcomp[i][0]-self.skelcomp[i-1][0])/self.lengths[-1]
- dy=(self.skelcomp[i][1]-self.skelcomp[i-1][1])/self.lengths[-1]
- else:
- x,y=bezmisc.tpoint(self.skelcomp[i],self.skelcomp[i+1],t)
- dx=(self.skelcomp[i+1][0]-self.skelcomp[i][0])/self.lengths[i]
- dy=(self.skelcomp[i+1][1]-self.skelcomp[i][1])/self.lengths[i]
- if follow:
- mat=[[dx,-dy,x],[dy,dx,y]]
- else:
- mat=[[1,0,x],[0,1,y]]
- return mat
-
-
- def effect(self):
-
- if len(self.options.ids)<2:
- inkex.debug("This extension requires that you select two paths.")
- return
- self.prepareSelectionList()
-
- #center at (0,0)
- bbox=pathmodifier.computeBBox([self.patternNode])
- mat=[[1,0,-(bbox[0]+bbox[1])/2],[0,1,-(bbox[2]+bbox[3])/2]]
- if self.options.vertical:
- bbox=[-bbox[3],-bbox[2],bbox[0],bbox[1]]
- mat=simpletransform.composeTransform([[0,-1,0],[1,0,0]],mat)
- mat[1][2] += self.options.noffset
- simpletransform.applyTransformToNode(mat,self.patternNode)
-
- width=bbox[1]-bbox[0]
- dx=width+self.options.space
-
- for skelnode in self.skeletons.itervalues():
- self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d'))
- for comp in self.curSekeleton:
- self.skelcomp,self.lengths=linearize(comp)
- #!!!!>----> TODO: really test if path is closed! end point==start point is not enough!
- self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1])
-
- length=sum(self.lengths)
- if self.options.stretch:
- dx=width+self.options.space
- n=int((length-self.options.toffset+self.options.space)/dx)
- if n>0:
- dx=(length-self.options.toffset)/n
-
-
- xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset
- yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset
-
- s=self.options.toffset
- while s<=length:
- mat=self.localTransformAt(s,self.options.follow)
-
- clone=copy.deepcopy(self.patternNode)
- #!!!--> should it be given an id?
- #seems to work without this!?!
- myid = self.patternNode.tag.split('}')[-1]
- clone.set("id", self.uniqueId(myid))
- self.gNode.append(clone)
-
- simpletransform.applyTransformToNode(mat,clone)
-
- s+=dx
- self.patternNode.getparent().remove(self.patternNode)
-
-
-e = PathScatter()
-e.affect()
-
-
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +barraud@math.univ-lille1.fr + +Quick description: +This script deforms an object (the pattern) along other paths (skeletons)... +The first selected object is the pattern +the last selected ones are the skeletons. + +Imagine a straight horizontal line L in the middle of the bounding box of the pattern. +Consider the normal bundle of L: the collection of all the vertical lines meeting L. +Consider this as the initial state of the plane; in particular, think of the pattern +as painted on these lines. + +Now move and bend L to make it fit a skeleton, and see what happens to the normals: +they move and rotate, deforming the pattern. +''' + +import inkex, cubicsuperpath, bezmisc +import pathmodifier, simpletransform +from lxml import etree + +import copy, math, re, random + +def zSort(inNode,idList): + sortedList=[] + theid = inNode.get("id") + if theid in idList: + sortedList.append(theid) + for child in inNode: + if len(sortedList)==len(idList): + break + sortedList+=zSort(child,idList) + return sortedList + + +def flipxy(path): + for pathcomp in path: + for ctl in pathcomp: + for pt in ctl: + tmp=pt[0] + pt[0]=-pt[1] + pt[1]=-tmp + +def offset(pathcomp,dx,dy): + for ctl in pathcomp: + for pt in ctl: + pt[0]+=dx + pt[1]+=dy + +def stretch(pathcomp,xscale,yscale,org): + for ctl in pathcomp: + for pt in ctl: + pt[0]=org[0]+(pt[0]-org[0])*xscale + pt[1]=org[1]+(pt[1]-org[1])*yscale + +def linearize(p,tolerance=0.001): + ''' + This function recieves a component of a 'cubicsuperpath' and returns two things: + The path subdivided in many straight segments, and an array containing the length of each segment. + + We could work with bezier path as well, but bezier arc lengths are (re)computed for each point + in the deformed object. For complex paths, this might take a while. + ''' + zero=0.000001 + i=0 + d=0 + lengths=[] + while i<len(p)-1: + box = bezmisc.pointdistance(p[i ][1],p[i ][2]) + box += bezmisc.pointdistance(p[i ][2],p[i+1][0]) + box += bezmisc.pointdistance(p[i+1][0],p[i+1][1]) + chord = bezmisc.pointdistance(p[i][1], p[i+1][1]) + if (box - chord) > tolerance: + b1, b2 = bezmisc.beziersplitatt([p[i][1],p[i][2],p[i+1][0],p[i+1][1]], 0.5) + p[i ][2][0],p[i ][2][1]=b1[1] + p[i+1][0][0],p[i+1][0][1]=b2[2] + p.insert(i+1,[[b1[2][0],b1[2][1]],[b1[3][0],b1[3][1]],[b2[1][0],b2[1][1]]]) + else: + d=(box+chord)/2 + lengths.append(d) + i+=1 + new=[p[i][1] for i in range(0,len(p)-1) if lengths[i]>zero] + new.append(p[-1][1]) + lengths=[l for l in lengths if l>zero] + return(new,lengths) + +class PathScatter(pathmodifier.Diffeo): + def __init__(self): + pathmodifier.Diffeo.__init__(self) + self.OptionParser.add_option("--title") + self.OptionParser.add_option("-n", "--noffset", + action="store", type="float", + dest="noffset", default=0.0, help="normal offset") + self.OptionParser.add_option("-t", "--toffset", + action="store", type="float", + dest="toffset", default=0.0, help="tangential offset") + self.OptionParser.add_option("-f", "--follow", + action="store", type="inkbool", + dest="follow", default=True, + help="choose between wave or snake effect") + self.OptionParser.add_option("-s", "--stretch", + action="store", type="inkbool", + dest="stretch", default=True, + help="repeat the path to fit deformer's length") + self.OptionParser.add_option("-p", "--space", + action="store", type="float", + dest="space", default=0.0) + self.OptionParser.add_option("-v", "--vertical", + action="store", type="inkbool", + dest="vertical", default=False, + help="reference path is vertical") + self.OptionParser.add_option("-d", "--duplicate", + action="store", type="inkbool", + dest="duplicate", default=False, + help="duplicate pattern before deformation") + self.OptionParser.add_option("-c", "--copymode", + action="store", type="string", + dest="copymode", default="clone", + help="duplicate pattern before deformation") + + def prepareSelectionList(self): + + idList=self.options.ids + idList=zSort(self.document.getroot(),idList) + + ##first selected->pattern, all but first selected-> skeletons + #id = self.options.ids[-1] + id = idList[-1] + self.patternNode=self.selected[id] + + self.gNode = etree.Element('{http://www.w3.org/2000/svg}g') + self.patternNode.getparent().append(self.gNode) + + if self.options.copymode=="copy": + duplist=self.duplicateNodes({id:self.patternNode}) + self.patternNode = duplist.values()[0] + + #TODO: allow 4th option: duplicate the first copy and clone the next ones. + if "%s"%self.options.copymode=="clone": + self.patternNode = etree.Element('{http://www.w3.org/2000/svg}use') + self.patternNode.set('{http://www.w3.org/1999/xlink}href',"#%s"%id) + self.gNode.append(self.patternNode) + + self.skeletons=self.selected + del self.skeletons[id] + self.expandGroupsUnlinkClones(self.skeletons, True, False) + self.objectsToPaths(self.skeletons,False) + + def lengthtotime(self,l): + ''' + Recieves an arc length l, and returns the index of the segment in self.skelcomp + containing the coresponding point, to gether with the position of the point on this segment. + + If the deformer is closed, do computations modulo the toal length. + ''' + if self.skelcompIsClosed: + l=l % sum(self.lengths) + if l<=0: + return 0,l/self.lengths[0] + i=0 + while (i<len(self.lengths)) and (self.lengths[i]<=l): + l-=self.lengths[i] + i+=1 + t=l/self.lengths[min(i,len(self.lengths)-1)] + return i, t + + def localTransformAt(self,s,follow=True): + ''' + recieves a length, and returns the coresponding point and tangent of self.skelcomp + if follow is set to false, returns only the translation + ''' + i,t=self.lengthtotime(s) + if i==len(self.skelcomp)-1: + x,y=bezmisc.tpoint(self.skelcomp[i-1],self.skelcomp[i],1+t) + dx=(self.skelcomp[i][0]-self.skelcomp[i-1][0])/self.lengths[-1] + dy=(self.skelcomp[i][1]-self.skelcomp[i-1][1])/self.lengths[-1] + else: + x,y=bezmisc.tpoint(self.skelcomp[i],self.skelcomp[i+1],t) + dx=(self.skelcomp[i+1][0]-self.skelcomp[i][0])/self.lengths[i] + dy=(self.skelcomp[i+1][1]-self.skelcomp[i][1])/self.lengths[i] + if follow: + mat=[[dx,-dy,x],[dy,dx,y]] + else: + mat=[[1,0,x],[0,1,y]] + return mat + + + def effect(self): + + if len(self.options.ids)<2: + inkex.debug("This extension requires that you select two paths.") + return + self.prepareSelectionList() + + #center at (0,0) + bbox=pathmodifier.computeBBox([self.patternNode]) + mat=[[1,0,-(bbox[0]+bbox[1])/2],[0,1,-(bbox[2]+bbox[3])/2]] + if self.options.vertical: + bbox=[-bbox[3],-bbox[2],bbox[0],bbox[1]] + mat=simpletransform.composeTransform([[0,-1,0],[1,0,0]],mat) + mat[1][2] += self.options.noffset + simpletransform.applyTransformToNode(mat,self.patternNode) + + width=bbox[1]-bbox[0] + dx=width+self.options.space + + for skelnode in self.skeletons.itervalues(): + self.curSekeleton=cubicsuperpath.parsePath(skelnode.get('d')) + for comp in self.curSekeleton: + self.skelcomp,self.lengths=linearize(comp) + #!!!!>----> TODO: really test if path is closed! end point==start point is not enough! + self.skelcompIsClosed = (self.skelcomp[0]==self.skelcomp[-1]) + + length=sum(self.lengths) + if self.options.stretch: + dx=width+self.options.space + n=int((length-self.options.toffset+self.options.space)/dx) + if n>0: + dx=(length-self.options.toffset)/n + + + xoffset=self.skelcomp[0][0]-bbox[0]+self.options.toffset + yoffset=self.skelcomp[0][1]-(bbox[2]+bbox[3])/2-self.options.noffset + + s=self.options.toffset + while s<=length: + mat=self.localTransformAt(s,self.options.follow) + + clone=copy.deepcopy(self.patternNode) + #!!!--> should it be given an id? + #seems to work without this!?! + myid = self.patternNode.tag.split('}')[-1] + clone.set("id", self.uniqueId(myid)) + self.gNode.append(clone) + + simpletransform.applyTransformToNode(mat,clone) + + s+=dx + self.patternNode.getparent().remove(self.patternNode) + + +e = PathScatter() +e.affect() + + diff --git a/share/extensions/rubberstretch.py b/share/extensions/rubberstretch.py index 60b1738c6..2dfa8bb66 100644 --- a/share/extensions/rubberstretch.py +++ b/share/extensions/rubberstretch.py @@ -1,79 +1,79 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-barraud@math.univ-lille1.fr
-
-'''
-
-import inkex, cubicsuperpath, bezmisc, pathmodifier
-import copy, math, re
-
-class RubberStretch(pathmodifier.Diffeo):
- def __init__(self):
- pathmodifier.Diffeo.__init__(self)
- self.OptionParser.add_option("-r", "--ratio",
- action="store", type="float",
- dest="ratio", default=0.5)
- self.OptionParser.add_option("-c", "--curve",
- action="store", type="float",
- dest="curve", default=0.5)
-
- def applyDiffeo(self,bpt,vects=()):
- for v in vects:
- v[0]-=bpt[0]
- v[1]-=bpt[1]
- v[1]*=-1
- bpt[1]*=-1
- a=self.options.ratio/100
- b=min(self.options.curve/100,0.99)
- x0= (self.bbox[0]+self.bbox[1])/2
- y0=-(self.bbox[2]+self.bbox[3])/2
- w,h=(self.bbox[1]-self.bbox[0])/2,(self.bbox[3]-self.bbox[2])/2
-
- x,y=(bpt[0]-x0),(bpt[1]-y0)
- sx=(1+b*(x/w+1)*(x/w-1))*2**(-a)
- sy=(1+b*(y/h+1)*(y/h-1))*2**(-a)
- bpt[0]=x0+x*sy
- bpt[1]=y0+y/sx
- for v in vects:
- dx,dy=v
- dXdx=sy
- dXdy= x*2*b*y/h/h*2**(-a)
- dYdx=-y*2*b*x/w/w*2**(-a)/sx/sx
- dYdy=1/sx
- v[0]=dXdx*dx+dXdy*dy
- v[1]=dYdx*dx+dYdy*dy
-
- #--spherify
- #s=((x*x+y*y)/(w*w+h*h))**(-a/2)
- #bpt[0]=x0+s*x
- #bpt[1]=y0+s*y
- #for v in vects:
- # dx,dy=v
- # v[0]=(1-a/2/(x*x+y*y)*2*x*x)*s*dx+( -a/2/(x*x+y*y)*2*y*x)*s*dy
- # v[1]=( -a/2/(x*x+y*y)*2*x*y)*s*dx+(1-a/2/(x*x+y*y)*2*y*y)*s*dy
-
- for v in vects:
- v[0]+=bpt[0]
- v[1]+=bpt[1]
- v[1]*=-1
- bpt[1]*=-1
-
-e = RubberStretch()
-e.affect()
-
-
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +barraud@math.univ-lille1.fr + +''' + +import inkex, cubicsuperpath, bezmisc, pathmodifier +import copy, math, re + +class RubberStretch(pathmodifier.Diffeo): + def __init__(self): + pathmodifier.Diffeo.__init__(self) + self.OptionParser.add_option("-r", "--ratio", + action="store", type="float", + dest="ratio", default=0.5) + self.OptionParser.add_option("-c", "--curve", + action="store", type="float", + dest="curve", default=0.5) + + def applyDiffeo(self,bpt,vects=()): + for v in vects: + v[0]-=bpt[0] + v[1]-=bpt[1] + v[1]*=-1 + bpt[1]*=-1 + a=self.options.ratio/100 + b=min(self.options.curve/100,0.99) + x0= (self.bbox[0]+self.bbox[1])/2 + y0=-(self.bbox[2]+self.bbox[3])/2 + w,h=(self.bbox[1]-self.bbox[0])/2,(self.bbox[3]-self.bbox[2])/2 + + x,y=(bpt[0]-x0),(bpt[1]-y0) + sx=(1+b*(x/w+1)*(x/w-1))*2**(-a) + sy=(1+b*(y/h+1)*(y/h-1))*2**(-a) + bpt[0]=x0+x*sy + bpt[1]=y0+y/sx + for v in vects: + dx,dy=v + dXdx=sy + dXdy= x*2*b*y/h/h*2**(-a) + dYdx=-y*2*b*x/w/w*2**(-a)/sx/sx + dYdy=1/sx + v[0]=dXdx*dx+dXdy*dy + v[1]=dYdx*dx+dYdy*dy + + #--spherify + #s=((x*x+y*y)/(w*w+h*h))**(-a/2) + #bpt[0]=x0+s*x + #bpt[1]=y0+s*y + #for v in vects: + # dx,dy=v + # v[0]=(1-a/2/(x*x+y*y)*2*x*x)*s*dx+( -a/2/(x*x+y*y)*2*y*x)*s*dy + # v[1]=( -a/2/(x*x+y*y)*2*x*y)*s*dx+(1-a/2/(x*x+y*y)*2*y*y)*s*dy + + for v in vects: + v[0]+=bpt[0] + v[1]+=bpt[1] + v[1]*=-1 + bpt[1]*=-1 + +e = RubberStretch() +e.affect() + + diff --git a/share/extensions/simpletransform.py b/share/extensions/simpletransform.py index f434d80ed..4e4de3019 100644 --- a/share/extensions/simpletransform.py +++ b/share/extensions/simpletransform.py @@ -1,177 +1,177 @@ -#!/usr/bin/env python
-'''
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-barraud@math.univ-lille1.fr
-
-This code defines several functions to make handling of transform
-attribute easier.
-'''
-import inkex, cubicsuperpath, bezmisc, simplestyle
-import copy, math, re
-
-def parseTransform(transf,mat=[[1.0,0.0,0.0],[0.0,1.0,0.0]]):
- if transf=="" or transf==None:
- return(mat)
- result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\(([^)]*)\)",transf)
-#-- translate --
- if result.group(1)=="translate":
- args=result.group(2).split(",")
- dx=float(args[0])
- if len(args)==1:
- dy=0.0
- else:
- dy=float(args[1])
- matrix=[[1,0,dx],[0,1,dy]]
-#-- scale --
- if result.groups(1)=="scale":
- args=result.group(2).split(",")
- sx=float(args[0])
- if len(args)==1:
- sy=sx
- else:
- sy=float(args[1])
- matrix=[[sx,0,0],[0,sy,0]]
-#-- rotate --
- if result.groups(1)=="rotate":
- args=result.group(2).split(",")
- a=float(args[0])*math.pi/180
- if len(args)==1:
- cx,cy=(0.0,0.0)
- else:
- cx,cy=args[1:]
- matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]]
-#-- skewX --
- if result.groups(1)=="skewX":
- a=float(result.group(2))*math.pi/180
- matrix=[[1,math.tan(a),0],[0,1,0]]
-#-- skewX --
- if result.groups(1)=="skewX":
- a=float(result.group(2))*math.pi/180
- matrix=[[1,0,0],[math.tan(a),1,0]]
-#-- matrix --
- if result.group(1)=="matrix":
- a11,a21,a12,a22,v1,v2=result.group(2).split(",")
- matrix=[[float(a11),float(a12),float(v1)],[float(a21),float(a22),float(v2)]]
-
- matrix=composeTransform(mat,matrix)
- if result.end()<len(transf):
- return(parseTransform(transf[result.end():],matrix))
- else:
- return matrix
-
-def formatTransform(mat):
- return("matrix(%f,%f,%f,%f,%f,%f)"%(mat[0][0],mat[1][0],mat[0][1],mat[1][1],mat[0][2],mat[1][2]))
-
-def composeTransform(M1,M2):
- a11=M1[0][0]*M2[0][0]+M1[0][1]*M2[1][0]
- a12=M1[0][0]*M2[0][1]+M1[0][1]*M2[1][1]
- a21=M1[1][0]*M2[0][0]+M1[1][1]*M2[1][0]
- a22=M1[1][0]*M2[0][1]+M1[1][1]*M2[1][1]
-
- v1=M1[0][0]*M2[0][2]+M1[0][1]*M2[1][2]+M1[0][2]
- v2=M1[1][0]*M2[0][2]+M1[1][1]*M2[1][2]+M1[1][2]
- return [[a11,a12,v1],[a21,a22,v2]]
-
-def applyTransformToNode(mat,node):
- m=parseTransform(node.get("transform"))
- newtransf=formatTransform(composeTransform(mat,m))
- node.set("transform", newtransf)
-
-def applyTransformToPoint(mat,pt):
- x=mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2]
- y=mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2]
- pt[0]=x
- pt[1]=y
-
-def applyTransformToPath(mat,path):
- for comp in path:
- for ctl in comp:
- for pt in ctl:
- applyTransformToPoint(mat,pt)
-
-def fuseTransform(node):
- if node.get('d')==None:
- #FIX ME: how do you raise errors?
- raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'
- t = node.get("transform")
- if t == None:
- return
- m = parseTransform(t)
- d = node.get('d')
- p = cubicsuperpath.parsePath(d)
- applyTransformToPath(m,p)
- node.set('d', cubicsuperpath.formatPath(p))
- del node.attrib["transform"]
-
-####################################################################
-##-- Some functions to compute a rough bbox of a given list of objects.
-##-- this should be shipped out in an separate file...
-
-def boxunion(b1,b2):
- if b1 is None:
- return b2
- elif b2 is None:
- return b1
- else:
- return((min(b1[0],b2[0]),max(b1[1],b2[1]),min(b1[2],b2[2]),max(b1[3],b2[3])))
-
-def roughBBox(path):
- xmin,xMax,ymin,yMax=path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1]
- for pathcomp in path:
- for ctl in pathcomp:
- for pt in ctl:
- xmin=min(xmin,pt[0])
- xMax=max(xMax,pt[0])
- ymin=min(ymin,pt[1])
- yMax=max(yMax,pt[1])
- return xmin,xMax,ymin,yMax
-
-def computeBBox(aList,mat=[[1,0,0],[0,1,0]]):
- bbox=None
- for node in aList:
- m = parseTransform(node.get('transform'))
- m = composeTransform(mat,m)
- #TODO: text not supported!
- if node.get("d"):
- d = node.get('d')
- p = cubicsuperpath.parsePath(d)
- applyTransformToPath(m,p)
- bbox=boxunion(roughBBox(p),bbox)
-
- elif node.tag == inkex.addNS('rect','svg') or node.tag=='rect':
- w = float(node.get('width'))/2.
- h = float(node.get('height'))/2.
- x = float(node.get('x'))
- y = float(node.get('y'))
- C = [x + w , y + h ]
- applyTransformToPoint(mat,C)
- xmin = C[0] - abs(m[0][0]) * w - abs(m[0][1]) * h
- xmax = C[0] + abs(m[0][0]) * w + abs(m[0][1]) * h
- ymin = C[1] - abs(m[1][0]) * w - abs(m[1][1]) * h
- ymax = C[1] + abs(m[1][0]) * w + abs(m[1][1]) * h
- bbox = xmin,xmax,ymin,ymax
-
- elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
- refid=node.get(inkex.addNS('href','xlink'))
- path = '//*[@id="%s"]' % refid[1:]
- refnode = node.xpath(path)
- bbox=boxunion(computeBBox(refnode,m),bbox)
-
- bbox=boxunion(computeBBox(node,m),bbox)
- return bbox
-
-
+#!/usr/bin/env python +''' +Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +barraud@math.univ-lille1.fr + +This code defines several functions to make handling of transform +attribute easier. +''' +import inkex, cubicsuperpath, bezmisc, simplestyle +import copy, math, re + +def parseTransform(transf,mat=[[1.0,0.0,0.0],[0.0,1.0,0.0]]): + if transf=="" or transf==None: + return(mat) + result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\(([^)]*)\)",transf) +#-- translate -- + if result.group(1)=="translate": + args=result.group(2).split(",") + dx=float(args[0]) + if len(args)==1: + dy=0.0 + else: + dy=float(args[1]) + matrix=[[1,0,dx],[0,1,dy]] +#-- scale -- + if result.groups(1)=="scale": + args=result.group(2).split(",") + sx=float(args[0]) + if len(args)==1: + sy=sx + else: + sy=float(args[1]) + matrix=[[sx,0,0],[0,sy,0]] +#-- rotate -- + if result.groups(1)=="rotate": + args=result.group(2).split(",") + a=float(args[0])*math.pi/180 + if len(args)==1: + cx,cy=(0.0,0.0) + else: + cx,cy=args[1:] + matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]] +#-- skewX -- + if result.groups(1)=="skewX": + a=float(result.group(2))*math.pi/180 + matrix=[[1,math.tan(a),0],[0,1,0]] +#-- skewX -- + if result.groups(1)=="skewX": + a=float(result.group(2))*math.pi/180 + matrix=[[1,0,0],[math.tan(a),1,0]] +#-- matrix -- + if result.group(1)=="matrix": + a11,a21,a12,a22,v1,v2=result.group(2).split(",") + matrix=[[float(a11),float(a12),float(v1)],[float(a21),float(a22),float(v2)]] + + matrix=composeTransform(mat,matrix) + if result.end()<len(transf): + return(parseTransform(transf[result.end():],matrix)) + else: + return matrix + +def formatTransform(mat): + return("matrix(%f,%f,%f,%f,%f,%f)"%(mat[0][0],mat[1][0],mat[0][1],mat[1][1],mat[0][2],mat[1][2])) + +def composeTransform(M1,M2): + a11=M1[0][0]*M2[0][0]+M1[0][1]*M2[1][0] + a12=M1[0][0]*M2[0][1]+M1[0][1]*M2[1][1] + a21=M1[1][0]*M2[0][0]+M1[1][1]*M2[1][0] + a22=M1[1][0]*M2[0][1]+M1[1][1]*M2[1][1] + + v1=M1[0][0]*M2[0][2]+M1[0][1]*M2[1][2]+M1[0][2] + v2=M1[1][0]*M2[0][2]+M1[1][1]*M2[1][2]+M1[1][2] + return [[a11,a12,v1],[a21,a22,v2]] + +def applyTransformToNode(mat,node): + m=parseTransform(node.get("transform")) + newtransf=formatTransform(composeTransform(mat,m)) + node.set("transform", newtransf) + +def applyTransformToPoint(mat,pt): + x=mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2] + y=mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2] + pt[0]=x + pt[1]=y + +def applyTransformToPath(mat,path): + for comp in path: + for ctl in comp: + for pt in ctl: + applyTransformToPoint(mat,pt) + +def fuseTransform(node): + if node.get('d')==None: + #FIX ME: how do you raise errors? + raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute' + t = node.get("transform") + if t == None: + return + m = parseTransform(t) + d = node.get('d') + p = cubicsuperpath.parsePath(d) + applyTransformToPath(m,p) + node.set('d', cubicsuperpath.formatPath(p)) + del node.attrib["transform"] + +#################################################################### +##-- Some functions to compute a rough bbox of a given list of objects. +##-- this should be shipped out in an separate file... + +def boxunion(b1,b2): + if b1 is None: + return b2 + elif b2 is None: + return b1 + else: + return((min(b1[0],b2[0]),max(b1[1],b2[1]),min(b1[2],b2[2]),max(b1[3],b2[3]))) + +def roughBBox(path): + xmin,xMax,ymin,yMax=path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1] + for pathcomp in path: + for ctl in pathcomp: + for pt in ctl: + xmin=min(xmin,pt[0]) + xMax=max(xMax,pt[0]) + ymin=min(ymin,pt[1]) + yMax=max(yMax,pt[1]) + return xmin,xMax,ymin,yMax + +def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): + bbox=None + for node in aList: + m = parseTransform(node.get('transform')) + m = composeTransform(mat,m) + #TODO: text not supported! + if node.get("d"): + d = node.get('d') + p = cubicsuperpath.parsePath(d) + applyTransformToPath(m,p) + bbox=boxunion(roughBBox(p),bbox) + + elif node.tag == inkex.addNS('rect','svg') or node.tag=='rect': + w = float(node.get('width'))/2. + h = float(node.get('height'))/2. + x = float(node.get('x')) + y = float(node.get('y')) + C = [x + w , y + h ] + applyTransformToPoint(mat,C) + xmin = C[0] - abs(m[0][0]) * w - abs(m[0][1]) * h + xmax = C[0] + abs(m[0][0]) * w + abs(m[0][1]) * h + ymin = C[1] - abs(m[1][0]) * w - abs(m[1][1]) * h + ymax = C[1] + abs(m[1][0]) * w + abs(m[1][1]) * h + bbox = xmin,xmax,ymin,ymax + + elif node.tag == inkex.addNS('use','svg') or node.tag=='use': + refid=node.get(inkex.addNS('href','xlink')) + path = '//*[@id="%s"]' % refid[1:] + refnode = node.xpath(path) + bbox=boxunion(computeBBox(refnode,m),bbox) + + bbox=boxunion(computeBBox(node,m),bbox) + return bbox + + diff --git a/share/extensions/text_braille.py b/share/extensions/text_braille.py index 5de353827..3dcbbc6ac 100644 --- a/share/extensions/text_braille.py +++ b/share/extensions/text_braille.py @@ -1,5 +1,5 @@ #encoding: utf-8 -import chardataeffect, inkex, string
+import chardataeffect, inkex, string convert_table = {\ 'a': unicode("⠁", "utf-8"),\ @@ -30,16 +30,16 @@ convert_table = {\ 'z': unicode("⠵", "utf-8"),\ } -class C(chardataeffect.CharDataEffect):
-
- def process_chardata(self,text, line, par):
- r = ""
+class C(chardataeffect.CharDataEffect): + + def process_chardata(self,text, line, par): + r = "" for c in text: - if convert_table.has_key(c.lower()):
- r = r + convert_table[c.lower()]
- else:
- r = r + c
+ if convert_table.has_key(c.lower()): + r = r + convert_table[c.lower()] + else: + r = r + c return r -
-c = C()
-c.affect()
+ +c = C() +c.affect() diff --git a/share/extensions/text_flipcase.py b/share/extensions/text_flipcase.py index 4909b4f4a..167f7f89c 100644 --- a/share/extensions/text_flipcase.py +++ b/share/extensions/text_flipcase.py @@ -1,19 +1,19 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
-
- def process_chardata(self,text, line, par):
- r = ""
- for i in range(len(text)):
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + + def process_chardata(self,text, line, par): + r = "" + for i in range(len(text)): c = text[i] - if c.islower():
- r = r + c.upper()
- elif c.isupper():
- r = r + c.lower()
- else:
- r = r + c
-
- return r
-
-c = C()
-c.affect()
+ if c.islower(): + r = r + c.upper() + elif c.isupper(): + r = r + c.lower() + else: + r = r + c + + return r + +c = C() +c.affect() diff --git a/share/extensions/text_lowercase.py b/share/extensions/text_lowercase.py index 7dd04a208..96dcef3fc 100644 --- a/share/extensions/text_lowercase.py +++ b/share/extensions/text_lowercase.py @@ -1,8 +1,8 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
- def process_chardata(self,text, line=False, par=False):
- return text.lower()
-
-c = C()
-c.affect()
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + def process_chardata(self,text, line=False, par=False): + return text.lower() + +c = C() +c.affect() diff --git a/share/extensions/text_randomcase.py b/share/extensions/text_randomcase.py index 0961c594b..0200aef3d 100644 --- a/share/extensions/text_randomcase.py +++ b/share/extensions/text_randomcase.py @@ -1,27 +1,27 @@ -import chardataeffect, inkex, string
-
-import random
-
-class C(chardataeffect.CharDataEffect):
-
- def process_chardata(self,text, line, par):
- r = ""
- a = 1
- for i in range(len(text)):
- c = text[i]
+import chardataeffect, inkex, string + +import random + +class C(chardataeffect.CharDataEffect): + + def process_chardata(self,text, line, par): + r = "" + a = 1 + for i in range(len(text)): + c = text[i] # bias the randomness towards inversion of the previous case: if a > 0: - a = random.choice([-2,-1,1])
+ a = random.choice([-2,-1,1]) else: - a = random.choice([-1,1,2])
- if a > 0 and c.isalpha():
- r = r + c.upper()
- elif a < 0 and c.isalpha():
- r = r + c.lower()
- else:
- r = r + c
-
- return r
-
-c = C()
-c.affect()
+ a = random.choice([-1,1,2]) + if a > 0 and c.isalpha(): + r = r + c.upper() + elif a < 0 and c.isalpha(): + r = r + c.lower() + else: + r = r + c + + return r + +c = C() +c.affect() diff --git a/share/extensions/text_replace.py b/share/extensions/text_replace.py index 73b562743..0d6e501f5 100644 --- a/share/extensions/text_replace.py +++ b/share/extensions/text_replace.py @@ -1,16 +1,16 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
- def __init__(self):
- chardataeffect.CharDataEffect.__init__(self)
- self.OptionParser.add_option("-f", "--from_text", action="store", type="string", dest="from_text", default="", help="Replace")
- self.OptionParser.add_option("-t", "--to_text", action="store", type="string", dest="to_text", default="", help="by")
-
- def process_chardata(self,text, line, par):
- fr = self.options.from_text.strip('"').replace('\$','$')
- to = self.options.to_text.strip('"').replace('\$','$')
-
- return (text.replace(unicode(fr,"utf-8"), unicode(to,"utf-8")))
-
-c = C()
-c.affect()
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + def __init__(self): + chardataeffect.CharDataEffect.__init__(self) + self.OptionParser.add_option("-f", "--from_text", action="store", type="string", dest="from_text", default="", help="Replace") + self.OptionParser.add_option("-t", "--to_text", action="store", type="string", dest="to_text", default="", help="by") + + def process_chardata(self,text, line, par): + fr = self.options.from_text.strip('"').replace('\$','$') + to = self.options.to_text.strip('"').replace('\$','$') + + return (text.replace(unicode(fr,"utf-8"), unicode(to,"utf-8"))) + +c = C() +c.affect() diff --git a/share/extensions/text_sentencecase.py b/share/extensions/text_sentencecase.py index 9b29f7f84..c5929ceb0 100644 --- a/share/extensions/text_sentencecase.py +++ b/share/extensions/text_sentencecase.py @@ -1,37 +1,37 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
-
- sentence_start = True
- was_punctuation = False
-
- def process_chardata(self,text, line, par):
- r = ""
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + + sentence_start = True + was_punctuation = False + + def process_chardata(self,text, line, par): + r = "" #inkex.debug(text+str(line)+str(par)) - for c in text:
- if c == '.' or c == '!' or c == '?':
- self.was_punctuation = True
- elif ((c.isspace() or line == True) and self.was_punctuation) or par == True:
- self.sentence_start = True
- self.was_punctuation = False
- elif c == '"' or c == ')':
- pass
- else:
- self.was_punctuation = False
+ for c in text: + if c == '.' or c == '!' or c == '?': + self.was_punctuation = True + elif ((c.isspace() or line == True) and self.was_punctuation) or par == True: + self.sentence_start = True + self.was_punctuation = False + elif c == '"' or c == ')': + pass + else: + self.was_punctuation = False + + if not c.isspace(): + line = False + par = False + + if self.sentence_start and c.isalpha(): + r = r + c.upper() + self.sentence_start = False + elif not self.sentence_start and c.isalpha(): + r = r + c.lower() + else: + r = r + c + + return r - if not c.isspace():
- line = False
- par = False
-
- if self.sentence_start and c.isalpha():
- r = r + c.upper()
- self.sentence_start = False
- elif not self.sentence_start and c.isalpha():
- r = r + c.lower()
- else:
- r = r + c
-
- return r
-
-c = C()
-c.affect()
+c = C() +c.affect() diff --git a/share/extensions/text_titlecase.py b/share/extensions/text_titlecase.py index b6548b62b..2fd3c49c3 100644 --- a/share/extensions/text_titlecase.py +++ b/share/extensions/text_titlecase.py @@ -1,28 +1,28 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
-
- word_ended = True
-
- def process_chardata(self,text, line, par):
- r = ""
- for i in range(len(text)):
- c = text[i]
- if c.isspace() or line == True or par == True:
- self.word_ended = True
- if not c.isspace():
- line = False
- par = False
-
- if self.word_ended and c.isalpha():
- r = r + c.upper()
- self.word_ended = False
- elif c.isalpha():
- r = r + c.lower()
- else:
- r = r + c
-
- return r
-
-c = C()
-c.affect()
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + + word_ended = True + + def process_chardata(self,text, line, par): + r = "" + for i in range(len(text)): + c = text[i] + if c.isspace() or line == True or par == True: + self.word_ended = True + if not c.isspace(): + line = False + par = False + + if self.word_ended and c.isalpha(): + r = r + c.upper() + self.word_ended = False + elif c.isalpha(): + r = r + c.lower() + else: + r = r + c + + return r + +c = C() +c.affect() diff --git a/share/extensions/text_uppercase.py b/share/extensions/text_uppercase.py index 8e894ed81..f5a51945d 100644 --- a/share/extensions/text_uppercase.py +++ b/share/extensions/text_uppercase.py @@ -1,8 +1,8 @@ -import chardataeffect, inkex, string
-
-class C(chardataeffect.CharDataEffect):
- def process_chardata(self,text, line=False, par=False):
- return text.upper()
-
-c = C()
-c.affect()
+import chardataeffect, inkex, string + +class C(chardataeffect.CharDataEffect): + def process_chardata(self,text, line=False, par=False): + return text.upper() + +c = C() +c.affect() diff --git a/share/palettes/PaletteGen.py b/share/palettes/PaletteGen.py index 69c952bfc..de7cb2e65 100644 --- a/share/palettes/PaletteGen.py +++ b/share/palettes/PaletteGen.py @@ -1,91 +1,91 @@ -import colorsys
-
-print '''GIMP Palette
-Name: Inkscape default
-Columns: 3
-# generated by PaletteGen.py'''
-
-
-# grays
-
-g_steps = 10
-g_step_size = 1.0 / g_steps
-
-for i in range(0, g_steps + 1):
- level = i * g_step_size
- r, g, b = colorsys.hls_to_rgb(0, level, 0)
-
- rval = int(round(r * 255))
- gval = int(round(g * 255))
- bval = int(round(b * 255))
-
- if i == 0:
- line = "%3s %3s %3s Black" % (rval, gval, bval)
- elif i == g_steps:
- line = "%3s %3s %3s White" % (rval, gval, bval)
- else:
- line = "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - int(level * 100))
- print line
-
- # add three more steps near white
- if i == g_steps - 1:
- level_m = level + 0.25 * g_step_size
- r, g, b = colorsys.hls_to_rgb(0, level_m, 0)
- rval = int(round(r * 255))
- gval = int(round(g * 255))
- bval = int(round(b * 255))
- print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - (level_m * 100))
-
- level_m = level + 0.5 * g_step_size
- r, g, b = colorsys.hls_to_rgb(0, level_m, 0)
- rval = int(round(r * 255))
- gval = int(round(g * 255))
- bval = int(round(b * 255))
- print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - int(level_m * 100))
-
- level_mm = level + 0.75 * g_step_size
- r, g, b = colorsys.hls_to_rgb(0, level_mm, 0)
- rval = int(round(r * 255))
- gval = int(round(g * 255))
- bval = int(round(b * 255))
- print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - (level_mm * 100))
-
-
-# standard HTML colors
-print '''128 0 0 Maroon (#800000)
-255 0 0 Red (#FF0000)
-128 128 0 Olive (#808000)
-255 255 0 Yellow (#FFFF00)
- 0 128 0 Green (#008000)
- 0 255 0 Lime (#00FF00)
- 0 128 128 Teal (#008080)
- 0 255 255 Aqua (#00FFFF)
- 0 0 128 Navy (#000080)
- 0 0 255 Blue (#0000FF)
-128 0 128 Purple (#800080)
-255 0 255 Fuchsia (#FF00FF)'''
-
-# HSL palette
-h_steps = 15
-s_steps = 3
-l_steps = 14
-h_step_size = 1.0 / h_steps
-s_step_size = 1.3 / s_steps
-
-for h in range(0, h_steps):
- for s in range(0, s_steps):
- l_range = int(round(l_steps - (s*6/s_steps))) - 2
- l_step_size = 1.0 / l_range
- for l in range(1, l_range):
- hval = h * h_step_size
- sval = 1 - (s * s_step_size)
- lval = l * l_step_size
-
- r, g, b = colorsys.hls_to_rgb(hval, lval, sval)
-
- rval = int(round(r * 255))
- gval = int(round(g * 255))
- bval = int(round(b * 255))
-
- line = "%3s %3s %3s #%02X%02X%02X" % (rval, gval, bval, rval, gval, bval)
- print line
+import colorsys + +print '''GIMP Palette +Name: Inkscape default +Columns: 3 +# generated by PaletteGen.py''' + + +# grays + +g_steps = 10 +g_step_size = 1.0 / g_steps + +for i in range(0, g_steps + 1): + level = i * g_step_size + r, g, b = colorsys.hls_to_rgb(0, level, 0) + + rval = int(round(r * 255)) + gval = int(round(g * 255)) + bval = int(round(b * 255)) + + if i == 0: + line = "%3s %3s %3s Black" % (rval, gval, bval) + elif i == g_steps: + line = "%3s %3s %3s White" % (rval, gval, bval) + else: + line = "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - int(level * 100)) + print line + + # add three more steps near white + if i == g_steps - 1: + level_m = level + 0.25 * g_step_size + r, g, b = colorsys.hls_to_rgb(0, level_m, 0) + rval = int(round(r * 255)) + gval = int(round(g * 255)) + bval = int(round(b * 255)) + print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - (level_m * 100)) + + level_m = level + 0.5 * g_step_size + r, g, b = colorsys.hls_to_rgb(0, level_m, 0) + rval = int(round(r * 255)) + gval = int(round(g * 255)) + bval = int(round(b * 255)) + print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - int(level_m * 100)) + + level_mm = level + 0.75 * g_step_size + r, g, b = colorsys.hls_to_rgb(0, level_mm, 0) + rval = int(round(r * 255)) + gval = int(round(g * 255)) + bval = int(round(b * 255)) + print "%3s %3s %3s %s%% Gray" % (rval, gval, bval, 100 - (level_mm * 100)) + + +# standard HTML colors +print '''128 0 0 Maroon (#800000) +255 0 0 Red (#FF0000) +128 128 0 Olive (#808000) +255 255 0 Yellow (#FFFF00) + 0 128 0 Green (#008000) + 0 255 0 Lime (#00FF00) + 0 128 128 Teal (#008080) + 0 255 255 Aqua (#00FFFF) + 0 0 128 Navy (#000080) + 0 0 255 Blue (#0000FF) +128 0 128 Purple (#800080) +255 0 255 Fuchsia (#FF00FF)''' + +# HSL palette +h_steps = 15 +s_steps = 3 +l_steps = 14 +h_step_size = 1.0 / h_steps +s_step_size = 1.3 / s_steps + +for h in range(0, h_steps): + for s in range(0, s_steps): + l_range = int(round(l_steps - (s*6/s_steps))) - 2 + l_step_size = 1.0 / l_range + for l in range(1, l_range): + hval = h * h_step_size + sval = 1 - (s * s_step_size) + lval = l * l_step_size + + r, g, b = colorsys.hls_to_rgb(hval, lval, sval) + + rval = int(round(r * 255)) + gval = int(round(g * 255)) + bval = int(round(b * 255)) + + line = "%3s %3s %3s #%02X%02X%02X" % (rval, gval, bval, rval, gval, bval) + print line |
