Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a2411fa

Browse files
committed
FIX: clamp get_rotation to [0, 360) when transform_rotates_text
transform_angles can return a tiny-negative value, and in Python (tiny_negative) % 360 float-rounds to exactly 360.0, breaking the [0, 360) range that the docstring promises. Clamp 360 back to 0 so callers can rely on the documented range. With that in place, the normalize + tolerance wrapper added to _get_dist_to_box in the previous commit is no longer needed. Reduce it to plain cardinal-angle short-circuits, per rcomer's suggestion in #31537. Rework the transform_rotates_text regression test to compare wrapped output against a plain rotation=0 reference at the same position, instead of the weaker "contains a space" assertion.
1 parent a8560a9 commit a2411fa

2 files changed

Lines changed: 23 additions & 23 deletions

File tree

lib/matplotlib/tests/test_text.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -778,20 +778,22 @@ def test_wrap_on_figure_edge(x, y, rotation):
778778

779779

780780
def test_wrap_on_figure_edge_transform_rotates_text():
781-
# With transform_rotates_text=True, get_rotation() goes through
782-
# transform_angles() and can return near-cardinal angles with float
783-
# noise (e.g. -90.00000000000003 for a 270 degree rotation), which
784-
# used to skip the cardinal-angle short-circuit in _get_dist_to_box.
785-
from matplotlib.transforms import Affine2D
786-
fig = plt.figure(figsize=(6, 4))
781+
# Regression test for #31537 - transform_rotates_text with an axis-aligned
782+
# transform can make get_rotation() float-round to 360.0.
787783
s = 'This is a very long text that should be wrapped multiple times.'
788-
# rotate_deg(90).rotate_deg(-90) is identity geometrically, but carries
789-
# enough numerical slop to perturb transform_angles.
790-
transform = Affine2D().rotate_deg(90).rotate_deg(-90) + fig.transFigure
791-
t = fig.text(0.0, 0.5, s, transform=transform, wrap=True, rotation=270,
792-
transform_rotates_text=True)
784+
785+
fig = plt.figure(figsize=(6, 4))
786+
transform = mtransforms.Affine2D().rotate_deg(270) + fig.transFigure
787+
t = fig.text(0.0, 0.0, s, transform=transform, wrap=True,
788+
rotation=90, transform_rotates_text=True)
793789
fig.canvas.draw()
794-
assert any(' ' in line for line in t._get_wrapped_text().split('\n'))
790+
791+
fig_ref = plt.figure(figsize=(6, 4))
792+
t_ref = fig_ref.text(0.0, 0.0, s, wrap=True, rotation=0)
793+
fig_ref.canvas.draw()
794+
795+
assert 0 <= t.get_rotation() < 360
796+
assert t._get_wrapped_text() == t_ref._get_wrapped_text()
795797

796798

797799
@check_figures_equal()

lib/matplotlib/text.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,10 @@ def _char_index_at(self, x):
339339
def get_rotation(self):
340340
"""Return the text angle in degrees in the range [0, 360)."""
341341
if self.get_transform_rotates_text():
342-
return self.get_transform().transform_angles(
342+
angle = self.get_transform().transform_angles(
343343
[self._rotation], [self.get_unitless_position()]).item(0) % 360
344+
# `(tiny_negative) % 360` can float-round to exactly 360.0.
345+
return 0.0 if angle == 360 else angle
344346
else:
345347
return self._rotation
346348

@@ -757,19 +759,15 @@ def _get_dist_to_box(self, rotation, x0, y0, figure_box):
757759
Return the distance from the given points to the boundaries of a
758760
rotated box, in pixels.
759761
"""
760-
# Normalize rotation; transform_angles can return values outside
761-
# [0, 360) with tiny float noise.
762-
rotation = rotation % 360
763-
# Short-circuit cardinal angles, otherwise cos(radians(90)) makes
764-
# the trig formula below blow up when the text is on the edge.
765-
tol = 1e-10
766-
if rotation < tol or rotation > 360 - tol:
762+
# Short-circuit cardinals; otherwise cos(radians(90)) makes the trig
763+
# formula below blow up when the text is on the matching edge.
764+
if rotation == 0:
767765
return figure_box.x1 - x0
768-
if abs(rotation - 90) < tol:
766+
if rotation == 90:
769767
return figure_box.y1 - y0
770-
if abs(rotation - 180) < tol:
768+
if rotation == 180:
771769
return x0 - figure_box.x0
772-
if abs(rotation - 270) < tol:
770+
if rotation == 270:
773771
return y0 - figure_box.y0
774772

775773
if rotation > 270:

0 commit comments

Comments
 (0)