Move PDF output to use new conversion framework

This commit is contained in:
John Schember 2009-03-31 20:23:49 -04:00
parent 90362ab56a
commit 79e509eeb4
5 changed files with 79 additions and 155 deletions

View File

@ -267,9 +267,10 @@ from calibre.ebooks.epub.input import EPUBInput
from calibre.ebooks.mobi.input import MOBIInput
from calibre.ebooks.oeb.output import OEBOutput
from calibre.ebooks.txt.output import TXTOutput
from calibre.ebooks.pdf.output import PDFOutput
from calibre.customize.profiles import input_profiles, output_profiles
plugins = [HTML2ZIP, EPUBInput, MOBIInput, OEBOutput, TXTOutput]
plugins = [HTML2ZIP, EPUBInput, MOBIInput, OEBOutput, TXTOutput, PDFOutput]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \

View File

@ -1,69 +0,0 @@
'''
Convert any ebook format to PDF.
'''
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net ' \
'and Marshall T. Vandegrift <llasram@gmail.com>' \
'and John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import sys, os, glob, logging
from calibre.ebooks.epub.from_any import any2epub, formats, USAGE
from calibre.ebooks.epub import config as common_config
from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.pdf.writer import oeb2pdf, config as pdf_config
def config(defaults=None):
c = common_config(defaults=defaults, name='pdf')
c.remove_opt('profile')
pdfc = pdf_config(defaults=defaults)
c.update(pdfc)
return c
def option_parser(usage=USAGE):
usage = usage % ('PDF', formats())
parser = config().option_parser(usage=usage)
return parser
def any2pdf(opts, path, notification=None):
ext = os.path.splitext(path)[1]
if not ext:
raise ValueError('Unknown file type: '+path)
ext = ext.lower()[1:]
if opts.output is None:
opts.output = os.path.splitext(os.path.basename(path))[0]+'.pdf'
opts.output = os.path.abspath(opts.output)
orig_output = opts.output
with TemporaryDirectory('_any2pdf') as tdir:
oebdir = os.path.join(tdir, 'oeb')
os.mkdir(oebdir)
opts.output = os.path.join(tdir, 'dummy.epub')
opts.profile = 'None'
opts.dont_split_on_page_breaks = True
orig_bfs = opts.base_font_size2
opts.base_font_size2 = 0
any2epub(opts, path, create_epub=False, oeb_cover=True, extract_to=oebdir)
opts.base_font_size2 = orig_bfs
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
opts.output = orig_output
logging.getLogger('html2epub').info(_('Creating PDF file from EPUB...'))
oeb2pdf(opts, opf)
def main(args=sys.argv):
parser = option_parser()
opts, args = parser.parse_args(args)
if len(args) < 2:
parser.print_help()
print 'No input file specified.'
return 1
any2pdf(opts, args[1])
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Convert OEB ebook format to PDF.
'''
#unit, papersize, orientation, custom_size, profile
import os
from calibre.customize.conversion import OutputFormatPlugin, \
OptionRecommendation
from calibre.ebooks.pdf.writer import PDFWriter, PDFMargins
class PDFOutput(OutputFormatPlugin):
name = 'PDF Output'
author = 'John Schember'
file_type = 'pdf'
options = set([
OptionRecommendation(name='margin_top', recommended_value='1',
level=OptionRecommendation.LOW, long_switch='margin_top',
help=_('The top margin around the document.')),
OptionRecommendation(name='margin_bottom', recommended_value='1',
level=OptionRecommendation.LOW, long_switch='margin_bottom',
help=_('The bottom margin around the document.')),
OptionRecommendation(name='margin_left', recommended_value='1',
level=OptionRecommendation.LOW, long_switch='margin_left',
help=_('The left margin around the document.')),
OptionRecommendation(name='margin_right', recommended_value='1',
level=OptionRecommendation.LOW, long_switch='margin_right',
help=_('The right margin around the document.')),
])
def convert(self, oeb_book, output_path, input_plugin, opts, log):
margins = PDFMargins()
margins.top = opts.margin_top
margins.bottom = opts.margin_bottom
margins.left = opts.margin_left
margins.right = opts.margin_right
writer = PDFWriter(log, margins)
close = False
if not hasattr(output_path, 'write'):
close = True
if not os.path.exists(os.path.dirname(output_path)) and os.path.dirname(output_path) != '':
os.makedirs(os.path.dirname(output_path))
out_stream = open(output_path, 'wb')
else:
out_stream = output_path
out_stream.seek(0)
out_stream.truncate()
writer.dump(oeb_book.spine, out_stream)
if close:
out_stream.close()

View File

@ -1,20 +1,17 @@
'''
Write content to PDF.
'''
# -*- coding: utf-8 -*-
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import os, logging, shutil, sys
'''
Write content to PDF.
'''
import os, shutil, sys
from calibre import LoggingInterface
from calibre.ebooks.epub.iterator import SpineItem
from calibre.ebooks.metadata.opf2 import OPF
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.customize.ui import run_plugins_on_postprocess
from calibre.utils.config import Config, StringConfig
from PyQt4 import QtCore
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, QApplication, QPrinter, \
QMetaObject, Qt
@ -29,13 +26,14 @@ class PDFMargins:
self.left = margin
self.right = margin
class PDFWriter(QObject):
def __init__(self, margins=PDFMargins()):
def __init__(self, log, margins=PDFMargins()):
if QApplication.instance() is None:
QApplication([])
QObject.__init__(self)
self.logger = logging.getLogger('oeb2pdf')
self.logger = log
self.loop = QEventLoop()
self.view = QWebView()
@ -45,13 +43,12 @@ class PDFWriter(QObject):
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
self.margins = margins
def dump(self, oebpath, path):
def dump(self, spine, out_stream):
self._delete_tmpdir()
opf = OPF(oebpath, os.path.dirname(oebpath))
self.render_queue = [SpineItem(i.path) for i in opf.spine]
self.render_queue = spine[:]
self.combine_queue = []
self.path = path
self.out_stream = out_stream
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
self.loop.exec_()
@ -98,75 +95,7 @@ class PDFWriter(QObject):
inputPDF = PdfFileReader(file(item, 'rb'))
for page in inputPDF.pages:
outPDF.addPage(page)
outputStream = file(self.path, 'wb')
outPDF.write(outputStream)
outputStream.close()
outPDF.write(self.out_stream)
finally:
self._delete_tmpdir()
self.loop.exit(0)
def config(defaults=None):
desc = _('Options to control the conversion to PDF')
if defaults is None:
c = Config('pdf', desc)
else:
c = StringConfig(defaults, desc)
pdf = c.add_group('PDF', _('PDF options.'))
pdf('margin_top', ['--margin_top'], default=1,
help=_('The top margin around the document in inches.'))
pdf('margin_bottom', ['--margin_bottom'], default=1,
help=_('The bottom margin around the document in inches.'))
pdf('margin_left', ['--margin_left'], default=1,
help=_('The left margin around the document in inches.'))
pdf('margin_right', ['--margin_right'], default=1,
help=_('The right margin around the document in inches.'))
return c
def option_parser():
c = config()
parser = c.option_parser(usage='%prog '+_('[options]')+' file.opf')
parser.add_option(
'-o', '--output', default=None,
help=_('Output file. Default is derived from input filename.'))
parser.add_option(
'-v', '--verbose', default=0, action='count',
help=_('Useful for debugging.'))
return parser
def oeb2pdf(opts, inpath):
logger = LoggingInterface(logging.getLogger('oeb2pdf'))
logger.setup_cli_handler(opts.verbose)
outpath = opts.output
if outpath is None:
outpath = os.path.basename(inpath)
outpath = os.path.splitext(outpath)[0] + '.pdf'
margins = PDFMargins()
margins.top = opts.margin_top
margins.bottom = opts.margin_bottom
margins.left = opts.margin_left
margins.right = opts.margin_right
writer = PDFWriter(margins)
writer.dump(inpath, outpath)
run_plugins_on_postprocess(outpath, 'pdf')
logger.log_info(_('Output written to ') + outpath)
def main(argv=sys.argv):
parser = option_parser()
opts, args = parser.parse_args(argv[1:])
if len(args) != 1:
parser.print_help()
return 1
inpath = args[0]
retval = oeb2pdf(opts, inpath)
return retval
if __name__ == '__main__':
sys.exit(main())

View File

@ -56,6 +56,7 @@ class TXTOutput(OutputFormatPlugin):
out_stream = output_path
out_stream.seek(0)
out_stream.truncate()
out_stream.write(txt)
if close: