From: Ben Pfaff Date: Wed, 29 Jul 2009 03:20:51 +0000 (-0700) Subject: output: Make chart geometry the responsibility of the output driver. X-Git-Tag: sav-api~503 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0c37920bb2cc46ee559e3992470572d4b4d27e6;p=pspp output: Make chart geometry the responsibility of the output driver. Currently, with libplot, all charts have the same geometry, because libplot allows us to reasonably set the dimensions of the drawing area to the same 1000x1000 size. But cairo will produce strangely scaled results if we attempt to do the same thing there (distorted font sizes, etc.). So make the output drivers responsible for setting up the chart geometry, so that the output drivers can tell the chart drawing routines the size of the drawing area. --- diff --git a/src/output/ascii.c b/src/output/ascii.c index c01e36cc3d..15af515f18 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -867,6 +867,7 @@ static void ascii_output_chart (struct outp_driver *this, const struct chart *chart) { struct ascii_driver_ext *x = this->ext; + struct chart_geometry geom; struct outp_text t; char *file_name; plPlotter *lp; @@ -880,7 +881,9 @@ ascii_output_chart (struct outp_driver *this, const struct chart *chart) NULL, &file_name, &lp)) return; x->chart_cnt++; - chart_draw (chart, lp); + chart_geometry_init (lp, &geom, 1000.0, 1000.0); + chart_draw (chart, lp, &geom); + chart_geometry_free (lp); pl_deletepl_r (lp); /* Mention chart in output. diff --git a/src/output/chart-provider.h b/src/output/chart-provider.h index 2ff4aafafd..fbec5d25b0 100644 --- a/src/output/chart-provider.h +++ b/src/output/chart-provider.h @@ -28,23 +28,6 @@ struct chart_colour uint8_t blue; }; -struct chart_class - { - void (*draw) (const struct chart *, plPlotter *); - void (*destroy) (struct chart *); - }; - -struct chart - { - const struct chart_class *class; - int ref_cnt; - }; - -void chart_init (struct chart *, const struct chart_class *); -bool chart_create_file (const char *type, const char *file_name_tmpl, - int number, plPlotterParams *, - char **file_namep, plPlotter **lpp); - /* The geometry of a chart. */ struct chart_geometry { @@ -76,7 +59,27 @@ struct chart_geometry double y_max; }; -void chart_geometry_init (plPlotter *, struct chart_geometry *); +struct chart_class + { + void (*draw) (const struct chart *, plPlotter *, struct chart_geometry *); + void (*destroy) (struct chart *); + }; + +struct chart + { + const struct chart_class *class; + int ref_cnt; + }; + +void chart_init (struct chart *, const struct chart_class *); +bool chart_create_file (const char *type, const char *file_name_tmpl, + int number, plPlotterParams *, + char **file_namep, plPlotter **lpp); + +void chart_geometry_init (plPlotter *, struct chart_geometry *, + double width, double length); void chart_geometry_free (plPlotter *); +void chart_draw (const struct chart *, plPlotter *, struct chart_geometry *); + #endif /* output/chart-provider.h */ diff --git a/src/output/chart.c b/src/output/chart.c index 8d99f41fd0..fb561a26b8 100644 --- a/src/output/chart.c +++ b/src/output/chart.c @@ -48,13 +48,14 @@ chart_init (struct chart *chart, const struct chart_class *class) } void -chart_geometry_init (plPlotter *lp, struct chart_geometry *geom) +chart_geometry_init (plPlotter *lp, struct chart_geometry *geom, + double width, double length) { /* Start output page. */ pl_openpl_r (lp); /* Set coordinate system. */ - pl_fspace_r (lp, 0.0, 0.0, 1000.0, 1000.0); + pl_fspace_r (lp, 0.0, 0.0, width, length); /* Set line thickness. */ pl_flinewidth_r (lp, 0.25); @@ -67,15 +68,15 @@ chart_geometry_init (plPlotter *lp, struct chart_geometry *geom) pl_savestate_r(lp); /* Set default chartetry. */ - geom->data_top = 900; - geom->data_right = 800; - geom->data_bottom = 120; - geom->data_left = 150; - geom->abscissa_top = 70; - geom->ordinate_right = 120; - geom->title_bottom = 920; - geom->legend_left = 810; - geom->legend_right = 1000; + geom->data_top = 0.900 * length; + geom->data_right = 0.800 * width; + geom->data_bottom = 0.120 * length; + geom->data_left = 0.150 * width; + geom->abscissa_top = 0.070 * length; + geom->ordinate_right = 0.120 * width; + geom->title_bottom = 0.920 * length; + geom->legend_left = 0.810 * width; + geom->legend_right = width; geom->font_size = 0; geom->fill_colour.red = 255; @@ -100,9 +101,10 @@ chart_geometry_free (plPlotter *lp) } void -chart_draw (const struct chart *chart, plPlotter *lp) +chart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { - chart->class->draw (chart, lp); + chart->class->draw (chart, lp, geom); } struct chart * diff --git a/src/output/chart.h b/src/output/chart.h index 598c91eb9f..b05b5ba41a 100644 --- a/src/output/chart.h +++ b/src/output/chart.h @@ -28,7 +28,6 @@ struct chart; -void chart_draw (const struct chart *, plPlotter *); struct chart *chart_ref (const struct chart *); void chart_unref (struct chart *); diff --git a/src/output/charts/box-whisker.c b/src/output/charts/box-whisker.c index 24b2914593..d799d7431d 100644 --- a/src/output/charts/box-whisker.c +++ b/src/output/charts/box-whisker.c @@ -233,26 +233,23 @@ boxplot_draw_yscale (plPlotter *lp, struct chart_geometry *geom, } static void -boxplot_chart_draw (const struct chart *chart, plPlotter *lp) +boxplot_chart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { const struct boxplot *boxplot = (struct boxplot *) chart; - struct chart_geometry geom; double box_width; size_t i; - chart_geometry_init (lp, &geom); - boxplot_draw_yscale (lp, &geom, boxplot->y_max, boxplot->y_min); - chart_write_title (lp, &geom, "%s", boxplot->title); + boxplot_draw_yscale (lp, geom, boxplot->y_max, boxplot->y_min); + chart_write_title (lp, geom, "%s", boxplot->title); - box_width = (geom.data_right - geom.data_left) / boxplot->n_boxes / 2.0; + box_width = (geom->data_right - geom->data_left) / boxplot->n_boxes / 2.0; for (i = 0; i < boxplot->n_boxes; i++) { const struct box *box = &boxplot->boxes[i]; - const double box_centre = (i * 2 + 1) * box_width + geom.data_left; - boxplot_draw_box (lp, &geom, box_centre, box_width, box->bw, box->label); + const double box_centre = (i * 2 + 1) * box_width + geom->data_left; + boxplot_draw_box (lp, geom, box_centre, box_width, box->bw, box->label); } - - chart_geometry_free (lp); } static void diff --git a/src/output/charts/np-plot.c b/src/output/charts/np-plot.c index df91add5d5..dba20bac56 100644 --- a/src/output/charts/np-plot.c +++ b/src/output/charts/np-plot.c @@ -121,60 +121,54 @@ dnp_plot_create (const struct np *np, const struct casereader *reader, } static void -np_plot_chart_draw (const struct chart *chart, plPlotter *lp) +np_plot_chart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { const struct np_plot_chart *npp = (struct np_plot_chart *) chart; - struct chart_geometry geom; struct casereader *data; struct ccase *c; - chart_geometry_init (lp, &geom); - chart_write_title (lp, &geom, _("Normal Q-Q Plot of %s"), npp->label); - chart_write_xlabel (lp, &geom, _("Observed Value")); - chart_write_ylabel (lp, &geom, _("Expected Normal")); - chart_write_xscale (lp, &geom, + chart_write_title (lp, geom, _("Normal Q-Q Plot of %s"), npp->label); + chart_write_xlabel (lp, geom, _("Observed Value")); + chart_write_ylabel (lp, geom, _("Expected Normal")); + chart_write_xscale (lp, geom, npp->x_lower - npp->slack, npp->x_upper + npp->slack, 5); - chart_write_yscale (lp, &geom, npp->y_first, npp->y_last, 5); + chart_write_yscale (lp, geom, npp->y_first, npp->y_last, 5); data = casereader_clone (npp->data); for (; (c = casereader_read (data)) != NULL; case_unref (c)) - chart_datum (lp, &geom, 0, + chart_datum (lp, geom, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_NS)->f); casereader_destroy (data); - chart_line (lp, &geom, npp->slope, npp->intercept, + chart_line (lp, geom, npp->slope, npp->intercept, npp->y_first, npp->y_last, CHART_DIM_Y); - - chart_geometry_free (lp); } static void -dnp_plot_chart_draw (const struct chart *chart, plPlotter *lp) +dnp_plot_chart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { const struct np_plot_chart *dnpp = (struct np_plot_chart *) chart; - struct chart_geometry geom; struct casereader *data; struct ccase *c; - chart_geometry_init (lp, &geom); - chart_write_title (lp, &geom, _("Detrended Normal Q-Q Plot of %s"), + chart_write_title (lp, geom, _("Detrended Normal Q-Q Plot of %s"), dnpp->label); - chart_write_xlabel (lp, &geom, _("Observed Value")); - chart_write_ylabel (lp, &geom, _("Dev from Normal")); - chart_write_xscale (lp, &geom, dnpp->y_min, dnpp->y_max, 5); - chart_write_yscale (lp, &geom, dnpp->dns_min, dnpp->dns_max, 5); + chart_write_xlabel (lp, geom, _("Observed Value")); + chart_write_ylabel (lp, geom, _("Dev from Normal")); + chart_write_xscale (lp, geom, dnpp->y_min, dnpp->y_max, 5); + chart_write_yscale (lp, geom, dnpp->dns_min, dnpp->dns_max, 5); data = casereader_clone (dnpp->data); for (; (c = casereader_read (data)) != NULL; case_unref (c)) - chart_datum (lp, &geom, 0, case_data_idx (c, NP_IDX_Y)->f, + chart_datum (lp, geom, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_DNS)->f); casereader_destroy (data); - chart_line (lp, &geom, 0, 0, dnpp->y_min, dnpp->y_max, CHART_DIM_X); - - chart_geometry_free (lp); + chart_line (lp, geom, 0, 0, dnpp->y_min, dnpp->y_max, CHART_DIM_X); } static void diff --git a/src/output/charts/piechart.c b/src/output/charts/piechart.c index 94881b417a..e33fd08670 100644 --- a/src/output/charts/piechart.c +++ b/src/output/charts/piechart.c @@ -77,10 +77,10 @@ piechart_create (const char *title, const struct slice *slices, int n_slices) } static void -piechart_draw (const struct chart *chart, plPlotter *lp) +piechart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { struct piechart *pie = (struct piechart *) chart; - struct chart_geometry geom; double total_magnitude; double left_label, right_label; double centre_x, centre_y; @@ -88,18 +88,16 @@ piechart_draw (const struct chart *chart, plPlotter *lp) double angle; int i; - chart_geometry_init (lp, &geom); + left_label = geom->data_left + (geom->data_right - geom->data_left)/10.0; + right_label = geom->data_right - (geom->data_right - geom->data_left)/10.0; - left_label = geom.data_left + (geom.data_right - geom.data_left)/10.0; - right_label = geom.data_right - (geom.data_right - geom.data_left)/10.0; + centre_x = (geom->data_right + geom->data_left) / 2.0 ; + centre_y = (geom->data_top + geom->data_bottom) / 2.0 ; - centre_x = (geom.data_right + geom.data_left) / 2.0 ; - centre_y = (geom.data_top + geom.data_bottom) / 2.0 ; + radius = MIN (5.0 / 12.0 * (geom->data_top - geom->data_bottom), + 1.0 / 4.0 * (geom->data_right - geom->data_left)); - radius = MIN (5.0 / 12.0 * (geom.data_top - geom.data_bottom), - 1.0 / 4.0 * (geom.data_right - geom.data_left)); - - chart_write_title (lp, &geom, "%s", pie->title); + chart_write_title (lp, geom, "%s", pie->title); total_magnitude = 0.0; for (i = 0; i < pie->n_slices; i++) @@ -143,8 +141,6 @@ piechart_draw (const struct chart *chart, plPlotter *lp) /* Draw an outline to the pie */ pl_filltype_r (lp,0); pl_fcircle_r (lp, centre_x, centre_y, radius); - - chart_geometry_free (lp); } /* Fill a segment with the current fill colour */ diff --git a/src/output/charts/plot-hist.c b/src/output/charts/plot-hist.c index 0e52889f0c..97656751e1 100644 --- a/src/output/charts/plot-hist.c +++ b/src/output/charts/plot-hist.c @@ -147,19 +147,17 @@ histogram_chart_create (const struct histogram *hist, const char *label, } static void -histogram_chart_draw (const struct chart *chart, plPlotter *lp) +histogram_chart_draw (const struct chart *chart, plPlotter *lp, + struct chart_geometry *geom) { struct histogram_chart *h = (struct histogram_chart *) chart; - struct chart_geometry geom; int i; int bins; - chart_geometry_init (lp, &geom); + chart_write_title (lp, geom, _("HISTOGRAM")); - chart_write_title (lp, &geom, _("HISTOGRAM")); - - chart_write_ylabel (lp, &geom, _("Frequency")); - chart_write_xlabel (lp, &geom, h->label); + chart_write_ylabel (lp, geom, _("Frequency")); + chart_write_xlabel (lp, geom, h->label); if (h->gsl_hist == NULL) { @@ -169,12 +167,12 @@ histogram_chart_draw (const struct chart *chart, plPlotter *lp) bins = gsl_histogram_bins (h->gsl_hist); - chart_write_yscale (lp, &geom, 0, gsl_histogram_max_val (h->gsl_hist), 5); + chart_write_yscale (lp, geom, 0, gsl_histogram_max_val (h->gsl_hist), 5); for (i = 0; i < bins; i++) - hist_draw_bar (lp, &geom, h->gsl_hist, i); + hist_draw_bar (lp, geom, h->gsl_hist, i); - histogram_write_legend (lp, &geom, h->n, h->mean, h->stddev); + histogram_write_legend (lp, geom, h->n, h->mean, h->stddev); if (h->show_normal && h->n != SYSMIS && h->mean != SYSMIS && h->stddev != SYSMIS) @@ -190,26 +188,24 @@ histogram_chart_draw (const struct chart *chart, plPlotter *lp) range = not_used - x_min; gsl_histogram_get_range (h->gsl_hist, bins - 1, ¬_used, &x_max); - abscissa_scale = (geom.data_right - geom.data_left) / (x_max - x_min); - ordinate_scale = (geom.data_top - geom.data_bottom) / + abscissa_scale = (geom->data_right - geom->data_left) / (x_max - x_min); + ordinate_scale = (geom->data_top - geom->data_bottom) / gsl_histogram_max_val (h->gsl_hist); - pl_move_r (lp, geom.data_left, geom.data_bottom); - for (d = geom.data_left; - d <= geom.data_right; - d += (geom.data_right - geom.data_left) / 100.0) + pl_move_r (lp, geom->data_left, geom->data_bottom); + for (d = geom->data_left; + d <= geom->data_right; + d += (geom->data_right - geom->data_left) / 100.0) { - const double x = (d - geom.data_left) / abscissa_scale + x_min; + const double x = (d - geom->data_left) / abscissa_scale + x_min; const double y = h->n * range * gsl_ran_gaussian_pdf (x - h->mean, h->stddev); - pl_fcont_r (lp, d, geom.data_bottom + y * ordinate_scale); + pl_fcont_r (lp, d, geom->data_bottom + y * ordinate_scale); } pl_endpath_r (lp); } - - chart_geometry_free (lp); } diff --git a/src/output/html.c b/src/output/html.c index 8c1a653017..d943f192aa 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -208,6 +208,7 @@ static void html_output_chart (struct outp_driver *this, const struct chart *chart) { struct html_driver_ext *x = this->ext; + struct chart_geometry geom; char *file_name; plPlotter *lp; @@ -216,7 +217,9 @@ html_output_chart (struct outp_driver *this, const struct chart *chart) NULL, &file_name, &lp)) return; x->chart_cnt++; - chart_draw (chart, lp); + chart_geometry_init (lp, &geom, 1000.0, 1000.0); + chart_draw (chart, lp, &geom); + chart_geometry_free (lp); pl_deletepl_r (lp); link_image (x->file, file_name); diff --git a/src/output/postscript.c b/src/output/postscript.c index bec23de6ef..743aea4ed2 100644 --- a/src/output/postscript.c +++ b/src/output/postscript.c @@ -607,6 +607,7 @@ static void ps_output_chart (struct outp_driver *this, const struct chart *chart) { struct ps_driver_ext *x = this->ext; + struct chart_geometry geom; plPlotterParams *params; int x_origin, y_origin; char buf[BUFSIZ]; @@ -644,7 +645,9 @@ ps_output_chart (struct outp_driver *this, const struct chart *chart) } /* Draw chart and free plotter. */ - chart_draw (chart, lp); + chart_geometry_init (lp, &geom, 1000.0, 1000.0); + chart_draw (chart, lp, &geom); + chart_geometry_free (lp); pl_deletepl_r (lp); /* Write prologue for chart. */