forked from zgrep/happybot
132 lines
4.5 KiB
Python
132 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
|
|
def sanitize(s):
|
|
return s.replace('&', '&')\
|
|
.replace('>', '>')\
|
|
.replace('<', '<')\
|
|
.replace("'", ''')\
|
|
.replace('"', '"')
|
|
|
|
class Tag:
|
|
def __init__(self, name, attrs={}, **kwattrs):
|
|
self.name = name
|
|
self.attrs = attrs
|
|
self.attrs.update(kwattrs)
|
|
self.children = []
|
|
def append(self, *tags):
|
|
self.children += tags
|
|
return self
|
|
def __getitem__(self, n):
|
|
return self.children[n]
|
|
def __setitem__(self, n, tag):
|
|
self.children[n] = tag
|
|
def __str__(self):
|
|
s = '<' + self.name
|
|
for name, value in self.attrs.items():
|
|
s += ' ' + name
|
|
if value is not None:
|
|
s += '="' + sanitize(str(value)) + '"'
|
|
if len(self.children) > 0:
|
|
s += '>'
|
|
for child in self.children:
|
|
if isinstance(child, str):
|
|
s += sanitize(child)
|
|
else:
|
|
s += str(child)
|
|
s += '</' + self.name + '>'
|
|
else:
|
|
s += ' />'
|
|
return s
|
|
def __repr__(self):
|
|
return str(self)
|
|
def attr(self, **kwargs):
|
|
self.attrs.update(kwargs)
|
|
return self
|
|
|
|
class Path(Tag):
|
|
def __init__(self, **kwargs):
|
|
Tag.__init__(self, 'path', attrs=kwargs)
|
|
self.paths = []
|
|
def __str__(self):
|
|
self.attrs['d'] = ' '.join(self.paths)
|
|
return Tag.__str__(self)
|
|
def move(self, x, y):
|
|
self.paths.append('M ' + str(x) + ' ' + str(y))
|
|
return self
|
|
def line(self, x, y):
|
|
self.paths.append('L ' + str(x) + ' ' + str(y))
|
|
return self
|
|
def x(self, x):
|
|
self.paths.append('H ' + str(x))
|
|
return self
|
|
def y(self, y):
|
|
self.paths.append('V ' + str(y))
|
|
return self
|
|
def curve(self, x1, y1, x2, y2, x, y):
|
|
self.paths.append('C ' + str(x1) + ' ' + str(y1) + ', ' + str(x2) + ' ' + str(y2) + ', ' + str(x) + ' ' + str(y))
|
|
return self
|
|
def arc(self, xrad, yrad, arcrotxaxis, biggeroption, sweepflag, nextx, nexty):
|
|
self.paths.append('A ' + str(xrad) + ' ' + str(yrad) + ', ' + str(arcrotxaxis) + ', ' + str(biggeroption) + ', ' + str(sweepflag) + ', ' + str(nextx) + ' ' + str(nexty))
|
|
return self
|
|
def close(self):
|
|
self.paths.append('Z')
|
|
return self
|
|
|
|
print('<?xml version="1.0" encoding="UTF-8" ?>')
|
|
|
|
def body(cx, cy, w, h, c=0.03):
|
|
topleft = (cx - w/2, cy - h/2)
|
|
topright = (cx + w/2, cy - h/2)
|
|
bottomleft = (cx - w/2, cy + h/2)
|
|
bottomright = (cx + w/2, cy + h/2)
|
|
return Path().move(*bottomleft)\
|
|
.arc(w*c, h/2, 0, 0, 1, *topleft)\
|
|
.arc(w/2, h*c, 0, 1, 0, *topright)\
|
|
.arc(w*c, h/2, 0, 0, 1, *bottomright)\
|
|
.close()
|
|
|
|
def eye(cx, cy, w, h, lx=0, ly=0, c=0.01):
|
|
def outer(cx, cy, w, h, c=0.01):
|
|
topleft = (cx - w/2, cy - h/2)
|
|
topright = (cx + w/2, cy - h/2)
|
|
bottomleft = (cx - w/2, cy + h/2)
|
|
bottomright = (cx + w/2, cy + h/2)
|
|
return Path().move(*bottomleft)\
|
|
.arc(w*c, h/2, 0, 0, 1, *topleft)\
|
|
.arc(w/2, h*c, 0, 0, 1, *topright)\
|
|
.arc(w*c, h/2, 0, 0, 1, *bottomright)\
|
|
.arc(w/2, h*c, 0, 1, 0, *bottomleft)
|
|
def inner(cx, cy, w, h, c=0.01):
|
|
topleft = (cx - w/2, cy - h/2)
|
|
topright = (cx + w/2, cy - h/2)
|
|
bottomleft = (cx - w/2, cy + h/2)
|
|
bottomright = (cx + w/2, cy + h/2)
|
|
return Path().move(*bottomleft)\
|
|
.arc(w*c, h/2, 0, 0, 1, *topleft)\
|
|
.arc(w/2, h*c, 0, 0, 1, *topright)\
|
|
.arc(w*c, h/2, 0, 0, 1, *bottomright)\
|
|
.arc(w/2, h*c, 0, 0, 1, *bottomleft)
|
|
icx = cx + lx * w/4
|
|
icy = cy + ly * h/4
|
|
return Tag('g').append(
|
|
outer(cx, cy, w, h, c).attr(fill='white'),
|
|
inner(icx, icy, w/2.2, h/2.2, c).attr(fill='black')
|
|
).attr(stroke='black')
|
|
|
|
def eyes(cx, cy, rad, w, h):
|
|
return [
|
|
eye(cx - rad, cy, w, h, 1, -1),
|
|
eye(cx + rad, cy, w, h, -1, -1)
|
|
]
|
|
|
|
def mouth(cx, cy, w, h):
|
|
left = (cx - w/2, cy)
|
|
right = (cx + w/2, cy)
|
|
return Path().move(*left).arc(w/2, h, 0, 0, 0, *right).close().attr(fill='white', stroke='black')
|
|
|
|
svg = Tag('svg', {'xmlns': 'http://www.w3.org/2000/svg', 'version': '1.1'})
|
|
svg.append(body(200, 200, 180, 100).attr(fill='white', stroke='black'))
|
|
svg.append(*eyes(200, 185, 64, 50, 56))
|
|
svg.append(mouth(200, 210, 55, 35))
|
|
|
|
print(str(svg))
|