From 929f65ecf2fdb44fa2341ce02ff4513b8dfaa5c5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 17 Jul 2019 14:43:56 +0530 Subject: [PATCH] Optionally get font data when listing fonts --- src/calibre/utils/podofo/fonts.cpp | 20 ++++++++++++++------ src/calibre/utils/podofo/global.h | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/calibre/utils/podofo/fonts.cpp b/src/calibre/utils/podofo/fonts.cpp index 62b125b204..bd322b8e73 100644 --- a/src/calibre/utils/podofo/fonts.cpp +++ b/src/calibre/utils/podofo/fonts.cpp @@ -75,6 +75,8 @@ used_fonts_in_page(PdfPage *page, int page_num, PyObject *ans) { extern "C" { PyObject* list_fonts(PDFDoc *self, PyObject *args) { + int get_font_data = 0; + if (!PyArg_ParseTuple(args, "|i", &get_font_data)) return NULL; pyunique_ptr ans(PyList_New(0)); if (!ans) return NULL; try { @@ -88,15 +90,20 @@ list_fonts(PDFDoc *self, PyObject *args) { const PdfReference &ref = (*it)->Reference(); unsigned long num = ref.ObjectNumber(), generation = ref.GenerationNumber(); const PdfObject *descriptor = (*it)->GetIndirectKey("FontDescriptor"); - long long stream_len = 0; - pyunique_ptr descendant_font, stream_ref; + pyunique_ptr descendant_font, stream_ref, encoding; + PyBytesOutputStream stream_data; + if (dict.HasKey("Encoding") && dict.GetKey("Encoding")->IsName()) { + encoding.reset(PyUnicode_FromString(dict.GetKey("Encoding")->GetName().GetName().c_str())); + } if (descriptor) { const PdfObject *ff = get_font_file(descriptor); if (ff) { stream_ref.reset(ref_as_tuple(ff->Reference())); if (!stream_ref) return NULL; const PdfStream *stream = ff->GetStream(); - if (stream) stream_len = stream->GetLength(); + if (stream && get_font_data) { + stream->GetCopy(&stream_data); + } } } else if (dict.HasKey("DescendantFonts")) { const PdfArray &df = dict.GetKey("DescendantFonts")->GetArray(); @@ -105,13 +112,14 @@ list_fonts(PDFDoc *self, PyObject *args) { } #define V(x) (x ? x.get() : Py_None) pyunique_ptr d(Py_BuildValue( - "{ss ss s(kk) sL sO sO}", + "{ss ss s(kk) sO sO sO sO}", "BaseFont", name.c_str(), "Subtype", subtype.c_str(), "Reference", num, generation, - "Length", stream_len, + "Data", V(stream_data), "DescendantFont", V(descendant_font), - "StreamRef", V(stream_ref) + "StreamRef", V(stream_ref), + "Encoding", V(encoding) )); #undef V if (!d) { return NULL; } diff --git a/src/calibre/utils/podofo/global.h b/src/calibre/utils/podofo/global.h index ee69492a05..2063d67ed6 100644 --- a/src/calibre/utils/podofo/global.h +++ b/src/calibre/utils/podofo/global.h @@ -50,6 +50,32 @@ struct PyObjectDeleter { // unique_ptr that uses Py_XDECREF as the destructor function. typedef std::unique_ptr pyunique_ptr; +class PyBytesOutputStream : public PdfOutputStream { + private: + pyunique_ptr bytes; + PyBytesOutputStream( const PyBytesOutputStream & ) ; + PyBytesOutputStream & operator=( const PyBytesOutputStream & ) ; + public: + PyBytesOutputStream() : bytes() {} + void Close() {} + operator bool() const { return bool(bytes); } + PyObject* get() const { return bytes.get(); } + pdf_long Write(const char *buf, const pdf_long sz){ + if (!bytes) { + bytes.reset(PyBytes_FromStringAndSize(buf, sz)); + if (!bytes) throw PdfError(ePdfError_OutOfMemory, __FILE__, __LINE__, NULL); + } else { + size_t old_sz = PyBytes_GET_SIZE(bytes.get()); + PyObject *old = bytes.release(); + if (_PyBytes_Resize(&old, old_sz + sz) != 0) throw PdfError(ePdfError_OutOfMemory, __FILE__, __LINE__, NULL); + memcpy(PyBytes_AS_STRING(old) + old_sz, buf, sz); + bytes.reset(old); + } + return sz; + } +}; + + template static inline bool dictionary_has_key_name(const PdfDictionary &d, T key, const char *name) {