[cu2qu] Add all_quadratic=True parameter
If set to False, then either a single quadratic or a single cubic is returned.
This commit is contained in:
parent
9e40409094
commit
a21b71ef01
@ -364,7 +364,7 @@ def cubic_approx_quadratic(cubic, tolerance, _2_3=2 / 3):
|
|||||||
q2=cython.complex,
|
q2=cython.complex,
|
||||||
d1=cython.complex,
|
d1=cython.complex,
|
||||||
)
|
)
|
||||||
def cubic_approx_spline(cubic, n, tolerance, _2_3=2 / 3):
|
def cubic_approx_spline(cubic, n, tolerance, all_quadratic, _2_3=2 / 3):
|
||||||
"""Approximate a cubic Bezier curve with a spline of n quadratics.
|
"""Approximate a cubic Bezier curve with a spline of n quadratics.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -383,6 +383,8 @@ def cubic_approx_spline(cubic, n, tolerance, _2_3=2 / 3):
|
|||||||
|
|
||||||
if n == 1:
|
if n == 1:
|
||||||
return cubic_approx_quadratic(cubic, tolerance)
|
return cubic_approx_quadratic(cubic, tolerance)
|
||||||
|
if n == 2 and all_quadratic == False:
|
||||||
|
return cubic
|
||||||
|
|
||||||
cubics = split_cubic_into_n_iter(cubic[0], cubic[1], cubic[2], cubic[3], n)
|
cubics = split_cubic_into_n_iter(cubic[0], cubic[1], cubic[2], cubic[3], n)
|
||||||
|
|
||||||
@ -423,24 +425,31 @@ def cubic_approx_spline(cubic, n, tolerance, _2_3=2 / 3):
|
|||||||
|
|
||||||
@cython.locals(max_err=cython.double)
|
@cython.locals(max_err=cython.double)
|
||||||
@cython.locals(n=cython.int)
|
@cython.locals(n=cython.int)
|
||||||
def curve_to_quadratic(curve, max_err):
|
def curve_to_quadratic(curve, max_err, all_quadratic=True):
|
||||||
"""Approximate a cubic Bezier curve with a spline of n quadratics.
|
"""Approximate a cubic Bezier curve with a spline of n quadratics.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cubic (sequence): Four 2D tuples representing control points of
|
cubic (sequence): Four 2D tuples representing control points of
|
||||||
the cubic Bezier curve.
|
the cubic Bezier curve.
|
||||||
max_err (double): Permitted deviation from the original curve.
|
max_err (double): Permitted deviation from the original curve.
|
||||||
|
all_quadratic (bool): If True (default) returned value is a
|
||||||
|
quadratic spline. If False, it's either a single quadratic
|
||||||
|
curve or a single cubic curve.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A list of 2D tuples, representing control points of the quadratic
|
If all_quadratic is True: A list of 2D tuples, representing
|
||||||
spline if it fits within the given tolerance, or ``None`` if no
|
control points of the quadratic spline if it fits within the
|
||||||
suitable spline could be calculated.
|
given tolerance, or ``None`` if no suitable spline could be
|
||||||
|
calculated.
|
||||||
|
|
||||||
|
If all_quadratic is False: Either a quadratic curve (if length
|
||||||
|
of output is 3), or a cubic curve (if length of output is 4).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
curve = [complex(*p) for p in curve]
|
curve = [complex(*p) for p in curve]
|
||||||
|
|
||||||
for n in range(1, MAX_N + 1):
|
for n in range(1, MAX_N + 1):
|
||||||
spline = cubic_approx_spline(curve, n, max_err)
|
spline = cubic_approx_spline(curve, n, max_err, all_quadratic)
|
||||||
if spline is not None:
|
if spline is not None:
|
||||||
# done. go home
|
# done. go home
|
||||||
return [(s.real, s.imag) for s in spline]
|
return [(s.real, s.imag) for s in spline]
|
||||||
@ -449,7 +458,7 @@ def curve_to_quadratic(curve, max_err):
|
|||||||
|
|
||||||
|
|
||||||
@cython.locals(l=cython.int, last_i=cython.int, i=cython.int)
|
@cython.locals(l=cython.int, last_i=cython.int, i=cython.int)
|
||||||
def curves_to_quadratic(curves, max_errors):
|
def curves_to_quadratic(curves, max_errors, all_quadratic=True):
|
||||||
"""Return quadratic Bezier splines approximating the input cubic Beziers.
|
"""Return quadratic Bezier splines approximating the input cubic Beziers.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -457,6 +466,9 @@ def curves_to_quadratic(curves, max_errors):
|
|||||||
2D tuples.
|
2D tuples.
|
||||||
max_errors: A sequence of *n* floats representing the maximum permissible
|
max_errors: A sequence of *n* floats representing the maximum permissible
|
||||||
deviation from each of the cubic Bezier curves.
|
deviation from each of the cubic Bezier curves.
|
||||||
|
all_quadratic (bool): If True (default) returned values are a
|
||||||
|
quadratic spline. If False, they are either a single quadratic
|
||||||
|
curve or a single cubic curve.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
@ -472,7 +484,11 @@ def curves_to_quadratic(curves, max_errors):
|
|||||||
( (75 + 125)/2 , (120 + 91.666..)/2 ) = (100, 83.333...).
|
( (75 + 125)/2 , (120 + 91.666..)/2 ) = (100, 83.333...).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A list of splines, each spline being a list of 2D tuples.
|
If all_quadratic is True, a list of splines, each spline being a list
|
||||||
|
of 2D tuples.
|
||||||
|
|
||||||
|
If all_quadratic is False, a list of curves, each curve being a quadratic
|
||||||
|
(length 3), or cubic (length 4).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
fontTools.cu2qu.Errors.ApproxNotFoundError: if no suitable approximation
|
fontTools.cu2qu.Errors.ApproxNotFoundError: if no suitable approximation
|
||||||
@ -487,7 +503,7 @@ def curves_to_quadratic(curves, max_errors):
|
|||||||
last_i = i = 0
|
last_i = i = 0
|
||||||
n = 1
|
n = 1
|
||||||
while True:
|
while True:
|
||||||
spline = cubic_approx_spline(curves[i], n, max_errors[i])
|
spline = cubic_approx_spline(curves[i], n, max_errors[i], all_quadratic)
|
||||||
if spline is None:
|
if spline is None:
|
||||||
if n == MAX_N:
|
if n == MAX_N:
|
||||||
break
|
break
|
||||||
|
@ -175,5 +175,18 @@ class CurveToQuadraticTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AllQuadraticFalseTest(unittest.TestCase):
|
||||||
|
def test_cubic(self):
|
||||||
|
cubic = [(0, 0), (0, 1), (2, 1), (2, 0)]
|
||||||
|
result = curve_to_quadratic(cubic, 0.1, all_quadratic=False)
|
||||||
|
assert result == cubic
|
||||||
|
|
||||||
|
def test_quadratic(self):
|
||||||
|
cubic = [(0, 0), (2, 2), (4, 2), (6, 0)]
|
||||||
|
result = curve_to_quadratic(cubic, 0.1, all_quadratic=False)
|
||||||
|
quadratic = [(0, 0), (3, 3), (6, 0)]
|
||||||
|
assert result == quadratic
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user