output: Make chart geometry the responsibility of the output driver.
authorBen Pfaff <blp@gnu.org>
Wed, 29 Jul 2009 03:20:51 +0000 (20:20 -0700)
committerBen Pfaff <blp@gnu.org>
Wed, 29 Jul 2009 03:20:51 +0000 (20:20 -0700)
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.

src/output/ascii.c
src/output/chart-provider.h
src/output/chart.c
src/output/chart.h
src/output/charts/box-whisker.c
src/output/charts/np-plot.c
src/output/charts/piechart.c
src/output/charts/plot-hist.c
src/output/html.c
src/output/postscript.c

index c01e36cc3d91ecdbfd9c0960bc9106daa865a729..15af515f18378e50b04a2e6ee26bc35d2552402c 100644 (file)
@@ -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.
index 2ff4aafafddbdd6daf7039f1ec34e100debdcbc0..fbec5d25b0bb610c69cbc55bb18810822b33d214 100644 (file)
@@ -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 */
index 8d99f41fd0194b04a25949f8b52099a9588040d0..fb561a26b86d23a5455cec2a47c8e6c0b738f942 100644 (file)
@@ -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 *
index 598c91eb9fb492c1f4d78b79c8e8e9c4b2940e84..b05b5ba41accc41eeeccda56ff1a7bbeadb996a3 100644 (file)
@@ -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 *);
 
index 24b2914593b4a1a9e1f224f5d6eb4ddb401aa166..d799d7431d2c247f077108b7e931e2ee416e64f7 100644 (file)
@@ -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
index df91add5d5d70b62f27dcf34094540e0629a9251..dba20bac56a7dfdd40c377ae389e7d5a0fc1db7c 100644 (file)
@@ -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
index 94881b417a2b7d3e4de784d67fb641156fb5489c..e33fd086704b4d6e342cb283a9464af1d74ab487 100644 (file)
@@ -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 */
index 0e52889f0c7a95df5968e92a55c86dfea8819361..97656751e1a671df9e0a1582827981a2f2bda159 100644 (file)
@@ -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, &not_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);
 }
 
 
index 8c1a653017273921fde64e07b685178a7f4f6bbd..d943f192aa3a63c93800599fc1099f71da05979c 100644 (file)
@@ -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);
index bec23de6efcaeb058bbe7356312255815770376d..743aea4ed29d706e5b6422ab2429fc069bd577f5 100644 (file)
@@ -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. */