[qu2cuPen] Process multiple qCurveTo's at a time
This commit is contained in:
parent
8c88184413
commit
1a10b05c99
@ -13,12 +13,12 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from fontTools.qu2cu import quadratic_to_curves
|
||||
from fontTools.pens.filterPen import FilterPen
|
||||
from fontTools.qu2cu import quadratics_to_curves
|
||||
from fontTools.pens.filterPen import ContourFilterPen
|
||||
from fontTools.pens.reverseContourPen import ReverseContourPen
|
||||
|
||||
|
||||
class Qu2CuPen(FilterPen):
|
||||
class Qu2CuPen(ContourFilterPen):
|
||||
"""A filter pen to convert quadratic bezier splines to cubic curves
|
||||
using the FontTools SegmentPen protocol.
|
||||
|
||||
@ -45,21 +45,30 @@ class Qu2CuPen(FilterPen):
|
||||
self.max_err = max_err
|
||||
self.stats = stats
|
||||
|
||||
def _quadratic_to_curve(self, points):
|
||||
quadratics = (self.current_pt,) + points
|
||||
curves = quadratic_to_curves(quadratics, self.max_err)
|
||||
def _quadratics_to_curve(self, q):
|
||||
curves = quadratics_to_curves(q, self.max_err)
|
||||
if self.stats is not None:
|
||||
n = str(len(curves))
|
||||
self.stats[n] = self.stats.get(n, 0) + 1
|
||||
if len(quadratics) <= len(curves) * 3:
|
||||
super().qCurveTo(*quadratics)
|
||||
else:
|
||||
for curve in curves:
|
||||
self.curveTo(*curve[1:])
|
||||
for curve in curves:
|
||||
if len(curve) == 4:
|
||||
yield ("curveTo", curve[1:])
|
||||
else:
|
||||
yield ("qCurveTo", curve[1:])
|
||||
|
||||
def qCurveTo(self, *points):
|
||||
n = len(points)
|
||||
if n <= 3 or points[-1] is None:
|
||||
super().qCurveTo(*points)
|
||||
else:
|
||||
self._quadratic_to_curve(points)
|
||||
def filterContour(self, contour):
|
||||
quadratics = []
|
||||
currentPt = None
|
||||
newContour = []
|
||||
for op,args in contour:
|
||||
if op == 'qCurveTo' and len(args) > 2 and args[-1] is not None:
|
||||
quadratics.append((currentPt,) + args)
|
||||
else:
|
||||
if quadratics:
|
||||
newContour.extend(self._quadratics_to_curve(quadratics))
|
||||
quadratics = []
|
||||
newContour.append((op, args))
|
||||
currentPt = args[-1] if args else None
|
||||
if quadratics:
|
||||
newContour.extend(self._quadratics_to_curve(quadratics))
|
||||
return newContour
|
||||
|
@ -171,9 +171,9 @@ def quadratics_to_curves(pp, tolerance=0.5):
|
||||
q = [pp[0][0]]
|
||||
for p in pp:
|
||||
assert q[-1] == p[0]
|
||||
q.extend(spline_to_curves(q)[1:])
|
||||
q.extend(add_implicit_on_curves(p)[1:])
|
||||
|
||||
q = add_implicit_on_curves(q)
|
||||
curves = spline_to_curves(q, tolerance)
|
||||
|
||||
if not is_complex:
|
||||
curves = [tuple((c.real, c.imag) for c in curve) for curve in curves]
|
||||
@ -210,7 +210,10 @@ def spline_to_curves(q, tolerance=0.5):
|
||||
for j in range(0, i):
|
||||
|
||||
# Fit elevated_quadratics[j:i] into one cubic
|
||||
curve, ts = merge_curves(elevated_quadratics[j:i])
|
||||
try:
|
||||
curve, ts = merge_curves(elevated_quadratics[j:i])
|
||||
except ZeroDivisionError:
|
||||
continue
|
||||
|
||||
# Now reconstruct the segments from the fitted curve
|
||||
reconstructed_iter = splitCubicAtTC(*curve, *ts)
|
||||
@ -265,7 +268,10 @@ def spline_to_curves(q, tolerance=0.5):
|
||||
curves = []
|
||||
j = 0
|
||||
for i in reversed(splits):
|
||||
curves.append(merge_curves(elevated_quadratics[j:i])[0])
|
||||
if j + 1 == i:
|
||||
curves.append(q[j:j+3])
|
||||
else:
|
||||
curves.append(merge_curves(elevated_quadratics[j:i])[0])
|
||||
j = i
|
||||
|
||||
return curves
|
||||
|
Loading…
x
Reference in New Issue
Block a user