diff --git a/Snippets/symfont.py b/Lib/fontTools/misc/symfont.py old mode 100755 new mode 100644 similarity index 95% rename from Snippets/symfont.py rename to Lib/fontTools/misc/symfont.py index 3ccb283d0..ca13d7fcd --- a/Snippets/symfont.py +++ b/Lib/fontTools/misc/symfont.py @@ -1,13 +1,10 @@ -#! /usr/bin/env python - from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * - -import sympy as sp -import sys from fontTools.pens.basePen import BasePen from functools import partial from itertools import count +import sympy as sp +import sys n = 3 # Max Bezier degree; 3 for cubic, 2 for quadratic @@ -40,86 +37,13 @@ BezierCurveC = tuple( sum(C[i]*bernstein for i,bernstein in enumerate(bernsteins)) for n,bernsteins in enumerate(BernsteinPolynomial)) + def green(f, curveXY): f = -sp.integrate(sp.sympify(f), y) f = f.subs({x:curveXY[0], y:curveXY[1]}) f = sp.integrate(f * sp.diff(curveXY[0], t), (t, 0, 1)) return f -def printPen(penName, funcs, file=sys.stdout): - print( -'''from __future__ import print_function, division, absolute_import -from fontTools.misc.py23 import * -from fontTools.pens.basePen import BasePen - -class %s(BasePen): - - def __init__(self, glyphset=None): - BasePen.__init__(self, glyphset) -'''%penName, file=file) - for name,f in funcs: - print(' self.%s = 0' % name, file=file) - print(''' - def _moveTo(self, p0): - self.__startPoint = p0 - - def _closePath(self): - p0 = self._getCurrentPoint() - if p0 != self.__startPoint: - self._lineTo(self.__startPoint) - - def _endPath(self): - p0 = self._getCurrentPoint() - if p0 != self.__startPoint: - # Green theorem is not defined on open contours. - raise NotImplementedError -''', end='', file=file) - - for n in (1, 2, 3): - - if n == 1: - print(''' - def _lineTo(self, p1): - x0,y0 = self._getCurrentPoint() - x1,y1 = p1 -''', file=file) - elif n == 2: - print(''' - def _qCurveToOne(self, p1, p2): - x0,y0 = self._getCurrentPoint() - x1,y1 = p1 - x2,y2 = p2 -''', file=file) - elif n == 3: - print(''' - def _curveToOne(self, p1, p2, p3): - x0,y0 = self._getCurrentPoint() - x1,y1 = p1 - x2,y2 = p2 - x3,y3 = p3 -''', file=file) - subs = {P[i][j]: [X, Y][j][i] for i in range(n+1) for j in range(2)} - greens = [green(f, BezierCurve[n]) for name,f in funcs] - greens = [sp.gcd_terms(f.collect(sum(P,()))) for f in greens] # Optimize - greens = [f.subs(subs) for f in greens] # Convert to p to x/y - defs, exprs = sp.cse(greens, - optimizations='basic', - symbols=(sp.Symbol('r%d'%i) for i in count())) - for name,value in defs: - print(' %s = %s' % (name, value), file=file) - print(file=file) - for name,value in zip([f[0] for f in funcs], exprs): - print(' self.%s += %s' % (name, value), file=file) - - print(''' -if __name__ == '__main__': - from symfont import x, y, printPen - printPen('%s', ['''%penName, file=file) - for name,f in funcs: - print(" ('%s', %s)," % (name, str(f)), file=file) - print(' ])', file=file) - - class BezierFuncs(dict): def __init__(self, symfunc): @@ -185,6 +109,81 @@ MomentYYPen = partial(GreenPen, func=y*y) MomentXYPen = partial(GreenPen, func=x*y) +def printGreenPen(penName, funcs, file=sys.stdout): + + print( +'''from __future__ import print_function, division, absolute_import +from fontTools.misc.py23 import * +from fontTools.pens.basePen import BasePen + +class %s(BasePen): + + def __init__(self, glyphset=None): + BasePen.__init__(self, glyphset) +'''%penName, file=file) + for name,f in funcs: + print(' self.%s = 0' % name, file=file) + print(''' + def _moveTo(self, p0): + self.__startPoint = p0 + + def _closePath(self): + p0 = self._getCurrentPoint() + if p0 != self.__startPoint: + self._lineTo(self.__startPoint) + + def _endPath(self): + p0 = self._getCurrentPoint() + if p0 != self.__startPoint: + # Green theorem is not defined on open contours. + raise NotImplementedError +''', end='', file=file) + + for n in (1, 2, 3): + + if n == 1: + print(''' + def _lineTo(self, p1): + x0,y0 = self._getCurrentPoint() + x1,y1 = p1 +''', file=file) + elif n == 2: + print(''' + def _qCurveToOne(self, p1, p2): + x0,y0 = self._getCurrentPoint() + x1,y1 = p1 + x2,y2 = p2 +''', file=file) + elif n == 3: + print(''' + def _curveToOne(self, p1, p2, p3): + x0,y0 = self._getCurrentPoint() + x1,y1 = p1 + x2,y2 = p2 + x3,y3 = p3 +''', file=file) + subs = {P[i][j]: [X, Y][j][i] for i in range(n+1) for j in range(2)} + greens = [green(f, BezierCurve[n]) for name,f in funcs] + greens = [sp.gcd_terms(f.collect(sum(P,()))) for f in greens] # Optimize + greens = [f.subs(subs) for f in greens] # Convert to p to x/y + defs, exprs = sp.cse(greens, + optimizations='basic', + symbols=(sp.Symbol('r%d'%i) for i in count())) + for name,value in defs: + print(' %s = %s' % (name, value), file=file) + print(file=file) + for name,value in zip([f[0] for f in funcs], exprs): + print(' self.%s += %s' % (name, value), file=file) + + print(''' +if __name__ == '__main__': + from fontTools.misc.symfont import x, y, printGreenPen + printGreenPen('%s', ['''%penName, file=file) + for name,f in funcs: + print(" ('%s', %s)," % (name, str(f)), file=file) + print(' ])', file=file) + + if __name__ == '__main__': pen = AreaPen() pen.moveTo((100,100)) diff --git a/Lib/fontTools/pens/momentsPen.py b/Lib/fontTools/pens/momentsPen.py index 95582ebd6..b0d546724 100644 --- a/Lib/fontTools/pens/momentsPen.py +++ b/Lib/fontTools/pens/momentsPen.py @@ -277,12 +277,12 @@ class MomentsPen(BasePen): self.momentYY += -r108*r121/9240 - r133*r73/9240 - r134*x3/12 - r135*r55/9240 - 3*r136*(r25 + r37)/3080 - r137*(r25 + r31 + x3)/660 + r26*(r135 + 126*r46 + 378*y2*y3)/9240 + r5*(r110*r127 + 27*r133 + 42*r134 + r138 + 70*r139 + r46*r62 + 27*r51*y2 + 15*r51*y3)/9240 - r52*(r56 + r63 + r78 + r79)/9240 - r53*(r128 + r25*y3 + 42*r43 + r82 + 42*r83 + 210*r84)/9240 - r6*(r114*x3 + r116 - 14*r119 + 84*r45)/9240 + x0*(r104*r51 + r109*r64 + 90*r110*y3 + r113*y0 + r114*y0 + r129*y1 + r132*y2 + 45*r133 + 14*r134 + 126*r136 + 770*r137 + r138 + 42*r139 + 135*r46*y1 + 14*r53*y3 + r64*r90 + r66*y3 + r69*y3 + r70*y0)/9240 - y0*(90*r118 + 63*r120 + r123 - 18*r124 - 30*r125 + 162*r126 - 27*r130 - 9*r131 + r36*y3 + 30*r43*y3 + 42*r45 + r48 + r51*r93)/9240 if __name__ == '__main__': - from symfont import x, y, printPen - printPen('MomentsPen', [ - ('area', 1), - ('momentX', x), - ('momentY', y), - ('momentXX', x**2), - ('momentXY', x*y), - ('momentYY', y**2), - ]) + from fontTools.misc.symfont import x, y, printGreenPen + printGreenPen('MomentsPen', [ + ('area', 1), + ('momentX', x), + ('momentY', y), + ('momentXX', x**2), + ('momentXY', x*y), + ('momentYY', y**2), + ])