fix(fonttools): scale Bezier subdivision to the pixel error
Flatten each quadratic with a segment count derived from |p0 - 2*p1 + p2| in pixel space, targeting < 0.5 px error. The count grows with the rendered font size. All-off-curve contours now use midpoint quadratics instead of polygon edges.
This commit is contained in:
1 parent
faab22c40e
commit
6a65d0a7f2
1 file changed
+25
-6
@@ -176,10 +176,18 @@ def _add_edge(x0: float, y0: float, x1: float, y1: float):
|
||||
_edge_count += 1
|
||||
|
||||
def _quad(x0: float, y0: float, x1: float, y1: float, x2: float, y2: float):
|
||||
# Maximum distance from the chord is |p0 - 2*p1 + p2| / 4.
|
||||
# Choose n so the error per segment is below 0.5 px.
|
||||
ddx: float = x0 - 2.0 * x1 + x2
|
||||
ddy: float = y0 - 2.0 * y1 + y2
|
||||
d: float = math.sqrtf(ddx * ddx + ddy * ddy)
|
||||
n: int = int(math.floorf(math.sqrtf(d / 2.0))) + 1
|
||||
if n < 8: n = 8
|
||||
if n > 64: n = 64
|
||||
px: float = x0
|
||||
py: float = y0
|
||||
for s in range(1, 9):
|
||||
t: float = float(s) / 8.0
|
||||
for s in range(1, n + 1):
|
||||
t: float = float(s) / float(n)
|
||||
mt: float = 1.0 - t
|
||||
x: float = mt * mt * x0 + 2.0 * mt * t * x1 + t * t * x2
|
||||
y: float = mt * mt * y0 + 2.0 * mt * t * y1 + t * t * y2
|
||||
@@ -194,10 +202,21 @@ def _build_contour(start: int, end: int):
|
||||
first_on = i
|
||||
break
|
||||
if first_on < 0:
|
||||
for i in range(start, end + 1):
|
||||
j: int = i + 1
|
||||
if j > end: j = start
|
||||
_add_edge(_px[i], _py[i], _px[j], _py[j])
|
||||
sx: float = (_px[end] + _px[start]) / 2.0
|
||||
sy: float = (_py[end] + _py[start]) / 2.0
|
||||
cx: float = sx
|
||||
cy: float = sy
|
||||
i: int = start
|
||||
while i <= end:
|
||||
nx: int = i + 1
|
||||
if nx > end: nx = start
|
||||
ex: float = (_px[i] + _px[nx]) / 2.0
|
||||
ey: float = (_py[i] + _py[nx]) / 2.0
|
||||
_quad(cx, cy, _px[i], _py[i], ex, ey)
|
||||
cx = ex
|
||||
cy = ey
|
||||
i += 1
|
||||
_add_edge(cx, cy, sx, sy)
|
||||
return
|
||||
cx: float = _px[first_on]
|
||||
cy: float = _py[first_on]
|
||||
|
||||
Reference in new issue
Block a user