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

Skip to content

Commit 80bba8e

Browse files
committed
Merge pull request #2621 from pwuertz/fix_2586
Simplify and fix dpi handling in tight_bbox
2 parents 0511450 + 2c84d10 commit 80bba8e

File tree

10 files changed

+49
-72
lines changed

10 files changed

+49
-72
lines changed

doc/api/api_changes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ original location:
134134
* Removed the class `FigureManagerQTAgg` and deprecated `NavigationToolbar2QTAgg`
135135
which will be removed in 1.5.
136136

137+
* The function signatures of `tight_bbox.adjust_bbox` and
138+
`tight_bbox.process_figure_for_rasterizing` have been changed. A new
139+
`fixed_dpi` parameter allows for overriding the `figure.dpi` setting
140+
instead of trying to deduce the intended behaviour from the file format.
141+
142+
137143
.. _changes_in_1_3:
138144

139145

lib/matplotlib/backend_bases.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,7 @@ class FigureCanvasBase(object):
16251625
]
16261626

16271627
supports_blit = True
1628+
fixed_dpi = None
16281629

16291630
filetypes = _default_filetypes
16301631
if _has_pil:
@@ -2171,8 +2172,8 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
21712172

21722173
bbox_inches = bbox_inches.padded(pad)
21732174

2174-
restore_bbox = tight_bbox.adjust_bbox(self.figure, format,
2175-
bbox_inches)
2175+
restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
2176+
canvas.fixed_dpi)
21762177

21772178
_bbox_inches_restore = (bbox_inches, restore_bbox)
21782179
else:

lib/matplotlib/backends/backend_mixed.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,9 @@ def start_rasterizing(self):
9393

9494
if self._bbox_inches_restore: # when tight bbox is used
9595
r = process_figure_for_rasterizing(self.figure,
96-
self._bbox_inches_restore,
97-
mode="png")
98-
96+
self._bbox_inches_restore)
9997
self._bbox_inches_restore = r
10098

101-
10299
if self._rasterizing == 0:
103100
self._raster_renderer = self._raster_renderer_class(
104101
self._width*self.dpi, self._height*self.dpi, self.dpi)
@@ -143,5 +140,5 @@ def stop_rasterizing(self):
143140
if self._bbox_inches_restore: # when tight bbox is used
144141
r = process_figure_for_rasterizing(self.figure,
145142
self._bbox_inches_restore,
146-
mode="pdf")
143+
self._figdpi)
147144
self._bbox_inches_restore = r

lib/matplotlib/backends/backend_pdf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,6 +2442,8 @@ class FigureCanvasPdf(FigureCanvasBase):
24422442
figure - A Figure instance
24432443
"""
24442444

2445+
fixed_dpi = 72
2446+
24452447
def draw(self):
24462448
pass
24472449

lib/matplotlib/backends/backend_pgf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ def _print_pgf_to_fh(self, fh, *args, **kwargs):
796796
writeln(fh, r"\makeatletter")
797797
writeln(fh, r"\begin{pgfpicture}")
798798
writeln(fh, r"\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{%fin}{%fin}}" % (w, h))
799-
writeln(fh, r"\pgfusepath{use as bounding box}")
799+
writeln(fh, r"\pgfusepath{use as bounding box, clip}")
800800
_bbox_inches_restore = kwargs.pop("bbox_inches_restore", None)
801801
renderer = MixedModeRenderer(self.figure, w, h, dpi,
802802
RendererPgf(self.figure, fh),

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,8 @@ def new_figure_manager_given_figure(num, figure):
969969
class FigureCanvasPS(FigureCanvasBase):
970970
_renderer_class = RendererPS
971971

972+
fixed_dpi = 72
973+
972974
def draw(self):
973975
pass
974976

lib/matplotlib/backends/backend_svg.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,8 @@ class FigureCanvasSVG(FigureCanvasBase):
11581158
filetypes = {'svg': 'Scalable Vector Graphics',
11591159
'svgz': 'Scalable Vector Graphics'}
11601160

1161+
fixed_dpi = 72
1162+
11611163
def print_svg(self, filename, *args, **kwargs):
11621164
if is_string_like(filename):
11631165
fh_to_close = svgwriter = io.open(filename, 'w', encoding='utf-8')
Binary file not shown.

lib/matplotlib/tests/test_backend_pgf.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ def backend_switcher(*args, **kwargs):
5858
return switch_backend_decorator
5959

6060

61-
def compare_figure(fname):
61+
def compare_figure(fname, savefig_kwargs={}):
6262
actual = os.path.join(result_dir, fname)
63-
plt.savefig(actual)
63+
plt.savefig(actual, **savefig_kwargs)
6464

6565
expected = os.path.join(result_dir, "expected_%s" % fname)
6666
shutil.copyfile(os.path.join(baseline_dir, fname), expected)
@@ -168,6 +168,24 @@ def test_mixedmode():
168168
compare_figure('pgf_mixedmode.pdf')
169169

170170

171+
# test bbox_inches clipping
172+
@switch_backend('pgf')
173+
def test_bbox_inches():
174+
if not check_for('xelatex'):
175+
raise SkipTest('xelatex + pgf is required')
176+
177+
Y, X = np.ogrid[-1:1:40j, -1:1:40j]
178+
fig = plt.figure()
179+
ax1 = fig.add_subplot(121)
180+
ax1.plot(range(5))
181+
ax2 = fig.add_subplot(122)
182+
ax2.plot(range(5))
183+
plt.tight_layout()
184+
185+
bbox = ax1.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
186+
compare_figure('pgf_bbox_inches.pdf', savefig_kwargs={'bbox_inches': bbox})
187+
188+
171189
if __name__ == '__main__':
172190
import nose
173191
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

lib/matplotlib/tight_bbox.py

Lines changed: 11 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from matplotlib.transforms import Bbox, TransformedBbox, Affine2D
1212

1313

14-
def adjust_bbox(fig, format, bbox_inches):
14+
def adjust_bbox(fig, bbox_inches, fixed_dpi=None):
1515
"""
1616
Temporarily adjust the figure so that only the specified area
1717
(bbox_inches) is saved.
@@ -50,74 +50,31 @@ def restore_bbox():
5050
fig.transFigure.invalidate()
5151
fig.patch.set_bounds(0, 0, 1, 1)
5252

