root/trunk/Lib/robofab/pens/marginPen.py

Revision 87, 3.2 kB (checked in by erik, 2 years ago)

Removed print statements.

Line 
1 from fontTools.pens.basePen import AbstractPen, BasePen
2 from fontTools.misc.bezierTools import splitLine, splitCubic
3
4
5 from sets import Set
6
7 class MarginPen(BasePen):
8
9         """
10                 Pen to calculate the horizontal margins at a given height.
11                 
12                 When a glyphset or font is given, MarginPen will also calculate for glyphs with components.
13
14                 pen.getMargins() returns the minimum and maximum intersections of the glyph.
15                 pen.getContourMargins() returns the minimum and maximum intersections for each contour.
16                 
17         """
18
19         def __init__(self, glyphSet, height):
20                 BasePen.__init__(self, glyphSet)
21                
22                 self.height = height
23                 self.hits = {}
24                 self.filterDoubles = True
25                 self.contourIndex = None
26                
27         def _moveTo(self, pt):
28                 self.currentPt = pt
29                 if self.contourIndex is None:
30                         self.contourIndex = 0
31                 else:
32                         self.contourIndex += 1
33
34         def _lineTo(self, pt):
35                 if self.filterDoubles:
36                         if pt == self.currentPt:
37                                 return
38                 hits = splitLine(self.currentPt, pt, self.height, True)
39                 if len(hits)>1:
40                         # result will be 2 tuples of 2 coordinates
41                         # first two points: start to intersect
42                         # second two points: intersect to end
43                         # so, second point in first tuple is the intersect
44                         # then, the first coordinate of that point is the x.
45                         if not self.contourIndex in self.hits:
46                                 self.hits[self.contourIndex] = []
47                         self.hits[self.contourIndex].append(round(hits[0][-1][0], 4))
48                 if pt[1] == self.height:
49                         # it could happen
50                         if not self.contourIndex in self.hits:
51                                 self.hits[self.contourIndex] =  []
52                                
53                         self.hits[self.contourIndex].append(pt[0])
54                 self.currentPt = pt
55
56         def _curveToOne(self, pt1, pt2, pt3):
57                 hits = splitCubic(self.currentPt, pt1, pt2, pt3, self.height, True)
58                 if len(hits)==2:
59                         if not self.contourIndex in self.hits:
60                                 self.hits[self.contourIndex] = []
61                         self.hits[self.contourIndex].append(round(hits[0][-1][0], 4))
62                 elif pt3[1] == self.height:
63                         # it could happen
64                         if not self.contourIndex in self.hits:
65                                 self.hits[self.contourIndex] = []
66                         self.hits[self.contourIndex].append(pt3[0])
67                 self.currentPt = pt3
68                
69         def _closePath(self):
70                 self.currentPt = None
71        
72         def _endPath(self):
73                 self.currentPt = None
74                
75         def getMargins(self):
76                 """Get the horizontal margins for all contours combined, i.e. the whole glyph."""
77                 allHits = []
78                 for index, pts in self.hits.items():
79                         allHits.extend(pts)
80                 unique = list(Set(allHits))
81                 unique.sort()
82                 if unique:
83                         return min(unique), max(unique)
84                 return None
85                
86         def getContourMargins(self):
87                 """Get the horizontal margins for each contour."""
88                 allHits = {}
89                 for index, pts in self.hits.items():
90                         unique = list(Set(pts))
91                         unique.sort()
92                         allHits[index] = unique
93                 return allHits
94        
95         def addComponent(self, baseGlyph, transformation):
96                 if self.glyphSet is None:
97                         return
98                 if baseGlyph in self.glyphSet:
99                         glyph = self.glyphSet[baseGlyph]
100                 if glyph is not None:
101                         glyph.draw(self)
102                
103                
104 if __name__ == "__main__":
105
106         from robofab.world import CurrentGlyph, CurrentFont
107         f = CurrentFont()
108         g = CurrentGlyph()
109
110         pt = (100, 249)
111         pen = MarginPen(f, pt[1])
112         g.draw(pen)     
113         print 'glyph margins', pen.getMargins()
114
115         print pen.getContourMargins()
Note: See TracBrowser for help on using the browser.