/* PSPP - a program for statistical analysis.
- Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "libpspp/str.h"
#include "libpspp/string-map.h"
#include "libpspp/version.h"
+#include "data/file-handle-def.h"
#include "output/cairo-chart.h"
#include "output/chart-item-provider.h"
#include "output/charts/boxplot.h"
#include "output/charts/np-plot.h"
#include "output/charts/piechart.h"
+#include "output/charts/barchart.h"
#include "output/charts/plot-hist.h"
#include "output/charts/roc-chart.h"
#include "output/charts/spreadlevel-plot.h"
#include "output/charts/scree.h"
+#include "output/charts/scatterplot.h"
#include "output/driver-provider.h"
#include "output/message-item.h"
#include "output/options.h"
XR_FONT_PROPORTIONAL,
XR_FONT_EMPHASIS,
XR_FONT_FIXED,
+ XR_FONT_MARKER,
XR_N_FONTS
};
int line_space; /* Space between lines. */
int line_width; /* Width of lines. */
+ int cell_margin;
+
int min_break[TABLE_N_AXES]; /* Min cell size to break across pages. */
struct xr_color bg; /* Background color */
"serif", font_size);
xr->fonts[XR_FONT_EMPHASIS].desc = parse_font (d, o, "emph-font",
"serif italic", font_size);
+ xr->fonts[XR_FONT_MARKER].desc = parse_font (d, o, "marker-font", "serif",
+ font_size * PANGO_SCALE_X_SMALL);
- xr->line_gutter = parse_dimension (opt (d, o, "gutter", "3pt")) * scale;
+ xr->line_gutter = XR_POINT / 2;
xr->line_space = XR_POINT;
xr->line_width = XR_POINT / 2;
xr->page_number = 0;
xr->char_width = MAX (xr->char_width, pango_to_xr (char_width));
xr->char_height = MAX (xr->char_height, pango_to_xr (char_height));
}
+ xr->cell_margin = xr->char_width;
if (xr->params == NULL)
{
for (i = 0; i < TABLE_N_AXES; i++)
xr->params->min_break[i] = xr->min_break[i];
+ xr->params->supports_margins = true;
}
cairo_set_source_rgb (xr->cairo, xr->fg.red, xr->fg.green, xr->fg.blue);
}
static struct output_driver *
-xr_pdf_create (const char *file_name, enum settings_output_devices device_type,
+xr_pdf_create (struct file_handle *fh, enum settings_output_devices device_type,
struct string_map *o)
{
- return xr_create (file_name, device_type, o, XR_PDF);
+ struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, XR_PDF);
+ fh_unref (fh);
+ return od ;
}
static struct output_driver *
-xr_ps_create (const char *file_name, enum settings_output_devices device_type,
+xr_ps_create (struct file_handle *fh, enum settings_output_devices device_type,
struct string_map *o)
{
- return xr_create (file_name, device_type, o, XR_PS);
+ struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, XR_PS);
+ fh_unref (fh);
+ return od ;
}
static struct output_driver *
-xr_svg_create (const char *file_name, enum settings_output_devices device_type,
+xr_svg_create (struct file_handle *fh, enum settings_output_devices device_type,
struct string_map *o)
{
- return xr_create (file_name, device_type, o, XR_SVG);
+ struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, XR_SVG);
+ fh_unref (fh);
+ return od ;
}
static void
cairo_destroy (xr->cairo);
}
- free (xr->command_name);
for (i = 0; i < XR_N_FONTS; i++)
{
struct xr_font *font = &xr->fonts[i];
cairo_surface_flush (cairo_get_target (xr->cairo));
}
-static void
-xr_init_caption_cell (const char *caption, struct table_cell *cell,
- struct cell_contents *contents)
-{
- contents->options = TAB_LEFT;
- contents->text = CONST_CAST (char *, caption);
- contents->table = NULL;
- cell->contents = contents;
- cell->n_contents = 1;
- cell->destructor = NULL;
-}
-
-static struct render_page *
-xr_render_table_item (struct xr_driver *xr, const struct table_item *item,
- int *caption_widthp, int *caption_heightp)
-{
- const char *caption = table_item_get_caption (item);
-
- if (caption != NULL)
- {
- /* XXX doesn't do well with very large captions */
- struct cell_contents contents;
- int min_width, max_width;
- struct table_cell cell;
-
- xr_init_caption_cell (caption, &cell, &contents);
-
- xr_measure_cell_width (xr, &cell, &min_width, &max_width);
- *caption_widthp = MIN (max_width, xr->width);
- *caption_heightp = xr_measure_cell_height (xr, &cell, *caption_widthp);
- }
- else
- *caption_heightp = 0;
-
- return render_page_create (xr->params, table_item_get_table (item));
-}
-
static void
xr_submit (struct output_driver *driver, const struct output_item *output_item)
{
struct xr_driver *xr = xr_driver_cast (driver);
- output_driver_track_current_command (output_item, &xr->command_name);
-
xr_driver_output_item (xr, output_item);
while (xr_driver_need_new_page (xr))
{
See the big comment in cairo.h for intended usage. */
-/* Gives new page CAIRO to XR for output. CAIRO may be null to skip actually
- rendering the page (which might be useful to find out how many pages an
- output document has without actually rendering it). */
+/* Gives new page CAIRO to XR for output. */
void
xr_driver_next_page (struct xr_driver *xr, cairo_t *cairo)
{
- if (cairo != NULL)
- {
- cairo_save (cairo);
- cairo_set_source_rgb (cairo, xr->bg.red, xr->bg.green, xr->bg.blue);
- cairo_rectangle (cairo, 0, 0, xr->width, xr->length);
- cairo_fill (cairo);
- cairo_restore (cairo);
-
- cairo_translate (cairo,
- xr_to_pt (xr->left_margin),
- xr_to_pt (xr->top_margin));
- }
+ cairo_save (cairo);
+ cairo_set_source_rgb (cairo, xr->bg.red, xr->bg.green, xr->bg.blue);
+ cairo_rectangle (cairo, 0, 0, xr->width, xr->length);
+ cairo_fill (cairo);
+ cairo_restore (cairo);
+
+ cairo_translate (cairo,
+ xr_to_pt (xr->left_margin),
+ xr_to_pt (xr->top_margin));
xr->page_number++;
xr->cairo = cairo;
const int x3 = bb[H][1];
const int y3 = bb[V][1];
const int top = styles[H][0];
- const int left = styles[V][0];
const int bottom = styles[H][1];
- const int right = styles[V][1];
+ const int start_of_line = render_direction_rtl() ? styles[V][1]: styles[V][0];
+ const int end_of_line = render_direction_rtl() ? styles[V][0]: styles[V][1];
/* The algorithm here is somewhat subtle, to allow it to handle
all the kinds of intersections that we need.
(It doesn't make sense to have different kinds of line on the
same axis, so we don't try to gracefully handle that case.) */
bool double_vert = top == RENDER_LINE_DOUBLE || bottom == RENDER_LINE_DOUBLE;
- bool double_horz = left == RENDER_LINE_DOUBLE || right == RENDER_LINE_DOUBLE;
+ bool double_horz = start_of_line == RENDER_LINE_DOUBLE || end_of_line == RENDER_LINE_DOUBLE;
/* When horizontal lines are doubled,
the left-side line along y1 normally runs from x0 to x2,
int x1 = xc - horz_line_ofs;
int x2 = xc + horz_line_ofs;
- bool shorten_x1_lines = left == RENDER_LINE_DOUBLE;
- bool shorten_x2_lines = right == RENDER_LINE_DOUBLE;
+ bool shorten_x1_lines = start_of_line == RENDER_LINE_DOUBLE;
+ bool shorten_x2_lines = end_of_line == RENDER_LINE_DOUBLE;
bool shorten_xc_line = shorten_x1_lines && shorten_x2_lines;
int vert_line_ofs = double_horz ? double_line_ofs : 0;
int yc = (y0 + y3) / 2;
int y2 = yc + vert_line_ofs;
if (!double_horz)
- horz_line (xr, x0, x1, x2, x3, yc, left, right, shorten_yc_line);
+ horz_line (xr, x0, x1, x2, x3, yc, start_of_line, end_of_line, shorten_yc_line);
else
{
- horz_line (xr, x0, x1, x2, x3, y1, left, right, shorten_y1_lines);
- horz_line (xr, x0, x1, x2, x3, y2, left, right, shorten_y2_lines);
+ horz_line (xr, x0, x1, x2, x3, y1, start_of_line, end_of_line, shorten_y1_lines);
+ horz_line (xr, x0, x1, x2, x3, y2, start_of_line, end_of_line, shorten_y2_lines);
}
if (!double_vert)
bb[H][1] = 1;
xr_layout_cell (xr, cell, bb, clip, min_width, &h, NULL);
+
+ if (*min_width > 0)
+ *min_width += xr->cell_margin * 2;
+ if (*max_width > 0)
+ *max_width += xr->cell_margin * 2;
}
static int
int w, h;
bb[H][0] = 0;
- bb[H][1] = width;
+ bb[H][1] = width - xr->cell_margin * 2;
bb[V][0] = 0;
bb[V][1] = INT_MAX;
clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
struct xr_driver *xr = xr_;
int w, h, brk;
+ bb[H][0] += xr->cell_margin;
+ bb[H][1] -= xr->cell_margin;
+ if (bb[H][0] >= bb[H][1])
+ return;
xr_layout_cell (xr, cell, bb, clip, &w, &h, &brk);
}
return -1;
bb[H][0] = 0;
- bb[H][1] = width;
+ bb[H][1] = width - 2 * xr->cell_margin;
+ if (bb[H][1] <= 0)
+ return 0;
bb[V][0] = 0;
bb[V][1] = height;
clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
}
}
+static void
+add_attr_with_start (PangoAttrList *list, PangoAttribute *attr, guint start_index)
+{
+ attr->start_index = start_index;
+ pango_attr_list_insert (list, attr);
+}
+
static int
xr_layout_cell_text (struct xr_driver *xr,
const struct cell_contents *contents,
int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
- int y, int *widthp, int *brk)
+ int *widthp, int *brk)
{
unsigned int options = contents->options;
struct xr_font *font;
+ bool merge_footnotes;
+ size_t length;
int w, h;
+ if (contents->n_footnotes == 0)
+ merge_footnotes = false;
+ else if (contents->n_footnotes == 1 && (options & TAB_HALIGN) == TAB_RIGHT)
+ {
+ PangoAttrList *attrs;
+
+ font = &xr->fonts[XR_FONT_MARKER];
+
+ const char *marker = contents->footnotes[0]->marker;
+ pango_layout_set_text (font->layout, marker, strlen (marker));
+
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_rise_new (7000));
+ pango_layout_set_attributes (font->layout, attrs);
+ pango_attr_list_unref (attrs);
+
+ pango_layout_get_size (font->layout, &w, &h);
+ merge_footnotes = w > xr->cell_margin;
+ if (!merge_footnotes && clip[H][0] != clip[H][1])
+ {
+ cairo_save (xr->cairo);
+ xr_clip (xr, clip);
+ cairo_translate (xr->cairo,
+ xr_to_pt (bb[H][1] + xr->x),
+ xr_to_pt (bb[V][0] + xr->y));
+ pango_layout_set_alignment (font->layout, PANGO_ALIGN_LEFT);
+ pango_layout_set_width (font->layout, -1);
+ pango_cairo_show_layout (xr->cairo, font->layout);
+ cairo_restore (xr->cairo);
+ }
+
+ pango_layout_set_attributes (font->layout, NULL);
+ }
+ else
+ merge_footnotes = true;
+
font = (options & TAB_FIX ? &xr->fonts[XR_FONT_FIXED]
: options & TAB_EMPH ? &xr->fonts[XR_FONT_EMPHASIS]
: &xr->fonts[XR_FONT_PROPORTIONAL]);
- pango_layout_set_text (font->layout, contents->text, -1);
+ length = strlen (contents->text);
+ if (merge_footnotes)
+ {
+ PangoAttrList *attrs;
+ struct string s;
+
+ bb[H][1] += xr->cell_margin;
+
+ ds_init_empty (&s);
+ ds_extend (&s, length + contents->n_footnotes * 10);
+ ds_put_cstr (&s, contents->text);
+ cell_contents_format_footnote_markers (contents, &s);
+ pango_layout_set_text (font->layout, ds_cstr (&s), ds_length (&s));
+ ds_destroy (&s);
+
+ attrs = pango_attr_list_new ();
+ add_attr_with_start (attrs, pango_attr_rise_new (7000), length);
+ add_attr_with_start (
+ attrs, pango_attr_font_desc_new (xr->fonts[XR_FONT_MARKER].desc), length);
+ pango_layout_set_attributes (font->layout, attrs);
+ pango_attr_list_unref (attrs);
+ }
+ else
+ pango_layout_set_text (font->layout, contents->text, -1);
pango_layout_set_alignment (
font->layout,
- ((options & TAB_ALIGNMENT) == TAB_RIGHT ? PANGO_ALIGN_RIGHT
- : (options & TAB_ALIGNMENT) == TAB_LEFT ? PANGO_ALIGN_LEFT
+ ((options & TAB_HALIGN) == TAB_RIGHT ? PANGO_ALIGN_RIGHT
+ : (options & TAB_HALIGN) == TAB_LEFT ? PANGO_ALIGN_LEFT
: PANGO_ALIGN_CENTER));
pango_layout_set_width (
font->layout,
xr_clip (xr, clip);
cairo_translate (xr->cairo,
xr_to_pt (bb[H][0] + xr->x),
- xr_to_pt (y + xr->y));
+ xr_to_pt (bb[V][0] + xr->y));
pango_cairo_show_layout (xr->cairo, font->layout);
/* If enabled, this draws a blue rectangle around the extents of each
h = pango_to_xr (h);
if (w > *widthp)
*widthp = w;
- if (y + h >= bb[V][1])
+ if (bb[V][0] + h >= bb[V][1])
{
PangoLayoutIter *iter;
int best UNUSED = 0;
extents.y = pango_to_xr (y0);
extents.width = pango_to_xr (extents.width);
extents.height = pango_to_xr (y1 - y0);
- bottom = y + extents.y + extents.height;
+ bottom = bb[V][0] + extents.y + extents.height;
if (bottom < bb[V][1])
{
if (brk && clip[H][0] != clip[H][1])
best = bottom;
- *brk = bottom;
+ if (brk)
+ *brk = bottom;
}
else
break;
}
while (pango_layout_iter_next_line (iter));
+ pango_layout_iter_free (iter);
/* If enabled, draws a green line across the chosen breakpoint, which can
be useful for debugging issues with breaking. */
}
}
}
- return y + h;
-}
-
-static int
-xr_layout_cell_subtable (struct xr_driver *xr,
- const struct cell_contents *contents,
- int bb[TABLE_N_AXES][2],
- int clip[TABLE_N_AXES][2], int *widthp, int *brk)
-{
- const struct table *table = contents->table;
- int single_width, double_width;
- struct render_params params;
- struct render_page *page;
- int r[TABLE_N_AXES][2];
- int width, height;
- int i;
-
- params.draw_line = xr_draw_line;
- params.measure_cell_width = xr_measure_cell_width;
- params.measure_cell_height = xr_measure_cell_height;
- params.adjust_break = NULL;
- params.draw_cell = xr_draw_cell;
- params.aux = xr;
- params.size[H] = bb[H][1] - bb[H][0];
- params.size[V] = bb[V][1] - bb[V][0];
- params.font_size[H] = xr->char_width;
- params.font_size[V] = xr->char_height;
-
- single_width = 2 * xr->line_gutter + xr->line_width;
- double_width = 2 * xr->line_gutter + xr->line_space + 2 * xr->line_width;
- for (i = 0; i < TABLE_N_AXES; i++)
- {
- params.line_widths[i][RENDER_LINE_NONE] = 0;
- params.line_widths[i][RENDER_LINE_SINGLE] = single_width;
- params.line_widths[i][RENDER_LINE_DOUBLE] = double_width;
- }
-
- xr->nest++;
- page = render_page_create (¶ms, table);
- width = render_page_get_size (page, H);
- height = render_page_get_size (page, V);
- if (bb[V][0] + height >= bb[V][1])
- *brk = bb[V][0] + render_page_get_best_breakpoint (page, bb[V][1] - bb[V][0]);
-
- /* r = intersect(bb, clip) - bb. */
- for (i = 0; i < TABLE_N_AXES; i++)
- {
- r[i][0] = MAX (bb[i][0], clip[i][0]) - bb[i][0];
- r[i][1] = MIN (bb[i][1], clip[i][1]) - bb[i][0];
- }
-
- if (r[H][0] < r[H][1] && r[V][0] < r[V][1])
- {
- unsigned int alignment = contents->options & TAB_ALIGNMENT;
- int save_x = xr->x;
-
- cairo_save (xr->cairo);
- xr_clip (xr, clip);
- xr->x += bb[H][0];
- if (alignment == TAB_RIGHT)
- xr->x += params.size[H] - width;
- else if (alignment == TAB_CENTER)
- xr->x += (params.size[H] - width) / 2;
- xr->y += bb[V][0];
- render_page_draw_region (page, r[H][0], r[V][0],
- r[H][1] - r[H][0], r[V][1] - r[V][0]);
- xr->y -= bb[V][0];
- xr->x = save_x;
- cairo_restore (xr->cairo);
- }
- render_page_unref (page);
- xr->nest--;
- if (width > *widthp)
- *widthp = width;
- return bb[V][0] + height;
+ pango_layout_set_attributes (font->layout, NULL);
+ return bb[V][0] + h;
}
static void
*brk = bb[V][0];
}
- if (contents->text)
- bb[V][0] = xr_layout_cell_text (xr, contents, bb, clip,
- bb[V][0], width, brk);
- else
- bb[V][0] = xr_layout_cell_subtable (xr, contents, bb, clip, width, brk);
+ bb[V][0] = xr_layout_cell_text (xr, contents, bb, clip, width, brk);
}
*height = bb[V][0] - bb_[V][0];
}
-
-static void
-xr_draw_title (struct xr_driver *xr, const char *title,
- int title_width, int title_height)
-{
- struct cell_contents contents;
- struct table_cell cell;
- int bb[TABLE_N_AXES][2];
-
- xr_init_caption_cell (title, &cell, &contents);
- bb[H][0] = 0;
- bb[H][1] = title_width;
- bb[V][0] = 0;
- bb[V][1] = title_height;
- xr_draw_cell (xr, &cell, bb, bb);
-}
\f
struct output_driver_factory pdf_driver_factory =
{ "pdf", "pspp.pdf", xr_pdf_create };
struct output_item *item;
/* Table items. */
- struct render_page *page;
+ struct render_pager *p;
struct xr_driver *xr;
- int title_width;
- int title_height;
};
#define CHART_WIDTH 500
struct table_item *table_item;
struct xr_rendering *r;
- table_item = table_item_create (table_from_string (TAB_LEFT, text), NULL);
+ table_item = table_item_create (table_from_string (TAB_LEFT, text),
+ NULL, NULL);
r = xr_rendering_create (xr, &table_item->output_item, cr);
table_item_unref (table_item);
return r;
}
-void
+void
xr_rendering_apply_options (struct xr_rendering *xr, struct string_map *o)
{
if (is_table_item (xr->item))
r->item = output_item_ref (item);
r->xr = xr;
xr_set_cairo (xr, cr);
- r->page = xr_render_table_item (xr, to_table_item (item),
- &r->title_width, &r->title_height);
+ r->p = render_pager_create (xr->params, to_table_item (item));
}
else if (is_chart_item (item))
{
return r;
}
+void
+xr_rendering_destroy (struct xr_rendering *r)
+{
+ if (r)
+ {
+ output_item_unref (r->item);
+ render_pager_destroy (r->p);
+ free (r);
+ }
+}
+
void
xr_rendering_measure (struct xr_rendering *r, int *w, int *h)
{
if (is_table_item (r->item))
{
- int w0 = render_page_get_size (r->page, H);
- int w1 = r->title_width;
- *w = MAX (w0, w1) / XR_POINT;
- *h = (render_page_get_size (r->page, V) + r->title_height) / XR_POINT;
+ *w = render_pager_get_size (r->p, H) / XR_POINT;
+ *h = render_pager_get_size (r->p, V) / XR_POINT;
}
else
{
static void xr_draw_chart (const struct chart_item *, cairo_t *,
double x, double y, double width, double height);
-/* Draws onto CR at least the region of R that is enclosed in (X,Y)-(X+W,Y+H),
- and possibly some additional parts. */
+/* Draws onto CR */
void
-xr_rendering_draw (struct xr_rendering *r, cairo_t *cr,
- int x, int y, int w, int h)
+xr_rendering_draw_all (struct xr_rendering *r, cairo_t *cr)
{
if (is_table_item (r->item))
{
xr_set_cairo (xr, cr);
- if (r->title_height > 0)
- {
- xr->y = 0;
- xr_draw_title (xr, table_item_get_caption (to_table_item (r->item)),
- r->title_width, r->title_height);
- }
+ render_pager_draw (r->p);
- xr->y = r->title_height;
- render_page_draw_region (r->page,
- x * XR_POINT, (y * XR_POINT) - r->title_height,
- w * XR_POINT, h * XR_POINT);
}
else
xr_draw_chart (to_chart_item (r->item), cr,
xrchart_draw_np_plot (chart_item, cr, &geom);
else if (is_piechart (chart_item))
xrchart_draw_piechart (chart_item, cr, &geom);
+ else if (is_barchart (chart_item))
+ xrchart_draw_barchart (chart_item, cr, &geom);
else if (is_roc_chart (chart_item))
xrchart_draw_roc (chart_item, cr, &geom);
else if (is_scree (chart_item))
xrchart_draw_scree (chart_item, cr, &geom);
else if (is_spreadlevel_plot_chart (chart_item))
xrchart_draw_spreadlevel (chart_item, cr, &geom);
+ else if (is_scatterplot_chart (chart_item))
+ xrchart_draw_scatterplot (chart_item, cr, &geom);
else
NOT_REACHED ();
xrchart_geometry_free (cr, &geom);
{
struct xr_render_fsm fsm;
struct table_item *table_item;
- struct render_break x_break;
- struct render_break y_break;
- int caption_height;
+ struct render_pager *p;
};
static bool
{
struct xr_table_state *ts = UP_CAST (fsm, struct xr_table_state, fsm);
- for (;;)
+ while (render_pager_has_next (ts->p))
{
- struct render_page *y_slice;
- int space;
+ int used;
- while (!render_break_has_next (&ts->y_break))
- {
- struct render_page *x_slice;
-
- render_break_destroy (&ts->y_break);
- if (!render_break_has_next (&ts->x_break))
- return false;
-
- x_slice = render_break_next (&ts->x_break, xr->width);
- render_break_init (&ts->y_break, x_slice, V);
- }
-
- space = xr->length - xr->y;
- if (render_break_next_size (&ts->y_break) > space)
+ used = render_pager_draw_next (ts->p, xr->length - xr->y);
+ if (!used)
{
assert (xr->y > 0);
return true;
}
-
- y_slice = render_break_next (&ts->y_break, space);
- if (ts->caption_height)
- {
- if (xr->cairo)
- xr_draw_title (xr, table_item_get_caption (ts->table_item),
- xr->width, ts->caption_height);
-
- xr->y += ts->caption_height;
- ts->caption_height = 0;
- }
-
- if (xr->cairo)
- render_page_draw (y_slice);
- xr->y += render_page_get_size (y_slice, V);
- render_page_unref (y_slice);
+ else
+ xr->y += used;
}
+ return false;
}
static void
struct xr_table_state *ts = UP_CAST (fsm, struct xr_table_state, fsm);
table_item_unref (ts->table_item);
- render_break_destroy (&ts->x_break);
- render_break_destroy (&ts->y_break);
+ render_pager_destroy (ts->p);
free (ts);
}
xr_render_table (struct xr_driver *xr, const struct table_item *table_item)
{
struct xr_table_state *ts;
- struct render_page *page;
- int caption_width;
ts = xmalloc (sizeof *ts);
ts->fsm.render = xr_table_render;
if (xr->y > 0)
xr->y += xr->char_height;
- page = xr_render_table_item (xr, table_item,
- &caption_width, &ts->caption_height);
- xr->params->size[V] = xr->length - ts->caption_height;
-
- render_break_init (&ts->x_break, page, H);
- render_break_init_empty (&ts->y_break);
+ ts->p = render_pager_create (xr->params, table_item);
return &ts->fsm;
}
{
struct xr_chart_state *cs = UP_CAST (fsm, struct xr_chart_state, fsm);
- if (xr->y > 0)
+ const int chart_height = 0.8 * (xr->length < xr->width ? xr->length : xr->width);
+
+ if (xr->y > xr->length - chart_height)
return true;
if (xr->cairo != NULL)
- xr_draw_chart (cs->chart_item, xr->cairo, 0.0, 0.0,
- xr_to_pt (xr->width), xr_to_pt (xr->length));
- xr->y = xr->length;
+ {
+ xr_draw_chart (cs->chart_item, xr->cairo,
+ 0.0,
+ xr_to_pt (xr->y),
+ xr_to_pt (xr->width),
+ xr_to_pt (chart_height));
+ }
+ xr->y += chart_height;
return false;
}
struct table_item *table_item;
struct xr_render_fsm *fsm;
- table_item = table_item_create (table_from_string (TAB_LEFT, text), NULL);
+ table_item = table_item_create (table_from_string (TAB_LEFT, text),
+ NULL, NULL);
fsm = xr_render_table (xr, table_item);
table_item_unref (table_item);
struct xr_render_fsm *fsm;
char *s;
- s = msg_to_string (msg, xr->command_name);
+ s = msg_to_string (msg, message_item->command_name);
fsm = xr_create_text_renderer (xr, s);
free (s);