+static struct xr_driver *
+xr_allocate (const char *name, int device_type,
+ enum xr_output_type output_type, struct string_map *o)
+{
+ struct xr_driver *xr = xzalloc (sizeof *xr);
+ struct output_driver *d = &xr->driver;
+
+ output_driver_init (d, &cairo_driver_class, name, device_type);
+ xr->output_type = output_type;
+
+ /* Scale factor from inch/72000 to inch/(72 * XR_POINT). */
+ const double scale = XR_POINT / 1000.;
+
+ int paper[TABLE_N_AXES];
+ parse_paper_size (opt (d, o, "paper-size", ""), &paper[H], &paper[V]);
+ for (int a = 0; a < TABLE_N_AXES; a++)
+ paper[a] *= scale;
+
+ int margins[TABLE_N_AXES][2];
+ margins[H][0] = parse_dimension (opt (d, o, "left-margin", ".5in")) * scale;
+ margins[H][1] = parse_dimension (opt (d, o, "right-margin", ".5in")) * scale;
+ margins[V][0] = parse_dimension (opt (d, o, "top-margin", ".5in")) * scale;
+ margins[V][1] = parse_dimension (opt (d, o, "bottom-margin", ".5in")) * scale;
+
+ int size[TABLE_N_AXES];
+ for (int a = 0; a < TABLE_N_AXES; a++)
+ size[a] = paper[a] - margins[a][0] - margins[a][1];
+
+ int min_break[TABLE_N_AXES];
+ min_break[H] = parse_dimension (opt (d, o, "min-hbreak", NULL)) * scale;
+ min_break[V] = parse_dimension (opt (d, o, "min-vbreak", NULL)) * scale;
+ for (int a = 0; a < TABLE_N_AXES; a++)
+ if (min_break[a] <= 0)
+ min_break[a] = size[a] / 2;
+
+ int font_size = parse_int (opt (d, o, "font-size", "10000"), 1000, 1000000);
+ PangoFontDescription *font = parse_font_option (
+ d, o, "prop-font", "Sans Serif", font_size, false, false);
+
+ struct cell_color fg = parse_color (opt (d, o, "foreground-color", "black"));
+
+ bool systemcolors = parse_boolean (opt (d, o, "systemcolors", "false"));
+
+ int object_spacing
+ = parse_dimension (opt (d, o, "object-spacing", NULL)) * scale;
+ if (object_spacing <= 0)
+ object_spacing = XR_POINT * 12;
+
+ const char *default_resolution = (output_type == XR_PNG ? "96" : "72");
+ int font_resolution = parse_int (opt (d, o, "font-resolution",
+ default_resolution), 10, 1000);
+
+ xr->trim = parse_boolean (opt (d, o, "trim", "false"));
+
+ /* Cairo 1.16.0 has a bug that causes crashes if outlines are enabled at the
+ same time as trimming:
+ https://lists.cairographics.org/archives/cairo/2020-December/029151.html
+ For now, just disable the outline if trimming is enabled. */
+ bool include_outline
+ = (output_type == XR_PDF
+ && parse_boolean (opt (d, o, "outline", xr->trim ? "false" : "true")));
+
+ xr->page_style = xmalloc (sizeof *xr->page_style);
+ *xr->page_style = (struct xr_page_style) {
+ .ref_cnt = 1,
+
+ .margins = {
+ [H] = { margins[H][0], margins[H][1], },
+ [V] = { margins[V][0], margins[V][1], },
+ },
+
+ .initial_page_number = 1,
+ .include_outline = include_outline,
+ };