mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
PDF Output: Add a new "page number map" setting to easily modify page numbers as needed in headers/fotters and the generated inline table of contents.
Fixes #1796902 [Feature: shift for page numbers in pdf](https://bugs.launchpad.net/calibre/+bug/1796902)
This commit is contained in:
parent
eeff70325d
commit
d32a5ecfc7
@ -303,7 +303,7 @@ OPTIONS = {
|
||||
'pdf_footer_template', 'pdf_header_template', 'pdf_add_toc',
|
||||
'toc_title', 'pdf_page_margin_left', 'pdf_page_margin_top',
|
||||
'pdf_page_margin_right', 'pdf_page_margin_bottom',
|
||||
'pdf_use_document_margins',),
|
||||
'pdf_use_document_margins', 'pdf_page_number_map',),
|
||||
|
||||
'pml': ('inline_toc', 'full_image_depth', 'pml_output_encoding'),
|
||||
|
||||
|
@ -148,6 +148,10 @@ class PDFOutput(OutputFormatPlugin):
|
||||
' This will cause the margins specified in the conversion settings to be ignored.'
|
||||
' If the document does not specify page margins, the conversion settings will be used as a fallback.')
|
||||
),
|
||||
OptionRecommendation(name='pdf_page_number_map', recommended_value=None,
|
||||
help=_('Adjust page numbers, as needed. Syntax is a JavaScript expression for the page number.'
|
||||
' For example, "if (n < 3) 0; else n - 3;", where n is current page number.')
|
||||
),
|
||||
}
|
||||
|
||||
def specialize_options(self, log, opts, input_fmt):
|
||||
|
@ -254,9 +254,10 @@ class PDFWriter(QObject):
|
||||
raise Exception('PDF Output failed, see log for details')
|
||||
|
||||
def render_inline_toc(self):
|
||||
evaljs = self.view.page().mainFrame().evaluateJavaScript
|
||||
self.rendered_inline_toc = True
|
||||
from calibre.ebooks.pdf.render.toc import toc_as_html
|
||||
raw = toc_as_html(self.toc, self.doc, self.opts)
|
||||
raw = toc_as_html(self.toc, self.doc, self.opts, evaljs)
|
||||
pt = PersistentTemporaryFile('_pdf_itoc.htm')
|
||||
pt.write(raw)
|
||||
pt.close()
|
||||
@ -460,12 +461,15 @@ class PDFWriter(QObject):
|
||||
if idx is not None:
|
||||
setattr(self, attr, sections[idx][0])
|
||||
|
||||
from calibre.ebooks.pdf.render.toc import calculate_page_number
|
||||
|
||||
while True:
|
||||
set_section(col, sections, 'current_section')
|
||||
set_section(col, tl_sections, 'current_tl_section')
|
||||
self.doc.init_page(page_margins)
|
||||
num = calculate_page_number(self.current_page_num, self.opts.pdf_page_number_map, evaljs)
|
||||
if self.header or self.footer:
|
||||
if evaljs('paged_display.update_header_footer(%d)'%self.current_page_num) is True:
|
||||
if evaljs('paged_display.update_header_footer(%d)'%num) is True:
|
||||
self.load_header_footer_images()
|
||||
|
||||
self.painter.save()
|
||||
|
@ -12,7 +12,14 @@ from lxml.html import tostring
|
||||
from lxml.html.builder import (HTML, HEAD, BODY, TABLE, TR, TD, H2, STYLE)
|
||||
|
||||
|
||||
def convert_node(toc, table, level, pdf):
|
||||
def calculate_page_number(num, map_expression, evaljs):
|
||||
if map_expression:
|
||||
num = int(evaljs('(function(){{var n={}; return {};}})()'.format(
|
||||
num, map_expression)))
|
||||
return num
|
||||
|
||||
|
||||
def convert_node(toc, table, level, pdf, pdf_page_number_map, evaljs):
|
||||
tr = TR(
|
||||
TD(toc.text or _('Unknown')), TD(),
|
||||
)
|
||||
@ -28,18 +35,18 @@ def convert_node(toc, table, level, pdf):
|
||||
return None
|
||||
a = anchors[path]
|
||||
dest = a.get(frag, a[None])
|
||||
num = pdf.page_tree.obj.get_num(dest[0])
|
||||
num = calculate_page_number(pdf.page_tree.obj.get_num(dest[0]), pdf_page_number_map, evaljs)
|
||||
tr[1].text = type('')(num)
|
||||
table.append(tr)
|
||||
|
||||
|
||||
def process_children(toc, table, level, pdf):
|
||||
def process_children(toc, table, level, pdf, pdf_page_number_map, evaljs):
|
||||
for child in toc:
|
||||
convert_node(child, table, level, pdf)
|
||||
process_children(child, table, level+1, pdf)
|
||||
convert_node(child, table, level, pdf, pdf_page_number_map, evaljs)
|
||||
process_children(child, table, level+1, pdf, pdf_page_number_map, evaljs)
|
||||
|
||||
|
||||
def toc_as_html(toc, pdf, opts):
|
||||
def toc_as_html(toc, pdf, opts, evaljs):
|
||||
pdf = pdf.engine.pdf
|
||||
indents = []
|
||||
for i in xrange(1, 7):
|
||||
@ -73,6 +80,6 @@ def toc_as_html(toc, pdf, opts):
|
||||
body = html[1]
|
||||
body.set('class', 'calibre-pdf-toc')
|
||||
|
||||
process_children(toc, body[1], 0, pdf)
|
||||
process_children(toc, body[1], 0, pdf, opts.pdf_page_number_map, evaljs)
|
||||
|
||||
return tostring(html, pretty_print=True, include_meta_content_type=True, encoding='utf-8')
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>638</width>
|
||||
<height>588</height>
|
||||
<height>634</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -197,14 +197,27 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Page &number map:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_pdf_page_number_map</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QLineEdit" name="opt_pdf_page_number_map"/>
|
||||
</item>
|
||||
<item row="17" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="page_margins_box">
|
||||
<property name="title">
|
||||
<string>Page margins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0" colspan="2">
|
||||
<item row="18" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="template_box">
|
||||
<property name="title">
|
||||
<string>Page headers and footers</string>
|
||||
|
@ -658,6 +658,7 @@ def pdf_output(container):
|
||||
g.appendChild(choices('pdf_standard_font', _('S&tandard font:'), ui_data.font_types))
|
||||
g.appendChild(int_spin('pdf_default_font_size', _('Default font si&ze:'), unit='px'))
|
||||
g.appendChild(int_spin('pdf_mono_font_size', _('Default font si&ze:'), unit='px'))
|
||||
g.appendChild(lineedit('pdf_page_number_map', _('Page number &map:')))
|
||||
g.appendChild(checkbox('pdf_use_document_margins', _('Use page margins from the &document being converted')))
|
||||
g.appendChild(float_spin('pdf_page_margin_left', indent + _('Left page margin'), unit='pt', min=-100, max=500))
|
||||
g.appendChild(float_spin('pdf_page_margin_top', indent + _('Top page margin'), unit='pt', min=-100, max=500))
|
||||
|
Loading…
x
Reference in New Issue
Block a user