diff options
| author | Nicolas Dufour <nicoduf@yahoo.fr> | 2013-08-22 12:41:57 +0000 |
|---|---|---|
| committer | JazzyNico <nicoduf@yahoo.fr> | 2013-08-22 12:41:57 +0000 |
| commit | bc74e6961282b6b6f089ad1faa1a2390a0987c1f (patch) | |
| tree | 867417aed1f6e392e20b0910edbc6db5175e2ad7 /share | |
| parent | Fix make check on OS X (diff) | |
| download | inkscape-bc74e6961282b6b6f089ad1faa1a2390a0987c1f.tar.gz inkscape-bc74e6961282b6b6f089ad1faa1a2390a0987c1f.zip | |
New merge text extension (see Bug #960046).
Fixed bugs:
- https://launchpad.net/bugs/960046
(bzr r12484)
Diffstat (limited to 'share')
| -rw-r--r-- | share/extensions/Makefile.am | 2 | ||||
| -rw-r--r-- | share/extensions/text_merge.inx | 34 | ||||
| -rw-r--r-- | share/extensions/text_merge.py | 199 |
3 files changed, 235 insertions, 0 deletions
diff --git a/share/extensions/Makefile.am b/share/extensions/Makefile.am index d9597b33f..b63356a8f 100644 --- a/share/extensions/Makefile.am +++ b/share/extensions/Makefile.am @@ -166,6 +166,7 @@ extensions = \ text_flipcase.py \ text_randomcase.py \ text_braille.py \ + text_merge.py \ triangle.py \ txt2svg.pl \ uniconv-ext.py \ @@ -348,6 +349,7 @@ modules = \ text_flipcase.inx \ text_randomcase.inx \ text_braille.inx \ + text_merge.inx \ triangle.inx \ txt2svg.inx \ voronoi2svg.inx \ diff --git a/share/extensions/text_merge.inx b/share/extensions/text_merge.inx new file mode 100644 index 000000000..c871f52c0 --- /dev/null +++ b/share/extensions/text_merge.inx @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>Merge</_name> + <id>org.inkscape.text.merge</id> + <dependency type="executable" location="extensions">text_merge.py</dependency> + <dependency type="executable" location="extensions">inkex.py</dependency> + <param name="direction" type="enum" _gui-text="Text direction:"> + <_item value="lr">Left to right</_item> + <_item value="bt">Bottom to top</_item> + <_item value="rl">Right to left</_item> + <_item value="tb">Top to bottom</_item> + </param> + <param name="xanchor" type="enum" _gui-text="Horizontal point:"> + <_item value="l">Left</_item> + <_item value="m">Middle</_item> + <_item value="r">Right</_item> + </param> + <param name="yanchor" type="enum" _gui-text="Vertical point:"> + <_item value="t">Top</_item> + <_item value="m">Middle</_item> + <_item value="b">Bottom</_item> + </param> + <param name="flowtext" type="boolean" _gui-text="Flow text">false</param> + <param name="keepstyle" type="boolean" _gui-text="Keep style">true</param> + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Text"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">text_merge.py</command> + </script> +</inkscape-extension> diff --git a/share/extensions/text_merge.py b/share/extensions/text_merge.py new file mode 100644 index 000000000..8cd8b751d --- /dev/null +++ b/share/extensions/text_merge.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python +""" +Copyright (C) 2013 Nicolas Dufour (jazzynico) +Direction code from the Restack extension, by Rob Antonishen + +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. + +""" +# standard library +import chardataeffect +import copy +import csv +import math +import os +import string +try: + from subprocess import Popen, PIPE + bsubprocess = True +except: + bsubprocess = False +# local library +import inkex + + +class Merge(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 merge text") + 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") + self.OptionParser.add_option("-t", "--flowtext", + action="store", type="inkbool", + dest="flowtext", default=False, + help="use a flow text structure instead of a normal text element") + self.OptionParser.add_option("-k", "--keepstyle", + action="store", type="inkbool", + dest="keepstyle", default=False, + help="keep format") + + def effect(self): + if len(self.selected)==0: + for node in self.document.xpath('//svg:text | //svg:flowRoot', namespaces=inkex.NSS): + self.selected[node.get('id')] = node + + if len( self.selected ) > 0: + objlist = [] + svg = self.document.getroot() + parentnode = self.current_layer + file = self.args[ -1 ] + + #get all bounding boxes in file by calling inkscape again with the --query-all command line option + #it returns a comma seperated list structured id,x,y,w,h + if bsubprocess: + p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) + err = p.stderr + f = p.communicate()[0] + try: + reader=csv.CSVParser().parse_string(f) #there was a module cvs.py in earlier inkscape that behaved differently + except: + reader=csv.reader(f.split( os.linesep )) + err.close() + else: + _,f,err = os.popen3('inkscape --query-all "%s"' % ( file ) ) + reader=csv.reader( f ) + err.close() + + #build a dictionary with id as the key + dimen = dict() + for line in reader: + if len(line) > 0: + dimen[line[0]] = map( float, line[1:]) + + if not bsubprocess: #close file if opened using os.popen3 + f.close + + #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 for 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": + objlist.append([cy,id]) + elif self.options.direction == "bt": + objlist.append([-cy,id]) + elif self.options.direction == "lr": + objlist.append([cx,id]) + elif self.options.direction == "rl": + objlist.append([-cx,id]) + + objlist.sort() + #move them to the top of the object stack in this order. + + if self.options.flowtext: + self.text_element = "flowRoot" + self.text_span = "flowPara" + else: + self.text_element = "text" + self.text_span = "tspan" + + self.textRoot=inkex.etree.SubElement(parentnode,inkex.addNS(self.text_element,'svg'),{inkex.addNS('space','xml'):'preserve'}) + self.textRoot.set(inkex.addNS('style', ''), 'font-size:20px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;') + + for item in objlist: + self.recurse(self.selected[item[1]], self.textRoot) + + if self.options.flowtext: + self.region=inkex.etree.SubElement(self.textRoot,inkex.addNS('flowRegion','svg'),{inkex.addNS('space','xml'):'preserve'}) + self.rect=inkex.etree.SubElement(self.region,inkex.addNS('rect','svg'),{inkex.addNS('space','xml'):'preserve'}) + self.rect.set(inkex.addNS('height', ''), '200') + self.rect.set(inkex.addNS('width', ''), '200') + + def recurse(self, node, span): + #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}tspan') + if node.tag != '{http://www.w3.org/2000/svg}flowRegion': + + newspan=inkex.etree.SubElement(span,inkex.addNS(self.text_span,'svg'),{inkex.addNS('space','xml'):'preserve'}) + + if node.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role'): + newspan.set(inkex.addNS('role', 'sodipodi'), node.get('{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}role')) + if (node.tag == '{http://www.w3.org/2000/svg}text' or node.tag == '{http://www.w3.org/2000/svg}flowPara'): + newspan.set(inkex.addNS('role', 'sodipodi'), 'line') + + if self.options.keepstyle: + if node.get('style'): + newspan.set(inkex.addNS('style', ''), node.get('style')) + + if node.text != None: + newspan.text = node.text + for child in node: + self.recurse(child, newspan) + +if __name__ == '__main__': + e = Merge() + e.affect() + +# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99 |
