Add PDF loader (with some help from raster)

SVN revision: 59338
This commit is contained in:
Vincent Torri 2011-05-12 05:44:42 +00:00
parent 476c349d86
commit 110a75531d
6 changed files with 377 additions and 11 deletions

View File

@ -0,0 +1,9 @@
Modules to add:
---------------
[x] XCF
[x] PDF
[ ] PS
[ ] DVI
[ ] Djvu

View File

@ -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

View File

@ -1,3 +1,7 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = xcf
if HAVE_PDF
SUBDIRS += pdf
endif

View File

@ -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 =

View File

@ -0,0 +1,304 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/mman.h>
#include <fcntl.h>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <ErrorCodes.h>
#include <Page.h>
#include <SplashOutputDev.h>
#include <splash/SplashBitmap.h>
#include <Eina.h>
#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;
}

View File

@ -1,7 +1,9 @@
#ifndef __COMMON
#define __COMMON 1
#include "config.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>