8000 Merge pull request #24484 from leejjoon/draw-prevent-rasterization-by… · matplotlib/matplotlib@cca039d · GitHub
[go: up one dir, main page]

Skip to content

Commit cca039d

Browse files
authored
Merge pull request #24484 from leejjoon/draw-prevent-rasterization-by-default
Artist's draw method prevents rasterization by default
2 parents 4d52a3e + d8d2c68 commit cca039d

File tree

5 files changed

+79
-12
lines changed

5 files changed

+79
-12
lines changed

doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,13 @@ mathtext glues
273273
The *copy* parameter of ``mathtext.Glue`` is deprecated (the underlying glue
274274
spec is now immutable). ``mathtext.GlueSpec`` is deprecated.
275275

276-
Signatures of `.Artist.draw` and `.Axes.draw`
277-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278-
The *inframe* parameter to `.Axes.draw` is deprecated. Use
276+
Signatures of `.Artist.draw` and `matplotlib.axes.Axes.draw`
277+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278+
The *inframe* parameter to `matplotlib.axes.Axes.draw` is deprecated. Use
279279
`.Axes.redraw_in_frame` instead.
280280

281-
Not passing the *renderer* parameter to `.Axes.draw` is deprecated. Use
282-
``axes.draw_artist(axes)`` instead.
281+
Not passing the *renderer* parameter to `matplotlib.axes.Axes.draw` is
282+
deprecated. Use ``axes.draw_artist(axes)`` instead.
283283

284284
These changes make the signature of the ``draw`` (``artist.draw(renderer)``)
285285
method consistent across all artists; thus, additional parameters to

doc/api/prev_api_changes/api_changes_3.5.0/removals.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ Arguments
260260

261261
- The *s* parameter to `.Axes.annotate` and `.pyplot.annotate` is no longer
262262
supported; use the new name *text*.
263-
- The *inframe* parameter to `.Axes.draw` has been removed; use
263+
- The *inframe* parameter to `matplotlib.axes.Axes.draw` has been removed; use
264264
`.Axes.redraw_in_frame` instead.
265265
- The *required*, *forbidden* and *allowed* parameters of
266266
`.cbook.normalize_kwargs` have been removed.
@@ -312,13 +312,13 @@ Arguments
312312
warning for keyword arguments that were overridden by the mappable is now
313313
removed.
314314

315-
- Omitting the *renderer* parameter to `.Axes.draw` is no longer supported; use
316-
``axes.draw_artist(axes)`` instead.
315+
- Omitting the *renderer* parameter to `matplotlib.axes.Axes.draw` is no longer
316+
supported; use ``axes.draw_artist(axes)`` instead.
317317
- Passing ``ismath="TeX!"`` to `.RendererAgg.get_text_width_height_descent` is
318318
no longer supported; pass ``ismath="TeX"`` instead,
319-
- Changes to the signature of the `.Axes.draw` method make it consistent with
320-
all other artists; thus additional parameters to `.Artist.draw` have also
321-
been removed.
319+
- Changes to the signature of the `matplotlib.axes.Axes.draw` method make it
320+
consistent with all other artists; thus additional parameters to
321+
`.Artist.draw` have also been removed.
322322

323323
rcParams
324324
~~~~~~~~

lib/matplotlib/artist.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@
2121
_log = logging.getLogger(__name__)
2222

2323

24+
def _prevent_rasterization(draw):
25+
# We assume that by default artists are not allowed to rasterize (unless
26+
# its draw method is explicitly decorated). If it is being drawn after a
27+
# rasterized artist and it has reached a raster_depth of 0, we stop
28+
# rasterization so that it does not affect the behavior of normal artist
29+
# (e.g., change in dpi).
30+
31+
@wraps(draw)
32+
def draw_wrapper(artist, renderer):
33+
if renderer._raster_depth == 0 and renderer._rasterizing:
34+
# Only stop when we are not in a rasterized parent
35+
# and something has been rasterized since last stop.
36+
renderer.stop_rasterizing()
37+
renderer._rasterizing = False
38+
39+
return draw(artist, renderer)
40+
41+
draw_wrapper._supports_rasterization = False
42+
return draw_wrapper
43+
44+
2445
def allow_rasterization(draw):
2546
"""
2647
Decorator for Artist.draw method. Provides routines
@@ -103,6 +124,15 @@ class Artist:
103124
zorder = 0
104125

105126
def __init_subclass__(cls):
127+
128+
# Decorate draw() method so that all artists are able to stop
129+
# rastrization when necessary. If the artist's draw method is already
130+
# decorated (has a `_supports_rasterization` attribute), it won't be
131+
# decorated.
132+
133+
if not hasattr(cls.draw, "_supports_rasterization"):
134+
cls.draw = _prevent_rasterization(cls.draw)
135+
106136
# Inject custom set() methods into the subclass with signature and
107137
# docstring based on the subclasses' properties.
108138

@@ -921,7 +951,9 @@ def set_rasterized(self, rasterized):
921951
----------
922952
rasterized : bool
923953
"""
924-
if rasterized and not hasattr(self.draw, "_supports_rasterization"):
954+
supports_rasterization = getattr(self.draw,
955+
"_supports_rasterization", False)
956+
if rasterized and not supports_rasterization:
925957
_api.warn_external(f"Rasterization of '{self}' will be ignored")
926958

927959
self._rasterized = rasterized

lib/matplotlib/tests/test_artist.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,17 @@ def test_format_cursor_data_BoundaryNorm():
535535
assert img.format_cursor_data(v) == label
536536

537537
plt.close()
538+
539+
540+
def test_auto_no_rasterize():
541+
class Gen1(martist.Artist):
542+
...
543+
544+
assert 'draw' in Gen1.__dict__
545+
assert Gen1.__dict__['draw'] is Gen1.draw
546+
547+
class Gen2(Gen1):
548+
...
549+
550+
assert 'draw' not in Gen2.__dict__
551+
assert Gen2.draw is Gen1.draw

lib/matplotlib/tests/test_backend_svg.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,27 @@ def test_rasterized_ordering(fig_test, fig_ref):
122122
ax_test.plot(x+1, y, "-", c="b", lw=10, rasterized=False, zorder=1.2)
123123

124124

125+
@check_figures_equal(tol=5, extensions=['svg', 'pdf'])
126+
def test_prevent_rasterization(fig_test, fig_ref):
127+
loc = [0.05, 0.05]
128+
129+
ax_ref = fig_ref.subplots()
130+
131+
ax_ref.plot([loc[0]], [loc[1]], marker="x", c="black", zorder=2)
132+
133+
b = mpl.offsetbox.TextArea("X")
134+
abox = mpl.offsetbox.AnnotationBbox(b, loc, zorder=2.1)
135+
ax_ref.add_artist(abox)
136+
137+
ax_test = fig_test.subplots()
138+
ax_test.plot([loc[0]], [loc[1]], marker="x", c="black", zorder=2,
139+
rasterized=True)
140+
141+
b = mpl.offsetbox.TextArea("X")
142+
abox = mpl.offsetbox.AnnotationBbox(b, loc, zorder=2.1)
143+
ax_test.add_artist(abox)
144+
145+
125146
def test_count_bitmaps():
126147
def count_tag(fig, tag):
127148
with BytesIO() as fd:

0 commit comments

Comments
 (0)
0