From 20e9b1f7cd4a3104e934c17ed5536a259054ad84 Mon Sep 17 00:00:00 2001 From: JazzyNico Date: Tue, 20 Apr 2010 18:14:27 +0200 Subject: [PATCH] Extensions. New text split extension (Bug #171748). --- po/POTFILES.in | 2 + share/extensions/Makefile.am | 2 + share/extensions/split.inx | 22 ++++ share/extensions/split.py | 215 +++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+) create mode 100644 share/extensions/split.inx create mode 100644 share/extensions/split.py diff --git a/po/POTFILES.in b/po/POTFILES.in index 285f3387a..7d92910e8 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -96,6 +96,7 @@ [type: gettext/xml] share/extensions/sk1_output.inx [type: gettext/xml] share/extensions/sk_input.inx [type: gettext/xml] share/extensions/spirograph.inx +[type: gettext/xml] share/extensions/split.inx [type: gettext/xml] share/extensions/straightseg.inx [type: gettext/xml] share/extensions/summersnight.inx [type: gettext/xml] share/extensions/svg2xaml.inx @@ -533,6 +534,7 @@ share/extensions/web-transmit-att.py [type: gettext/xml] share/extensions/sk1_output.inx [type: gettext/xml] share/extensions/sk_input.inx [type: gettext/xml] share/extensions/spirograph.inx +[type: gettext/xml] share/extensions/split.inx [type: gettext/xml] share/extensions/straightseg.inx [type: gettext/xml] share/extensions/summersnight.inx [type: gettext/xml] share/extensions/svg2xaml.inx diff --git a/share/extensions/Makefile.am b/share/extensions/Makefile.am index b5bf8cd33..7327ffbd5 100644 --- a/share/extensions/Makefile.am +++ b/share/extensions/Makefile.am @@ -115,6 +115,7 @@ extensions = \ sk2svg.sh \ SpSVG.pm \ spirograph.py\ + split.py \ straightseg.py \ summersnight.py \ svgcalendar.py \ @@ -245,6 +246,7 @@ modules = \ sk1_input.inx \ sk1_output.inx \ spirograph.inx \ + split.inx \ straightseg.inx \ summersnight.inx \ svg2xaml.inx \ diff --git a/share/extensions/split.inx b/share/extensions/split.inx new file mode 100644 index 000000000..0f8cea0ce --- /dev/null +++ b/share/extensions/split.inx @@ -0,0 +1,22 @@ + + <_name>Split text + com.nerdson.split + split.py + inkex.py + This effect splits texts into different lines, words or letters. Select below how your text should be splitted. + + Lines + Words + Letters + + true + + text + + + + + + diff --git a/share/extensions/split.py b/share/extensions/split.py new file mode 100644 index 000000000..5e9de002b --- /dev/null +++ b/share/extensions/split.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python +''' +Copyright (C) 2009 Karlisson Bezerra, contato@nerdson.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 +''' + +import inkex + +class Split(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("-s", "--splittype", + action="store", type="string", + dest="split_type", default="word", + help="type of split") + self.OptionParser.add_option("-p", "--preserve", + action="store", type="inkbool", + dest="preserve", default="True", + help="Preserve original") + + + def split_lines(self, node): + """Returns a list of lines""" + + lines = [] + count = 1 + + for n in node: + if not (n.tag == inkex.addNS("flowPara", "svg") or n.tag == inkex.addNS("tspan", "svg")): + if n.tag == inkex.addNS("textPath", "svg"): + inkex.debug("This type of text element isn't supported. First remove text from path.") + break + else: + continue + + text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib) + + #handling flowed text nodes + if node.tag == inkex.addNS("flowRoot", "svg"): + try: + from simplestyle import parseStyle + fontsize = parseStyle(node.get("style"))["font-size"] + except: + fontsize = "12px" + fs = inkex.unittouu(fontsize) + + #selects the flowRegion's child (svg:rect) to get @X and @Y + id = node.get("id") + flowref = self.xpathSingle('/svg:svg//*[@id="%s"]/svg:flowRegion[1]' % id)[0] + + if flowref.tag == inkex.addNS("rect", "svg"): + text.set("x", flowref.get("x")) + text.set("y", str(float(flowref.get("y")) + fs * count)) + count += 1 + else: + inkex.debug("This type of text element isn't supported. First unflow text.") + break + + #now let's convert flowPara into tspan + tspan = inkex.etree.Element(inkex.addNS("tspan", "svg")) + tspan.set(inkex.addNS("role","sodipodi"), "line") + tspan.text = n.text + text.append(tspan) + + else: + from copy import copy + x = n.get("x") or node.get("x") + y = n.get("y") or node.get("y") + + text.set("x", x) + text.set("y", y) + text.append(copy(n)) + + lines.append(text) + + return lines + + + def split_words(self, node): + """Returns a list of words""" + + words = [] + + #Function to recursively extract text + def plain_str(elem): + words = [] + if elem.text: + words.append(elem.text) + for n in elem: + words.extend(plain_str(n)) + if n.tail: + words.append(n.tail) + return words + + #if text has more than one line, iterates through elements + lines = self.split_lines(node) + if not lines: + return words + + for line in lines: + #gets the position of text node + x = float(line.get("x")) + y = line.get("y") + + #gets the font size. if element doesn't have a style attribute, it assumes font-size = 12px + try: + from simplestyle import parseStyle + fontsize = parseStyle(line.get("style"))["font-size"] + except: + fontsize = "12px" + fs = inkex.unittouu(fontsize) + + #extract and returns a list of words + words_list = "".join(plain_str(line)).split() + prev_len = 0 + + #creates new text nodes for each string in words_list + for word in words_list: + tspan = inkex.etree.Element(inkex.addNS("tspan", "svg")) + tspan.text = word + + text = inkex.etree.Element(inkex.addNS("text", "svg"), line.attrib) + tspan.set(inkex.addNS("role","sodipodi"), "line") + + #positioning new text elements + x = x + prev_len * fs + prev_len = len(word) + text.set("x", str(x)) + text.set("y", str(y)) + + text.append(tspan) + words.append(text) + + return words + + + def split_letters(self, node): + """Returns a list of letters""" + + letters = [] + + words = self.split_words(node) + if not words: + return letters + + for word in words: + + x = float(word.get("x")) + y = word.get("y") + + #gets the font size. If element doesn't have a style attribute, it assumes font-size = 12px + try: + import simplestyle + fontsize = simplestyle.parseStyle(word.get("style"))["font-size"] + except: + fontsize = "12px" + fs = inkex.unittouu(fontsize) + + #for each letter in element string + for letter in word[0].text: + tspan = inkex.etree.Element(inkex.addNS("tspan", "svg")) + tspan.text = letter + + text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib) + text.set("x", str(x)) + text.set("y", str(y)) + x += fs + + text.append(tspan) + letters.append(text) + return letters + + + def effect(self): + """Applies the effect""" + + split_type = self.options.split_type + preserve = self.options.preserve + + #checks if the selected elements are text nodes + for id, node in self.selected.iteritems(): + if not (node.tag == inkex.addNS("text", "svg") or node.tag == inkex.addNS("flowRoot", "svg")): + inkex.debug("Please select only text elements.") + break + else: + if split_type == "line": + nodes = self.split_lines(node) + elif split_type == "word": + nodes = self.split_words(node) + elif split_type == "letter": + nodes = self.split_letters(node) + + for n in nodes: + node.getparent().append(n) + + #preserve original element + if not preserve and nodes: + parent = node.getparent() + parent.remove(node) + +b = Split() +b.affect() -- 2.30.2