1 /********************************************************************
3 * THIS FILE IS PART OF THE OggGhost SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggGhost SOURCE CODE IS (C) COPYRIGHT 2007-2011 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: graphing code for chirp tests
16 ********************************************************************/
21 #include "chirpgraph.h"
26 #include <cairo/cairo.h>
29 /********************** colors for graphs *********************************/
31 void set_iter_color(cairo_t
*cC
, int ret
, float a
){
33 cairo_set_source_rgba(cC
,1,1,1,a
); /* white */
34 }else if (ret
>50){ /* 51(black)-100(white) */
35 cairo_set_source_rgba(cC
,(ret
-50)*.02,(ret
-50)*.02,(ret
-50)*.02,a
);
36 }else if (ret
>30){ /* 31(red) - 50(black) */
37 cairo_set_source_rgba(cC
,1-(ret
-30)*.05,0,0,a
);
38 }else if (ret
>10){ /* 11(yellow) - 30(red) */
39 cairo_set_source_rgba(cC
,1,1-(ret
-10)*.05,0,a
);
40 }else if (ret
>4){ /* 5 (green) - 10 (yellow) */
41 cairo_set_source_rgba(cC
,(ret
-5)*.15+.25,1,0,a
);
42 }else if (ret
==4){ /* 4 brighter cyan */
43 cairo_set_source_rgba(cC
,0,.8,.4,a
);
44 }else if (ret
==3){ /* 3 cyan */
45 cairo_set_source_rgba(cC
,0,.6,.6,a
);
46 }else if (ret
==2){ /* 2 dark cyan */
47 cairo_set_source_rgba(cC
,0,.4,.8,a
);
48 }else if (ret
==1){ /* 1 blue */
49 cairo_set_source_rgba(cC
,.1,.2,1,a
);
50 }else{ /* dark blue */
51 cairo_set_source_rgba(cC
,.2,0,1,a
);
55 void set_iter_text_color(cairo_t
*cC
, int ret
){
57 cairo_set_source_rgba(cC
,0,0,0,1); /* black on white*/
59 cairo_set_source_rgba(cC
,1,1,1,1); /* white on red/black */
61 cairo_set_source_rgba(cC
,0,0,0,1); /* black on cyan */
63 cairo_set_source_rgba(cC
,1,1,1,1); /* white on dark */
67 void set_error_color(cairo_t
*c
, float err
,float a
){
68 if(isnan(err
) || fabs(err
)>1.){
69 cairo_set_source_rgba(c
,1,1,1,a
); /* white */
73 cairo_set_source_rgba(c
,(err
-.1)/.9,(err
-.1)/.9,(err
-.1)/.9,a
); /* white->black */
75 cairo_set_source_rgba(c
,1.-((err
-.01)/.09),0,0,a
); /* black->red */
77 cairo_set_source_rgba(c
,1,1.-((err
-.001)/.009),0,a
); /* red->yellow */
79 cairo_set_source_rgba(c
,((err
-.0001)/.0009),1,0,a
); /* yellow->green */
81 cairo_set_source_rgba(c
,0,1,1.-((err
-.00001)/.00009),a
); /* green->cyan */
82 }else if(err
>.000001){
83 cairo_set_source_rgba(c
,.2-((err
-.000001)/.000009)*.2,
84 ((err
-.000001)/.000009)*.8+.2,1,a
); /* cyan->blue */
86 cairo_set_source_rgba(c
,.1,.1,1,a
); /* blue */
91 void set_error_text_color(cairo_t
*c
, float err
){
92 if(isnan(err
) || fabs(err
)>1.){
93 cairo_set_source_rgba(c
,0,0,0,1); /* black on white */
97 cairo_set_source_rgba(c
,0,0,0,1); /* black on white */
99 cairo_set_source_rgba(c
,1,1,1,1); /* white */
100 }else if(err
>.000005){
101 cairo_set_source_rgba(c
,0,0,0,1); /* black */
103 cairo_set_source_rgba(c
,1,1,1,1); /* white */
108 /********* draw everything in the graph except the graph data itself *******/
110 static float fontsize
=12;
111 static int x0s
,x1s
,xmajor
,xmajorf
;
112 static int y0s
,y1s
,ymajor
,ymajorf
;
114 /* computed configuration globals */
116 static int rightpad
=0;
118 static int bottompad
=0;
119 static float legendy
=0;
120 static float legendh
=0;
123 static float titleheight
=0.;
127 /* determines padding, etc. Will not expand the frame to prevent
128 overruns of user-set titles/legends */
129 void setup_graphs(int start_x_step
,
130 int end_x_step
, /* inclusive; not one past */
135 int end_y_step
, /* inclusive; not one past */
142 /* determine ~ padding needed */
143 cairo_surface_t
*cs
=cairo_image_surface_create(CAIRO_FORMAT_RGB24
,100,100);
144 cairo_t
*ct
=cairo_create(cs
);
145 cairo_text_extents_t extents
;
146 cairo_font_extents_t fextents
;
160 x_n
= end_x_step
-start_x_step
+1;
161 y_n
= end_y_step
-start_y_step
+1;
173 cairo_set_font_size(ct
, fontsize
);
174 for(y
=y0s
+fontsize
;y
<=y1s
;y
++){
177 snprintf(buf
,80,"%.0f",(float)y
/ymajor
*ymajorf
);
178 cairo_text_extents(ct
, buf
, &extents
);
179 if(extents
.width
+ extents
.height
*3.5>leftpad
)leftpad
=extents
.width
+ extents
.height
*3.5;
184 cairo_font_extents(ct
, &fextents
);
185 if(fextents
.height
*3>bottompad
)bottompad
=fextents
.height
*3;
187 /* center horizontally */
188 if(leftpad
<rightpad
)leftpad
=rightpad
;
189 if(rightpad
<leftpad
)rightpad
=leftpad
;
195 cairo_select_font_face (ct
, "",
196 CAIRO_FONT_SLANT_NORMAL
,
197 CAIRO_FONT_WEIGHT_BOLD
);
198 cairo_set_font_size(ct
,fontsize
*1.25);
199 cairo_font_extents(ct
, &fextents
);
200 sofar
+=fextents
.height
;
203 cairo_font_extents(ct
, &fextents
);
205 sofar
+=fextents
.height
;
206 if(sofar
>titleheight
)titleheight
=sofar
;
207 if(toppad
<titleheight
+fontsize
*2)toppad
=titleheight
+fontsize
*2;
215 cairo_text_extents(ct
, "100", &extents
);
216 w1
=extents
.width
*2*12;
217 cairo_text_extents(ct
, ".000001", &extents
);
218 w2
=extents
.width
*1.5*7;
219 cairo_text_extents(ct
, ".0001%", &extents
);
220 w3
=extents
.width
*1.5*7;
222 width
+=MAX(w1
,MAX(w2
,w3
));
224 legendy
= y_n
+extents
.height
*4;
225 legendh
= extents
.height
*1.5;
227 if(legendy
+legendh
*4>bottompad
)
228 bottompad
=(legendy
-y_n
)+legendh
*2.5;
231 pic_w
= x_n
+ leftpad
+ rightpad
;
232 pic_h
= y_n
+ toppad
+ bottompad
;
235 /* draws the page surrounding the graph data itself */
236 cairo_t
*draw_page(char *title
,
247 cairo_text_extents_t extents
;
248 cairo_font_extents_t fextents
;
249 cairo_surface_t
*cs
=cairo_image_surface_create(CAIRO_FORMAT_ARGB32
,pic_w
, pic_h
);
250 if(!cs
|| cairo_surface_status(cs
)!=CAIRO_STATUS_SUCCESS
){
251 fprintf(stderr
,"Could not set up Cairo surface.\n\n");
254 cairo_t
*c
= cairo_create(cs
);
256 /* clear page to white */
257 cairo_set_source_rgb(c
,1,1,1);
258 cairo_rectangle(c
,0,0,pic_w
,pic_h
);
260 cairo_set_font_size(c
, fontsize
);
262 /* set graph area to transparent */
264 cairo_set_source_rgba(c
,0,0,0,0);
265 cairo_set_operator(c
,CAIRO_OPERATOR_SOURCE
);
266 cairo_rectangle(c
,leftpad
,toppad
,x_n
,y_n
);
270 /* Y axis numeric labels */
271 cairo_set_source_rgb(c
,0,0,0);
272 for(i
=y0s
+fontsize
/2;i
<=y1s
;i
++){
274 int y
= toppad
+y_n
-i
+y0s
;
277 snprintf(buf
,80,"%.0f",(float)i
/ymajor
*ymajorf
);
278 cairo_text_extents(c
, buf
, &extents
);
279 cairo_move_to(c
,leftpad
- fontsize
*.5 - extents
.width
,y
+extents
.height
*.5);
280 cairo_show_text(c
,buf
);
285 for(i
=x0s
;i
<=x1s
;i
++){
288 int x
= leftpad
+ i
- x0s
;
290 snprintf(buf
,80,"DC");
292 snprintf(buf
,80,"%.0f",(float)i
/xmajor
*xmajorf
);
294 cairo_text_extents(c
, buf
, &extents
);
295 cairo_move_to(c
,x
- extents
.width
/2,y_n
+toppad
+extents
.height
+fontsize
*.5);
296 cairo_show_text(c
,buf
);
303 cairo_matrix_t b
= {0.,-1., 1.,0., 0.,0.}; // account for border!
305 cairo_text_extents(c
, yaxis_label
, &extents
);
306 cairo_move_to(c
,extents
.height
+fontsize
*.5,y_n
/2+toppad
+extents
.width
*.5);
309 cairo_get_matrix(c
,&a
);
310 cairo_matrix_multiply(&d
,&a
,&b
);
311 cairo_set_matrix(c
,&d
);
312 cairo_show_text(c
,yaxis_label
);
318 cairo_text_extents(c
, xaxis_label
, &extents
);
319 cairo_move_to(c
,pic_w
/2-extents
.width
/2,y_n
+toppad
+extents
.height
*2+fontsize
*.25);
320 cairo_show_text(c
,xaxis_label
);
325 float y
= (toppad
-titleheight
);
328 cairo_select_font_face (c
, "",
329 CAIRO_FONT_SLANT_NORMAL
,
330 CAIRO_FONT_WEIGHT_BOLD
);
331 cairo_set_font_size(c
,fontsize
*1.25);
332 cairo_font_extents(c
, &fextents
);
333 cairo_text_extents(c
, title
, &extents
);
334 cairo_move_to(c
,pic_w
/2-extents
.width
/2,y
);
335 cairo_show_text(c
,title
);
339 cairo_font_extents(c
, &fextents
);
341 cairo_text_extents(c
, subtitle1
, &extents
);
342 cairo_move_to(c
,pic_w
/2-extents
.width
/2,y
);
343 cairo_show_text(c
,subtitle1
);
347 cairo_text_extents(c
, subtitle2
, &extents
);
348 cairo_move_to(c
,pic_w
/2-extents
.width
/2,y
);
349 cairo_show_text(c
,subtitle2
);
353 cairo_text_extents(c
, subtitle3
, &extents
);
354 cairo_move_to(c
,pic_w
/2-extents
.width
/2,y
);
355 cairo_show_text(c
,subtitle3
);
364 cairo_text_extents(c
, "100", &extents
);
365 cw
=extents
.width
*2*11;
366 cairo_text_extents(c
, ".000001", &extents
);
367 cw
=MAX(cw
,extents
.width
*1.5*7);
368 cairo_text_extents(c
, ".0001%", &extents
);
369 cw
=MAX(cw
,extents
.width
*1.5*7);
371 if(datatype
==DT_iterations
){
374 float w
=cw
/11,px
=leftpad
+x_n
;
391 cairo_rectangle(c
,px
,legendy
+toppad
,w
,legendh
*1.25);
392 cairo_set_source_rgb(c
,0,0,0);
393 cairo_stroke_preserve(c
);
394 set_iter_color(c
, i
, 1.);
397 snprintf(buf
,80,"%d",i
);
398 cairo_text_extents(c
, buf
, &extents
);
399 cairo_move_to(c
,px
+w
/2-extents
.width
*.5,
400 ly
=legendy
+toppad
+legendh
*.625+extents
.height
/2);
401 set_iter_text_color(c
, i
);
402 cairo_show_text(c
, buf
);
407 cairo_text_extents(c
, legend_label
, &extents
);
408 cairo_move_to(c
,px
-extents
.width
-legendh
*.75,ly
);
409 cairo_show_text(c
,legend_label
);
411 int per_p
= (datatype
==DT_percent
);
413 float w
=cw
/7,px
=leftpad
+x_n
;
419 cairo_rectangle(c
,px
,legendy
+toppad
,w
,legendh
*1.25);
420 cairo_set_source_rgb(c
,0,0,0);
421 cairo_stroke_preserve(c
);
425 buf
=(per_p
?".0001%":".000001");
426 set_error_color(c
, 0., 1.);
428 set_error_text_color(c
, 0.);
431 buf
=(per_p
?".001%":".00001");
432 set_error_color(c
, .00001, 1.);
434 set_error_text_color(c
, .00001);
437 buf
=(per_p
?".01%":".0001");
438 set_error_color(c
, .0001, 1.);
440 set_error_text_color(c
, .0001);
443 buf
=(per_p
?".1%":".001");
444 set_error_color(c
, .001, 1.);
446 set_error_text_color(c
, .001);
449 buf
=(per_p
?"1%":".01");
450 set_error_color(c
, .01, 1.);
452 set_error_text_color(c
, .01);
455 buf
=(per_p
?"10%":".1");
456 set_error_color(c
, .1, 1.);
458 set_error_text_color(c
, .1);
461 buf
=(per_p
?"100%":"1");
462 set_error_color(c
, 1., 1.);
464 set_error_text_color(c
, 1.);
468 cairo_text_extents(c
, buf
, &extents
);
469 cairo_move_to(c
,px
+w
/2-extents
.width
*.5,
470 ly
=legendy
+toppad
+legendh
*.625+extents
.height
/2);
471 cairo_show_text(c
,buf
);
474 cairo_text_extents(c
, legend_label
, &extents
);
475 cairo_move_to(c
,px
-extents
.width
-legendh
*.75,ly
);
476 cairo_show_text(c
,legend_label
);
483 void to_png(cairo_t
*c
,char *base
, char *name
){
485 cairo_surface_t
*cs
=cairo_get_target(c
);
487 snprintf(buf
,320,"%s-%s.png",base
,name
);
488 cairo_surface_write_to_png(cs
,buf
);
492 void destroy_page(cairo_t
*c
){
494 cairo_surface_t
*cs
=cairo_get_target(c
);
496 cairo_surface_destroy(cs
);