Example #1
0
 def _split_super_bezier_segments(self, points):
     sub_segments = []
     # n is the number of control points
     n = len(points) - 1
     if n == 2:
         # a simple bezier curve segment
         sub_segments.append(points)
     elif n > 2:
         # a "super" bezier; decompose it
         on_curve, smooth, name, kwargs = points[-1]
         num_sub_segments = n - 1
         for i, sub_points in enumerate(
                 decomposeSuperBezierSegment([pt
                                              for pt, _, _, _ in points])):
             new_segment = []
             for point in sub_points[:-1]:
                 new_segment.append((point, False, None, {}))
             if i == (num_sub_segments - 1):
                 # the last on-curve keeps its original attributes
                 new_segment.append((on_curve, smooth, name, kwargs))
             else:
                 # on-curves of sub-segments are always "smooth"
                 new_segment.append((sub_points[-1], True, None, {}))
             sub_segments.append(new_segment)
     else:
         raise AssertionError("expected 2 control points, found: %d" % n)
     return sub_segments
Example #2
0
 def _split_super_bezier_segments(self, points):
     sub_segments = []
     # n is the number of control points
     n = len(points) - 1
     if n == 2:
         # a simple bezier curve segment
         sub_segments.append(points)
     elif n > 2:
         # a "super" bezier; decompose it
         on_curve, smooth, name, kwargs = points[-1]
         num_sub_segments = n - 1
         for i, sub_points in enumerate(decomposeSuperBezierSegment([
                 pt for pt, _, _, _ in points])):
             new_segment = []
             for point in sub_points[:-1]:
                 new_segment.append((point, False, None, {}))
             if i == (num_sub_segments - 1):
                 # the last on-curve keeps its original attributes
                 new_segment.append((on_curve, smooth, name, kwargs))
             else:
                 # on-curves of sub-segments are always "smooth"
                 new_segment.append((sub_points[-1], True, None, {}))
             sub_segments.append(new_segment)
     else:
         raise AssertionError(
             "expected 2 control points, found: %d" % n)
     return sub_segments
Example #3
0
 def curveTo(self, *points):
     self._check_contour_is_open()
     n = len(points)
     if n == 3:
         # this is the most common case, so we special-case it
         self._curve_to_quadratic(*points)
     elif n > 3:
         for segment in decomposeSuperBezierSegment(points):
             self._curve_to_quadratic(*segment)
     elif n == 2:
         self.qCurveTo(*points)
     elif n == 1:
         self.lineTo(points[0])
     else:
         raise AssertionError("illegal curve segment point count: %d" % n)
Example #4
0
 def curveTo(self, *points):
     self._check_contour_is_open()
     n = len(points)
     if n == 3:
         # this is the most common case, so we special-case it
         self._curve_to_quadratic(*points)
     elif n > 3:
         for segment in decomposeSuperBezierSegment(points):
             self._curve_to_quadratic(*segment)
     elif n == 2:
         self.qCurveTo(*points)
     elif n == 1:
         self.lineTo(points[0])
     else:
         raise AssertionError("illegal curve segment point count: %d" % n)
Example #5
0
	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)