diff options
author | Rasmus Andersson <rasmus@notion.se> | 2018-09-03 22:55:49 +0300 |
---|---|---|
committer | Rasmus Andersson <rasmus@notion.se> | 2018-09-03 22:55:49 +0300 |
commit | c833e252c925e8dd68108660710ca835d95daa6f (patch) | |
tree | 6b2e28264ed45efd7f054e453b622098d0d875b8 /misc/pylib/robofab/pens/flPen.py | |
parent | 8c1a4c181ef12000179dfec541f1af87e9b03122 (diff) | |
download | inter-c833e252c925e8dd68108660710ca835d95daa6f.tar.xz |
Major overhaul, moving from UFO2 to Glyphs and UFO3, plus a brand new and much simpler fontbuild
Diffstat (limited to 'misc/pylib/robofab/pens/flPen.py')
-rwxr-xr-x | misc/pylib/robofab/pens/flPen.py | 274 |
1 files changed, 0 insertions, 274 deletions
diff --git a/misc/pylib/robofab/pens/flPen.py b/misc/pylib/robofab/pens/flPen.py deleted file mode 100755 index d5a867cd9..000000000 --- a/misc/pylib/robofab/pens/flPen.py +++ /dev/null @@ -1,274 +0,0 @@ -"""Pens for creating glyphs in FontLab.""" - - -__all__ = ["FLPen", "FLPointPen", "drawFLGlyphOntoPointPen"] - - -from FL import * - -try: - from fl_cmd import * -except ImportError: - print "The fl_cmd module is not available here. flPen.py" - -from robofab.tools.toolsFL import NewGlyph -from robofab.pens.pointPen import AbstractPointPen -from robofab.pens.adapterPens import SegmentToPointPen - - -def roundInt(x): - return int(round(x)) - - -class FLPen(SegmentToPointPen): - - def __init__(self, glyph): - SegmentToPointPen.__init__(self, FLPointPen(glyph)) - - -class FLPointPen(AbstractPointPen): - - def __init__(self, glyph): - if hasattr(glyph, "isRobofab"): - self.glyph = glyph.naked() - else: - self.glyph = glyph - self.currentPath = None - - def beginPath(self): - self.currentPath = [] - - def endPath(self): - # Love is... abstracting away FL's madness. - path = self.currentPath - self.currentPath = None - glyph = self.glyph - if len(path) == 1 and path[0][3] is not None: - # Single point on the contour, it has a name. Make it an anchor. - x, y = path[0][0] - name = path[0][3] - anchor = Anchor(name, roundInt(x), roundInt(y)) - glyph.anchors.append(anchor) - return - firstOnCurveIndex = None - for i in range(len(path)): - if path[i][1] is not None: - firstOnCurveIndex = i - break - if firstOnCurveIndex is None: - # TT special case: on-curve-less contour. FL doesn't support that, - # so we insert an implied point at the end. - x1, y1 = path[0][0] - x2, y2 = path[-1][0] - impliedPoint = 0.5 * (x1 + x2), 0.5 * (y1 + y2) - path.append((impliedPoint, "qcurve", True, None)) - firstOnCurveIndex = 0 - path = path[firstOnCurveIndex + 1:] + path[:firstOnCurveIndex + 1] - firstPoint, segmentType, smooth, name = path[-1] - closed = True - if segmentType == "move": - path = path[:-1] - closed = False - # XXX The contour is not closed, but I can't figure out how to - # create an open contour in FL. Creating one by hand shows type"0x8011" - # for a move node in an open contour, but I'm not able to access - # that flag. - elif segmentType == "line": - # The contour is closed and ends in a lineto, which is redundant - # as it's implied by closepath. - path = path[:-1] - x, y = firstPoint - node = Node(nMOVE, Point(roundInt(x), roundInt(y))) - if smooth and closed: - if segmentType == "line" or path[0][1] == "line": - node.alignment = nFIXED - else: - node.alignment = nSMOOTH - glyph.Insert(node, len(glyph)) - segment = [] - nPoints = len(path) - for i in range(nPoints): - pt, segmentType, smooth, name = path[i] - segment.append(pt) - if segmentType is None: - continue - if segmentType == "curve": - if len(segment) < 2: - segmentType = "line" - elif len(segment) == 2: - segmentType = "qcurve" - if segmentType == "qcurve": - for x, y in segment[:-1]: - glyph.Insert(Node(nOFF, Point(roundInt(x), roundInt(y))), len(glyph)) - x, y = segment[-1] - node = Node(nLINE, Point(roundInt(x), roundInt(y))) - glyph.Insert(node, len(glyph)) - elif segmentType == "curve": - if len(segment) == 3: - cubicSegments = [segment] - else: - from fontTools.pens.basePen import decomposeSuperBezierSegment - cubicSegments = decomposeSuperBezierSegment(segment) - nSegments = len(cubicSegments) - for i in range(nSegments): - pt1, pt2, pt3 = cubicSegments[i] - x, y = pt3 - node = Node(nCURVE, Point(roundInt(x), roundInt(y))) - node.points[1].x, node.points[1].y = roundInt(pt1[0]), roundInt(pt1[1]) - node.points[2].x, node.points[2].y = roundInt(pt2[0]), roundInt(pt2[1]) - if i != nSegments - 1: - node.alignment = nSMOOTH - glyph.Insert(node, len(self.glyph)) - elif segmentType == "line": - assert len(segment) == 1, segment - x, y = segment[0] - node = Node(nLINE, Point(roundInt(x), roundInt(y))) - glyph.Insert(node, len(glyph)) - else: - assert 0, "unsupported curve type (%s)" % segmentType - if smooth: - if i + 1 < nPoints or closed: - # Can't use existing node, as you can't change node attributes - # AFTER it's been appended to the glyph. - node = glyph[-1] - if segmentType == "line" or path[(i+1) % nPoints][1] == "line": - # tangent - node.alignment = nFIXED - else: - # curve - node.alignment = nSMOOTH - segment = [] - if closed: - # we may have output a node too much - node = glyph[-1] - if node.type == nLINE and (node.x, node.y) == (roundInt(firstPoint[0]), roundInt(firstPoint[1])): - glyph.DeleteNode(len(glyph) - 1) - - def addPoint(self, pt, segmentType=None, smooth=None, name=None, **kwargs): - self.currentPath.append((pt, segmentType, smooth, name)) - - def addComponent(self, baseName, transformation): - assert self.currentPath is None - # make base glyph if needed, Component() needs the index - NewGlyph(self.glyph.parent, baseName, updateFont=False) - baseIndex = self.glyph.parent.FindGlyph(baseName) - if baseIndex == -1: - raise KeyError, "couldn't find or make base glyph" - xx, xy, yx, yy, dx, dy = transformation - # XXX warn when xy or yx != 0 - new = Component(baseIndex, Point(dx, dy), Point(xx, yy)) - self.glyph.components.append(new) - - -def drawFLGlyphOntoPointPen(flGlyph, pen): - """Draw a FontLab glyph onto a PointPen.""" - for anchor in flGlyph.anchors: - pen.beginPath() - pen.addPoint((anchor.x, anchor.y), name=anchor.name) - pen.endPath() - for contour in _getContours(flGlyph): - pen.beginPath() - for pt, segmentType, smooth in contour: - pen.addPoint(pt, segmentType=segmentType, smooth=smooth) - pen.endPath() - for baseGlyph, tranform in _getComponents(flGlyph): - pen.addComponent(baseGlyph, tranform) - - - -class FLPointContourPen(FLPointPen): - """Same as FLPointPen, except that it ignores components.""" - def addComponent(self, baseName, transformation): - pass - - -NODE_TYPES = {nMOVE: "move", nLINE: "line", nCURVE: "curve", - nOFF: None} - -def _getContours(glyph): - contours = [] - for i in range(len(glyph)): - node = glyph[i] - segmentType = NODE_TYPES[node.type] - if segmentType == "move": - contours.append([]) - for pt in node.points[1:]: - contours[-1].append(((pt.x, pt.y), None, False)) - smooth = node.alignment != nSHARP - contours[-1].append(((node.x, node.y), segmentType, smooth)) - - for contour in contours: - # filter out or change the move - movePt, segmentType, smooth = contour[0] - assert segmentType == "move" - lastSegmentType = contour[-1][1] - if movePt == contour[-1][0] and lastSegmentType == "curve": - contour[0] = contour[-1] - contour.pop() - elif lastSegmentType is None: - contour[0] = movePt, "qcurve", smooth - else: - assert lastSegmentType in ("line", "curve") - contour[0] = movePt, "line", smooth - - # change "line" to "qcurve" if appropriate - previousSegmentType = "ArbitraryValueOtherThanNone" - for i in range(len(contour)): - pt, segmentType, smooth = contour[i] - if segmentType == "line" and previousSegmentType is None: - contour[i] = pt, "qcurve", smooth - previousSegmentType = segmentType - - return contours - - -def _simplifyValues(*values): - """Given a set of numbers, convert items to ints if they are - integer float values, eg. 0.0, 1.0.""" - newValues = [] - for v in values: - i = int(v) - if v == i: - v = i - newValues.append(v) - return newValues - - -def _getComponents(glyph): - components = [] - for comp in glyph.components: - baseName = glyph.parent[comp.index].name - dx, dy = comp.delta.x, comp.delta.y - sx, sy = comp.scale.x, comp.scale.y - dx, dy, sx, sy = _simplifyValues(dx, dy, sx, sy) - components.append((baseName, (sx, 0, 0, sy, dx, dy))) - return components - - -def test(): - g = fl.glyph - g.Clear() - - p = PLPen(g) - p.moveTo((50, 50)) - p.lineTo((150,50)) - p.lineTo((170, 200), smooth=2) - p.curveTo((173, 225), (150, 250), (120, 250), smooth=1) - p.curveTo((85, 250), (50, 200), (50, 200)) - p.closePath() - - p.moveTo((300, 300)) - p.lineTo((400, 300)) - p.curveTo((450, 325), (450, 375), (400, 400)) - p.qCurveTo((400, 500), (350, 550), (300, 500), (300, 400)) - p.closePath() - p.setWidth(600) - p.setNote("Hello, this is a note") - p.addAnchor("top", (250, 600)) - - fl.UpdateGlyph(-1) - fl.UpdateFont(-1) - - -if __name__ == "__main__": - test() |