Reset platonic code.
[voro++.git] / branches / 2d_boundary / Tests / svgfig / defaults.py
blobbdda734087bcef7e0ad7b1ad71cd1eac093a5a45
1 import math, re, os, platform, warnings
2 import pathdata
4 version = "SVGFig 2.0.0alpha2"
5 version_info = (2, 0, 0, "alpha2")
7 ############################### default filenames
9 class VersionWarning(UserWarning): pass
10 warnings.filterwarnings("default", category=VersionWarning)
12 if re.search("windows", platform.system(), re.I):
13 try:
14 import _winreg
15 directory = _winreg.QueryValueEx(_winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
16 r"Software\Microsoft\Windows\Current Version\Explorer\Shell Folders"), "Desktop")[0]
17 except:
18 directory = os.path.expanduser("~") + os.sep + "Desktop"
20 def expand_fileName(fileName):
21 if re.search("windows", platform.system(), re.I) and not os.path.isabs(fileName):
22 fileName = defaults.directory + os.sep + fileName
23 return fileName
25 ############################### Defaults for each SVG element type
27 xml_header = """\
28 <?xml version="1.0" standalone="no"?>
29 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
30 """
32 ##### a
33 ##### altGlyph
34 ##### altGlyphDef
35 ##### altGlyphItem
36 ##### animate
37 ##### animateColor
38 ##### animateMotion
39 ##### animateTransform
40 ##### circle
41 signature_circle = ["cx", "cy", "r", "stroke", "fill"]
42 require_circle = ["cx", "cy", "r"]
43 defaults_circle = {"stroke": "black", "fill": "none"}
44 def tonumber_circle(svg):
45 svg.cx, svg.cy, svg.r = tonumber(svg.cx), tonumber(svg.cy), tonumber(svg.r)
47 def transform_circle(trans, svg):
48 if isnumber(svg.cx) and isnumber(svg.cy):
49 x1, y1 = trans(svg.cx, svg.cy)
50 if isnumber(svg.r):
51 x2, y2 = trans(svg.cx + svg.r, svg.cy)
52 svg.r = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
53 svg.cx, svg.cy = x1, y1
55 def bbox_circle(svg):
56 if isnumber(svg.cx) and isnumber(svg.cy):
57 if isnumber(svg.r):
58 return BBox(svg.cx - svg.r, svg.cx + svg.r, svg.cy - svg.r, svg.cy + svg.r)
59 else:
60 return BBox(svg.cx, svg.cx, svg.cy, svg.cy)
61 else:
62 return BBox(None, None, None, None)
64 ##### clipPath
65 ##### color-profile
66 ##### cursor
67 ##### definition-src
68 ##### defs
69 signature_defs = None
71 ##### desc
72 ##### ellipse
73 ##### feBlend
74 ##### feColorMatrix
75 ##### feComponentTransfer
76 ##### feComposite
77 ##### feConvolveMatrix
78 ##### feDiffuseLighting
79 ##### feDisplacementMap
80 ##### feDistantLight
81 ##### feFlood
82 ##### feFuncA
83 ##### feFuncB
84 ##### feFuncG
85 ##### feFuncR
86 ##### feGaussianBlur
87 ##### feImage
88 ##### feMerge
89 ##### feMergeNode
90 ##### feMorphology
91 ##### feOffset
92 ##### fePointLight
93 ##### feSpecularLighting
94 ##### feSpotLight
95 ##### feTile
96 ##### feTurbulence
97 ##### filter
98 ##### font
99 ##### font-face
100 ##### font-face-format
101 ##### font-face-name
102 ##### font-face-src
103 ##### font-face-uri
104 ##### foreignObject
105 ##### g
106 signature_g = None
108 ##### glyph
109 ##### glyphRef
110 ##### hkern
111 ##### image
112 ##### line
113 signature_line = ["x1", "y1", "x2", "y2", "stroke"]
114 require_line = ["x1", "y1", "x2", "y2"]
115 defaults_line = {"stroke": "black"}
117 def tonumber_line(svg):
118 svg.x1, svg.y1, svg.x2, svg.y2 = tonumber(svg.x1), tonumber(svg.y1), tonumber(svg.x2), tonumber(svg.y2)
120 def transform_line(trans, svg):
121 if isnumber(svg.x1) and isnumber(svg.y1):
122 svg.x1, svg.y1 = trans(svg.x1, svg.y1)
124 if isnumber(svg.x2) and isnumber(svg.y2):
125 svg.x2, svg.y2 = trans(svg.x2, svg.y2)
127 def bbox_line(svg):
128 isnumber1 = (isnumber(svg.x1) and isnumber(svg.y1))
129 isnumber2 = (isnumber(svg.x2) and isnumber(svg.y2))
131 if isnumber1 and isnumber2: return BBox(svg.x1, svg.x2, svg.y1, svg.y2)
132 elif isnumber1 and not isnumber2: return BBox(svg.x1, svg.x1, svg.y1, svg.y1)
133 elif not isnumber1 and isnumber2: return BBox(svg.x2, svg.x2, svg.y2, svg.y2)
134 else: return BBox(None, None, None, None)
136 ##### linearGradient
137 ##### marker
138 signature_marker = None
140 ##### mask
141 ##### metadata
142 ##### missing-glyph
143 ##### mpath
144 ##### path
145 signature_path = ["d", "stroke", "fill"]
146 require_path = []
147 defaults_path = {"d": [], "stroke": "black", "fill": "none"}
149 def tonumber_path(svg):
150 svg.d = pathdata.parse(svg.d)
152 def transform_path(trans, svg):
153 svg.d = pathdata.transform(trans, svg.d)
155 def bbox_path(svg):
156 return pathdata.bbox(pathdata.parse(svg.d))
158 ##### pattern
159 ##### polygon
160 ##### polyline
161 ##### radialGradient
162 ##### rect
163 signature_rect = ["x", "y", "width", "height", "stroke", "fill"]
164 require_rect = ["x", "y", "width", "height"]
165 defaults_rect = {"stroke": "black", "fill": "none"}
167 def transform_rect(trans, svg):
168 if isnumber(svg.x) and isnumber(svg.y):
169 if isnumber(svg.width) and isnumber(svg.height):
170 x1, y1 = trans(svg.x, svg.y)
171 x2, y2 = trans(svg.x + svg.width, svg.y + svg.height)
172 svg.x, svg.y = x1, y1
173 svg.width, svg.height = x2 - x1, y2 - y1
174 else:
175 svg.x, svg.y = trans(svg.x, svg.y)
177 def bbox_rect(svg):
178 if isnumber(svg.x) and isnumber(svg.y):
179 if isnumber(svg.width) and isnumber(svg.height):
180 return BBox(svg.x, svg.x + svg.width, svg.y, svg.y + svg.height)
181 else:
182 return BBox(svg.x, svg.x, svg.y, svg.y)
183 else:
184 return BBox(None, None, None, None)
186 ##### script
187 ##### set
188 ##### stop
189 ##### style
190 ##### svg
191 signature_svg = ["width", "height", "viewBox"]
192 require_svg = []
193 defaults_svg = {"width": 400, "height": 400, "viewBox": (0, 0, 100, 100),
194 "style": {"stroke-width": "0.5pt", "font-size": "4px", "text-anchor": "middle"},
195 "font-family": ["Helvetica", "Arial", "FreeSans", "Sans", "sans", "sans-serif"],
196 "xmlns": "http://www.w3.org/2000/svg", "xmlns:xlink": "http://www.w3.org/1999/xlink", "version":"1.1",
199 def tonumber_svg(svg):
200 svg.width = tonumber(svg.width)
201 svg.height = tonumber(svg.height)
202 svg.viewBox = tonumberlist(svg.viewBox)
203 svg["style"] = tostringmap(svg["style"])
204 svg["font-family"] = tostringlist(svg["font-family"])
206 ##### switch
207 ##### symbol
208 signature_symbol = None
210 ##### text
211 signature_text = ["x", "y", "stroke", "fill"]
212 require_text = ["x", "y"]
213 defaults_text = {"stroke": "none", "fill": "black"}
215 def tonumber_text(svg):
216 svg.x = tonumber(svg.x)
217 svg.y = tonumber(svg.y)
219 def transform_text(trans, svg):
220 if isnumber(svg.x) and isnumber(svg.y):
221 svg.x, svg.y = trans(svg.x, svg.y)
223 def bbox_text(svg):
224 if isnumber(svg.x) and isnumber(svg.y):
225 return BBox(svg.x, svg.x, svg.y, svg.y) # how to calculate text size???
226 else:
227 return BBox(None, None, None, None)
229 ##### textPath
230 ##### title
231 ##### tref
232 ##### tspan
233 signature_tspan = None
235 ##### use
236 signature_use = ["x", "y", "xlink:href"]
237 require_use = ["x", "y", "xlink:href"]
239 def tonumber_use(svg):
240 svg.x = tonumber(svg.x)
241 svg.y = tonumber(svg.y)
243 def transform_use(trans, svg):
244 if isnumber(svg.x) and isnumber(svg.y):
245 svg.x, svg.y = trans(svg.x, svg.y)
247 def bbox_use(svg):
248 if isnumber(svg.x) and isnumber(svg.y):
249 return BBox(svg.x, svg.x, svg.y, svg.y)
250 else:
251 return BBox(None, None, None, None)
253 ##### view
254 ##### vkern
256 ############################### utility functions for default actions
258 def tonumber(x):
259 try:
260 return float(x)
261 except ValueError:
262 return x
264 def tonumberlist(x):
265 if isinstance(x, basestring):
266 try:
267 return tuple(map(float, re.split("[, \t]+", x)))
268 except ValueError:
269 return x
270 return x
272 def tostringlist(x):
273 if isinstance(x, basestring):
274 return re.split("[, \t]+", x)
275 return x
277 def tostringmap(x):
278 if isinstance(x, basestring):
279 try:
280 return dict(map(lambda word: word.split(":"), re.split("[; \t]+", x)))
281 except ValueError:
282 return x
283 else:
284 return x
286 def isnumber(x): return isinstance(x, (int, long, float))
288 ############################### BBox class
290 class BBox:
291 def __init__(self, xmin, xmax, ymin, ymax):
292 self.xmin, self.xmax, self.ymin, self.ymax = xmin, xmax, ymin, ymax
294 def __repr__(self):
295 return "<BBox xmin=%g xmax=%g ymin=%g ymax=%g>" % (self.xmin, self.xmax, self.ymin, self.ymax)
297 def insert(self, x, y):
298 if self.xmin == None or x < self.xmin: self.xmin = x
299 if self.ymin == None or y < self.ymin: self.ymin = y
300 if self.xmax == None or x > self.xmax: self.xmax = x
301 if self.ymax == None or y > self.ymax: self.ymax = y
303 def __add__(self, other):
304 output = BBox(self.xmin, self.xmax, self.ymin, self.ymax)
305 output += other
306 return output
308 def __iadd__(self, other):
309 if self.xmin is None: self.xmin = other.xmin
310 elif other.xmin is None: pass
311 else: self.xmin = min(self.xmin, other.xmin)
313 if self.xmax is None: self.xmax = other.xmax
314 elif other.xmax is None: pass
315 else: self.xmax = max(self.xmax, other.xmax)
317 if self.ymin is None: self.ymin = other.ymin
318 elif other.ymin is None: pass
319 else: self.ymin = min(self.ymin, other.ymin)
321 if self.ymax is None: self.ymax = other.ymax
322 elif other.ymax is None: pass
323 else: self.ymax = max(self.ymax, other.ymax)
325 return self
327 def __eq__(self, other):
328 return self.xmin == other.xmin and self.xmax == other.xmax and self.ymin == other.ymin and self.ymax == other.ymax
330 def __ne__(self, other): return not (self == other)