Skip to content

Commit df3c55c

Browse files
committed
Enhance the renderer support of the DrawingArea class by adding DPI correction for rasterized content
1 parent 716d046 commit df3c55c

1 file changed

Lines changed: 42 additions & 6 deletions

File tree

lib/matplotlib/offsetbox.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@
4242
DEBUG = False
4343

4444

45+
def _is_vector_renderer(renderer):
46+
# 1. Check the mode name
47+
# If it's MixedModeRenderer, get the actual renderer recursively
48+
while type(renderer).__name__ == 'MixedModeRenderer':
49+
eff = getattr(renderer, '_renderer', renderer)
50+
mod = getattr(eff.__class__, '__module__', '').lower()
51+
if any(x in mod for x in ('pdf', 'svg', 'ps')):
52+
return True
53+
# 2. The vectorized backends
54+
vector_bases = (
55+
'RendererPdf', 'RendererSVG', 'RendererPS'
56+
)
57+
if any(base in type(renderer).__name__ for base in vector_bases):
58+
return True
59+
# 3. fallback: Agg/bitmap are not vector renderers
60+
if 'agg' in mod or 'bitmap' in mod:
61+
return False
62+
# 4. For unknown renderers, assume they are not vector
63+
return False
64+
65+
4566
def _compat_get_offset(meth):
4667
"""
4768
Decorator for the get_offset method of OffsetBox and subclasses, that
@@ -689,18 +710,33 @@ def draw(self, renderer):
689710
self.dpi_transform.clear()
690711
self.dpi_transform.scale(dpi_cor)
691712

692-
# At this point the DrawingArea has a transform
693-
# to the display space so the path created is
694-
# good for clipping children
695713
tpath = mtransforms.TransformedPath(
696714
mpath.Path([[0, 0], [0, self.height],
697715
[self.width, self.height],
698716
[self.width, 0]]),
699717
self.get_transform())
700718
for c in self._children:
701-
if self._clip_children and not (c.clipbox or c._clippath):
702-
c.set_clip_path(tpath)
703-
c.draw(renderer)
719+
is_rasterized = getattr(c, 'get_rasterized', lambda: False)()
720+
if is_rasterized and _is_vector_renderer(renderer):
721+
# PDF/SVG backend uses 72 dpi in display units,
722+
# so we need to scale the rasterized content accordingly
723+
target_dpi = getattr(renderer, 'dpi', 72) or 72
724+
dpi_correction = target_dpi / 72
725+
# New transform to apply the dpi correction
726+
corrected_transform = self.get_transform() \
727+
+ mtransforms.Affine2D().scale(dpi_correction)
728+
orig_transform = c.get_transform() \
729+
if hasattr(c, 'get_transform') else None
730+
c.set_transform(corrected_transform)
731+
if self._clip_children and not (c.clipbox or c._clippath):
732+
c.set_clip_path(tpath)
733+
c.draw(renderer)
734+
if orig_transform is not None:
735+
c.set_transform(orig_transform)
736+
else:
737+
if self._clip_children and not (c.clipbox or c._clippath):
738+
c.set_clip_path(tpath)
739+
c.draw(renderer)
704740

705741
_bbox_artist(self, renderer, fill=False, props=dict(pad=0.))
706742
self.stale = False

0 commit comments

Comments
 (0)