X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcairo-fsm.c;h=698141e080fbb4550885cf73131c8d607c48dcc6;hb=6bc102626c5d7546d34375dd42ef204a248264cc;hp=16cf47dec43883b711da0d14cf4fd371f7a1e22a;hpb=e91782a2d25dec932c93b7a57bd03d836614ba43;p=pspp diff --git a/src/output/cairo-fsm.c b/src/output/cairo-fsm.c index 16cf47dec4..698141e080 100644 --- a/src/output/cairo-fsm.c +++ b/src/output/cairo-fsm.c @@ -41,6 +41,8 @@ #include "output/message-item.h" #include "output/page-eject-item.h" #include "output/page-setup-item.h" +#include "output/pivot-output.h" +#include "output/pivot-table.h" #include "output/render.h" #include "output/table-item.h" #include "output/text-item.h" @@ -105,6 +107,7 @@ xr_fsm_style_equals (const struct xr_fsm_style *a, || a->min_break[H] != b->min_break[H] || a->min_break[V] != b->min_break[V] || a->use_system_colors != b->use_system_colors + || a->object_spacing != b->object_spacing || a->font_resolution != b->font_resolution) return false; @@ -115,18 +118,33 @@ xr_fsm_style_equals (const struct xr_fsm_style *a, return true; } +/* Renders a single output_item to an output device in one of two ways: + + - 'print == true': Broken across multiple pages if necessary. + + - 'print == false': In a single region that the user may scroll around if + needed. + + Normally 'output_item' corresponds to a single rendering. There is a + special case when 'print == true' and 'output_item' is a table_item with + multiple layers and 'item->pt->table_look->print_all_layers == true'. In + that case, each layer is rendered separately from the FSM's internal point + of view; from the client's point of view, it is all one operation. +*/ struct xr_fsm { struct xr_fsm_style *style; struct output_item *item; + bool print; + + /* Print mode only. */ + bool done; /* Table items only. */ + size_t *layer_indexes; struct render_params rp; struct render_pager *p; cairo_t *cairo; /* XXX should this be here?! */ - - /* Chart and page-eject items only. */ - bool done; }; /* The unit used for internal measurements is inch/(72 * XR_POINT). @@ -725,7 +743,7 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell, PANGO_UNDERLINE_SINGLE)); } - if (cell->n_footnotes || cell->n_subscripts || cell->superscript) + if (cell->n_footnotes || cell->n_subscripts) { /* If we haven't already put TEXT into tmp, do it now. */ if (ds_is_empty (&tmp)) @@ -742,16 +760,15 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell, ds_put_cstr (&tmp, cell->subscripts[i]); } - size_t superscript_ofs = ds_length (&tmp); - if (cell->superscript) - ds_put_cstr (&tmp, cell->superscript); - size_t footnote_ofs = ds_length (&tmp); for (size_t i = 0; i < cell->n_footnotes; i++) { if (i) ds_put_byte (&tmp, ','); - ds_put_cstr (&tmp, cell->footnotes[i]->marker); + + pivot_value_format (cell->footnotes[i]->marker, + SETTINGS_VALUE_SHOW_DEFAULT, + SETTINGS_VALUE_SHOW_DEFAULT, &tmp); } /* Allow footnote markers to occupy the right margin. That way, numbers @@ -793,9 +810,9 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell, subscript_ofs, PANGO_ATTR_INDEX_TO_TEXT_END); if (cell->n_subscripts) add_attr (attrs, pango_attr_rise_new (-3000), subscript_ofs, - superscript_ofs - subscript_ofs); - if (cell->superscript || cell->n_footnotes) - add_attr (attrs, pango_attr_rise_new (3000), superscript_ofs, + footnote_ofs - subscript_ofs); + if (cell->n_footnotes) + add_attr (attrs, pango_attr_rise_new (3000), footnote_ofs, PANGO_ATTR_INDEX_TO_TEXT_END); } @@ -961,9 +978,10 @@ xr_layout_cell (struct xr_fsm *xr, const struct table_cell *cell, #define CHART_WIDTH 500 #define CHART_HEIGHT 375 -struct xr_fsm * +static struct xr_fsm * xr_fsm_create (const struct output_item *item_, - const struct xr_fsm_style *style, cairo_t *cr) + const struct xr_fsm_style *style, cairo_t *cr, + bool print) { if (is_page_setup_item (item_) || is_group_open_item (item_) @@ -996,7 +1014,8 @@ xr_fsm_create (const struct output_item *item_, item = table_item_super ( text_item_to_table_item ( text_item_create (TEXT_ITEM_TITLE, - to_group_open_item (item_)->command_name))); + to_group_open_item (item_)->command_name, + NULL))); } else NOT_REACHED (); @@ -1004,6 +1023,15 @@ xr_fsm_create (const struct output_item *item_, || is_chart_item (item) || is_page_eject_item (item)); + size_t *layer_indexes = NULL; + if (is_table_item (item)) + { + const struct table_item *table_item = to_table_item (item); + layer_indexes = pivot_output_next_layer (table_item->pt, NULL, print); + if (!layer_indexes) + return NULL; + } + static const struct render_ops xrr_render_ops = { .measure_cell_width = xrr_measure_cell_width, .measure_cell_height = xrr_measure_cell_height, @@ -1028,6 +1056,8 @@ xr_fsm_create (const struct output_item *item_, *fsm = (struct xr_fsm) { .style = xr_fsm_style_ref (style), .item = item, + .print = print, + .layer_indexes = layer_indexes, .rp = { .ops = &xrr_render_ops, .aux = fsm, @@ -1039,13 +1069,6 @@ xr_fsm_create (const struct output_item *item_, } }; - if (is_table_item (item)) - { - fsm->cairo = cr; - fsm->p = render_pager_create (&fsm->rp, to_table_item (item)); - fsm->cairo = NULL; - } - for (int i = 0; i < XR_N_FONTS; i++) { PangoContext *context = pango_cairo_create_context (cr); @@ -1068,9 +1091,25 @@ xr_fsm_create (const struct output_item *item_, g_object_unref (G_OBJECT (layout)); } + if (is_table_item (item)) + { + struct table_item *table_item = to_table_item (item); + + fsm->cairo = cr; + fsm->p = render_pager_create (&fsm->rp, table_item, fsm->layer_indexes); + fsm->cairo = NULL; + } + return fsm; } +struct xr_fsm * +xr_fsm_create_for_printing (const struct output_item *item, + const struct xr_fsm_style *style, cairo_t *cr) +{ + return xr_fsm_create (item, style, cr, true); +} + void xr_fsm_destroy (struct xr_fsm *fsm) { @@ -1078,17 +1117,27 @@ xr_fsm_destroy (struct xr_fsm *fsm) { xr_fsm_style_unref (fsm->style); output_item_unref (fsm->item); + free (fsm->layer_indexes); render_pager_destroy (fsm->p); assert (!fsm->cairo); free (fsm); } } + +/* Scrolling API. */ + +struct xr_fsm * +xr_fsm_create_for_scrolling (const struct output_item *item, + const struct xr_fsm_style *style, cairo_t *cr) +{ + return xr_fsm_create (item, style, cr, false); +} -/* This is primarily meant for use with screen rendering since the result is a - fixed value for charts. */ void xr_fsm_measure (struct xr_fsm *fsm, cairo_t *cr, int *wp, int *hp) { + assert (!fsm->print); + int w, h; if (is_table_item (fsm->item)) @@ -1112,38 +1161,10 @@ xr_fsm_measure (struct xr_fsm *fsm, cairo_t *cr, int *wp, int *hp) *hp = h; } -static int -xr_fsm_draw_table (struct xr_fsm *fsm, int space) -{ - return (render_pager_has_next (fsm->p) - ? render_pager_draw_next (fsm->p, space) - : 0); -} - -static int -xr_fsm_draw_chart (struct xr_fsm *fsm, int space) -{ - const int chart_height = 0.8 * MIN (fsm->rp.size[H], fsm->rp.size[V]); - if (space < chart_height) - return 0; - - fsm->done = true; - xr_draw_chart (to_chart_item (fsm->item), fsm->cairo, - xr_to_pt (fsm->rp.size[H]), xr_to_pt (chart_height)); - return chart_height; -} - -static int -xr_fsm_draw_eject (struct xr_fsm *fsm, int space) -{ - if (space >= fsm->rp.size[V]) - fsm->done = true; - return 0; -} - void xr_fsm_draw_all (struct xr_fsm *fsm, cairo_t *cr) { + assert (!fsm->print); xr_fsm_draw_region (fsm, cr, 0, 0, INT_MAX, INT_MAX); } @@ -1159,6 +1180,7 @@ void xr_fsm_draw_region (struct xr_fsm *fsm, cairo_t *cr, int x, int y, int w, int h) { + assert (!fsm->print); if (is_table_item (fsm->item)) { fsm->cairo = cr; @@ -1175,11 +1197,65 @@ xr_fsm_draw_region (struct xr_fsm *fsm, cairo_t *cr, else NOT_REACHED (); } + +/* Printing API. */ + +static int +xr_fsm_draw_table (struct xr_fsm *fsm, int space) +{ + struct table_item *table_item = to_table_item (fsm->item); + int used = render_pager_draw_next (fsm->p, space); + if (!render_pager_has_next (fsm->p)) + { + render_pager_destroy (fsm->p); + + fsm->layer_indexes = pivot_output_next_layer (table_item->pt, + fsm->layer_indexes, true); + if (fsm->layer_indexes) + { + fsm->p = render_pager_create (&fsm->rp, table_item, + fsm->layer_indexes); + if (table_item->pt->look->paginate_layers) + used = space; + else + used += fsm->style->object_spacing; + } + else + { + fsm->p = NULL; + fsm->done = true; + } + } + return MIN (used, space); +} + +static int +xr_fsm_draw_chart (struct xr_fsm *fsm, int space) +{ + const int chart_height = 0.8 * MIN (fsm->rp.size[H], fsm->rp.size[V]); + if (space < chart_height) + return 0; + + fsm->done = true; + xr_draw_chart (to_chart_item (fsm->item), fsm->cairo, + xr_to_pt (fsm->rp.size[H]), xr_to_pt (chart_height)); + return chart_height; +} + +static int +xr_fsm_draw_eject (struct xr_fsm *fsm, int space) +{ + if (space >= fsm->rp.size[V]) + fsm->done = true; + return 0; +} int xr_fsm_draw_slice (struct xr_fsm *fsm, cairo_t *cr, int space) { - if (xr_fsm_is_empty (fsm)) + assert (fsm->print); + + if (fsm->done) return 0; cairo_save (cr); @@ -1194,11 +1270,10 @@ xr_fsm_draw_slice (struct xr_fsm *fsm, cairo_t *cr, int space) return used; } - bool xr_fsm_is_empty (const struct xr_fsm *fsm) { - return (is_table_item (fsm->item) - ? !render_pager_has_next (fsm->p) - : fsm->done); + assert (fsm->print); + + return fsm->done; }