From 110a75531d44dae80529a8ec7d563b1930ca8a45 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Thu, 12 May 2011 05:44:42 +0000 Subject: [PATCH] Add PDF loader (with some help from raster) SVN revision: 59338 --- legacy/evas_generic_loaders/TODO | 9 + legacy/evas_generic_loaders/configure.ac | 48 ++- .../evas_generic_loaders/src/bin/Makefile.am | 4 + .../src/bin/pdf/Makefile.am | 19 ++ .../evas_generic_loaders/src/bin/pdf/main.cpp | 304 ++++++++++++++++++ .../evas_generic_loaders/src/bin/xcf/common.h | 4 +- 6 files changed, 377 insertions(+), 11 deletions(-) create mode 100644 legacy/evas_generic_loaders/TODO create mode 100644 legacy/evas_generic_loaders/src/bin/pdf/Makefile.am create mode 100644 legacy/evas_generic_loaders/src/bin/pdf/main.cpp diff --git a/legacy/evas_generic_loaders/TODO b/legacy/evas_generic_loaders/TODO new file mode 100644 index 0000000000..f35cb337be --- /dev/null +++ b/legacy/evas_generic_loaders/TODO @@ -0,0 +1,9 @@ + +Modules to add: +--------------- + + [x] XCF + [x] PDF + [ ] PS + [ ] DVI + [ ] Djvu diff --git a/legacy/evas_generic_loaders/configure.ac b/legacy/evas_generic_loaders/configure.ac index a056f64f6c..b7db8eaf31 100644 --- a/legacy/evas_generic_loaders/configure.ac +++ b/legacy/evas_generic_loaders/configure.ac @@ -28,11 +28,6 @@ AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([1.6 dist-bzip2]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -AC_LIBTOOL_WIN32_DLL -define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl -define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl -AC_PROG_LIBTOOL - ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_ifdef([v_rev], , [m4_define([v_rev], [0])]) @@ -54,8 +49,10 @@ AC_SUBST(VMAJ) AC_CANONICAL_BUILD AC_CANONICAL_HOST -AC_C_BIGENDIAN + +### Checks for libraries AC_PROG_CC +AC_PROG_CXX PKG_PROG_PKG_CONFIG ### Checks for libraries @@ -63,14 +60,16 @@ PKG_PROG_PKG_CONFIG # Eina library PKG_CHECK_MODULES(EINA, [eina >= 1.0.0]) +PKG_CHECK_MODULES([POPPLER], [poppler >= 0.14], [have_poppler="yes"], [have_poppler="no"]) + +AM_CONDITIONAL([HAVE_PDF], [test "x${have_poppler}" = "xyes"]) + ### Checks for header files AC_CHECK_HEADER([zlib.h], [dummy="yes"], [AC_MSG_ERROR("Cannot find zlib.h. Make sure your CFLAGS environment variable contains include lines for the location of this file")]) -AC_CHECK_HEADERS(netinet/in.h) - SHM_OPEN_LIBS="" AC_MSG_CHECKING([whether shm_open() is present]) LIBS_save=${LIBS} @@ -102,15 +101,44 @@ AM_PROG_CC_C_O AC_C_CONST AC_C_INLINE AC_PROG_CC_STDC +AC_C_BIGENDIAN AC_C___ATTRIBUTE__ ### Checks for library functions AC_ISC_POSIX -AC_FUNC_ALLOCA -AC_OUTPUT([ +AC_CONFIG_FILES([ Makefile src/Makefile src/bin/Makefile src/bin/xcf/Makefile +src/bin/pdf/Makefile ]) + +AC_OUTPUT + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE $VERSION" +echo "------------------------------------------------------------------------" +echo +echo +echo "Configuration Options Summary:" +echo +echo "Loaders:" +echo " XCF..................: yes" +echo " PDF..................: ${have_poppler}" +echo +echo "Compilation............: make (or gmake)" +echo " CPPFLAGS.............: $CPPFLAGS" +echo " CFLAGS...............: $CFLAGS" +echo " LDFLAGS..............: $LDFLAGS" +echo +echo "Installation...........: make install (as root if needed, with 'su' or 'sudo')" +echo " prefix...............: $prefix" +echo diff --git a/legacy/evas_generic_loaders/src/bin/Makefile.am b/legacy/evas_generic_loaders/src/bin/Makefile.am index f64bd1c426..eae5af316a 100644 --- a/legacy/evas_generic_loaders/src/bin/Makefile.am +++ b/legacy/evas_generic_loaders/src/bin/Makefile.am @@ -1,3 +1,7 @@ MAINTAINERCLEANFILES = Makefile.in SUBDIRS = xcf + +if HAVE_PDF +SUBDIRS += pdf +endif diff --git a/legacy/evas_generic_loaders/src/bin/pdf/Makefile.am b/legacy/evas_generic_loaders/src/bin/pdf/Makefile.am new file mode 100644 index 0000000000..3700ceb1d6 --- /dev/null +++ b/legacy/evas_generic_loaders/src/bin/pdf/Makefile.am @@ -0,0 +1,19 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src \ +-I$(top_srcdir)/src/bin \ +-I$(top_srcdir)/src/bin/pdf \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EINA_CFLAGS@ \ +@POPPLER_CFLAGS@ + +bin_PROGRAMS = evas_image_loader.pdf + +evas_image_loader_pdf_SOURCES = main.cpp +evas_image_loader_pdf_CFLAGS = +evas_image_loader_pdf_LDADD = @POPPLER_LIBS@ @EINA_LIBS@ @SHM_OPEN_LIBS@ +evas_image_loader_pdf_LDFLAGS = diff --git a/legacy/evas_generic_loaders/src/bin/pdf/main.cpp b/legacy/evas_generic_loaders/src/bin/pdf/main.cpp new file mode 100644 index 0000000000..24017bb77d --- /dev/null +++ b/legacy/evas_generic_loaders/src/bin/pdf/main.cpp @@ -0,0 +1,304 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +#define DATA32 unsigned int + +//#define PDF_DBG + +#ifdef PDF_DBG +#define D(fmt, args...) fprintf(stderr, fmt, ## args) +#else +#define D(fmt, args...) +#endif + + +PDFDoc *pdfdoc; +bool locked = false; +SplashOutputDev *output_dev; + +::Page *page; +int width = 0; +int height = 0; +void *data; + +static int shm_fd = -1; +static int shm_size = 0; +static void *shm_addr = NULL; +static char shmfile[1024] = ""; + +static void +shm_alloc(int dsize) +{ +#ifdef HAVE_SHM_OPEN + srand(time(NULL)); + do + { + snprintf(shmfile, sizeof(shmfile), "/evas-loader-xcf.%i.%i", + (int)getpid(), (int)rand()); + shm_fd = shm_open(shmfile, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + } + while (shm_fd < 0); + + if (ftruncate(shm_fd, dsize) < 0) + { + close(shm_fd); + shm_unlink(shmfile); + shm_fd = -1; + goto failed; + } + shm_addr = mmap(NULL, dsize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm_addr == MAP_FAILED) + { + close(shm_fd); + shm_unlink(shmfile); + shm_fd = -1; + goto failed; + } + shm_size = dsize; + return; +failed: +#endif + shm_addr = malloc(dsize); +} + +static void +shm_free(void) +{ +#ifdef HAVE_SHM_OPEN + if (shm_fd >= 0) + { + munmap(shm_addr, shm_size); + close(shm_fd); + shm_fd = -1; + shm_addr = NULL; + return; + } +#endif + free(shm_addr); + shm_addr = NULL; + shm_fd = -1; +} + +Eina_Bool poppler_init(const char *file, int page_nbr, double dpi, int size_w, int size_h) +{ + Object obj; + SplashColor white; + + if (!file || !*file) + return EINA_FALSE; + + if (page_nbr < 0) + return EINA_FALSE; + + if (!(globalParams = new GlobalParams())) + return EINA_FALSE; + + if (!eina_init()) + goto del_global_param; + + if (globalParams->getAntialias()) + globalParams->setAntialias((char *)"yes"); + if (globalParams->getVectorAntialias()) + globalParams->setVectorAntialias((char *)"yes"); + + pdfdoc = new PDFDoc(new GooString(file), NULL); + if (!pdfdoc) + goto del_global_param; + + if (!pdfdoc->isOk() || (pdfdoc->getErrorCode() == errEncrypted)) + goto del_pdfdoc; + + if (page_nbr >= pdfdoc->getNumPages()) + goto del_pdfdoc; + + /* load the page */ + + page = pdfdoc->getCatalog()->getPage(page_nbr + 1); + if (!page || !page->isOk()) + goto del_pdfdoc; + + width = page->getMediaWidth(); + height = page->getMediaHeight(); + + if ((size_w > 0) || (size_h > 0)) + { + /* FIXME: tell poller to render at the new width and height + unsigned int w2 = width, h2 = height; + if (size_w > 0) + { + w2 = size_w; + h2 = (size_w * h) / w; + if ((size_h > 0) && (h2 > size_h)) + { + unsigned int w3; + h2 = size_h; + w3 = (size_h * w) / h; + if (w3 > w2) + w2 = w3; + } + } + else if (size_h > 0) + { + h2 = size_h; + w2 = (size_h * w) / h; + } + width = w2; + height = h2; + */ + } + else if (dpi > 0.0) + { + /* FIXME: tell poppler to render at this size + width = (width * dpi) / 72.0; + height = (height * dpi) / 72.0; + */ + } + + return EINA_TRUE; + + del_pdfdoc: + delete pdfdoc; + del_global_param: + delete globalParams; + + return EINA_FALSE; +} + +void poppler_shutdown() +{ + delete pdfdoc; + eina_shutdown(); + delete globalParams; +} + +void poppler_load_image(double dpi, int size_w, int size_h) +{ + SplashOutputDev *output_dev; + SplashColor white; + SplashColorPtr color_ptr; + + white[0] = 255; + white[1] = 255; + white[2] = 255; + white[3] = 255; + + output_dev = new SplashOutputDev(splashModeXBGR8, 4, gFalse, white); + if (!output_dev) + return; + + output_dev->startDoc(pdfdoc->getXRef()); + + if (dpi <= 0.0) dpi = 72.0; + + page->display(output_dev, + dpi, dpi, 0, + false, false, false, + pdfdoc->getCatalog()); + color_ptr = output_dev->getBitmap()->getDataPtr(); + + shm_alloc(width * height * sizeof(DATA32)); + if (!shm_addr) + goto del_outpput_dev; + data = shm_addr; + memcpy(data, color_ptr, width * height * sizeof(DATA32)); + + del_outpput_dev: + delete output_dev; +} + +int +main(int argc, char **argv) +{ + char *file; + int i; + int size_w = 0, size_h = 0; + int head_only = 0; + int page = 0; + double dpi = -1.0; + + if (argc < 2) return -1; + // file is ALWAYS first arg, other options come after + file = argv[1]; + for (i = 2; i < argc; i++) + { + if (!strcmp(argv[i], "-head")) + // asked to only load header, not body/data + head_only = 1; + else if (!strcmp(argv[i], "-key")) + { + i++; + page = atoi(argv[i]); + i++; + } + else if (!strcmp(argv[i], "-opt-scale-down-by")) + { // not used by pdf loader + i++; + // int scale_down = atoi(argv[i]); + } + else if (!strcmp(argv[i], "-opt-dpi")) + { + i++; + dpi = ((double)atoi(argv[i])) / 1000.0; // dpi is an int multiplied by 1000 (so 72dpi is 72000) + i++; + } + else if (!strcmp(argv[i], "-opt-size")) + { // not used by pdf loader + i++; + size_w = atoi(argv[i]); + i++; + size_h = atoi(argv[i]); + } + } + + D("poppler_file_init\n"); + D("dpi....: %f\n", dpi); + D("page...: %d\n", page); + + if (!poppler_init(file, page, dpi, size_w, size_h)) + return -1; + D("poppler_file_init done\n"); + + if (!head_only) + { + poppler_load_image(dpi, size_w, size_h); + } + + D("size...: %ix%i\n", width, height); + D("alpha..: 1\n"); + + printf("size %i %i\n", width, height); + printf("alpha 0\n"); + + if (!head_only) + { + if (shm_fd >= 0) printf("shmfile %s\n", shmfile); + else + { + // could also to "tmpfile %s\n" like shmfile but just + // a mmaped tmp file on the system + printf("data\n"); + fwrite(data, width * height * sizeof(DATA32), 1, stdout); + } + shm_free(); + } + else + printf("done\n"); + + poppler_shutdown(); + + return 0; +} diff --git a/legacy/evas_generic_loaders/src/bin/xcf/common.h b/legacy/evas_generic_loaders/src/bin/xcf/common.h index a6de7444c4..209c3c13e3 100644 --- a/legacy/evas_generic_loaders/src/bin/xcf/common.h +++ b/legacy/evas_generic_loaders/src/bin/xcf/common.h @@ -1,7 +1,9 @@ #ifndef __COMMON #define __COMMON 1 -#include "config.h" +#ifdef HAVE_CONFIG_H +# include +#endif #include #include