orca/sketches/tiger/svg2oc.py

244 lines
6.0 KiB
Python

import xml.etree.ElementTree as et
import sys
def expect_char(s, i, c):
if i >= len(s) or c != s[i]:
print("error: expected character " + c + " at index " + str(i))
exit()
return(i+1)
def accept_char(s, i, c):
if i < len(s) and c == s[i]:
i += 1
return(i)
def consume_number(s, i):
sign = 1
if s[i] == '+':
i += 1
if s[i] == '-':
sign = -1
i += 1
res = 0
decimalPos = 0.1
while i < len(s) and s[i].isdigit() :
res *= 10
res += int(s[i])
i += 1
if i < len(s) and s[i] == '.':
i += 1
while i < len(s) and s[i].isdigit() :
res += decimalPos * int(s[i])
decimalPos *= 0.1
i += 1
return(res*sign, i)
def consume_point(s, i):
(x, i) = consume_number(s, i)
i = accept_char(s, i, ',')
(y, i) = consume_number(s, i)
return(x, y, i)
def f2s(x):
return f'{x:.3f}'
class svgContext:
sp = (0, 0)
cp = (0, 0)
rp = (0, 0)
def reset(self):
self.cp = self.sp = self.rp = (0,0)
def move_to(self, rel, x, y):
if rel:
x += self.cp[0]
y += self.cp[1]
print("\t\toc_move_to(" + f2s(x) + ", " + f2s(y) + ");")
self.sp = (x, y)
self.cp = (x, y)
self.rp = self.cp
def curve_to(self, rel, x1, y1, x2, y2, x3, y3):
if rel:
x1 += self.cp[0]
y1 += self.cp[1]
x2 += self.cp[0]
y2 += self.cp[1]
x3 += self.cp[0]
y3 += self.cp[1]
print("\t\toc_cubic_to(" + f2s(x1) + ", " + f2s(y1) + ", " + f2s(x2) + ", " + f2s(y2) + ", " + f2s(x3) + ", " + f2s(y3) + ");")
self.rp = (x2, y2)
self.cp = (x3, y3)
def smooth_curve_to(self, rel, x2, y2, x3, y3):
if rel:
x2 += self.cp[0]
y2 += self.cp[1]
x3 += self.cp[0]
y3 += self.cp[1]
x1 = 2*self.cp[0] - self.rp[0]
y1 = 2*self.cp[1] - self.rp[1]
print("\t\toc_cubic_to(" + f2s(x1) + ", " + f2s(y1) + ", " + f2s(x2) + ", " + f2s(y2) + ", " + f2s(x3) + ", " + f2s(y3) + ");")
self.rp = (x2, y2)
self.cp = (x3, y3)
def line_to(self, rel, x1, y1):
if rel:
x1 += self.cp[0]
y1 += self.cp[1]
print("\t\toc_line_to(" + f2s(x1) + ", " + f2s(y1) + ");")
self.cp = (x1, y1)
self.rp = self.cp
def vertical_to(self, rel, y1):
if rel:
y1 += self.cp[1]
x1 = self.cp[0]
print("\t\toc_line_to(" + f2s(x1) + ", " + f2s(y1) + ");")
self.cp = (x1, y1)
self.rp = self.cp
def close_path(self):
print("\t\toc_close_path();");
self.cp = self.rp = self.sp
def print_path(path, ctx):
# print("path " + path.get('id') + ":")
d = path.get('d')
index = 0
c = d[index]
while index < len(d):
c = d[index]
index += 1
rel = c.islower()
c = c.lower()
if c == 'm':
(x, y, index) = consume_point(d, index)
ctx.move_to(rel, x, y)
while index < len(d) and (d[index] == ',' or d[index] == '+' or d[index] == '-'):
index = accept_char(d, index, ',')
(x, y, index) = consume_point(d, index)
ctx.move_to(rel, x, y)
elif c == 'l':
(x1, y1, index) = consume_point(d, index)
ctx.line_to(rel, x1, y1)
while index < len(d) and (d[index] == ',' or d[index] == '+' or d[index] == '-'):
index = accept_char(d, index, ',')
(x1, y1, index) = consume_point(d, index)
ctx.line_to(rel, x1, y1)
elif c == 'v':
(y1, index) = consume_number(d, index)
ctx.vertical_to(rel, y1)
elif c == 'c':
(x1, y1, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x2, y2, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x3, y3, index) = consume_point(d, index)
ctx.curve_to(rel, x1, y1, x2, y2, x3, y3)
while index < len(d) and (d[index] == ',' or d[index] == '+' or d[index] == '-'):
index = accept_char(d, index, ',')
(x1, y1, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x2, y2, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x3, y3, index) = consume_point(d, index)
ctx.curve_to(rel, x1, y1, x2, y2, x3, y3)
elif c == 's':
(x2, y2, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x3, y3, index) = consume_point(d, index)
ctx.smooth_curve_to(rel, x2, y2, x3, y3)
while index < len(d) and (d[index] == ',' or d[index] == '+' or d[index] == '-'):
index = accept_char(d, index, ',')
(x2, y2, index) = consume_point(d, index)
index = accept_char(d, index, ',')
(x3, y3, index) = consume_point(d, index)
ctx.smooth_curve_to(rel, x2, y2, x3, y3)
elif c == 'z':
ctx.close_path()
index += 1
else:
print('error: unrecognized command')
exit()
def parse_color(s):
s = s.lstrip('#')
if len(s) == 3:
return (int(s[0]+s[0], 16)/255., int(s[1]+s[1], 16)/255., int(s[2]+s[2], 16)/255.)
elif len(s) == 6:
return (int(s[0:2], 16)/255., int(s[2:4], 16)/255., int(s[4:6], 16)/255.)
else:
print("error: unrecognized color: " + s)
exit()
tree = et.parse('./Ghostscript_Tiger.svg')
ctx = svgContext()
print("void draw_tiger(bool singlePath, int singlePathIndex)")
print("{")
pathIndex = 0;
for g in tree.iter('{http://www.w3.org/2000/svg}g'):
for path in g.findall('{http://www.w3.org/2000/svg}path'):
ctx.reset()
print("\tif(!singlePath || singlePathIndex == "+ str(pathIndex) +")")
print("\t{")
print_path(path, ctx)
fill = g.get('fill')
stroke = g.get('stroke')
stroke_width = g.get('stroke-width')
if fill != None and fill != "none":
(r, g, b) = parse_color(fill)
print("\t\toc_set_color_rgba(" + f2s(r) + ", " + f2s(g) + ", " + f2s(b) + ", 1);")
print("\t\toc_fill();")
print("\t}")
pathIndex += 1
if stroke != None and stroke != "none":
print("\tif(!singlePath || singlePathIndex == "+ str(pathIndex) +")")
print("\t{")
if stroke_width != None:
print("\t\toc_set_width(" + stroke_width + ");");
else:
print("\t\toc_set_width(1);");
(r, g, b) = parse_color(stroke)
if fill != None:
ctx.reset()
print_path(path, ctx)
print("\t\toc_set_color_rgba(" + f2s(r) + ", " + f2s(g) + ", " + f2s(b) + ", 1);")
print("\t\toc_stroke();")
print("\t}")
pathIndex += 1
if (stroke == None or stroke == 'none') and (fill == None or fill == ''):
print("error, group " + g.get("id") + " has no command")
print("")
print("}")