summaryrefslogtreecommitdiff
path: root/misc/pylib/robofab/pens/angledMarginPen.py
blob: 49ff8eed32ef5eb8cb093609b52e77ff86f70651 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from robofab.world import RFont
from fontTools.pens.basePen import BasePen
from robofab.misc.arrayTools import updateBounds, pointInRect, unionRect
from robofab.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()