This commit is contained in:
Kovid Goyal 2009-04-26 23:00:47 -07:00
parent 3938bbdaeb
commit 0749f44979
4 changed files with 42 additions and 26 deletions

View File

@ -133,6 +133,14 @@ class InputFormatPlugin(Plugin):
#: (option_name, recommended_value, recommendation_level) #: (option_name, recommended_value, recommendation_level)
recommendations = set([]) recommendations = set([])
def get_images(self):
'''
Return a list of absolute paths to the images, if this input plugin
represents an image collection. The list of images is in the same order
as the spine and the TOC.
'''
raise NotImplementedError()
def convert(self, stream, options, file_ext, log, accelerators): def convert(self, stream, options, file_ext, log, accelerators):
''' '''
This method must be implemented in sub-classes. It must return This method must be implemented in sub-classes. It must return

View File

@ -357,6 +357,9 @@ class ComicInput(InputFormatPlugin):
thumbnail = None thumbnail = None
return new_pages return new_pages
def get_images(self):
return self._images
def convert(self, stream, opts, file_ext, log, accelerators, def convert(self, stream, opts, file_ext, log, accelerators,
progress=lambda p, m : m): progress=lambda p, m : m):
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
@ -401,6 +404,9 @@ class ComicInput(InputFormatPlugin):
spine = [] spine = []
for comic in comics: for comic in comics:
spine.extend(map(href, comic[2])) spine.extend(map(href, comic[2]))
self._images = []
for comic in comics:
self._images.extend(comic[1])
opf.create_spine(spine) opf.create_spine(spine)
toc = TOC() toc = TOC()
if len(comics) == 1: if len(comics) == 1:

View File

@ -40,7 +40,7 @@ class PDFOutput(OutputFormatPlugin):
OptionRecommendation(name='margin_right', recommended_value='1', OptionRecommendation(name='margin_right', recommended_value='1',
level=OptionRecommendation.LOW, level=OptionRecommendation.LOW,
help=_('The right margin around the document.')), help=_('The right margin around the document.')),
OptionRecommendation(name='unit', recommended_value='inch', OptionRecommendation(name='unit', recommended_value='inch',
level=OptionRecommendation.LOW, short_switch='u', choices=UNITS.keys(), level=OptionRecommendation.LOW, short_switch='u', choices=UNITS.keys(),
help=_('The unit of measure. Default is inch. Choices ' help=_('The unit of measure. Default is inch. Choices '
@ -58,15 +58,18 @@ class PDFOutput(OutputFormatPlugin):
help=_('The orientation of the page. Default is portrait. Choices ' help=_('The orientation of the page. Default is portrait. Choices '
'are %s' % ORIENTATIONS.keys())), 'are %s' % ORIENTATIONS.keys())),
]) ])
def convert(self, oeb_book, output_path, input_plugin, opts, log): def convert(self, oeb_book, output_path, input_plugin, opts, log):
self.opts, self.log = opts, log
if input_plugin.is_image_collection:
self.convert_images(input_plugin.get_images())
with TemporaryDirectory('_pdf_out') as oebdir: with TemporaryDirectory('_pdf_out') as oebdir:
OEBOutput(None).convert(oeb_book, oebdir, input_plugin, opts, log) OEBOutput(None).convert(oeb_book, oebdir, input_plugin, opts, log)
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0] opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
writer = PDFWriter(log, opts) writer = PDFWriter(log, opts)
close = False close = False
if not hasattr(output_path, 'write'): if not hasattr(output_path, 'write'):
close = True close = True
@ -75,10 +78,10 @@ class PDFOutput(OutputFormatPlugin):
out_stream = open(output_path, 'wb') out_stream = open(output_path, 'wb')
else: else:
out_stream = output_path out_stream = output_path
out_stream.seek(0) out_stream.seek(0)
out_stream.truncate() out_stream.truncate()
writer.dump(opf, out_stream, PDFMetadata(oeb_book.metadata)) writer.dump(opf, out_stream, PDFMetadata(oeb_book.metadata))
if close: if close:
out_stream.close() out_stream.close()

View File

