Move StatisticsPen into fontTools.pens.statisticsPen
This commit is contained in:
parent
5cbfaa2792
commit
f3224d7d34
79
Lib/fontTools/pens/statisticsPen.py
Normal file
79
Lib/fontTools/pens/statisticsPen.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
from __future__ import print_function, division, absolute_import
|
||||||
|
from fontTools.misc.py23 import *
|
||||||
|
import math
|
||||||
|
from fontTools.pens.momentsPen import MomentsPen
|
||||||
|
|
||||||
|
class StatisticsPen(MomentsPen):
|
||||||
|
|
||||||
|
# Center of mass
|
||||||
|
# https://en.wikipedia.org/wiki/Center_of_mass#A_continuous_volume
|
||||||
|
@property
|
||||||
|
def meanX(self):
|
||||||
|
return self.momentX / self.area if self.area else 0
|
||||||
|
@property
|
||||||
|
def meanY(self):
|
||||||
|
return self.momentY / self.area if self.area else 0
|
||||||
|
|
||||||
|
# Var(X) = E[X^2] - E[X]^2
|
||||||
|
@property
|
||||||
|
def varianceX(self):
|
||||||
|
return self.momentXX / self.area - self.meanX**2 if self.area else 0
|
||||||
|
@property
|
||||||
|
def varianceY(self):
|
||||||
|
return self.momentYY / self.area - self.meanY**2 if self.area else 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stddevX(self):
|
||||||
|
return math.copysign(abs(self.varianceX)**.5, self.varianceX)
|
||||||
|
@property
|
||||||
|
def stddevY(self):
|
||||||
|
return math.copysign(abs(self.varianceY)**.5, self.varianceY)
|
||||||
|
|
||||||
|
# Covariance(X,Y) = ( E[X.Y] - E[X]E[Y] )
|
||||||
|
@property
|
||||||
|
def covariance(self):
|
||||||
|
return self.momentXY / self.area - self.meanX*self.meanY if self.area else 0
|
||||||
|
|
||||||
|
# Correlation(X,Y) = Covariance(X,Y) / ( stddev(X) * stddev(Y) )
|
||||||
|
# https://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient
|
||||||
|
@property
|
||||||
|
def correlation(self):
|
||||||
|
correlation = self.covariance / (self.stddevX * self.stddevY) if self.area else 0
|
||||||
|
return correlation if abs(correlation) > 1e-3 else 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def slant(self):
|
||||||
|
slant = self.covariance / self.varianceY if self.area else 0
|
||||||
|
return slant if abs(slant) > 1e-3 else 0
|
||||||
|
|
||||||
|
|
||||||
|
def _test(glyphset, upem, glyphs):
|
||||||
|
from fontTools.pens.transformPen import TransformPen
|
||||||
|
from fontTools.misc.transform import Scale
|
||||||
|
|
||||||
|
print('upem', upem)
|
||||||
|
|
||||||
|
for glyph_name in glyphs:
|
||||||
|
print()
|
||||||
|
print("glyph:", glyph_name)
|
||||||
|
glyph = glyphset[glyph_name]
|
||||||
|
pen = StatisticsPen(glyphset=glyphset)
|
||||||
|
transformer = TransformPen(pen, Scale(1./upem))
|
||||||
|
glyph.draw(transformer)
|
||||||
|
for item in ['area', 'momentX', 'momentY', 'momentXX', 'momentYY', 'momentXY', 'meanX', 'meanY', 'varianceX', 'varianceY', 'stddevX', 'stddevY', 'covariance', 'correlation', 'slant']:
|
||||||
|
if item[0] == '_': continue
|
||||||
|
print ("%s: %g" % (item, getattr(pen, item)))
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
if not args:
|
||||||
|
return
|
||||||
|
filename, glyphs = args[0], args[1:]
|
||||||
|
if not glyphs:
|
||||||
|
glyphs = ['e', 'o', 'I', 'slash', 'E', 'zero', 'eight', 'minus', 'equal']
|
||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
font = TTFont(filename)
|
||||||
|
_test(font.getGlyphSet(), font['head'].unitsPerEm, glyphs)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
main(sys.argv[1:])
|
@ -9,7 +9,7 @@ from __future__ import print_function, division, absolute_import
|
|||||||
from fontTools.misc.py23 import *
|
from fontTools.misc.py23 import *
|
||||||
|
|
||||||
from fontTools.pens.basePen import BasePen
|
from fontTools.pens.basePen import BasePen
|
||||||
from symfont import StatisticsPen
|
from fontTools.pens.statisticsPen import StatisticsPen
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
class PerContourOrComponentPen(BasePen):
|
class PerContourOrComponentPen(BasePen):
|
||||||
|
@ -12,11 +12,7 @@ from fontTools.misc.py23 import *
|
|||||||
|
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sys
|
import sys
|
||||||
import math
|
|
||||||
from fontTools.pens.basePen import BasePen
|
from fontTools.pens.basePen import BasePen
|
||||||
from fontTools.pens.transformPen import TransformPen
|
|
||||||
from fontTools.pens.momentsPen import MomentsPen
|
|
||||||
from fontTools.misc.transform import Scale
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
@ -188,79 +184,3 @@ MomentXYPen = partial(GreenPen, func=x*y)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Glyph statistics object
|
|
||||||
#
|
|
||||||
|
|
||||||
class StatisticsPen(MomentsPen):
|
|
||||||
|
|
||||||
# Center of mass
|
|
||||||
# https://en.wikipedia.org/wiki/Center_of_mass#A_continuous_volume
|
|
||||||
@property
|
|
||||||
def meanX(self):
|
|
||||||
return self.momentX / self.area if self.area else 0
|
|
||||||
@property
|
|
||||||
def meanY(self):
|
|
||||||
return self.momentY / self.area if self.area else 0
|
|
||||||
|
|
||||||
# Var(X) = E[X^2] - E[X]^2
|
|
||||||
@property
|
|
||||||
def varianceX(self):
|
|
||||||
return self.momentXX / self.area - self.meanX**2 if self.area else 0
|
|
||||||
@property
|
|
||||||
def varianceY(self):
|
|
||||||
return self.momentYY / self.area - self.meanY**2 if self.area else 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def stddevX(self):
|
|
||||||
return math.copysign(abs(self.varianceX)**.5, self.varianceX)
|
|
||||||
@property
|
|
||||||
def stddevY(self):
|
|
||||||
return math.copysign(abs(self.varianceY)**.5, self.varianceY)
|
|
||||||
|
|
||||||
# Covariance(X,Y) = ( E[X.Y] - E[X]E[Y] )
|
|
||||||
@property
|
|
||||||
def covariance(self):
|
|
||||||
return self.momentXY / self.area - self.meanX*self.meanY if self.area else 0
|
|
||||||
|
|
||||||
# Correlation(X,Y) = Covariance(X,Y) / ( stddev(X) * stddev(Y) )
|
|
||||||
# https://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient
|
|
||||||
@property
|
|
||||||
def correlation(self):
|
|
||||||
correlation = self.covariance / (self.stddevX * self.stddevY) if self.area else 0
|
|
||||||
return correlation if abs(correlation) > 1e-3 else 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def slant(self):
|
|
||||||
slant = self.covariance / self.varianceY if self.area else 0
|
|
||||||
return slant if abs(slant) > 1e-3 else 0
|
|
||||||
|
|
||||||
|
|
||||||
def test(glyphset, upem, glyphs):
|
|
||||||
print('upem', upem)
|
|
||||||
|
|
||||||
for glyph_name in glyphs:
|
|
||||||
print()
|
|
||||||
print("glyph:", glyph_name)
|
|
||||||
glyph = glyphset[glyph_name]
|
|
||||||
pen = StatisticsPen(glyphset=glyphset)
|
|
||||||
transformer = TransformPen(pen, Scale(1./upem))
|
|
||||||
glyph.draw(transformer)
|
|
||||||
for item in ['area', 'momentX', 'momentY', 'momentXX', 'momentYY', 'momentXY', 'meanX', 'meanY', 'varianceX', 'varianceY', 'stddevX', 'stddevY', 'covariance', 'correlation', 'slant']:
|
|
||||||
if item[0] == '_': continue
|
|
||||||
print ("%s: %g" % (item, getattr(pen, item)))
|
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
if not args:
|
|
||||||
return
|
|
||||||
filename, glyphs = args[0], args[1:]
|
|
||||||
if not glyphs:
|
|
||||||
glyphs = ['e', 'o', 'I', 'slash', 'E', 'zero', 'eight', 'minus', 'equal']
|
|
||||||
from fontTools.ttLib import TTFont
|
|
||||||
font = TTFont(filename)
|
|
||||||
test(font.getGlyphSet(), font['head'].unitsPerEm, glyphs)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
main(sys.argv[1:])
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user