fonttools/Lib/fontTools/pens/statisticsPen.py
2017-02-24 14:06:58 -08:00

85 lines
2.5 KiB
Python

from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
import math
from fontTools.pens.momentsPen import MomentsPen
__all__ = ["StatisticsPen"]
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):
variance = self.varianceX
return math.copysign(abs(variance)**.5, variance)
@property
def stddevY(self):
variance = self.varianceY
return math.copysign(abs(variance)**.5, variance)
# 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:])