]> git.cworth.org Git - acre/blob - acre.c
Add preliminary implementation of acre
[acre] / acre.c
1 /* acre - A cairo-based library for creating plots and charts.
2  *
3  * Copyright © 2009 Carl Worth <cworth@cworth.org>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18  */
19
20 #include "acre.h"
21 #include "xmalloc.h"
22
23 #include <string.h>
24
25 typedef struct _acre_data_point_2d {
26     double x;
27     double y;
28 } acre_data_point_2d_t;
29
30 struct _acre_data {
31     char *name;
32
33     acre_data_point_2d_t *points;
34     unsigned int points_size;
35     unsigned int num_points;
36 };
37
38 struct _acre {
39     char *title;
40     char *x_axis_label;
41     char *y_axis_label;
42
43     acre_data_t **data;
44     unsigned int data_size;
45     unsigned int num_data;
46 };
47
48 /* Create a new, empty plot. */
49 acre_t *
50 acre_create (void)
51 {
52     acre_t *acre;
53
54     acre = xmalloc (sizeof (acre_t));
55
56     acre->title = NULL;
57     acre->x_axis_label = NULL;
58     acre->y_axis_label = NULL;
59
60     acre->data = NULL;
61     acre->data_size = 0;
62     acre->num_data = 0;
63
64     return acre;
65 }
66
67 /* Destroy a plot. */
68 void
69 acre_destroy (acre_t *acre)
70 {
71     unsigned int i;
72
73     free (acre->title);
74     free (acre->x_axis_label);
75     free (acre->y_axis_label);
76
77     for (i = 0; i < acre->num_data; i++)
78         acre_data_destroy (acre->data[i]);
79
80     free (acre->data);
81
82     free (acre);
83 }
84
85 void
86 acre_set_title (acre_t *acre, const char *title)
87 {
88     free (acre->title);
89
90     acre->title = strdup (title);
91 }
92
93 void
94 acre_set_x_axis_label (acre_t *acre, const char *label)
95 {
96     free (acre->x_axis_label);
97
98     acre->x_axis_label = strdup (label);
99 }
100
101 void
102 acre_set_y_axis_label (acre_t *acre, const char *label)
103 {
104     free (acre->y_axis_label);
105
106     acre->y_axis_label = strdup (label);
107 }
108
109 /* Add a dataset to the plot. The plot assumes ownership of the
110  * dataset so it is not necessary to call acre_data_destroy on it. */
111 void
112 acre_add_data (acre_t *acre, acre_data_t *data)
113 {
114     if (acre->num_data >= acre->data_size) {
115         acre->data_size *= 2;
116         if (acre->data_size == 0)
117             acre->data_size = 1;
118         acre->data = xrealloc_ab (acre->data,
119                                   acre->data_size,
120                                   sizeof (acre_data_t *));
121     }
122
123     acre->data[acre->num_data] = data;
124     acre->num_data++;
125 }
126
127 /* Draw the plot to the given cairo context within a user-space
128  * rectangle from (0, 0) to (width, height). This size includes all
129  * space for extra-plot elements (such as the title, the axis labels,
130  * etc.)
131  */
132 void
133 acre_draw (acre_t *acre, cairo_t *cr, double width, double height)
134 {
135     cairo_save (cr);
136
137     cairo_rectangle (cr, 0, 0, width, height);
138
139     cairo_set_source_rgb (cr, 1, 0, 1);
140
141     cairo_paint (cr);
142 }
143
144 /* Create a new dataset---a collection of (x, y) datapoints. A single
145  * plot can contain multiple datasets, (see acre_add_data). */
146 acre_data_t *
147 acre_data_create (void)
148 {
149     acre_data_t *data;
150
151     data = xmalloc (sizeof (acre_data_t));
152
153     data->name = NULL;
154
155     data->points = NULL;
156     data->points_size = 0;
157     data->num_points = 0;
158
159     return data;
160 }
161
162 /* Destroy an acre dataset. Do not call this function if the dataset
163  * has been added to an acre_t plot with acre_add_data. */
164 void
165 acre_data_destroy (acre_data_t *data)
166 {
167     free (data->points);
168
169     free (data);
170 }
171
172 /* Set the label for this dataset (to appear in the plot's key). */
173 void
174 acre_data_set_name (acre_data_t *data, const char *name)
175 {
176     free (data->name);
177
178     data->name = strdup (name);
179 }
180
181 /* Add a datapoint to the given dataset. */
182 void
183 acre_data_add_point_2d (acre_data_t *data, double x, double y)
184 {
185     if (data->num_points >= data->points_size) {
186         data->points_size *= 2;
187         if (data->points_size == 0)
188             data->points_size = 16;
189         data->points = xrealloc_ab (data->points,
190                                     data->points_size,
191                                     sizeof (acre_data_point_2d_t));
192     }
193
194     data->points[data->num_points].x = x;
195     data->points[data->num_points].y = y;
196     data->num_points++;
197 }