From a4e1bd8ab33dfa7247ba936b1d774218bf1f1480 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 27 Mar 2012 09:46:29 +0530 Subject: [PATCH] PDF Output: Fix margin specifications not being applied --- setup/installer/__init__.py | 2 +- src/calibre/ebooks/oeb/display/__init__.py | 11 ++++ src/calibre/ebooks/oeb/display/webview.py | 59 ++++++++++++++++++++++ src/calibre/ebooks/pdf/writer.py | 14 +++-- src/calibre/gui2/viewer/documentview.py | 51 ++++--------------- 5 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 src/calibre/ebooks/oeb/display/__init__.py create mode 100644 src/calibre/ebooks/oeb/display/webview.py diff --git a/setup/installer/__init__.py b/setup/installer/__init__.py index d0a6cd6fa3..8374f93e38 100644 --- a/setup/installer/__init__.py +++ b/setup/installer/__init__.py @@ -48,7 +48,7 @@ class Push(Command): threads = [] for host in ( r'Owner@winxp:/cygdrive/c/Documents\ and\ Settings/Owner/calibre', - 'kovid@leopard_test:calibre', + 'kovid@ox:calibre', r'kovid@win7:/cygdrive/c/Users/kovid/calibre', ): rcmd = BASE_RSYNC + EXCLUDES + ['.', host] diff --git a/src/calibre/ebooks/oeb/display/__init__.py b/src/calibre/ebooks/oeb/display/__init__.py new file mode 100644 index 0000000000..dd9615356c --- /dev/null +++ b/src/calibre/ebooks/oeb/display/__init__.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + + diff --git a/src/calibre/ebooks/oeb/display/webview.py b/src/calibre/ebooks/oeb/display/webview.py new file mode 100644 index 0000000000..efcfe0346c --- /dev/null +++ b/src/calibre/ebooks/oeb/display/webview.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import re + +from calibre import guess_type + +class EntityDeclarationProcessor(object): # {{{ + + def __init__(self, html): + self.declared_entities = {} + for match in re.finditer(r']+)>', html): + tokens = match.group(1).split() + if len(tokens) > 1: + self.declared_entities[tokens[0].strip()] = tokens[1].strip().replace('"', '') + self.processed_html = html + for key, val in self.declared_entities.iteritems(): + self.processed_html = self.processed_html.replace('&%s;'%key, val) +# }}} + +def self_closing_sub(match): + tag = match.group(1) + if tag.lower().strip() == 'br': + return match.group() + return '<%s %s>'%(match.group(1), match.group(2), match.group(1)) + +def load_html(path, view, codec='utf-8', mime_type=None, + pre_load_callback=lambda x:None): + from PyQt4.Qt import QUrl, QByteArray + if mime_type is None: + mime_type = guess_type(path)[0] + with open(path, 'rb') as f: + html = f.read().decode(codec, 'replace') + + html = EntityDeclarationProcessor(html).processed_html + has_svg = re.search(r'<[:a-zA-Z]*svg', html) is not None + if 'xhtml' in mime_type: + self_closing_pat = re.compile(r'<([a-z1-6]+)\s+([^>]+)/>', + re.IGNORECASE) + html = self_closing_pat.sub(self_closing_sub, html) + + html = re.sub(ur'<\s*title\s*/\s*>', u'', html, flags=re.IGNORECASE) + loading_url = QUrl.fromLocalFile(path) + pre_load_callback(loading_url) + + if has_svg: + view.setContent(QByteArray(html.encode(codec)), mime_type, + loading_url) + else: + view.setHtml(html, loading_url) + + + diff --git a/src/calibre/ebooks/pdf/writer.py b/src/calibre/ebooks/pdf/writer.py index 2c2e6a2f0e..fa2f5ebcfa 100644 --- a/src/calibre/ebooks/pdf/writer.py +++ b/src/calibre/ebooks/pdf/writer.py @@ -18,10 +18,11 @@ from calibre.ebooks.pdf.pageoptions import unit, paper_size, \ from calibre.ebooks.metadata import authors_to_string from calibre.ptempfile import PersistentTemporaryFile from calibre import __appname__, __version__, fit_image +from calibre.ebooks.oeb.display.webview import load_html from PyQt4 import QtCore -from PyQt4.Qt import QUrl, QEventLoop, QObject, \ - QPrinter, QMetaObject, QSizeF, Qt, QPainter, QPixmap +from PyQt4.Qt import (QEventLoop, QObject, + QPrinter, QMetaObject, QSizeF, Qt, QPainter, QPixmap) from PyQt4.QtWebKit import QWebView from pyPdf import PdfFileWriter, PdfFileReader @@ -70,7 +71,7 @@ def get_pdf_printer(opts, for_comic=False): opts.margin_right, opts.margin_bottom, QPrinter.Point) printer.setOrientation(orientation(opts.orientation)) printer.setOutputFormat(QPrinter.PdfFormat) - printer.setFullPage(True) + printer.setFullPage(for_comic) return printer def get_printer_page_size(opts, for_comic=False): @@ -156,8 +157,7 @@ class PDFWriter(QObject): # {{{ self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1))) self.logger.debug('Processing %s...' % item) - - self.view.load(QUrl.fromLocalFile(item)) + load_html(item, self.view) def _render_html(self, ok): if ok: @@ -171,6 +171,10 @@ class PDFWriter(QObject): # {{{ # previously set on the printer. if isosx: printer.setOutputFormat(QPrinter.NativeFormat) + self.view.page().mainFrame().evaluateJavaScript(''' + document.body.style.backgroundColor = "white"; + + ''') self.view.print_(printer) printer.abort() else: diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index b03de237c1..4992510dc4 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -4,14 +4,14 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' # Imports {{{ -import os, math, re, glob, sys, zipfile +import os, math, glob, sys, zipfile from base64 import b64encode from functools import partial from PyQt4.Qt import (QSize, QSizePolicy, QUrl, SIGNAL, Qt, QPainter, QPalette, QBrush, QFontDatabase, QDialog, QColor, QPoint, QImage, QRegion, QVariant, QIcon, - QFont, pyqtSignature, QAction, QByteArray, QMenu, + QFont, pyqtSignature, QAction, QMenu, pyqtSignal, QSwipeGesture, QApplication) from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings @@ -21,10 +21,11 @@ from calibre.gui2.viewer.config_ui import Ui_Dialog from calibre.gui2.viewer.flip import SlideFlip from calibre.gui2.shortcuts import Shortcuts, ShortcutConfig from calibre.constants import iswindows -from calibre import prints, guess_type +from calibre import prints from calibre.gui2.viewer.keys import SHORTCUTS from calibre.gui2.viewer.javascript import JavaScriptLoader from calibre.gui2.viewer.position import PagePosition +from calibre.ebooks.oeb.display.webview import load_html # }}} @@ -474,19 +475,6 @@ class Document(QWebPage): # {{{ # }}} -class EntityDeclarationProcessor(object): # {{{ - - def __init__(self, html): - self.declared_entities = {} - for match in re.finditer(r']+)>', html): - tokens = match.group(1).split() - if len(tokens) > 1: - self.declared_entities[tokens[0].strip()] = tokens[1].strip().replace('"', '') - self.processed_html = html - for key, val in self.declared_entities.iteritems(): - self.processed_html = self.processed_html.replace('&%s;'%key, val) -# }}} - class DocumentView(QWebView): # {{{ magnification_changed = pyqtSignal(object) @@ -497,8 +485,6 @@ class DocumentView(QWebView): # {{{ self.is_auto_repeat_event = False self.debug_javascript = debug_javascript self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer') - self.self_closing_pat = re.compile(r'<([a-z1-6]+)\s+([^>]+)/>', - re.IGNORECASE) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self._size_hint = QSize(510, 680) self.initial_pos = 0.0 @@ -689,31 +675,16 @@ class DocumentView(QWebView): # {{{ def path(self): return os.path.abspath(unicode(self.url().toLocalFile())) - def self_closing_sub(self, match): - tag = match.group(1) - if tag.lower().strip() == 'br': - return match.group() - return '<%s %s>'%(match.group(1), match.group(2), match.group(1)) - def load_path(self, path, pos=0.0): self.initial_pos = pos - mt = getattr(path, 'mime_type', None) - if mt is None: - mt = guess_type(path)[0] - html = open(path, 'rb').read().decode(path.encoding, 'replace') - html = EntityDeclarationProcessor(html).processed_html - has_svg = re.search(r'<[:a-zA-Z]*svg', html) is not None - if 'xhtml' in mt: - html = self.self_closing_pat.sub(self.self_closing_sub, html) - if self.manager is not None: - self.manager.load_started() - self.loading_url = QUrl.fromLocalFile(path) - html = re.sub(ur'<\s*title\s*/\s*>', u'', html, flags=re.IGNORECASE) - if has_svg: - self.setContent(QByteArray(html.encode(path.encoding)), mt, QUrl.fromLocalFile(path)) - else: - self.setHtml(html, self.loading_url) + def callback(lu): + self.loading_url = lu + if self.manager is not None: + self.manager.load_started() + + load_html(path, self, codec=path.encoding, mime_type=getattr(path, + 'mime_type', None), pre_load_callback=callback) self.turn_off_internal_scrollbars() def initialize_scrollbar(self):