diff --git a/doc/users/whats_new/pdfpages_notes.rst b/doc/users/whats_new/pdfpages_notes.rst new file mode 100644 index 000000000000..9f4784ff76e8 --- /dev/null +++ b/doc/users/whats_new/pdfpages_notes.rst @@ -0,0 +1,12 @@ +Per-page pdf notes in multi-page pdfs (PdfPages) +------------------------------------------------ + +Add a new method attach_note to the PdfPages class, allowing the +attachment of simple text notes to pages in a multi-page pdf of +figures. The new note is visible in the list of pdf annotations in a +viewer that has this facility (Adobe Reader, OSX Preview, Skim, +etc.). Per default the note itself is kept off-page to prevent it to +appear in print-outs. + +PdfPages.attach_note needs to be called before savefig in order to be +added to the correct figure. diff --git a/examples/pylab_examples/multipage_pdf.py b/examples/pylab_examples/multipage_pdf.py index 2ccdfd2fe046..c639b62726c0 100644 --- a/examples/pylab_examples/multipage_pdf.py +++ b/examples/pylab_examples/multipage_pdf.py @@ -20,6 +20,8 @@ x = np.arange(0, 5, 0.1) plt.plot(x, np.sin(x), 'b-') plt.title('Page Two') + pdf.attach_note("plot of sin(x)") # you can add a pdf note to + # attach metadata to a page pdf.savefig() plt.close() diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 085c0e7ec665..7e26871789cd 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -480,6 +480,9 @@ def __init__(self, filename): self.paths = [] + self.pageAnnotations = [] # A list of annotations for the + # current page + # The PDF spec recommends to include every procset procsets = [Name(x) for x in "PDF Text ImageB ImageC ImageI".split()] @@ -507,7 +510,8 @@ def newPage(self, width, height): 'Contents': contentObject, 'Group': {'Type': Name('Group'), 'S': Name('Transparency'), - 'CS': Name('DeviceRGB')} + 'CS': Name('DeviceRGB')}, + 'Annots': self.pageAnnotations, } pageObject = self.reserveObject('page') self.writeObject(pageObject, thePage) @@ -519,6 +523,20 @@ def newPage(self, width, height): # graphics context: currently only the join style needs to be set self.output(GraphicsContextPdf.joinstyles['round'], Op.setlinejoin) + # Clear the list of annotations for the next page + self.pageAnnotations = [] + + def newTextnote(self, text, positionRect=[-100, -100, 0, 0]): + # Create a new annotation of type text + theNote = {'Type': Name('Annot'), + 'Subtype': Name('Text'), + 'Contents': text, + 'Rect': positionRect, + } + annotObject = self.reserveObject('annotation') + self.writeObject(annotObject, theNote) + self.pageAnnotations.append(annotObject) + def close(self): self.endStream() # Write out the various deferred objects @@ -2445,6 +2463,15 @@ def get_pagecount(self): """ return len(self._file.pageList) + def attach_note(self, text, positionRect=[-100, -100, 0, 0]): + """ + Add a new text note to the page to be saved next. The optional + positionRect specifies the position of the new note on the + page. It is outside the page per default to make sure it is + invisible on printouts. + """ + self._file.newTextnote(text, positionRect) + class FigureCanvasPdf(FigureCanvasBase): """