mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
IGN:Fix a memory leak in the new PDF get_metadata code, remove use of tmpfile and make it build on windows
This commit is contained in:
parent
9d292633c7
commit
73801dd2ae
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)))
|
||||
|
@ -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;
|
||||
|
@ -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<int>(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<char> *buf = static_cast< vector<char>* >(png_ptr->io_ptr);
|
||||
buf->reserve(buf->capacity() + length);
|
||||
do {
|
||||
buf->push_back(static_cast<char>(*data));
|
||||
data++; length--;
|
||||
} while(length > 0);
|
||||
}
|
||||
|
||||
void calibre_png_mem_flush(png_structp png_ptr) {}
|
||||
|
||||
void PNGMemWriter::init(vector<char> *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<void *>(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);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <GfxState.h>
|
||||
#include <splash/SplashBitmap.h>
|
||||
#include <png.h>
|
||||
#include <jpeglib.h>
|
||||
#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<char> *buf, int width, int height);
|
||||
};
|
||||
|
||||
class ImageInfo {
|
||||
public:
|
||||
|
||||
@ -89,6 +99,32 @@ namespace calibre_reflow {
|
||||
vector<string*> 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
|
||||
|
@ -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<char> *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<char> *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
|
||||
|
@ -3,7 +3,11 @@
|
||||
* License: GNU GPL v3
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <poppler/Object.h>
|
||||
#else
|
||||
#include <Object.h>
|
||||
#endif
|
||||
#include <Outline.h>
|
||||
#include <PDFDocEncoding.h>
|
||||
#include <goo/GooList.h>
|
||||
@ -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<char>* 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<char> *buf = new vector<char>();
|
||||
writer.init(buf, bmp->getWidth(), bmp->getHeight());
|
||||
writer.write_splash_bitmap(bmp);
|
||||
writer.close();
|
||||
delete out;
|
||||
return buf;
|
||||
}
|
||||
|
||||
class MemOutStream : public OutStream {
|
||||
|
@ -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<char>* 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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user