Revision: 7964
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7964&view=rev
Author:   jouni
Date:     2009-11-13 19:22:52 +0000 (Fri, 13 Nov 2009)

Log Message:
-----------
Expose the pdf information dictionary

Modified Paths:
--------------
    trunk/matplotlib/CHANGELOG
    trunk/matplotlib/doc/api/api_changes.rst
    trunk/matplotlib/examples/pylab_examples/multipage_pdf.py
    trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py

Property Changed:
----------------
    trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py

Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG  2009-11-13 00:44:11 UTC (rev 7963)
+++ trunk/matplotlib/CHANGELOG  2009-11-13 19:22:52 UTC (rev 7964)
@@ -1,3 +1,6 @@
+2009-11-13 The pdf backend now allows changing the contents of
+           a pdf file's information dictionary via PdfPages.infodict. - JKS
+
 2009-11-12 font_manager.py should no longer cause EINTR on Python 2.6
            (but will on the 2.5 version of subprocess). Also the
            fc-list command in that file was fixed so now it should

Modified: trunk/matplotlib/doc/api/api_changes.rst
===================================================================
--- trunk/matplotlib/doc/api/api_changes.rst    2009-11-13 00:44:11 UTC (rev 
7963)
+++ trunk/matplotlib/doc/api/api_changes.rst    2009-11-13 19:22:52 UTC (rev 
7964)
@@ -10,7 +10,8 @@
 Changes beyond 0.99.x
 =====================
 
-* You can now print several figures to one pdf file. See the docstrings
+* You can now print several figures to one pdf file and modify the 
+  document information dictionary of a pdf file. See the docstrings
   of the class :class:`matplotlib.backends.backend_pdf.PdfPages` for
   more information.
 

Modified: trunk/matplotlib/examples/pylab_examples/multipage_pdf.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/multipage_pdf.py   2009-11-13 
00:44:11 UTC (rev 7963)
+++ trunk/matplotlib/examples/pylab_examples/multipage_pdf.py   2009-11-13 
19:22:52 UTC (rev 7964)
@@ -1,5 +1,6 @@
 # This is a demo of creating a pdf file with several pages.
 
+import datetime
 import numpy as np
 import matplotlib
 from matplotlib.backends.backend_pdf import PdfPages
@@ -29,5 +30,14 @@
 pdf.savefig(fig) # or you can pass a Figure object to pdf.savefig
 close()
 
+# We can also set the file's metadata via the PdfPages object:
+d = pdf.infodict()
+d['Title'] = 'Multipage PDF Example'
+d['Author'] = u'Jouni K. Sepp\xe4nen'
+d['Subject'] = 'How to create a multipage pdf file and set its metadata'
+d['Keywords'] = 'PdfPages multipage keywords author title subject'
+d['CreationDate'] = datetime.datetime(2009,11,13)
+d['ModDate'] = datetime.datetime.today()
+
 # Remember to close the object - otherwise the file will not be usable
 pdf.close()

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py     2009-11-13 
00:44:11 UTC (rev 7963)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py     2009-11-13 
19:22:52 UTC (rev 7964)
@@ -5,6 +5,7 @@
 """
 from __future__ import division
 
+import codecs
 import os
 import re
 import sys
@@ -149,6 +150,16 @@
     elif isinstance(obj, (int, long)):
         return "%d" % obj
 
+    # Unicode strings are encoded in UTF-16BE with byte-order mark.
+    elif isinstance(obj, unicode):
+        try:
+            # But maybe it's really ASCII?
+            s = obj.encode('ASCII')
+            return pdfRepr(s)
+        except UnicodeEncodeError:
+            s = codecs.BOM_UTF16_BE + obj.encode('UTF-16BE')
+            return pdfRepr(s)
+
     # Strings are written in parentheses, with backslashes and parens
     # escaped. Actually balanced parens are allowed, but it is
     # simpler to escape them all. TODO: cut long strings into lines;
@@ -374,7 +385,6 @@
         fh.write("%\254\334 \253\272\n")
 
         self.rootObject = self.reserveObject('root')
-        self.infoObject = self.reserveObject('info')
         self.pagesObject = self.reserveObject('pages')
         self.pageList = []
         self.fontObject = self.reserveObject('fonts')
@@ -388,14 +398,13 @@
                  'Pages': self.pagesObject }
         self.writeObject(self.rootObject, root)
 
-        info = { 'Creator': 'matplotlib ' + __version__ \
-                 + ', http://matplotlib.sf.net',
-                 'Producer': 'matplotlib pdf backend',
-                 'CreationDate': datetime.today() }
+        revision = '$Rev$'.strip('$').split(':')[1].strip()
+        self.infoDict = {
+            'Creator': 'matplotlib %s, http://matplotlib.sf.net' % __version__,
+            'Producer': 'matplotlib pdf backend r%s' % revision,
+            'CreationDate': datetime.today()
+            }
 
-        # Possible TODO: Title, Author, Subject, Keywords
-        self.writeObject(self.infoObject, info)
-
         self.fontNames = {}     # maps filenames to internal font names
         self.nextFont = 1       # next free internal font name
         self.dviFontInfo = {}   # information on dvi fonts
@@ -471,6 +480,7 @@
                          { 'Type': Name('Pages'),
                            'Kids': self.pageList,
                            'Count': len(self.pageList) })
+        self.writeInfoDict()
 
         # Finalize the file
         self.writeXref()
@@ -1280,6 +1290,31 @@
         if borken:
             raise AssertionError, 'Indirect object does not exist'
 
+    def writeInfoDict(self):
+        """Write out the info dictionary, checking it for good form"""
+
+        is_date = lambda x: isinstance(x, datetime)
+        check_trapped = lambda x: isinstance(x, Name) and x.name in \
+                                         ('True', 'False', 'Unknown')
+        keywords = {'Title': is_string_like,
+                    'Author': is_string_like,
+                    'Subject': is_string_like,
+                    'Keywords': is_string_like,
+                    'Creator': is_string_like,
+                    'Producer': is_string_like,
+                    'CreationDate': is_date,
+                    'ModDate': is_date,
+                    'Trapped': check_trapped}
+        for k in self.infoDict.keys():
+            if k not in keywords:
+                warnings.warn('Unknown infodict keyword: %s' % k)
+            else:
+                if not keywords[k](self.infoDict[k]):
+                    warnings.warn('Bad value for infodict keyword %s' % k)
+
+        self.infoObject = self.reserveObject('info')
+        self.writeObject(self.infoObject, self.infoDict)
+
     def writeTrailer(self):
         """Write out the PDF trailer."""
 
@@ -2052,6 +2087,14 @@
         self._file.close()
         self._file = None
 
+    def infodict(self):
+        """
+        Return a modifiable information dictionary object
+        (see PDF reference section 10.2.1 'Document Information
+        Dictionary').
+        """
+        return self._file.infoDict
+
     def savefig(self, figure=None, **kwargs):
         """
         Save the Figure instance *figure* to this file as a new page.


Property changes on: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
___________________________________________________________________
Added: svn:keywords
   + Rev


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Matplotlib-checkins mailing list
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to