Merge pull request #2521 from fonttools/fix-round-radial-gradient-circle

[colrv1] use math.isclose with relative tolerance to check radial circles' inside-ness
This commit is contained in:
Cosimo Lupo 2022-02-01 10:57:55 +00:00 committed by GitHub
commit f3b4c5b031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 6 deletions

View File

@ -1,6 +1,6 @@
"""Helpers for manipulating 2D points and vectors in COLR table."""
from math import copysign, cos, hypot, pi
from math import copysign, cos, hypot, isclose, pi
from fontTools.misc.roundTools import otRound
@ -19,9 +19,7 @@ def _unit_vector(vec):
return (vec[0] / length, vec[1] / length)
# This is the same tolerance used by Skia's SkTwoPointConicalGradient.cpp to detect
# when a radial gradient's focal point lies on the end circle.
_NEARLY_ZERO = 1 / (1 << 12) # 0.000244140625
_CIRCLE_INSIDE_TOLERANCE = 1e-4
# The unit vector's X and Y components are respectively
@ -64,10 +62,10 @@ class Circle:
def round(self):
return Circle(_round_point(self.centre), otRound(self.radius))
def inside(self, outer_circle):
def inside(self, outer_circle, tolerance=_CIRCLE_INSIDE_TOLERANCE):
dist = self.radius + hypot(*_vector_between(self.centre, outer_circle.centre))
return (
abs(outer_circle.radius - dist) <= _NEARLY_ZERO
isclose(outer_circle.radius, dist, rel_tol=_CIRCLE_INSIDE_TOLERANCE)
or outer_circle.radius > dist
)

View File

@ -1747,6 +1747,16 @@ class TrickyRadialGradientTest:
r1 = 260.0072
assert self.round_start_circle(c0, r0, c1, r1, inside=True) == ((386, 71), 0)
def test_noto_emoji_horns_sign_u1f918_1f3fc(self):
# This radial gradient is taken from noto-emoji's 'SIGNS OF THE HORNS'
# (1f918_1f3fc). We check that c0 is inside c1 both before and after rounding.
c0 = (-437.6789059060543, -2116.9237094478003)
r0 = 0.0
c1 = (-488.7330118252256, -1876.5036857045086)
r1 = 245.77147821915673
assert self.circle_inside_circle(c0, r0, c1, r1)
assert self.circle_inside_circle(c0, r0, c1, r1, rounded=True)
@pytest.mark.parametrize(
"c0, r0, c1, r1, inside, expected",
[