From: Ben Pfaff Date: Mon, 14 Dec 2020 05:27:49 +0000 (-0800) Subject: Refactoring. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=512b5c3dbf65f26cd44b47abc6c43598ea865c1c;p=pspp Refactoring. --- diff --git a/src/output/cairo-pager.c b/src/output/cairo-pager.c index 224ad0381f..8a0f948cc8 100644 --- a/src/output/cairo-pager.c +++ b/src/output/cairo-pager.c @@ -28,6 +28,10 @@ #include "gettext.h" #define _(msgid) gettext (msgid) + +/* This file uses TABLE_HORZ and TABLE_VERT enough to warrant abbreviating. */ +#define H TABLE_HORZ +#define V TABLE_VERT struct xr_page_style * xr_page_style_ref (const struct xr_page_style *ps_) @@ -38,6 +42,25 @@ xr_page_style_ref (const struct xr_page_style *ps_) return ps; } +struct xr_page_style * +xr_page_style_unshare (struct xr_page_style *old) +{ + assert (old->ref_cnt > 0); + if (old->ref_cnt == 1) + return old; + + xr_page_style_unref (old); + + struct xr_page_style *new = xmemdup (old, sizeof *old); + new->ref_cnt = 1; + for (int i = 0; i < 2; i++) + page_heading_copy (&new->headings[i], &old->headings[i]); + if (old->font) + new->font = pango_font_description_copy (old->font); + + return new; +} + void xr_page_style_unref (struct xr_page_style *ps) { @@ -177,40 +200,42 @@ xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font, } static void -xr_measure_headings (struct xr_pager *p) +xr_measure_headings (const struct xr_page_style *ps, int heading_heights[2]) { - const struct xr_page_style *ps = p->page_style; - cairo_surface_t *surface = cairo_recording_surface_create ( CAIRO_CONTENT_COLOR, NULL); cairo_t *cairo = cairo_create (surface); for (int i = 0; i < 2; i++) { - int h = xr_render_page_heading (cairo, ps->font, &ps->headings[i], -1, - ps->size[TABLE_HORZ], false, 0); - - /* If the heading is nonempty, add a margin above or below it. */ - if (h) - h += ps->object_spacing; - - p->heading_heights[i] = h; + int *h = &heading_heights[i]; + *h = xr_render_page_heading (cairo, ps->font, &ps->headings[i], -1, + ps->size[H], false, 0); + if (*h) + *h += ps->object_spacing; } cairo_destroy (cairo); cairo_surface_destroy (surface); - - int total = p->heading_heights[0] + p->heading_heights[1]; - if (total >= ps->size[TABLE_VERT]) - p->heading_heights[0] = p->heading_heights[1] = 0; } struct xr_pager * -xr_pager_create (const struct xr_page_style *ps) +xr_pager_create (const struct xr_page_style *ps_) { - struct xr_pager *p = xmalloc (sizeof *p); - *p = (struct xr_pager) { .page_style = xr_page_style_ref (ps) }; + struct xr_page_style *ps = xr_page_style_ref (ps_); - xr_measure_headings (p); + int heading_heights[2]; + xr_measure_headings (ps, heading_heights); + int total = heading_heights[0] + heading_heights[1]; + if (total > 0 && total < ps->size[V]) + { + ps = xr_page_style_unshare (ps); + + for (int i = 0; i < 2; i++) + ps->margins[V][i] += heading_heights[i]; + ps->size[V] -= total; + } + struct xr_pager *p = xmalloc (sizeof *p); + *p = (struct xr_pager) { .page_style = ps }; return p; } @@ -266,26 +291,23 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) cairo_save (cr); cairo_set_source_rgba (cr, bg->r / 255.0, bg->g / 255.0, bg->b / 255.0, bg->alpha / 255.0); - cairo_rectangle (cr, 0, 0, ps->size[TABLE_HORZ], ps->size[TABLE_VERT]); + cairo_rectangle (cr, 0, 0, ps->size[H], ps->size[V]); cairo_fill (cr); cairo_restore (cr); } cairo_translate (cr, - xr_to_pt (ps->margins[TABLE_HORZ][0]), - xr_to_pt (ps->margins[TABLE_VERT][0])); + xr_to_pt (ps->margins[H][0]), + xr_to_pt (ps->margins[V][0])); int page_number = p->page_index++ + ps->initial_page_number; if (p->heading_heights[0]) xr_render_page_heading (cr, ps->font, &ps->headings[0], page_number, - ps->size[TABLE_HORZ], true, 0); + ps->size[H], true, -p->heading_heights[0]); if (p->heading_heights[1]) - xr_render_page_heading ( - cr, ps->font, &ps->headings[1], page_number, - ps->size[TABLE_HORZ], true, - ps->size[TABLE_VERT] - p->heading_heights[1] + ps->object_spacing); - - cairo_translate (cr, 0, xr_to_pt (p->heading_heights[0])); + xr_render_page_heading (cr, ps->font, &ps->headings[1], page_number, + ps->size[H], true, + ps->size[V] + ps->object_spacing); xr_pager_run (p); } @@ -293,9 +315,7 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) bool xr_pager_needs_new_page (struct xr_pager *p) { - int vsize = (p->page_style->size[TABLE_VERT] - - p->heading_heights[0] - p->heading_heights[1]); - if (p->item && p->y >= vsize) + if (p->item && p->y >= p->page_style->size[V]) { cairo_destroy (p->cr); p->cr = NULL; @@ -308,9 +328,7 @@ xr_pager_needs_new_page (struct xr_pager *p) static void xr_pager_run (struct xr_pager *p) { - int vsize = (p->page_style->size[TABLE_VERT] - - p->heading_heights[0] - p->heading_heights[1]); - if (p->item && p->cr && p->y < vsize) + if (p->item && p->cr && p->y < p->page_style->size[V]) { if (!p->fsm) { @@ -330,7 +348,8 @@ xr_pager_run (struct xr_pager *p) for (;;) { int spacing = p->page_style->object_spacing; - int chunk = xr_fsm_draw_slice (p->fsm, p->cr, vsize - p->y); + int chunk = xr_fsm_draw_slice (p->fsm, p->cr, + p->page_style->size[V] - p->y); p->y += chunk + spacing; cairo_translate (p->cr, 0, xr_to_pt (chunk + spacing)); diff --git a/src/output/cairo-pager.h b/src/output/cairo-pager.h index 2e722be6cf..b0cdfdf914 100644 --- a/src/output/cairo-pager.h +++ b/src/output/cairo-pager.h @@ -45,6 +45,7 @@ struct xr_page_style int object_spacing; }; struct xr_page_style *xr_page_style_ref (const struct xr_page_style *); +struct xr_page_style *xr_page_style_unshare (struct xr_page_style *); void xr_page_style_unref (struct xr_page_style *); bool xr_page_style_equals (const struct xr_page_style *, const struct xr_page_style *); @@ -56,7 +57,8 @@ xr_page_style_paper_size (const struct xr_page_style *ps, enum table_axis a) return ps->size[a] + ps->margins[a][0] + ps->margins[a][1]; } -struct xr_pager *xr_pager_create (const struct xr_page_style *); +struct xr_pager *xr_pager_create (const struct xr_page_style *, + const struct xr_fsm_style *); void xr_pager_destroy (struct xr_pager *); bool xr_pager_has_item (const struct xr_pager *);