Code

Extensions. New text split extension (Bug #171748).
authorJazzyNico <nicoduf@yahoo.fr>
Tue, 20 Apr 2010 16:14:27 +0000 (18:14 +0200)
committerJazzyNico <nicoduf@yahoo.fr>
Tue, 20 Apr 2010 16:14:27 +0000 (18:14 +0200)
po/POTFILES.in
share/extensions/Makefile.am
share/extensions/split.inx [new file with mode: 0644]
share/extensions/split.py [new file with mode: 0644]

index 285f3387aed8ab0a033e1ad05bfd74cd6e8c99e3..7d92910e8ae9c3d626f4aa34850a1bad13493521 100644 (file)
@@ -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/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
 [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/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
 [type: gettext/xml] share/extensions/straightseg.inx
 [type: gettext/xml] share/extensions/summersnight.inx
 [type: gettext/xml] share/extensions/svg2xaml.inx
index b5bf8cd331f6c929f23d034ffddc82831634bdc5..7327ffbd50d85bb68ca068b353a33fac7bef4f4b 100644 (file)
@@ -115,6 +115,7 @@ extensions = \
        sk2svg.sh \
        SpSVG.pm \
        spirograph.py\
        sk2svg.sh \
        SpSVG.pm \
        spirograph.py\
+       split.py \
        straightseg.py \
        summersnight.py \
        svgcalendar.py \
        straightseg.py \
        summersnight.py \
        svgcalendar.py \
@@ -245,6 +246,7 @@ modules = \
        sk1_input.inx \
        sk1_output.inx \
        spirograph.inx \
        sk1_input.inx \
        sk1_output.inx \
        spirograph.inx \
+       split.inx \
        straightseg.inx \
        summersnight.inx \
        svg2xaml.inx \
        straightseg.inx \
        summersnight.inx \
        svg2xaml.inx \
diff --git a/share/extensions/split.inx b/share/extensions/split.inx
new file mode 100644 (file)
index 0000000..0f8cea0
--- /dev/null
@@ -0,0 +1,22 @@
+<inkscape-extension>
+    <_name>Split text</_name>
+    <id>com.nerdson.split</id>
+       <dependency type="executable" location="extensions">split.py</dependency>
+       <dependency type="executable" location="extensions">inkex.py</dependency>
+       <param name="texthelp" type="description">This effect splits texts into different lines, words or letters. Select below how your text should be splitted.</param>
+       <param name="splittype" type="enum" _gui-text="Split:">
+               <item value="line">Lines</item>
+               <item value="word">Words</item>
+               <item value="letter">Letters</item>
+       </param>
+       <param name="preserve" type="boolean" _gui-text="Preserve original text?">true</param>
+    <effect>
+               <object-type>text</object-type>
+               <effects-menu>
+                       <submenu _name="Text"/>
+               </effects-menu>
+    </effect>
+    <script>
+        <command reldir="extensions" interpreter="python">split.py</command>
+    </script>
+</inkscape-extension>
diff --git a/share/extensions/split.py b/share/extensions/split.py
new file mode 100644 (file)
index 0000000..5e9de00
--- /dev/null
@@ -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()