[Snippets/symfont] Add glyph perimeter to GlyphStatistics
This commit is contained in:
parent
f70d264ef0
commit
6bfe6989de
@ -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)))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user