source: trunk/Lib/robofab/pens/angledMarginPen.py @ 599

Revision 471, 3.9 KB checked in by erik, 3 years ago (diff)

Diverts the import of fontTools.misc.arrayTools and fontTools.misc.bezierTools to robofab.misc.arrayTools / robofab.misc.bezierTools.
If the new arrayTools and bezierTools could move to fontTools that would be great too. For the time being, they will live here, making installing Robofab just a tiny bit easier.

Line 
1from robofab.world import RFont
2from fontTools.pens.basePen import BasePen
3from robofab.misc.arrayTools import updateBounds, pointInRect, unionRect
4from robofab.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
5from robofab.pens.filterPen import _estimateCubicCurveLength, _getCubicPoint
6import math
7
8
9
10__all__ = ["AngledMarginPen", "getAngledMargins",
11        "setAngledLeftMargin", "setAngledRightMargin",
12        "centerAngledMargins"]
13
14
15
16class AngledMarginPen(BasePen):
17        """
18                Angled Margin Pen
19
20                Pen to calculate the margins as if the margin lines were slanted
21                according to the font.info.italicAngle.
22
23                Notes:
24                - this pen works on the on-curve points, and approximates the distance to curves.
25                - results will be float.
26                - when used in FontLab, the resulting margins may be slightly
27                        different from the values originally set, due to rounding errors.
28                - similar to what RoboFog used to do.
29                - RoboFog had a special attribute for "italicoffset", horizontal
30                shift of all glyphs. This is missing in Robofab.
31        """
32        def __init__(self, glyphSet, width, italicAngle):
33                BasePen.__init__(self, glyphSet)
34                self.width = width
35                self._angle = math.radians(90+italicAngle)
36                self.maxSteps = 100
37                self.margin = None
38                self._left = None
39                self._right = None
40                self._start = None
41                self.currentPt = None
42       
43        def _getAngled(self, pt):
44                r = (g.width + (pt[1] / math.tan(self._angle)))-pt[0]
45                l = pt[0]-((pt[1] / math.tan(self._angle)))
46                if self._right is None:
47                        self._right = r
48                else:
49                        self._right = min(self._right, r)
50                if self._left is None:
51                        self._left = l
52                else:
53                        self._left = min(self._left, l)
54                #print pt, l, r
55                self.margin = self._left, self._right
56               
57        def _moveTo(self, pt):
58                self._start = self.currentPt = pt
59
60        def _addMoveTo(self):
61                if self._start is None:
62                        return
63                self._start = self.currentPt = None
64
65        def _lineTo(self, pt):
66                self._addMoveTo()
67                self._getAngled(pt)
68
69        def _curveToOne(self, pt1, pt2, pt3):
70                step = 1.0/self.maxSteps
71                factors = range(0, self.maxSteps+1)
72                for i in factors:
73                        pt = _getCubicPoint(i*step, self.currentPt, pt1, pt2, pt3)
74                        self._getAngled(pt)
75                self.currentPt = pt3
76                                       
77        def _qCurveToOne(self, bcp, pt):
78                self._addMoveTo()
79                # add curve tracing magic here.
80                self._getAngled(pt)
81                self.currentPt = pt3
82
83def getAngledMargins(glyph, font):
84        """Get the angled margins for this glyph."""
85        pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
86        glyph.draw(pen)
87        return pen.margin
88       
89def setAngledLeftMargin(glyph, font, value):
90        """Set the left angled margin to value, adjusted for font.info.italicAngle."""
91        pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
92        g.draw(pen)
93        isLeft, isRight = pen.margin
94        glyph.leftMargin += value-isLeft
95       
96def setAngledRightMargin(glyph, font, value):
97        """Set the right angled margin to value, adjusted for font.info.italicAngle."""
98        pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
99        g.draw(pen)
100        isLeft, isRight = pen.margin
101        glyph.rightMargin += value-isRight
102
103def centerAngledMargins(glyph, font):
104        """Center the glyph on angled margins."""
105        pen = AngledMarginPen(font, glyph.width, font.info.italicAngle)
106        g.draw(pen)
107        isLeft, isRight = pen.margin
108        setAngledLeftMargin(glyph, font, (isLeft+isRight)*.5)
109        setAngledRightMargin(glyph, font, (isLeft+isRight)*.5)
110       
111def guessItalicOffset(glyph, font):
112        """Guess the italic offset based on the margins of a symetric glyph.
113                For instance H or I.
114        """
115        l, r = getAngledMargins(glyph, font)
116        return l - (l+r)*.5
117
118
119if __name__ == "__main__":
120       
121        # example for FontLab, with a glyph open.
122        from robofab.world import CurrentFont, CurrentGlyph
123        g = CurrentGlyph()
124        f = CurrentFont()
125
126        print "margins!", getAngledMargins(g, f)
127        # set the angled margin to a value
128        m = 50
129        setAngledLeftMargin(g, f, m)
130        setAngledRightMargin(g, f, m)
131        g.update()
132
Note: See TracBrowser for help on using the repository browser.