Code

svn propset svn:eol-style native *.py
authorpjrm <pjrm@users.sourceforge.net>
Sat, 29 Mar 2008 10:21:03 +0000 (10:21 +0000)
committerpjrm <pjrm@users.sourceforge.net>
Sat, 29 Mar 2008 10:21:03 +0000 (10:21 +0000)
44 files changed:
share/extensions/Barcode/Base.py
share/extensions/chardataeffect.py
share/extensions/color_brighter.py
share/extensions/color_custom.py
share/extensions/color_darker.py
share/extensions/color_desaturate.py
share/extensions/color_grayscale.py
share/extensions/color_lesshue.py
share/extensions/color_lesslight.py
share/extensions/color_lesssaturation.py
share/extensions/color_morehue.py
share/extensions/color_morelight.py
share/extensions/color_moresaturation.py
share/extensions/color_negative.py
share/extensions/color_randomize.py
share/extensions/color_removeblue.py
share/extensions/color_removegreen.py
share/extensions/color_removered.py
share/extensions/color_replace.py
share/extensions/color_rgbbarrel.py
share/extensions/coloreffect.py
share/extensions/dxf_templates.py
share/extensions/edge3d.py
share/extensions/export_gimp_palette.py
share/extensions/fractalize.py
share/extensions/funcplot.py
share/extensions/gears.py
share/extensions/lorem_ipsum.py
share/extensions/markers_strokepaint.py
share/extensions/measure.py
share/extensions/pathalongpath.py
share/extensions/pathmodifier.py
share/extensions/pathscatter.py
share/extensions/rubberstretch.py
share/extensions/simpletransform.py
share/extensions/text_braille.py
share/extensions/text_flipcase.py
share/extensions/text_lowercase.py
share/extensions/text_randomcase.py
share/extensions/text_replace.py
share/extensions/text_sentencecase.py
share/extensions/text_titlecase.py
share/extensions/text_uppercase.py
share/palettes/PaletteGen.py

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