@ -9,12 +9,11 @@ __docformat__ = 'restructuredtext en'
Write content to PDF. Write content to PDF.
''' '''
import os, shutil, sys import os, shutil
from calibre.ptempfile import PersistentTemporaryDirectory from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.customize.profiles import OutputProfile
from calibre.ebooks.pdf.pageoptions import unit, paper_size, \ from calibre.ebooks.pdf.pageoptions import unit, paper_size, \
orientation, size orientation, size
from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata import authors_to_string
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
@ -24,12 +23,12 @@ from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, \
from PyQt4.QtWebKit import QWebView from PyQt4.QtWebKit import QWebView
from pyPdf import PdfFileWriter, PdfFileReader from pyPdf import PdfFileWriter, PdfFileReader
class PDFMetadata(object): class PDFMetadata(object):
def __init__(self, oeb_metadata=None): def __init__(self, oeb_metadata=None):
self.title = _('Unknown') self.title = _('Unknown')
self.author = _('Unknown') self.author = _('Unknown')
if oeb_metadata != None: if oeb_metadata != None:
if len(oeb_metadata.title) >= 1: if len(oeb_metadata.title) >= 1:
self.title = oeb_metadata.title[0].value self.title = oeb_metadata.title[0].value
@ -42,16 +41,16 @@ class PDFWriter(QObject):
if QApplication.instance() is None: if QApplication.instance() is None:
QApplication([]) QApplication([])
QObject.__init__(self) QObject.__init__(self)
self.logger = log self.logger = log
self.loop = QEventLoop() self.loop = QEventLoop()
self.view = QWebView() self.view = QWebView()
self.connect(self.view, SIGNAL('loadFinished(bool)'), self._render_html) self.connect(self.view, SIGNAL('loadFinished(bool)'), self._render_html)
self.render_queue = [] self.render_queue = []
self.combine_queue = [] self.combine_queue = []
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts') self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
self.custom_size = None self.custom_size = None
if opts.custom_size != None: if opts.custom_size != None:
width, sep, height = opts.custom_size.partition('x') width, sep, height = opts.custom_size.partition('x')
@ -62,44 +61,44 @@ class PDFWriter(QObject):
self.custom_size = (width, height) self.custom_size = (width, height)
except: except:
self.custom_size = None self.custom_size = None
self.opts = opts self.opts = opts
def dump(self, opfpath, out_stream, pdf_metadata): def dump(self, opfpath, out_stream, pdf_metadata):
self.metadata = pdf_metadata self.metadata = pdf_metadata
self._delete_tmpdir() self._delete_tmpdir()
opf = OPF(opfpath, os.path.dirname(opfpath)) opf = OPF(opfpath, os.path.dirname(opfpath))
self.render_queue = [i.path for i in opf.spine] self.render_queue = [i.path for i in opf.spine]
self.combine_queue = [] self.combine_queue = []
self.out_stream = out_stream self.out_stream = out_stream
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection) QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
self.loop.exec_() self.loop.exec_()
@QtCore.pyqtSignature('_render_book()') @QtCore.pyqtSignature('_render_book()')
def _render_book(self): def _render_book(self):
if len(self.render_queue) == 0: if len(self.render_queue) == 0:
self._write() self._write()
else: else:
self._render_next() self._render_next()
def _render_next(self): def _render_next(self):
item = str(self.render_queue.pop(0)) item = str(self.render_queue.pop(0))
self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1))) self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1)))
self.logger.info('Processing %s...' % item) self.logger.info('Processing %s...' % item)
self.view.load(QUrl(item)) self.view.load(QUrl(item))
def _render_html(self, ok): def _render_html(self, ok):
if ok: if ok:
item_path = os.path.join(self.tmp_path, '%i.pdf' % len(self.combine_queue)) item_path = os.path.join(self.tmp_path, '%i.pdf' % len(self.combine_queue))
self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue))) self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue)))
printer = QPrinter(QPrinter.HighResolution) printer = QPrinter(QPrinter.HighResolution)
if self.opts.output_profile.short_name == 'default': if self.opts.output_profile.short_name == 'default':
if self.custom_size == None: if self.custom_size == None:
printer.setPaperSize(paper_size(self.opts.paper_size)) printer.setPaperSize(paper_size(self.opts.paper_size))
@ -107,7 +106,7 @@ class PDFWriter(QObject):
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit)) printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
else: else:
printer.setPaperSize(QSizeF(self.opts.output_profile.width / self.opts.output_profile.dpi, self.opts.output_profile.height / self.opts.output_profile.dpi), QPrinter.Inch) printer.setPaperSize(QSizeF(self.opts.output_profile.width / self.opts.output_profile.dpi, self.opts.output_profile.height / self.opts.output_profile.dpi), QPrinter.Inch)
printer.setPageMargins(size(self.opts.margin_left), size(self.opts.margin_top), size(self.opts.margin_right), size(self.opts.margin_bottom), unit(self.opts.unit)) printer.setPageMargins(size(self.opts.margin_left), size(self.opts.margin_top), size(self.opts.margin_right), size(self.opts.margin_bottom), unit(self.opts.unit))
printer.setOrientation(orientation(self.opts.orientation)) printer.setOrientation(orientation(self.opts.orientation))
printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFormat(QPrinter.PdfFormat)
@ -122,7 +121,7 @@ class PDFWriter(QObject):
def _write(self): def _write(self):
self.logger.info('Combining individual PDF parts...') self.logger.info('Combining individual PDF parts...')
try: try:
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author) outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
for item in self.combine_queue: for item in self.combine_queue: