mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
PDF Output: Fix margin specifications not being applied
This commit is contained in:
parent
fc15737d4f
commit
a4e1bd8ab3
@ -48,7 +48,7 @@ class Push(Command):
|
|||||||
threads = []
|
threads = []
|
||||||
for host in (
|
for host in (
|
||||||
r'Owner@winxp:/cygdrive/c/Documents\ and\ Settings/Owner/calibre',
|
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',
|
r'kovid@win7:/cygdrive/c/Users/kovid/calibre',
|
||||||
):
|
):
|
||||||
rcmd = BASE_RSYNC + EXCLUDES + ['.', host]
|
rcmd = BASE_RSYNC + EXCLUDES + ['.', host]
|
||||||
|
11
src/calibre/ebooks/oeb/display/__init__.py
Normal file
11
src/calibre/ebooks/oeb/display/__init__.py
Normal file
@ -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 <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
|
|
59
src/calibre/ebooks/oeb/display/webview.py
Normal file
59
src/calibre/ebooks/oeb/display/webview.py
Normal file
@ -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 <kovid@kovidgoyal.net>'
|
||||||
|
__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'<!\s*ENTITY\s+([^>]+)>', 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></%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)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,10 +18,11 @@ from calibre.ebooks.pdf.pageoptions import unit, paper_size, \
|
|||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
from calibre import __appname__, __version__, fit_image
|
from calibre import __appname__, __version__, fit_image
|
||||||
|
from calibre.ebooks.oeb.display.webview import load_html
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
from PyQt4.Qt import QUrl, QEventLoop, QObject, \
|
from PyQt4.Qt import (QEventLoop, QObject,
|
||||||
QPrinter, QMetaObject, QSizeF, Qt, QPainter, QPixmap
|
QPrinter, QMetaObject, QSizeF, Qt, QPainter, QPixmap)
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
from pyPdf import PdfFileWriter, PdfFileReader
|
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)
|
opts.margin_right, opts.margin_bottom, QPrinter.Point)
|
||||||
printer.setOrientation(orientation(opts.orientation))
|
printer.setOrientation(orientation(opts.orientation))
|
||||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||||
printer.setFullPage(True)
|
printer.setFullPage(for_comic)
|
||||||
return printer
|
return printer
|
||||||
|
|
||||||
def get_printer_page_size(opts, for_comic=False):
|
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.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1)))
|
||||||
|
|
||||||
self.logger.debug('Processing %s...' % item)
|
self.logger.debug('Processing %s...' % item)
|
||||||
|
load_html(item, self.view)
|
||||||
self.view.load(QUrl.fromLocalFile(item))
|
|
||||||
|
|
||||||
def _render_html(self, ok):
|
def _render_html(self, ok):
|
||||||
if ok:
|
if ok:
|
||||||
@ -171,6 +171,10 @@ class PDFWriter(QObject): # {{{
|
|||||||
# previously set on the printer.
|
# previously set on the printer.
|
||||||
if isosx:
|
if isosx:
|
||||||
printer.setOutputFormat(QPrinter.NativeFormat)
|
printer.setOutputFormat(QPrinter.NativeFormat)
|
||||||
|
self.view.page().mainFrame().evaluateJavaScript('''
|
||||||
|
document.body.style.backgroundColor = "white";
|
||||||
|
|
||||||
|
''')
|
||||||
self.view.print_(printer)
|
self.view.print_(printer)
|
||||||
printer.abort()
|
printer.abort()
|
||||||
else:
|
else:
|
||||||
|
@ -4,14 +4,14 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
# Imports {{{
|
# Imports {{{
|
||||||
import os, math, re, glob, sys, zipfile
|
import os, math, glob, sys, zipfile
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import (QSize, QSizePolicy, QUrl, SIGNAL, Qt,
|
from PyQt4.Qt import (QSize, QSizePolicy, QUrl, SIGNAL, Qt,
|
||||||
QPainter, QPalette, QBrush, QFontDatabase, QDialog,
|
QPainter, QPalette, QBrush, QFontDatabase, QDialog,
|
||||||
QColor, QPoint, QImage, QRegion, QVariant, QIcon,
|
QColor, QPoint, QImage, QRegion, QVariant, QIcon,
|
||||||
QFont, pyqtSignature, QAction, QByteArray, QMenu,
|
QFont, pyqtSignature, QAction, QMenu,
|
||||||
pyqtSignal, QSwipeGesture, QApplication)
|
pyqtSignal, QSwipeGesture, QApplication)
|
||||||
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
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.viewer.flip import SlideFlip
|
||||||
from calibre.gui2.shortcuts import Shortcuts, ShortcutConfig
|
from calibre.gui2.shortcuts import Shortcuts, ShortcutConfig
|
||||||
from calibre.constants import iswindows
|
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.keys import SHORTCUTS
|
||||||
from calibre.gui2.viewer.javascript import JavaScriptLoader
|
from calibre.gui2.viewer.javascript import JavaScriptLoader
|
||||||
from calibre.gui2.viewer.position import PagePosition
|
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'<!\s*ENTITY\s+([^>]+)>', 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): # {{{
|
class DocumentView(QWebView): # {{{
|
||||||
|
|
||||||
magnification_changed = pyqtSignal(object)
|
magnification_changed = pyqtSignal(object)
|
||||||
@ -497,8 +485,6 @@ class DocumentView(QWebView): # {{{
|
|||||||
self.is_auto_repeat_event = False
|
self.is_auto_repeat_event = False
|
||||||
self.debug_javascript = debug_javascript
|
self.debug_javascript = debug_javascript
|
||||||
self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer')
|
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.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||||
self._size_hint = QSize(510, 680)
|
self._size_hint = QSize(510, 680)
|
||||||
self.initial_pos = 0.0
|
self.initial_pos = 0.0
|
||||||
@ -689,31 +675,16 @@ class DocumentView(QWebView): # {{{
|
|||||||
def path(self):
|
def path(self):
|
||||||
return os.path.abspath(unicode(self.url().toLocalFile()))
|
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></%s>'%(match.group(1), match.group(2), match.group(1))
|
|
||||||
|
|
||||||
def load_path(self, path, pos=0.0):
|
def load_path(self, path, pos=0.0):
|
||||||
self.initial_pos = pos
|
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:
|
def callback(lu):
|
||||||
html = self.self_closing_pat.sub(self.self_closing_sub, html)
|
self.loading_url = lu
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.load_started()
|
self.manager.load_started()
|
||||||
self.loading_url = QUrl.fromLocalFile(path)
|
|
||||||
html = re.sub(ur'<\s*title\s*/\s*>', u'', html, flags=re.IGNORECASE)
|
load_html(path, self, codec=path.encoding, mime_type=getattr(path,
|
||||||
if has_svg:
|
'mime_type', None), pre_load_callback=callback)
|
||||||
self.setContent(QByteArray(html.encode(path.encoding)), mt, QUrl.fromLocalFile(path))
|
|
||||||
else:
|
|
||||||
self.setHtml(html, self.loading_url)
|
|
||||||
self.turn_off_internal_scrollbars()
|
self.turn_off_internal_scrollbars()
|
||||||
|
|
||||||
def initialize_scrollbar(self):
|
def initialize_scrollbar(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user