Skip to content

Commit dad0ce2

Browse files
committed
pdf: Export path collections as a single group
1 parent c2d502d commit dad0ce2

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,9 @@ def __init__(self, filename, metadata=None):
735735
self._hatch_pattern_seq = (Name(f'H{i}') for i in itertools.count(1))
736736
self.gouraudTriangles = []
737737

738+
self._groups = {}
739+
self._group_seq = (Name(f'G{i}') for i in itertools.count(1))
740+
738741
self._images = {}
739742
self._image_seq = (Name(f'I{i}') for i in itertools.count(1))
740743

@@ -829,16 +832,17 @@ def finalize(self):
829832
self._write_soft_mask_groups()
830833
self.writeHatches()
831834
self.writeGouraudTriangles()
832-
xobjects = {
833-
name: ob for image, name, ob in self._images.values()}
835+
xobjects = {name: ob for image, name, ob in self._images.values()}
834836
for tup in self.markers.values():
835837
xobjects[tup[0]] = tup[1]
836838
for name, value in self.multi_byte_charprocs.items():
837839
xobjects[name] = value
838-
for name, path, trans, ob, join, cap, padding, filled, stroked \
839-
in self.paths:
840-
xobjects[name] = ob
840+
for name, path, trans, obj, join, cap, padding, filled, stroked in self.paths:
841+
xobjects[name] = obj
842+
for group, name, obj in self._groups.values():
843+
xobjects[name] = obj
841844
self.writeObject(self.XObjectObject, xobjects)
845+
self.writeGroups()
842846
self.writeImages()
843847
self.writeMarkers()
844848
self.writePathCollectionTemplates()
@@ -1658,6 +1662,18 @@ def writeGouraudTriangles(self):
16581662
self.endStream()
16591663
self.writeObject(self.gouraudObject, gouraudDict)
16601664

1665+
def groupObject(self, group):
1666+
"""Return name of a group XObject representing the given group."""
1667+
1668+
entry = self._groups.get(id(group), None)
1669+
if entry is not None:
1670+
return entry[1]
1671+
1672+
name = next(self._group_seq)
1673+
obj = self.reserveObject(f'group {name}')
1674+
self._groups[id(group)] = (group, name, obj)
1675+
return name
1676+
16611677
def imageObject(self, image):
16621678
"""Return name of an image XObject representing the given image."""
16631679

@@ -1785,6 +1801,16 @@ def _writeImg(self, data, id, smask=None):
17851801
self.currentstream.write(data.tobytes())
17861802
self.endStream()
17871803

1804+
def writeGroups(self):
1805+
print('writeGroups', len(self._groups))
1806+
for group, name, obj in self._groups.values():
1807+
self.beginStream(
1808+
obj.id, None,
1809+
{'Type': Name('XObject'), 'Subtype': Name('Form'),
1810+
'Group': {'S': Name('Transparency'), 'I': True, 'K': True}})
1811+
self.output(*group)
1812+
self.endStream()
1813+
17881814
def writeImages(self):
17891815
for img, name, ob in self._images.values():
17901816
data, adata = self._unpack(img)
@@ -2082,8 +2108,8 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms,
20822108
gc, path, transform, padding, filled, stroked)
20832109
path_codes.append(name)
20842110

2085-
output = self.file.output
2086-
output(*self.gc.push())
2111+
ops = []
2112+
ops.extend(self.gc.push())
20872113
lastx, lasty = 0, 0
20882114
for xo, yo, path_id, gc0, rgbFace in self._iter_collection(
20892115
gc, path_codes, offsets, offset_trans,
@@ -2092,10 +2118,12 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms,
20922118

20932119
self.check_gc(gc0, rgbFace)
20942120
dx, dy = xo - lastx, yo - lasty
2095-
output(1, 0, 0, 1, dx, dy, Op.concat_matrix, path_id,
2096-
Op.use_xobject)
2121+
ops.extend([1, 0, 0, 1, dx, dy, Op.concat_matrix, path_id, Op.use_xobject])
20972122
lastx, lasty = xo, yo
2098-
output(*self.gc.pop())
2123+
ops.extend(self.gc.pop())
2124+
2125+
group_name = self.file.groupObject(ops)
2126+
self.file.output(group_name, Op.use_xobject)
20992127

21002128
def draw_markers(self, gc, marker_path, marker_trans, path, trans,
21012129
rgbFace=None):

0 commit comments

Comments
 (0)