diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip
index b1c550c8f0..c6744d5df7 100644
Binary files a/resources/compiled_coffeescript.zip and b/resources/compiled_coffeescript.zip differ
diff --git a/resources/viewer/blank.html b/resources/viewer/blank.html
new file mode 100644
index 0000000000..da7c5a637d
--- /dev/null
+++ b/resources/viewer/blank.html
@@ -0,0 +1,11 @@
+
+
+
+ blank
+
+
+
+
+
+
+
diff --git a/src/calibre/ebooks/oeb/display/paged.coffee b/src/calibre/ebooks/oeb/display/paged.coffee
new file mode 100644
index 0000000000..ef365541ff
--- /dev/null
+++ b/src/calibre/ebooks/oeb/display/paged.coffee
@@ -0,0 +1,203 @@
+#!/usr/bin/env coffee
+# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
+
+###
+ Copyright 2012, Kovid Goyal
+ Released under the GPLv3 License
+###
+
+log = (args...) -> # {{{
+ if args
+ msg = args.join(' ')
+ if window?.console?.log
+ window.console.log(msg)
+ else if process?.stdout?.write
+ process.stdout.write(msg + '\n')
+# }}}
+
+body_height = () ->
+ db = document.body
+ dde = document.documentElement
+ if db? and dde?
+ return Math.max(db.scrollHeight, dde.scrollHeight, db.offsetHeight,
+ dde.offsetHeight, db.clientHeight, dde.clientHeight)
+ return 0
+
+absleft = (elem) ->
+ r = elem.getBoundingClientRect()
+ return r.left + window.pageXOffset
+
+class PagedDisplay
+ ###
+ This class is a namespace to expose functions via the
+ window.paged_display object. The most important functions are:
+
+ layout(): causes the currently loaded document to be laid out in columns.
+ ###
+
+ constructor: () ->
+ this.set_geometry()
+ this.page_width = 0
+ this.screen_width = 0
+ this.in_paged_mode = false
+ this.current_margin_side = 0
+
+ set_geometry: (cols_per_screen=2, margin_top=20, margin_side=40, margin_bottom=20) ->
+ this.margin_top = margin_top
+ this.margin_side = margin_side
+ this.margin_bottom = margin_bottom
+ this.cols_per_screen = cols_per_screen
+
+ layout: () ->
+ ww = window.innerWidth
+ wh = window.innerHeight
+ body_height = wh - this.margin_bottom = this.margin_top
+ n = this.cols_per_screen
+
+ # Calculate the column width so that cols_per_screen columns fit in the
+ # window in such a way the right margin of the last column is <=
+ # side_margin (it may be less if the window width is not a
+ # multiple of n*(col_width+2*side_margin).
+
+ adjust = ww - Math.floor(ww/n)*n
+ # Ensure that the margins are large enough that the adjustment does not
+ # cause them to become negative semidefinite
+ sm = Math.max(2*adjust, this.margin_side)
+ # Minimum column width, for the cases when the window is too
+ # narrow
+ col_width = Math.max(100, ((ww - adjust)/n) - 2*sm)
+ this.page_width = col_width + 2*sm
+ this.screen_width = this.page_width * this.cols_per_screen
+
+ body_style = window.getComputedStyle(document.body)
+ fgcolor = body_style.getPropertyValue('color')
+ bs = document.body.style
+
+ bs.setProperty('-webkit-column-gap', (2*sm)+'px')
+ bs.setProperty('-webkit-column-width', col_width+'px')
+ bs.setProperty('-webkit-column-rule-color', fgcolor)
+ bs.setProperty('overflow', 'visible')
+ bs.setProperty('height', 'auto')
+ bs.setProperty('width', 'auto')
+ bs.setProperty('margin-top', this.margin_top+'px')
+ bs.setProperty('margin-bottom', this.margin_bottom+'px')
+ bs.setProperty('margin-left', sm+'px')
+ bs.setProperty('margin-right', sm+'px')
+ for edge in ['left', 'right', 'top', 'bottom']
+ bs.setProperty('padding-'+edge, '0px')
+ bs.setProperty('border-'+edge+'-width', '0px')
+ bs.setProperty('min-width', '0')
+ bs.setProperty('max-width', 'none')
+ bs.setProperty('min-height', '0')
+ bs.setProperty('max-height', 'none')
+
+ # Ensure that the top margin is correct, otherwise for some documents,
+ # webkit lays out the body with a lot of space on top
+ brect = document.body.getBoundingClientRect()
+ if brect.top > this.margin_top
+ bs.setProperty('margin-top', (this.margin_top - brect.top)+'px')
+ brect = document.body.getBoundingClientRect()
+ this.in_paged_mode = true
+ this.current_margin_side = sm
+ return sm
+
+ scroll_to_pos: (frac) ->
+ # Scroll to the position represented by frac (number between 0 and 1)
+ xpos = Math.floor(document.body.scrollWidth * frac)
+ this.scroll_to_xpos(xpos)
+
+ scroll_to_xpos: (xpos) ->
+ # Scroll so that the column containing xpos is the left most column in
+ # the viewport
+ pos = 0
+ until (pos <= xpos < pos + this.page_width)
+ pos += this.page_width
+ limit = document.body.scrollWidth - this.screen_width
+ pos = limit if pos > limit
+ window.scrollTo(pos, 0)
+
+ current_pos: (frac) ->
+ # The current scroll position as a fraction between 0 and 1
+ limit = document.body.scrollWidth - window.innerWidth
+ if limit <= 0
+ return 0.0
+ return window.pageXOffset / limit
+
+ current_column_location: () ->
+ # The location of the left edge of the left most column currently
+ # visible in the viewport
+ x = window.pageXOffset + Math.max(10, this.current_margin_side)
+ edge = Math.floor(x/this.page_width)
+ while edge < x
+ edge += this.page_width
+ return edge - this.page_width
+
+ next_screen_location: () ->
+ # The position to scroll to for the next screen (which could contain
+ # more than one pages). Returns -1 if no further scrolling is possible.
+ cc = this.current_column_location()
+ ans = cc + this.screen_width
+ limit = document.body.scrollWidth - window.innerWidth
+ if ans > limit
+ ans = if window.pageXOffset < limit then limit else -1
+ return ans
+
+ previous_screen_location: () ->
+ # The position to scroll to for the previous screen (which could contain
+ # more than one pages). Returns -1 if no further scrolling is possible.
+ cc = this.current_column_location()
+ ans = cc - this.screen_width
+ if ans < 0
+ # We ignore small scrolls (less than 15px) when going to previous
+ # screen
+ ans = if window.pageXOffset > 15 then 0 else -1
+ return ans
+
+ next_col_location: () ->
+ # The position to scroll to for the next column (same as
+ # next_screen_location() if columns per screen == 1). Returns -1 if no
+ # further scrolling is possible.
+ cc = this.current_column_location()
+ ans = cc + this.page_width
+ limit = document.body.scrollWidth - window.innerWidth
+ if ans > limit
+ ans = if window.pageXOffset < limit then limit else -1
+ return ans
+
+ previous_col_location: () ->
+ # The position to scroll to for the previous column (same as
+ # previous_screen_location() if columns per screen == 1). Returns -1 if
+ # no further scrolling is possible.
+ cc = this.current_column_location()
+ ans = cc - this.page_width
+ if ans < 0
+ ans = if window.pageXOffset > 0 then 0 else -1
+ return ans
+
+ jump_to_anchor: (name) ->
+ elem = document.getElementById(name)
+ if !elem
+ elems = document.getElementsByName(name)
+ if elems
+ elem = elems[0]
+ if !elem
+ return
+ elem.scrollIntoView()
+ if this.in_paged_mode
+ # Ensure we are scrolled to the column containing elem
+ this.scroll_to_xpos(absleft(elem)+10)
+
+if window?
+ window.paged_display = new PagedDisplay()
+
+# TODO:
+# jump_to_anchor() and handling of internal links in the same flow and
+# different flows
+# css pagebreak rules
+# CFI and bookmarks
+# Go to reference positions
+# Indexing
+# Resizing of images
+# Special handling for identifiable covers (colspan)?
+# Full screen mode
+# Resizing of viewport
diff --git a/src/calibre/ebooks/oeb/display/webview.py b/src/calibre/ebooks/oeb/display/webview.py
index efcfe0346c..8b89f54176 100644
--- a/src/calibre/ebooks/oeb/display/webview.py
+++ b/src/calibre/ebooks/oeb/display/webview.py
@@ -31,12 +31,15 @@ def self_closing_sub(match):
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):
+ pre_load_callback=lambda x:None, path_is_html=False):
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')
+ if path_is_html:
+ html = path
+ else:
+ 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
diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py
index 84204027c9..8d1016d1dc 100644
--- a/src/calibre/gui2/viewer/documentview.py
+++ b/src/calibre/gui2/viewer/documentview.py
@@ -22,7 +22,7 @@ from calibre.gui2.viewer.javascript import JavaScriptLoader
from calibre.gui2.viewer.position import PagePosition
from calibre.gui2.viewer.config import config, ConfigDialog
from calibre.ebooks.oeb.display.webview import load_html
-
+from calibre.utils.config import tweaks
# }}}
def load_builtin_fonts():
@@ -59,10 +59,12 @@ class Document(QWebPage): # {{{
def __init__(self, shortcuts, parent=None, debug_javascript=False):
QWebPage.__init__(self, parent)
self.setObjectName("py_bridge")
+ self.in_paged_mode = tweaks.get('viewer_test_paged_mode', False)
# Use this to pass arbitrary JSON encodable objects between python and
# javascript. In python get/set the value as: self.bridge_value. In
# javascript, get/set the value as: py_bridge.value
self.bridge_value = None
+ self.first_load = True
self.debug_javascript = debug_javascript
self.anchor_positions = {}
@@ -104,6 +106,13 @@ class Document(QWebPage): # {{{
self.mainFrame().javaScriptWindowObjectCleared.connect(
self.add_window_objects)
+ self.turn_off_internal_scrollbars()
+
+ def turn_off_internal_scrollbars(self):
+ mf = self.mainFrame()
+ mf.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
+ mf.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
+
def set_user_stylesheet(self):
raw = config().parse().user_css
raw = '::selection {background:#ffff00; color:#000;}\nbody {background-color: white;}\n'+raw
@@ -175,9 +184,12 @@ class Document(QWebPage): # {{{
'document.body.style.marginLeft').toString())
self.initial_right_margin = unicode(self.javascript(
'document.body.style.marginRight').toString())
+ if self.in_paged_mode:
+ self.switch_to_paged_mode()
if self.in_fullscreen_mode:
self.switch_to_fullscreen_mode()
self.read_anchor_positions(use_cache=False)
+ self.first_load = False
def read_anchor_positions(self, use_cache=True):
self.bridge_value = tuple(self.index_anchors)
@@ -190,6 +202,22 @@ class Document(QWebPage): # {{{
self.anchor_positions = {}
return self.anchor_positions
+ def switch_to_paged_mode(self, onresize=False):
+ side_margin = self.javascript('paged_display.layout()', typ=int)
+ # Setup the contents size to ensure that there is a right most margin.
+ # Without this webkit renders the final column with no margin, as the
+ # columns extend beyond the boundaries (and margin) of body
+ mf = self.mainFrame()
+ sz = mf.contentsSize()
+ if sz.width() > self.window_width:
+ sz.setWidth(sz.width()+side_margin)
+ self.setPreferredContentsSize(sz)
+
+ def after_resize(self):
+ if self.in_paged_mode:
+ self.setPreferredContentsSize(QSize())
+ self.switch_to_paged_mode(onresize=True)
+
def switch_to_fullscreen_mode(self):
self.in_fullscreen_mode = True
self.javascript('''
@@ -233,20 +261,21 @@ class Document(QWebPage): # {{{
def javascript(self, string, typ=None):
ans = self.mainFrame().evaluateJavaScript(string)
- if typ == 'int':
+ if typ in {'int', int}:
ans = ans.toInt()
if ans[1]:
return ans[0]
return 0
+ if typ in {'float', float}:
+ ans = ans.toReal()
+ return ans[0] if ans[1] else 0.0
if typ == 'string':
return unicode(ans.toString())
return ans
def javaScriptConsoleMessage(self, msg, lineno, msgid):
if self.debug_javascript:
- prints( 'JS:', msgid, lineno)
prints(msg)
- prints(' ')
else:
return QWebPage.javaScriptConsoleMessage(self, msg, lineno, msgid)
@@ -263,13 +292,7 @@ class Document(QWebPage): # {{{
self.mainFrame().setScrollPosition(QPoint(x, y))
def jump_to_anchor(self, anchor):
- self.javascript('document.location.hash = "%s"'%anchor)
-
- def quantize(self):
- if self.height > self.window_height:
- r = self.height%self.window_height
- if r > 0:
- self.javascript('document.body.style.paddingBottom = "%dpx"'%r)
+ self.javascript('paged_display.jump_to_anchor("%s")'%anchor)
def element_ypos(self, elem):
ans, ok = elem.evaluateJavaScript('$(this).offset().top').toInt()
@@ -314,15 +337,22 @@ class Document(QWebPage): # {{{
@dynamic_property
def scroll_fraction(self):
def fget(self):
- try:
- return abs(float(self.ypos)/(self.height-self.window_height))
- except ZeroDivisionError:
- return 0.
+ if self.in_paged_mode:
+ return self.javascript('paged_display.current_pos()',
+ typ='float')
+ else:
+ try:
+ return abs(float(self.ypos)/(self.height-self.window_height))
+ except ZeroDivisionError:
+ return 0.
def fset(self, val):
- npos = val * (self.height - self.window_height)
- if npos < 0:
- npos = 0
- self.scroll_to(x=self.xpos, y=npos)
+ if self.in_paged_mode:
+ self.javascript('paged_display.scroll_to_pos(%f)'%val)
+ else:
+ npos = val * (self.height - self.window_height)
+ if npos < 0:
+ npos = 0
+ self.scroll_to(x=self.xpos, y=npos)
return property(fget=fget, fset=fset)
@property
@@ -363,6 +393,7 @@ class DocumentView(QWebView): # {{{
DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
def initialize_view(self, debug_javascript=False):
+ self.setRenderHints(QPainter.Antialiasing|QPainter.TextAntialiasing|QPainter.SmoothPixmapTransform)
self.flipper = SlideFlip(self)
self.is_auto_repeat_event = False
self.debug_javascript = debug_javascript
@@ -570,7 +601,7 @@ class DocumentView(QWebView): # {{{
if self.manager is not None:
self.manager.load_started()
- load_html(path, self, codec=path.encoding, mime_type=getattr(path,
+ load_html(path, self, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path,
'mime_type', None), pre_load_callback=callback)
entries = set()
for ie in getattr(path, 'index_entries', []):
@@ -579,10 +610,12 @@ class DocumentView(QWebView): # {{{
if ie.end_anchor:
entries.add(ie.end_anchor)
self.document.index_anchors = entries
- self.turn_off_internal_scrollbars()
def initialize_scrollbar(self):
if getattr(self, 'scrollbar', None) is not None:
+ if self.document.in_paged_mode:
+ self.scrollbar.setVisible(False)
+ return
delta = self.document.width - self.size().width()
if delta > 0:
self._ignore_scrollbar_signals = True
@@ -623,7 +656,6 @@ class DocumentView(QWebView): # {{{
self.manager.scrolled(self.document.scroll_fraction,
onload=True)
- self.turn_off_internal_scrollbars()
if self.flipper.isVisible():
if self.flipper.running:
self.flipper.setVisible(False)
@@ -631,12 +663,6 @@ class DocumentView(QWebView): # {{{
self.flipper(self.current_page_image(),
duration=self.document.page_flip_duration)
-
- def turn_off_internal_scrollbars(self):
- self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
- self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
-
-
@classmethod
def test_line(cls, img, y):
'Test if line contains pixels of exactly the same color'
@@ -651,6 +677,7 @@ class DocumentView(QWebView): # {{{
overlap = self.height()
img = QImage(self.width(), overlap, QImage.Format_ARGB32_Premultiplied)
painter = QPainter(img)
+ painter.setRenderHints(self.renderHints())
self.document.mainFrame().render(painter, QRegion(0, 0, self.width(), overlap))
painter.end()
return img
@@ -670,6 +697,28 @@ class DocumentView(QWebView): # {{{
return
epf = self.document.enable_page_flip and not self.is_auto_repeat_event
+ if self.document.in_paged_mode:
+ loc = self.document.javascript(
+ 'paged_display.previous_screen_location()', typ='int')
+ if loc < 0:
+ if self.manager is not None:
+ if epf:
+ self.flipper.initialize(self.current_page_image(),
+ forwards=False)
+ self.manager.previous_document()
+ else:
+ if epf:
+ self.flipper.initialize(self.current_page_image(),
+ forwards=False)
+ self.document.scroll_to(x=loc, y=0)
+ if epf:
+ self.flipper(self.current_page_image(),
+ duration=self.document.page_flip_duration)
+ if self.manager is not None:
+ self.manager.scrolled(self.scroll_fraction)
+
+ return
+
delta_y = self.document.window_height - 25
if self.document.at_top:
if self.manager is not None:
@@ -700,6 +749,26 @@ class DocumentView(QWebView): # {{{
return
epf = self.document.enable_page_flip and not self.is_auto_repeat_event
+ if self.document.in_paged_mode:
+ loc = self.document.javascript(
+ 'paged_display.next_screen_location()', typ='int')
+ if loc < 0:
+ if self.manager is not None:
+ if epf:
+ self.flipper.initialize(self.current_page_image())
+ self.manager.next_document()
+ else:
+ if epf:
+ self.flipper.initialize(self.current_page_image())
+ self.document.scroll_to(x=loc, y=0)
+ if epf:
+ self.flipper(self.current_page_image(),
+ duration=self.document.page_flip_duration)
+ if self.manager is not None:
+ self.manager.scrolled(self.scroll_fraction)
+
+ return
+
window_height = self.document.window_height
document_height = self.document.height
ddelta = document_height - window_height
@@ -762,25 +831,38 @@ class DocumentView(QWebView): # {{{
#print 'After all:', self.document.ypos
def scroll_by(self, x=0, y=0, notify=True):
- old_pos = self.document.ypos
+ old_pos = (self.document.xpos if self.document.in_paged_mode else
+ self.document.ypos)
self.document.scroll_by(x, y)
- if notify and self.manager is not None and self.document.ypos != old_pos:
+ new_pos = (self.document.xpos if self.document.in_paged_mode else
+ self.document.ypos)
+ if notify and self.manager is not None and new_pos != old_pos:
self.manager.scrolled(self.scroll_fraction)
def scroll_to(self, pos, notify=True):
if self._ignore_scrollbar_signals:
return
- old_pos = self.document.ypos
- if isinstance(pos, basestring):
- self.document.jump_to_anchor(pos)
- else:
- if pos >= 1:
- self.document.scroll_to(0, self.document.height)
+ old_pos = (self.document.xpos if self.document.in_paged_mode else
+ self.document.ypos)
+ if self.document.in_paged_mode:
+ if isinstance(pos, basestring):
+ self.document.jump_to_anchor(pos)
else:
- y = int(math.ceil(
- pos*(self.document.height-self.document.window_height)))
- self.document.scroll_to(0, y)
- if notify and self.manager is not None and self.document.ypos != old_pos:
+ self.document.scroll_fraction = pos
+ else:
+ if isinstance(pos, basestring):
+ self.document.jump_to_anchor(pos)
+ else:
+ if pos >= 1:
+ self.document.scroll_to(0, self.document.height)
+ else:
+ y = int(math.ceil(
+ pos*(self.document.height-self.document.window_height)))
+ self.document.scroll_to(0, y)
+
+ new_pos = (self.document.xpos if self.document.in_paged_mode else
+ self.document.ypos)
+ if notify and self.manager is not None and new_pos != old_pos:
self.manager.scrolled(self.scroll_fraction)
@dynamic_property
@@ -813,9 +895,8 @@ class DocumentView(QWebView): # {{{
return QWebView.changeEvent(self, event)
def paintEvent(self, event):
- self.turn_off_internal_scrollbars()
-
painter = QPainter(self)
+ painter.setRenderHints(self.renderHints())
self.document.mainFrame().render(painter, event.region())
if not self.isEnabled():
painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH)
@@ -827,6 +908,18 @@ class DocumentView(QWebView): # {{{
if self.manager is not None and event.delta() != 0:
(self.manager.font_size_larger if event.delta() > 0 else
self.manager.font_size_smaller)()
+ return
+
+ if self.document.in_paged_mode:
+ if abs(event.delta()) < 15: return
+ typ = 'screen' if self.document.wheel_flips_pages else 'col'
+ direction = 'next' if event.delta() < 0 else 'previous'
+ loc = self.document.javascript('paged_display.%s_%s_location()'%(
+ direction, typ), typ='int')
+ if loc > -1:
+ self.document.scroll_to(x=loc, y=0)
+ return
+
if event.delta() < -14:
if self.document.wheel_flips_pages:
self.next_page()
@@ -866,6 +959,17 @@ class DocumentView(QWebView): # {{{
if not self.handle_key_press(event):
return QWebView.keyPressEvent(self, event)
+ def paged_col_scroll(self, forward=True):
+ dir = 'next' if forward else 'previous'
+ loc = self.document.javascript(
+ 'paged_display.%s_col_location()'%dir, typ='int')
+ if loc > -1:
+ self.document.scroll_to(x=loc, y=0)
+ self.manager.scrolled(self.document.scroll_fraction)
+ else:
+ (self.manager.next_document() if forward else
+ self.manager.previous_document())
+
def handle_key_press(self, event):
handled = True
key = self.shortcuts.get_match(event)
@@ -877,21 +981,33 @@ class DocumentView(QWebView): # {{{
finally:
self.is_auto_repeat_event = False
elif key == 'Down':
- if (not self.document.line_scrolling_stops_on_pagebreaks and
- self.document.at_bottom):
- self.manager.next_document()
+ if self.document.in_paged_mode:
+ self.paged_col_scroll()
else:
- self.scroll_by(y=15)
+ if (not self.document.line_scrolling_stops_on_pagebreaks and
+ self.document.at_bottom):
+ self.manager.next_document()
+ else:
+ self.scroll_by(y=15)
elif key == 'Up':
- if (not self.document.line_scrolling_stops_on_pagebreaks and
- self.document.at_top):
- self.manager.previous_document()
+ if self.document.in_paged_mode:
+ self.paged_col_scroll(forward=False)
else:
- self.scroll_by(y=-15)
+ if (not self.document.line_scrolling_stops_on_pagebreaks and
+ self.document.at_top):
+ self.manager.previous_document()
+ else:
+ self.scroll_by(y=-15)
elif key == 'Left':
- self.scroll_by(x=-15)
+ if self.document.in_paged_mode:
+ self.paged_col_scroll(forward=False)
+ else:
+ self.scroll_by(x=-15)
elif key == 'Right':
- self.scroll_by(x=15)
+ if self.document.in_paged_mode:
+ self.paged_col_scroll()
+ else:
+ self.scroll_by(x=15)
else:
handled = False
return handled
diff --git a/src/calibre/gui2/viewer/javascript.py b/src/calibre/gui2/viewer/javascript.py
index c4814cc04e..1594a1d5db 100644
--- a/src/calibre/gui2/viewer/javascript.py
+++ b/src/calibre/gui2/viewer/javascript.py
@@ -30,10 +30,11 @@ class JavaScriptLoader(object):
CS = {
'cfi':'ebooks.oeb.display.cfi',
'indexing':'ebooks.oeb.display.indexing',
+ 'paged':'ebooks.oeb.display.paged',
}
ORDER = ('jquery', 'jquery_scrollTo', 'bookmarks', 'referencing', 'images',
- 'hyphenation', 'hyphenator', 'cfi', 'indexing',)
+ 'hyphenation', 'hyphenator', 'cfi', 'indexing', 'paged')
def __init__(self, dynamic_coffeescript=False):
diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py
index ee0d3bd361..d2886d6337 100644
--- a/src/calibre/gui2/viewer/main.py
+++ b/src/calibre/gui2/viewer/main.py
@@ -747,6 +747,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
# There hasn't been a resize event for some time
# restore the current page position.
self.resize_in_progress = False
+ self.view.document.after_resize()
if self.window_mode_changed:
# This resize is part of a window mode change, special case it
self.handle_window_mode_toggle()
@@ -1003,6 +1004,12 @@ def main(args=sys.argv):
QApplication.setApplicationName(APP_UID)
main = EbookViewer(args[1] if len(args) > 1 else None,
debug_javascript=opts.debug_javascript, open_at=open_at)
+ # This is needed for paged mode. Without it, the first document that is
+ # loaded will have extra blank space at the bottom, as
+ # turn_off_internal_scrollbars does not take effect for the first
+ # rendered document
+ main.view.load_path(P('viewer/blank.html', allow_user_override=False))
+
sys.excepthook = main.unhandled_exception
main.show()
if opts.raise_window: