mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement imposing headers/footers onto their target pages
This commit is contained in:
parent
848d91c6d8
commit
227679985f
@ -116,7 +116,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "podofo",
|
"name": "podofo",
|
||||||
"sources": "calibre/utils/podofo/utils.cpp calibre/utils/podofo/output.cpp calibre/utils/podofo/doc.cpp calibre/utils/podofo/outline.cpp calibre/utils/podofo/fonts.cpp calibre/utils/podofo/podofo.cpp",
|
"sources": "calibre/utils/podofo/utils.cpp calibre/utils/podofo/output.cpp calibre/utils/podofo/doc.cpp calibre/utils/podofo/outline.cpp calibre/utils/podofo/fonts.cpp calibre/utils/podofo/impose.cpp calibre/utils/podofo/podofo.cpp",
|
||||||
"headers": "calibre/utils/podofo/global.h",
|
"headers": "calibre/utils/podofo/global.h",
|
||||||
"libraries": "podofo",
|
"libraries": "podofo",
|
||||||
"lib_dirs": "!podofo_lib",
|
"lib_dirs": "!podofo_lib",
|
||||||
|
@ -860,7 +860,7 @@ def add_header_footer(manager, opts, pdf_doc, container, page_number_display_map
|
|||||||
root = container.parsed(name)
|
root = container.parsed(name)
|
||||||
body = root[-1]
|
body = root[-1]
|
||||||
body.attrib.pop('id', None)
|
body.attrib.pop('id', None)
|
||||||
body.set('style', 'margin: 0; padding: 0; border-width: 0')
|
body.set('style', 'margin: 0; padding: 0; border-width: 0; background-color: unset')
|
||||||
job = job_for_name(container, name, Margins(0, 0, 0, 0), page_layout)
|
job = job_for_name(container, name, Margins(0, 0, 0, 0), page_layout)
|
||||||
|
|
||||||
def m(tag_name, text=None, style=None, **attrs):
|
def m(tag_name, text=None, style=None, **attrs):
|
||||||
@ -928,6 +928,7 @@ def add_header_footer(manager, opts, pdf_doc, container, page_number_display_map
|
|||||||
'padding': '0',
|
'padding': '0',
|
||||||
'border-width': '0',
|
'border-width': '0',
|
||||||
'overflow': 'hidden',
|
'overflow': 'hidden',
|
||||||
|
'background-color': 'unset',
|
||||||
}
|
}
|
||||||
|
|
||||||
ans = m('div', style=style, id='p{}'.format(page_num))
|
ans = m('div', style=style, id='p{}'.format(page_num))
|
||||||
@ -944,7 +945,7 @@ def add_header_footer(manager, opts, pdf_doc, container, page_number_display_map
|
|||||||
style = ans.get('style') or ''
|
style = ans.get('style') or ''
|
||||||
style = (
|
style = (
|
||||||
'margin: 0; padding: 0; height: {height}pt; border-width: 0;'
|
'margin: 0; padding: 0; height: {height}pt; border-width: 0;'
|
||||||
'display: flex; align-items: center; overflow: hidden').format(height=height) + style
|
'display: flex; align-items: center; overflow: hidden; background-color: unset').format(height=height) + style
|
||||||
ans.set('style', style)
|
ans.set('style', style)
|
||||||
for child in ans.xpath('descendant-or-self::*[@class]'):
|
for child in ans.xpath('descendant-or-self::*[@class]'):
|
||||||
cls = frozenset(child.get('class').split())
|
cls = frozenset(child.get('class').split())
|
||||||
@ -970,7 +971,13 @@ def add_header_footer(manager, opts, pdf_doc, container, page_number_display_map
|
|||||||
if not isinstance(data, bytes):
|
if not isinstance(data, bytes):
|
||||||
raise SystemExit(data)
|
raise SystemExit(data)
|
||||||
doc = data_as_pdf_doc(data)
|
doc = data_as_pdf_doc(data)
|
||||||
|
first_page_num = pdf_doc.page_count()
|
||||||
|
num_pages = doc.page_count()
|
||||||
|
if first_page_num != num_pages:
|
||||||
|
raise ValueError('The number of header/footers pages ({}) != number of document pages ({})'.format(
|
||||||
|
num_pages, first_page_num))
|
||||||
pdf_doc.append(doc)
|
pdf_doc.append(doc)
|
||||||
|
pdf_doc.impose(1, first_page_num + 1, num_pages)
|
||||||
report_progress(0.9, _('Headers and footers added'))
|
report_progress(0.9, _('Headers and footers added'))
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
@ -756,6 +756,9 @@ static PyMethodDef PDFDoc_methods[] = {
|
|||||||
{"dedup_type3_fonts", (PyCFunction)py_dedup_type3_fonts, METH_VARARGS,
|
{"dedup_type3_fonts", (PyCFunction)py_dedup_type3_fonts, METH_VARARGS,
|
||||||
"dedup_type3_fonts() -> De-duplicate repeated glyphs in Type3 fonts"
|
"dedup_type3_fonts() -> De-duplicate repeated glyphs in Type3 fonts"
|
||||||
},
|
},
|
||||||
|
{"impose", (PyCFunction)py_impose, METH_VARARGS,
|
||||||
|
"impose() -> impose pages onto each other"
|
||||||
|
},
|
||||||
{"delete_pages", (PyCFunction)PDFDoc_delete_pages, METH_VARARGS,
|
{"delete_pages", (PyCFunction)PDFDoc_delete_pages, METH_VARARGS,
|
||||||
"delete_page(page_num, count=1) -> Delete the specified pages from the pdf."
|
"delete_page(page_num, count=1) -> Delete the specified pages from the pdf."
|
||||||
},
|
},
|
||||||
|
@ -11,14 +11,6 @@
|
|||||||
|
|
||||||
using namespace pdf;
|
using namespace pdf;
|
||||||
|
|
||||||
#define PYWRAP(name) extern "C" PyObject* py_##name(PDFDoc *self, PyObject *args) { \
|
|
||||||
try { \
|
|
||||||
return name(self, args); \
|
|
||||||
} catch (const PdfError &err) { podofo_set_exception(err); return NULL; \
|
|
||||||
} catch (const std::exception &err) { PyErr_Format(Error, "Error in %s(): %s", #name, err.what()); return NULL; \
|
|
||||||
} catch (...) { PyErr_SetString(Error, "An unknown error occurred in " #name); return NULL; } \
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline PyObject*
|
static inline PyObject*
|
||||||
ref_as_tuple(const PdfReference &ref) {
|
ref_as_tuple(const PdfReference &ref) {
|
||||||
unsigned long num = ref.ObjectNumber(), generation = ref.GenerationNumber();
|
unsigned long num = ref.ObjectNumber(), generation = ref.GenerationNumber();
|
||||||
|
@ -100,5 +100,14 @@ PyObject* py_list_fonts(PDFDoc*, PyObject*);
|
|||||||
PyObject* py_remove_unused_fonts(PDFDoc *self, PyObject *args);
|
PyObject* py_remove_unused_fonts(PDFDoc *self, PyObject *args);
|
||||||
PyObject* py_merge_fonts(PDFDoc *self, PyObject *args);
|
PyObject* py_merge_fonts(PDFDoc *self, PyObject *args);
|
||||||
PyObject* py_dedup_type3_fonts(PDFDoc *self, PyObject *args);
|
PyObject* py_dedup_type3_fonts(PDFDoc *self, PyObject *args);
|
||||||
|
PyObject* py_impose(PDFDoc *self, PyObject *args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PYWRAP(name) extern "C" PyObject* py_##name(PDFDoc *self, PyObject *args) { \
|
||||||
|
try { \
|
||||||
|
return name(self, args); \
|
||||||
|
} catch (const PdfError &err) { podofo_set_exception(err); return NULL; \
|
||||||
|
} catch (const std::exception &err) { PyErr_Format(Error, "Error in %s(): %s", #name, err.what()); return NULL; \
|
||||||
|
} catch (...) { PyErr_SetString(Error, "An unknown error occurred in " #name); return NULL; } \
|
||||||
|
}
|
||||||
|
40
src/calibre/utils/podofo/impose.cpp
Normal file
40
src/calibre/utils/podofo/impose.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* impose.cpp
|
||||||
|
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
using namespace pdf;
|
||||||
|
|
||||||
|
static void
|
||||||
|
impose_page(PdfMemDocument *doc, unsigned long dest_page_num, unsigned long src_page_num) {
|
||||||
|
PdfXObject *xobj = new PdfXObject(doc, src_page_num, "HeaderFooter");
|
||||||
|
PdfPage *dest = doc->GetPage(dest_page_num);
|
||||||
|
dest->AddResource(xobj->GetIdentifier(), xobj->GetObject()->Reference(), "XObject");
|
||||||
|
PdfStream *stream = dest->GetContents()->GetStream();
|
||||||
|
char *buffer = NULL; pdf_long sz;
|
||||||
|
stream->GetFilteredCopy(&buffer, &sz);
|
||||||
|
stream->BeginAppend();
|
||||||
|
stream->Append("q\n1 0 0 1 0 0 cm\n/");
|
||||||
|
stream->Append(xobj->GetIdentifier().GetName());
|
||||||
|
stream->Append(" Do\nQ\n");
|
||||||
|
stream->Append(buffer, sz);
|
||||||
|
stream->EndAppend();
|
||||||
|
podofo_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
impose(PDFDoc *self, PyObject *args) {
|
||||||
|
unsigned long dest_page_num, src_page_num, count;
|
||||||
|
if (!PyArg_ParseTuple(args, "kkk", &dest_page_num, &src_page_num, &count)) return NULL;
|
||||||
|
for (unsigned long i = 0; i < count; i++) {
|
||||||
|
impose_page(self->doc, dest_page_num - 1 + i, src_page_num - 1 + i);
|
||||||
|
}
|
||||||
|
self->doc->DeletePages(src_page_num - 1, count);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYWRAP(impose)
|
Loading…
x
Reference in New Issue
Block a user