1
2
3 """
4 License:
5 Copyright (c) 2008 Kerim Mansour
6 All rights reserved.
7
8 COMMERCIAL USAGE:
9 Commercial usage is understood as usage in order to make a profit or in a corporate environment.
10 For commercial usage please contact kmansour ATT web DOT de
11
12 NONCOMMERCIAL USAGE:
13 The following license applies to NONCOMMERCIAL usage of the software.
14 Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16
17 * Redistributions of source code must retain the above copyright notice,
18 this list of conditions and the following disclaimer.
19 * Redistributions in binary form must reproduce the above copyright notice,
20 this list of conditions and the following disclaimer in the documentation
21 and/or other materials provided with the distribution.
22 * Neither the name of the author nor the names of other contributors
23 may be used to endorse or promote products derived from this software without
24 specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 """
35
36 """
37 Not supported as of yet / NOT Working
38 Viewport, transforms, gradients....
39 """
40
41 SVG_HEADER='''<?xml version="1.0" encoding="UTF-8"?>
42 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" '''
43 SVG_FOOTER='</svg>'
44 END_TAG_LINE='>\n'
45
47 """ Base class for a SVG document """
48 - def __init__(self,title="svg",description="", height=None,width=None, viewBox=None):
49 self.title = title
50 self.descr = description
51 self.height = height
52 self.width = width
53 self.viewBox=viewBox
54 self.elements = []
55
57 """
58 Return a XML representation of the current SVG document.
59 This function can be used for debugging purposes.
60
61 @return: the representation of the current SVG as an xml string
62 """
63 xml=SVG_HEADER
64
65 if self.height!= None:
66 xml+='height="%s" ' % (self.height)
67
68 if self.width!= None:
69 xml+='width="%s" ' % (self.width)
70
71 if self.viewBox!= None:
72 xml+='viewBox="%s" ' % (self.viewBox)
73
74 xml+=END_TAG_LINE
75 for element in self.elements:
76 xml+=element.getXML()
77 xml+=SVG_FOOTER
78 return xml
79
81 """
82 Saves the current SVG document into a file.
83 @type filename: string
84 @param filename: file to store the svg in (complete path+filename+extension)
85 """
86 f=open(filename,'w')
87 xml=self.getXML()
88 f.write(xml)
89 f.close()
90
92 """
93 Generic method to add any element to the document
94 @type element: Object that contains a getXML method (circle, line, text, polyline, etc....)
95 @param element: the element to add to the doc
96 """
97 self.elements.append(element)
98
100 """
101 This is the base class for all svg elements like elipses, texts, lines etc.
102 """
103 - def __init__(self, startTag, style_dict=None, focusable=None,endTag="/>\n"):
104 """
105 initializes the object
106 @type startTag: string
107 @param startTag: the tag for the svg element name (e.g. <text )
108 @type style_dict: dictionary
109 @param style_dict: the style to use for this element
110 @type focusable: ??
111 @param focusable: ??
112 """
113 self.startXML=startTag
114 self.endXML=endTag
115
116 self.focusable=focusable
117 self.style_dict=style_dict
118
120 """
121 This method converts the information in the style
122 dictionary into svg syntax for the style attribute
123
124 @return: the representation of the current style as an xml string
125 """
126 count=0;
127 xml="style="
128 for key in self.style_dict.keys():
129 if self.style_dict.get(key)=="":
130 continue
131 if count>0:
132 xml+='; '
133 else:
134 xml+='"'
135 xml+='%s:%s' %(key,self.style_dict.get(key))
136 count+=1
137 xml+='" '
138 if len(xml)>8:
139 return xml
140 else:
141 return ""
142
144 """
145 Return a XML representation of the current element.
146 This function can be used for debugging purposes. It is also used by getXML in SVG
147
148 @return: the representation of the current element as an xml string
149 """
150 xml=self.startXML
151 for item in dir(self):
152 if item.find('_')==-1 and item.find('XML')==-1:
153 if getattr(self,item) != None:
154 xml+=item+"=\"%s\" " %(getattr(self,item))
155 elif item=='style_dict':
156 if getattr(self,item) != None:
157 xml+=self.getXMLFromStyle()
158 xml+=self.endXML
159 return xml
160
161
163 """ Base class for a container element. Different shapes, paths and
164 text can be put together inside a container sharing the same style.
165 """
166 startXML="<g "
167 endTag=">\n"
168 endXML="</g>\n"
169
170 - def __init__(self,style_dict=None, transform_dict=None):
171 """
172 Initialization.
173 @type style_dict: dict
174 @param style_dict: The style that should be applied to all elements within this container
175 """
176 self.style_dict=style_dict
177 self.transform_dict=transform_dict
178 self.elements=[]
179
180
182 """
183 Generic method to add any element to the container
184 @type element: Object that contains a getXML method (circle, line, text, polyline, etc....)
185 @param element: the element to add to the container
186 """
187 self.elements.append(element)
188
190 """
191 This method converts the information in the style
192 dictionary into svg syntax for the style attribute
193
194 @return: the representation of the current style as an xml string
195 """
196 if self.style_dict==None:
197 return""
198 count=0;
199 xml="style="
200 for key in self.style_dict.keys():
201 if self.style_dict.get(key)=="":
202 continue
203 if count>0:
204 xml+='; '
205 else:
206 xml+='"'
207 xml+='%s:%s' %(key,self.style_dict.get(key))
208 count+=1
209 xml+='" '
210 if len(xml)>8:
211 return xml
212 else:
213 return ""
214
215
241
243 """
244 Return a XML representation of the current element.
245 This function can be used for debugging purposes. It is also used by getXML in SVG
246
247 @return: the representation of the current element as an xml string
248 """
249 xml=self.startXML
250 xml+=self.getXMLFromStyle()
251 xml+=self.getXMLFromTransform()
252 xml+=self.endTag
253 for element in self.elements:
254 xml+=element.getXML()
255 xml+=self.endXML
256 return xml
257
259 """
260 This class packs all definitions
261 """
262 startXML="<defs>\n"
263 endXML="</defs>\n"
264
267
269 self.definitions.append(definition)
270
272 for defintion in self.definitions:
273 if definition.find('id="'+id+'"')>-1:
274 self.definitions.remove(definition)
275
277 """
278 Return a XML representation of the current element.
279 This function can be used for debugging purposes. It is also used by getXML in SVG
280
281 @return: the representation of the current element as an xml string
282 """
283 xml=self.startXML
284 xml+=self.getXMLFromStyle()
285 xml+=self.getXMLFromTransform()
286
287 for element in self.elements:
288 xml+=element.getXML()
289 xml+=self.endXML
290 return xml
291
293 startXML="<linearGradient "
294 endTag=">\n"
295 endXML="</linearGradient>\n"
296
298 self.id=id
299 self.stop=[]
300
302 s=stop(offset,color)
303 self.stop.apend(s)
304
306 """
307 Return a XML representation of the current element.
308 This function can be used for debugging purposes. It is also used by getXML in SVG
309
310 @return: the representation of the current element as an xml string
311 """
312 xml=self.startXML
313 for item in dir(self):
314 if item.find('_')==-1 and item.find('XML')==-1:
315 if getattr(self,item) != None:
316 xml+=item+"=\"%s\" " %(getattr(self,item))
317 elif item=='style_dict':
318 if getattr(self,item) != None:
319 xml+=self.getXMLFromStyle()
320 xml+=self.endXML
321 return xml
322
323 -class stop(BaseElement):
325 """
326 Creates a line
327 @type x1: string or int
328 @param x1: starting x-coordinate
329 @type x1: string or int
330 @param y1: starting y-coordinate
331 @type y2: string or int
332 @param x2: ending x-coordinate
333 @type y2: string or int
334 @param y2: ending y-coordinate
335 @type style_dict: dictionary
336 @param style_dict: style(s) to use for this element
337 @type focusable: ???
338 @param focusable: ??
339 """
340 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", None,None)
341 if offset.find('.')>-1:
342 offset=offset[offset.find('.')+1:]+'%'
343 self.offset = offset
344 self.stopcolor = stopcolor
345
347 """
348 Return a XML representation of the current element.
349 This function can be used for debugging purposes. It is also used by getXML in SVG
350
351 @return: the representation of the current element as an xml string
352 """
353 xml=self.startXML
354 for item in dir(self):
355 if item.find('_')==-1 and item.find('XML')==-1:
356 if getattr(self,item) != None:
357 xml+=item+"=\"%s\" " %(getattr(self,item))
358 xml+=self.endXML
359 return xml
360
361
362 -class line(BaseElement):
363 """
364 Class representing the line element of an svg doc.
365 Note that this element is NOT painted VISIBLY by default UNLESS you provide
366 a style including STROKE and STROKE-WIDTH
367 """
368 - def __init__(self,x1=None,y1=None,x2=None,y2=None,style_dict=None,focusable=None):
369 """
370 Creates a line
371 @type x1: string or int
372 @param x1: starting x-coordinate
373 @type x1: string or int
374 @param y1: starting y-coordinate
375 @type y2: string or int
376 @param x2: ending x-coordinate
377 @type y2: string or int
378 @param y2: ending y-coordinate
379 @type style_dict: dictionary
380 @param style_dict: style(s) to use for this element
381 @type focusable: ???
382 @param focusable: ??
383 """
384 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict,focusable)
385 self.x1 = x1
386 self.y1 = y1
387 self.x2=x2
388 self.y2=y2
389
390
392 """
393 Class representing the ellipse element of an svg doc.
394 """
395 - def __init__(self,cx=None,cy=None,rx=None,ry=None,style_dict=None,focusable=None):
396 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
397 self.cx = cx
398 self.cy = cy
399 self.rx=rx
400 self.ry=ry
401
402
403 -class rect(BaseElement):
404 """
405 Class representing the rect element of an svg doc.
406 """
407 - def __init__(self,x=None,y=None,width=None,height=None, rx=None, ry=None,style_dict=None,focusable=None):
408 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
409 self.x = x
410 self.y = y
411 self.height = height
412 self.width = width
413 self.rx=rx
414 self.ry=ry
415
416
418 """
419 Class representing the cirle element of an svg doc.
420 """
421 - def __init__(self,cx=None,cy=None,r=None,style_dict=None,focusable=None):
422 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
423 self.cx = cx
424 self.cy = cy
425 self.r=r
426
427
429 """
430 Class representing the polyline element of an svg doc.
431 """
432 - def __init__(self,points=None,style_dict=None,focusable=None):
433 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
434 self.points = points
435
436
437
439 - def __init__(self,points=None,style_dict=None,focusable=None):
440 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
441 self.points = points
442
443
444 -class text(BaseElement):
445 """
446 Class representing the text element of an svg doc.
447 @type content: string
448 @param content: the text to display
449 @type x: int
450 @param x: x-coordinate for the text
451 @type y: int
452 @param y: y-coordinate for the text
453 @type rotate: int
454 @param rotate: rotation in degrees (negative means counterclockwise)
455 """
456 - def __init__(self,content, x ,y, rotate=None,style_dict=None,editable=None, focusable=None):
457 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable,endTag="</text>\n")
458 self.x=x
459 self.y=y
460 self.rotate=rotate
461 self.editable=editable
462 self.content=content
463
465 """
466 Return a XML representation of the current element.
467 This function can be used for debugging purposes. It is also used by getXML in SVG
468
469 @return: the representation of the current element as an xml string
470 """
471 xml=self.startXML
472 for item in dir(self):
473 if item.find('_')==-1 and item.find('XML') ==-1 and item.find('content')==-1:
474 if getattr(self,item) != None:
475 xml+=item+"=\"%s\" " %(getattr(self,item))
476 elif item=='style_dict':
477 if getattr(self,item) != None:
478 xml+=self.getXMLFromStyle()
479 xml+=">"
480 xml+=self.content
481 xml+=self.endXML
482 return xml
483
484 -class path(BaseElement):
485 - def __init__(self,pathData="",pathLength=None,style_dict=None, focusable=None):
486 BaseElement.__init__(self,"<"+self.__class__.__name__+" ", style_dict, focusable)
487 if pathData!='' and not pathData.endswith(' '):
488 pathData+=' '
489 self.d=pathData
490
491
492 - def __append__(self,command, params, relative=True):
493 if relative==True:
494 self.d+=command.lower()
495 else:
496 self.d+=command.upper()
497 for param in params:
498 self.d+=' %s ' %(param)
499
502
505
508
511
514
515 - def appendCubicCurveToPath(self, controlstartx, controlstarty, controlendx, controlendy, endx,endy,relative=True):
516 self.__append__('c',[controlstartx, controlstarty, controlendx, controlendy, endx,endy], relative)
517
519 self.__append__('s',[controlendx, controlendy, endx,endy], relative)
520
522 self.__append__('q',[controlx, controly, endx,endy], relative)
523
526
527 - def appendArcToPath(self,rx,ry,x,y,x_axis_rotation=0,large_arc_flag=0,sweep_flag=1 ,relative=True):
528 self.__append__('a',[rx,ry,x,y,x_axis_rotation,large_arc_flag,sweep_flag], relative)
529
531 """
532 Return a XML representation of the current element.
533 This function can be used for debugging purposes. It is also used by getXML in SVG
534
535 @return: the representation of the current element as an xml string
536 """
537 xml=self.startXML
538 xml+='d=\"'+self.d+'" '
539 for item in dir(self):
540 if item.find('_')==-1 and item.find('XML') ==-1 and item.find('append')==-1 and item.find('d')!=0:
541 if getattr(self,item) != None:
542 xml+=item+"=\"%s\" " %(getattr(self,item))
543 elif item=='style_dict':
544 if getattr(self,item) != None:
545 xml+=self.getXMLFromStyle()
546
547
548 xml+=self.endXML
549 return xml
550