X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fchart.c;fp=src%2Foutput%2Fchart.c;h=e31422bc6bb35799243d68337d41914ae059c430;hb=cb72db62c20ecab427229110820c5b053d0663c4;hp=e324901cc4df1d445f3fc8c7a4b64296bca55bca;hpb=c2f0df181038fe9975d642096e65ea48ca491acd;p=pspp-builds.git diff --git a/src/output/chart.c b/src/output/chart.c index e324901c..e31422bc 100644 --- a/src/output/chart.c +++ b/src/output/chart.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,8 +17,10 @@ #include #include +#include #include +#include #include #include #include @@ -27,8 +29,6 @@ #include #include -#include - #include #include #include @@ -41,128 +41,141 @@ extern struct som_table_class tab_table_class; -struct chart * -chart_create(void) +void +chart_init (struct chart *chart, const struct chart_class *class) { - struct chart *chart; - struct outp_driver *d; - - d = outp_drivers (NULL); - if (d == NULL) - return NULL; - - chart = xmalloc (sizeof *chart); - chart->lp = NULL; - d->class->initialise_chart(d, chart); - if (!chart->lp) - { - free (chart); - return NULL; - } - - if (pl_openpl_r (chart->lp) < 0) /* open Plotter */ - return NULL; - - pl_fspace_r (chart->lp, 0.0, 0.0, 1000.0, 1000.0); /* set coordinate system */ - pl_flinewidth_r (chart->lp, 0.25); /* set line thickness */ - pl_pencolorname_r (chart->lp, "black"); - - pl_erase_r (chart->lp); /* erase graphics display */ - pl_filltype_r(chart->lp,0); - - pl_savestate_r(chart->lp); - - /* Set default chartetry */ - chart->data_top = 900; - chart->data_right = 800; - chart->data_bottom = 120; - chart->data_left = 150; - chart->abscissa_top = 70; - chart->ordinate_right = 120; - chart->title_bottom = 920; - chart->legend_left = 810; - chart->legend_right = 1000; - chart->font_size = 0; - chart->in_path = false; - chart->dataset = NULL; - chart->n_datasets = 0; - strcpy(chart->fill_colour,"red"); - - /* Get default font size */ - if ( !chart->font_size) - chart->font_size = pl_fontsize_r(chart->lp, -1); - - /* Draw the data area */ - pl_box_r(chart->lp, - chart->data_left, chart->data_bottom, - chart->data_right, chart->data_top); + chart->class = class; + chart->ref_cnt = 1; +} - return chart; +void +chart_geometry_init (cairo_t *cr, struct chart_geometry *geom, + double width, double length) +{ + /* Set default chartetry. */ + 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 = 15.0; + geom->in_path = false; + geom->dataset = NULL; + geom->n_datasets = 0; + + geom->fill_colour.red = 255; + geom->fill_colour.green = 0; + geom->fill_colour.blue = 0; + + cairo_set_line_width (cr, 1.0); + + cairo_rectangle (cr, geom->data_left, geom->data_bottom, + geom->data_right - geom->data_left, + geom->data_top - geom->data_bottom); + cairo_stroke (cr); } void -chart_submit(struct chart *chart) +chart_geometry_free (cairo_t *cr UNUSED, struct chart_geometry *geom) { int i; - struct som_entity s; - struct outp_driver *d; - - if ( ! chart ) - return ; - - pl_restorestate_r(chart->lp); - - s.class = &tab_table_class; - s.ext = chart; - s.type = SOM_CHART; - som_submit (&s); - if (pl_closepl_r (chart->lp) < 0) /* close Plotter */ - { - fprintf (stderr, "Couldn't close Plotter\n"); - } - - pl_deletepl_r(chart->lp); + for (i = 0 ; i < geom->n_datasets; ++i) + free (geom->dataset[i]); + free (geom->dataset); +} - pl_deleteplparams(chart->pl_params); +void +chart_draw (const struct chart *chart, cairo_t *cr, + struct chart_geometry *geom) +{ + chart->class->draw (chart, cr, geom); +} - d = outp_drivers (NULL); - d->class->finalise_chart(d, chart); +char * +chart_draw_png (const struct chart *chart, const char *file_name_template, + int number) +{ + const int width = 640; + const int length = 480; + + struct chart_geometry geom; + cairo_surface_t *surface; + cairo_status_t status; + const char *number_pos; + char *file_name; + cairo_t *cr; + + number_pos = strchr (file_name_template, '#'); + if (number_pos != NULL) + file_name = xasprintf ("%.*s%d%s", (int) (number_pos - file_name_template), + file_name_template, number, number_pos + 1); + else + file_name = xstrdup (file_name_template); + + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, length); + cr = cairo_create (surface); + + cairo_translate (cr, 0.0, length); + cairo_scale (cr, 1.0, -1.0); + + cairo_save (cr); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_rectangle (cr, 0, 0, width, length); + cairo_fill (cr); + cairo_restore (cr); + + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + + chart_geometry_init (cr, &geom, width, length); + chart_draw (chart, cr, &geom); + chart_geometry_free (cr, &geom); + + status = cairo_surface_write_to_png (surface, file_name); + if (status != CAIRO_STATUS_SUCCESS) + error (0, 0, _("writing output file \"%s\": %s"), + file_name, cairo_status_to_string (status)); + + cairo_destroy (cr); + cairo_surface_destroy (surface); + + return file_name; +} - for (i = 0 ; i < chart->n_datasets; ++i) - free (chart->dataset[i]); - free (chart->dataset); - free(chart); +struct chart * +chart_ref (const struct chart *chart_) +{ + struct chart *chart = CONST_CAST (struct chart *, chart_); + chart->ref_cnt++; + return chart; } void -chart_init_separate (struct chart *ch, const char *type, - const char *file_name_tmpl, int number) +chart_unref (struct chart *chart) { - FILE *fp; - int number_pos; - - number_pos = strchr (file_name_tmpl, '#') - file_name_tmpl; - ch->file_name = xasprintf ("%.*s%d%s", - number_pos, file_name_tmpl, - number, - file_name_tmpl + number_pos + 1); - fp = fopen (ch->file_name, "wb"); - if (fp == NULL) + if (chart != NULL) { - error (0, errno, _("creating \"%s\""), ch->file_name); - free (ch->file_name); - ch->file_name = NULL; - return; + assert (chart->ref_cnt > 0); + if (--chart->ref_cnt == 0) + chart->class->destroy (chart); } - - ch->pl_params = pl_newplparams (); - ch->lp = pl_newpl_r (type, 0, fp, stderr, ch->pl_params); } void -chart_finalise_separate (struct chart *ch) +chart_submit (struct chart *chart) { - free (ch->file_name); +#ifdef HAVE_CAIRO + struct outp_driver *d; + + for (d = outp_drivers (NULL); d; d = outp_drivers (d)) + if (d->class->output_chart != NULL) + d->class->output_chart (d, chart); +#endif + + chart_unref (chart); }