fonttools/Lib/robofab/pens/angledMarginPen.py
Erik van Blokland 3950975a77 AngledMarginPen calculates the left and right side-bearings of a glyph, relative to slanted margins. The angle is taken from font.info.italicAngle. Curves are approximated. This also contains 5 convenience functions to set and get individual margins and to center the glyph.
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
2008-05-27 09:00:58 +00:00

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()