render_alphabetsoup.py revision 181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico#!/usr/bin/env python
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico'''
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoCopyright (C) 2001-2002 Matt Chisholm matt@theory.org
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoCopyright (C) 2008 Joel Holdsworth joel@airwebreathe.org.uk
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for AP
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoThis program is free software; you can redistribute it and/or modify
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoit under the terms of the GNU General Public License as published by
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicothe Free Software Foundation; either version 2 of the License, or
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico(at your option) any later version.
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoThis program is distributed in the hope that it will be useful,
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicobut WITHOUT ANY WARRANTY; without even the implied warranty of
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoGNU General Public License for more details.
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoYou should have received a copy of the GNU General Public License
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoalong with this program; if not, write to the Free Software
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico'''
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport copy
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport inkex
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport simplestyle
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport math
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport cmath
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport string
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport random
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport render_alphabetsoup_config
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport bezmisc
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport simplepath
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport os
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport sys
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicoimport re
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoimport gettext
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico_ = gettext.gettext
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicosyntax = render_alphabetsoup_config.syntax
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoalphabet = render_alphabetsoup_config.alphabet
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicounits = render_alphabetsoup_config.units
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicofont = render_alphabetsoup_config.font
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico# Loads a super-path from a given SVG file
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef loadPath( svgPath ):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico extensionDir = os.path.normpath(
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico os.path.join( os.getcwd(), os.path.dirname(__file__) )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # __file__ is better then sys.argv[0] because this file may be a module
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # for another one.
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico tree = inkex.etree.parse( extensionDir + "/" + svgPath )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico root = tree.getroot()
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico pathElement = root.find('{http://www.w3.org/2000/svg}path')
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if pathElement == None:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return None, 0, 0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico d = pathElement.get("d")
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico width = float(root.get("width"))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico height = float(root.get("height"))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return simplepath.parsePath(d), width, height # Currently we only support a single path
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef combinePaths( pathA, pathB ):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if pathA == None and pathB == None:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif pathA == None:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return pathB
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif pathB == None:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return pathA
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return pathA + pathB
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicodef reverseComponent(c):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico nc = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico last = c.pop()
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico nc.append(['M', last[1][-2:]])
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico while c:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico this = c.pop()
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico cmd = last[0]
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if cmd == 'C':
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico nc.append([last[0], last[1][2:4] + last[1][:2] + this[1][-2:]])
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico nc.append([last[0], this[1][-2:]])
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico last = this
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico return nc
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicodef reversePath(sp):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico rp = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico component = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for p in sp:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico cmd, params = p
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if cmd == 'Z':
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico rp.extend(reverseComponent(component))
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico rp.append(['Z', []])
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico component = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico component.append(p)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico return rp
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef flipLeftRight( sp, width ):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for cmd,params in sp:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico defs = simplepath.pathdefs[cmd]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for i in range(defs[1]):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if defs[3][i] == 'x':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico params[i] = width - params[i]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef flipTopBottom( sp, height ):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for cmd,params in sp:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico defs = simplepath.pathdefs[cmd]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for i in range(defs[1]):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if defs[3][i] == 'y':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico params[i] = height - params[i]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef solveQuadratic(a, b, c):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico det = b*b - 4.0*a*c
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if det >= 0: # real roots
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico sdet = math.sqrt(det)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: # complex roots
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico sdet = cmath.sqrt(det)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return (-b + sdet) / (2*a), (-b - sdet) / (2*a)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef cbrt(x):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if x >= 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return x**(1.0/3.0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return -((-x)**(1.0/3.0))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef findRealRoots(a,b,c,d):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if a != 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico a, b, c, d = 1, b/float(a), c/float(a), d/float(a) # Divide through by a
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico t = b / 3.0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico p, q = c - 3 * t**2, d - c * t + 2 * t**3
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico u, v = solveQuadratic(1, q, -(p/3.0)**3)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if type(u) == type(0j): # Complex Cubic Root
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico r = math.sqrt(u.real**2 + u.imag**2)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico w = math.atan2(u.imag, u.real)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico y1 = 2 * cbrt(r) * math.cos(w / 3.0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: # Complex Real Root
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico y1 = cbrt(u) + cbrt(v)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico y2, y3 = solveQuadratic(1, y1, p + y1**2)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if type(y2) == type(0j): # Are y2 and y3 complex?
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return [y1 - t]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return [y1 - t, y2 - t, y3 - t]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif b != 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico det=c*c - 4.0*b*d
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if det >= 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return [(-c + math.sqrt(det))/(2.0*b),(-c - math.sqrt(det))/(2.0*b)]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif c != 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return [-d/c]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return []
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef getPathBoundingBox( sp ):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico box = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lostctrl = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for cmd,params in sp:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if cmd == 'M':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # A move cannot contribute to the bounding box
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'L':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if last:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (min(params[0], last[0]), max(params[0], last[0]), min(params[1], last[1]), max(params[1], last[1]))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'C':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if last:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (min(params[4], last[0]), max(params[4], last[0]), min(params[5], last[1]), max(params[5], last[1]))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx0, by0 = last[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx1, by1, bx2, by2, bx3, by3 = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Compute the x limits
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico a = (-bx0 + 3*bx1 - 3*bx2 + bx3)*3
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico b = (3*bx0 - 6*bx1 + 3*bx2)*2
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico c = (-3*bx0 + 3*bx1)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ts = findRealRoots(0, a, b, c)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for t in ts:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if t >= 0 and t <= 1:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico x = (-bx0 + 3*bx1 - 3*bx2 + bx3)*(t**3) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (3*bx0 - 6*bx1 + 3*bx2)*(t**2) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (-3*bx0 + 3*bx1)*t + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (min(segmentBox[0], x), max(segmentBox[1], x), segmentBox[2], segmentBox[3])
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Compute the y limits
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico a = (-by0 + 3*by1 - 3*by2 + by3)*3
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico b = (3*by0 - 6*by1 + 3*by2)*2
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico c = (-3*by0 + 3*by1)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ts = findRealRoots(0, a, b, c)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for t in ts:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if t >= 0 and t <= 1:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico y = (-by0 + 3*by1 - 3*by2 + by3)*(t**3) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (3*by0 - 6*by1 + 3*by2)*(t**2) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (-3*by0 + 3*by1)*t + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico by0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (segmentBox[0], segmentBox[1], min(segmentBox[2], y), max(segmentBox[3], y))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'Q':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Provisional
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if last:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (min(params[0], last[0]), max(params[0], last[0]), min(params[1], last[1]), max(params[1], last[1]))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'A':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Provisional
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if last:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = (min(params[0], last[0]), max(params[0], last[0]), min(params[1], last[1]), max(params[1], last[1]))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if segmentBox:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if box:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico box = (min(segmentBox[0],box[0]), max(segmentBox[1],box[1]), min(segmentBox[2],box[2]), max(segmentBox[3],box[3]))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico box = segmentBox
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return box
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef mxfm( image, width, height, stack ): # returns possibly transformed image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico tbimage = image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( stack[0] == "-" ): # top-bottom flip
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico flipTopBottom(tbimage, height)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico tbimage = reversePath(tbimage)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.pop( 0 )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lrimage = tbimage
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( stack[0] == "|" ): # left-right flip
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico flipLeftRight(tbimage, width)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico lrimage = reversePath(lrimage)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.pop( 0 )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return lrimage
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef comparerule( rule, nodes ): # compare node list to nodes in rule
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for i in range( 0, len(nodes)): # range( a, b ) = (a, a+1, a+2 ... b-2, b-1)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (nodes[i] == rule[i][0]):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico pass
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: return 0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return 1
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef findrule( state, nodes ): # find the rule which generated this subtree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ruleset = syntax[state][1]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico nodelen = len(nodes)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for rule in ruleset:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico rulelen = len(rule)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ((rulelen == nodelen) and (comparerule( rule, nodes ))):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return rule
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef generate( state ): # generate a random tree (in stack form)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack = [ state ]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( len(syntax[state]) == 1 ): # if this is a stop symbol
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return stack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.append( "[" )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico path = random.randint(0, (len(syntax[state][1])-1)) # choose randomly from next states
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for symbol in syntax[state][1][path]: # recurse down each non-terminal
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( symbol != 0 ): # 0 denotes end of list ###
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico substack = generate( symbol[0] ) # get subtree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for elt in substack:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.append( elt )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (symbol[3]):stack.append( "-" ) # top-bottom flip
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (symbol[4]):stack.append( "|" ) # left-right flip
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #inkex.debug("found end of list in generate( state =", state, ")") # this should be deprecated/never happen
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.append("]")
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return stack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef draw( stack ): # draw a character based on a tree stack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico state = stack.pop(0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #print state,
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image, width, height = loadPath( font+syntax[state][0] ) # load the image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (stack[0] != "["): # terminal stack element
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (len(syntax[state]) == 1): # this state is a terminal node
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return image, width, height
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico substack = generate( state ) # generate random substack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return draw( substack ) # draw random substack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #inkex.debug("[")
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.pop(0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico images = [] # list of daughter images
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico nodes = [] # list of daughter names
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico while (stack[0] != "]"): # for all nodes in stack
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico newstate = stack[0] # the new state
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico newimage, width, height = draw( stack ) # draw the daughter state
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (newimage):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico tfimage = mxfm( newimage, width, height, stack ) # maybe transform daughter state
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico images.append( [tfimage, width, height] ) # list of daughter images
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico nodes.append( newstate ) # list of daughter nodes
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #inkex.debug(("recurse on",newstate,"failed")) # this should never happen
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return None, 0, 0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico rule = findrule( state, nodes ) # find the rule for this subtree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for i in range( 0, len(images)):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico currimg, width, height = images[i]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if currimg:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #box = getPathBoundingBox(currimg)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico dx = rule[i][1]*units
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico dy = rule[i][2]*units
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #newbox = ((box[0]+dx),(box[1]+dy),(box[2]+dx),(box[3]+dy))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico simplepath.translatePath(currimg, dx, dy)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image = combinePaths( image, currimg )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack.pop( 0 )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return image, width, height
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef draw_crop_scale( stack, zoom ): # draw, crop and scale letter image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image, width, height = draw(stack)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bbox = getPathBoundingBox(image)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico simplepath.translatePath(image, -bbox[0], 0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico simplepath.scalePath(image, zoom/units, zoom/units)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return image, bbox[1] - bbox[0], bbox[3] - bbox[2]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicodef randomize_input_string(tokens, zoom ): # generate a glyph starting from each token in the input string
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico imagelist = []
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for i in range(0,len(tokens)):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico char = tokens[i]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #if ( re.match("[a-zA-Z0-9?]", char)):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( alphabet.has_key(char)):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if ((i > 0) and (char == tokens[i-1])): # if this letter matches previous letter
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico imagelist.append(imagelist[len(stack)-1])# make them the same image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: # generate image for letter
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico stack = string.split( alphabet[char][random.randint(0,(len(alphabet[char])-1))] , "." )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico #stack = string.split( alphabet[char][random.randint(0,(len(alphabet[char])-2))] , "." )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico imagelist.append( draw_crop_scale( stack, zoom ))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif( char == " "): # add a " " space to the image list
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico imagelist.append( " " )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: # this character is not in config.alphabet, skip it
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico sys.stderr.write('bad character "%s"\n' % char)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico return imagelist
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicodef generate_random_string( tokens, zoom ): # generate a totally random glyph for each glyph in the input string
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico imagelist = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for char in tokens:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if ( char == " "): # add a " " space to the image list
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico imagelist.append( " " )
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if ( re.match("[a-z]", char )): # generate lowercase letter
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico stack = generate("lc")
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico elif ( re.match("[A-Z]", char )): # generate uppercase letter
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico stack = generate("UC")
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else: # this character is not in config.alphabet, skip it
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico sys.stderr.write('bad character"%s"\n' % char)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico stack = generate("start")
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico imagelist.append( draw_crop_scale( stack, zoom ))
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return imagelist
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef optikern( image, width, zoom ): # optical kerning algorithm
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico left = []
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico right = []
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico resolution = 8
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for i in range( 0, 18 * resolution ):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico y = 1.0/resolution * (i + 0.5) * zoom
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico xmin = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico xmax = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for cmd,params in image:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico segmentBox = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if cmd == 'M':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # A move cannot contribute to the bounding box
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'L':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (y >= last[1] and y <= params[1]) or (y >= params[1] and y <= last[1]):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if params[0] == last[0]:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico x = params[0]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico a = (params[1] - last[1]) / (params[0] - last[0])
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico b = last[1] - a * last[0]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if a != 0:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico x = (y - b) / a
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else: x = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if x:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if xmin == None or x < xmin: xmin = x
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if xmax == None or x > xmax: xmax = x
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'C':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if last:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx0, by0 = last[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx1, by1, bx2, by2, bx3, by3 = params[:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico d = by0 - y
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico c = -3*by0 + 3*by1
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico b = 3*by0 - 6*by1 + 3*by2
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico a = -by0 + 3*by1 - 3*by2 + by3
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ts = findRealRoots(a, b, c, d)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for t in ts:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if t >= 0 and t <= 1:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico x = (-bx0 + 3*bx1 - 3*bx2 + bx3)*(t**3) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (3*bx0 - 6*bx1 + 3*bx2)*(t**2) + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico (-3*bx0 + 3*bx1)*t + \
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico bx0
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if xmin == None or x < xmin: xmin = x
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if xmax == None or x > xmax: xmax = x
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'Q':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Quadratic beziers are ignored
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico elif cmd == 'A':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # Arcs are ignored
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico last = params[-2:]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico lastctrl = params[2:4]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if xmin != None and xmax != None:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico left.append( xmin ) # distance from left edge of region to left edge of bbox
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico right.append( width - xmax ) # distance from right edge of region to right edge of bbox
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico left.append( width )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico right.append( width )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return (left, right)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicodef layoutstring( imagelist, zoom ): # layout string of letter-images using optical kerning
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico kernlist = []
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico length = zoom
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for entry in imagelist:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if (entry == " "): # leaving room for " " space characters
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico length = length + (zoom * render_alphabetsoup_config.space)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image, width, height = entry
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico length = length + width + zoom # add letter length to overall length
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico kernlist.append( optikern(image, width, zoom) ) # append kerning data for this image
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico workspace = None
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico position = zoom
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for i in range(0, len(kernlist)):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico while(imagelist[i] == " "):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico position = position + (zoom * render_alphabetsoup_config.space )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico imagelist.pop(i)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image, width, height = imagelist[i]
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico # set the kerning
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if i == 0: kern = 0 # for first image, kerning is zero
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico else:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico kerncompare = [] # kerning comparison array
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for j in range( 0, len(kernlist[i][0])):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico kerncompare.append( kernlist[i][0][j]+kernlist[i-1][1][j] )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico kern = min( kerncompare )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico position = position - kern # move position back by kern amount
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico thisimage = copy.deepcopy(image)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico simplepath.translatePath(thisimage, position, 0)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico workspace = combinePaths(workspace, thisimage)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico position = position + width + zoom # advance position by letter width
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return workspace
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNicodef tokenize(text):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico """Tokenize the string, looking for LaTeX style, multi-character tokens in the string, like \\yogh."""
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico tokens = []
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico i = 0
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico while i < len(text):
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico c = text[i]
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico i += 1
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if c == '\\': # found the beginning of an escape
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico t = ''
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico while i < len(text): # gobble up content of the escape
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico c = text[i]
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if c == '\\': # found another escape, stop this one
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico break
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico i += 1
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if c == ' ': # a space terminates this escape
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico break
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico t += c # stick this character onto the token
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if t:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico tokens.append(t)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico tokens.append(c)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico return tokens
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoclass AlphabetSoup(inkex.Effect):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico def __init__(self):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico inkex.Effect.__init__(self)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico self.OptionParser.add_option("-t", "--text",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico action="store", type="string",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico dest="text", default="Inkscape",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico help="The text for alphabet soup")
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico self.OptionParser.add_option("-z", "--zoom",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico action="store", type="float",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico dest="zoom", default="8.0",
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico help="The zoom on the output graphics")
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico self.OptionParser.add_option("-r", "--randomize",
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico action="store", type="inkbool",
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico dest="randomize", default=False,
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico help="Generate random (unreadable) text")
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico def effect(self):
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico zoom = self.options.zoom
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if self.options.randomize:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico imagelist = generate_random_string(self.options.text, zoom)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico else:
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico tokens = tokenize(self.options.text)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico imagelist = randomize_input_string(tokens, zoom)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico image = layoutstring( imagelist, zoom )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if image:
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico s = { 'stroke': 'none', 'fill': '#000000' }
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico new = inkex.etree.Element(inkex.addNS('path','svg'))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico new.set('style', simplestyle.formatStyle(s))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico new.set('d', simplepath.formatPath(image))
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico self.current_layer.append(new)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoif __name__ == '__main__':
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico e = AlphabetSoup()
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico e.affect()
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico