Code

Translations. French translation minor update.
[inkscape.git] / share / extensions / split.py
1 #!/usr/bin/env python 
2 '''
3 Copyright (C) 2009 Karlisson Bezerra, contato@nerdson.com
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 '''
20 import inkex
22 class Split(inkex.Effect):
23     def __init__(self):
24         inkex.Effect.__init__(self)
25         self.OptionParser.add_option("-s", "--splittype", 
26                         action="store", type="string", 
27                         dest="split_type", default="word", 
28                         help="type of split")
29         self.OptionParser.add_option("-p", "--preserve", 
30                         action="store", type="inkbool", 
31                         dest="preserve", default="True", 
32                         help="Preserve original")
33         self.OptionParser.add_option("--tab",
34                         action="store", type="string",
35                         dest="tab",
36                         help="The selected UI-tab when OK was pressed")
38     def split_lines(self, node):
39         """Returns a list of lines"""
41         lines = []
42         count = 1
43         
44         for n in node:
45             if not (n.tag == inkex.addNS("flowPara", "svg") or n.tag == inkex.addNS("tspan", "svg")):
46                 if n.tag == inkex.addNS("textPath", "svg"):
47                     inkex.debug("This type of text element isn't supported. First remove text from path.")
48                     break
49                 else:
50                     continue
51            
52             text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib)
53             
54             #handling flowed text nodes
55             if node.tag == inkex.addNS("flowRoot", "svg"):
56                 try:
57                     from simplestyle import parseStyle
58                     fontsize = parseStyle(node.get("style"))["font-size"]
59                 except:
60                     fontsize = "12px"
61                 fs = inkex.unittouu(fontsize)
62                 
63                 #selects the flowRegion's child (svg:rect) to get @X and @Y
64                 id = node.get("id")
65                 flowref = self.xpathSingle('/svg:svg//*[@id="%s"]/svg:flowRegion[1]' % id)[0]
66                 
67                 if flowref.tag == inkex.addNS("rect", "svg"):
68                     text.set("x", flowref.get("x"))
69                     text.set("y", str(float(flowref.get("y")) + fs * count))
70                     count += 1
71                 else:
72                     inkex.debug("This type of text element isn't supported. First unflow text.")
73                     break
74                 
75                 #now let's convert flowPara into tspan
76                 tspan = inkex.etree.Element(inkex.addNS("tspan", "svg"))
77                 tspan.set(inkex.addNS("role","sodipodi"), "line")
78                 tspan.text = n.text
79                 text.append(tspan)
80             
81             else:
82                 from copy import copy
83                 x = n.get("x") or node.get("x")
84                 y = n.get("y") or node.get("y")
86                 text.set("x", x)
87                 text.set("y", y)
88                 text.append(copy(n))
89             
90             lines.append(text)
92         return lines
95     def split_words(self, node):
96         """Returns a list of words"""
97         
98         words = []
100         #Function to recursively extract text
101         def plain_str(elem):
102             words = []
103             if elem.text:
104                 words.append(elem.text)
105             for n in elem:
106                 words.extend(plain_str(n))
107                 if n.tail:
108                     words.append(n.tail)
109             return words
110         
111         #if text has more than one line, iterates through elements
112         lines = self.split_lines(node)
113         if not lines:
114             return words
116         for line in lines:
117             #gets the position of text node
118             x = float(line.get("x"))
119             y = line.get("y")
120             
121             #gets the font size. if element doesn't have a style attribute, it assumes font-size = 12px
122             try:
123                 from simplestyle import parseStyle
124                 fontsize = parseStyle(line.get("style"))["font-size"]
125             except:
126                 fontsize = "12px"
127             fs = inkex.unittouu(fontsize)
129             #extract and returns a list of words
130             words_list = "".join(plain_str(line)).split()
131             prev_len = 0
132             
133             #creates new text nodes for each string in words_list
134             for word in words_list:
135                 tspan = inkex.etree.Element(inkex.addNS("tspan", "svg"))
136                 tspan.text = word
137                 
138                 text = inkex.etree.Element(inkex.addNS("text", "svg"), line.attrib)
139                 tspan.set(inkex.addNS("role","sodipodi"), "line")
140                 
141                 #positioning new text elements
142                 x = x + prev_len * fs
143                 prev_len = len(word)
144                 text.set("x", str(x))
145                 text.set("y", str(y))
146                 
147                 text.append(tspan)
148                 words.append(text)
149         
150         return words
153     def split_letters(self, node):
154         """Returns a list of letters"""
156         letters = []
157         
158         words = self.split_words(node)
159         if not words:
160             return letters
162         for word in words:
163             
164             x = float(word.get("x"))
165             y = word.get("y")
166            
167             #gets the font size. If element doesn't have a style attribute, it assumes font-size = 12px
168             try:
169                 import simplestyle
170                 fontsize = simplestyle.parseStyle(word.get("style"))["font-size"]
171             except:
172                 fontsize = "12px"
173             fs = inkex.unittouu(fontsize)
175             #for each letter in element string
176             for letter in word[0].text:
177                 tspan = inkex.etree.Element(inkex.addNS("tspan", "svg"))
178                 tspan.text = letter
180                 text = inkex.etree.Element(inkex.addNS("text", "svg"), node.attrib)
181                 text.set("x", str(x))
182                 text.set("y", str(y))
183                 x += fs
184                 
185                 text.append(tspan)
186                 letters.append(text)
187         return letters
190     def effect(self):
191         """Applies the effect"""
193         split_type = self.options.split_type
194         preserve = self.options.preserve
195        
196         #checks if the selected elements are text nodes
197         for id, node in self.selected.iteritems():
198             if not (node.tag == inkex.addNS("text", "svg") or node.tag == inkex.addNS("flowRoot", "svg")):
199                 inkex.debug("Please select only text elements.")
200                 break
201             else:
202                 if split_type == "line":
203                     nodes = self.split_lines(node)
204                 elif split_type == "word":
205                     nodes = self.split_words(node)
206                 elif split_type == "letter":
207                     nodes = self.split_letters(node)
208                 
209                 for n in nodes:
210                     node.getparent().append(n)
211                         
212                 #preserve original element
213                 if not preserve and nodes:
214                     parent = node.getparent()
215                     parent.remove(node)
217 b = Split()
218 b.affect()