I disagree. My original pdftocairo patch outputted PS/PDF to one file.
That is the way it is intended to work similar to pdftops. Your patch
introduced a bug.
Gotcha.
Ok, I've used multipage as the default behavior where supported and
added a "-split" option for splitting into individual files.
New patchset attached. This final version should address all feedback
from reviewers. Thanks again!
Cheers,
Stefan
>From 56f5261d1e6103b3e9df1395de030fca2978a739 Mon Sep 17 00:00:00 2001
From: Adrian Johnson <[email protected]>
Date: Fri, 11 Dec 2009 18:46:23 +1030
Subject: [PATCH 01/10] Add pdftocairo util
---
utils/Makefile.am | 20 +++-
utils/pdftocairo.cc | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 397 insertions(+), 2 deletions(-)
create mode 100644 utils/pdftocairo.cc
diff --git a/utils/Makefile.am b/utils/Makefile.am
index e57c71b..ac08b5e 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -17,7 +17,8 @@ INCLUDES = \
-I$(top_srcdir)/poppler \
$(UTILS_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
- $(ABIWORD_CFLAGS)
+ $(ABIWORD_CFLAGS) \
+ $(CAIRO_CFLAGS)
LDADD = \
$(top_builddir)/poppler/libpoppler.la \
@@ -36,6 +37,20 @@ pdftoabw_binary = pdftoabw
endif
+if BUILD_CAIRO_OUTPUT
+
+pdftocairo_SOURCES = \
+ pdftocairo.cc \
+ $(common)
+
+pdftocairo_LDADD = $(LDADD) $(CAIRO_LIBS) \
+ $(top_builddir)/poppler/libpoppler-cairo.la
+
+
+pdftocairo_binary = pdftocairo
+
+endif
+
AM_LDFLAGS = @auto_import_flags@
bin_PROGRAMS = \
@@ -46,7 +61,8 @@ bin_PROGRAMS = \
pdftotext \
pdftohtml \
$(pdftoppm_binary) \
- $(pdftoabw_binary)
+ $(pdftoabw_binary) \
+ $(pdftocairo_binary)
dist_man1_MANS = \
pdffonts.1 \
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
new file mode 100644
index 0000000..8540b42
--- /dev/null
+++ b/utils/pdftocairo.cc
@@ -0,0 +1,379 @@
+//========================================================================
+//
+// pdftocairo.cc
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2007 Ilmari Heikkinen <[email protected]>
+// Copyright (C) 2008 Richard Airlie <[email protected]>
+// Copyright (C) 2009 Michael K. Johnson <[email protected]>
+// Copyright (C) 2009 Shen Liang <[email protected]>
+// Copyright (C) 2009 Stefan Thomas <[email protected]>
+// Copyright (C) 2009 Adrian Johnson <[email protected]>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+#include "config.h"
+#include <poppler-config.h>
+#include <stdio.h>
+#include <math.h>
+#include <cairo.h>
+#include <cairo-ps.h>
+#include <cairo-pdf.h>
+#include "parseargs.h"
+#include "goo/gmem.h"
+#include "goo/GooString.h"
+#include "GlobalParams.h"
+#include "Object.h"
+#include "PDFDoc.h"
+#include "CairoOutputDev.h"
+
+#define OUT_FILE_SZ 512
+
+static int firstPage = 1;
+static int lastPage = 0;
+static double resolution = 0.0;
+static double x_resolution = 150.0;
+static double y_resolution = 150.0;
+static int scaleTo = 0;
+static int x_scaleTo = 0;
+static int y_scaleTo = 0;
+static int x = 0;
+static int y = 0;
+static int w = 0;
+static int h = 0;
+static int sz = 0;
+static GBool useCropBox = gFalse;
+static GBool png = gFalse;
+static GBool ps = gFalse;
+static GBool pdf = gFalse;
+static char ownerPassword[33] = "";
+static char userPassword[33] = "";
+static GBool quiet = gFalse;
+static GBool printVersion = gFalse;
+static GBool printHelp = gFalse;
+
+static const ArgDesc argDesc[] = {
+ {"-f", argInt, &firstPage, 0,
+ "first page to print"},
+ {"-l", argInt, &lastPage, 0,
+ "last page to print"},
+
+ {"-r", argFP, &resolution, 0,
+ "resolution, in DPI (default is 150)"},
+ {"-rx", argFP, &x_resolution, 0,
+ "X resolution, in DPI (default is 150)"},
+ {"-ry", argFP, &y_resolution, 0,
+ "Y resolution, in DPI (default is 150)"},
+ {"-scale-to", argInt, &scaleTo, 0,
+ "scales each page to fit within scale-to*scale-to pixel box"},
+ {"-scale-to-x", argInt, &x_scaleTo, 0,
+ "scales each page horizontally to fit in scale-to-x pixels"},
+ {"-scale-to-y", argInt, &y_scaleTo, 0,
+ "scales each page vertically to fit in scale-to-y pixels"},
+
+ {"-x", argInt, &x, 0,
+ "x-coordinate of the crop area top left corner"},
+ {"-y", argInt, &y, 0,
+ "y-coordinate of the crop area top left corner"},
+ {"-W", argInt, &w, 0,
+ "width of crop area in pixels (default is 0)"},
+ {"-H", argInt, &h, 0,
+ "height of crop area in pixels (default is 0)"},
+ {"-sz", argInt, &sz, 0,
+ "size of crop square in pixels (sets W and H)"},
+ {"-cropbox",argFlag, &useCropBox, 0,
+ "use the crop box rather than media box"},
+
+ {"-png", argFlag, &png, 0,
+ "generate a PNG file"},
+ {"-ps", argFlag, &ps, 0,
+ "generate PostScript file"},
+ {"-pdf", argFlag, &pdf, 0,
+ "generate a PDF file"},
+
+
+ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
+ "owner password (for encrypted files)"},
+ {"-upw", argString, userPassword, sizeof(userPassword),
+ "user password (for encrypted files)"},
+
+ {"-q", argFlag, &quiet, 0,
+ "don't print any messages or errors"},
+ {"-v", argFlag, &printVersion, 0,
+ "print copyright and version info"},
+ {"-h", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"--help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-?", argFlag, &printHelp, 0,
+ "print usage information"},
+ {NULL}
+};
+
+
+static void create_surface(char *outFile, cairo_surface_t **surface_out,
+ GBool *printing_out)
+{
+ char file[OUT_FILE_SZ];
+
+ strcpy(file, outFile);
+ if (png) {
+ *surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ *printing_out = gFalse;
+ } else if (ps) {
+ strcat(file, ".ps");
+ *surface_out = cairo_ps_surface_create (file, w, h);
+ *printing_out = gTrue;
+ } else if (pdf) {
+ strcat(file, ".pdf");
+ *surface_out = cairo_pdf_surface_create (file, w, h);
+ *printing_out = gTrue;
+ }
+}
+
+static void start_page(cairo_surface_t **surface, int w, int h,
+ double x_res, double y_res, int rotate)
+{
+ if (png) {
+ cairo_surface_destroy(*surface);
+ *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ } else if (ps) {
+ cairo_ps_surface_set_size(*surface, w, h);
+ } else if (pdf) {
+ cairo_pdf_surface_set_size(*surface, w, h);
+ }
+}
+
+static void end_page(cairo_surface_t *surface, char *outFile)
+{
+ char file[OUT_FILE_SZ];
+
+ strcpy(file, outFile);
+ if (png) {
+ strcat(file, ".png");
+ cairo_surface_write_to_png (surface, file);
+ } else if (ps || pdf) {
+ cairo_surface_show_page(surface);
+ }
+}
+
+static int render_page(CairoOutputDev *output_dev, PDFDoc *doc,
+ cairo_surface_t *surface,
+ GBool printing, int pg,
+ int x, int y, int w, int h,
+ double pg_w, double pg_h,
+ double x_res, double y_res)
+{
+ cairo_t *cr;
+ cairo_status_t status;
+ TextPage *text = NULL;
+
+ if (w == 0) w = (int)ceil(pg_w);
+ if (h == 0) h = (int)ceil(pg_h);
+ w = (x+w > pg_w ? (int)ceil(pg_w-x) : w);
+ h = (y+h > pg_h ? (int)ceil(pg_h-y) : h);
+
+ cr = cairo_create (surface);
+ cairo_save (cr);
+ output_dev->setCairo (cr);
+ output_dev->setPrinting (printing);
+
+ if (!printing)
+ cairo_scale (cr, x_res/72.0, y_res/72.0);
+
+ text = new TextPage(gFalse);
+ if (!printing)
+ output_dev->setTextPage (text);
+
+ /* NOTE: instead of passing -1 we should/could use cairo_clip_extents()
+ * to get a bounding box */
+ cairo_save (cr);
+ doc->displayPageSlice(output_dev, pg, /* page */
+ 72.0, 72.0, 0,
+ gFalse, /* useMediaBox */
+ !useCropBox, /* Crop */
+ printing,
+ x, y, w, h);
+ cairo_restore (cr);
+
+ output_dev->setCairo (NULL);
+ output_dev->setTextPage (NULL);
+
+ if (!printing) {
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
+
+ status = cairo_status(cr);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ cairo_destroy (cr);
+
+ if (text != NULL)
+ text->decRefCnt();
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ PDFDoc *doc;
+ GooString *fileName = NULL;
+ char *outRoot;
+ char outFile[OUT_FILE_SZ];
+ GooString *ownerPW, *userPW;
+ GBool ok;
+ int exitCode;
+ int pg, pg_num_len;
+ double pg_w, pg_h, tmp;
+ char *p;
+ CairoOutputDev *output_dev;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ GBool printing;
+
+ exitCode = 99;
+
+ // parse args
+ ok = parseArgs(argDesc, &argc, argv);
+
+ if ( resolution != 0.0 &&
+ (x_resolution == 150.0 ||
+ y_resolution == 150.0)) {
+ x_resolution = resolution;
+ y_resolution = resolution;
+ }
+ if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
+ fprintf(stderr, "pdftocairo version %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "%s\n", popplerCopyright);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersion) {
+ printUsage("pdftocairo", "PDF-file [output-file]", argDesc);
+ }
+ goto err0;
+ }
+
+ if (!png && !ps && !pdf) {
+ fprintf(stderr, "One of -png, -ps, or -pdf must be specified\n");
+ goto err0;
+ }
+
+ fileName = new GooString(argv[1]);
+ if (argc == 3)
+ outRoot = strdup(argv[2]);
+ else
+ outRoot = strdup(argv[1]);
+
+ p = strrchr(outRoot, '.');
+ if (p)
+ *p = 0;
+
+ // read config file
+ globalParams = new GlobalParams();
+ if (quiet) {
+ globalParams->setErrQuiet(quiet);
+ }
+
+ // open PDF file
+ if (ownerPassword[0]) {
+ ownerPW = new GooString(ownerPassword);
+ } else {
+ ownerPW = NULL;
+ }
+ if (userPassword[0]) {
+ userPW = new GooString(userPassword);
+ } else {
+ userPW = NULL;
+ }
+ doc = new PDFDoc(fileName, ownerPW, userPW);
+ if (userPW) {
+ delete userPW;
+ }
+ if (ownerPW) {
+ delete ownerPW;
+ }
+ if (!doc->isOk()) {
+ exitCode = 1;
+ goto err1;
+ }
+
+ // get page range
+ if (firstPage < 1)
+ firstPage = 1;
+ if (lastPage < 1 || lastPage > doc->getNumPages())
+ lastPage = doc->getNumPages();
+
+ if (sz != 0)
+ w = h = sz;
+
+ create_surface(outRoot, &surface, &printing);
+ output_dev = new CairoOutputDev ();
+ output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
+
+ pg_num_len = (int)ceil(log((double)doc->getNumPages()) / log((double)10));
+ for (pg = firstPage; pg <= lastPage; ++pg) {
+ if (useCropBox) {
+ pg_w = doc->getPageCropWidth(pg);
+ pg_h = doc->getPageCropHeight(pg);
+ } else {
+ pg_w = doc->getPageMediaWidth(pg);
+ pg_h = doc->getPageMediaHeight(pg);
+ }
+
+ if (scaleTo != 0) {
+ resolution = (72.0 * scaleTo) / (pg_w > pg_h ? pg_w : pg_h);
+ x_resolution = y_resolution = resolution;
+ } else {
+ if (x_scaleTo != 0) {
+ x_resolution = (72.0 * x_scaleTo) / pg_w;
+ }
+ if (y_scaleTo != 0) {
+ y_resolution = (72.0 * y_scaleTo) / pg_h;
+ }
+ }
+
+ start_page(&surface, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ render_page(output_dev, doc, surface, printing, pg,
+ x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
+ snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
+ OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
+ end_page(surface, outFile);
+ }
+ cairo_surface_finish(surface);
+ status = cairo_surface_status(surface);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ cairo_surface_destroy(surface);
+ delete output_dev;
+
+ exitCode = 0;
+
+ // clean up
+ err1:
+ delete doc;
+ delete globalParams;
+ err0:
+
+ // check for memory leaks
+ Object::memCheck(stderr);
+ gMemReport(stderr);
+
+ return exitCode;
+}
--
1.7.0.4
>From ce2b2c9b1ee3282ba25bd7766ecaa20ea54cb2b6 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Sat, 9 Jan 2010 17:08:11 +0000
Subject: [PATCH 02/10] pdftocairo: Added SVG support.
Simplified initialization code (necessary because there is no resize option for
Cairo SVG surfaces.)
---
utils/.gitignore | 1 +
utils/pdftocairo.cc | 49 +++++++++++++++++++++++--------------------------
2 files changed, 24 insertions(+), 26 deletions(-)
diff --git a/utils/.gitignore b/utils/.gitignore
index 696f074..a77622a 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -7,6 +7,7 @@ pdfimages
pdfinfo
pdftohtml
pdftoppm
+pdftocairo
pdftops
pdftotext
pdftoabw
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 8540b42..2a8b6dc 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -32,6 +32,7 @@
#include <cairo.h>
#include <cairo-ps.h>
#include <cairo-pdf.h>
+#include <cairo-svg.h>
#include "parseargs.h"
#include "goo/gmem.h"
#include "goo/GooString.h"
@@ -59,6 +60,7 @@ static GBool useCropBox = gFalse;
static GBool png = gFalse;
static GBool ps = gFalse;
static GBool pdf = gFalse;
+static GBool svg = gFalse;
static char ownerPassword[33] = "";
static char userPassword[33] = "";
static GBool quiet = gFalse;
@@ -103,6 +105,8 @@ static const ArgDesc argDesc[] = {
"generate PostScript file"},
{"-pdf", argFlag, &pdf, 0,
"generate a PDF file"},
+ {"-svg", argFlag, &svg, 0,
+ "generate a SVG file"},
{"-opw", argString, ownerPassword, sizeof(ownerPassword),
@@ -126,37 +130,28 @@ static const ArgDesc argDesc[] = {
};
-static void create_surface(char *outFile, cairo_surface_t **surface_out,
- GBool *printing_out)
+static cairo_surface_t *start_page(char *outFile, int w, int h,
+ double x_res, double y_res, int rotate)
{
char file[OUT_FILE_SZ];
+ cairo_surface_t *surface;
strcpy(file, outFile);
+
if (png) {
- *surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- *printing_out = gFalse;
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
strcat(file, ".ps");
- *surface_out = cairo_ps_surface_create (file, w, h);
- *printing_out = gTrue;
+ surface = cairo_ps_surface_create (file, w, h);
} else if (pdf) {
strcat(file, ".pdf");
- *surface_out = cairo_pdf_surface_create (file, w, h);
- *printing_out = gTrue;
- }
-}
-
-static void start_page(cairo_surface_t **surface, int w, int h,
- double x_res, double y_res, int rotate)
-{
- if (png) {
- cairo_surface_destroy(*surface);
- *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
- } else if (ps) {
- cairo_ps_surface_set_size(*surface, w, h);
- } else if (pdf) {
- cairo_pdf_surface_set_size(*surface, w, h);
+ surface = cairo_pdf_surface_create (file, w, h);
+ } else if (svg) {
+ strcat(file, ".svg");
+ surface = cairo_svg_surface_create (file, w, h);
}
+
+ return surface;
}
static void end_page(cairo_surface_t *surface, char *outFile)
@@ -167,7 +162,7 @@ static void end_page(cairo_surface_t *surface, char
*outFile)
if (png) {
strcat(file, ".png");
cairo_surface_write_to_png (surface, file);
- } else if (ps || pdf) {
+ } else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
}
@@ -270,8 +265,8 @@ int main(int argc, char *argv[]) {
goto err0;
}
- if (!png && !ps && !pdf) {
- fprintf(stderr, "One of -png, -ps, or -pdf must be specified\n");
+ if (!png && !ps && !pdf && !svg) {
+ fprintf(stderr, "One of -png, -ps, -pdf or -svg must be specified\n");
goto err0;
}
@@ -323,7 +318,6 @@ int main(int argc, char *argv[]) {
if (sz != 0)
w = h = sz;
- create_surface(outRoot, &surface, &printing);
output_dev = new CairoOutputDev ();
output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
@@ -348,8 +342,11 @@ int main(int argc, char *argv[]) {
y_resolution = (72.0 * y_scaleTo) / pg_h;
}
}
+
+ // Enable printing mode for all output types except PNG
+ printing = (png) ? gFalse : gTrue;
- start_page(&surface, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ surface = start_page(outRoot, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
render_page(output_dev, doc, surface, printing, pg,
x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
--
1.7.0.4
>From 8f34d06e42fa3f67f1acec2e50845a905536cab3 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Sat, 9 Jan 2010 17:11:45 +0000
Subject: [PATCH 03/10] pdftocairo: Code style; Removed spaces before
parentheses in function calls.
---
utils/pdftocairo.cc | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 2a8b6dc..b13d5d2 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -204,17 +204,17 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
!useCropBox, /* Crop */
printing,
x, y, w, h);
- cairo_restore (cr);
+ cairo_restore(cr);
- output_dev->setCairo (NULL);
- output_dev->setTextPage (NULL);
+ output_dev->setCairo(NULL);
+ output_dev->setTextPage(NULL);
if (!printing) {
- cairo_save (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_restore (cr);
+ cairo_save(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_paint(cr);
+ cairo_restore(cr);
}
status = cairo_status(cr);
@@ -318,8 +318,8 @@ int main(int argc, char *argv[]) {
if (sz != 0)
w = h = sz;
- output_dev = new CairoOutputDev ();
- output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
+ output_dev = new CairoOutputDev();
+ output_dev->startDoc(doc->getXRef(), doc->getCatalog());
pg_num_len = (int)ceil(log((double)doc->getNumPages()) / log((double)10));
for (pg = firstPage; pg <= lastPage; ++pg) {
@@ -356,7 +356,7 @@ int main(int argc, char *argv[]) {
cairo_surface_finish(surface);
status = cairo_surface_status(surface);
if (status)
- fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
cairo_surface_destroy(surface);
delete output_dev;
--
1.7.0.4
>From 639478c156089a6d247bdb3885bab682e737726a Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Sat, 9 Jan 2010 17:32:07 +0000
Subject: [PATCH 04/10] pdftocairo: Centralized output filename generation.
Nicer to have the filename generated in one place, also the filenames now all
have numbers, not just png.
---
utils/pdftocairo.cc | 58 ++++++++++++++++++++++++++++----------------------
1 files changed, 32 insertions(+), 26 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index b13d5d2..9c4981f 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -130,25 +130,36 @@ static const ArgDesc argDesc[] = {
};
+static void format_output_filename(char *outFile, char *outRoot,
+ int pg_num_len, int pg)
+{
+ snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
+ OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
+
+ if (png) {
+ strcat(outFile, ".png");
+ } else if (ps) {
+ strcat(outFile, ".ps");
+ } else if (pdf) {
+ strcat(outFile, ".pdf");
+ } else if (svg) {
+ strcat(outFile, ".svg");
+ }
+}
+
static cairo_surface_t *start_page(char *outFile, int w, int h,
double x_res, double y_res, int rotate)
{
- char file[OUT_FILE_SZ];
cairo_surface_t *surface;
-
- strcpy(file, outFile);
if (png) {
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
- strcat(file, ".ps");
- surface = cairo_ps_surface_create (file, w, h);
+ surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
- strcat(file, ".pdf");
- surface = cairo_pdf_surface_create (file, w, h);
+ surface = cairo_pdf_surface_create(outFile, w, h);
} else if (svg) {
- strcat(file, ".svg");
- surface = cairo_svg_surface_create (file, w, h);
+ surface = cairo_svg_surface_create(outFile, w, h);
}
return surface;
@@ -156,12 +167,8 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
static void end_page(cairo_surface_t *surface, char *outFile)
{
- char file[OUT_FILE_SZ];
-
- strcpy(file, outFile);
if (png) {
- strcat(file, ".png");
- cairo_surface_write_to_png (surface, file);
+ cairo_surface_write_to_png(surface, outFile);
} else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
@@ -231,7 +238,7 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
int main(int argc, char *argv[]) {
PDFDoc *doc;
GooString *fileName = NULL;
- char *outRoot;
+ char *outRoot = NULL;
char outFile[OUT_FILE_SZ];
GooString *ownerPW, *userPW;
GBool ok;
@@ -270,15 +277,14 @@ int main(int argc, char *argv[]) {
goto err0;
}
- fileName = new GooString(argv[1]);
- if (argc == 3)
+ if (argc > 1) fileName = new GooString(argv[1]);
+ if (argc == 3) {
outRoot = strdup(argv[2]);
- else
- outRoot = strdup(argv[1]);
- p = strrchr(outRoot, '.');
- if (p)
- *p = 0;
+ p = strrchr(outRoot, '.');
+ if (p)
+ *p = 0;
+ }
// read config file
globalParams = new GlobalParams();
@@ -345,12 +351,12 @@ int main(int argc, char *argv[]) {
// Enable printing mode for all output types except PNG
printing = (png) ? gFalse : gTrue;
+
+ format_output_filename(outFile, outRoot, pg_num_len, pg);
- surface = start_page(outRoot, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ surface = start_page(outFile, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
render_page(output_dev, doc, surface, printing, pg,
x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
- snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
- OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
end_page(surface, outFile);
}
cairo_surface_finish(surface);
--
1.7.0.4
>From e931603d0953ce8cea5b3554b39f84d239852780 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Tue, 13 Jul 2010 14:53:34 +0100
Subject: [PATCH 05/10] pdftocairo: Updated to use PDFDocFactory.
---
utils/pdftocairo.cc | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 9c4981f..a832e8c 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -39,6 +39,7 @@
#include "GlobalParams.h"
#include "Object.h"
#include "PDFDoc.h"
+#include "PDFDocFactory.h"
#include "CairoOutputDev.h"
#define OUT_FILE_SZ 512
@@ -133,6 +134,8 @@ static const ArgDesc argDesc[] = {
static void format_output_filename(char *outFile, char *outRoot,
int pg_num_len, int pg)
{
+ if (!outRoot) outRoot = "cairoout";
+
snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
@@ -303,7 +306,17 @@ int main(int argc, char *argv[]) {
} else {
userPW = NULL;
}
- doc = new PDFDoc(fileName, ownerPW, userPW);
+
+ if (fileName == NULL) {
+ fileName = new GooString("fd://0");
+ }
+ if (fileName->cmp("-") == 0) {
+ delete fileName;
+ fileName = new GooString("fd://0");
+ }
+ doc = PDFDocFactory().createPDFDoc(*fileName, ownerPW, userPW);
+ delete fileName;
+
if (userPW) {
delete userPW;
}
--
1.7.0.4
>From abc53481cdf2bccecb4ddd07c34437608dad9d47 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Thu, 15 Jul 2010 04:12:04 +0100
Subject: [PATCH 06/10] pdftocairo: Added -jpeg output option.
---
utils/pdftocairo.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index a832e8c..8e5db15 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -36,6 +36,7 @@
#include "parseargs.h"
#include "goo/gmem.h"
#include "goo/GooString.h"
+#include "goo/JpegWriter.h"
#include "GlobalParams.h"
#include "Object.h"
#include "PDFDoc.h"
@@ -59,6 +60,7 @@ static int h = 0;
static int sz = 0;
static GBool useCropBox = gFalse;
static GBool png = gFalse;
+static GBool jpg = gFalse;
static GBool ps = gFalse;
static GBool pdf = gFalse;
static GBool svg = gFalse;
@@ -102,11 +104,13 @@ static const ArgDesc argDesc[] = {
{"-png", argFlag, &png, 0,
"generate a PNG file"},
- {"-ps", argFlag, &ps, 0,
+ {"-jpeg", argFlag, &jpg, 0,
+ "generate a JPEG file"},
+ {"-ps", argFlag, &ps, 0,
"generate PostScript file"},
- {"-pdf", argFlag, &pdf, 0,
+ {"-pdf", argFlag, &pdf, 0,
"generate a PDF file"},
- {"-svg", argFlag, &svg, 0,
+ {"-svg", argFlag, &svg, 0,
"generate a SVG file"},
@@ -141,6 +145,8 @@ static void format_output_filename(char *outFile, char
*outRoot,
if (png) {
strcat(outFile, ".png");
+ } else if (jpg) {
+ strcat(outFile, ".jpg");
} else if (ps) {
strcat(outFile, ".ps");
} else if (pdf) {
@@ -157,6 +163,8 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
if (png) {
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ } else if (jpg) {
+ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
@@ -168,10 +176,43 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
return surface;
}
+static void end_page_jpeg(cairo_surface_t *surface, char *outFile)
+{
+ unsigned char *p;
+ int width, height, stride, i, j;
+ FILE *f;
+ JpegWriter *writer;
+ unsigned char *row;
+
+ width = cairo_image_surface_get_width(surface);
+ height = cairo_image_surface_get_height(surface);
+ stride = cairo_image_surface_get_stride(surface);
+ p = cairo_image_surface_get_data(surface);
+
+ f = fopen(outFile, "w");
+ writer = new JpegWriter();
+ writer->init(f, width, height, 72, 72);
+
+ row = new unsigned char[3 * width];
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ row[3*j] = p[j * 4 + 2];
+ row[3*j+1] = p[j * 4 + 1];
+ row[3*j+2] = p[j * 4];
+ }
+
+ writer->writeRow(&row);
+ p += stride;
+ }
+ writer->close();
+}
+
static void end_page(cairo_surface_t *surface, char *outFile)
{
if (png) {
cairo_surface_write_to_png(surface, outFile);
+ } else if (jpg) {
+ end_page_jpeg(surface, outFile);
} else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
@@ -194,6 +235,7 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
h = (y+h > pg_h ? (int)ceil(pg_h-y) : h);
cr = cairo_create (surface);
+
cairo_save (cr);
output_dev->setCairo (cr);
output_dev->setPrinting (printing);
@@ -201,6 +243,13 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
if (!printing)
cairo_scale (cr, x_res/72.0, y_res/72.0);
+ // JPEGs are non-transparent, so we need a white background
+ if (jpg) {
+ cairo_rectangle(cr, 0, 0, w, h);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+ }
+
text = new TextPage(gFalse);
if (!printing)
output_dev->setTextPage (text);
@@ -275,8 +324,8 @@ int main(int argc, char *argv[]) {
goto err0;
}
- if (!png && !ps && !pdf && !svg) {
- fprintf(stderr, "One of -png, -ps, -pdf or -svg must be specified\n");
+ if (!png && !jpg && !ps && !pdf && !svg) {
+ fprintf(stderr, "One of -png, -jpeg, -ps, -pdf or -svg must be
specified\n");
goto err0;
}
@@ -363,7 +412,7 @@ int main(int argc, char *argv[]) {
}
// Enable printing mode for all output types except PNG
- printing = (png) ? gFalse : gTrue;
+ printing = (png || jpg) ? gFalse : gTrue;
format_output_filename(outFile, outRoot, pg_num_len, pg);
--
1.7.0.4
>From 632b4b513acf82a6e1a5fd579dbdefaf9154fa68 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Thu, 15 Jul 2010 16:24:42 +0100
Subject: [PATCH 07/10] pdftocairo: Added manpage.
---
utils/Makefile.am | 5 ++-
utils/pdftocairo.1 | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 129 insertions(+), 1 deletions(-)
create mode 100644 utils/pdftocairo.1
diff --git a/utils/Makefile.am b/utils/Makefile.am
index ac08b5e..a551fe5 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -49,6 +49,8 @@ pdftocairo_LDADD = $(LDADD) $(CAIRO_LIBS) \
pdftocairo_binary = pdftocairo
+pdftocairo_manpage = pdftocairo.1
+
endif
AM_LDFLAGS = @auto_import_flags@
@@ -71,7 +73,8 @@ dist_man1_MANS = \
pdftops.1 \
pdftotext.1 \
pdftohtml.1 \
- $(pdftoppm_manpage)
+ $(pdftoppm_manpage) \
+ $(pdftocairo_manpage)
common = parseargs.c parseargs.h
diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1
new file mode 100644
index 0000000..376c133
--- /dev/null
+++ b/utils/pdftocairo.1
@@ -0,0 +1,125 @@
+.\" Copyright 2010 Stefan Thomas
+.TH pdftocairo 1 "17 July 2010"
+.SH NAME
+pdftocairo \- Portable Document Format (PDF) converter using Cairo
+converter (version 1.00)
+.SH SYNOPSIS
+.B pdftocairo
+[options]
+.I PDF-file Out-root
+.SH DESCRIPTION
+.B Pdftocairo
+converts Portable Document Format (PDF) files to vector based (PDF, PS, SVG)
and
+non-vector based (PNG, JPEG) formats.
+.PP
+Pdftocairo reads the PDF file,
+.IR PDF-file ,
+and writes one output file for each page,
+.IR Out-root - nnnnnn .[format],
+where
+.I nnnnnn
+is the page number.
+.SH OPTIONS
+.TP
+.BI \-f " number"
+Specifies the first page to convert.
+.TP
+.BI \-l " number"
+Specifies the last page to convert.
+.TP
+.BI \-r " number"
+Specifies the X and Y resolution, in DPI. The default is 150 DPI.
+.TP
+.BI \-rx " number"
+Specifies the X resolution, in DPI. The default is 150 DPI.
+.TP
+.BI \-ry " number"
+Specifies the Y resolution, in DPI. The default is 150 DPI.
+.TP
+.BI \-scale-to " number"
+Scales each page to fit in scale-to*scale-to pixel box.
+.TP
+.BI \-scale-to-x " number"
+Scales each page horizontally to fit in scale-to-x pixels.
+.TP
+.BI \-scale-to-y " number"
+Scales each page vertically to fit in scale-to-y pixels.
+.TP
+.BI \-x " number"
+Specifies the x-coordinate of the crop area top left corner
+.TP
+.BI \-y " number"
+Specifies the y-coordinate of the crop area top left corner
+.TP
+.BI \-W " number"
+Specifies the width of crop area in pixels (default is 0)
+.TP
+.BI \-H " number"
+Specifies the height of crop area in pixels (default is 0)
+.TP
+.BI \-sz " number"
+Specifies the size of crop square in pixels (sets W and H)
+.TP
+.B \-cropbox
+Uses the crop box rather than media box when generating the files
+.TP
+.B \-png
+Generates a PNG file
+.TP
+.B \-jpeg
+Generates a JPEG file
+.TP
+.B \-ps
+Generates a PS file
+.TP
+.B \-pdf
+Generates a PDF file
+.TP
+.B \-svg
+Generates a SVG file
+.TP
+.BI \-opw " password"
+Specify the owner password for the PDF file. Providing this will
+bypass all security restrictions.
+.TP
+.BI \-upw " password"
+Specify the user password for the PDF file.
+.TP
+.B \-q
+Don't print any messages or errors.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXIT CODES
+The poppler tools use the following exit codes:
+.TP
+0
+No error.
+.TP
+1
+Error opening a PDF file.
+.TP
+2
+Error opening an output file.
+.TP
+3
+Error related to PDF permissions.
+.TP
+99
+Other error.
+.SH AUTHOR
+The pdftocairo software and documentation are copyright 2009 Adrian Johnson
and 2010 Stefan Thomas
+.SH "SEE ALSO"
+.BR pdftoppm (1),
+.BR pdftops (1),
+.BR pdftotext (1),
+.BR pdfinfo (1),
+.BR pdffonts (1),
+.BR pdfimages (1),
--
1.7.0.4
>From afc2c809323380dcb5301b2275993f1a455b039a Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Thu, 15 Jul 2010 16:24:55 +0100
Subject: [PATCH 08/10] pdftocairo: Added to CMake build system.
---
utils/CMakeLists.txt | 21 ++++++++++++++++++++-
1 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index f8e8f4c..7bd982e 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -1,4 +1,3 @@
-
set(common_srcs
parseargs.c
)
@@ -20,6 +19,26 @@ if (ENABLE_SPLASH)
install(FILES pdftoppm.1 DESTINATION share/man/man1)
endif (ENABLE_SPLASH)
+if (HAVE_CAIRO)
+ # pdftocairo
+ set(pdftocairo_SOURCES ${common_srcs}
+ pdftocairo.cc
+ ${CMAKE_SOURCE_DIR}/poppler/CairoFontEngine.cc
+ ${CMAKE_SOURCE_DIR}/poppler/CairoOutputDev.cc
+ ${CMAKE_SOURCE_DIR}/poppler/CairoRescaleBox.cc
+ )
+ include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CAIRO_INCLUDE_DIRS}
+ )
+ add_definitions(${CAIRO_CFLAGS})
+ add_executable(pdftocairo ${pdftocairo_SOURCES})
+ target_link_libraries(pdftocairo ${CAIRO_LIBRARIES} ${common_libs})
+ install(TARGETS pdftocairo DESTINATION bin)
+ install(FILES pdftocairo.1 DESTINATION share/man/man1)
+endif (HAVE_CAIRO)
+
# pdffonts
set(pdffonts_SOURCES ${common_srcs}
pdffonts.cc
--
1.7.0.4
>From 87051c878567befecffcc5b092f30407fd7b1000 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Fri, 16 Jul 2010 19:53:22 +0100
Subject: [PATCH 09/10] Minor fixes based on reviewer feedback (memory leaks,
removed TextPage instance).
---
utils/pdftocairo.cc | 37 +++++++++++++------------------------
1 files changed, 13 insertions(+), 24 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 8e5db15..dd9ef41 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -135,7 +135,7 @@ static const ArgDesc argDesc[] = {
};
-static void format_output_filename(char *outFile, char *outRoot,
+static void format_output_filename(char *outFile, const char *outRoot,
int pg_num_len, int pg)
{
if (!outRoot) outRoot = "cairoout";
@@ -164,7 +164,7 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
if (png) {
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (jpg) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w*x_res/72.0,
h*y_res/72.0);
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
@@ -205,6 +205,9 @@ static void end_page_jpeg(cairo_surface_t *surface, char
*outFile)
p += stride;
}
writer->close();
+
+ delete writer;
+ delete[] row;
}
static void end_page(cairo_surface_t *surface, char *outFile)
@@ -227,7 +230,6 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
{
cairo_t *cr;
cairo_status_t status;
- TextPage *text = NULL;
if (w == 0) w = (int)ceil(pg_w);
if (h == 0) h = (int)ceil(pg_h);
@@ -243,17 +245,6 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
if (!printing)
cairo_scale (cr, x_res/72.0, y_res/72.0);
- // JPEGs are non-transparent, so we need a white background
- if (jpg) {
- cairo_rectangle(cr, 0, 0, w, h);
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_fill(cr);
- }
-
- text = new TextPage(gFalse);
- if (!printing)
- output_dev->setTextPage (text);
-
/* NOTE: instead of passing -1 we should/could use cairo_clip_extents()
* to get a bounding box */
cairo_save (cr);
@@ -266,8 +257,8 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
cairo_restore(cr);
output_dev->setCairo(NULL);
- output_dev->setTextPage(NULL);
+ // Add a white background
if (!printing) {
cairo_save(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
@@ -281,9 +272,6 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
cairo_destroy (cr);
- if (text != NULL)
- text->decRefCnt();
-
return 0;
}
@@ -296,7 +284,7 @@ int main(int argc, char *argv[]) {
GBool ok;
int exitCode;
int pg, pg_num_len;
- double pg_w, pg_h, tmp;
+ double pg_w, pg_h;
char *p;
CairoOutputDev *output_dev;
cairo_surface_t *surface;
@@ -420,12 +408,12 @@ int main(int argc, char *argv[]) {
render_page(output_dev, doc, surface, printing, pg,
x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
end_page(surface, outFile);
+ cairo_surface_finish(surface);
+ status = cairo_surface_status(surface);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
+ cairo_surface_destroy(surface);
}
- cairo_surface_finish(surface);
- status = cairo_surface_status(surface);
- if (status)
- fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
- cairo_surface_destroy(surface);
delete output_dev;
exitCode = 0;
@@ -434,6 +422,7 @@ int main(int argc, char *argv[]) {
err1:
delete doc;
delete globalParams;
+ if (outRoot) free(outRoot);
err0:
// check for memory leaks
--
1.7.0.4
>From 896d9b2384245d1be7f856bd5d020d7d52d21b22 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Tue, 20 Jul 2010 16:27:26 +0100
Subject: [PATCH 10/10] pdftocairo: Re-added ability for output as multipage
files.
---
utils/pdftocairo.1 | 4 ++
utils/pdftocairo.cc | 81 ++++++++++++++++++++++++++++++++++-----------------
2 files changed, 58 insertions(+), 27 deletions(-)
diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1
index 376c133..b56a949 100644
--- a/utils/pdftocairo.1
+++ b/utils/pdftocairo.1
@@ -27,6 +27,10 @@ Specifies the first page to convert.
.BI \-l " number"
Specifies the last page to convert.
.TP
+.B \-split
+Always split the output into one file per page. The default is to have one file
+for all extracted pages if the output format supports it.
+.TP
.BI \-r " number"
Specifies the X and Y resolution, in DPI. The default is 150 DPI.
.TP
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index dd9ef41..d12f9ce 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -50,6 +50,7 @@ static int lastPage = 0;
static double resolution = 0.0;
static double x_resolution = 150.0;
static double y_resolution = 150.0;
+static GBool split = gFalse;
static int scaleTo = 0;
static int x_scaleTo = 0;
static int y_scaleTo = 0;
@@ -75,6 +76,8 @@ static const ArgDesc argDesc[] = {
"first page to print"},
{"-l", argInt, &lastPage, 0,
"last page to print"},
+ {"-split", argFlag, &split, 0,
+ "force one file per page"},
{"-r", argFP, &resolution, 0,
"resolution, in DPI (default is 150)"},
@@ -156,27 +159,30 @@ static void format_output_filename(char *outFile, const
char *outRoot,
}
}
-static cairo_surface_t *start_page(char *outFile, int w, int h,
+static cairo_surface_t *create_surface(char *outFile, int w, int h,
double x_res, double y_res, int rotate)
{
cairo_surface_t *surface;
-
- if (png) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
- } else if (jpg) {
- surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
- } else if (ps) {
+
+ if (ps) {
surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
surface = cairo_pdf_surface_create(outFile, w, h);
} else if (svg) {
surface = cairo_svg_surface_create(outFile, w, h);
+
+ // If the user requests multipage output, we need at least SVG 1.2
+ if (!split) cairo_svg_surface_restrict_to_version(surface,
CAIRO_SVG_VERSION_1_2);
+ } else if (png) {
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ } else if (jpg) {
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
}
return surface;
}
-static void end_page_jpeg(cairo_surface_t *surface, char *outFile)
+static void end_file_jpeg(cairo_surface_t *surface, const char *outFile)
{
unsigned char *p;
int width, height, stride, i, j;
@@ -210,15 +216,21 @@ static void end_page_jpeg(cairo_surface_t *surface, char
*outFile)
delete[] row;
}
-static void end_page(cairo_surface_t *surface, char *outFile)
+static void end_file(cairo_surface_t *surface, const char *outFile)
{
+ cairo_status_t status;
+
if (png) {
cairo_surface_write_to_png(surface, outFile);
} else if (jpg) {
- end_page_jpeg(surface, outFile);
- } else if (ps || pdf || svg) {
- cairo_surface_show_page(surface);
+ end_file_jpeg(surface, outFile);
}
+
+ cairo_surface_finish(surface);
+ status = cairo_surface_status(surface);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
+ cairo_surface_destroy(surface);
}
static int render_page(CairoOutputDev *output_dev, PDFDoc *doc,
@@ -271,6 +283,9 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
if (status)
fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
cairo_destroy (cr);
+
+ // Emit and clear page on supporting surfaces (SVG, PDF, PS)
+ cairo_surface_show_page(surface);
return 0;
}
@@ -287,8 +302,7 @@ int main(int argc, char *argv[]) {
double pg_w, pg_h;
char *p;
CairoOutputDev *output_dev;
- cairo_surface_t *surface;
- cairo_status_t status;
+ cairo_surface_t *surface = NULL;
GBool printing;
exitCode = 99;
@@ -316,6 +330,9 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "One of -png, -jpeg, -ps, -pdf or -svg must be
specified\n");
goto err0;
}
+
+ // JPEG and PNG don't support multiple pages
+ split = split || jpg || png;
if (argc > 1) fileName = new GooString(argv[1]);
if (argc == 3) {
@@ -373,11 +390,16 @@ int main(int argc, char *argv[]) {
if (sz != 0)
w = h = sz;
-
+
output_dev = new CairoOutputDev();
output_dev->startDoc(doc->getXRef(), doc->getCatalog());
+ // Enable printing mode for all output types except PNG
+ printing = (png || jpg) ? gFalse : gTrue;
+
+ // Calculate number of digits in output file name
pg_num_len = (int)ceil(log((double)doc->getNumPages()) / log((double)10));
+
for (pg = firstPage; pg <= lastPage; ++pg) {
if (useCropBox) {
pg_w = doc->getPageCropWidth(pg);
@@ -399,21 +421,26 @@ int main(int argc, char *argv[]) {
}
}
- // Enable printing mode for all output types except PNG
- printing = (png || jpg) ? gFalse : gTrue;
-
+ // Note that we always generate filenames for all pages, even if we only
+ // use the first one.
format_output_filename(outFile, outRoot, pg_num_len, pg);
-
- surface = start_page(outFile, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+
+ if (!surface) surface = create_surface(outFile,
+ pg_w, pg_h,
+ x_resolution, y_resolution,
+ doc->getPageRotate(pg));
+
render_page(output_dev, doc, surface, printing, pg,
- x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
- end_page(surface, outFile);
- cairo_surface_finish(surface);
- status = cairo_surface_status(surface);
- if (status)
- fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
- cairo_surface_destroy(surface);
+ x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
+
+ // In multiple file mode, we're done with this surface
+ if (split) {
+ end_file(surface, outFile);
+ surface = NULL;
+ }
}
+
+ if (surface) end_file(surface, outFile);
delete output_dev;
exitCode = 0;
--
1.7.0.4
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler