[Snippets/symfont] Add glyph perimeter to GlyphStatistics

This commit is contained in:
Behdad Esfahbod 2016-03-28 15:47:19 -07:00
parent f70d264ef0
commit 6bfe6989de

View File

@ -13,6 +13,9 @@ from fontTools.misc.py23 import *
import sympy as sp import sympy as sp
import math import math
from fontTools.pens.basePen import BasePen from fontTools.pens.basePen import BasePen
from fontTools.pens.transformPen import TransformPen
from fontTools.misc.transform import Scale
from fontTools.misc.bezierTools import splitCubicAtT
from functools import partial from functools import partial
n = 3 # Max Bezier degree; 3 for cubic, 2 for quadratic n = 3 # Max Bezier degree; 3 for cubic, 2 for quadratic
@ -71,15 +74,12 @@ def getGreenBezierFuncs(func):
class GreenPen(BasePen): class GreenPen(BasePen):
def __init__(self, glyphset, func, scale=1): def __init__(self, func, glyphset=None):
BasePen.__init__(self, glyphset) BasePen.__init__(self, glyphset)
self._funcs = getGreenBezierFuncs(func) self._funcs = getGreenBezierFuncs(func)
self._scale = scale
self.value = 0 self.value = 0
def _segment(self, *P): def _segment(self, *P):
scale = self._scale
P = tuple((x/scale,y/scale) for x,y in P)
self.value += self._funcs[len(P) - 1](P) self.value += self._funcs[len(P) - 1](P)
def _moveTo(self, p0): def _moveTo(self, p0):
@ -97,7 +97,6 @@ class GreenPen(BasePen):
p0 = self._getCurrentPoint() p0 = self._getCurrentPoint()
self._segment(p0,p1,p2,p3) self._segment(p0,p1,p2,p3)
AreaPen = partial(GreenPen, func=1) AreaPen = partial(GreenPen, func=1)
Moment1XPen = partial(GreenPen, func=x) Moment1XPen = partial(GreenPen, func=x)
Moment1YPen = partial(GreenPen, func=y) Moment1YPen = partial(GreenPen, func=y)
@ -105,23 +104,56 @@ Moment2XXPen = partial(GreenPen, func=x*x)
Moment2YYPen = partial(GreenPen, func=y*y) Moment2YYPen = partial(GreenPen, func=y*y)
Moment2XYPen = partial(GreenPen, func=x*y) Moment2XYPen = partial(GreenPen, func=x*y)
def distance(p0, p1):
return math.hypot(p0[0] - p1[0], p0[1] - p1[1])
class PerimeterPen(BasePen):
def __init__(self, tolerance=0.005, glyphset=None):
BasePen.__init__(self, glyphset)
self.value = 0
self._mult = 1.+tolerance
def _moveTo(self, p0):
pass
def _lineTo(self, p1):
p0 = self._getCurrentPoint()
self.value += distance(p0, p1)
def _addCubic(self, p0, p1, p2, p3):
arch = distance(p0, p3)
box = distance(p0, p1) + distance(p1, p2) + distance(p2, p3)
if arch * self._mult >= box:
self.value += (arch + box) * .5
else:
for c in splitCubicAtT(p0,p1,p2,p3,.5):
self._addCubic(*c)
def _curveToOne(self, p1, p2, p3):
p0 = self._getCurrentPoint()
self._addCubic(p0, p1, p2, p3)
class GlyphStatistics(object): class GlyphStatistics(object):
def __init__(self, glyph, glyphset=None, scale=1): def __init__(self, glyph, transform=None, glyphset=None):
self._glyph = glyph self._glyph = glyph
self._glyphset = glyphset self._glyphset = glyphset
self._scale = scale self._transform = transform
def _penAttr(self, attr): def _penAttr(self, attr):
internalName = '_'+attr internalName = '_'+attr
if internalName not in self.__dict__: if internalName not in self.__dict__:
Pen = globals()[attr+'Pen'] Pen = globals()[attr+'Pen']
pen = Pen(self._glyphset, scale=self._scale) pen = transformer = Pen(glyphset=self._glyphset)
self._glyph.draw(pen) if self._transform:
transformer = TransformPen(pen, self._transform)
self._glyph.draw(transformer)
self.__dict__[internalName] = pen.value self.__dict__[internalName] = pen.value
return self.__dict__[internalName] return self.__dict__[internalName]
Area = property(partial(_penAttr, attr='Area')) Area = property(partial(_penAttr, attr='Area'))
Perimeter = property(partial(_penAttr, attr='Perimeter'))
Moment1X = property(partial(_penAttr, attr='Moment1X')) Moment1X = property(partial(_penAttr, attr='Moment1X'))
Moment1Y = property(partial(_penAttr, attr='Moment1Y')) Moment1Y = property(partial(_penAttr, attr='Moment1Y'))
Moment2XX = property(partial(_penAttr, attr='Moment2XX')) Moment2XX = property(partial(_penAttr, attr='Moment2XX'))
@ -196,7 +228,7 @@ def test(glyphset, upem, glyphs):
print() print()
print("glyph:", glyph_name) print("glyph:", glyph_name)
glyph = glyphset[glyph_name] glyph = glyphset[glyph_name]
stats = GlyphStatistics(glyph, glyphset, scale=upem) stats = GlyphStatistics(glyph, transform=Scale(1./upem), glyphset=glyphset)
for item in dir(stats): for item in dir(stats):
if item[0] == '_': continue if item[0] == '_': continue
print ("%s: %g" % (item, getattr(stats, item))) print ("%s: %g" % (item, getattr(stats, item)))