Import upstream version 0.99.2
[fmit.git] / src / modules / GLErrorHistory.cpp
1 // Copyright 2004 "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 "GLErrorHistory.h"
20
21 static const unsigned char g_icon_error_graph[] = {
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     0xa7, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0xad, 0x96, 0x6b, 0x6c, 0x14,
26     0xe7, 0x15, 0x86, 0x9f, 0x99, 0xd9, 0x9d, 0xdd, 0xf1, 0xda, 0x2c, 0xbe,
27     0xc6, 0x18, 0x63, 0x9b, 0xa4, 0x4d, 0x7c, 0x81, 0x60, 0x70, 0x1a, 0x1b,
28     0x5a, 0xe3, 0xc4, 0x24, 0xa4, 0xa2, 0x11, 0x25, 0x40, 0x12, 0x88, 0x94,
29     0x0b, 0xa9, 0x22, 0x15, 0xa5, 0x37, 0x45, 0x95, 0xaa, 0x26, 0x52, 0x2a,
30     0x35, 0x45, 0x55, 0xd3, 0x4a, 0xa1, 0x6d, 0x54, 0x1a, 0xa9, 0x09, 0x71,
31     0x83, 0x52, 0xe4, 0x34, 0x8d, 0x9a, 0x90, 0xd0, 0x48, 0x34, 0xa9, 0xb9,
32     0xd8, 0x01, 0x92, 0x62, 0xa8, 0xb9, 0x18, 0xb1, 0x06, 0xdb, 0x05, 0x7b,
33     0xd7, 0x7b, 0xf1, 0xee, 0xec, 0xce, 0xee, 0xec, 0xee, 0xcc, 0xf4, 0x87,
34     0xed, 0x05, 0x5f, 0xb0, 0x37, 0xd0, 0xf7, 0xdf, 0x9c, 0xf9, 0xbe, 0xf3,
35     0x3e, 0x73, 0xe6, 0x3b, 0x67, 0x06, 0xbe, 0xbc, 0x5c, 0xc0, 0x36, 0xa0,
36     0x43, 0x90, 0x65, 0x43, 0x94, 0xe5, 0xa4, 0x20, 0x49, 0x1a, 0xa0, 0x02,
37     0x67, 0x81, 0xe7, 0x80, 0x82, 0x6c, 0x93, 0x09, 0x5f, 0xd2, 0xfc, 0x6b,
38     0x40, 0x7b, 0xcd, 0x13, 0x4f, 0x56, 0x55, 0xaf, 0x5b, 0x4f, 0x61, 0xe9,
39     0x02, 0xf2, 0x9d, 0x06, 0x05, 0x8e, 0x34, 0x45, 0x4e, 0x0b, 0x77, 0xca,
40     0x45, 0xe7, 0xfe, 0x7f, 0xf1, 0xfa, 0xcb, 0xbf, 0x4a, 0xa8, 0x81, 0xe0,
41     0x5e, 0xe0, 0x79, 0x60, 0xe8, 0xff, 0x05, 0xf0, 0x03, 0xa5, 0xa8, 0xf8,
42     0xd7, 0x6b, 0x7f, 0xfb, 0xaa, 0x5c, 0x52, 0x5e, 0x01, 0xc0, 0x7c, 0x47,
43     0x3a, 0x63, 0xde, 0x50, 0xb4, 0x98, 0x65, 0x85, 0x95, 0xf4, 0x45, 0xbc,
44     0x9c, 0x09, 0x0d, 0xb1, 0xe7, 0xbd, 0x7d, 0xbc, 0xf3, 0xdc, 0x8b, 0x17,
45     0x80, 0x35, 0xc0, 0xc0, 0xcd, 0x00, 0xb8, 0x81, 0x37, 0x16, 0x36, 0xb7,
46     0x6c, 0xbc, 0xf7, 0x85, 0x9f, 0xa1, 0x28, 0xca, 0xac, 0xe6, 0x1e, 0xd5,
47     0x47, 0x5f, 0x64, 0x04, 0x35, 0x25, 0xf2, 0xf9, 0x17, 0xbd, 0xbc, 0xf3,
48     0xcc, 0xb3, 0x03, 0x98, 0xe6, 0x1a, 0xe0, 0xc2, 0x8d, 0x00, 0x34, 0x00,
49     0xed, 0x4d, 0x3f, 0x79, 0xfe, 0xd6, 0x87, 0xb7, 0x3c, 0x46, 0xb1, 0x53,
50     0xc6, 0xb2, 0xc0, 0x69, 0x33, 0x71, 0xd9, 0x41, 0x92, 0x12, 0x94, 0x2a,
51     0xf3, 0xb9, 0xb3, 0xb0, 0x62, 0x9a, 0x79, 0x34, 0x25, 0xa1, 0x26, 0x25,
52     0x3c, 0x17, 0x06, 0xd8, 0xf7, 0xf4, 0xe3, 0x43, 0x96, 0x61, 0x54, 0x03,
53     0x91, 0xa9, 0x06, 0xd2, 0x2c, 0xe6, 0xad, 0x39, 0xf9, 0xf9, 0x9f, 0x7c,
54     0xf7, 0xf5, 0xdd, 0xc5, 0x77, 0x35, 0x36, 0xd2, 0xd9, 0x77, 0x81, 0xfd,
55     0xbd, 0xe7, 0xe8, 0xea, 0xbf, 0xc4, 0xa1, 0x8b, 0xfd, 0x7c, 0xe2, 0xe9,
56     0x27, 0x9e, 0x80, 0xa5, 0x45, 0x65, 0xa4, 0x2c, 0x9d, 0x8b, 0xaa, 0x0f,
57     0xcf, 0x14, 0xf3, 0x68, 0x4a, 0xc4, 0x12, 0x20, 0x21, 0x8a, 0x79, 0xc1,
58     0x53, 0x27, 0x83, 0x40, 0x67, 0xb6, 0x15, 0xa8, 0x05, 0x3a, 0x1f, 0xf8,
59     0xc5, 0x0e, 0x77, 0xb4, 0xac, 0x8c, 0x68, 0x32, 0x49, 0x5a, 0x55, 0x89,
60     0x75, 0x9f, 0xc2, 0x8a, 0x69, 0x98, 0x9a, 0x86, 0x63, 0x71, 0x25, 0xca,
61     0x92, 0x3a, 0x44, 0xbb, 0x9d, 0x62, 0x45, 0xe1, 0xd1, 0xea, 0x0a, 0xc2,
62     0x76, 0x83, 0xb0, 0x61, 0xcb, 0x98, 0xab, 0xe1, 0x51, 0xd4, 0x48, 0x98,
63     0x50, 0xc0, 0x4f, 0xd7, 0x8f, 0xbe, 0x7f, 0x19, 0x58, 0x0c, 0xa4, 0xb2,
64     0xa9, 0xc0, 0xde, 0x82, 0xe6, 0xe6, 0x1a, 0xa9, 0xa9, 0x89, 0x78, 0x2c,
65     0x46, 0xe8, 0xc3, 0x7f, 0xe0, 0xfa, 0xfc, 0x2c, 0x1b, 0x97, 0xad, 0xa5,
66     0xb1, 0xe2, 0x4e, 0x56, 0xd7, 0x34, 0x92, 0x3b, 0x12, 0xe7, 0xd2, 0x81,
67     0xfd, 0xa8, 0x97, 0x2e, 0x62, 0xdc, 0x5a, 0x45, 0xb7, 0x2f, 0x44, 0xa9,
68     0x6e, 0x92, 0xb0, 0xe7, 0xa0, 0x9a, 0xf6, 0x8c, 0xb9, 0x1a, 0x09, 0xa3,
69     0x45, 0x55, 0xd2, 0x02, 0xf3, 0xb4, 0xbe, 0x3e, 0x0f, 0x70, 0x72, 0x2e,
70     0x80, 0x66, 0xb9, 0xa8, 0xf8, 0xe7, 0x55, 0xdb, 0xb7, 0x23, 0x88, 0x22,
71     0xe1, 0xdd, 0x7b, 0xd8, 0xd6, 0xb2, 0x95, 0xef, 0x3c, 0xb1, 0x9d, 0x15,
72     0x2b, 0x6a, 0x39, 0x7a, 0xf4, 0x63, 0x62, 0xb1, 0x00, 0x0f, 0x7e, 0xeb,
73     0x51, 0x9a, 0xef, 0xbe, 0x8f, 0x5c, 0x4d, 0xe2, 0x8b, 0xf7, 0xdf, 0xc6,
74     0x56, 0x57, 0xcd, 0x25, 0x3d, 0x85, 0xe3, 0xca, 0x30, 0xba, 0xcd, 0x8e,
75     0x1a, 0x8b, 0xa2, 0x46, 0xc2, 0x44, 0xc7, 0x41, 0x8c, 0xbc, 0x3c, 0xa2,
76     0xc7, 0x8f, 0xbb, 0x81, 0xb6, 0x6b, 0xcd, 0x6c, 0x33, 0x00, 0x7c, 0xbb,
77     0x60, 0xd5, 0x4a, 0x24, 0x87, 0x03, 0x7f, 0xfb, 0x5f, 0x79, 0x7c, 0xcd,
78     0x56, 0x36, 0x6d, 0x5e, 0xc7, 0x6d, 0xb7, 0x15, 0xe2, 0x70, 0xd8, 0x40,
79     0xd8, 0x4a, 0x30, 0x10, 0xa7, 0xb8, 0x30, 0x07, 0x3d, 0x21, 0x73, 0x4f,
80     0xeb, 0x7d, 0xb8, 0xdd, 0xf9, 0xbc, 0xf6, 0xa7, 0x9d, 0x14, 0x3e, 0xb3,
81     0x8d, 0x5e, 0x01, 0xf2, 0x7b, 0x4e, 0x91, 0x2c, 0x2e, 0xce, 0x98, 0xab,
82     0x91, 0x30, 0xa6, 0x69, 0xc2, 0xd8, 0xa1, 0x16, 0x00, 0x6b, 0xc2, 0x4c,
83     0x9c, 0x01, 0xe0, 0xeb, 0xae, 0xaf, 0x7c, 0x95, 0x64, 0x28, 0x44, 0x55,
84     0x5a, 0x61, 0xf3, 0xa6, 0x0d, 0xd4, 0x2d, 0x29, 0xc5, 0x66, 0x13, 0x39,
85     0x77, 0xda, 0xcb, 0xe5, 0xc1, 0x20, 0xa1, 0x40, 0x00, 0x41, 0x10, 0x70,
86     0x2a, 0x76, 0x4a, 0x0a, 0x73, 0x58, 0xde, 0xd0, 0xc0, 0xa6, 0x96, 0xc7,
87     0x88, 0x1e, 0x3c, 0x82, 0x21, 0xcb, 0xf8, 0xbc, 0x43, 0x44, 0x02, 0xfe,
88     0x8c, 0xb9, 0x91, 0x4e, 0x63, 0x99, 0x26, 0x82, 0x2c, 0xcf, 0x03, 0x1c,
89     0xd7, 0x9a, 0x4d, 0x05, 0x70, 0x22, 0x49, 0x2b, 0x72, 0xaa, 0xaa, 0xd0,
90     0x4f, 0xf5, 0xf0, 0xc0, 0xbd, 0x0f, 0x72, 0x7b, 0x4d, 0x09, 0x96, 0x05,
91     0x9e, 0xf3, 0x7e, 0xd2, 0x69, 0x93, 0xe1, 0xe1, 0xcb, 0x78, 0x2e, 0x9e,
92     0x07, 0x40, 0x10, 0xa0, 0xe4, 0x96, 0x3c, 0xf2, 0xdd, 0x4e, 0x56, 0x35,
93     0xad, 0xc1, 0x3a, 0x77, 0x01, 0x33, 0x99, 0xc4, 0x28, 0x2f, 0xc7, 0x77,
94     0xba, 0x27, 0x63, 0x9e, 0x91, 0x30, 0xfd, 0xcc, 0x4f, 0x05, 0x58, 0xa6,
95     0x2c, 0x2c, 0x97, 0x45, 0x59, 0xc6, 0x3c, 0xdf, 0xc7, 0x82, 0x85, 0xb7,
96     0xf0, 0xca, 0xce, 0x97, 0x09, 0x87, 0xe2, 0x24, 0x93, 0x06, 0x00, 0xf1,
97     0xb8, 0x86, 0xaa, 0x8e, 0xb5, 0xb3, 0x53, 0xb1, 0x53, 0x54, 0xe2, 0x42,
98     0x71, 0xda, 0xc8, 0xcd, 0x93, 0x59, 0xd7, 0xfc, 0x30, 0x91, 0x23, 0x9d,
99     0xd8, 0x0b, 0x0b, 0x11, 0xe7, 0xcf, 0x9f, 0x6c, 0x7e, 0x1d, 0x4d, 0x05,
100     0x50, 0x44, 0xe7, 0x58, 0x85, 0x72, 0x45, 0x99, 0x25, 0xb5, 0xb7, 0x53,
101     0x5f, 0x5f, 0x4f, 0x28, 0xa8, 0x65, 0x16, 0x24, 0x12, 0xf1, 0x0c, 0x40,
102     0x5c, 0x4b, 0xe1, 0x39, 0xef, 0x47, 0x92, 0x44, 0x72, 0x5d, 0x32, 0xf5,
103     0x4b, 0x57, 0x62, 0xf6, 0xff, 0x17, 0x80, 0x9c, 0xca, 0xca, 0x39, 0xcd,
104     0x67, 0x02, 0xc8, 0x28, 0x6d, 0x99, 0xe4, 0xe5, 0xb9, 0x59, 0xbf, 0x7e,
105     0x3d, 0xb1, 0xa8, 0x3e, 0x19, 0x20, 0x3a, 0x6d, 0xa0, 0x61, 0xb3, 0x09,
106     0x28, 0x2e, 0x17, 0x42, 0x72, 0xec, 0xa9, 0x45, 0x69, 0xb6, 0x19, 0x97,
107     0x05, 0x80, 0x6e, 0xa5, 0xd1, 0xb4, 0x24, 0xa9, 0x94, 0x81, 0x65, 0x5d,
108     0x8d, 0xcb, 0x0e, 0x07, 0x47, 0x8f, 0x1d, 0xe2, 0x44, 0xf7, 0xb1, 0x49,
109     0xeb, 0xaf, 0x5c, 0x19, 0xa0, 0xa7, 0xa7, 0x13, 0x9b, 0x38, 0x66, 0x6c,
110     0x61, 0x91, 0x8d, 0x66, 0x6a, 0x43, 0x00, 0xd2, 0x36, 0x89, 0xe1, 0xe1,
111     0x20, 0x91, 0xd1, 0xa2, 0x49, 0xf1, 0x75, 0xdf, 0x7c, 0x88, 0xbb, 0x56,
112     0x34, 0xb1, 0xef, 0xa3, 0xbf, 0xf1, 0xf7, 0x0f, 0xda, 0x69, 0x59, 0x7d,
113     0x3f, 0xf7, 0xac, 0x5e, 0x4b, 0x34, 0x16, 0x65, 0x68, 0x68, 0x80, 0xb4,
114     0x31, 0xfe, 0xde, 0xb3, 0xf3, 0xbf, 0x3e, 0x80, 0xdc, 0xd8, 0xc0, 0x5f,
115     0xda, 0xdb, 0xa8, 0xac, 0xfc, 0xf1, 0xb4, 0x7b, 0x25, 0x25, 0x0b, 0x78,
116     0xfa, 0xa9, 0x67, 0x01, 0xe8, 0x39, 0x7d, 0x82, 0xbd, 0xed, 0xbb, 0x51,
117     0x72, 0x0a, 0xa9, 0xaa, 0x5c, 0x8a, 0x18, 0xe8, 0x1d, 0x07, 0xc8, 0x8e,
118     0xe0, 0xba, 0xaf, 0x20, 0xb7, 0xb6, 0x86, 0xce, 0xb3, 0x9f, 0x31, 0xe2,
119     0x0b, 0xcf, 0x9a, 0x60, 0x49, 0xdd, 0x72, 0x36, 0x6f, 0x7c, 0x92, 0xba,
120     0xda, 0x55, 0x1c, 0x39, 0xf6, 0x31, 0xf6, 0x65, 0x75, 0x59, 0x19, 0xcf,
121     0x09, 0x00, 0x60, 0xfb, 0x46, 0x23, 0x3b, 0xff, 0xf0, 0x0a, 0x09, 0xfd,
122     0x6a, 0x3b, 0xf9, 0x46, 0x86, 0x09, 0x06, 0xfd, 0x99, 0x6b, 0xcb, 0xb4,
123     0x08, 0x8c, 0xc6, 0xf1, 0x0e, 0x07, 0x38, 0x3d, 0xf8, 0x1f, 0x94, 0xf1,
124     0xd3, 0x6f, 0xdd, 0x6c, 0x05, 0x00, 0x72, 0x97, 0xd4, 0x71, 0xc6, 0xa5,
125     0xf3, 0xcb, 0xdf, 0xec, 0x40, 0xd3, 0x92, 0x58, 0x16, 0xec, 0xfb, 0xf0,
126     0x5d, 0xfe, 0xf9, 0xe9, 0x7e, 0x00, 0x52, 0x29, 0x83, 0x40, 0x48, 0xc3,
127     0x3b, 0x1c, 0xe6, 0x77, 0x6f, 0xbc, 0x88, 0xfb, 0x91, 0x87, 0x10, 0x66,
128     0x18, 0x36, 0xb3, 0x3e, 0xe4, 0x5c, 0x0b, 0xf2, 0x5a, 0x9a, 0x39, 0xdd,
129     0x75, 0x94, 0x1f, 0xfe, 0xf4, 0x7b, 0x6c, 0xd9, 0xb0, 0x8d, 0xd6, 0xd6,
130     0x8d, 0x88, 0xa2, 0x88, 0x2f, 0x10, 0x23, 0x12, 0xd1, 0xe9, 0x3e, 0xf1,
131     0x6f, 0xde, 0xde, 0xb7, 0x0b, 0xdb, 0xea, 0x26, 0x9c, 0x65, 0x65, 0x57,
132     0x37, 0x66, 0x59, 0x81, 0xa9, 0x00, 0x96, 0xee, 0xf5, 0xa2, 0x9e, 0x3b,
133     0x4b, 0x5e, 0x75, 0x4d, 0x26, 0x98, 0xbb, 0xb2, 0x91, 0xd8, 0x1d, 0x41,
134     0x7e, 0xff, 0xe9, 0x5b, 0x88, 0x7b, 0xbc, 0x28, 0x0e, 0x17, 0xa6, 0x65,
135     0x92, 0x36, 0xd3, 0xe8, 0xc5, 0xf3, 0x99, 0xf7, 0xd4, 0x16, 0x6c, 0x2e,
136     0xd7, 0xe4, 0x44, 0x59, 0xb6, 0xc1, 0xd4, 0x7a, 0x09, 0xc0, 0x26, 0xe0,
137     0xa5, 0xdc, 0x3b, 0xaa, 0xab, 0x4b, 0x37, 0x6c, 0xc0, 0xb5, 0x78, 0xf1,
138     0xe4, 0xc4, 0xa6, 0x89, 0x65, 0x18, 0x88, 0x76, 0xfb, 0xac, 0x89, 0x63,
139     0x7e, 0x3f, 0xa3, 0x03, 0xfd, 0x93, 0x62, 0x81, 0xb6, 0x36, 0x2c, 0x5d,
140     0x57, 0x80, 0xc4, 0x44, 0x6c, 0xa6, 0x71, 0x75, 0x06, 0xf8, 0x63, 0x32,
141     0xe0, 0xbf, 0x14, 0x3c, 0x72, 0x78, 0x79, 0x7c, 0x70, 0xd0, 0xed, 0x2c,
142     0x2b, 0xc3, 0x3e, 0x6f, 0xde, 0x18, 0xa1, 0x20, 0x20, 0x64, 0x31, 0xe5,
143     0x52, 0x5a, 0x8c, 0x44, 0x78, 0x72, 0x07, 0xc5, 0x4f, 0x9e, 0x04, 0xc3,
144     0xd8, 0x01, 0x64, 0x4e, 0xf5, 0xf5, 0x32, 0x59, 0x40, 0x37, 0xb0, 0x4b,
145     0xf7, 0x7a, 0x47, 0x02, 0x87, 0x0e, 0x36, 0xe8, 0x3e, 0x9f, 0x4b, 0x29,
146     0x2f, 0x9f, 0x56, 0xea, 0xeb, 0x29, 0x19, 0xd3, 0xd0, 0x23, 0x57, 0x01,
147     0x04, 0x49, 0x22, 0x76, 0xfc, 0xb8, 0x85, 0x65, 0xbd, 0x04, 0x18, 0x73,
148     0x01, 0x4c, 0xc8, 0x00, 0x8e, 0x02, 0xbb, 0x12, 0x97, 0x2f, 0x6b, 0xfe,
149     0x83, 0x1d, 0x0d, 0xe9, 0x70, 0xd8, 0xa9, 0x2c, 0x5a, 0x84, 0xe4, 0x74,
150     0xce, 0x0e, 0xa0, 0xc5, 0xd0, 0x23, 0xe3, 0xdf, 0x0c, 0x41, 0x20, 0xd1,
151     0xd5, 0x45, 0x72, 0x68, 0xe8, 0x05, 0xa0, 0xe3, 0xda, 0x75, 0xd9, 0x7d,
152     0x31, 0xc6, 0x7e, 0x24, 0x0f, 0x61, 0x59, 0xaf, 0xc5, 0xfb, 0xfb, 0xf1,
153     0x77, 0x74, 0xac, 0x30, 0xe2, 0x71, 0xbb, 0x52, 0x59, 0x89, 0x28, 0xcb,
154     0x33, 0x03, 0xc4, 0xae, 0x02, 0x18, 0x7d, 0x17, 0x89, 0x74, 0x75, 0xb6,
155     0x01, 0xd3, 0xc6, 0x6a, 0xb6, 0x00, 0x13, 0x4a, 0x00, 0x07, 0x30, 0xcd,
156     0xdd, 0x5a, 0x9f, 0x47, 0x09, 0x1c, 0xec, 0xa8, 0xb7, 0x0c, 0x53, 0x52,
157     0x2a, 0x2a, 0x10, 0x6d, 0x93, 0x1b, 0x2a, 0x19, 0x8d, 0xa2, 0xab, 0x11,
158     0x84, 0x70, 0x84, 0xc0, 0x07, 0xef, 0x1f, 0x04, 0x1e, 0xe1, 0x9a, 0xd2,
159     0xdf, 0x28, 0xc0, 0x84, 0xa2, 0xc0, 0x47, 0x56, 0x3a, 0xbd, 0x27, 0x76,
160     0xbe, 0xb7, 0x20, 0x70, 0xf8, 0xf0, 0x52, 0x41, 0x94, 0x04, 0x65, 0xd1,
161     0xa2, 0xcc, 0x01, 0xd5, 0x63, 0x51, 0xd2, 0xe1, 0x30, 0xbe, 0xb7, 0xfe,
162     0xec, 0x01, 0xee, 0x1f, 0xdf, 0x33, 0x4d, 0x37, 0x0a, 0x30, 0xa1, 0x51,
163     0xe0, 0x3d, 0x2b, 0x99, 0x7c, 0x57, 0x3d, 0x73, 0xa6, 0x2c, 0xf4, 0x59,
164     0x57, 0xb5, 0xe8, 0x74, 0x22, 0x17, 0x14, 0x10, 0x1f, 0x1c, 0x60, 0xe8,
165     0xcd, 0x37, 0x47, 0x31, 0x8c, 0x56, 0x60, 0xf0, 0x26, 0x7d, 0xb2, 0xd6,
166     0xdd, 0xc0, 0x81, 0x71, 0xb0, 0x6e, 0xa0, 0x75, 0xae, 0x0d, 0xff, 0x03,
167     0xed, 0xb9, 0xfb, 0x1d, 0x80, 0xeb, 0x9a, 0x91, 0x00, 0x00, 0x00, 0x00,
168     0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
169 };
170
171 #include <iostream>
172 #include <limits>
173 using namespace std;
174 #include <GL/glut.h>
175 #include <qtimer.h>
176 #include <qtooltip.h>
177 #include <qimage.h>
178 #include <qwidgetaction.h>
179 #include <qboxlayout.h>
180 #include <Music/Music.h>
181
182 void GLErrorHistory::Note::init()
183 {
184         min_err = numeric_limits<float>::max();
185         max_err = -numeric_limits<float>::max();
186         avg_err = 0.0f;
187 }
188 GLErrorHistory::Note::Note(int h)
189         : ht(h)
190 {
191         init();
192 }
193 GLErrorHistory::Note::Note(int h, int num, int den)
194         : ht(h)
195 {
196         init();
197         factor = QString::number(num)+"/"+QString::number(den);
198 }
199 GLErrorHistory::Note::Note(int h, float cents)
200         : ht(h)
201 {
202         init();
203         factor = QString::number(cents);
204 }
205 QString GLErrorHistory::Note::getName() const
206 {
207         return QString::fromStdString(Music::h2n(ht))+factor;
208 }
209 void GLErrorHistory::Note::addError(float err)
210 {
211         min_err = (err<min_err)?err:min_err;
212         max_err = (err>max_err)?err:max_err;
213
214         if(!errors.empty())
215                 avg_err *= errors.size();
216
217         errors.push_back(err);
218
219         avg_err += err;
220         avg_err /= errors.size();
221 }
222
223 GLErrorHistory::GLErrorHistory(QWidget* parent)
224 : QGLWidget(parent)
225 , View(tr("Error history"), this)
226 {
227         // settings
228         QPixmap img;
229         img.loadFromData(g_icon_error_graph, sizeof(g_icon_error_graph), "PNG");
230         setting_show->setIcon(QIcon(img));
231         setting_show->setChecked(true);
232
233         setting_keep = new QAction(tr("Keep previous notes"), this);
234         setting_keep->setCheckable(true);
235         setting_keep->setChecked(false);
236         connect(setting_keep, SIGNAL(toggled(bool)), this, SLOT(keepPreviousNotes(bool)));
237         m_popup_menu.addAction(setting_keep);
238
239         setting_useCents = new QAction(tr("Use cents"), this);
240         setting_useCents->setCheckable(true);
241         setting_useCents->setChecked(true);
242         connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update()));
243         m_popup_menu.addAction(setting_useCents);
244
245         QHBoxLayout* scaleActionLayout = new QHBoxLayout(&m_popup_menu);
246
247         QLabel* scaleActionTitle = new QLabel(tr("Scale range"), &m_popup_menu);
248         scaleActionLayout->addWidget(scaleActionTitle);
249
250         setting_spinScale = new QSpinBox(&m_popup_menu);
251         setting_spinScale->setMinimum(5);
252         setting_spinScale->setMaximum(50);
253         setting_spinScale->setSingleStep(1);
254         setting_spinScale->setValue(50);
255         setting_spinScale->setToolTip(tr("Scale range (in cents)"));
256         connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update()));
257         scaleActionLayout->addWidget(setting_spinScale);
258
259         QWidget* scaleActionWidget = new QWidget(&m_popup_menu);
260         scaleActionWidget->setLayout(scaleActionLayout);
261
262         QWidgetAction* scaleAction = new QWidgetAction(&m_popup_menu);
263         scaleAction->setDefaultWidget(scaleActionWidget);
264         m_popup_menu.addAction(scaleAction);
265 }
266
267 void GLErrorHistory::save()
268 {
269         s_settings->setValue("keep", setting_keep->isChecked());
270         s_settings->setValue("useCents", setting_useCents->isChecked());
271         s_settings->setValue("spinScale", setting_spinScale->value());
272 }
273 void GLErrorHistory::load()
274 {
275         setting_keep->setChecked(s_settings->value("keep", setting_keep->isChecked()).toBool());
276         setting_useCents->setChecked(s_settings->value("useCents", setting_useCents->isChecked()).toBool());
277         setting_spinScale->setValue(s_settings->value("spinScale", setting_spinScale->value()).toInt());
278 }
279 void GLErrorHistory::clearSettings()
280 {
281         s_settings->remove("keep");
282         s_settings->remove("useCents");
283         s_settings->remove("spinScale");
284 }
285
286 void GLErrorHistory::addNote(GLErrorHistory::Note note)
287 {
288         m_notes.push_back(note);
289
290         if(!setting_keep->isChecked())
291                 while(m_notes.size()>1)
292                         m_notes.pop_front();
293 }
294 void GLErrorHistory::addError(float err)
295 {
296         m_notes.back().addError(err);
297 }
298
299 void GLErrorHistory::keepPreviousNotes(bool keep)
300 {
301         if(!keep)
302                 while(m_notes.size()>1)
303                         m_notes.pop_front();
304 }
305
306 void GLErrorHistory::initializeGL()
307 {
308         // Set the clear color to black
309         glClearColor(1.0, 1.0, 1.0, 0.0);
310
311         // glShadeModel( GL_FLAT );
312         glShadeModel( GL_SMOOTH );
313
314         glLoadIdentity();
315 }
316
317 void GLErrorHistory::drawTicksCent(int r, int ticks_size)
318 {
319         // only work within range that is a pure multiple of r
320         float range = int(setting_spinScale->value()/r)*r;
321
322         float scale = 50.0f/setting_spinScale->value();
323         if((height()-ticks_size)*r/100.0f*scale>2)
324         {
325                 for(float i=-range; i<=range; i+=r)
326                 {
327                         int y = int(height()*i/100.0f*scale) + height()/2;
328                         glVertex2i(ticks_size,  y);
329                         glVertex2i(width(),  y);
330                 }
331         }
332 }
333 void GLErrorHistory::drawTextTickCent(int r, int dy)
334 {
335         // only work within range that is a pure multiple of r
336         int range = int(setting_spinScale->value()/r)*r;
337
338         float scale = 50.0f/setting_spinScale->value();
339         QString txt;
340         for(int i=-range; i<range; i+=r)
341         {
342                 txt = QString::number(i);
343                 if(i>=0) txt = QString("  ")+txt;
344                 if(i==0) txt = QString("  ")+txt;
345                 glRasterPos2i(2, int(height()*i/100.0f*scale) + height()/2 - dy);
346                 string str = txt.toStdString();
347                 for(size_t i=0; i<str.length(); i++)
348                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[i]);
349         }
350 }
351
352 void GLErrorHistory::paintGL()
353 {
354 //      cerr << "GLErrorHistory::paintGL " << m_notes.size() << endl;
355
356         glClear(GL_COLOR_BUFFER_BIT);
357
358         glLineWidth(1.0f);
359
360         // name
361         string str = tr("Error").toStdString();
362         glColor3f(0.75,0.75,0.75);
363         glRasterPos2i(2, height()-20);
364         for(size_t i = 0; i < str.length(); i++)
365                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (unsigned char)str[i]);
366
367         int char_size = 9;
368         int ticks_size = 2+3*char_size;
369         int dy = char_size/2;
370
371         // horiz lines
372         if(setting_useCents->isChecked())
373         {
374                 glBegin(GL_LINES);
375                 float gray = 0.87;
376 //              glColor3f(gray, gray, gray);
377 //              drawTicksCent(1, ticks_size);
378                 gray = 0.875;
379                 glColor3f(gray, gray, gray);
380                 drawTicksCent(2, ticks_size);
381                 gray = 0.75;
382                 glColor3f(gray, gray, gray);
383                 drawTicksCent(10, ticks_size);
384                 glEnd();
385         }
386         else
387         {
388                 glBegin(GL_LINES);
389                         float gray = 0.5;
390                         glColor3f(gray, gray, gray);
391                         glVertex2i(ticks_size,  height()/2);
392                         glVertex2i(width(),  height()/2);
393                         gray = 0.75;
394                         glColor3f(gray, gray, gray);
395                         glVertex2i(ticks_size,  height()/4);
396                         glVertex2i(width(),  height()/4);
397                         glVertex2i(ticks_size,  3*height()/4);
398                         glVertex2i(width(),  3*height()/4);
399                         gray = 0.87;
400                         glColor3f(gray, gray, gray);
401                         glVertex2i(ticks_size,  height()/8);
402                         glVertex2i(width(),  height()/8);
403                         glVertex2i(ticks_size,  7*height()/8);
404                         glVertex2i(width(),  7*height()/8);
405                         glVertex2i(ticks_size,  3*height()/8);
406                         glVertex2i(width(),  3*height()/8);
407                         glVertex2i(ticks_size,  5*height()/8);
408                         glVertex2i(width(),  5*height()/8);
409                 glEnd();
410         }
411
412         // text marks
413         float gray = 0.5;
414         glColor3f(gray, gray, gray);
415         if(setting_useCents->isChecked())
416         {
417                 int grad = 10;
418                 if(setting_spinScale->value() <= 25) grad=5;
419                 if(setting_spinScale->value() <= 10) grad=1;
420                 drawTextTickCent(grad, dy);
421         }
422         else
423         {
424                 string sfraq, sufraq;
425                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).toStdString();
426                 sfraq = string("+")+sufraq;
427                 glRasterPos2i(2, 3*height()/4-dy);
428                 for(size_t i = 0; i < sfraq.size(); i++)
429                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
430                 sfraq = string("-")+sufraq;
431                 glRasterPos2i(2, height()/4-dy);
432                 for(size_t i = 0; i < sfraq.size(); i++)
433                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
434
435                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).toStdString();
436                 sfraq = string("+")+sufraq;
437                 glRasterPos2i(2, 5*height()/8-dy);
438                 for(size_t i = 0; i < sfraq.size(); i++)
439                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
440                 sfraq = string("-")+sufraq;
441                 glRasterPos2i(2, 3*height()/8-dy);
442                 for(size_t i = 0; i < sfraq.size(); i++)
443                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
444         }
445
446         // errors
447         if(!m_notes.empty())
448         {
449                 int total_size = 0;
450                 for(size_t i=0; i<m_notes.size(); i++)
451                         total_size += m_notes[i].errors.size()-1;
452
453                 float step = float(width()-ticks_size)/total_size;
454
455 //              cerr << "total_size=" << total_size << " step=" << step << endl;
456
457                 int curr_total = 0;
458                 for(size_t i=0; i<m_notes.size(); i++)
459                 {
460                         float x = ticks_size+step*curr_total;
461
462                         // if it's not the first, add a separation
463                         if(i>0)
464                         {
465                                 glColor3f(0.75,0.75,0.75);
466                                 glLineWidth(1.0f);
467                                 glBegin(GL_LINES);
468                                 glVertex2f(x, 0);       glVertex2f(x, height());
469                                 glEnd();
470                         }
471
472                         // the note name
473                         string str = m_notes[i].getName().toStdString();
474                         glColor3f(0.0,0.0,1.0);
475                         glRasterPos2f(x+2, 2);
476                         for(size_t c=0; c<str.length(); c++)
477                                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[c]);
478
479                         // draw the error graph
480                         glColor3f(0.0f,0.0f,0.0f);
481                         glLineWidth(2.0f);
482                         glBegin(GL_LINE_STRIP);
483
484                         if(setting_useCents->isChecked())
485                         {
486                                 float scale = 50.0f/setting_spinScale->value();
487                                 glVertex2f(x, int(scale*m_notes[i].errors[0]*height()) + height()/2);
488                                 for(int j=1; j<int(m_notes[i].errors.size()); j++)
489                                         glVertex2f(x+j*step, scale*m_notes[i].errors[j]*height() + height()/2);
490                         }
491                         else
492                         {
493                                 float scale = int(50/setting_spinScale->value());
494                                 glVertex2f(x, int((scale*m_notes[i].errors[0])*height()) + height()/2);
495                                 for(int j=1; j<int(m_notes[i].errors.size()); j++)
496                                         glVertex2f(x+j*step, (scale*m_notes[i].errors[j])*height() + height()/2);
497                         }
498                         glEnd();
499
500                         curr_total += m_notes[i].errors.size()-1;
501                 }
502         }
503
504         glFlush();
505 }
506
507 void GLErrorHistory::resizeGL( int w, int h )
508 {
509         // Set the new viewport size
510         glViewport(0, 0, (GLint)w, (GLint)h);
511
512         // Choose the projection matrix to be the matrix
513         // manipulated by the following calls
514         glMatrixMode(GL_PROJECTION);
515
516         // Set the projection matrix to be the identity matrix
517         glLoadIdentity();
518
519         // Define the dimensions of the Orthographic Viewing Volume
520         glOrtho(0.0, w, 0.0, h, 0.0, 1.0);
521
522         // Choose the modelview matrix to be the matrix
523         // manipulated by further calls
524         glMatrixMode(GL_MODELVIEW);
525 }
526