X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcharts%2Fbarchart-cairo.c;fp=src%2Foutput%2Fcharts%2Fbarchart-cairo.c;h=397715ff386d38884ce4ca9838ec39a1bb648c74;hb=97fb55e07cac602cbca57ce8005de5c8a67a73cc;hp=3ba3f001c5959dec57748e61a22487cb39b5c130;hpb=6e44fb76d15ebc34122753b8a7a7d4a1b82bcb43;p=pspp diff --git a/src/output/charts/barchart-cairo.c b/src/output/charts/barchart-cairo.c index 3ba3f001c5..397715ff38 100644 --- a/src/output/charts/barchart-cairo.c +++ b/src/output/charts/barchart-cairo.c @@ -20,6 +20,7 @@ #include "output/charts/piechart.h" #include +#include "data/variable.h" #include "output/cairo-chart.h" @@ -29,42 +30,31 @@ #define _(msgid) gettext (msgid) + static void -draw_bar (cairo_t *cr, const struct xrchart_geometry *geom, - const struct barchart *bc, int bar) +abscissa_label (const struct barchart *bc, cairo_t *cr, + struct xrchart_geometry *geom, + const union value *prev, + double x_pos, + double width, + int n_last_cat) { - const double width = - (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) - / - (double) bc->n_bars ; - - const double x_pos = - (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) * - bar - / - (double) bc->n_bars ; - - - double height = geom->axis[SCALE_ORDINATE].scale * bc->bars[bar].magnitude; - - cairo_rectangle (cr, - geom->axis[SCALE_ABSCISSA].data_min + x_pos + width * 0.1, - geom->axis[SCALE_ORDINATE].data_min, - width * 0.8, height); - cairo_save (cr); - cairo_set_source_rgb (cr, - geom->fill_colour.red / 255.0, - geom->fill_colour.green / 255.0, - geom->fill_colour.blue / 255.0); - cairo_fill_preserve (cr); - cairo_restore (cr); - cairo_stroke (cr); - - draw_tick (cr, geom, SCALE_ABSCISSA, true, - x_pos + width / 2.0, "%s", ds_cstr (&bc->bars[bar].label)); + struct category *foo = NULL; + size_t hash = value_hash (prev, bc->widths[0], 0); + HMAP_FOR_EACH_WITH_HASH (foo, struct category, node, hash, &bc->primaries) + { + if (value_equal (&foo->val, prev, bc->widths[0])) + break; + } + + draw_tick (cr, geom, SCALE_ABSCISSA, false, + x_pos - (width * n_last_cat) / 2.0, + "%s", ds_cstr (&foo->label)); } + + void xrchart_draw_barchart (const struct chart_item *chart_item, cairo_t *cr, struct xrchart_geometry *geom) @@ -72,16 +62,112 @@ xrchart_draw_barchart (const struct chart_item *chart_item, cairo_t *cr, struct barchart *bc = to_barchart (chart_item); int i; - xrchart_write_title (cr, geom, _("BARCHART")); + xrchart_write_title (cr, geom, _("Bar Chart")); xrchart_write_ylabel (cr, geom, bc->ylabel); xrchart_write_xlabel (cr, geom, chart_item_get_title (chart_item)); xrchart_write_yscale (cr, geom, 0, bc->largest); - for (i = 0; i < bc->n_bars; i++) + const double abscale = geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min; + const double width = abscale / (double) (bc->n_nzcats + bc->n_pcats); + + double x_pos = 0.5 * width; + union value *prev = NULL; + + if (bc->ss) { - draw_bar (cr, geom, bc, i); + const int blob_size = 13; + const int height = blob_size * (hmap_count (&bc->secondaries) * 2); + + cairo_rectangle (cr, + geom->axis[SCALE_ABSCISSA].data_max + 10, + geom->axis[SCALE_ORDINATE].data_max - height, + 100, height); + + cairo_stroke (cr); + + int ypos = blob_size * 1.5; + for (i = 0 ; i < hmap_count (&bc->secondaries) ; ++i) + { + const struct category *foo = bc->ss[i]; + + cairo_move_to (cr, + geom->axis[SCALE_ABSCISSA].data_max + (1.5 * blob_size) + 20, + geom->axis[SCALE_ORDINATE].data_max - ypos); + + xrchart_label (cr, 'l', 'b', geom->font_size, ds_cstr (&foo->label)); + + cairo_rectangle (cr, + geom->axis[SCALE_ABSCISSA].data_max + 20, + geom->axis[SCALE_ORDINATE].data_max - ypos, + blob_size, blob_size); + + cairo_save (cr); + cairo_set_source_rgb (cr, + data_colour[foo->idx].red / 255.0, + data_colour[foo->idx].green / 255.0, + data_colour[foo->idx].blue / 255.0); + cairo_fill_preserve (cr); + + cairo_restore (cr); + + cairo_stroke (cr); + + ypos += blob_size * 2; + } } + + int n_last_cat = 0; + for (i = 0; i < bc->n_nzcats; i++) + { + double height = geom->axis[SCALE_ORDINATE].scale * bc->cats[i]->count; + + if (prev && !value_equal (prev, &bc->cats[i]->values[0], bc->widths[0])) + { + abscissa_label (bc, cr, geom, prev, x_pos, width, n_last_cat); + + x_pos += width; + n_last_cat = 0; + } + + cairo_rectangle (cr, + geom->axis[SCALE_ABSCISSA].data_min + x_pos, + geom->axis[SCALE_ORDINATE].data_min, + width, height); + cairo_save (cr); + + + int cidx = 0; + if (bc->ss) + { + struct category *foo; + size_t hash = value_hash (&bc->cats[i]->values[1], bc->widths[1], 0); + HMAP_FOR_EACH_WITH_HASH (foo, struct category, node, hash, &bc->secondaries) + { + if (value_equal (&foo->val, &bc->cats[i]->values[1], bc->widths[1])) + { + cidx = foo->idx; + break; + } + } + } + + cairo_set_source_rgb (cr, + data_colour[cidx].red / 255.0, + data_colour[cidx].green / 255.0, + data_colour[cidx].blue / 255.0); + cairo_fill_preserve (cr); + + cairo_restore (cr); + cairo_stroke (cr); + + x_pos += width; + + prev = &bc->cats[i]->values[0]; + n_last_cat ++; + } + + abscissa_label (bc, cr, geom, prev, x_pos, width, n_last_cat); }