#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
\f
struct xr_page_style *
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)
{
}
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;
}
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);
}
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;
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)
{
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));