Import fmit upstream version 0.97.6
[fmit.git] / src / modules / GLStatistics.cpp
1 // Copyright 2007 "Gilles Degottex"
2
3 // This file is part of "fmit"
4
5 // "fmit" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // "fmit" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 #include "GLStatistics.h"
20
21 static const unsigned char g_icon_statistics[] = {
22         0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
23         0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
24         0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x06,
25         0xc4, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xb5, 0x97, 0x6d, 0x4c, 0x5b,
26         0xd7, 0x19, 0xc7, 0x7f, 0xf7, 0x5e, 0x1b, 0x1b, 0xdb, 0x04, 0x6c, 0x63,
27         0xc0, 0xe1, 0xd5, 0x04, 0x92, 0x40, 0x63, 0x9c, 0x89, 0xac, 0x1f, 0x12,
28         0xa1, 0x69, 0x5a, 0x84, 0x14, 0x05, 0x91, 0x69, 0x5a, 0xaa, 0x54, 0x51,
29         0x42, 0xb6, 0x26, 0x43, 0x8b, 0xca, 0x40, 0xcd, 0x3e, 0xa4, 0xca, 0xa2,
30         0x4a, 0x45, 0xcd, 0xb4, 0x2f, 0xec, 0x43, 0x22, 0xa5, 0x48, 0x93, 0x26,
31         0x2d, 0x9b, 0x54, 0x6d, 0x51, 0xa3, 0xd2, 0xa8, 0xeb, 0xa6, 0xee, 0x25,
32         0xb3, 0x50, 0xa7, 0x89, 0xa5, 0x84, 0xb2, 0x26, 0x59, 0x49, 0x00, 0x63,
33         0x9b, 0xf2, 0x6e, 0xe3, 0x6b, 0x83, 0x5f, 0xef, 0x3e, 0xf8, 0x05, 0x1b,
34         0x9b, 0x8e, 0x6d, 0xda, 0x23, 0x1d, 0x9d, 0x73, 0x8f, 0xce, 0x39, 0xff,
35         0xdf, 0xf3, 0x9c, 0x97, 0x7b, 0x8e, 0xc0, 0xff, 0xc1, 0x3a, 0xba, 0x7b,
36         0xb5, 0x40, 0x15, 0x60, 0x06, 0xca, 0x80, 0x35, 0xe0, 0x13, 0xe7, 0xc8,
37         0xb0, 0xb2, 0xbd, 0xad, 0xf0, 0x5f, 0x0c, 0x2e, 0x02, 0xd5, 0x80, 0x0d,
38         0x68, 0x00, 0xea, 0x80, 0x9a, 0x54, 0x5d, 0x4d, 0x2a, 0x99, 0x0b, 0x8c,
39         0x3d, 0x09, 0x9c, 0x72, 0x8e, 0x0c, 0x3f, 0xcf, 0xae, 0x54, 0xed, 0x20,
40         0x62, 0x04, 0x9a, 0x53, 0x22, 0xe9, 0xd4, 0x90, 0xca, 0xeb, 0x81, 0xa2,
41         0x9d, 0x00, 0x35, 0x45, 0x45, 0x18, 0xf4, 0xc5, 0xe8, 0xf5, 0xc5, 0x18,
42         0x74, 0xc5, 0x68, 0x8a, 0xd4, 0x3c, 0x7d, 0xe6, 0x22, 0xb4, 0xb1, 0x79,
43         0x08, 0x78, 0x0d, 0x78, 0xb5, 0x20, 0x40, 0x47, 0x77, 0xaf, 0x1e, 0xb8,
44         0x02, 0x9c, 0x4d, 0x89, 0x0b, 0x00, 0x92, 0x24, 0x52, 0x69, 0x31, 0x61,
45         0x31, 0x19, 0x29, 0x2b, 0x35, 0x50, 0x56, 0x5a, 0x82, 0xb1, 0xb4, 0x24,
46         0x93, 0x97, 0x96, 0x96, 0xa0, 0xd7, 0xeb, 0xd1, 0xe9, 0xf4, 0xa8, 0x35,
47         0x5a, 0xe2, 0x8a, 0x48, 0x38, 0x9a, 0x20, 0xa1, 0x80, 0x4a, 0x14, 0xa8,
48         0xb7, 0x68, 0xf8, 0xe0, 0x0f, 0xa3, 0xfc, 0xe4, 0xe6, 0x1d, 0x52, 0x0e,
49         0x90, 0x07, 0x90, 0x12, 0x1f, 0x05, 0x1c, 0xa2, 0x28, 0x72, 0xec, 0xab,
50         0x76, 0x8e, 0xbe, 0xd8, 0x46, 0x5b, 0x4b, 0x13, 0x55, 0x95, 0xe5, 0x44,
51         0xe3, 0x02, 0xa1, 0x70, 0x9c, 0x60, 0x38, 0x41, 0x28, 0x92, 0xe0, 0xaf,
52         0x1f, 0x7f, 0x8c, 0xae, 0xa2, 0x99, 0x88, 0x5a, 0xcf, 0x6c, 0x28, 0x41,
53         0x5c, 0x56, 0x50, 0x88, 0xa3, 0x28, 0x41, 0x14, 0x05, 0x14, 0x40, 0x51,
54         0x14, 0x14, 0x05, 0x4c, 0x25, 0x2a, 0xf6, 0x37, 0xd6, 0xa5, 0xf5, 0x6a,
55         0x0b, 0x02, 0x00, 0x97, 0x00, 0x87, 0x24, 0x8a, 0xdc, 0xfc, 0xf1, 0x0f,
56         0xd9, 0xdf, 0x64, 0x63, 0x66, 0x31, 0x8c, 0x6b, 0x3d, 0xca, 0xe3, 0x65,
57         0x99, 0x44, 0x42, 0x49, 0x0d, 0x9c, 0xcc, 0xff, 0xfc, 0xe0, 0x01, 0xdd,
58         0x67, 0x5a, 0x50, 0xa3, 0x20, 0x8a, 0x02, 0x82, 0x40, 0x96, 0x70, 0x56,
59         0xae, 0x80, 0xbc, 0x19, 0xc7, 0x64, 0xdc, 0x93, 0xd6, 0xdb, 0xd7, 0xd1,
60         0xdd, 0x2b, 0x64, 0x2f, 0xc6, 0x34, 0x40, 0x23, 0xc0, 0xc1, 0xe6, 0x7a,
61         0x0e, 0x34, 0xd9, 0x18, 0x7b, 0x2e, 0xb3, 0x19, 0x49, 0x86, 0x51, 0x12,
62         0x41, 0x14, 0x84, 0x9c, 0x81, 0xd5, 0x92, 0x84, 0x28, 0x24, 0x50, 0x49,
63         0xe9, 0x3a, 0x21, 0x23, 0x98, 0x1e, 0x39, 0xa1, 0x00, 0x0a, 0x84, 0x23,
64         0x0a, 0xd6, 0x8a, 0x3d, 0x68, 0x35, 0x45, 0x6c, 0x86, 0x23, 0x3a, 0x60,
65         0x2f, 0xe0, 0x49, 0x03, 0x88, 0xd9, 0x20, 0x55, 0x95, 0xe5, 0x78, 0xd7,
66         0x22, 0xc4, 0xe2, 0xc9, 0xf9, 0xcb, 0x24, 0x49, 0x40, 0x25, 0x91, 0x29,
67         0x1b, 0xcd, 0xe5, 0xc8, 0xbe, 0x95, 0x64, 0x7d, 0xa1, 0x36, 0xe2, 0x56,
68         0xff, 0x70, 0x2c, 0x81, 0x20, 0x08, 0xd4, 0xec, 0xad, 0x48, 0x6b, 0x1e,
69         0xc8, 0x9e, 0x02, 0x31, 0xfb, 0x43, 0xa7, 0xd5, 0x10, 0x8b, 0x2b, 0xc9,
70         0x81, 0x24, 0x61, 0x2b, 0x89, 0x59, 0xdf, 0xa2, 0x40, 0xd5, 0xde, 0x1a,
71         0x56, 0x97, 0x3c, 0x59, 0xc2, 0xdb, 0x20, 0xb2, 0xfa, 0x46, 0x63, 0xc9,
72         0x98, 0x34, 0xd4, 0x5a, 0xd3, 0x32, 0x2d, 0x85, 0x00, 0x22, 0x00, 0x5a,
73         0x4d, 0x51, 0xae, 0xb0, 0x54, 0x48, 0x40, 0xa0, 0xb6, 0xce, 0xc6, 0x17,
74         0x9e, 0x99, 0x2f, 0x6d, 0x93, 0x4e, 0xb1, 0x44, 0x12, 0xa0, 0xb1, 0x7e,
75         0x6f, 0x5a, 0xf3, 0x60, 0x21, 0x80, 0x75, 0x80, 0x78, 0x22, 0x81, 0x5a,
76         0x25, 0xe4, 0x86, 0xbf, 0x80, 0x97, 0xd5, 0x35, 0xb5, 0x78, 0x66, 0xa7,
77         0x08, 0xc9, 0xbe, 0xc2, 0x6d, 0x32, 0x09, 0xd4, 0x52, 0x52, 0xc2, 0x56,
78         0x57, 0xfd, 0xef, 0x01, 0x22, 0x91, 0x28, 0x45, 0x2a, 0x31, 0xcb, 0x03,
79         0xf2, 0x3c, 0xfb, 0xfc, 0xb3, 0x71, 0x2e, 0xbe, 0xf4, 0x75, 0xde, 0xf9,
80         0xf9, 0x2d, 0xbe, 0xfd, 0x0d, 0x3b, 0xaf, 0xbf, 0xfa, 0x32, 0xb2, 0x7f,
81         0x25, 0x77, 0x9a, 0x24, 0x81, 0xf2, 0x12, 0x15, 0x0e, 0x9b, 0x9e, 0x43,
82         0x75, 0xc5, 0x49, 0x80, 0xdd, 0x44, 0x20, 0x12, 0x8d, 0xa1, 0xfe, 0x92,
83         0x29, 0xf0, 0xb8, 0xa6, 0xf8, 0xc1, 0x2b, 0xdf, 0xa2, 0xe7, 0x52, 0x3f,
84         0xe7, 0xbf, 0x37, 0xc0, 0x47, 0x7f, 0x9b, 0xc6, 0xb6, 0xaf, 0x99, 0xfe,
85         0xef, 0x76, 0x13, 0x0d, 0x87, 0x50, 0x4b, 0x02, 0x95, 0x65, 0x6a, 0x0e,
86         0xdb, 0x74, 0xd8, 0xeb, 0x75, 0x98, 0x0c, 0x5b, 0x07, 0xad, 0xb5, 0xc2,
87         0x4c, 0xb1, 0x56, 0x03, 0x50, 0xdd, 0xd1, 0xdd, 0x5b, 0xb2, 0x1d, 0x60,
88         0x19, 0x20, 0x18, 0xdc, 0x48, 0x02, 0xe4, 0xac, 0xe4, 0x2d, 0xcf, 0xde,
89         0xfe, 0xe9, 0x5b, 0x5c, 0xb8, 0xd4, 0x47, 0xd7, 0x37, 0x5f, 0xc2, 0x58,
90         0x66, 0x24, 0x16, 0xdd, 0xe4, 0xb5, 0xd7, 0xdf, 0xa2, 0x69, 0x7f, 0x2b,
91         0xbf, 0x7c, 0xfb, 0x06, 0x8e, 0x06, 0x3d, 0x4d, 0x55, 0x5a, 0xf4, 0x1a,
92         0x29, 0xdb, 0x49, 0x42, 0xa1, 0x10, 0x82, 0x20, 0xd0, 0x50, 0x67, 0x85,
93         0xe4, 0x09, 0x7b, 0x70, 0x3b, 0xc0, 0x22, 0x80, 0x3f, 0x10, 0xdc, 0xd1,
94         0xfb, 0x68, 0x38, 0xc4, 0x83, 0x3f, 0x7e, 0xc8, 0xcb, 0xe7, 0x2e, 0xa2,
95         0x92, 0x04, 0x5a, 0xed, 0x0e, 0x9e, 0x3d, 0xfd, 0x14, 0x4b, 0xa9, 0x8a,
96         0x9f, 0x0d, 0xdf, 0xe4, 0xdd, 0x5f, 0xff, 0x8a, 0x79, 0x8f, 0x8b, 0x40,
97         0x20, 0x80, 0xdf, 0xef, 0xc7, 0xe7, 0xf3, 0x65, 0x92, 0x28, 0x8a, 0xa9,
98         0x85, 0x98, 0x59, 0x07, 0x2f, 0x6c, 0x07, 0x58, 0x02, 0x58, 0x97, 0x83,
99         0xa9, 0x79, 0x27, 0x0f, 0xe2, 0x9f, 0x8f, 0x27, 0xd8, 0xd7, 0x7c, 0x00,
100         0x93, 0xc9, 0x88, 0x4a, 0x12, 0x38, 0xdc, 0xf6, 0x02, 0x9f, 0x4f, 0x8c,
101         0xa2, 0x13, 0x42, 0x14, 0x6b, 0xd4, 0x9c, 0x3e, 0x7d, 0x9a, 0x5b, 0xb7,
102         0x6e, 0xa1, 0xd7, 0xeb, 0x29, 0x2d, 0x2d, 0xa5, 0xac, 0xac, 0x2c, 0x93,
103         0xb4, 0x5a, 0x2d, 0x00, 0xfb, 0xb6, 0x00, 0x0e, 0x15, 0x8e, 0x80, 0x5f,
104         0x46, 0x14, 0x84, 0xad, 0x69, 0xc8, 0xf2, 0xde, 0x3d, 0x3b, 0x8d, 0x41,
105         0x6f, 0x20, 0x24, 0xfb, 0xd0, 0x12, 0xa4, 0xc5, 0x56, 0x81, 0x28, 0x90,
106         0x11, 0xe9, 0xeb, 0xeb, 0xe3, 0xce, 0x9d, 0x3b, 0x78, 0x3c, 0x99, 0x43,
107         0x2e, 0xcf, 0x1a, 0x77, 0x02, 0x70, 0x8e, 0x0c, 0xaf, 0x01, 0x41, 0x7f,
108         0x40, 0xc6, 0xbf, 0x1e, 0x60, 0x23, 0xe0, 0x27, 0x28, 0xfb, 0x09, 0x06,
109         0x7c, 0xc8, 0xb2, 0x8f, 0xa2, 0x22, 0x35, 0xe6, 0x72, 0x33, 0x92, 0x24,
110         0xd0, 0x62, 0xab, 0xa4, 0xa6, 0xca, 0x9c, 0xf1, 0x2a, 0x6d, 0xad, 0xad,
111         0xad, 0x5c, 0xbd, 0x7a, 0x95, 0x93, 0x27, 0x4f, 0xb2, 0xba, 0xba, 0x5a,
112         0x18, 0xa0, 0x61, 0xe7, 0x08, 0x00, 0xb8, 0x01, 0x02, 0xf2, 0x06, 0x16,
113         0x8b, 0x19, 0xb3, 0xd9, 0x84, 0xc5, 0x6c, 0xa2, 0xdc, 0x64, 0x42, 0xaf,
114         0xd3, 0xf2, 0xa7, 0x8f, 0x7e, 0x4b, 0xe7, 0xf1, 0xe3, 0xa8, 0xa4, 0xad,
115         0x7b, 0x86, 0xc9, 0x64, 0xca, 0x11, 0x1b, 0x18, 0x18, 0xe0, 0xd4, 0xa9,
116         0x53, 0x1c, 0x3d, 0x7a, 0x94, 0xd1, 0xd1, 0xd1, 0x3c, 0x80, 0xb2, 0x3d,
117         0x06, 0xcc, 0xc6, 0x52, 0x48, 0xee, 0x04, 0x23, 0xe4, 0x5e, 0x48, 0xe6,
118         0x80, 0x03, 0x8b, 0x2b, 0x6b, 0x58, 0x2c, 0x96, 0xe4, 0x4f, 0x45, 0x49,
119         0xfe, 0x54, 0xbc, 0x5e, 0x0f, 0xef, 0xbd, 0xfb, 0x1b, 0x26, 0x27, 0x27,
120         0x73, 0x06, 0x3c, 0x72, 0xe4, 0x08, 0x63, 0x63, 0x63, 0x74, 0x76, 0x76,
121         0x66, 0xea, 0x06, 0x07, 0x07, 0xb1, 0xdb, 0xed, 0x9c, 0x39, 0x73, 0x86,
122         0xaa, 0xaa, 0x2a, 0x3a, 0x3b, 0x3b, 0xb9, 0x7e, 0xfd, 0x3a, 0x13, 0x13,
123         0x13, 0x8c, 0x8f, 0x8f, 0x53, 0x5f, 0x5b, 0xc9, 0xca, 0x9a, 0x3f, 0x1d,
124         0x05, 0x67, 0x76, 0x04, 0xe6, 0x00, 0x96, 0x96, 0xd7, 0x90, 0x44, 0x32,
125         0xdb, 0x10, 0x25, 0x4e, 0xdf, 0xf7, 0x5f, 0xa1, 0xbf, 0xbf, 0x1f, 0xab,
126         0xd5, 0x9a, 0x03, 0xd0, 0xde, 0xde, 0xce, 0xd8, 0xd8, 0x58, 0x4e, 0x9d,
127         0x2c, 0xcb, 0x54, 0x57, 0x57, 0x73, 0xe5, 0xca, 0x15, 0xec, 0x76, 0x3b,
128         0x5e, 0xaf, 0x97, 0xa1, 0xa1, 0x21, 0x16, 0x17, 0x17, 0xe9, 0xea, 0xea,
129         0xa2, 0xae, 0xba, 0x2a, 0xdd, 0xd4, 0xbe, 0x3d, 0x02, 0x6e, 0x80, 0xc5,
130         0xe5, 0x35, 0x44, 0x51, 0x40, 0x05, 0x2c, 0x2d, 0x2d, 0x73, 0xe9, 0xe2,
131         0x77, 0xd0, 0xeb, 0x74, 0x5c, 0xbb, 0x76, 0x2d, 0x2f, 0xa4, 0xe1, 0x70,
132         0x98, 0x27, 0x4f, 0x9e, 0x30, 0x34, 0x34, 0x84, 0xcf, 0xe7, 0x03, 0xc0,
133         0x60, 0x30, 0xe0, 0x70, 0x38, 0x38, 0x7b, 0xf6, 0x2c, 0x03, 0x03, 0x03,
134         0x79, 0x7d, 0x6a, 0xf6, 0x56, 0xa6, 0x8b, 0x87, 0x0b, 0x4d, 0x41, 0x12,
135         0x40, 0x80, 0x37, 0x07, 0xdf, 0xe4, 0xf6, 0xed, 0xdb, 0x9c, 0x3f, 0x7f,
136         0x8e, 0x1b, 0x37, 0x6e, 0xb0, 0xba, 0xba, 0xca, 0xc3, 0x87, 0x0f, 0x79,
137         0xf4, 0xe8, 0x11, 0xb2, 0x2c, 0x03, 0xc9, 0x1d, 0xa0, 0x28, 0x0a, 0x3d,
138         0x3d, 0x3d, 0x98, 0xcd, 0xe6, 0x3c, 0xb1, 0x42, 0x56, 0xbb, 0xf5, 0x5b,
139         0xfe, 0x4a, 0x41, 0x80, 0x85, 0xa5, 0x55, 0xbc, 0x5e, 0x2f, 0x82, 0x00,
140         0x17, 0x2e, 0xf4, 0xa0, 0xd1, 0x68, 0x18, 0x1c, 0x1c, 0xa4, 0xbc, 0xbc,
141         0x9c, 0xf6, 0xf6, 0x76, 0x2e, 0x5f, 0xbe, 0x8c, 0xc1, 0x60, 0xc8, 0x74,
142         0xba, 0x7b, 0xf7, 0x2e, 0x6e, 0xb7, 0x7b, 0xd7, 0x00, 0x16, 0xb3, 0x31,
143         0x5d, 0x6c, 0xeb, 0xe8, 0xee, 0xd5, 0x65, 0x03, 0xb8, 0x00, 0x66, 0xe6,
144         0xe6, 0xb9, 0x7f, 0xff, 0x3e, 0x27, 0x4e, 0x9c, 0xa0, 0xad, 0xad, 0x2d,
145         0x6f, 0xbb, 0x6d, 0xb7, 0x63, 0xc7, 0x8e, 0x71, 0xef, 0xde, 0x3d, 0x1c,
146         0x0e, 0xc7, 0xae, 0x00, 0x34, 0x1a, 0x75, 0xba, 0x58, 0x04, 0xd8, 0xb2,
147         0x01, 0x9e, 0x03, 0x89, 0x85, 0xa5, 0x55, 0xb1, 0xa7, 0xe7, 0x0d, 0x34,
148         0x9a, 0x1d, 0x6f, 0xde, 0x39, 0x66, 0xb5, 0x5a, 0x99, 0x9f, 0x9f, 0xdf,
149         0x55, 0xdb, 0x8d, 0xcd, 0x30, 0xf7, 0x7f, 0x9f, 0xb3, 0x3d, 0x7d, 0x19,
150         0x00, 0xe7, 0xc8, 0xf0, 0x66, 0x47, 0x77, 0xaf, 0x4b, 0x51, 0x94, 0x06,
151         0x97, 0x67, 0x81, 0xe6, 0xc6, 0xbc, 0x0b, 0xec, 0x7f, 0x64, 0x4b, 0x2b,
152         0x3e, 0xa6, 0xa6, 0xdd, 0x4c, 0x4d, 0xcf, 0x31, 0x35, 0xe3, 0x66, 0x6a,
153         0xda, 0x8d, 0x67, 0x7e, 0x91, 0x44, 0x22, 0x73, 0x1f, 0x7d, 0xdf, 0x39,
154         0x32, 0xec, 0xd9, 0xfe, 0x30, 0x79, 0x0c, 0x34, 0xcc, 0xce, 0xcd, 0xef,
155         0x1a, 0x20, 0x16, 0x8b, 0x63, 0x3f, 0x7c, 0x84, 0xf7, 0x7f, 0xe7, 0xc4,
156         0xe5, 0x5d, 0x48, 0x89, 0xba, 0xf1, 0xaf, 0xcb, 0x3b, 0x75, 0x99, 0x05,
157         0xee, 0x01, 0x6f, 0x40, 0xfe, 0xcb, 0xe8, 0xef, 0xc0, 0x89, 0xa7, 0xcf,
158         0x5c, 0x1c, 0xff, 0xda, 0x8b, 0x79, 0x3d, 0x03, 0x72, 0x28, 0x29, 0x30,
159         0x33, 0x97, 0x11, 0x9a, 0x99, 0x9b, 0x27, 0x1a, 0x8d, 0x15, 0x12, 0x4a,
160         0x00, 0xcf, 0x80, 0x4f, 0x81, 0x71, 0xe0, 0x13, 0x60, 0xcc, 0x39, 0x32,
161         0xfc, 0x45, 0x76, 0xa3, 0xed, 0x00, 0x0f, 0x80, 0x1f, 0xbd, 0xf7, 0xe1,
162         0x5f, 0xd0, 0x15, 0x6b, 0xd9, 0x53, 0xa2, 0x67, 0x65, 0xcd, 0xcf, 0xb4,
163         0xcb, 0xcb, 0xd4, 0xb4, 0x9b, 0x85, 0xa5, 0xc2, 0x67, 0x3c, 0xb0, 0x42,
164         0xf2, 0xed, 0x37, 0x91, 0x12, 0x9c, 0x00, 0x26, 0x9d, 0x23, 0xc3, 0xc1,
165         0x9d, 0x3a, 0xa4, 0x2d, 0xef, 0x71, 0xda, 0xd1, 0xdd, 0xfb, 0x0b, 0xe0,
166         0xdc, 0x0e, 0xed, 0x03, 0xc0, 0x67, 0x29, 0xb1, 0x7f, 0xa4, 0xf2, 0x49,
167         0xe7, 0xc8, 0xf0, 0xee, 0x56, 0x61, 0x01, 0x2b, 0xf4, 0x38, 0xed, 0x01,
168         0xde, 0x01, 0xba, 0x00, 0x43, 0x96, 0xe0, 0x24, 0x30, 0x5b, 0xe8, 0x89,
169         0xfd, 0xbf, 0xd8, 0xbf, 0x00, 0x33, 0x30, 0x7d, 0x18, 0x07, 0x61, 0x44,
170         0x81, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
171         0x82
172 };
173
174 #include <iostream>
175 #include <limits>
176 using namespace std;
177 #include <GL/glut.h>
178 #include <qtimer.h>
179 #include <qtooltip.h>
180 #include <qimage.h>
181 #include <Music/Music.h>
182
183 void GLStatistics::AverageNote::init()
184 {
185         err_mean = 0.0;
186         err_std = 0.0;
187 }
188 GLStatistics::AverageNote::AverageNote()
189         : ht(-1000)
190 {
191         init();
192 }
193 GLStatistics::AverageNote::AverageNote(int h)
194         : ht(h)
195 {
196         init();
197 }
198 GLStatistics::AverageNote::AverageNote(int h, int num, int den)
199         : ht(h)
200 {
201         init();
202         factor = QString::number(num)+"/"+QString::number(den);
203 }
204 GLStatistics::AverageNote::AverageNote(int h, float cents)
205         : ht(h)
206 {
207         init();
208         factor = QString::number(cents);
209 }
210 QString GLStatistics::AverageNote::getName() const
211 {
212         return Music::h2n(ht)+factor;
213 }
214 void GLStatistics::AverageNote::addErr(float err)
215 {
216         // mean estimation
217         if(!errs.empty())
218                 err_mean *= errs.size();
219         errs.push_back(err);
220         err_mean += err;
221         err_mean /= errs.size();
222
223         // standard deviation estimation
224         err_std = 0.0;
225         for(size_t i=0; i<errs.size(); i++)
226         {
227                 float de = errs[i]-err_mean;
228                 err_std += de*de;
229         }
230         if(errs.size()>1)
231         {
232                 err_std /= errs.size()-1;                                               // unbiased estimation of the variance
233                 err_std = sqrt(err_std);
234         }
235 }
236
237 void GLStatistics::addNote(int ht, float err)
238 {
239         if(isHidden() && !setting_keep_hidden->isOn())
240                 return;
241
242         if(ht<setting_scale_min->minValue() || ht>setting_scale_max->maxValue())
243                 return;
244
245 //      cerr << "ht=" << ht << endl;
246
247         if(setting_scale_auto->isOn())
248         {
249                 if(m_avg_notes.empty())
250                 {
251                         m_avg_notes.resize(1);
252                         m_avg_notes[0] = AverageNote(ht);
253                         setting_scale_min->setValue(ht);
254                         setting_scale_max->setValue(ht);
255                 }
256                 else if(ht<setting_scale_min->value())
257                 {
258 //                      cerr << "min: ";
259                         int min_ht = ht;
260                         vector<AverageNote> avg_notes(setting_scale_max->value()-min_ht+1);
261                         for(int i=0; i<setting_scale_min->value()-min_ht; i++)
262                                 avg_notes[i].ht = min_ht+i;
263                         for(size_t i=0; i<m_avg_notes.size(); i++)
264                                 avg_notes[setting_scale_min->value()-min_ht+i] = m_avg_notes[i];
265                         m_avg_notes = avg_notes;
266                         setting_scale_min->setValue(ht);
267 /*                      for(size_t i=0; i<m_avg_notes.size(); i++)
268                                 cerr << m_avg_notes[i].ht << " ";
269                         cerr << "[" << setting_scale_min->value() << ":" << setting_scale_max->value() << "]" << endl;*/
270                 }
271                 else if(ht>setting_scale_max->value())
272                 {
273 //                      cerr << "max: ";
274                         int max_ht = ht;
275                         vector<AverageNote> avg_notes(max_ht-setting_scale_min->value()+1);
276                         for(size_t i=0; i<m_avg_notes.size(); i++)
277                                 avg_notes[i] = m_avg_notes[i];
278                         for(size_t i=m_avg_notes.size(); i<avg_notes.size(); i++)
279                                 avg_notes[i].ht = setting_scale_min->value()+i;
280                         m_avg_notes = avg_notes;
281                         setting_scale_max->setValue(ht);
282 /*                      for(size_t i=0; i<m_avg_notes.size(); i++)
283                                 cerr << m_avg_notes[i].ht << " ";
284                         cerr << "[" << setting_scale_min->value() << ":" << setting_scale_max->value() << "]" << endl;*/
285                 }
286
287 //              cerr << setting_scale_min->value()-ht << endl;
288
289                 m_avg_notes[ht-setting_scale_min->value()].addErr(err);
290         }
291 }
292 void GLStatistics::addNote(int ht, int num, int den, float err)
293 {
294 }
295 void GLStatistics::addNote(int ht, float cents, float err)
296 {
297 }
298
299 GLStatistics::GLStatistics(QWidget* parent)
300 : QGLWidget(parent, "GLStatistics")
301 , View("Statistics", this)
302 {
303         // settings
304         QImage img;
305         img.loadFromData(g_icon_statistics, sizeof(g_icon_statistics), "PNG");
306         setting_show->setIconSet(QIconSet(QImage(img)));
307         setting_show->setOn(false);
308         hide();
309
310         setting_reset = new QAction(this);
311         setting_reset->setMenuText(tr("Reset statistics"));
312         connect(setting_reset, SIGNAL(activated()), this, SLOT(reset()));
313         setting_reset->addTo(&m_popup_menu);
314
315         setting_keep_hidden = new QAction(this);
316         setting_keep_hidden->setMenuText(tr("Keep notes when hidden"));
317         setting_keep_hidden->setToggleAction(true);
318         setting_keep_hidden->setOn(false);
319         connect(setting_keep_hidden, SIGNAL(toggled(bool)), this, SLOT(update()));
320         setting_keep_hidden->addTo(&m_popup_menu);
321
322         setting_show_std = new QAction(this);
323         setting_show_std->setMenuText(tr("Show standard deviation"));
324         setting_show_std->setToggleAction(true);
325         setting_show_std->setOn(true);
326         setting_show_std->setEnabled(true);
327         connect(setting_show_std, SIGNAL(toggled(bool)), this, SLOT(update()));
328         setting_show_std->addTo(&m_popup_menu);
329
330         setting_scale_auto = new QAction(this);
331         setting_scale_auto->setMenuText(tr("Scale auto"));
332         setting_scale_auto->setToggleAction(true);
333         setting_scale_auto->setOn(true);
334         setting_scale_auto->setEnabled(false);
335         connect(setting_scale_auto, SIGNAL(toggled(bool)), this, SLOT(update()));
336         setting_scale_auto->addTo(&m_popup_menu);
337
338         m_popup_menu.insertItem(new Title(tr("Scale min"), &m_popup_menu));
339         setting_scale_min = new QSpinBox(-96, 96, 1, &m_popup_menu);
340         setting_scale_min->setValue(0);
341         QToolTip::add(setting_scale_min, tr("Scale min value (in semi-tones)"));
342         connect(setting_scale_min, SIGNAL(valueChanged(int)), this, SLOT(update()));
343         m_popup_menu.insertItem(setting_scale_min);
344         setting_scale_min->setEnabled(false);
345
346         m_popup_menu.insertItem(new Title(tr("Scale max"), &m_popup_menu));
347         setting_scale_max = new QSpinBox(-96, 96, 1, &m_popup_menu);
348         setting_scale_max->setValue(0);
349         QToolTip::add(setting_scale_max, tr("Scale max value (in semi-tones)"));
350         connect(setting_scale_max, SIGNAL(valueChanged(int)), this, SLOT(update()));
351         m_popup_menu.insertItem(setting_scale_max);
352         setting_scale_max->setEnabled(false);
353
354         setting_showTolerance = new QAction(this);
355         setting_showTolerance->setMenuText(tr("Show tolerance"));
356         setting_showTolerance->setToggleAction(true);
357         setting_showTolerance->setOn(true);
358         connect(setting_showTolerance, SIGNAL(toggled(bool)), this, SLOT(update()));
359         setting_showTolerance->addTo(&m_popup_menu);
360
361         setting_useCents = new QAction(this);
362         setting_useCents->setMenuText(tr("Use cents"));
363         setting_useCents->setToggleAction(true);
364         setting_useCents->setOn(true);
365         connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update()));
366         setting_useCents->addTo(&m_popup_menu);
367
368         m_popup_menu.insertItem(new Title(tr("Scale range"), &m_popup_menu));
369         setting_spinScale = new QSpinBox(5, 50, 1, &m_popup_menu);
370         setting_spinScale->setValue(50);
371         QToolTip::add(setting_spinScale, tr("Scale range (in cents)"));
372         connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update()));
373         m_popup_menu.insertItem(setting_spinScale);
374 }
375
376 void GLStatistics::save()
377 {
378         s_settings->writeEntry("setting_keep_hidden", setting_keep_hidden->isOn());
379         s_settings->writeEntry("setting_show_std", setting_show_std->isOn());
380         s_settings->writeEntry("setting_scale_auto", setting_scale_auto->isOn());
381         s_settings->writeEntry("setting_scale_min", setting_scale_min->value());
382         s_settings->writeEntry("setting_scale_max", setting_scale_max->value());
383 }
384 void GLStatistics::load()
385 {
386         setting_keep_hidden->setOn(s_settings->readBoolEntry("setting_keep_hidden", setting_keep_hidden->isOn()));
387         setting_show_std->setOn(s_settings->readBoolEntry("setting_show_std", setting_show_std->isOn()));
388         setting_scale_auto->setOn(s_settings->readBoolEntry("setting_scale_auto", setting_scale_auto->isOn()));
389         setting_scale_min->setValue(s_settings->readNumEntry("setting_scale_min", setting_scale_min->value()));
390         setting_scale_max->setValue(s_settings->readNumEntry("setting_scale_max", setting_scale_max->value()));
391 }
392 void GLStatistics::clearSettings()
393 {
394         s_settings->removeEntry("setting_keep_hidden");
395         s_settings->removeEntry("setting_show_std");
396         s_settings->removeEntry("setting_scale_auto");
397         s_settings->removeEntry("setting_scale_min");
398         s_settings->removeEntry("setting_scale_max");
399 }
400
401 void GLStatistics::reset()
402 {
403         m_avg_notes.clear();
404         setting_scale_min->setValue(0);
405         setting_scale_max->setValue(0);
406         updateGL();
407 }
408
409 void GLStatistics::initializeGL()
410 {
411         // Set the clear color to black
412         glClearColor(1.0, 1.0, 1.0, 0.0);
413
414         // glShadeModel( GL_FLAT );
415         glShadeModel( GL_SMOOTH );
416
417         glLoadIdentity();
418 }
419
420 void GLStatistics::drawTicksCent(int r, int dx, int dy)
421 {
422         // only work within range that is a pure multiple of r
423         float range = int(setting_spinScale->value()/r)*r;
424
425         float scale = 50.0f/setting_spinScale->value();
426
427         if((height()-dy)*r/100.0f*scale>2)
428         {
429                 for(float i=-range; i<=range; i+=r)
430                 {
431                         int y = int((height()-dy)*i/100.0f*scale) + (height()-dy)/2 + dy;
432                         glVertex2i(dx,  y);
433                         glVertex2i(width(),  y);
434                 }
435         }
436 }
437 void GLStatistics::drawTextTickCent(int r, int dy)
438 {
439         // only work within range that is a pure multiple of r
440         int range = int(setting_spinScale->value()/r)*r;
441
442         float scale = 50.0f/setting_spinScale->value();
443         QString txt;
444         for(int i=-range; i<range; i+=r)
445         {
446                 txt = QString::number(i);
447                 if(i>=0) txt = QString("  ")+txt;
448                 if(i==0) txt = QString("  ")+txt;
449                 glRasterPos2i(2, int((height()-dy)*i/100.0f*scale) + (height()-dy)/2 + dy - 4);
450                 for(size_t i=0; i<txt.length(); i++)
451                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, txt.latin1()[i]);
452         }
453 }
454
455 void GLStatistics::paintGL()
456 {
457 //      cerr << "GLStatistics::paintGL " << m_notes.size() << endl;
458
459         glClear(GL_COLOR_BUFFER_BIT);
460
461         glLineWidth(1.0f);
462         float human_tol = Music::f2hf(441.0,440.0);
463         float scale;
464         if(setting_useCents->isOn())
465                 scale = 50.0f/setting_spinScale->value();
466         else
467                 scale = int(50/setting_spinScale->value());
468
469         // name
470         QString str = tr("Statistics");
471         glColor3f(0.75,0.75,0.75);
472         glRasterPos2i(2, height()-20);
473         for(size_t i = 0; i < str.length(); i++)
474                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str.latin1()[i]);
475
476         int char_size = 9;
477         int ticks_size = 2+3*char_size;
478         int grid_width = width()-ticks_size;
479         int dy = char_size/2;
480         int legend_height = 40;
481         int grid_height = height()-legend_height;
482
483         // draw green rect
484         if(setting_showTolerance->isOn())
485         {
486                 int green_ytop = int((scale*human_tol+0.5)*grid_height) + legend_height;
487                 int green_ybottom = int((-scale*human_tol+0.5)*grid_height) + legend_height;
488
489                 glBegin(GL_QUADS);
490                 glColor3f(168/256.0,221/256.0,182/256.0);
491                 glVertex2i(ticks_size, green_ytop);
492                 glVertex2i(ticks_size, green_ybottom);
493                 glVertex2i(width(), green_ybottom);
494                 glVertex2i(width(), green_ytop);
495                 glEnd();
496
497                 // draw green lines
498                 glBegin(GL_LINES);
499                 glColor3f(0.48,0.80,0.57);
500                 glVertex2i(ticks_size, green_ytop);
501                 glVertex2i(width(), green_ytop);
502                 glVertex2i(ticks_size, green_ybottom);
503                 glVertex2i(width(), green_ybottom);
504                 glEnd();
505         }
506
507         // std
508         if(setting_show_std->isOn())
509         {
510                 glBegin(GL_QUADS);
511                 glLineWidth(1.0f);
512                 glColor3f(0.85, 0.85, 0.85);
513                 for(size_t i=0; i<m_avg_notes.size(); i++)
514                 {
515                         if(!m_avg_notes[i].errs.empty())
516                         {
517                                 int top = int((scale*(m_avg_notes[i].err_mean+m_avg_notes[i].err_std)+0.5)*grid_height) + legend_height;
518                                 top = max(top, legend_height);
519                                 int bottom = int((scale*(m_avg_notes[i].err_mean-m_avg_notes[i].err_std)+0.5)*grid_height) + legend_height;
520                                 bottom = max(bottom, legend_height);
521                                 int left = ticks_size+int(i*float(grid_width)/m_avg_notes.size())+1;
522                                 int right = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
523
524                                 glVertex2i(left, top);
525                                 glVertex2i(left, bottom);
526                                 glVertex2i(right, bottom);
527                                 glVertex2i(right, top);
528                         }
529                 }
530                 glEnd();
531         }
532
533         // horiz lines
534         if(setting_useCents->isOn())
535         {
536                 glBegin(GL_LINES);
537                 float gray = 0.87;
538 //              glColor3f(gray, gray, gray);
539 //              drawTicksCent(1, ticks_size);
540                 gray = 0.875;
541                 glColor3f(gray, gray, gray);
542                 drawTicksCent(2, ticks_size, legend_height);
543                 gray = 0.75;
544                 glColor3f(gray, gray, gray);
545                 drawTicksCent(10, ticks_size, legend_height);
546                 glEnd();
547         }
548         else
549         {
550                 glBegin(GL_LINES);
551                         float gray = 0.5;
552                         glColor3f(gray, gray, gray);
553                         glVertex2i(ticks_size,  grid_height/2+legend_height);
554                         glVertex2i(width(),  grid_height/2+legend_height);
555                         gray = 0.75;
556                         glColor3f(gray, gray, gray);
557                         glVertex2i(ticks_size,  grid_height/4+legend_height);
558                         glVertex2i(width(),  grid_height/4+legend_height);
559                         glVertex2i(ticks_size,  3*grid_height/4+legend_height);
560                         glVertex2i(width(),  3*grid_height/4+legend_height);
561                         gray = 0.87;
562                         glColor3f(gray, gray, gray);
563                         glVertex2i(ticks_size,  grid_height/8+legend_height);
564                         glVertex2i(width(),  grid_height/8+legend_height);
565                         glVertex2i(ticks_size,  7*grid_height/8+legend_height);
566                         glVertex2i(width(),  7*grid_height/8+legend_height);
567                         glVertex2i(ticks_size,  3*grid_height/8+legend_height);
568                         glVertex2i(width(),  3*grid_height/8+legend_height);
569                         glVertex2i(ticks_size,  5*grid_height/8+legend_height);
570                         glVertex2i(width(),  5*grid_height/8+legend_height);
571                 glEnd();
572         }
573
574         // center line
575 //      glBegin(GL_LINES);
576 //      glColor3f(0,0,0);
577 //      glVertex2i(ticks_size, grid_height/2+legend_height);
578 //      glVertex2i(width(), grid_height/2+legend_height);
579 //      glEnd();
580
581         // text marks
582         float gray = 0.5;
583         glColor3f(gray, gray, gray);
584         if(setting_useCents->isOn())
585         {
586                 int grad = 10;
587                 if(setting_spinScale->value() <= 25) grad=5;
588                 if(setting_spinScale->value() <= 10) grad=1;
589                 drawTextTickCent(grad, legend_height);
590         }
591         else
592         {
593                 string sfraq, sufraq;
594                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).latin1();
595                 sfraq = string("+")+sufraq;
596                 glRasterPos2i(2, 3*grid_height/4-dy+legend_height);
597                 for(size_t i = 0; i < sfraq.size(); i++)
598                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
599                 sfraq = string("-")+sufraq;
600                 glRasterPos2i(2, grid_height/4-dy+legend_height);
601                 for(size_t i = 0; i < sfraq.size(); i++)
602                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
603
604                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).latin1();
605                 sfraq = string("+")+sufraq;
606                 glRasterPos2i(2, 5*grid_height/8-dy+legend_height);
607                 for(size_t i = 0; i < sfraq.size(); i++)
608                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
609                 sfraq = string("-")+sufraq;
610                 glRasterPos2i(2, 3*grid_height/8-dy+legend_height);
611                 for(size_t i = 0; i < sfraq.size(); i++)
612                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
613         }
614
615         // vertical lines
616         glBegin(GL_LINES);
617         gray = 0.5;
618         glColor3f(gray, gray, gray);
619         for(size_t i=0; i<m_avg_notes.size(); i++)
620         {
621                 int x = ticks_size+int(i*float(grid_width)/m_avg_notes.size());
622                 glVertex2i(x, legend_height);
623                 glVertex2i(x, height());
624         }
625         glEnd();
626
627         // note names
628         glColor3f(0, 0, 1);
629         for(size_t i=0; i<m_avg_notes.size(); i++)
630         {
631                 string str = m_avg_notes[i].getName();
632
633                 glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 2);
634
635                 for(size_t c=0; c<str.length(); c++)
636                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[c]);
637         }
638
639         // sizes
640         glColor3f(0, 0, 1);
641         for(size_t i=0; i<m_avg_notes.size(); i++)
642         {
643                 if(!m_avg_notes[i].errs.empty())
644                 {
645
646                         string str = QString::number(m_avg_notes[i].errs.size());
647
648                         glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 4+legend_height/2);
649
650                         for(size_t c=0; c<str.length(); c++)
651                                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[c]);
652                 }
653         }
654
655         // means
656         glLineWidth(2.0f);
657         glBegin(GL_LINES);
658         glColor3f(0, 0, 0);
659         for(size_t i=0; i<m_avg_notes.size(); i++)
660         {
661                 if(!m_avg_notes[i].errs.empty())
662                 {
663                         int y = int((scale*(m_avg_notes[i].err_mean)+0.5)*grid_height) + legend_height;
664                         int left = ticks_size+int(i*float(grid_width)/m_avg_notes.size())+1;
665                         int right = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
666
667                         glVertex2i(left, y);
668                         glVertex2i(right, y);
669                 }
670         }
671         glEnd();
672
673         glFlush();
674 }
675
676 void GLStatistics::resizeGL( int w, int h )
677 {
678         // Set the new viewport size
679         glViewport(0, 0, (GLint)w, (GLint)h);
680
681         // Choose the projection matrix to be the matrix
682         // manipulated by the following calls
683         glMatrixMode(GL_PROJECTION);
684
685         // Set the projection matrix to be the identity matrix
686         glLoadIdentity();
687
688         // Define the dimensions of the Orthographic Viewing Volume
689         glOrtho(0.0, w, 0.0, h, 0.0, 1.0);
690
691         // Choose the modelview matrix to be the matrix
692         // manipulated by further calls
693         glMatrixMode(GL_MODELVIEW);
694 }