[PATCH 10/10] pdftocairo: Re-added ability for output as multipage files.

Stefan Thomas thomas at txtbear.com
Tue Jul 20 08:27:26 PDT 2010


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


--------------050505050001050507090905--


More information about the poppler mailing list