Rewrite PSPP output engine.
[pspp-builds.git] / src / output / charts / piechart.c
index 935c6eb0fed9784024c54e571e53936e07c09c7b..0b9153d545b76d26340532a22b9e218bb29f15c6 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-
 #include <config.h>
 
 #include <output/charts/piechart.h>
 
-#include <assert.h>
-#include <float.h>
-#include <gsl/gsl_math.h>
-#include <math.h>
-#include <stdio.h>
+#include <stdlib.h>
 
-#include <data/value-labels.h>
 #include <libpspp/cast.h>
 #include <libpspp/str.h>
-#include <output/charts/plot-chart.h>
-#include <output/chart-provider.h>
-
-#include "minmax.h"
-
-struct piechart
-  {
-    struct chart chart;
-    char *title;
-    struct slice *slices;
-    int n_slices;
-  };
-
-static const struct chart_class piechart_class;
-
-/* Draw a single slice of the pie */
-static void
-draw_segment(cairo_t *,
-            double centre_x, double centre_y,
-            double radius,
-            double start_angle, double segment_angle,
-            const struct chart_colour *) ;
-
+#include <output/chart-item-provider.h>
 
+#include "gl/xalloc.h"
 
 /* Creates and returns a chart that will render a piechart with
    the given TITLE and the N_SLICES described in SLICES. */
-struct chart *
+struct chart_item *
 piechart_create (const char *title, const struct slice *slices, int n_slices)
 {
   struct piechart *pie;
   int i;
 
   pie = xmalloc (sizeof *pie);
-  chart_init (&pie->chart, &piechart_class);
-  pie->title = xstrdup (title);
+  chart_item_init (&pie->chart_item, &piechart_class, title);
   pie->slices = xnmalloc (n_slices, sizeof *pie->slices);
   for (i = 0; i < n_slices; i++)
     {
@@ -74,113 +46,15 @@ piechart_create (const char *title, const struct slice *slices, int n_slices)
       dst->magnitude = src->magnitude;
     }
   pie->n_slices = n_slices;
-  return &pie->chart;
-}
-
-static void
-piechart_draw (const struct chart *chart, cairo_t *cr,
-               struct chart_geometry *geom)
-{
-  const struct piechart *pie = UP_CAST (chart, struct piechart, chart);
-  double total_magnitude;
-  double left_label, right_label;
-  double centre_x, centre_y;
-  double radius;
-  double angle;
-  int i;
-
-  centre_x = (geom->data_right + geom->data_left) / 2.0 ;
-  centre_y = (geom->data_top + geom->data_bottom) / 2.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;
-
-  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 (cr, geom, "%s", pie->title);
-
-  total_magnitude = 0.0;
-  for (i = 0; i < pie->n_slices; i++)
-    total_magnitude += pie->slices[i].magnitude;
-
-  angle = 0.0;
-  for (i = 0; i < pie->n_slices ; ++i )
-    {
-      const double segment_angle =
-       pie->slices[i].magnitude / total_magnitude * 2 * M_PI ;
-
-      const double label_x = centre_x -
-       radius * sin(angle + segment_angle/2.0);
-
-      const double label_y = centre_y +
-       radius * cos(angle + segment_angle/2.0);
-
-      /* Fill the segment */
-      draw_segment (cr,
-                    centre_x, centre_y, radius,
-                    angle, segment_angle,
-                    &data_colour[i % N_CHART_COLOURS]);
-
-      /* Now add the labels */
-      if ( label_x < centre_x )
-       {
-          cairo_move_to (cr, label_x, label_y);
-          cairo_line_to (cr, left_label, label_y);
-          cairo_stroke (cr);
-         cairo_move_to (cr, left_label, label_y + 5);
-         chart_label (cr, 'l', 'x', geom->font_size,
-                       ds_cstr (&pie->slices[i].label));
-       }
-      else
-       {
-         cairo_move_to (cr, label_x, label_y);
-          cairo_line_to (cr, right_label, label_y);
-          cairo_stroke (cr);
-         cairo_move_to (cr, right_label, label_y + 5);
-         chart_label (cr, 'r', 'x', geom->font_size,
-                       ds_cstr (&pie->slices[i].label));
-       }
-
-      angle += segment_angle;
-    }
-
-  /* Draw an outline to the pie */
-  cairo_arc (cr, centre_x, centre_y, radius, 0, 2 * M_PI);
-  cairo_stroke (cr);
-}
-
-/* Draw a single slice of the pie */
-static void
-draw_segment(cairo_t *cr,
-            double x0, double y0,
-            double radius,
-            double start_angle, double segment_angle,
-            const struct chart_colour *colour)
-{
-  cairo_move_to (cr, x0, y0);
-  cairo_arc (cr, x0, y0, radius, start_angle, start_angle + segment_angle);
-  cairo_line_to (cr, x0, y0);
-  cairo_save (cr);
-  cairo_set_source_rgb (cr,
-                        colour->red / 255.0,
-                        colour->green / 255.0,
-                        colour->blue / 255.0);
-  cairo_fill_preserve (cr);
-  cairo_restore (cr);
-  cairo_stroke (cr);
+  return &pie->chart_item;
 }
 
 static void
-piechart_destroy (struct chart *chart)
+piechart_destroy (struct chart_item *chart_item)
 {
-  struct piechart *pie = UP_CAST (chart, struct piechart, chart);
+  struct piechart *pie = to_piechart (chart_item);
   int i;
 
-  free (pie->title);
   for (i = 0; i < pie->n_slices; i++)
     {
       struct slice *slice = &pie->slices[i];
@@ -190,8 +64,7 @@ piechart_destroy (struct chart *chart)
   free (pie);
 }
 
-static const struct chart_class piechart_class =
+const struct chart_item_class piechart_class =
   {
-    piechart_draw,
     piechart_destroy
   };