cairo: Allow xr_driver_create()'s caller to usefully set more options.
[pspp-builds.git] / src / output / cairo.c
index a415e5bd8701626a5584038b4e5bcd9ee2345048..a1445bcfe1c5b3763797a88ca5ba1b8061b59ced 100644 (file)
@@ -136,8 +136,6 @@ struct xr_driver
     int line_space;            /* Space between lines. */
     int line_width;            /* Width of lines. */
 
-    enum xr_output_type file_type; /* Type of output file. */
-
     /* Internal state. */
     struct render_params *params;
     char *command_name;
@@ -190,13 +188,13 @@ opt (struct output_driver *d, struct string_map *options, const char *key,
 static struct xr_driver *
 xr_allocate (const char *name, int device_type, struct string_map *o)
 {
+  int paper_width, paper_length;
   struct output_driver *d;
   struct xr_driver *xr;
 
   xr = xzalloc (sizeof *xr);
   d = &xr->driver;
   output_driver_init (d, &cairo_driver_class, name, device_type);
-  xr->headers = true;
   xr->font_height = XR_POINT * 10;
   xr->fonts[XR_FONT_FIXED].string
     = parse_string (opt (d, o, "fixed-font", "monospace"));
@@ -207,7 +205,20 @@ xr_allocate (const char *name, int device_type, struct string_map *o)
   xr->line_gutter = XR_POINT;
   xr->line_space = XR_POINT;
   xr->line_width = XR_POINT / 2;
-  xr->page_number = 1;
+  xr->page_number = 0;
+
+  xr->headers = parse_boolean (opt (d, o, "headers", "true"));
+
+  parse_paper_size (opt (d, o, "paper-size", ""), &paper_width, &paper_length);
+  xr->left_margin = parse_dimension (opt (d, o, "left-margin", ".5in"));
+  xr->right_margin = parse_dimension (opt (d, o, "right-margin", ".5in"));
+  xr->top_margin = parse_dimension (opt (d, o, "top-margin", ".5in"));
+  xr->bottom_margin = parse_dimension (opt (d, o, "bottom-margin", ".5in"));
+
+  if (xr->headers)
+    xr->top_margin += 3 * xr->font_height;
+  xr->width = paper_width - xr->left_margin - xr->right_margin;
+  xr->length = paper_length - xr->top_margin - xr->bottom_margin;
 
   return xr;
 }
@@ -263,33 +274,17 @@ xr_create (const char *file_name, enum settings_output_devices device_type,
   cairo_surface_t *surface;
   cairo_status_t status;
   double width_pt, length_pt;
-  int paper_width, paper_length;
 
   xr = xr_allocate (file_name, device_type, o);
   d = &xr->driver;
 
-  xr->headers = parse_boolean (opt (d, o, "headers", "true"));
-
-  xr->file_type = file_type;
-
-  parse_paper_size (opt (d, o, "paper-size", ""), &paper_width, &paper_length);
-  xr->left_margin = parse_dimension (opt (d, o, "left-margin", ".5in"));
-  xr->right_margin = parse_dimension (opt (d, o, "right-margin", ".5in"));
-  xr->top_margin = parse_dimension (opt (d, o, "top-margin", ".5in"));
-  xr->bottom_margin = parse_dimension (opt (d, o, "bottom-margin", ".5in"));
-
-  if (xr->headers)
-    xr->top_margin += 3 * xr->font_height;
-  xr->width = paper_width - xr->left_margin - xr->right_margin;
-  xr->length = paper_length - xr->top_margin - xr->bottom_margin;
-
-  width_pt = paper_width / 1000.0;
-  length_pt = paper_length / 1000.0;
-  if (xr->file_type == XR_PDF)
+  width_pt = (xr->width + xr->left_margin + xr->right_margin) / 1000.0;
+  length_pt = (xr->length + xr->top_margin + xr->bottom_margin) / 1000.0;
+  if (file_type == XR_PDF)
     surface = cairo_pdf_surface_create (file_name, width_pt, length_pt);
-  else if (xr->file_type == XR_PS)
+  else if (file_type == XR_PS)
     surface = cairo_ps_surface_create (file_name, width_pt, length_pt);
-  else if (xr->file_type == XR_SVG)
+  else if (file_type == XR_SVG)
     surface = cairo_svg_surface_create (file_name, width_pt, length_pt);
   else
     NOT_REACHED ();
@@ -306,13 +301,12 @@ xr_create (const char *file_name, enum settings_output_devices device_type,
   xr->cairo = cairo_create (surface);
   cairo_surface_destroy (surface);
 
-  cairo_translate (xr->cairo,
-                   xr_to_pt (xr->left_margin),
-                   xr_to_pt (xr->top_margin));
-
   if (!xr_set_cairo (xr, xr->cairo))
     goto error;
 
+  cairo_save (xr->cairo);
+  xr_driver_next_page (xr, xr->cairo);
+
   if (xr->width / (xr->font_height / 2) < MIN_WIDTH)
     {
       error (0, 0, _("The defined page is not wide enough to hold at least %d "
@@ -435,7 +429,9 @@ xr_submit (struct output_driver *driver, const struct output_item *output_item)
   xr_driver_output_item (xr, output_item);
   while (xr_driver_need_new_page (xr))
     {
+      cairo_restore (xr->cairo);
       cairo_show_page (xr->cairo);
+      cairo_save (xr->cairo);
       xr_driver_next_page (xr, xr->cairo);
     }
 }
@@ -454,6 +450,11 @@ xr_submit (struct output_driver *driver, const struct output_item *output_item)
 void
 xr_driver_next_page (struct xr_driver *xr, cairo_t *cairo)
 {
+  if (cairo != NULL)
+    cairo_translate (cairo,
+                     xr_to_pt (xr->left_margin),
+                     xr_to_pt (xr->top_margin));
+
   xr->page_number++;
   xr->cairo = cairo;
   xr->y = 0;
@@ -919,8 +920,6 @@ struct xr_driver *
 xr_driver_create (cairo_t *cairo, struct string_map *options)
 {
   struct xr_driver *xr = xr_allocate ("cairo", 0, options);
-  xr->width = INT_MAX / 8;
-  xr->length = INT_MAX / 8;
   if (!xr_set_cairo (xr, cairo))
     {
       output_driver_destroy (&xr->driver);