2 * Copyright © 2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 int chart_init(struct chart
*chart
, const char *name
, int num_samples
)
36 memset(chart
, 0, sizeof(*chart
));
38 chart
->samples
= malloc(sizeof(*chart
->samples
)*num_samples
);
39 if (chart
->samples
== NULL
)
42 chart
->num_samples
= num_samples
;
43 chart
->range_automatic
= 1;
44 chart
->stroke_width
= 2;
45 chart
->smooth
= CHART_CURVE
;
49 void chart_set_mode(struct chart
*chart
, enum chart_mode mode
)
54 void chart_set_smooth(struct chart
*chart
, enum chart_smooth smooth
)
56 chart
->smooth
= smooth
;
59 void chart_set_stroke_width(struct chart
*chart
, float width
)
61 chart
->stroke_width
= width
;
64 void chart_set_stroke_rgba(struct chart
*chart
, float red
, float green
, float blue
, float alpha
)
66 chart
->stroke_rgb
[0] = red
;
67 chart
->stroke_rgb
[1] = green
;
68 chart
->stroke_rgb
[2] = blue
;
69 chart
->stroke_rgb
[3] = alpha
;
72 void chart_set_fill_rgba(struct chart
*chart
, float red
, float green
, float blue
, float alpha
)
74 chart
->fill_rgb
[0] = red
;
75 chart
->fill_rgb
[1] = green
;
76 chart
->fill_rgb
[2] = blue
;
77 chart
->fill_rgb
[3] = alpha
;
80 void chart_set_position(struct chart
*chart
, int x
, int y
)
86 void chart_set_size(struct chart
*chart
, int w
, int h
)
92 void chart_set_range(struct chart
*chart
, double min
, double max
)
94 chart
->range
[0] = min
;
95 chart
->range
[1] = max
;
96 chart
->range_automatic
= 0;
99 void chart_get_range(struct chart
*chart
, double *range
)
101 int n
, max
= chart
->current_sample
;
102 if (max
> chart
->num_samples
)
103 max
= chart
->num_samples
;
104 for (n
= 0; n
< max
; n
++) {
105 if (chart
->samples
[n
] < range
[0])
106 range
[0] = chart
->samples
[n
];
107 else if (chart
->samples
[n
] > range
[1])
108 range
[1] = chart
->samples
[n
];
112 void chart_add_sample(struct chart
*chart
, double value
)
116 if (chart
->num_samples
== 0)
119 pos
= chart
->current_sample
++ % chart
->num_samples
;
120 chart
->samples
[pos
] = value
;
123 static void chart_update_range(struct chart
*chart
)
125 int n
, max
= chart
->current_sample
;
126 if (max
> chart
->num_samples
)
127 max
= chart
->num_samples
;
128 chart
->range
[0] = chart
->range
[1] = chart
->samples
[0];
129 for (n
= 1; n
< max
; n
++) {
130 if (chart
->samples
[n
] < chart
->range
[0])
131 chart
->range
[0] = chart
->samples
[n
];
132 else if (chart
->samples
[n
] > chart
->range
[1])
133 chart
->range
[1] = chart
->samples
[n
];
135 if (strcmp(chart
->name
, "power") == 0)
136 printf ("chart_update_range [%f, %f]\n", chart
->range
[0], chart
->range
[1]);
139 static double value_at(struct chart
*chart
, int n
)
141 if (n
< chart
->current_sample
- chart
->num_samples
)
142 n
= chart
->current_sample
;
143 else if (n
>= chart
->current_sample
)
144 n
= chart
->current_sample
- 1;
146 n
%= chart
->num_samples
;
148 n
+= chart
->num_samples
;
150 return chart
->samples
[n
];
153 static double gradient_at(struct chart
*chart
, int n
)
157 y0
= value_at(chart
, n
-1);
158 y1
= value_at(chart
, n
+1);
160 return (y1
- y0
) / 2.;
163 void chart_draw(struct chart
*chart
, cairo_t
*cr
)
167 if (chart
->current_sample
== 0)
170 if (chart
->range_automatic
)
171 chart_update_range(chart
);
173 if (chart
->range
[1] <= chart
->range
[0])
178 cairo_translate(cr
, chart
->x
, chart
->y
+ chart
->h
);
180 chart
->w
/ (double)(chart
->num_samples
-1),
181 -chart
->h
/ (chart
->range
[1] - chart
->range
[0]));
184 max
= chart
->current_sample
;
185 if (max
>= chart
->num_samples
) {
186 max
= chart
->num_samples
;
187 i
= chart
->current_sample
- max
;
190 x
= chart
->num_samples
- max
;
192 cairo_translate(cr
, x
, -chart
->range
[0]);
195 if (chart
->mode
!= CHART_STROKE
)
196 cairo_move_to(cr
, 0, 0);
197 for (n
= 0; n
< max
; n
++) {
198 switch (chart
->smooth
) {
201 n
, value_at(chart
, i
+ n
));
205 n
-2/3., value_at(chart
, i
+ n
-1) + gradient_at(chart
, i
+ n
- 1)/3.,
206 n
-1/3., value_at(chart
, i
+ n
) - gradient_at(chart
, i
+ n
)/3.,
207 n
, value_at(chart
, i
+ n
));
211 if (chart
->mode
!= CHART_STROKE
)
212 cairo_line_to(cr
, n
-1, 0);
214 cairo_identity_matrix(cr
);
215 cairo_set_line_width(cr
, chart
->stroke_width
);
216 switch (chart
->mode
) {
218 cairo_set_source_rgba(cr
, chart
->stroke_rgb
[0], chart
->stroke_rgb
[1], chart
->stroke_rgb
[2], chart
->stroke_rgb
[3]);
222 cairo_set_source_rgba(cr
, chart
->fill_rgb
[0], chart
->fill_rgb
[1], chart
->fill_rgb
[2], chart
->fill_rgb
[3]);
225 case CHART_FILL_STROKE
:
226 cairo_set_antialias(cr
, CAIRO_ANTIALIAS_NONE
);
227 cairo_set_source_rgba(cr
, chart
->fill_rgb
[0], chart
->fill_rgb
[1], chart
->fill_rgb
[2], chart
->fill_rgb
[3]);
228 cairo_fill_preserve(cr
);
229 cairo_set_antialias(cr
, CAIRO_ANTIALIAS_DEFAULT
);
230 cairo_set_source_rgba(cr
, chart
->stroke_rgb
[0], chart
->stroke_rgb
[1], chart
->stroke_rgb
[2], chart
->stroke_rgb
[3]);
237 void chart_fini(struct chart
*chart
)
239 free(chart
->samples
);