[Cu2QuPen] Use FilterPen
This commit is contained in:
parent
e18fca76ef
commit
ac94ee9949
@ -13,13 +13,14 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from fontTools.cu2qu import curve_to_quadratic, curves_to_quadratic
|
from fontTools.cu2qu import curve_to_quadratic, curves_to_quadratic
|
||||||
from fontTools.pens.basePen import AbstractPen, decomposeSuperBezierSegment
|
from fontTools.pens.basePen import decomposeSuperBezierSegment
|
||||||
|
from fontTools.pens.filterPen import FilterPen
|
||||||
from fontTools.pens.reverseContourPen import ReverseContourPen
|
from fontTools.pens.reverseContourPen import ReverseContourPen
|
||||||
from fontTools.pens.pointPen import BasePointToSegmentPen
|
from fontTools.pens.pointPen import BasePointToSegmentPen
|
||||||
from fontTools.pens.pointPen import ReverseContourPointPen
|
from fontTools.pens.pointPen import ReverseContourPointPen
|
||||||
|
|
||||||
|
|
||||||
class Cu2QuPen(AbstractPen):
|
class Cu2QuPen(FilterPen):
|
||||||
"""A filter pen to convert cubic bezier curves to quadratic b-splines
|
"""A filter pen to convert cubic bezier curves to quadratic b-splines
|
||||||
using the FontTools SegmentPen protocol.
|
using the FontTools SegmentPen protocol.
|
||||||
|
|
||||||
@ -41,42 +42,10 @@ class Cu2QuPen(AbstractPen):
|
|||||||
stats=None,
|
stats=None,
|
||||||
):
|
):
|
||||||
if reverse_direction:
|
if reverse_direction:
|
||||||
self.pen = ReverseContourPen(other_pen)
|
other_pen = ReverseContourPen(other_pen)
|
||||||
else:
|
super().__init__(other_pen)
|
||||||
self.pen = other_pen
|
|
||||||
self.max_err = max_err
|
self.max_err = max_err
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
self.current_pt = None
|
|
||||||
|
|
||||||
def _check_contour_is_open(self):
|
|
||||||
if self.current_pt is None:
|
|
||||||
raise AssertionError("moveTo is required")
|
|
||||||
|
|
||||||
def _check_contour_is_closed(self):
|
|
||||||
if self.current_pt is not None:
|
|
||||||
raise AssertionError("closePath or endPath is required")
|
|
||||||
|
|
||||||
def moveTo(self, pt):
|
|
||||||
self._check_contour_is_closed()
|
|
||||||
self.current_pt = pt
|
|
||||||
self.pen.moveTo(pt)
|
|
||||||
self.current_pt = pt
|
|
||||||
|
|
||||||
def lineTo(self, pt):
|
|
||||||
self._check_contour_is_open()
|
|
||||||
self.pen.lineTo(pt)
|
|
||||||
self.current_pt = pt
|
|
||||||
|
|
||||||
def qCurveTo(self, *points):
|
|
||||||
self._check_contour_is_open()
|
|
||||||
n = len(points)
|
|
||||||
if n == 1:
|
|
||||||
self.lineTo(points[0])
|
|
||||||
elif n > 1:
|
|
||||||
self.pen.qCurveTo(*points)
|
|
||||||
self.current_pt = points[-1]
|
|
||||||
else:
|
|
||||||
raise AssertionError("illegal qcurve segment point count: %d" % n)
|
|
||||||
|
|
||||||
def _curve_to_quadratic(self, pt1, pt2, pt3):
|
def _curve_to_quadratic(self, pt1, pt2, pt3):
|
||||||
curve = (self.current_pt, pt1, pt2, pt3)
|
curve = (self.current_pt, pt1, pt2, pt3)
|
||||||
@ -87,7 +56,6 @@ class Cu2QuPen(AbstractPen):
|
|||||||
self.qCurveTo(*quadratic[1:])
|
self.qCurveTo(*quadratic[1:])
|
||||||
|
|
||||||
def curveTo(self, *points):
|
def curveTo(self, *points):
|
||||||
self._check_contour_is_open()
|
|
||||||
n = len(points)
|
n = len(points)
|
||||||
if n == 3:
|
if n == 3:
|
||||||
# this is the most common case, so we special-case it
|
# this is the most common case, so we special-case it
|
||||||
@ -95,26 +63,8 @@ class Cu2QuPen(AbstractPen):
|
|||||||
elif n > 3:
|
elif n > 3:
|
||||||
for segment in decomposeSuperBezierSegment(points):
|
for segment in decomposeSuperBezierSegment(points):
|
||||||
self._curve_to_quadratic(*segment)
|
self._curve_to_quadratic(*segment)
|
||||||
elif n == 2:
|
|
||||||
self.qCurveTo(*points)
|
|
||||||
elif n == 1:
|
|
||||||
self.lineTo(points[0])
|
|
||||||
else:
|
else:
|
||||||
raise AssertionError("illegal curve segment point count: %d" % n)
|
self.qCurveTo(*points)
|
||||||
|
|
||||||
def closePath(self):
|
|
||||||
self._check_contour_is_open()
|
|
||||||
self.pen.closePath()
|
|
||||||
self.current_pt = None
|
|
||||||
|
|
||||||
def endPath(self):
|
|
||||||
self._check_contour_is_open()
|
|
||||||
self.pen.endPath()
|
|
||||||
self.current_pt = None
|
|
||||||
|
|
||||||
def addComponent(self, glyphName, transformation):
|
|
||||||
self._check_contour_is_closed()
|
|
||||||
self.pen.addComponent(glyphName, transformation)
|
|
||||||
|
|
||||||
|
|
||||||
class Cu2QuPointPen(BasePointToSegmentPen):
|
class Cu2QuPointPen(BasePointToSegmentPen):
|
||||||
|
@ -117,52 +117,6 @@ class TestCu2QuPen(unittest.TestCase, _TestPenMixin):
|
|||||||
self.pen_getter_name = "getPen"
|
self.pen_getter_name = "getPen"
|
||||||
self.draw_method_name = "draw"
|
self.draw_method_name = "draw"
|
||||||
|
|
||||||
def test__check_contour_is_open(self):
|
|
||||||
msg = "moveTo is required"
|
|
||||||
quadpen = Cu2QuPen(DummyPen(), MAX_ERR)
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.lineTo((0, 0))
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.qCurveTo((0, 0), (1, 1))
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.curveTo((0, 0), (1, 1), (2, 2))
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.closePath()
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.endPath()
|
|
||||||
|
|
||||||
quadpen.moveTo((0, 0)) # now it works
|
|
||||||
quadpen.lineTo((1, 1))
|
|
||||||
quadpen.qCurveTo((2, 2), (3, 3))
|
|
||||||
quadpen.curveTo((4, 4), (5, 5), (6, 6))
|
|
||||||
quadpen.closePath()
|
|
||||||
|
|
||||||
def test__check_contour_closed(self):
|
|
||||||
msg = "closePath or endPath is required"
|
|
||||||
quadpen = Cu2QuPen(DummyPen(), MAX_ERR)
|
|
||||||
quadpen.moveTo((0, 0))
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.moveTo((1, 1))
|
|
||||||
with self.assertRaisesRegex(AssertionError, msg):
|
|
||||||
quadpen.addComponent("a", (1, 0, 0, 1, 0, 0))
|
|
||||||
|
|
||||||
# it works if contour is closed
|
|
||||||
quadpen.closePath()
|
|
||||||
quadpen.moveTo((1, 1))
|
|
||||||
quadpen.endPath()
|
|
||||||
quadpen.addComponent("a", (1, 0, 0, 1, 0, 0))
|
|
||||||
|
|
||||||
def test_qCurveTo_no_points(self):
|
|
||||||
quadpen = Cu2QuPen(DummyPen(), MAX_ERR)
|
|
||||||
quadpen.moveTo((0, 0))
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(
|
|
||||||
AssertionError, "illegal qcurve segment point count: 0"
|
|
||||||
):
|
|
||||||
quadpen.qCurveTo()
|
|
||||||
|
|
||||||
def test_qCurveTo_1_point(self):
|
def test_qCurveTo_1_point(self):
|
||||||
pen = DummyPen()
|
pen = DummyPen()
|
||||||
quadpen = Cu2QuPen(pen, MAX_ERR)
|
quadpen = Cu2QuPen(pen, MAX_ERR)
|
||||||
@ -173,7 +127,7 @@ class TestCu2QuPen(unittest.TestCase, _TestPenMixin):
|
|||||||
str(pen).splitlines(),
|
str(pen).splitlines(),
|
||||||
[
|
[
|
||||||
"pen.moveTo((0, 0))",
|
"pen.moveTo((0, 0))",
|
||||||
"pen.lineTo((1, 1))",
|
"pen.qCurveTo((1, 1))",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -191,15 +145,6 @@ class TestCu2QuPen(unittest.TestCase, _TestPenMixin):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_curveTo_no_points(self):
|
|
||||||
quadpen = Cu2QuPen(DummyPen(), MAX_ERR)
|
|
||||||
quadpen.moveTo((0, 0))
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(
|
|
||||||
AssertionError, "illegal curve segment point count: 0"
|
|
||||||
):
|
|
||||||
quadpen.curveTo()
|
|
||||||
|
|
||||||
def test_curveTo_1_point(self):
|
def test_curveTo_1_point(self):
|
||||||
pen = DummyPen()
|
pen = DummyPen()
|
||||||
quadpen = Cu2QuPen(pen, MAX_ERR)
|
quadpen = Cu2QuPen(pen, MAX_ERR)
|
||||||
@ -210,7 +155,7 @@ class TestCu2QuPen(unittest.TestCase, _TestPenMixin):
|
|||||||
str(pen).splitlines(),
|
str(pen).splitlines(),
|
||||||
[
|
[
|
||||||
"pen.moveTo((0, 0))",
|
"pen.moveTo((0, 0))",
|
||||||
"pen.lineTo((1, 1))",
|
"pen.qCurveTo((1, 1))",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user