1from datetime import datetime 2import io 3import warnings 4 5import numpy as np 6from numpy.testing import assert_almost_equal 7import pytest 8 9import matplotlib as mpl 10from matplotlib.backend_bases import MouseEvent 11from matplotlib.font_manager import FontProperties 12import matplotlib.patches as mpatches 13import matplotlib.pyplot as plt 14import matplotlib.transforms as mtransforms 15from matplotlib.testing.decorators import check_figures_equal, image_comparison 16from matplotlib.text import Text 17 18 19needs_usetex = pytest.mark.skipif( 20 not mpl.checkdep_usetex(True), 21 reason="This test needs a TeX installation") 22 23 24@image_comparison(['font_styles']) 25def test_font_styles(): 26 27 def find_matplotlib_font(**kw): 28 prop = FontProperties(**kw) 29 path = findfont(prop, directory=mpl.get_data_path()) 30 return FontProperties(fname=path) 31 32 from matplotlib.font_manager import FontProperties, findfont 33 warnings.filterwarnings( 34 'ignore', 35 r"findfont: Font family \[u?'Foo'\] not found. Falling back to .", 36 UserWarning, 37 module='matplotlib.font_manager') 38 39 fig, ax = plt.subplots() 40 41 normal_font = find_matplotlib_font( 42 family="sans-serif", 43 style="normal", 44 variant="normal", 45 size=14) 46 ax.annotate( 47 "Normal Font", 48 (0.1, 0.1), 49 xycoords='axes fraction', 50 fontproperties=normal_font) 51 52 bold_font = find_matplotlib_font( 53 family="Foo", 54 style="normal", 55 variant="normal", 56 weight="bold", 57 stretch=500, 58 size=14) 59 ax.annotate( 60 "Bold Font", 61 (0.1, 0.2), 62 xycoords='axes fraction', 63 fontproperties=bold_font) 64 65 bold_italic_font = find_matplotlib_font( 66 family="sans serif", 67 style="italic", 68 variant="normal", 69 weight=750, 70 stretch=500, 71 size=14) 72 ax.annotate( 73 "Bold Italic Font", 74 (0.1, 0.3), 75 xycoords='axes fraction', 76 fontproperties=bold_italic_font) 77 78 light_font = find_matplotlib_font( 79 family="sans-serif", 80 style="normal", 81 variant="normal", 82 weight=200, 83 stretch=500, 84 size=14) 85 ax.annotate( 86 "Light Font", 87 (0.1, 0.4), 88 xycoords='axes fraction', 89 fontproperties=light_font) 90 91 condensed_font = find_matplotlib_font( 92 family="sans-serif", 93 style="normal", 94 variant="normal", 95 weight=500, 96 stretch=100, 97 size=14) 98 ax.annotate( 99 "Condensed Font", 100 (0.1, 0.5), 101 xycoords='axes fraction', 102 fontproperties=condensed_font) 103 104 ax.set_xticks([]) 105 ax.set_yticks([]) 106 107 108@image_comparison(['multiline']) 109def test_multiline(): 110 plt.figure() 111 ax = plt.subplot(1, 1, 1) 112 ax.set_title("multiline\ntext alignment") 113 114 plt.text( 115 0.2, 0.5, "TpTpTp\n$M$\nTpTpTp", size=20, ha="center", va="top") 116 117 plt.text( 118 0.5, 0.5, "TpTpTp\n$M^{M^{M^{M}}}$\nTpTpTp", size=20, 119 ha="center", va="top") 120 121 plt.text( 122 0.8, 0.5, "TpTpTp\n$M_{q_{q_{q}}}$\nTpTpTp", size=20, 123 ha="center", va="top") 124 125 plt.xlim(0, 1) 126 plt.ylim(0, 0.8) 127 128 ax.set_xticks([]) 129 ax.set_yticks([]) 130 131 132@image_comparison(['multiline2'], style='mpl20') 133def test_multiline2(): 134 # Remove this line when this test image is regenerated. 135 plt.rcParams['text.kerning_factor'] = 6 136 137 fig, ax = plt.subplots() 138 139 ax.set_xlim([0, 1.4]) 140 ax.set_ylim([0, 2]) 141 ax.axhline(0.5, color='C2', linewidth=0.3) 142 sts = ['Line', '2 Lineg\n 2 Lg', '$\\sum_i x $', 'hi $\\sum_i x $\ntest', 143 'test\n $\\sum_i x $', '$\\sum_i x $\n $\\sum_i x $'] 144 renderer = fig.canvas.get_renderer() 145 146 def draw_box(ax, tt): 147 r = mpatches.Rectangle((0, 0), 1, 1, clip_on=False, 148 transform=ax.transAxes) 149 r.set_bounds( 150 tt.get_window_extent(renderer) 151 .transformed(ax.transAxes.inverted()) 152 .bounds) 153 ax.add_patch(r) 154 155 horal = 'left' 156 for nn, st in enumerate(sts): 157 tt = ax.text(0.2 * nn + 0.1, 0.5, st, horizontalalignment=horal, 158 verticalalignment='bottom') 159 draw_box(ax, tt) 160 ax.text(1.2, 0.5, 'Bottom align', color='C2') 161 162 ax.axhline(1.3, color='C2', linewidth=0.3) 163 for nn, st in enumerate(sts): 164 tt = ax.text(0.2 * nn + 0.1, 1.3, st, horizontalalignment=horal, 165 verticalalignment='top') 166 draw_box(ax, tt) 167 ax.text(1.2, 1.3, 'Top align', color='C2') 168 169 ax.axhline(1.8, color='C2', linewidth=0.3) 170 for nn, st in enumerate(sts): 171 tt = ax.text(0.2 * nn + 0.1, 1.8, st, horizontalalignment=horal, 172 verticalalignment='baseline') 173 draw_box(ax, tt) 174 ax.text(1.2, 1.8, 'Baseline align', color='C2') 175 176 ax.axhline(0.1, color='C2', linewidth=0.3) 177 for nn, st in enumerate(sts): 178 tt = ax.text(0.2 * nn + 0.1, 0.1, st, horizontalalignment=horal, 179 verticalalignment='bottom', rotation=20) 180 draw_box(ax, tt) 181 ax.text(1.2, 0.1, 'Bot align, rot20', color='C2') 182 183 184@image_comparison(['antialiased.png']) 185def test_antialiasing(): 186 mpl.rcParams['text.antialiased'] = True 187 188 fig = plt.figure(figsize=(5.25, 0.75)) 189 fig.text(0.5, 0.75, "antialiased", horizontalalignment='center', 190 verticalalignment='center') 191 fig.text(0.5, 0.25, r"$\sqrt{x}$", horizontalalignment='center', 192 verticalalignment='center') 193 # NOTE: We don't need to restore the rcParams here, because the 194 # test cleanup will do it for us. In fact, if we do it here, it 195 # will turn antialiasing back off before the images are actually 196 # rendered. 197 198 199def test_afm_kerning(): 200 fn = mpl.font_manager.findfont("Helvetica", fontext="afm") 201 with open(fn, 'rb') as fh: 202 afm = mpl.afm.AFM(fh) 203 assert afm.string_width_height('VAVAVAVAVAVA') == (7174.0, 718) 204 205 206@image_comparison(['text_contains.png']) 207def test_contains(): 208 fig = plt.figure() 209 ax = plt.axes() 210 211 mevent = MouseEvent('button_press_event', fig.canvas, 0.5, 0.5, 1, None) 212 213 xs = np.linspace(0.25, 0.75, 30) 214 ys = np.linspace(0.25, 0.75, 30) 215 xs, ys = np.meshgrid(xs, ys) 216 217 txt = plt.text( 218 0.5, 0.4, 'hello world', ha='center', fontsize=30, rotation=30) 219 # uncomment to draw the text's bounding box 220 # txt.set_bbox(dict(edgecolor='black', facecolor='none')) 221 222 # draw the text. This is important, as the contains method can only work 223 # when a renderer exists. 224 fig.canvas.draw() 225 226 for x, y in zip(xs.flat, ys.flat): 227 mevent.x, mevent.y = plt.gca().transAxes.transform([x, y]) 228 contains, _ = txt.contains(mevent) 229 color = 'yellow' if contains else 'red' 230 231 # capture the viewLim, plot a point, and reset the viewLim 232 vl = ax.viewLim.frozen() 233 ax.plot(x, y, 'o', color=color) 234 ax.viewLim.set(vl) 235 236 237def test_annotation_contains(): 238 # Check that Annotation.contains looks at the bboxes of the text and the 239 # arrow separately, not at the joint bbox. 240 fig, ax = plt.subplots() 241 ann = ax.annotate( 242 "hello", xy=(.4, .4), xytext=(.6, .6), arrowprops={"arrowstyle": "->"}) 243 fig.canvas.draw() # Needed for the same reason as in test_contains. 244 event = MouseEvent( 245 "button_press_event", fig.canvas, *ax.transData.transform((.5, .6))) 246 assert ann.contains(event) == (False, {}) 247 248 249@image_comparison(['titles']) 250def test_titles(): 251 # left and right side titles 252 plt.figure() 253 ax = plt.subplot(1, 1, 1) 254 ax.set_title("left title", loc="left") 255 ax.set_title("right title", loc="right") 256 ax.set_xticks([]) 257 ax.set_yticks([]) 258 259 260@image_comparison(['text_alignment'], style='mpl20') 261def test_alignment(): 262 plt.figure() 263 ax = plt.subplot(1, 1, 1) 264 265 x = 0.1 266 for rotation in (0, 30): 267 for alignment in ('top', 'bottom', 'baseline', 'center'): 268 ax.text( 269 x, 0.5, alignment + " Tj", va=alignment, rotation=rotation, 270 bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5)) 271 ax.text( 272 x, 1.0, r'$\sum_{i=0}^{j}$', va=alignment, rotation=rotation) 273 x += 0.1 274 275 ax.plot([0, 1], [0.5, 0.5]) 276 ax.plot([0, 1], [1.0, 1.0]) 277 278 ax.set_xlim([0, 1]) 279 ax.set_ylim([0, 1.5]) 280 ax.set_xticks([]) 281 ax.set_yticks([]) 282 283 284@image_comparison(['axes_titles.png']) 285def test_axes_titles(): 286 # Related to issue #3327 287 plt.figure() 288 ax = plt.subplot(1, 1, 1) 289 ax.set_title('center', loc='center', fontsize=20, fontweight=700) 290 ax.set_title('left', loc='left', fontsize=12, fontweight=400) 291 ax.set_title('right', loc='right', fontsize=12, fontweight=400) 292 293 294def test_set_position(): 295 fig, ax = plt.subplots() 296 297 # test set_position 298 ann = ax.annotate( 299 'test', (0, 0), xytext=(0, 0), textcoords='figure pixels') 300 fig.canvas.draw() 301 302 init_pos = ann.get_window_extent(fig.canvas.renderer) 303 shift_val = 15 304 ann.set_position((shift_val, shift_val)) 305 fig.canvas.draw() 306 post_pos = ann.get_window_extent(fig.canvas.renderer) 307 308 for a, b in zip(init_pos.min, post_pos.min): 309 assert a + shift_val == b 310 311 # test xyann 312 ann = ax.annotate( 313 'test', (0, 0), xytext=(0, 0), textcoords='figure pixels') 314 fig.canvas.draw() 315 316 init_pos = ann.get_window_extent(fig.canvas.renderer) 317 shift_val = 15 318 ann.xyann = (shift_val, shift_val) 319 fig.canvas.draw() 320 post_pos = ann.get_window_extent(fig.canvas.renderer) 321 322 for a, b in zip(init_pos.min, post_pos.min): 323 assert a + shift_val == b 324 325 326@pytest.mark.parametrize('text', ['', 'O'], ids=['empty', 'non-empty']) 327def test_non_default_dpi(text): 328 fig, ax = plt.subplots() 329 330 t1 = ax.text(0.5, 0.5, text, ha='left', va='bottom') 331 fig.canvas.draw() 332 dpi = fig.dpi 333 334 bbox1 = t1.get_window_extent() 335 bbox2 = t1.get_window_extent(dpi=dpi * 10) 336 np.testing.assert_allclose(bbox2.get_points(), bbox1.get_points() * 10, 337 rtol=5e-2) 338 # Text.get_window_extent should not permanently change dpi. 339 assert fig.dpi == dpi 340 341 342def test_get_rotation_string(): 343 assert mpl.text.get_rotation('horizontal') == 0. 344 assert mpl.text.get_rotation('vertical') == 90. 345 assert mpl.text.get_rotation('15.') == 15. 346 347 348def test_get_rotation_float(): 349 for i in [15., 16.70, 77.4]: 350 assert mpl.text.get_rotation(i) == i 351 352 353def test_get_rotation_int(): 354 for i in [67, 16, 41]: 355 assert mpl.text.get_rotation(i) == float(i) 356 357 358def test_get_rotation_raises(): 359 with pytest.raises(ValueError): 360 mpl.text.get_rotation('hozirontal') 361 362 363def test_get_rotation_none(): 364 assert mpl.text.get_rotation(None) == 0.0 365 366 367def test_get_rotation_mod360(): 368 for i, j in zip([360., 377., 720+177.2], [0., 17., 177.2]): 369 assert_almost_equal(mpl.text.get_rotation(i), j) 370 371 372@pytest.mark.parametrize("ha", ["center", "right", "left"]) 373@pytest.mark.parametrize("va", ["center", "top", "bottom", 374 "baseline", "center_baseline"]) 375def test_null_rotation_with_rotation_mode(ha, va): 376 fig, ax = plt.subplots() 377 kw = dict(rotation=0, va=va, ha=ha) 378 t0 = ax.text(.5, .5, 'test', rotation_mode='anchor', **kw) 379 t1 = ax.text(.5, .5, 'test', rotation_mode='default', **kw) 380 fig.canvas.draw() 381 assert_almost_equal(t0.get_window_extent(fig.canvas.renderer).get_points(), 382 t1.get_window_extent(fig.canvas.renderer).get_points()) 383 384 385@image_comparison(['text_bboxclip']) 386def test_bbox_clipping(): 387 plt.text(0.9, 0.2, 'Is bbox clipped?', backgroundcolor='r', clip_on=True) 388 t = plt.text(0.9, 0.5, 'Is fancy bbox clipped?', clip_on=True) 389 t.set_bbox({"boxstyle": "round, pad=0.1"}) 390 391 392@image_comparison(['annotation_negative_ax_coords.png']) 393def test_annotation_negative_ax_coords(): 394 fig, ax = plt.subplots() 395 396 ax.annotate('+ pts', 397 xytext=[30, 20], textcoords='axes points', 398 xy=[30, 20], xycoords='axes points', fontsize=32) 399 ax.annotate('- pts', 400 xytext=[30, -20], textcoords='axes points', 401 xy=[30, -20], xycoords='axes points', fontsize=32, 402 va='top') 403 ax.annotate('+ frac', 404 xytext=[0.75, 0.05], textcoords='axes fraction', 405 xy=[0.75, 0.05], xycoords='axes fraction', fontsize=32) 406 ax.annotate('- frac', 407 xytext=[0.75, -0.05], textcoords='axes fraction', 408 xy=[0.75, -0.05], xycoords='axes fraction', fontsize=32, 409 va='top') 410 411 ax.annotate('+ pixels', 412 xytext=[160, 25], textcoords='axes pixels', 413 xy=[160, 25], xycoords='axes pixels', fontsize=32) 414 ax.annotate('- pixels', 415 xytext=[160, -25], textcoords='axes pixels', 416 xy=[160, -25], xycoords='axes pixels', fontsize=32, 417 va='top') 418 419 420@image_comparison(['annotation_negative_fig_coords.png']) 421def test_annotation_negative_fig_coords(): 422 fig, ax = plt.subplots() 423 424 ax.annotate('+ pts', 425 xytext=[10, 120], textcoords='figure points', 426 xy=[10, 120], xycoords='figure points', fontsize=32) 427 ax.annotate('- pts', 428 xytext=[-10, 180], textcoords='figure points', 429 xy=[-10, 180], xycoords='figure points', fontsize=32, 430 va='top') 431 ax.annotate('+ frac', 432 xytext=[0.05, 0.55], textcoords='figure fraction', 433 xy=[0.05, 0.55], xycoords='figure fraction', fontsize=32) 434 ax.annotate('- frac', 435 xytext=[-0.05, 0.5], textcoords='figure fraction', 436 xy=[-0.05, 0.5], xycoords='figure fraction', fontsize=32, 437 va='top') 438 439 ax.annotate('+ pixels', 440 xytext=[50, 50], textcoords='figure pixels', 441 xy=[50, 50], xycoords='figure pixels', fontsize=32) 442 ax.annotate('- pixels', 443 xytext=[-50, 100], textcoords='figure pixels', 444 xy=[-50, 100], xycoords='figure pixels', fontsize=32, 445 va='top') 446 447 448def test_text_stale(): 449 fig, (ax1, ax2) = plt.subplots(1, 2) 450 plt.draw_all() 451 assert not ax1.stale 452 assert not ax2.stale 453 assert not fig.stale 454 455 txt1 = ax1.text(.5, .5, 'aardvark') 456 assert ax1.stale 457 assert txt1.stale 458 assert fig.stale 459 460 ann1 = ax2.annotate('aardvark', xy=[.5, .5]) 461 assert ax2.stale 462 assert ann1.stale 463 assert fig.stale 464 465 plt.draw_all() 466 assert not ax1.stale 467 assert not ax2.stale 468 assert not fig.stale 469 470 471@image_comparison(['agg_text_clip.png']) 472def test_agg_text_clip(): 473 np.random.seed(1) 474 fig, (ax1, ax2) = plt.subplots(2) 475 for x, y in np.random.rand(10, 2): 476 ax1.text(x, y, "foo", clip_on=True) 477 ax2.text(x, y, "foo") 478 479 480def test_text_size_binding(): 481 mpl.rcParams['font.size'] = 10 482 fp = mpl.font_manager.FontProperties(size='large') 483 sz1 = fp.get_size_in_points() 484 mpl.rcParams['font.size'] = 100 485 486 assert sz1 == fp.get_size_in_points() 487 488 489@image_comparison(['font_scaling.pdf']) 490def test_font_scaling(): 491 mpl.rcParams['pdf.fonttype'] = 42 492 fig, ax = plt.subplots(figsize=(6.4, 12.4)) 493 ax.xaxis.set_major_locator(plt.NullLocator()) 494 ax.yaxis.set_major_locator(plt.NullLocator()) 495 ax.set_ylim(-10, 600) 496 497 for i, fs in enumerate(range(4, 43, 2)): 498 ax.text(0.1, i*30, "{fs} pt font size".format(fs=fs), fontsize=fs) 499 500 501@pytest.mark.parametrize('spacing1, spacing2', [(0.4, 2), (2, 0.4), (2, 2)]) 502def test_two_2line_texts(spacing1, spacing2): 503 text_string = 'line1\nline2' 504 fig = plt.figure() 505 renderer = fig.canvas.get_renderer() 506 507 text1 = plt.text(0.25, 0.5, text_string, linespacing=spacing1) 508 text2 = plt.text(0.25, 0.5, text_string, linespacing=spacing2) 509 fig.canvas.draw() 510 511 box1 = text1.get_window_extent(renderer=renderer) 512 box2 = text2.get_window_extent(renderer=renderer) 513 514 # line spacing only affects height 515 assert box1.width == box2.width 516 if spacing1 == spacing2: 517 assert box1.height == box2.height 518 else: 519 assert box1.height != box2.height 520 521 522def test_nonfinite_pos(): 523 fig, ax = plt.subplots() 524 ax.text(0, np.nan, 'nan') 525 ax.text(np.inf, 0, 'inf') 526 fig.canvas.draw() 527 528 529def test_hinting_factor_backends(): 530 plt.rcParams['text.hinting_factor'] = 1 531 fig = plt.figure() 532 t = fig.text(0.5, 0.5, 'some text') 533 534 fig.savefig(io.BytesIO(), format='svg') 535 expected = t.get_window_extent().intervalx 536 537 fig.savefig(io.BytesIO(), format='png') 538 # Backends should apply hinting_factor consistently (within 10%). 539 np.testing.assert_allclose(t.get_window_extent().intervalx, expected, 540 rtol=0.1) 541 542 543@needs_usetex 544def test_usetex_is_copied(): 545 # Indirectly tests that update_from (which is used to copy tick label 546 # properties) copies usetex state. 547 fig = plt.figure() 548 plt.rcParams["text.usetex"] = False 549 ax1 = fig.add_subplot(121) 550 plt.rcParams["text.usetex"] = True 551 ax2 = fig.add_subplot(122) 552 fig.canvas.draw() 553 for ax, usetex in [(ax1, False), (ax2, True)]: 554 for t in ax.xaxis.majorTicks: 555 assert t.label1.get_usetex() == usetex 556 557 558@needs_usetex 559def test_single_artist_usetex(): 560 # Check that a single artist marked with usetex does not get passed through 561 # the mathtext parser at all (for the Agg backend) (the mathtext parser 562 # currently fails to parse \frac12, requiring \frac{1}{2} instead). 563 fig = plt.figure() 564 fig.text(.5, .5, r"$\frac12$", usetex=True) 565 fig.canvas.draw() 566 567 568@pytest.mark.parametrize("fmt", ["png", "pdf", "svg"]) 569def test_single_artist_usenotex(fmt): 570 # Check that a single artist can be marked as not-usetex even though the 571 # rcParam is on ("2_2_2" fails if passed to TeX). This currently skips 572 # postscript output as the ps renderer doesn't support mixing usetex and 573 # non-usetex. 574 plt.rcParams["text.usetex"] = True 575 fig = plt.figure() 576 fig.text(.5, .5, "2_2_2", usetex=False) 577 fig.savefig(io.BytesIO(), format=fmt) 578 579 580@image_comparison(['text_as_path_opacity.svg']) 581def test_text_as_path_opacity(): 582 plt.figure() 583 plt.gca().set_axis_off() 584 plt.text(0.25, 0.25, 'c', color=(0, 0, 0, 0.5)) 585 plt.text(0.25, 0.5, 'a', alpha=0.5) 586 plt.text(0.25, 0.75, 'x', alpha=0.5, color=(0, 0, 0, 1)) 587 588 589@image_comparison(['text_as_text_opacity.svg']) 590def test_text_as_text_opacity(): 591 mpl.rcParams['svg.fonttype'] = 'none' 592 plt.figure() 593 plt.gca().set_axis_off() 594 plt.text(0.25, 0.25, '50% using `color`', color=(0, 0, 0, 0.5)) 595 plt.text(0.25, 0.5, '50% using `alpha`', alpha=0.5) 596 plt.text(0.25, 0.75, '50% using `alpha` and 100% `color`', alpha=0.5, 597 color=(0, 0, 0, 1)) 598 599 600def test_text_repr(): 601 # smoketest to make sure text repr doesn't error for category 602 plt.plot(['A', 'B'], [1, 2]) 603 repr(plt.text(['A'], 0.5, 'Boo')) 604 605 606def test_annotation_update(): 607 fig, ax = plt.subplots(1, 1) 608 an = ax.annotate('annotation', xy=(0.5, 0.5)) 609 extent1 = an.get_window_extent(fig.canvas.get_renderer()) 610 fig.tight_layout() 611 extent2 = an.get_window_extent(fig.canvas.get_renderer()) 612 613 assert not np.allclose(extent1.get_points(), extent2.get_points(), 614 rtol=1e-6) 615 616 617@check_figures_equal(extensions=["png"]) 618def test_annotation_units(fig_test, fig_ref): 619 ax = fig_test.add_subplot() 620 ax.plot(datetime.now(), 1, "o") # Implicitly set axes extents. 621 ax.annotate("x", (datetime.now(), 0.5), xycoords=("data", "axes fraction"), 622 # This used to crash before. 623 xytext=(0, 0), textcoords="offset points") 624 ax = fig_ref.add_subplot() 625 ax.plot(datetime.now(), 1, "o") 626 ax.annotate("x", (datetime.now(), 0.5), xycoords=("data", "axes fraction")) 627 628 629@image_comparison(['large_subscript_title.png'], style='mpl20') 630def test_large_subscript_title(): 631 # Remove this line when this test image is regenerated. 632 plt.rcParams['text.kerning_factor'] = 6 633 plt.rcParams['axes.titley'] = None 634 635 fig, axs = plt.subplots(1, 2, figsize=(9, 2.5), constrained_layout=True) 636 ax = axs[0] 637 ax.set_title(r'$\sum_{i} x_i$') 638 ax.set_title('New way', loc='left') 639 ax.set_xticklabels('') 640 641 ax = axs[1] 642 ax.set_title(r'$\sum_{i} x_i$', y=1.01) 643 ax.set_title('Old Way', loc='left') 644 ax.set_xticklabels('') 645 646 647def test_wrap(): 648 fig = plt.figure(figsize=(6, 4)) 649 s = 'This is a very long text that should be wrapped multiple times.' 650 text = fig.text(0.7, 0.5, s, wrap=True) 651 fig.canvas.draw() 652 assert text._get_wrapped_text() == ('This is a very long\n' 653 'text that should be\n' 654 'wrapped multiple\n' 655 'times.') 656 657 658def test_long_word_wrap(): 659 fig = plt.figure(figsize=(6, 4)) 660 text = fig.text(9.5, 8, 'Alonglineoftexttowrap', wrap=True) 661 fig.canvas.draw() 662 assert text._get_wrapped_text() == 'Alonglineoftexttowrap' 663 664 665def test_wrap_no_wrap(): 666 fig = plt.figure(figsize=(6, 4)) 667 text = fig.text(0, 0, 'non wrapped text', wrap=True) 668 fig.canvas.draw() 669 assert text._get_wrapped_text() == 'non wrapped text' 670 671 672@check_figures_equal(extensions=["png"]) 673def test_buffer_size(fig_test, fig_ref): 674 # On old versions of the Agg renderer, large non-ascii single-character 675 # strings (here, "€") would be rendered clipped because the rendering 676 # buffer would be set by the physical size of the smaller "a" character. 677 ax = fig_test.add_subplot() 678 ax.set_yticks([0, 1]) 679 ax.set_yticklabels(["€", "a"]) 680 ax.yaxis.majorTicks[1].label1.set_color("w") 681 ax = fig_ref.add_subplot() 682 ax.set_yticks([0, 1]) 683 ax.set_yticklabels(["€", ""]) 684 685 686def test_fontproperties_kwarg_precedence(): 687 """Test that kwargs take precedence over fontproperties defaults.""" 688 plt.figure() 689 text1 = plt.xlabel("value", fontproperties='Times New Roman', size=40.0) 690 text2 = plt.ylabel("counts", size=40.0, fontproperties='Times New Roman') 691 assert text1.get_size() == 40.0 692 assert text2.get_size() == 40.0 693 694 695def test_transform_rotates_text(): 696 ax = plt.gca() 697 transform = mtransforms.Affine2D().rotate_deg(30) 698 text = ax.text(0, 0, 'test', transform=transform, 699 transform_rotates_text=True) 700 result = text.get_rotation() 701 assert_almost_equal(result, 30) 702 703 704def test_update_mutate_input(): 705 inp = dict(fontproperties=FontProperties(weight="bold"), 706 bbox=None) 707 cache = dict(inp) 708 t = Text() 709 t.update(inp) 710 assert inp['fontproperties'] == cache['fontproperties'] 711 assert inp['bbox'] == cache['bbox'] 712 713 714def test_invalid_color(): 715 with pytest.raises(ValueError): 716 plt.figtext(.5, .5, "foo", c="foobar") 717 718 719@image_comparison(['text_pdf_kerning.pdf'], style='mpl20') 720def test_pdf_kerning(): 721 plt.figure() 722 plt.figtext(0.1, 0.5, "ATATATATATATATATATA", size=30) 723