From be53a7a37e9159dfd7e629e92b08c708d339f162 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 25 Dec 2020 21:54:48 -0800 Subject: [PATCH] cairo: Avoid using cairo_t for a destroyed cairo_surface_t. xr_pager_destroy() would destroy the latest cairo_t, if there was one. Generally there wasn't, since in the common case it got destroyed by xr_pager_run() when the fsm emptied out, but in the case of the last page in a produced output file, xr_destroy() would call xr_pager_destroy() after first destroying the surface_t it was drawing on. I don't think this is an actual bug, because everything is properly reference-counted inside Cairo (the cairo_t holds a reference on its cairo_surface_t) but I found it confusing. --- src/output/cairo-pager.c | 18 ++++++++++++------ src/output/cairo-pager.h | 1 + src/output/cairo.c | 5 ++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/output/cairo-pager.c b/src/output/cairo-pager.c index f23ad5faa2..e771e1a03b 100644 --- a/src/output/cairo-pager.c +++ b/src/output/cairo-pager.c @@ -298,17 +298,23 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) xr_pager_run (p); } +void +xr_pager_finish_page (struct xr_pager *p) +{ + if (p->cr) + { + cairo_restore (p->cr); + cairo_destroy (p->cr); + p->cr = NULL; + } +} + bool xr_pager_needs_new_page (struct xr_pager *p) { if (p->item && (!p->cr || p->y >= p->fsm_style->size[V])) { - if (p->cr) - { - cairo_restore (p->cr); - cairo_destroy (p->cr); - p->cr = NULL; - } + xr_pager_finish_page (p); return true; } else diff --git a/src/output/cairo-pager.h b/src/output/cairo-pager.h index 87dcd367f7..47b49199df 100644 --- a/src/output/cairo-pager.h +++ b/src/output/cairo-pager.h @@ -63,6 +63,7 @@ void xr_pager_add_item (struct xr_pager *, const struct output_item *); bool xr_pager_has_page (const struct xr_pager *); void xr_pager_add_page (struct xr_pager *, cairo_t *); +void xr_pager_finish_page (struct xr_pager *); bool xr_pager_needs_new_page (struct xr_pager *); #endif /* HAVE_CAIRO */ diff --git a/src/output/cairo.c b/src/output/cairo.c index fdcf67fd3a..00ac472f7c 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -396,6 +396,8 @@ xr_report_error (cairo_status_t status, const char *file_name) 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 +527,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) @@ -538,7 +542,6 @@ xr_destroy (struct output_driver *driver) 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); -- 2.30.2