PDF Output: Fix occasional blank pages erroneously inserted in the text (at the end of an internal html file). Fixes #1559855 [epub to pdf conversion results in random blank pages](https://bugs.launchpad.net/calibre/+bug/1559855)

This commit is contained in:
Kovid Goyal 2016-03-26 16:28:40 +05:30
parent 887c92ad6f
commit ac2d7ccbcf
3 changed files with 21 additions and 7 deletions

View File

@ -87,6 +87,7 @@ class PdfEngine(QPaintEngine):
self.fonts = {} self.fonts = {}
self.current_page_num = 1 self.current_page_num = 1
self.current_page_inited = False self.current_page_inited = False
self.content_written_to_current_page = False
self.qt_hack, err = plugins['qt_hack'] self.qt_hack, err = plugins['qt_hack']
if err: if err:
raise RuntimeError('Failed to load qt_hack with err: %s'%err) raise RuntimeError('Failed to load qt_hack with err: %s'%err)
@ -107,6 +108,7 @@ class PdfEngine(QPaintEngine):
return self.graphics.current_state.do_stroke return self.graphics.current_state.do_stroke
def init_page(self): def init_page(self):
self.content_written_to_current_page = False
self.pdf.transform(self.pdf_system) self.pdf.transform(self.pdf_system)
self.pdf.apply_fill(color=(1, 1, 1)) # QPainter has a default background brush of white self.pdf.apply_fill(color=(1, 1, 1)) # QPainter has a default background brush of white
self.graphics.reset() self.graphics.reset()
@ -127,12 +129,14 @@ class PdfEngine(QPaintEngine):
return False return False
return True return True
def end_page(self): def end_page(self, is_last_page=False):
if self.current_page_inited: if self.current_page_inited:
self.pdf.restore_stack() self.pdf.restore_stack()
self.pdf.end_page() drop_page = is_last_page and not self.content_written_to_current_page
self.pdf.end_page(drop_page=drop_page)
self.current_page_inited = False self.current_page_inited = False
self.current_page_num += 1 self.current_page_num += 0 if drop_page else 1
return self.content_written_to_current_page
def end(self): def end(self):
try: try:
@ -156,6 +160,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawTiledPixmap(self, rect, pixmap, point): def drawTiledPixmap(self, rect, pixmap, point):
self.content_written_to_current_page = 'drawTiledPixmap'
self.apply_graphics_state() self.apply_graphics_state()
brush = QBrush(pixmap) brush = QBrush(pixmap)
bl = rect.topLeft() bl = rect.topLeft()
@ -170,6 +175,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawPixmap(self, rect, pixmap, source_rect): def drawPixmap(self, rect, pixmap, source_rect):
self.content_written_to_current_page = 'drawPixmap'
self.apply_graphics_state() self.apply_graphics_state()
source_rect = source_rect.toRect() source_rect = source_rect.toRect()
pixmap = (pixmap if source_rect == pixmap.rect() else pixmap = (pixmap if source_rect == pixmap.rect() else
@ -182,6 +188,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawImage(self, rect, image, source_rect, flags=Qt.AutoColor): def drawImage(self, rect, image, source_rect, flags=Qt.AutoColor):
self.content_written_to_current_page = 'drawImage'
self.apply_graphics_state() self.apply_graphics_state()
source_rect = source_rect.toRect() source_rect = source_rect.toRect()
image = (image if source_rect == image.rect() else image = (image if source_rect == image.rect() else
@ -197,6 +204,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawPath(self, path): def drawPath(self, path):
self.content_written_to_current_page = 'drawPath'
self.apply_graphics_state() self.apply_graphics_state()
p = convert_path(path) p = convert_path(path)
fill_rule = {Qt.OddEvenFill:'evenodd', fill_rule = {Qt.OddEvenFill:'evenodd',
@ -206,6 +214,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawPoints(self, points): def drawPoints(self, points):
self.content_written_to_current_page = 'drawPoints'
self.apply_graphics_state() self.apply_graphics_state()
p = Path() p = Path()
for point in points: for point in points:
@ -220,6 +229,8 @@ class PdfEngine(QPaintEngine):
for rect in rects: for rect in rects:
self.resolve_fill(rect) self.resolve_fill(rect)
bl = rect.topLeft() bl = rect.topLeft()
if self.do_stroke or self.do_fill:
self.content_written_to_current_page = 'drawRects'
self.pdf.draw_rect(bl.x(), bl.y(), rect.width(), rect.height(), self.pdf.draw_rect(bl.x(), bl.y(), rect.width(), rect.height(),
stroke=self.do_stroke, fill=self.do_fill) stroke=self.do_stroke, fill=self.do_fill)
@ -240,6 +251,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawTextItem(self, point, text_item): def drawTextItem(self, point, text_item):
self.content_written_to_current_page = 'drawTextItem'
# return super(PdfEngine, self).drawTextItem(point, text_item) # return super(PdfEngine, self).drawTextItem(point, text_item)
self.apply_graphics_state() self.apply_graphics_state()
gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item)) gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item))
@ -274,6 +286,7 @@ class PdfEngine(QPaintEngine):
@store_error @store_error
def drawPolygon(self, points, mode): def drawPolygon(self, points, mode):
self.content_written_to_current_page = 'drawPolygon'
self.apply_graphics_state() self.apply_graphics_state()
if not points: if not points:
return return

View File

@ -393,7 +393,7 @@ class PDFWriter(QObject):
nsl = int(evaljs('paged_display.next_screen_location()')) nsl = int(evaljs('paged_display.next_screen_location()'))
except (TypeError, ValueError): except (TypeError, ValueError):
break break
self.doc.end_page() self.doc.end_page(nsl <= 0)
if nsl <= 0: if nsl <= 0:
break break
evaljs('window.scrollTo(%d, 0); paged_display.position_header_footer();'%nsl) evaljs('window.scrollTo(%d, 0); paged_display.position_header_footer();'%nsl)

View File

@ -377,9 +377,10 @@ class PDFStream(object):
self.fill_opacities[opacity] = self.objects.add(op) self.fill_opacities[opacity] = self.objects.add(op)
self.current_page.set_opacity(self.fill_opacities[opacity]) self.current_page.set_opacity(self.fill_opacities[opacity])
def end_page(self): def end_page(self, drop_page=False):
pageref = self.current_page.end(self.objects, self.stream) if not drop_page:
self.page_tree.obj.add_page(pageref) pageref = self.current_page.end(self.objects, self.stream)
self.page_tree.obj.add_page(pageref)
self.current_page = Page(self.page_tree, compress=self.compress) self.current_page = Page(self.page_tree, compress=self.compress)
def draw_glyph_run(self, transform, size, font_metrics, glyphs): def draw_glyph_run(self, transform, size, font_metrics, glyphs):