diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 42e71f7778b5..1e2fc5290818 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -3316,12 +3316,37 @@ def savefig(self, fname, *, transparent=None, **kwargs): with ExitStack() as stack: if transparent: + def _recursively_make_subfig_transparent(exit_stack, subfig): + exit_stack.enter_context( + subfig.patch._cm_set( + facecolor="none", edgecolor="none")) + for ax in subfig.axes: + exit_stack.enter_context( + ax.patch._cm_set( + facecolor="none", edgecolor="none")) + for sub_subfig in subfig.subfigs: + _recursively_make_subfig_transparent( + exit_stack, sub_subfig) + + def _recursively_make_axes_transparent(exit_stack, ax): + exit_stack.enter_context( + ax.patch._cm_set(facecolor="none", edgecolor="none")) + for child_ax in ax.child_axes: + exit_stack.enter_context( + child_ax.patch._cm_set( + facecolor="none", edgecolor="none")) + for child_childax in ax.child_axes: + _recursively_make_axes_transparent( + exit_stack, child_childax) + kwargs.setdefault('facecolor', 'none') kwargs.setdefault('edgecolor', 'none') + # set subfigure to appear transparent in printed image + for subfig in self.subfigs: + _recursively_make_subfig_transparent(stack, subfig) + # set axes to be transparent for ax in self.axes: - stack.enter_context( - ax.patch._cm_set(facecolor='none', edgecolor='none')) - + _recursively_make_axes_transparent(stack, ax) self.canvas.print_figure(fname, **kwargs) def ginput(self, n=1, timeout=30, show_clicks=True, diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 5d625d661ae0..8ee6bf2d2751 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -539,6 +539,29 @@ def test_savefig_preserve_layout_engine(tmp_path): assert fig.get_layout_engine()._compress +@mpl.rc_context({"savefig.transparent": True}) +@check_figures_equal(extensions=["png"]) +def test_savefig_transparent(fig_test, fig_ref): + # create two transparent subfigures with corresponding transparent inset + # axes. the entire background of the image should be transparent. + gs1 = fig_test.add_gridspec(3, 3, left=0.05, wspace=0.05) + f1 = fig_test.add_subfigure(gs1[:, :]) + f2 = f1.add_subfigure(gs1[0, 0]) + + ax12 = f2.add_subplot(gs1[:, :]) + + ax1 = f1.add_subplot(gs1[:-1, :]) + iax1 = ax1.inset_axes([.1, .2, .3, .4]) + iax2 = iax1.inset_axes([.1, .2, .3, .4]) + + ax2 = fig_test.add_subplot(gs1[-1, :-1]) + ax3 = fig_test.add_subplot(gs1[-1, -1]) + + for ax in [ax12, ax1, iax1, iax2, ax2, ax3]: + ax.set(xticks=[], yticks=[]) + ax.spines[:].set_visible(False) + + def test_figure_repr(): fig = plt.figure(figsize=(10, 20), dpi=10) assert repr(fig) == "
"