X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcairo.c;h=a08771bb449ae68cb2d0d126c3c439a0e2907395;hb=d98583b9425b8a053dc21b539203406bac74adc5;hp=a3fb1b7d13b184bf9b8eb9198ac6c816a0e375fc;hpb=13ca98079f4cb3cd80deb10b173813548b1f3ddc;p=pspp diff --git a/src/output/cairo.c b/src/output/cairo.c index a3fb1b7d13..a08771bb44 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -26,6 +26,7 @@ #include "output/cairo-pager.h" #include "output/driver-provider.h" #include "output/options.h" +#include "output/output-item.h" #include "output/table.h" #include @@ -186,7 +187,7 @@ 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 xr_driver *xr = XZALLOC (struct xr_driver); struct output_driver *d = &xr->driver; output_driver_init (d, &cairo_driver_class, name, device_type); @@ -218,10 +219,8 @@ xr_allocate (const char *name, int device_type, min_break[a] = size[a] / 2; int font_size = parse_int (opt (d, o, "font-size", "10000"), 1000, 1000000); - PangoFontDescription *fixed_font = parse_font_option - (d, o, "fixed-font", "monospace", font_size, false, false); - PangoFontDescription *proportional_font = parse_font_option ( - d, o, "prop-font", "sans serif", font_size, false, false); + 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")); @@ -238,6 +237,14 @@ xr_allocate (const char *name, int device_type, 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, @@ -248,7 +255,7 @@ xr_allocate (const char *name, int device_type, }, .initial_page_number = 1, - .object_spacing = object_spacing, + .include_outline = include_outline, }; xr->fsm_style = xmalloc (sizeof *xr->fsm_style); @@ -256,12 +263,10 @@ xr_allocate (const char *name, int device_type, .ref_cnt = 1, .size = { [H] = size[H], [V] = size[V] }, .min_break = { [H] = min_break[H], [V] = min_break[V] }, - .fonts = { - [XR_FONT_PROPORTIONAL] = proportional_font, - [XR_FONT_FIXED] = fixed_font, - }, + .font = font, .fg = fg, .use_system_colors = systemcolors, + .object_spacing = object_spacing, .font_resolution = font_resolution, }; @@ -390,12 +395,14 @@ static void xr_report_error (cairo_status_t status, const char *file_name) { if (status != CAIRO_STATUS_SUCCESS) - fprintf (stderr, "%s: %s", file_name, cairo_status_to_string (status)); + fprintf (stderr, "%s: %s\n", file_name, cairo_status_to_string (status)); } static void xr_finish_page (struct xr_driver *xr) { + xr_pager_finish_page (xr->pager); + /* For 'trim' true: - If the destination is PDF or PostScript, set the dest surface size, copy @@ -525,6 +532,8 @@ xr_destroy (struct output_driver *driver) if (xr->pager) xr_finish_page (xr); + xr_pager_destroy (xr->pager); + if (xr->drawing_surface && xr->drawing_surface != xr->dest_surface) cairo_surface_destroy (xr->drawing_surface); if (xr->dest_surface) @@ -532,13 +541,12 @@ xr_destroy (struct output_driver *driver) cairo_surface_finish (xr->dest_surface); cairo_status_t status = cairo_surface_status (xr->dest_surface); if (status != CAIRO_STATUS_SUCCESS) - fprintf (stderr, _("error drawing output for %s driver: %s"), + fprintf (stderr, _("error drawing output for %s driver: %s\n"), output_driver_get_name (driver), cairo_status_to_string (status)); cairo_surface_destroy (xr->dest_surface); } - xr_pager_destroy (xr->pager); xr_page_style_unref (xr->page_style); xr_fsm_style_unref (xr->fsm_style); free (xr); @@ -546,79 +554,81 @@ xr_destroy (struct output_driver *driver) static void xr_update_page_setup (struct output_driver *driver, - const struct page_setup *ps) + const struct page_setup *setup) { struct xr_driver *xr = xr_driver_cast (driver); const double scale = 72 * XR_POINT; - int swap = ps->orientation == PAGE_LANDSCAPE; + int swap = setup->orientation == PAGE_LANDSCAPE; enum table_axis h = H ^ swap; enum table_axis v = V ^ swap; - xr_page_style_unref (xr->page_style); + struct xr_page_style *old_ps = xr->page_style; xr->page_style = xmalloc (sizeof *xr->page_style); *xr->page_style = (struct xr_page_style) { .ref_cnt = 1, .margins = { - [H] = { ps->margins[h][0] * scale, ps->margins[h][1] * scale }, - [V] = { ps->margins[v][0] * scale, ps->margins[v][1] * scale }, + [H] = { setup->margins[h][0] * scale, setup->margins[h][1] * scale }, + [V] = { setup->margins[v][0] * scale, setup->margins[v][1] * scale }, }, - .initial_page_number = ps->initial_page_number, - .object_spacing = ps->object_spacing * 72 * XR_POINT, + .initial_page_number = setup->initial_page_number, + .include_outline = old_ps->include_outline, }; for (size_t i = 0; i < 2; i++) - page_heading_copy (&xr->page_style->headings[i], &ps->headings[i]); + page_heading_copy (&xr->page_style->headings[i], &setup->headings[i]); + xr_page_style_unref (old_ps); struct xr_fsm_style *old_fs = xr->fsm_style; xr->fsm_style = xmalloc (sizeof *xr->fsm_style); *xr->fsm_style = (struct xr_fsm_style) { .ref_cnt = 1, - .size = { [H] = ps->paper[H] * scale, [V] = ps->paper[V] * scale }, + .size = { [H] = setup->paper[H] * scale, [V] = setup->paper[V] * scale }, .min_break = { - [H] = ps->paper[H] * scale / 2, - [V] = ps->paper[V] * scale / 2, + [H] = setup->paper[H] * scale / 2, + [V] = setup->paper[V] * scale / 2, }, + .font = pango_font_description_copy (old_fs->font), .fg = old_fs->fg, .use_system_colors = old_fs->use_system_colors, + .object_spacing = setup->object_spacing * 72 * XR_POINT, .font_resolution = old_fs->font_resolution, }; - for (size_t i = 0; i < XR_N_FONTS; i++) - xr->fsm_style->fonts[i] = pango_font_description_copy (old_fs->fonts[i]); xr_fsm_style_unref (old_fs); - xr_set_surface_size (xr->dest_surface, xr->output_type, ps->paper[H] * 72.0, - ps->paper[V] * 72.0); + xr_set_surface_size (xr->dest_surface, xr->output_type, + setup->paper[H] * 72.0, setup->paper[V] * 72.0); } static void -xr_submit (struct output_driver *driver, const struct output_item *output_item) +xr_submit (struct output_driver *driver, const struct output_item *item) { struct xr_driver *xr = xr_driver_cast (driver); - if (is_page_setup_item (output_item)) - { - if (!xr->pager) - xr_update_page_setup (driver, - to_page_setup_item (output_item)->page_setup); - return; - } - if (!xr->pager) { xr->pager = xr_pager_create (xr->page_style, xr->fsm_style); xr_pager_add_page (xr->pager, cairo_create (xr->drawing_surface)); } - xr_pager_add_item (xr->pager, output_item); + xr_pager_add_item (xr->pager, item); while (xr_pager_needs_new_page (xr->pager)) { xr_finish_page (xr); xr_pager_add_page (xr->pager, cairo_create (xr->drawing_surface)); } } + +static void +xr_setup (struct output_driver *driver, const struct page_setup *ps) +{ + struct xr_driver *xr = xr_driver_cast (driver); + + if (!xr->pager) + xr_update_page_setup (driver, ps); +} struct output_driver_factory pdf_driver_factory = { "pdf", "pspp.pdf", xr_pdf_create }; @@ -631,8 +641,9 @@ struct output_driver_factory png_driver_factory = static const struct output_driver_class cairo_driver_class = { - "cairo", - xr_destroy, - xr_submit, - NULL, + .name = "cairo", + .destroy = xr_destroy, + .submit = xr_submit, + .setup = xr_setup, + .handles_groups = true, };