2011-05-11 22:44:42 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <fcntl.h>
|
2013-10-31 02:29:28 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <libgen.h>
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
#include <GlobalParams.h>
|
|
|
|
#include <PDFDoc.h>
|
|
|
|
#include <ErrorCodes.h>
|
|
|
|
#include <Page.h>
|
|
|
|
#include <SplashOutputDev.h>
|
|
|
|
#include <splash/SplashBitmap.h>
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
|
2011-05-13 02:06:56 -07:00
|
|
|
#include "shmfile.h"
|
2012-09-26 01:07:33 -07:00
|
|
|
#include "timeout.h"
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
#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;
|
|
|
|
|
|
|
|
::Page *page;
|
2011-05-13 00:45:22 -07:00
|
|
|
int width = 0, height = 0;
|
|
|
|
int crop_width = 0, crop_height = 0;
|
|
|
|
void *data = NULL;
|
|
|
|
double dpi = -1.0;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
#define DEF_DPI 72.0
|
|
|
|
|
|
|
|
Eina_Bool poppler_init(const char *file, int page_nbr, int size_w, int size_h)
|
2011-05-11 22:44:42 -07:00
|
|
|
{
|
|
|
|
Object obj;
|
2011-05-13 00:45:22 -07:00
|
|
|
double w, h, cw, ch;
|
|
|
|
int rot;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2015-03-06 01:44:50 -08:00
|
|
|
#ifndef HAVE_POPPLER_031
|
2011-05-11 22:44:42 -07:00
|
|
|
if (globalParams->getAntialias())
|
|
|
|
globalParams->setAntialias((char *)"yes");
|
|
|
|
if (globalParams->getVectorAntialias())
|
|
|
|
globalParams->setVectorAntialias((char *)"yes");
|
2015-03-06 01:44:50 -08:00
|
|
|
#endif
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
w = page->getMediaWidth();
|
|
|
|
h = page->getMediaHeight();
|
|
|
|
cw = page->getCropWidth();
|
|
|
|
ch = page->getCropHeight();
|
|
|
|
rot = page->getRotate();
|
|
|
|
if (cw > w) cw = w;
|
|
|
|
if (ch > h) ch = h;
|
|
|
|
if ((rot == 90) || (rot == 270))
|
|
|
|
{
|
|
|
|
double t;
|
|
|
|
// swap width & height
|
|
|
|
t = w; w = h; h = t;
|
|
|
|
// swap crop width & height
|
|
|
|
t = cw; cw = ch; ch = t;
|
|
|
|
}
|
|
|
|
|
2011-05-11 22:44:42 -07:00
|
|
|
if ((size_w > 0) || (size_h > 0))
|
|
|
|
{
|
2011-05-13 00:45:22 -07:00
|
|
|
double w2 = cw, h2 = ch;
|
|
|
|
|
|
|
|
w2 = size_w;
|
|
|
|
h2 = (size_w * ch) / cw;
|
|
|
|
if (h2 > size_h)
|
2011-05-11 22:44:42 -07:00
|
|
|
{
|
|
|
|
h2 = size_h;
|
2011-05-13 00:45:22 -07:00
|
|
|
w2 = (size_h * cw) / ch;
|
2011-05-11 22:44:42 -07:00
|
|
|
}
|
2011-05-13 00:45:22 -07:00
|
|
|
D("XXXXXXXXXXXXXXXXXXXXx %3.3fx%3.3f\n", w2, h2);
|
|
|
|
if (w2 > h2) dpi = (w2 * DEF_DPI) / cw;
|
|
|
|
else dpi = (h2 * DEF_DPI) / ch;
|
2011-05-11 22:44:42 -07:00
|
|
|
}
|
2011-05-13 00:45:22 -07:00
|
|
|
|
|
|
|
if (dpi > 0.0)
|
2011-05-11 22:44:42 -07:00
|
|
|
{
|
2011-05-13 00:45:22 -07:00
|
|
|
cw = (cw * dpi) / DEF_DPI;
|
|
|
|
ch = (ch * dpi) / DEF_DPI;
|
|
|
|
w = (w * dpi) / DEF_DPI;
|
|
|
|
h = (h * dpi) / DEF_DPI;
|
2011-05-11 22:44:42 -07:00
|
|
|
}
|
2011-05-13 00:45:22 -07:00
|
|
|
width = w;
|
|
|
|
height = h;
|
|
|
|
crop_width = cw;
|
|
|
|
crop_height = ch;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
del_pdfdoc:
|
|
|
|
delete pdfdoc;
|
|
|
|
del_global_param:
|
|
|
|
delete globalParams;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void poppler_shutdown()
|
|
|
|
{
|
|
|
|
delete pdfdoc;
|
|
|
|
eina_shutdown();
|
|
|
|
delete globalParams;
|
|
|
|
}
|
|
|
|
|
2015-08-11 06:44:38 -07:00
|
|
|
void poppler_load_image(int size_w EINA_UNUSED, int size_h EINA_UNUSED)
|
2011-05-11 22:44:42 -07:00
|
|
|
{
|
|
|
|
SplashOutputDev *output_dev;
|
|
|
|
SplashColor white;
|
|
|
|
SplashColorPtr color_ptr;
|
2011-05-13 00:45:22 -07:00
|
|
|
DATA32 *src, *dst;
|
|
|
|
int y;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
white[0] = 255;
|
|
|
|
white[1] = 255;
|
|
|
|
white[2] = 255;
|
|
|
|
white[3] = 255;
|
|
|
|
|
|
|
|
output_dev = new SplashOutputDev(splashModeXBGR8, 4, gFalse, white);
|
|
|
|
if (!output_dev)
|
|
|
|
return;
|
|
|
|
|
2015-03-06 01:44:50 -08:00
|
|
|
#if defined(HAVE_POPPLER_020) || defined(HAVE_POPPLER_031)
|
2012-06-05 03:30:38 -07:00
|
|
|
output_dev->startDoc(pdfdoc);
|
|
|
|
#else
|
2011-05-11 22:44:42 -07:00
|
|
|
output_dev->startDoc(pdfdoc->getXRef());
|
2012-06-05 03:30:38 -07:00
|
|
|
#endif
|
2011-05-11 22:44:42 -07:00
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
if (dpi <= 0.0) dpi = DEF_DPI;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
2015-03-06 01:44:50 -08:00
|
|
|
#ifdef HAVE_POPPLER_031
|
|
|
|
output_dev->setFontAntialias(EINA_TRUE);
|
|
|
|
output_dev->setVectorAntialias(EINA_TRUE);
|
|
|
|
#endif
|
2012-06-05 03:30:38 -07:00
|
|
|
|
2015-03-06 01:44:50 -08:00
|
|
|
#if defined(HAVE_POPPLER_020) || defined(HAVE_POPPLER_031)
|
2012-06-05 03:30:38 -07:00
|
|
|
page->displaySlice(output_dev, dpi, dpi,
|
|
|
|
0, false, false,
|
|
|
|
0, 0, width, height,
|
|
|
|
false, NULL, NULL);
|
|
|
|
#else
|
2011-05-13 00:45:22 -07:00
|
|
|
page->displaySlice(output_dev, dpi, dpi,
|
|
|
|
0, false, false,
|
|
|
|
0, 0, width, height,
|
|
|
|
false, pdfdoc->getCatalog());
|
2012-06-05 03:30:38 -07:00
|
|
|
#endif
|
2011-05-11 22:44:42 -07:00
|
|
|
color_ptr = output_dev->getBitmap()->getDataPtr();
|
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
shm_alloc(crop_width * crop_height * sizeof(DATA32));
|
|
|
|
if (!shm_addr) goto del_outpput_dev;
|
2011-05-11 22:44:42 -07:00
|
|
|
data = shm_addr;
|
2011-05-13 00:45:22 -07:00
|
|
|
src = (DATA32 *)color_ptr;
|
|
|
|
dst = (DATA32 *)data;
|
|
|
|
for (y = 0; y < crop_height; y++)
|
|
|
|
{
|
|
|
|
memcpy(dst, src, crop_width * sizeof(DATA32));
|
|
|
|
src += width;
|
|
|
|
dst += crop_width;
|
|
|
|
}
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
del_outpput_dev:
|
|
|
|
delete output_dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2013-10-31 02:29:28 -07:00
|
|
|
Eina_Tmpstr *tmpdir = NULL;
|
|
|
|
Eina_Tmpstr *generated = NULL;
|
|
|
|
char *extension;
|
|
|
|
char *dir;
|
2011-05-11 22:44:42 -07:00
|
|
|
char *file;
|
|
|
|
int i;
|
|
|
|
int size_w = 0, size_h = 0;
|
|
|
|
int head_only = 0;
|
2015-11-10 07:10:19 -08:00
|
|
|
int page_num = 0;
|
2011-05-11 22:44:42 -07:00
|
|
|
|
|
|
|
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++;
|
2015-11-10 07:10:19 -08:00
|
|
|
page_num = atoi(argv[i]);
|
2011-05-11 22:44:42 -07:00
|
|
|
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("dpi....: %f\n", dpi);
|
2015-11-10 07:10:19 -08:00
|
|
|
D("page...: %d\n", page_num);
|
2011-05-11 22:44:42 -07:00
|
|
|
|
2013-10-31 02:29:28 -07:00
|
|
|
// This is a funny hack to call an external tool to generate a pdf that will then be processed by poppler
|
|
|
|
extension = strrchr(file, '.');
|
|
|
|
dir = dirname(argv[0]);
|
|
|
|
if (extension && dir && strcmp(extension, ".pdf"))
|
|
|
|
{
|
|
|
|
if (eina_file_mkdtemp("evas_generic_pdf_loaderXXXXXX", &tmpdir))
|
|
|
|
{
|
|
|
|
Eina_Strbuf *tmp;
|
|
|
|
FILE *cmd;
|
|
|
|
|
|
|
|
tmp = eina_strbuf_new();
|
|
|
|
eina_strbuf_append_printf(tmp, "%s/evas_generic_pdf_loader.%s '%s' %s", dir, extension + 1, file, tmpdir);
|
|
|
|
|
|
|
|
cmd = popen(eina_strbuf_string_get(tmp), "r");
|
|
|
|
D("running preprocessing process '%s'...\n", eina_strbuf_string_get(tmp));
|
|
|
|
eina_strbuf_reset(tmp);
|
|
|
|
|
|
|
|
if (cmd)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
const char *filename;
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof (buf), cmd))
|
|
|
|
;
|
|
|
|
pclose(cmd);
|
|
|
|
|
|
|
|
filename = basename(file);
|
|
|
|
generated = eina_tmpstr_add_length(filename, strlen(filename) - strlen(extension));
|
|
|
|
|
|
|
|
eina_strbuf_append_printf(tmp, "%s/%s.pdf", tmpdir, generated);
|
|
|
|
|
|
|
|
eina_tmpstr_del(generated);
|
|
|
|
generated = NULL;
|
|
|
|
|
|
|
|
if (stat(eina_strbuf_string_get(tmp), &st) == 0)
|
|
|
|
{
|
|
|
|
generated = eina_tmpstr_add_length(eina_strbuf_string_get(tmp),
|
|
|
|
eina_strbuf_length_get(tmp));
|
|
|
|
file = (char*) generated;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
D("generated file: '%s'\n", generated);
|
|
|
|
eina_strbuf_free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let's force a timeout if things go wrong
|
2012-09-26 01:07:33 -07:00
|
|
|
timeout_init(10);
|
2013-10-31 02:29:28 -07:00
|
|
|
|
|
|
|
// Now process the pdf (or the generated pdf)
|
|
|
|
D("poppler_file_init\n");
|
2015-11-10 07:10:19 -08:00
|
|
|
if (!poppler_init(file, page_num, size_w, size_h))
|
2011-05-11 22:44:42 -07:00
|
|
|
return -1;
|
|
|
|
D("poppler_file_init done\n");
|
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
D("dpi2...: %f\n", dpi);
|
2011-05-11 22:44:42 -07:00
|
|
|
if (!head_only)
|
|
|
|
{
|
2011-05-13 00:45:22 -07:00
|
|
|
poppler_load_image(size_w, size_h);
|
2011-05-11 22:44:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
D("size...: %ix%i\n", width, height);
|
2011-05-13 00:45:22 -07:00
|
|
|
D("crop...: %ix%i\n", crop_width, crop_height);
|
2011-05-11 22:44:42 -07:00
|
|
|
D("alpha..: 1\n");
|
|
|
|
|
2011-05-13 00:45:22 -07:00
|
|
|
printf("size %i %i\n", crop_width, crop_height);
|
2011-05-11 22:44:42 -07:00
|
|
|
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");
|
2011-05-13 00:45:22 -07:00
|
|
|
fwrite(data, crop_width * crop_height * sizeof(DATA32), 1, stdout);
|
2011-05-11 22:44:42 -07:00
|
|
|
}
|
|
|
|
shm_free();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("done\n");
|
|
|
|
|
|
|
|
poppler_shutdown();
|
|
|
|
|
2013-10-31 02:29:28 -07:00
|
|
|
if (tmpdir)
|
|
|
|
{
|
|
|
|
if (generated) unlink(generated);
|
|
|
|
rmdir(tmpdir);
|
|
|
|
|
|
|
|
eina_tmpstr_del(tmpdir);
|
|
|
|
eina_tmpstr_del(generated);
|
|
|
|
}
|
2015-08-11 05:34:48 -07:00
|
|
|
fflush(stdout);
|
2011-05-11 22:44:42 -07:00
|
|
|
return 0;
|
|
|
|
}
|