diff --git a/setup/build_environment.py b/setup/build_environment.py index b39df4e58d..42fdea5d07 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -73,14 +73,17 @@ def pkgconfig_libs(name, envvar, default): def consolidate(envvar, default): val = os.environ.get(envvar, default) - ans = [x.strip() for x in val.split(os.pathsep())] + ans = [x.strip() for x in val.split(os.pathsep)] return [x for x in ans if x and os.path.exists(x)] pyqt = pyqtconfig.Configuration() qt_inc = pyqt.qt_inc_dir qt_lib = pyqt.qt_lib_dir - +ft_lib_dirs = [] +ft_libs = [] +jpg_libs = [] +jpg_lib_dirs = [] fc_inc = '/usr/include/fontconfig' fc_lib = '/usr/lib' podofo_inc = '/usr/include/podofo' @@ -90,13 +93,27 @@ if iswindows: fc_inc = r'C:\cygwin\home\kovid\fontconfig\include\fontconfig' fc_lib = r'C:\cygwin\home\kovid\fontconfig\lib' poppler_inc_dirs = consolidate('POPPLER_INC_DIR', - r'C:\cygwin\home\kovid\poppler\include\poppler') - popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[0]+r'\qt4'] + (r'C:\cygwin\home\kovid\poppler\poppler-source\poppler;' + r'C:\cygwin\home\kovid\poppler\poppler-source;' + r'C:\cygwin\home\kovid\poppler\poppler-build;' + r'C:\cygwin\home\kovid\poppler\poppler-build\poppler')) + popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[1]+r'\qt4'] poppler_lib_dirs = consolidate('POPPLER_LIB_DIR', - r'C:\cygwin\home\kovid\poppler\lib') + (r'C:\cygwin\home\kovid\poppler\poppler-build\qt4\src\Release;' + r'C:\cygwin\home\kovid\poppler\poppler-build\Release')) popplerqt4_lib_dirs = poppler_lib_dirs - poppler_libs = ['poppler'] + poppler_libs = ['poppler', 'poppler-qt4'] popplerqt4_libs = poppler_libs + ['QtCore4', 'QtGui4'] + png_inc_dirs = [r'C:\cygwin\home\\kovid\gnuwin32\include'] + png_lib_dirs = [r'C:\cygwin\home\\kovid\gnuwin32\lib'] + png_libs = [r'libpng'] + jpg_lib_dirs = [r'C:\cygwin\home\\kovid\gnuwin32\lib'] + jpg_libs = ['jpeg'] + magick_inc_dirs = [r'C:\cygwin\home\kovid\ImageMagick-6.5.6-Q16\include'] + magick_lib_dirs = [r'C:\cygwin\home\kovid\ImageMagick-6.5.6-Q16\lib'] + magick_libs = ['CORE_RL_wand_', 'CORE_RL_magick_'] + ft_lib_dirs = [r'C:\cygwin\home\\kovid\gnuwin32\lib'] + ft_libs = ['freetype'] podofo_inc = 'C:\\podofo\\include\\podofo' podofo_lib = r'C:\podofo' elif isosx: diff --git a/setup/extensions.py b/setup/extensions.py index 1f50593bb8..2c1aa07815 100644 --- a/setup/extensions.py +++ b/setup/extensions.py @@ -17,7 +17,7 @@ from setup.build_environment import fc_inc, fc_lib, \ podofo_lib, podofo_error, poppler_error, pyqt, OSX_SDK, NMAKE, \ leopard_build, QMAKE, msvc, MT, win_inc, win_lib, png_inc_dirs, \ magick_inc_dirs, magick_lib_dirs, png_lib_dirs, png_libs, \ - magick_error, magick_libs + magick_error, magick_libs, ft_lib_dirs, ft_libs, jpg_libs, jpg_lib_dirs MT isunix = islinux or isosx @@ -49,7 +49,21 @@ reflow_sources = glob.glob(os.path.join(SRC, 'calibre', 'ebooks', 'pdf', '*.cpp' reflow_headers = glob.glob(os.path.join(SRC, 'calibre', 'ebooks', 'pdf', '*.h')) reflow_error = poppler_error if poppler_error else magick_error +pdfreflow_libs = [] +if iswindows: + pdfreflow_libs = ['advapi32', 'User32', 'Gdi32'] + extensions = [ + Extension('pdfreflow', + reflow_sources, + headers=reflow_headers, + libraries=poppler_libs+magick_libs+png_libs+ft_libs+jpg_libs+pdfreflow_libs, + lib_dirs=poppler_lib_dirs+magick_lib_dirs+png_lib_dirs+ft_lib_dirs+jpg_lib_dirs, + inc_dirs=poppler_inc_dirs+magick_inc_dirs+png_inc_dirs, + error=reflow_error, + cflags=['-DPNG_SKIP_SETJMP_CHECK'] if islinux else [] + ), + Extension('lzx', ['calibre/utils/lzx/lzxmodule.c', 'calibre/utils/lzx/compressor.c', @@ -96,15 +110,6 @@ extensions = [ sip_files = ['calibre/gui2/pictureflow/pictureflow.sip'] ), - Extension('pdfreflow', - reflow_sources, - headers=reflow_headers, - libraries=poppler_libs+magick_libs+png_libs, - lib_dirs=poppler_lib_dirs+magick_lib_dirs+png_lib_dirs, - inc_dirs=poppler_inc_dirs+magick_inc_dirs+png_inc_dirs, - error=reflow_error, - cflags=['-DPNG_SKIP_SETJMP_CHECK'] if islinux else [] - ) ] @@ -266,7 +271,7 @@ class Build(Command): ['/EXPORT:init'+ext.name] + objects + ['/OUT:'+dest] else: cmd += objects + ['-o', dest] + ldflags + ext.ldflags + elib + xlib - print ' '.join(cmd) + self.info('\n\n', ' '.join(cmd), '\n\n') subprocess.check_call(cmd) if iswindows: #manifest = dest+'.manifest' @@ -369,7 +374,7 @@ class BuildPDF2XML(Command): continue obj = self.j(odest, self.b(src+'.o')) if self.newer(obj, [src]+reflow_headers): - cmd = ['g++', '-pthread', '-pedantic', '-g', '-c', '-Wall', '-I/usr/include/poppler', + cmd = ['g++', '-pthread', '-pedantic', '-ggdb', '-c', '-Wall', '-I/usr/include/poppler', '-I/usr/include/ImageMagick', '-DPDF2XML', '-o', obj, src] self.info(*cmd) diff --git a/setup/installer/windows/calibre/calibre.mpi b/setup/installer/windows/calibre/calibre.mpi index df36672cf6..2309a1129c 100644 --- a/setup/installer/windows/calibre/calibre.mpi +++ b/setup/installer/windows/calibre/calibre.mpi @@ -296,8 +296,15 @@ File ::F1D1D581-9194-D12F-6139-F920EEC1B14E -name winutil.pyd -parent 0AC00D67-8 File ::A94E4D31-5F8C-A363-AE61-A8F2E3A7B756 -name lzx.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 File ::2C88788E-B9FB-729D-442B-600ED97096A0 -name cPalmdoc.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 File ::26503DDE-8C5F-102F-B689-C6A17B2D6C93 -name msdes.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 -File ::0FE771BC-EBF3-E4E0-DDE0-2D69F2BD99C6 -name calibre_poppler.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 File ::FCB0D098-8F90-1C97-9E20-65546F08A203 -name fontconfig.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::E3BD0592-A0B9-B69D-7FD8-AD828D301351 -name cPalmdoc.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::03E9E137-98F0-1B8C-CBE7-6E3A6691D4F1 -name pdfreflow.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::BF6697B0-1BA5-024A-0566-2F3B22D8449F -name lzx.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::520B27CC-2288-A6BA-689B-B7C090B1D27E -name pdfreflow.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::F49E4A29-3607-039C-C67C-31E59861037C -name fontconfig.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::3F660706-F752-6458-0DF5-CFD1C556DDC1 -name winutil.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::4DD0593A-E9D1-2EB4-4CB4-DF75F28C9D0C -name podofo.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::F6486848-58DE-9CC7-7F72-A1A3BC936DD3 -name msdes.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 File ::01034EB7-C79C-42B9-6FF0-E06C72EF2623 -type dir -name iconengines -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::8ADB07A0-6B9E-8F53-34DF-2035C7C343F1 -name qsvgicon4.dll -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 File ::41F512E3-9F39-68C6-BB7F-58F572755D35 -name qsvgicon4.exp -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 @@ -565,8 +572,8 @@ File ::7BE6B538-70D5-A7EB-5F91-E14CE57B394B -name calibre-complete.exe.local -pa File ::C4E40030-3EE0-8B05-E6B9-89E81433EE1F -name phonon4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9E84342F-36ED-7ED3-8F90-1EC55267BCFC -name poppler-qt4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C9967023-A4C2-856C-1D90-DC710105EBCD -name jpeg62.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::12FA46DA-F25E-0D26-E23C-006013332FED -name freetype.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B1560042-C99B-9803-552E-21C15F0DFD85 -type dir -name resources -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::DEDE8BE9-D712-2770-A1EC-7E9164CC6D29 -name libpng12.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 Component ::F6829AB7-9F66-4CEE-CA0E-21F54C6D3609 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Main -parent Components SetupType ::D9ADE41C-B744-690C-2CED-CF826BF03D2E -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Typical -parent SetupTypes diff --git a/setup/installer/windows/freeze.py b/setup/installer/windows/freeze.py index eb04db197f..704f3b3b7b 100644 --- a/setup/installer/windows/freeze.py +++ b/setup/installer/windows/freeze.py @@ -9,8 +9,8 @@ Freeze app into executable using py2exe. QT_DIR = 'C:\\Qt\\4.5.2' LIBUSB_DIR = 'C:\\libusb' LIBUNRAR = 'C:\\Program Files\\UnrarDLL\\unrar.dll' -PDFTOHTML = 'C:\\cygwin\\home\\kovid\\poppler-0.10.6\\rel\\pdftohtml.exe' -POPPLER = 'C:\\cygwin\\home\\kovid\\poppler' +POPPLER = 'C:\\cygwin\\home\\kovid\\poppler\\poppler-build' +GNUWIN32 = r'C:\cygwin\home\kovid\gnuwin32' IMAGEMAGICK_DIR = 'C:\\ImageMagick' PDFTK = 'C:\\pdftk.exe' PODOFO = 'C:\\podofo' @@ -189,10 +189,12 @@ class BuildEXE(bc): print '\tAdding unrar' shutil.copyfile(LIBUNRAR, os.path.join(PY2EXE_DIR, os.path.basename(LIBUNRAR))) print '\tAdding poppler' - for x in ('bin\\pdftohtml.exe', 'bin\\poppler-qt4.dll', - 'bin\\freetype.dll', 'bin\\jpeg62.dll'): + for x in (r'utils\Release\pdftohtml.exe', + r'qt4\src\Release\poppler-qt4.dll'): shutil.copyfile(os.path.join(POPPLER, x), os.path.join(PY2EXE_DIR, os.path.basename(x))) + for x in ('jpeg62', 'zlib1', 'libpng12'): + shutil.copy2(os.path.join(GNUWIN32, 'bin', x+'.dll'), PY2EXE_DIR) print '\tAdding podofo' for f in glob.glob(os.path.join(PODOFO, '*.dll')): shutil.copyfile(f, os.path.join(PY2EXE_DIR, os.path.basename(f))) diff --git a/src/calibre/ebooks/pdf/fonts.cpp b/src/calibre/ebooks/pdf/fonts.cpp index 43de8646a9..3cd7ef0c5b 100644 --- a/src/calibre/ebooks/pdf/fonts.cpp +++ b/src/calibre/ebooks/pdf/fonts.cpp @@ -31,11 +31,12 @@ static const char *FONT_MODS[7] = { NULL }; +#ifdef _WIN32 #define ap_toupper(c) (toupper(((unsigned char)(c)))) static inline -char *strcasestr( char *h, char *n ) +const char *strcasestr(const char *h, const char *n ) { /* h="haystack", n="needle" */ - char *a=h, *e=n; + const char *a=h, *e=n; if( !h || !*h || !n || !*n ) { return 0; } @@ -49,6 +50,7 @@ char *strcasestr( char *h, char *n ) } return *e ? 0 : h; } +#endif static string* family_name(const string *font_name) { if (!font_name) return NULL; diff --git a/src/calibre/ebooks/pdf/images.cpp b/src/calibre/ebooks/pdf/images.cpp index 2221c06900..2899da8307 100644 --- a/src/calibre/ebooks/pdf/images.cpp +++ b/src/calibre/ebooks/pdf/images.cpp @@ -10,6 +10,10 @@ #include "images.h" #include "utils.h" +#ifdef _WIN32 +inline double round(double x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); } +#endif + #define xoutRound(x) ( static_cast(round(x)) ) using namespace std; using namespace calibre_reflow; @@ -287,3 +291,134 @@ void PNGWriter::write_splash_bitmap(SplashBitmap *bitmap) { this->writePointers(row_pointers); delete[] row_pointers; } + +void calibre_png_mem_write(png_structp png_ptr, png_bytep data, png_size_t length) { + if (!png_ptr || length < 1) return; + vector *buf = static_cast< vector* >(png_ptr->io_ptr); + buf->reserve(buf->capacity() + length); + do { + buf->push_back(static_cast(*data)); + data++; length--; + } while(length > 0); +} + +void calibre_png_mem_flush(png_structp png_ptr) {} + +void PNGMemWriter::init(vector *buf, int width, int height) { + /* initialize stuff */ + this->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!this->png_ptr) + throw ReflowException("png_create_write_struct failed"); + + this->info_ptr = png_create_info_struct(png_ptr); + if (!this->info_ptr) + throw ReflowException("png_create_info_struct failed"); + + if (setjmp(png_jmpbuf(this->png_ptr))) + throw ReflowException("png_jmpbuf failed"); + + png_set_write_fn(this->png_ptr, static_cast(buf), + calibre_png_mem_write, calibre_png_mem_flush); + if (setjmp(png_jmpbuf(this->png_ptr))) + throw ReflowException("png_set_write failed"); + + + // Set up the type of PNG image and the compression level + png_set_compression_level(this->png_ptr, Z_BEST_COMPRESSION); + + png_byte bit_depth = 8; + png_byte color_type = PNG_COLOR_TYPE_RGB; + png_byte interlace_type = PNG_INTERLACE_NONE; + + png_set_IHDR(this->png_ptr, this->info_ptr, width, height, + bit_depth, color_type, interlace_type, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png_ptr, info_ptr); + if (setjmp(png_jmpbuf(png_ptr))) + throw ReflowException("error during writing png info bytes"); + +} + + +void calibre_jpeg_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + calibre_jpeg_err_mgr *err = (calibre_jpeg_err_mgr *)(cinfo->err); + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + //(*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(err->setjmp_buffer, 1); +} + + +JPEGWriter::JPEGWriter() { + this->cinfo.err = jpeg_std_error(&this->jerr.pub); + jpeg_create_compress(&this->cinfo); + this->jerr.pub.error_exit = calibre_jpeg_error_exit; + this->check(); + this->outfile = NULL; +} + +void JPEGWriter::init(int width, int height) { + cinfo.image_width = width; + cinfo.image_height = height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; + jpeg_set_defaults(&this->cinfo); + this->check(); + jpeg_start_compress(&this->cinfo, TRUE); + this->check(); +} + +void JPEGWriter::init_io(FILE *f) { + jpeg_stdio_dest(&this->cinfo, f); + this->check(); + this->outfile = f; +} + +void JPEGWriter::check() { + if (setjmp(jerr.setjmp_buffer)) this->raise(); +} + +void JPEGWriter::raise() { + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*this->cinfo.err->format_message) ((jpeg_common_struct *)(&this->cinfo), buffer); + jpeg_destroy_compress(&this->cinfo); + throw ReflowException(buffer); +} + +void JPEGWriter::write_image(JSAMPARRAY image_buffer, JDIMENSION num) { + size_t num_written = jpeg_write_scanlines(&this->cinfo, image_buffer, num); + this->check(); + if (num_written != num) { + jpeg_destroy_compress(&this->cinfo); + throw ReflowException("Failed to write all JPEG scanlines."); + } +} + +void JPEGWriter::write_splash_bitmap(SplashBitmap *bitmap) { + SplashColorPtr row = bitmap->getDataPtr(); + int height = bitmap->getHeight(); + int row_size = bitmap->getRowSize(); + JSAMPARRAY row_pointers = new JSAMPLE*[height]; + + for (int y = 0; y < height; ++y) { + row_pointers[y] = row; + row += row_size; + } + this->write_image(row_pointers, height); + delete[] row_pointers; + jpeg_finish_compress(&this->cinfo); + this->check(); + fclose(this->outfile); +} + +JPEGWriter::~JPEGWriter() { + jpeg_destroy_compress(&this->cinfo); +} diff --git a/src/calibre/ebooks/pdf/images.h b/src/calibre/ebooks/pdf/images.h index b403abe4fb..b6e8407ac9 100644 --- a/src/calibre/ebooks/pdf/images.h +++ b/src/calibre/ebooks/pdf/images.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include "utils.h" using namespace std; @@ -27,11 +29,19 @@ namespace calibre_reflow { void write_splash_bitmap(SplashBitmap *bitmap); void close(); - private: + protected: png_structp png_ptr; png_infop info_ptr; }; + + class PNGMemWriter : public PNGWriter + { + + public: + void init(vector *buf, int width, int height); + }; + class ImageInfo { public: @@ -89,6 +99,32 @@ namespace calibre_reflow { vector str() const; void clear(); }; + + struct calibre_jpeg_err_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ + }; + + class JPEGWriter { + private: + FILE *outfile; + + protected: + struct jpeg_compress_struct cinfo; + struct calibre_jpeg_err_mgr jerr; + + void raise(); + void check(); + + public: + JPEGWriter(); + ~JPEGWriter(); + void init_io(FILE *f); + void init(int width, int height); + void write_image(JSAMPARRAY image_buffer, JDIMENSION number_of_scanlines); + void write_splash_bitmap(SplashBitmap *bitmap); + }; } #endif diff --git a/src/calibre/ebooks/pdf/main.cpp b/src/calibre/ebooks/pdf/main.cpp index 96bb5ed853..bde406dd49 100644 --- a/src/calibre/ebooks/pdf/main.cpp +++ b/src/calibre/ebooks/pdf/main.cpp @@ -52,12 +52,14 @@ extern "C" { info = reflow.get_info(); if (PyObject_IsTrue(cover)) { if (!reflow.is_locked()) { - size_t size; - char *data = reflow.render_first_page(&size); - PyObject *d = PyString_FromStringAndSize(data, size); - delete[] data; - if (d == NULL) return PyErr_NoMemory(); - if (PyDict_SetItemString(ans, "cover", d) == -1) return NULL; + vector *data = reflow.render_first_page(); + if (data->size() > 0) { + PyObject *d = PyBytes_FromStringAndSize(&((*data)[0]), data->size()); + delete data; + if (d == NULL) return PyErr_NoMemory(); + if (PyDict_SetItemString(ans, "cover", d) == -1) return NULL; + Py_XDECREF(d); + } } else { if (PyDict_SetItemString(ans, "cover", Py_None) == -1) return NULL; } @@ -75,6 +77,7 @@ extern "C" { PyObject *val = PyUnicode_Decode((*it).second.c_str(), (*it).second.size(), "UTF-8", "replace"); if (!val) return NULL; if (PyDict_SetItem(ans, key, val) == -1) return NULL; + Py_XDECREF(key); Py_XDECREF(val); } return ans; } @@ -180,19 +183,21 @@ int main(int argc, char **argv) { return 1; } + int ret = 0; try { Reflow reflow(memblock, size); reflow.render(); - size_t sz = 0; - char *data = reflow.render_first_page(&sz); + vector *data = reflow.render_first_page(); ofstream file("cover.png", ios::binary); - file.write(data, sz); + file.write(&((*data)[0]), data->size()); + delete data; file.close(); } catch(exception &e) { cerr << e.what() << endl; - return 1; + ret = 1; } - return 0; + delete[] memblock; + return ret; } #endif diff --git a/src/calibre/ebooks/pdf/reflow.cpp b/src/calibre/ebooks/pdf/reflow.cpp index a494887bca..3b3dba4f34 100644 --- a/src/calibre/ebooks/pdf/reflow.cpp +++ b/src/calibre/ebooks/pdf/reflow.cpp @@ -3,7 +3,11 @@ * License: GNU GPL v3 */ +#ifdef _WIN32 +#include +#else #include +#endif #include #include #include @@ -683,11 +687,14 @@ void XMLOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, static char stream_pdf[15] = "stream.pdf"; class MemInStream : public MemStream { + private: + GooString stream_name; + public: MemInStream(char *buf, size_t st, size_t sz, Object *obj) : - MemStream(buf, st, sz, obj) {} + MemStream(buf, st, sz, obj), stream_name(stream_pdf) {} ~MemInStream() {} - GooString *getFileName() { return new GooString(stream_pdf); } + GooString *getFileName() { return &this->stream_name; } }; Reflow::Reflow(char *pdfdata, size_t sz) : @@ -861,8 +868,7 @@ string Reflow::decode_info_string(Dict *info, const char *key) const { return oss.str(); } -char* Reflow::render_first_page(size_t *data_size, - bool use_crop_box, double x_res, +vector* Reflow::render_first_page(bool use_crop_box, double x_res, double y_res) { if (this->is_locked()) throw ReflowException("Document is locked."); char encoding[10] = "UTF-8"; @@ -900,24 +906,14 @@ char* Reflow::render_first_page(size_t *data_size, this->doc->displayPageSlice(out, pg, x_res, y_res, 0, !use_crop_box, false, false, x, y, pg_w, pg_h); - FILE * f = tmpfile(); - if (!f) throw ReflowException(strerror(errno)); SplashBitmap *bmp = out->getBitmap(); - PNGWriter *writer = new PNGWriter(); - writer->init(f, bmp->getWidth(), bmp->getHeight()); - writer->write_splash_bitmap(bmp); - writer->close(); - delete writer; - - - long size = ftell(f); - rewind(f); - char *buffer = new char[size]; - *data_size = fread(buffer, 1, size, f); - if (*data_size != (size_t)size) { - throw ReflowException("I/O error reading from tmpfile"); - } - return buffer; + PNGMemWriter writer; + vector *buf = new vector(); + writer.init(buf, bmp->getWidth(), bmp->getHeight()); + writer.write_splash_bitmap(bmp); + writer.close(); + delete out; + return buf; } class MemOutStream : public OutStream { diff --git a/src/calibre/ebooks/pdf/reflow.h b/src/calibre/ebooks/pdf/reflow.h index cf17cd15ae..458d452b72 100644 --- a/src/calibre/ebooks/pdf/reflow.h +++ b/src/calibre/ebooks/pdf/reflow.h @@ -68,8 +68,7 @@ class Reflow { bool is_locked() const { return !this->doc || this->doc->isEncrypted(); } /* Return the first page of the PDF, rendered as a PNG image */ - char* render_first_page(size_t *data_size, - bool use_crop_box=true, double x_res=150.0, + vector* render_first_page(bool use_crop_box=true, double x_res=150.0, double y_res = 150.0); /* Dump the PDF outline as the file outline.xml in the current directory */