53-
adjust_bbox_handler = _adjust_bbox_handler_d.get(format)
54-
if adjust_bbox_handler is not None:
55-
adjust_bbox_handler(fig, bbox_inches)
56-
return restore_bbox
53+
if fixed_dpi is not None:
54+
tr = Affine2D().scale(fixed_dpi)
55+
dpi_scale = fixed_dpi / fig.dpi
5756
else:
58-
warnings.warn("bbox_inches option for %s backend is not "
59-
"implemented yet." % (format))
60-
return None
61-
62-
63-
def adjust_bbox_png(fig, bbox_inches):
64-
"""
65-
adjust_bbox for png (Agg) format
66-
"""
67-
68-
tr = fig.dpi_scale_trans
69-
70-
_bbox = TransformedBbox(bbox_inches,
71-
tr)
72-
x0, y0 = _bbox.x0, _bbox.y0
73-
fig.bbox_inches = Bbox.from_bounds(0, 0,
74-
bbox_inches.width,
75-
bbox_inches.height)
76-
77-
x0, y0 = _bbox.x0, _bbox.y0
78-
w1, h1 = fig.bbox.width, fig.bbox.height
79-
fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0,
80-
w1, h1)
81-
fig.transFigure.invalidate()
82-
83-
fig.bbox = TransformedBbox(fig.bbox_inches, tr)
84-
85-
fig.patch.set_bounds(x0 / w1, y0 / h1,
86-
fig.bbox.width / w1, fig.bbox.height / h1)
87-
88-
89-
def adjust_bbox_pdf(fig, bbox_inches):
90-
"""
91-
adjust_bbox for pdf & eps format
92-
"""
93-
94-
if fig._cachedRenderer.__class__.__name__ == "RendererPgf":
9557
tr = Affine2D().scale(fig.dpi)
96-
f = 1.
97-
else:
98-
tr = Affine2D().scale(72)
99-
f = 72. / fig.dpi
58+
dpi_scale = 1.
10059

10160
_bbox = TransformedBbox(bbox_inches, tr)
10261

10362
fig.bbox_inches = Bbox.from_bounds(0, 0,
104-
bbox_inches.width,
105-
bbox_inches.height)
63+
bbox_inches.width, bbox_inches.height)
10664
x0, y0 = _bbox.x0, _bbox.y0
107-
w1, h1 = fig.bbox.width * f, fig.bbox.height * f
108-
fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0,
109-
w1, h1)
65+
w1, h1 = fig.bbox.width * dpi_scale, fig.bbox.height * dpi_scale
66+
fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0, w1, h1)
11067
fig.transFigure.invalidate()
11168

11269
fig.bbox = TransformedBbox(fig.bbox_inches, tr)
11370

11471
fig.patch.set_bounds(x0 / w1, y0 / h1,
11572
fig.bbox.width / w1, fig.bbox.height / h1)
11673

74+
return restore_bbox
11775

118-
def process_figure_for_rasterizing(figure,
119-
bbox_inches_restore, mode):
12076

77+
def process_figure_for_rasterizing(fig, bbox_inches_restore, fixed_dpi=None):
12178
"""
12279
This need to be called when figure dpi changes during the drawing
12380
(e.g., rasterizing). It recovers the bbox and re-adjust it with
@@ -126,14 +83,6 @@ def process_figure_for_rasterizing(figure,
12683

12784
bbox_inches, restore_bbox = bbox_inches_restore
12885
restore_bbox()
129-
r = adjust_bbox(figure, mode,
130-
bbox_inches)
86+
r = adjust_bbox(figure, bbox_inches, fixed_dpi)
13187

13288
return bbox_inches, r
133-
134-
135-
_adjust_bbox_handler_d = {}
136-
for format in ["png", "raw", "rgba", "jpg", "jpeg", "tiff"]:
137-
_adjust_bbox_handler_d[format] = adjust_bbox_png
138-
for format in ["pgf", "pdf", "eps", "svg", "svgz"]:
139-
_adjust_bbox_handler_d[format] = adjust_bbox_pdf

0 commit comments

Comments
 (0)