9274e24cf014e4d132518578c221b04c60974d63JazzyNico#!/usr/bin/env python
9274e24cf014e4d132518578c221b04c60974d63JazzyNico"""
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoCopyright (C) 2011 Nicolas Dufour (jazzynico)
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoDirection code from the Restack extension, by Rob Antonishen
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoPermission is hereby granted, free of charge, to any person obtaining a copy
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoof this software and associated documentation files (the "Software"), to deal
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoin the Software without restriction, including without limitation the rights
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9274e24cf014e4d132518578c221b04c60974d63JazzyNicocopies of the Software, and to permit persons to whom the Software is
9274e24cf014e4d132518578c221b04c60974d63JazzyNicofurnished to do so, subject to the following conditions:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoThe above copyright notice and this permission notice shall be included in
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoall copies or substantial portions of the Software.
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoTHE SOFTWARE.
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico"""
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico# standard library
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport chardataeffect
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicofrom copy import deepcopy
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport csv
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport math
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport os
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport string
9274e24cf014e4d132518578c221b04c60974d63JazzyNicotry:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico from subprocess import Popen, PIPE
9274e24cf014e4d132518578c221b04c60974d63JazzyNico bsubprocess = True
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoexcept:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico bsubprocess = False
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico# local library
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNicoimport inkex
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoclass Extract(inkex.Effect):
9274e24cf014e4d132518578c221b04c60974d63JazzyNico def __init__(self):
9274e24cf014e4d132518578c221b04c60974d63JazzyNico inkex.Effect.__init__(self)
9274e24cf014e4d132518578c221b04c60974d63JazzyNico self.OptionParser.add_option("-d", "--direction",
629aea629b26536692b4cb4a2adebecfd59c6193bryce action="store", type="string",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico dest="direction", default="tb",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico help="direction to extract text")
9274e24cf014e4d132518578c221b04c60974d63JazzyNico self.OptionParser.add_option("-x", "--xanchor",
629aea629b26536692b4cb4a2adebecfd59c6193bryce action="store", type="string",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico dest="xanchor", default="m",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico help="horizontal point to compare")
9274e24cf014e4d132518578c221b04c60974d63JazzyNico self.OptionParser.add_option("-y", "--yanchor",
629aea629b26536692b4cb4a2adebecfd59c6193bryce action="store", type="string",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico dest="yanchor", default="m",
9274e24cf014e4d132518578c221b04c60974d63JazzyNico help="vertical point to compare")
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico def effect(self):
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if len(self.selected)==0:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico for node in self.document.xpath('//svg:text | //svg:flowRoot', namespaces=inkex.NSS):
9274e24cf014e4d132518578c221b04c60974d63JazzyNico self.selected[node.get('id')] = node
629aea629b26536692b4cb4a2adebecfd59c6193bryce
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if len( self.selected ) > 0:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist = []
9274e24cf014e4d132518578c221b04c60974d63JazzyNico svg = self.document.getroot()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico parentnode = self.current_layer
9274e24cf014e4d132518578c221b04c60974d63JazzyNico file = self.args[ -1 ]
629aea629b26536692b4cb4a2adebecfd59c6193bryce
629aea629b26536692b4cb4a2adebecfd59c6193bryce # get all bounding boxes in file by calling inkscape again with the --query-all command line option
629aea629b26536692b4cb4a2adebecfd59c6193bryce # it returns a comma separated list structured id,x,y,w,h
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if bsubprocess:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE)
9274e24cf014e4d132518578c221b04c60974d63JazzyNico err = p.stderr
9274e24cf014e4d132518578c221b04c60974d63JazzyNico f = p.communicate()[0]
9274e24cf014e4d132518578c221b04c60974d63JazzyNico try:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico reader=csv.CSVParser().parse_string(f) #there was a module cvs.py in earlier inkscape that behaved differently
9274e24cf014e4d132518578c221b04c60974d63JazzyNico except:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico reader=csv.reader(f.split( os.linesep ))
629aea629b26536692b4cb4a2adebecfd59c6193bryce err.close()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico else:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico _,f,err = os.popen3('inkscape --query-all "%s"' % ( file ) )
9274e24cf014e4d132518578c221b04c60974d63JazzyNico reader=csv.reader( f )
9274e24cf014e4d132518578c221b04c60974d63JazzyNico err.close()
629aea629b26536692b4cb4a2adebecfd59c6193bryce
9274e24cf014e4d132518578c221b04c60974d63JazzyNico #build a dictionary with id as the key
9274e24cf014e4d132518578c221b04c60974d63JazzyNico dimen = dict()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico for line in reader:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if len(line) > 0:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico dimen[line[0]] = map( float, line[1:])
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if not bsubprocess: #close file if opened using os.popen3
9274e24cf014e4d132518578c221b04c60974d63JazzyNico f.close
629aea629b26536692b4cb4a2adebecfd59c6193bryce
9274e24cf014e4d132518578c221b04c60974d63JazzyNico #find the center of all selected objects **Not the average!
9274e24cf014e4d132518578c221b04c60974d63JazzyNico x,y,w,h = dimen[self.selected.keys()[0]]
9274e24cf014e4d132518578c221b04c60974d63JazzyNico minx = x
9274e24cf014e4d132518578c221b04c60974d63JazzyNico miny = y
9274e24cf014e4d132518578c221b04c60974d63JazzyNico maxx = x + w
9274e24cf014e4d132518578c221b04c60974d63JazzyNico maxy = y + h
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico for id, node in self.selected.iteritems():
9274e24cf014e4d132518578c221b04c60974d63JazzyNico # get the bounding box
9274e24cf014e4d132518578c221b04c60974d63JazzyNico x,y,w,h = dimen[id]
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if x < minx:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico minx = x
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if (x + w) > maxx:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico maxx = x + w
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if y < miny:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico miny = y
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if (y + h) > maxy:
9274e24cf014e4d132518578c221b04c60974d63JazzyNico maxy = y + h
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico midx = (minx + maxx) / 2
9274e24cf014e4d132518578c221b04c60974d63JazzyNico midy = (miny + maxy) / 2
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico #calculate distances for each selected object
9274e24cf014e4d132518578c221b04c60974d63JazzyNico for id, node in self.selected.iteritems():
9274e24cf014e4d132518578c221b04c60974d63JazzyNico # get the bounding box
9274e24cf014e4d132518578c221b04c60974d63JazzyNico x,y,w,h = dimen[id]
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico # calc the comparison coords
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if self.options.xanchor == "l":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cx = x
9274e24cf014e4d132518578c221b04c60974d63JazzyNico elif self.options.xanchor == "r":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cx = x + w
9274e24cf014e4d132518578c221b04c60974d63JazzyNico else: # middle
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cx = x + w / 2
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if self.options.yanchor == "t":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cy = y
9274e24cf014e4d132518578c221b04c60974d63JazzyNico elif self.options.yanchor == "b":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cy = y + h
9274e24cf014e4d132518578c221b04c60974d63JazzyNico else: # middle
9274e24cf014e4d132518578c221b04c60974d63JazzyNico cy = y + h / 2
629aea629b26536692b4cb4a2adebecfd59c6193bryce
9274e24cf014e4d132518578c221b04c60974d63JazzyNico #direction chosen
9274e24cf014e4d132518578c221b04c60974d63JazzyNico if self.options.direction == "tb":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist.append([cy,id])
9274e24cf014e4d132518578c221b04c60974d63JazzyNico elif self.options.direction == "bt":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist.append([-cy,id])
9274e24cf014e4d132518578c221b04c60974d63JazzyNico elif self.options.direction == "lr":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist.append([cx,id])
9274e24cf014e4d132518578c221b04c60974d63JazzyNico elif self.options.direction == "rl":
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist.append([-cx,id])
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico objlist.sort()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico #move them to the top of the object stack in this order.
9274e24cf014e4d132518578c221b04c60974d63JazzyNico for item in objlist:
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico self.recurse(deepcopy(self.selected[item[1]]))
629aea629b26536692b4cb4a2adebecfd59c6193bryce
9274e24cf014e4d132518578c221b04c60974d63JazzyNico def recurse(self, node):
9274e24cf014e4d132518578c221b04c60974d63JazzyNico 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')
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico if node.text != None or node.tail != None:
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico for child in node:
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico if child.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role'):
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico child.tail = "\n"
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico inkex.errormsg(inkex.etree.tostring(node, method='text').strip())
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico else:
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico for child in node:
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico self.recurse(child)
13f50632425a012e0bd5a7b31015c7895f5d1375JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
9274e24cf014e4d132518578c221b04c60974d63JazzyNicoif __name__ == '__main__':
9274e24cf014e4d132518578c221b04c60974d63JazzyNico e = Extract()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico e.affect()
9274e24cf014e4d132518578c221b04c60974d63JazzyNico
76afb6b15a6b74cb64d169e0afac83c6915e9dc8~suv# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99