PDF Output: Write XMP metadata when creating PDF files

This commit is contained in:
Kovid Goyal 2014-02-17 21:50:30 +05:30
parent 39287d31fe
commit 8b804f8811
3 changed files with 35 additions and 12 deletions

View File

@ -22,20 +22,21 @@ PAPER_SIZES = [u'a0', u'a1', u'a2', u'a3', u'a4', u'a5', u'a6', u'b0', u'b1',
u'b2', u'b3', u'b4', u'b5', u'b6', u'legal', u'letter']
class PDFMetadata(object): # {{{
def __init__(self, oeb_metadata=None):
def __init__(self, mi=None):
from calibre import force_unicode
from calibre.ebooks.metadata import authors_to_string
self.title = _(u'Unknown')
self.author = _(u'Unknown')
self.tags = u''
self.mi = mi
if oeb_metadata is not None:
if len(oeb_metadata.title) >= 1:
self.title = oeb_metadata.title[0].value
if len(oeb_metadata.creator) >= 1:
self.author = authors_to_string([x.value for x in oeb_metadata.creator])
if oeb_metadata.subject:
self.tags = u', '.join(map(unicode, oeb_metadata.subject))
if mi is not None:
if mi.title:
self.title = mi.title
if mi.authors:
self.author = authors_to_string(mi.authors)
if mi.tags:
self.tags = u', '.join(mi.tags)
self.title = force_unicode(self.title)
self.author = force_unicode(self.author)
@ -125,7 +126,15 @@ class PDFOutput(OutputFormatPlugin):
self.oeb = oeb_book
self.input_plugin, self.opts, self.log = input_plugin, opts, log
self.output_path = output_path
self.metadata = oeb_book.metadata
from calibre.ebooks.oeb.base import OPF, OPF2_NS
from lxml import etree
from io import BytesIO
package = etree.Element(OPF('package'),
attrib={'version': '2.0', 'unique-identifier': 'dummy'},
nsmap={None: OPF2_NS})
from calibre.ebooks.metadata.opf2 import OPF
self.oeb.metadata.to_opf2(package)
self.metadata = OPF(BytesIO(etree.tostring(package))).to_book_metadata()
self.cover_data = None
if input_plugin.is_image_collection:

View File

@ -209,7 +209,7 @@ class PDFWriter(QObject):
self.painter = QPainter(self.doc)
self.doc.set_metadata(title=pdf_metadata.title,
author=pdf_metadata.author,
tags=pdf_metadata.tags)
tags=pdf_metadata.tags, mi=pdf_metadata.mi)
self.doc_title = pdf_metadata.title
self.doc_author = pdf_metadata.author
self.painter.save()

View File

@ -20,7 +20,7 @@ from calibre.ebooks.pdf.render.fonts import FontManager
from calibre.ebooks.pdf.render.links import Links
from calibre.utils.date import utcnow
PDFVER = b'%PDF-1.3'
PDFVER = b'%PDF-1.4' # 1.4 is needed for XMP metadata
class IndirectObjects(object):
@ -239,6 +239,17 @@ class Image(Stream):
if self.soft_mask is not None:
d['SMask'] = self.soft_mask
class Metadata(Stream):
def __init__(self, mi):
Stream.__init__(self)
from calibre.ebooks.metadata.xmp import metadata_to_xmp_packet
self.write(metadata_to_xmp_packet(mi))
def add_extra_keys(self, d):
d['Type'] = Name('Metadata')
d['Subtype'] = Name('XML')
class PDFStream(object):
PATH_OPS = {
@ -292,13 +303,16 @@ class PDFStream(object):
def get_pageref(self, pagenum):
return self.page_tree.obj.get_ref(pagenum)
def set_metadata(self, title=None, author=None, tags=None):
def set_metadata(self, title=None, author=None, tags=None, mi=None):
if title:
self.info['Title'] = String(title)
if author:
self.info['Author'] = String(author)
if tags:
self.info['Keywords'] = String(tags)
if mi is not None:
self.metadata = self.objects.add(Metadata(mi))
self.catalog.obj['Metadata'] = self.metadata
def write_line(self, byts=b''):
byts = byts if isinstance(byts, bytes) else byts.encode('ascii')