The approximation can be improved upon, perhaps taking the size of the bezier into account and so on. Also the italic offset, as it was used in RoboFog is missing, and could perhaps be taken into account. git-svn-id: http://svn.robofab.com/trunk@85 b5fa9d6c-a76f-4ffd-b3cb-f825fc41095c
133 lines
3.9 KiB
Python
133 lines
3.9 KiB
Python
from robofab.world import RFont
|
|
from fontTools.pens.basePen import BasePen
|
|
from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
|
|
from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
|
|
from robofab.pens.filterPen import _estimateCubicCurveLength, _getCubicPoint
|
|
import math
|
|
|
|
|
|
|
|
__all__ = ["AngledMarginPen", "getAngledMargins",
|
|
"setAngledLeftMargin", "setAngledRightMargin",
|
|
"centerAngledMargins"]
|
|
|
|
|
|
|
|
class AngledMarginPen(BasePen):
|
|
"""
|
|
Angled Margin Pen
|
|
|
|
Pen to calculate the margins as if the margin lines were slanted
|
|
according to the font.info.italicAngle.
|
|
|
|
Notes:
|
|
- this pen works on the on-curve points, and approximates the distance to curves.
|
|
- results will be float.
|
|
- when used in FontLab, the resulting margins may be slightly
|
|
different from the values originally set, due to rounding errors.
|
|
- similar to what RoboFog used to do.
|
|
- RoboFog had a special attribute for "italicoffset", horizontal
|
|
shift of all glyphs. This is missing in Robofab.
|
|
"""
|
|
def __init__(self, glyphSet, width, italicAngle):
|
|
BasePen.__init__(self, glyphSet)
|
|
self.width = width
|
|
self._angle = math.radians(90+italicAngle)
|
|
self.maxSteps = 100
|
|
self.margin = None
|
|
self._left = None
|
|
self._right = None
|
|
self._start = None
|
|
self.currentPt = None
|
|
|
|
def _getAngled(self, pt):
|
|
r = (g.width + (pt[1] / math.tan(self._angle)))-pt[0]
|
|
l = pt[0]-((pt[1] / math.tan(self._angle)))
|
|
if self._right is None:
|
|
self._right = r
|
|
else:
|
|
self._right = min(self._right, r)
|
|
if self._left is None:
|
|
self._left = l
|
|
else:
|
|
self._left = min(self._left, l)
|
|
#print pt, l, r
|
|
self.margin = self._left, self._right
|
|
|
|
def _moveTo(self, pt):
|
|
self._start = self.currentPt = pt
|
|
|
|
def _addMoveTo(self):
|
|
if self._start is None:
|
|
return
|
|
self._start = self.currentPt = None
|
|
|
|
def _lineTo(self, pt):
|
|
self._addMoveTo()
|
|
self._getAngled(pt)
|
|
|
|
def _curveToOne(self, pt1, pt2, pt3):
|
|
step = 1.0/self.maxSteps
|
|
factors = range(0, self.maxSteps+1)
|
|
for i in factors:
|
|
pt = _getCubicPoint(i*step, self.currentPt, pt1, pt2, pt3)
|
|
self._getAngled(pt)
|
|
self.currentPt = pt3
|
|
|
|
def _qCurveToOne(self, bcp, pt):
|
|
self._addMoveTo()
|
|
# add curve tracing magic here.
|
|
self._getAngled(pt)
|
|
self.currentPt = pt3
|
|
|
|
def getAngledMargins(glyph, font):
|
|
"""Get the angled margins for this glyph."""
|
|
pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
|
|
glyph.draw(pen)
|
|
return pen.margin
|
|
|
|
def setAngledLeftMargin(glyph, font, value):
|
|
"""Set the left angled margin to value, adjusted for font.info.italicAngle."""
|
|
pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
|
|
g.draw(pen)
|
|
isLeft, isRight = pen.margin
|
|
glyph.leftMargin += value-isLeft
|
|
|
|
def setAngledRightMargin(glyph, font, value):
|
|
"""Set the right angled margin to value, adjusted for font.info.italicAngle."""
|
|
pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
|
|
g.draw(pen)
|
|
isLeft, isRight = pen.margin
|
|
glyph.rightMargin += value-isRight
|
|
|
|
def centerAngledMargins(glyph, font):
|
|
"""Center the glyph on angled margins."""
|
|
pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
|
|
g.draw(pen)
|
|
isLeft, isRight = pen.margin
|
|
setAngledLeftMargin(glyph, font, (isLeft+isRight)*.5)
|
|
setAngledRightMargin(glyph, font, (isLeft+isRight)*.5)
|
|
|
|
def guessItalicOffset(glyph, font):
|
|
"""Guess the italic offset based on the margins of a symetric glyph.
|
|
For instance H or I.
|
|
"""
|
|
l, r = getAngledMargins(glyph, font)
|
|
return l - (l+r)*.5
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
# example for FontLab, with a glyph open.
|
|
from robofab.world import CurrentFont, CurrentGlyph
|
|
g = CurrentGlyph()
|
|
f = CurrentFont()
|
|
|
|
print "margins!", getAngledMargins(g, f)
|
|
# set the angled margin to a value
|
|
m = 50
|
|
setAngledLeftMargin(g, f, m)
|
|
setAngledRightMargin(g, f, m)
|
|
g.update()
|
|
|