Code

added Restack extension from Rob Antonishen
authorprokoudine <prokoudine@users.sourceforge.net>
Thu, 17 Apr 2008 15:18:50 +0000 (15:18 +0000)
committerprokoudine <prokoudine@users.sourceforge.net>
Thu, 17 Apr 2008 15:18:50 +0000 (15:18 +0000)
po/POTFILES.in
share/extensions/Makefile.am
share/extensions/restack.inx [new file with mode: 0644]
share/extensions/restack.py [new file with mode: 0644]

index 70b9cff4a98c08f214ff647dc3ad01a8a7b5f070..9952e1054eae5a04f7b0bc0f43528f55c41a706e 100644 (file)
@@ -352,6 +352,7 @@ src/winmain.cpp
 [type: gettext/xml] share/extensions/randompnt.inx
 [type: gettext/xml] share/extensions/randompos.inx
 [type: gettext/xml] share/extensions/render_barcode.inx
+[type: gettext/xml] share/extensions/restack.inx
 [type: gettext/xml] share/extensions/rtree.inx
 [type: gettext/xml] share/extensions/rubberstretch.inx
 [type: gettext/xml] share/extensions/sk_input.inx
index de8d5369a4427ddc632689936854d7e96bc85b7a..e17f6558834609c347de13138f1b893cff8b2548 100644 (file)
@@ -78,6 +78,7 @@ extensions = \
        ps2pdf.sh \
        pturtle.py \
        radiusrand.py \
+       restack.py \
        render_barcode.py \
        render_alphabetsoup.py \
        render_alphabetsoup_config.py \
@@ -186,6 +187,7 @@ modules = \
        randompos.inx \
        render_barcode.inx \
        render_alphabetsoup.inx \
+       restack.inx \
        rubberstretch.inx \
        rtree.inx \
        sk_input.inx \
diff --git a/share/extensions/restack.inx b/share/extensions/restack.inx
new file mode 100644 (file)
index 0000000..de87397
--- /dev/null
@@ -0,0 +1,35 @@
+<inkscape-extension>
+    <_name>Restack</_name>
+    <id>org.inkscape.filter.restack</id>
+       <dependency type="executable" location="extensions">restack.py</dependency>
+       <dependency type="executable" location="extensions">inkex.py</dependency>
+    <param name="direction" type="optiongroup" _gui-text="Restack Direction:">
+        <_option value="lr">Left to Right (0)</_option>
+        <_option value="bt">Bottom to Top (90)</_option>
+        <_option value="rl">Right to Left (180)</_option>
+        <_option value="tb">Top to Bottom (270)</_option>
+        <_option value="ro">Radial Outward</_option>
+        <_option value="ri">Radial Inward</_option>
+       <_option value="aa">Arbitrary Angle:</_option>
+    </param>
+       <param name="angle" type="float" min="0.0" max="360.0" _gui-text="Angle">0.00</param>
+    <param name="xanchor" type="optiongroup" _gui-text="Horizontal Point:">
+        <_option value="l">Left</_option>
+        <_option value="m">Middle</_option>
+        <_option value="r">Right</_option>
+    </param>
+    <param name="yanchor" type="optiongroup" _gui-text="Vertical Point:">
+        <_option value="t">Top</_option>
+        <_option value="m">Middle</_option>
+        <_option value="b">Bottom</_option>
+    </param>
+    <effect>
+       <object-type>path</object-type>
+       <effects-menu>
+               <submenu _name="Modify Path"/>
+       </effects-menu>
+       </effect>
+    <script>
+        <command reldir="extensions" interpreter="python">restack.py</command>
+    </script>
+</inkscape-extension>
diff --git a/share/extensions/restack.py b/share/extensions/restack.py
new file mode 100644 (file)
index 0000000..8623bb1
--- /dev/null
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+"""
+Copyright (C) 2007,2008 Rob Antonishen; rob.antonishen@gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+"""
+import inkex, os, csv, math
+
+class Restack(inkex.Effect):
+    def __init__(self):
+        inkex.Effect.__init__(self)
+        self.OptionParser.add_option("-d", "--direction",
+                        action="store", type="string", 
+                        dest="direction", default="tb",
+                        help="direction to restack")
+        self.OptionParser.add_option("-a", "--angle",
+                        action="store", type="float", 
+                        dest="angle", default=0.0,
+                        help="arbitrary angle")
+        self.OptionParser.add_option("-x", "--xanchor",
+                        action="store", type="string", 
+                        dest="xanchor", default="m",
+                        help="horizontal point to compare")
+        self.OptionParser.add_option("-y", "--yanchor",
+                        action="store", type="string", 
+                        dest="yanchor", default="m",
+                        help="vertical point to compare")
+    def effect(self):
+        if len( self.selected ) > 0:
+            objlist = []
+            svg = self.document.getroot()
+
+            file = self.args[ -1 ]
+            #get all bounding boxes in file by calling inkscape again with the --querry-all command line option
+                       #it returns a comma seperated list structured id,x,y,w,h
+            _,f,err = os.popen3( "inkscape --query-all %s" % ( file ) )
+            reader=csv.reader( f.readlines() )
+            f.close()
+            err.close()
+                       
+            #build a dictionary with id as the key
+            dimen = dict()
+            for line in reader:
+                dimen[line[0]] = map( float, line[1:])
+                               
+                       #find the center of all selected objects **Not the average!     
+            x,y,w,h = dimen[self.selected.keys()[0]]
+            minx = x
+            miny = y
+            maxx = x + w
+            maxy = y + h
+                       
+            for id, node in self.selected.iteritems():
+                # get the bounding box
+                x,y,w,h = dimen[id]
+                if x < minx:
+                    minx = x
+                if (x + w) > maxx:
+                    maxx = x + w
+                if y < miny:
+                    miny = y
+                if (y + h) > maxy:
+                    maxy = y + h                               
+
+            midx = (minx + maxx) / 2
+            midy = (miny + maxy) / 2
+                       
+            #calculate distances fro each selected object
+            for id, node in self.selected.iteritems():
+                # get the bounding box
+                x,y,w,h = dimen[id]
+                
+                # calc the comparison coords
+                if self.options.xanchor == "l":
+                    cx = x
+                elif self.options.xanchor == "r":
+                    cx = x + w
+                else:  # middle
+                    cx = x + w / 2
+
+                if self.options.yanchor == "t":
+                    cy = y
+                elif self.options.yanchor == "b":
+                    cy = y + h
+                else:  # middle
+                    cy = y + h / 2
+                               
+                #direction chosen
+                if self.options.direction == "tb" or self.options.angle == 270:
+                           objlist.append([cy,id])
+                elif self.options.direction == "bt" or self.options.angle == 90:
+                           objlist.append([-cy,id])
+                elif self.options.direction == "lr" or self.options.angle == 0 or self.options.angle == 360:
+                           objlist.append([cx,id])
+                elif self.options.direction == "rl" or self.options.angle == 180:
+                           objlist.append([-cx,id])                    
+                elif self.options.direction == "aa":
+                    distance = math.hypot(cx,cy)*(math.cos(math.radians(-self.options.angle)-math.atan2(cy, cx)))
+                           objlist.append([distance,id])
+                elif self.options.direction == "ro":
+                    distance = math.hypot(midx - cx, midy - cy)
+                           objlist.append([distance,id])
+                elif self.options.direction == "ri":
+                    distance = -math.hypot(midx - cx, midy - cy)
+                           objlist.append([distance,id])
+
+            objlist.sort()
+            #move them to the top of the object stack in this order.
+            for item in objlist:
+                svg.append( self.selected[item[1]])
+
+e = Restack()
+e.affect()