From 580c48fef10df9184cf2728338e89f7db0fef2f5 Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Sat, 15 Aug 2009 22:39:16 +0200 Subject: [PATCH] added pdf2pdf tool --- .gitignore | 1 + config.h.in | 7 +- configure | 98 +++++++++++++++++- configure.in | 21 +++- lib/Makefile.in | 8 +- lib/devices/pdf.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++ lib/devices/pdf.h | 37 +++++++ lib/devices/polyops.c | 6 +- lib/gfxpoly/active.c | 2 +- lib/pdf/GFXOutputDev.cc | 26 +++-- lib/pdf/GFXOutputDev.h | 5 +- lib/q.h | 1 + src/Makefile.in | 9 +- src/pdf2pdf.c | 233 +++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 682 insertions(+), 26 deletions(-) create mode 100644 lib/devices/pdf.c create mode 100644 lib/devices/pdf.h create mode 100644 src/pdf2pdf.c diff --git a/.gitignore b/.gitignore index f7baca2..4b7b50e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ swfstrings swfc swfbbox font2swf +src/pdf2pdf gif2swf pdf2swf as3compile diff --git a/config.h.in b/config.h.in index 57052d9..e91ada7 100644 --- a/config.h.in +++ b/config.h.in @@ -130,6 +130,9 @@ /* Define if you have the header file. */ #undef HAVE_ZLIB_H +/* Define if you have the header file. */ +#undef HAVE_PDFLIB_H + /* Define if you have the header file. */ #undef HAVE_AVIFILE_VERSION_H @@ -161,9 +164,11 @@ #undef HAVE_OUTPUTDEV_H /* Define if you have the jpeg library (-ljpeg). */ -/* Define if you have the jpeg library (-ljpeg). */ #undef HAVE_LIBJPEG +/* Define if you have the jpeg library (-ljpeg). */ +#undef HAVE_LIBPDF + /* Define if you have the m library (-lm). */ #undef HAVE_LIBM diff --git a/configure b/configure index 28644c5..c804ce3 100755 --- a/configure +++ b/configure @@ -640,6 +640,8 @@ LIBOBJS PNG2SWF GIF2SWF JPEG2SWF +PDF2PDF +DEVICE_PDF LIBPDF PDF2SWF HAVE_PYTHON_IMAGING @@ -4288,6 +4290,83 @@ if test "x$ZLIBMISSING" = "xtrue";then fi +{ $as_echo "$as_me:$LINENO: checking for PDF_open_file in -lpdf" >&5 +$as_echo_n "checking for PDF_open_file in -lpdf... " >&6; } +if test "${ac_cv_lib_pdf_PDF_open_file+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpdf $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char PDF_open_file (); +int +main () +{ +return PDF_open_file (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_pdf_PDF_open_file=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pdf_PDF_open_file=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pdf_PDF_open_file" >&5 +$as_echo "$ac_cv_lib_pdf_PDF_open_file" >&6; } +if test "x$ac_cv_lib_pdf_PDF_open_file" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPDF 1 +_ACEOF + + LIBS="-lpdf $LIBS" + +else + PDFLIBMISSING=true +fi + + { $as_echo "$as_me:$LINENO: checking for jpeg_write_raw_data in -ljpeg" >&5 $as_echo_n "checking for jpeg_write_raw_data in -ljpeg... " >&6; } if test "${ac_cv_lib_jpeg_jpeg_write_raw_data+set}" = set; then @@ -5417,7 +5496,8 @@ done -for ac_header in zlib.h gif_lib.h io.h wchar.h jpeglib.h assert.h signal.h pthread.h sys/stat.h sys/mman.h sys/types.h dirent.h sys/bsdtypes.h sys/ndir.h sys/dir.h ndir.h time.h sys/time.h sys/resource.h + +for ac_header in zlib.h gif_lib.h io.h wchar.h jpeglib.h assert.h signal.h pthread.h sys/stat.h sys/mman.h sys/types.h dirent.h sys/bsdtypes.h sys/ndir.h sys/dir.h ndir.h time.h sys/time.h sys/resource.h pdflib.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then @@ -10122,6 +10202,9 @@ if test "x$JPEGLIBMISSING" = "xtrue";then DISABLEJPEG2SWF=true PARTIAL=true fi +if test "x$PDFLIBMISSING" = "xtrue";then + DISABLEPDF2PDF=true; +fi #if test "x$T1LIBMISSING" = "xtrue";then # MISSINGLIBS="${MISSINGLIBS} t1lib" #fi @@ -10131,6 +10214,9 @@ if test "x$UNGIFMISSING" = "xtrue";then PARTIAL=true fi +if test "x${ac_cv_header_pdflib_h}" '!=' "xyes";then + DISABLEPDF2PDF=true; +fi if test "x${ac_cv_header_jpeglib_h}" '!=' "xyes"; then DISABLEPDF2SWF=true; DISABLEJPEG2SWF=true; @@ -10192,6 +10278,16 @@ fi +PDF2PDF='pdf2pdf$(E)' +DEVICE_PDF='devices/pdf.$(O)' +if test "x${DISABLEPDF2PDF}" = "xtrue"; then + #echo "* Disabling pdf2pdf tool..." + PDF2PDF= + DEVICE_PDF= +fi + + + if test "x${ZLIBMISSING}" = "xtrue"; then echo echo "* Warning! Without zlib, you will not be able to read" diff --git a/configure.in b/configure.in index 4c05912..5dae635 100644 --- a/configure.in +++ b/configure.in @@ -223,7 +223,8 @@ if test "x$ZLIBMISSING" = "xtrue";then echo exit fi - + +AC_CHECK_LIB(pdf, PDF_open_file,, PDFLIBMISSING=true) AC_CHECK_LIB(jpeg, jpeg_write_raw_data,, JPEGLIBMISSING=true) AC_CHECK_LIB(ungif, DGifOpen,, UNGIFMISSING=true) if test "$UNGIFMISSING";then @@ -243,7 +244,7 @@ dnl Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC - AC_CHECK_HEADERS(zlib.h gif_lib.h io.h wchar.h jpeglib.h assert.h signal.h pthread.h sys/stat.h sys/mman.h sys/types.h dirent.h sys/bsdtypes.h sys/ndir.h sys/dir.h ndir.h time.h sys/time.h sys/resource.h) + AC_CHECK_HEADERS(zlib.h gif_lib.h io.h wchar.h jpeglib.h assert.h signal.h pthread.h sys/stat.h sys/mman.h sys/types.h dirent.h sys/bsdtypes.h sys/ndir.h sys/dir.h ndir.h time.h sys/time.h sys/resource.h pdflib.h) AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package]) @@ -389,6 +390,9 @@ if test "x$JPEGLIBMISSING" = "xtrue";then DISABLEJPEG2SWF=true PARTIAL=true fi +if test "x$PDFLIBMISSING" = "xtrue";then + DISABLEPDF2PDF=true; +fi #if test "x$T1LIBMISSING" = "xtrue";then # MISSINGLIBS="${MISSINGLIBS} t1lib" #fi @@ -398,6 +402,9 @@ if test "x$UNGIFMISSING" = "xtrue";then PARTIAL=true fi +if test "x${ac_cv_header_pdflib_h}" '!=' "xyes";then + DISABLEPDF2PDF=true; +fi if test "x${ac_cv_header_jpeglib_h}" '!=' "xyes"; then DISABLEPDF2SWF=true; DISABLEJPEG2SWF=true; @@ -458,6 +465,16 @@ fi AC_SUBST(PDF2SWF) AC_SUBST(LIBPDF) +PDF2PDF='pdf2pdf$(E)' +DEVICE_PDF='devices/pdf.$(O)' +if test "x${DISABLEPDF2PDF}" = "xtrue"; then + #echo "* Disabling pdf2pdf tool..." + PDF2PDF= + DEVICE_PDF= +fi +AC_SUBST(DEVICE_PDF) +AC_SUBST(PDF2PDF) + if test "x${ZLIBMISSING}" = "xtrue"; then echo echo "* Warning! Without zlib, you will not be able to read" diff --git a/lib/Makefile.in b/lib/Makefile.in index 8a5ac6c..e1d2295 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -3,9 +3,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ include ../Makefile.common -DEVICES = devices/swf.$(O) #devices/lrf.$(O) devices/opengl.$(O) - -all: librfxswf$(A) libpdf$(A) libbase$(A) libgfx$(A) libgfxswf$(A) libocr$(A) $(DEVICES) +all: librfxswf$(A) libpdf$(A) libbase$(A) libgfx$(A) libgfxswf$(A) libocr$(A) lame_objects = lame/psymodel.$(O) lame/fft.$(O) lame/newmdct.$(O) lame/quantize.$(O) lame/takehiro.$(O) lame/reservoir.$(O) lame/quantize_pvt.$(O) lame/vbrquantize.$(O) lame/encoder.$(O) lame/id3tag.$(O) lame/version.$(O) lame/tables.$(O) lame/util.$(O) lame/bitstream.$(O) lame/set_get.$(O) lame/VbrTag.$(O) lame/lame.$(O) lame_in_source = @lame_in_source@ @@ -21,7 +19,7 @@ gfxpoly_objects = gfxpoly/active.$(O) gfxpoly/convert.$(O) gfxpoly/poly.$(O) gfx rfxswf_modules = modules/swfbits.c modules/swfaction.c modules/swfdump.c modules/swfcgi.c modules/swfbutton.c modules/swftext.c modules/swffont.c modules/swftools.c modules/swfsound.c modules/swfshape.c modules/swfobject.c modules/swfdraw.c modules/swffilter.c modules/swfrender.c h.263/swfvideo.c base_objects=q.$(O) utf8.$(O) png.$(O) jpeg.$(O) wav.$(O) mp3.$(O) os.$(O) bitio.$(O) log.$(O) mem.$(O) -gfx_objects=gfxtools.$(O) gfxfont.$(O) devices/dummy.$(O) devices/file.$(O) devices/render.$(O) devices/text.$(O) devices/record.$(O) devices/ops.$(O) devices/polyops.$(O) devices/bbox.$(O) devices/rescale.$(O) @DEVICE_OPENGL@ +gfx_objects=gfxtools.$(O) gfxfont.$(O) devices/dummy.$(O) devices/file.$(O) devices/render.$(O) devices/text.$(O) devices/record.$(O) devices/ops.$(O) devices/polyops.$(O) devices/bbox.$(O) devices/rescale.$(O) @DEVICE_OPENGL@ @DEVICE_PDF@ rfxswf_objects=modules/swfaction.$(O) modules/swfbits.$(O) modules/swfbutton.$(O) modules/swfcgi.$(O) modules/swfdraw.$(O) modules/swfdump.$(O) modules/swffilter.$(O) modules/swffont.$(O) modules/swfobject.$(O) modules/swfrender.$(O) modules/swfshape.$(O) modules/swfsound.$(O) modules/swftext.$(O) modules/swftools.$(O) ocr_objects=gocr/box.$(O) gocr/database.$(O) gocr/detect.$(O) gocr/job.$(O) gocr/lines.$(O) gocr/list.$(O) gocr/ocr0.$(O) gocr/ocr0n.$(O) gocr/ocr1.$(O) gocr/otsu.$(O) gocr/output.$(O) gocr/pgm2asc.$(O) gocr/pixel.$(O) gocr/progress.$(O) gocr/remove.$(O) gocr/unicode.$(O) @@ -168,7 +166,7 @@ uninstall: clean: rm -f *.o *.obj *.lo *.a *.lib *.la gmon.out - for dir in modules devices swf as3 h.263;do rm -f $$dir/*.o $$dir/*.obj $$dir/*.lo $$dir/*.a $$dir/*.lib $$dir/*.la $$dir/gmon.out;done + for dir in modules devices swf as3 h.263 gfxpoly;do rm -f $$dir/*.o $$dir/*.obj $$dir/*.lo $$dir/*.a $$dir/*.lib $$dir/*.la $$dir/gmon.out;done cd lame && $(MAKE) clean && cd .. || true cd action && $(MAKE) clean && cd .. cd python && $(MAKE) clean && cd .. diff --git a/lib/devices/pdf.c b/lib/devices/pdf.c new file mode 100644 index 0000000..720abd1 --- /dev/null +++ b/lib/devices/pdf.c @@ -0,0 +1,254 @@ +/* pdf.c + + Part of the swftools package. + + Copyright (c) 2007 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include +#include +#include +#include "../types.h" +#include "../mem.h" +#include "../gfxdevice.h" +#include "../gfxtools.h" + +typedef struct _internal { + PDF* p; + char*tempfile; +} internal_t; + +int pdf_setparameter(gfxdevice_t*dev, const char*key, const char*value) +{ + internal_t*i = (internal_t*)dev->internal; + return 0; +} + +void pdf_startpage(gfxdevice_t*dev, int width, int height) +{ + internal_t*i = (internal_t*)dev->internal; + + i->tempfile = strdup("tmp.pdf"); + PDF_open_file(i->p, i->tempfile); + PDF_set_parameter(i->p, "usercoordinates", "true"); + PDF_set_parameter(i->p, "topdown", "true"); + PDF_begin_page(i->p, width, height); + PDF_set_parameter(i->p, "fillrule", "evenodd"); +} + +static int mkline(gfxline_t*line, PDF*p) +{ + int ret = 0; + double x=0,y=0; + while(line) { + if(line->type == gfx_moveTo) { + PDF_moveto(p, line->x, line->y); + } else if(line->type == gfx_lineTo) { + PDF_lineto(p, line->x, line->y); + ret = 1; + } else { + /* when converting a quadratic bezier to a cubic bezier, the + two new control points are both 2/3 the way from the + endpoints to the old control point */ + double c1x = (x + line->sx*2)/3; + double c1y = (y + line->sy*2)/3; + double c2x = (line->x + line->sx*2)/3; + double c2y = (line->y + line->sy*2)/3; + PDF_curveto(p, c1x, c1y, c2x, c2y, line->x, line->y); + ret = 1; + } + x = line->x; + y = line->y; + line = line->next; + } + return ret; +} + +void pdf_startclip(gfxdevice_t*dev, gfxline_t*line) +{ + internal_t*i = (internal_t*)dev->internal; + PDF_save(i->p); + PDF_set_parameter(i->p, "fillrule", "evenodd"); + if(mkline(line, i->p)) + PDF_clip(i->p); + else + ; // TODO: not sure about this + +} +void pdf_endclip(gfxdevice_t*dev) +{ + internal_t*i = (internal_t*)dev->internal; + PDF_restore(i->p); +} +void pdf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) +{ + internal_t*i = (internal_t*)dev->internal; + PDF_setlinewidth(i->p, width); + PDF_setlinecap(i->p, cap_style==gfx_capButt?0:(cap_style==gfx_capRound?1:2)); + PDF_setlinejoin(i->p, joint_style==gfx_joinMiter?0:(joint_style==gfx_joinRound?1:2)); + PDF_setrgbcolor_stroke(i->p, color->r/255.0, color->g/255.0, color->b/255.0); + if(joint_style==gfx_joinMiter) + PDF_setmiterlimit(i->p, miterLimit); + if(mkline(line, i->p)) + PDF_stroke(i->p); +} + +void pdf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) +{ + internal_t*i = (internal_t*)dev->internal; + PDF_setrgbcolor_fill(i->p, color->r/255.0, color->g/255.0, color->b/255.0); + PDF_set_parameter(i->p, "fillrule", "evenodd"); + + if(mkline(line, i->p)) { + PDF_fill(i->p); + } +} + +void pdf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) +{ + internal_t*i = (internal_t*)dev->internal; + + //PDFLIB_API int PDFLIB_CALL + //PDF_load_image(i->pPDF *p, const char *imagetype, const char *filename, int len, const char *optlist); +} + +void pdf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) +{ + internal_t*i = (internal_t*)dev->internal; +} + +void pdf_addfont(gfxdevice_t*dev, gfxfont_t*font) +{ + internal_t*i = (internal_t*)dev->internal; +} + +void pdf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) +{ + internal_t*i = (internal_t*)dev->internal; + if(!font) + return; + /* align characters to whole pixels */ + matrix->tx = (int)matrix->tx; + matrix->ty = (int)matrix->ty; + + gfxglyph_t*glyph = &font->glyphs[glyphnr]; + gfxline_t*line2 = gfxline_clone(glyph->line); + gfxline_transform(line2, matrix); + PDF_setrgbcolor_fill(i->p, color->r/255.0, color->g/255.0, color->b/255.0); + PDF_set_parameter(i->p, "fillrule", "evenodd"); + + if(mkline(line2, i->p)) { + PDF_fill(i->p); + } + gfxline_free(line2); + return; +} + +void pdf_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action) +{ + internal_t*i = (internal_t*)dev->internal; +} + +void pdf_endpage(gfxdevice_t*dev) +{ + internal_t*i = (internal_t*)dev->internal; + PDF_end_page(i->p); + PDF_close(i->p); + PDF_delete(i->p); +} + +typedef struct pdfresult_internal { + char*tempfile; +} pdfresult_internal_t; + +void pdfresult_destroy(gfxresult_t*gfx) +{ + pdfresult_internal_t*i = (pdfresult_internal_t*)gfx->internal; + free(i->tempfile); + free(gfx->internal);gfx->internal = 0; + free(gfx); +} + +int pdfresult_save(gfxresult_t*gfx, const char*filename) +{ + pdfresult_internal_t*i = (pdfresult_internal_t*)gfx->internal; + FILE*fi = fopen(i->tempfile, "rb"); + FILE*fo = fopen(filename, "wb"); + if(!fo) { + perror(filename); + return -1; + } + char buffer[4096]; + int size = 0; + while((size = fread(buffer, 1, 4096, fi))) { + fwrite(buffer, 1, size, fo); + } + fclose(fi); + fclose(fo); + return 0; +} + +void* pdfresult_get(gfxresult_t*gfx, const char*name) +{ + return 0; +} + +gfxresult_t* pdf_finish(gfxdevice_t*dev) +{ + internal_t*i = (internal_t*)dev->internal; + + gfxresult_t*result = (gfxresult_t*)malloc(sizeof(gfxresult_t)); + memset(result, 0, sizeof(gfxresult_t)); + result->save = pdfresult_save; + result->get = pdfresult_get; + result->destroy = pdfresult_destroy; + result->internal = 0; + result->internal = malloc(sizeof(pdfresult_internal_t)); + pdfresult_internal_t*ri = (pdfresult_internal_t*)result->internal; + ri->tempfile = i->tempfile;i->tempfile=0; + free(dev->internal);dev->internal = 0;i=0; + return result; +} + +void gfxdevice_pdf_init(gfxdevice_t*dev) +{ + internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t)); + memset(dev, 0, sizeof(gfxdevice_t)); + + dev->name = "pdf"; + + dev->internal = i; + + dev->setparameter = pdf_setparameter; + dev->startpage = pdf_startpage; + dev->startclip = pdf_startclip; + dev->endclip = pdf_endclip; + dev->stroke = pdf_stroke; + dev->fill = pdf_fill; + dev->fillbitmap = pdf_fillbitmap; + dev->fillgradient = pdf_fillgradient; + dev->addfont = pdf_addfont; + dev->drawchar = pdf_drawchar; + dev->drawlink = pdf_drawlink; + dev->endpage = pdf_endpage; + dev->finish = pdf_finish; + + i->p = PDF_new(); +} + diff --git a/lib/devices/pdf.h b/lib/devices/pdf.h new file mode 100644 index 0000000..e64ca7e --- /dev/null +++ b/lib/devices/pdf.h @@ -0,0 +1,37 @@ +/* pdf.h + Header file for pdf.c + + Part of the swftools package. + + Copyright (c) 2009 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __gfxdevice_pdf_h__ +#define __gfxdevice_pdf_h__ + +#include "../gfxdevice.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxdevice_pdf_init(gfxdevice_t*dev); + +#ifdef __cplusplus +} +#endif + +#endif //__gfxdevice_pdf_h__ diff --git a/lib/devices/polyops.c b/lib/devices/polyops.c index fea200b..de03533 100644 --- a/lib/devices/polyops.c +++ b/lib/devices/polyops.c @@ -105,7 +105,11 @@ void polyops_startclip(struct _gfxdevice*dev, gfxline_t*line) a gfxline into a gfxpoly- for polygons which are too complex or just degenerate, this might fail. So handle all the cases where polygon conversion or intersection - might go awry */ + might go awry + UPDATE: this is not needed anymore. The new gfxpoly + implementation is stable enough so it always returns + a valid result. Still, it's good practice. + */ if(!poly && !oldclip) { i->out->startclip(i->out,line); currentclip = 0; diff --git a/lib/gfxpoly/active.c b/lib/gfxpoly/active.c index e9270e4..2904e08 100644 --- a/lib/gfxpoly/active.c +++ b/lib/gfxpoly/active.c @@ -375,7 +375,7 @@ static void move_to_root(actlist_t*a, segment_t*s) } } -static int actlist_splay(actlist_t*a, point_t p1, point_t p2) +static void actlist_splay(actlist_t*a, point_t p1, point_t p2) { if(!a->list) return; diff --git a/lib/pdf/GFXOutputDev.cc b/lib/pdf/GFXOutputDev.cc index 6c4a3a9..2d80cb2 100644 --- a/lib/pdf/GFXOutputDev.cc +++ b/lib/pdf/GFXOutputDev.cc @@ -599,6 +599,7 @@ GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc) this->config_remapunicode=0; this->config_transparent=0; this->config_extrafontdata = 0; + this->config_drawonlyshapes = 0; this->config_disable_polygon_conversion = 0; this->config_multiply = 1; this->page2page = 0; @@ -615,6 +616,8 @@ void GFXOutputDev::setParameter(const char*key, const char*value) this->config_remapunicode = atoi(value); } else if(!strcmp(key,"transparent")) { this->config_transparent = atoi(value); + } else if(!strcmp(key,"drawonlyshapes")) { + this->config_drawonlyshapes = atoi(value); } else if(!strcmp(key,"extrafontdata")) { this->config_extrafontdata = atoi(value); } else if(!strcmp(key,"convertgradients")) { @@ -1219,20 +1222,21 @@ gfxcolor_t getFillColor(GfxState * state) return col; } -void GFXOutputDev::fillGfxLine(GfxState *state, gfxline_t*line) +void GFXOutputDev::fillGfxLine(GfxState *state, gfxline_t*line, char evenodd) { gfxcolor_t col = getFillColor(state); if(getLogLevel() >= LOGLEVEL_TRACE) { - msg(" fill %02x%02x%02x%02x", col.r, col.g, col.b, col.a); + msg(" %sfill %02x%02x%02x%02x%s", evenodd?"eo":"", col.r, col.g, col.b, col.a); dump_outline(line); } device->fill(device, line, &col); } -void GFXOutputDev::clipToGfxLine(GfxState *state, gfxline_t*line) +void GFXOutputDev::clipToGfxLine(GfxState *state, gfxline_t*line, char evenodd) { if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" %sclip", evenodd?"eo":""); dump_outline(line); } gfxbbox_t bbox = gfxline_getbbox(line); @@ -1252,7 +1256,7 @@ void GFXOutputDev::clip(GfxState *state) gfxline_free(line); line = line2; } - clipToGfxLine(state, line); + clipToGfxLine(state, line, 0); gfxline_free(line); } @@ -1260,7 +1264,7 @@ void GFXOutputDev::eoClip(GfxState *state) { GfxPath * path = state->getPath(); gfxline_t*line = gfxPath_to_gfxline(state, path, 1, user_movex + clipmovex, user_movey + clipmovey); - clipToGfxLine(state, line); + clipToGfxLine(state, line, 1); gfxline_free(line); } void GFXOutputDev::clipToStrokePath(GfxState *state) @@ -1415,7 +1419,7 @@ void GFXOutputDev::drawChar(GfxState *state, double x, double y, msg(" drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d render=%d glyphid=%d font=%08x",m.tx,m.ty,(charid&127)>=32?charid:'?', charid, u, uLen, font->isCIDFont(), render, glyphid, current_gfxfont); - if(render == RENDER_FILL || render == RENDER_INVISIBLE) { + if((render == RENDER_FILL && !config_drawonlyshapes) || render == RENDER_INVISIBLE) { device->drawchar(device, current_gfxfont, glyphid, &col, &m); } else { msg(" Drawing glyph %d as shape", charid); @@ -1453,11 +1457,11 @@ void GFXOutputDev::endString(GfxState *state) however */ device->setparameter(device, "mark","TXT"); if((render&3) == RENDER_FILL) { - fillGfxLine(state, current_text_stroke); + fillGfxLine(state, current_text_stroke, 0); gfxline_free(current_text_stroke); current_text_stroke = 0; } else if((render&3) == RENDER_FILLSTROKE) { - fillGfxLine(state, current_text_stroke); + fillGfxLine(state, current_text_stroke, 0); strokeGfxline(state, current_text_stroke,0); gfxline_free(current_text_stroke); current_text_stroke = 0; @@ -1477,7 +1481,7 @@ void GFXOutputDev::endTextObject(GfxState *state) if(current_text_clip) { device->setparameter(device, "mark","TXT"); - clipToGfxLine(state, current_text_clip); + clipToGfxLine(state, current_text_clip, 0); device->setparameter(device, "mark",""); gfxline_free(current_text_clip); current_text_clip = 0; @@ -2473,7 +2477,7 @@ void GFXOutputDev::fill(GfxState *state) gfxline_free(line); line = line2; } - fillGfxLine(state, line); + fillGfxLine(state, line, 0); gfxline_free(line); } @@ -2484,7 +2488,7 @@ void GFXOutputDev::eoFill(GfxState *state) GfxPath * path = state->getPath(); gfxline_t*line= gfxPath_to_gfxline(state, path, 1, user_movex + clipmovex, user_movey + clipmovey); - fillGfxLine(state, line); + fillGfxLine(state, line, 1); gfxline_free(line); } diff --git a/lib/pdf/GFXOutputDev.h b/lib/pdf/GFXOutputDev.h index 1a820a7..0b07e4f 100644 --- a/lib/pdf/GFXOutputDev.h +++ b/lib/pdf/GFXOutputDev.h @@ -228,8 +228,8 @@ public: Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap); void strokeGfxline(GfxState *state, gfxline_t*line, int flags); - void clipToGfxLine(GfxState *state, gfxline_t*line); - void fillGfxLine(GfxState *state, gfxline_t*line); + void clipToGfxLine(GfxState *state, gfxline_t*line, char evenodd); + void fillGfxLine(GfxState *state, gfxline_t*line, char evenodd); gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src); @@ -284,6 +284,7 @@ public: int config_disable_polygon_conversion; int config_multiply; int config_bigchar; + int config_drawonlyshapes; double config_fontquality; }; diff --git a/lib/q.h b/lib/q.h index df1c074..585d420 100644 --- a/lib/q.h +++ b/lib/q.h @@ -23,6 +23,7 @@ #define __q_h__ #include +#include "mem.h" #ifdef __cplusplus extern "C" { diff --git a/src/Makefile.in b/src/Makefile.in index 3bb42bb..3304e62 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -3,7 +3,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ include ../Makefile.common -programs = wav2swf$(E) @PNG2SWF@ swfcombine$(E) swfstrings$(E) swfextract$(E) swfdump$(E) swfc$(E) @JPEG2SWF@ @GIF2SWF@ swfbbox$(E) font2swf$(E) swfrender$(E) as3compile$(E) @PDF2SWF@ +programs = wav2swf$(E) @PNG2SWF@ swfcombine$(E) swfstrings$(E) swfextract$(E) swfdump$(E) swfc$(E) @JPEG2SWF@ @GIF2SWF@ swfbbox$(E) font2swf$(E) swfrender$(E) as3compile$(E) @PDF2SWF@ @PDF2PDF@ opt_programs = swfbytes$(E) all: $(programs) @@ -14,6 +14,8 @@ png2swf.$(O): png2swf.c $(C) png2swf.c -o $@ pdf2swf.$(O): pdf2swf.c $(C) pdf2swf.c -o $@ +pdf2pdf.$(O): pdf2pdf.c + $(C) pdf2pdf.c -o $@ gif2swf.$(O): gif2swf.c $(C) gif2swf.c -o $@ swfcombine.$(O): swfcombine.c @@ -99,10 +101,13 @@ swfrender$(E): swfrender.$(O) ../lib/librfxswf$(A) ../lib/libgfx$(A) ../lib/libb $(L) swfrender.$(O) -o $@ ../lib/librfxswf$(A) ../lib/libgfx$(A) ../lib/libgfxswf$(A) ../lib/libbase$(A) $(LIBS) $(STRIP) $@ -PDF2SWF_OBJ=../lib/libpdf$(A) ../lib/devices/polyops.$(O) ../lib/devices/swf.$(O) ../lib/librfxswf$(A) ../lib/libgfx$(A) ../lib/libbase$(A) +PDF2SWF_OBJ=../lib/libgfxswf$(A) ../lib/librfxswf$(A) ../lib/libpdf$(A) ../lib/libgfx$(A) ../lib/libbase$(A) pdf2swf$(E): pdf2swf.$(O) $(PDF2SWF_OBJ) $(LL) pdf2swf.$(O) -o $@ $(PDF2SWF_OBJ) $(LIBS) $(CXXLIBS) $(STRIP) $@ +pdf2pdf$(E): pdf2pdf.$(O) $(PDF2SWF_OBJ) + $(LL) pdf2pdf.$(O) -o $@ $(PDF2SWF_OBJ) $(LIBS) $(CXXLIBS) + $(STRIP) $@ swfc$(E): parser.$(O) swfc.$(O) swfc-feedback.$(O) swfc-history.$(O) swfc-interpolation.$(O) ../lib/librfxswf$(A) ../lib/libbase$(A) $(L) parser.$(O) swfc.$(O) swfc-feedback.$(O) swfc-history.$(O) swfc-interpolation.$(O) -o $@ ../lib/librfxswf$(A) ../lib/libbase$(A) $(LIBS) $(STRIP) $@ diff --git a/src/pdf2pdf.c b/src/pdf2pdf.c new file mode 100644 index 0000000..f642df6 --- /dev/null +++ b/src/pdf2pdf.c @@ -0,0 +1,233 @@ +/* pdf2pdf.c + main routine for pdf2pdf(1) + + Part of the swftools package. + + Copyright (c) 2009 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include +#include +#include "../config.h" +#include "../lib/args.h" +#include "../lib/os.h" +#include "../lib/gfxsource.h" +#include "../lib/gfxdevice.h" +#include "../lib/gfxpoly.h" +#include "../lib/devices/rescale.h" +#include "../lib/devices/polyops.h" +#include "../lib/devices/pdf.h" +#include "../lib/readers/image.h" +#include "../lib/readers/swf.h" +#include "../lib/pdf/pdf.h" +#include "../lib/log.h" + +static gfxsource_t*driver = 0; + +static char * outputname = 0; +static int loglevel = 3; +static char * pagerange = 0; +static char * filename = 0; +static const char * format = "ocr"; + +int args_callback_option(char*name,char*val) { + if (!strcmp(name, "o")) + { + outputname = val; + return 1; + } + else if (!strcmp(name, "v")) + { + loglevel ++; + setConsoleLogging(loglevel); + return 0; + } + else if (!strcmp(name, "f")) + { + format = val; + return 1; + } + else if (!strcmp(name, "q")) + { + loglevel --; + setConsoleLogging(loglevel); + return 0; + } + else if (name[0]=='p') + { + do { + name++; + } while(*name == 32 || *name == 13 || *name == 10 || *name == '\t'); + + if(*name) { + pagerange = name; + return 0; + } + pagerange = val; + return 1; + } + else if (!strcmp(name, "s")) + { + if(!driver) { + fprintf(stderr, "Specify input file before -s\n"); + exit(1); + } + char*s = strdup(val); + char*c = strchr(s, '='); + if(c && *c && c[1]) { + *c = 0; + c++; + driver->set_parameter(driver, s,c); + } else { + driver->set_parameter(driver, s,"1"); + } + free(s); + return 1; + } + else if (!strcmp(name, "V")) + { + printf("pdf2swf - part of %s %s\n", PACKAGE, VERSION); + exit(0); + } + else + { + fprintf(stderr, "Unknown option: -%s\n", name); + exit(1); + } + return 0; +} + +struct options_t options[] = +{{"o","output"}, + {"q","quiet"}, + {"V","version"}, + {"s","set"}, + {"p","pages"}, + {0,0} +}; + +int args_callback_longoption(char*name,char*val) { + return args_long2shortoption(options, name, val); +} + +int args_callback_command(char*name, char*val) { + if (!filename) { + + filename = name; + + if(strstr(filename, ".pdf") || strstr(filename, ".PDF")) { + msg(" Treating file as PDF"); + driver = gfxsource_pdf_create(); + } else if(strstr(filename, ".swf") || strstr(filename, ".SWF")) { + msg(" Treating file as SWF"); + driver = gfxsource_swf_create(); + } else if(strstr(filename, ".jpg") || strstr(filename, ".JPG") || + strstr(filename, ".png") || strstr(filename, ".PNG")) { + msg(" Treating file as Image"); + driver = gfxsource_image_create(); + } else { + driver = gfxsource_pdf_create(); + } + } else { + if(outputname) + { + fprintf(stderr, "Error: Do you want the output to go to %s or to %s?", + outputname, name); + exit(1); + } + outputname = name; + } + return 0; +} + +void args_callback_usage(char*name) +{ +} + +int main(int argn, char *argv[]) +{ + processargs(argn, argv); + initLog(0,-1,0,0,-1,loglevel); + + if(!filename) { + fprintf(stderr, "Please specify an input file\n"); + exit(1); + } + + if(!outputname) + { + if(filename) { + outputname = stripFilename(filename, ".print.pdf"); + msg(" Output filename not given. Writing to %s", outputname); + } + } + if(!outputname) + { + fprintf(stderr, "Please use -o to specify an output file\n"); + exit(1); + } + + is_in_range(0x7fffffff, pagerange); + if(pagerange) + driver->set_parameter(driver, "pages", pagerange); + + if(!filename) { + args_callback_usage(argv[0]); + exit(0); + } + + gfxdocument_t* doc = driver->open(driver, filename); + doc->set_parameter(doc, "drawonlyshapes", "1"); + doc->set_parameter(doc, "disable_polygon_conversion", "1"); + + if(!doc) { + msg(" Couldn't open %s", filename); + exit(1); + } + + gfxdevice_t _out,*out=&_out; + gfxdevice_pdf_init(out); + + /*gfxdevice_t wrap; + gfxdevice_removeclippings_init(&wrap, out); + out = &wrap;*/ + + int pagenr; + for(pagenr = 1; pagenr <= doc->num_pages; pagenr++) + { + if(is_in_range(pagenr, pagerange)) { + gfxpage_t* page = doc->getpage(doc, pagenr); + out->startpage(out, page->width, page->height); + page->render(page, out); + out->endpage(out); + page->destroy(page); + } + } + gfxresult_t*result = out->finish(out); + if(result) { + if(result->save(result, outputname) < 0) { + exit(1); + } + result->destroy(result); + } + doc->destroy(doc); + driver->destroy(driver); + return 0; +} + -- 1.7.10.4