Import fmit upstream version 0.97.6
[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 <Music/Music.h>
179
180 void GLErrorHistory::Note::init()
181 {
182         min_err = numeric_limits<float>::max();
183         max_err = -numeric_limits<float>::max();
184         avg_err = 0.0f;
185 }
186 GLErrorHistory::Note::Note(int h)
187         : ht(h)
188 {
189         init();
190 }
191 GLErrorHistory::Note::Note(int h, int num, int den)
192         : ht(h)
193 {
194         init();
195         factor = QString::number(num)+"/"+QString::number(den);
196 }
197 GLErrorHistory::Note::Note(int h, float cents)
198         : ht(h)
199 {
200         init();
201         factor = QString::number(cents);
202 }
203 QString GLErrorHistory::Note::getName() const
204 {
205         return Music::h2n(ht)+factor;
206 }
207 void GLErrorHistory::Note::addError(float err)
208 {
209         min_err = (err<min_err)?err:min_err;
210         max_err = (err>max_err)?err:max_err;
211
212         if(!errors.empty())
213                 avg_err *= errors.size();
214
215         errors.push_back(err);
216
217         avg_err += err;
218         avg_err /= errors.size();
219 }
220
221 GLErrorHistory::GLErrorHistory(QWidget* parent)
222 : QGLWidget(parent, "GLErrorHistory")
223 , View("Error history", this)
224 {
225         // settings
226         QImage img;
227         img.loadFromData(g_icon_error_graph, sizeof(g_icon_error_graph), "PNG");
228         setting_show->setIconSet(QIconSet(QImage(img)));
229         setting_show->setOn(true);
230
231         setting_keep = new QAction(this);
232         setting_keep->setMenuText(tr("Keep previous notes"));
233         setting_keep->setToggleAction(true);
234         setting_keep->setOn(false);
235         connect(setting_keep, SIGNAL(toggled(bool)), this, SLOT(keepPreviousNotes(bool)));
236 //      setting_keep->addTo(&m_popup_menu);
237
238         ui_notesNameMenu = new QPopupMenu(this);
239         ui_notesNameMenu->insertItem(tr("Anglo-saxon"), Music::LOCAL_ANGLO);
240         ui_notesNameMenu->connectItem(int(Music::LOCAL_ANGLO), this, SLOT(selectNotesNames(int)));
241         ui_notesNameMenu->insertItem(tr("Latin"), Music::LOCAL_LATIN);
242         ui_notesNameMenu->connectItem(int(Music::LOCAL_LATIN), this, SLOT(selectNotesNames(int)));
243         ui_notesNameMenu->setCheckable(true);
244         ui_notesNameMenu->setItemChecked(int(Music::GetNotesName()), true);
245 //      m_popup_menu.insertItem("Notes names", ui_notesNameMenu);
246
247         setting_useCents = new QAction(this);
248         setting_useCents->setMenuText(tr("Use cents"));
249         setting_useCents->setToggleAction(true);
250         setting_useCents->setOn(true);
251         connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update()));
252         setting_useCents->addTo(&m_popup_menu);
253
254         m_popup_menu.insertItem(new Title(tr("Scale range"), &m_popup_menu));
255         setting_spinScale = new QSpinBox(5, 50, 1, &m_popup_menu);
256         setting_spinScale->setValue(50);
257         QToolTip::add(setting_spinScale, tr("Scale range (in cents)"));
258         connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update()));
259         m_popup_menu.insertItem(setting_spinScale);
260 }
261
262 void GLErrorHistory::save()
263 {
264         s_settings->writeEntry("keep", setting_keep->isOn());
265 //      s_settings->writeEntry("notesNames", int(Music::GetNotesName()));
266         s_settings->writeEntry("useCents", setting_useCents->isOn());
267         s_settings->writeEntry("spinScale", setting_spinScale->value());
268 }
269 void GLErrorHistory::load()
270 {
271         setting_keep->setOn(s_settings->readBoolEntry("keep", setting_keep->isOn()));
272 //      selectNotesNames(s_settings->readNumEntry("notesNames", int(Music::GetNotesName())));
273         setting_useCents->setOn(s_settings->readBoolEntry("useCents", setting_useCents->isOn()));
274         setting_spinScale->setValue(s_settings->readNumEntry("spinScale", setting_spinScale->value()));
275 }
276 void GLErrorHistory::clearSettings()
277 {
278 //      cerr << "GLErrorHistory::clearSettings" << endl;
279         s_settings->removeEntry("keep");
280         s_settings->removeEntry("notesNames");
281         s_settings->removeEntry("useCents");
282         s_settings->removeEntry("spinScale");
283 }
284
285 void GLErrorHistory::addNote(GLErrorHistory::Note note)
286 {
287         m_notes.push_back(note);
288
289         if(!setting_keep->isOn())
290                 while(m_notes.size()>1)
291                         m_notes.pop_front();
292 }
293 void GLErrorHistory::addError(float err)
294 {
295         m_notes.back().addError(err);
296 }
297
298 void GLErrorHistory::keepPreviousNotes(bool keep)
299 {
300         if(!keep)
301                 while(m_notes.size()>1)
302                         m_notes.pop_front();
303 }
304
305 void GLErrorHistory::selectNotesNames(int id)
306 {
307         for(int i=0; i<int(ui_notesNameMenu->count()); i++)
308                 ui_notesNameMenu->setItemChecked(ui_notesNameMenu->idAt(i), id==ui_notesNameMenu->idAt(i));
309
310         Music::SetNotesName((Music::NotesName)id);
311
312         updateGL();
313 }
314
315 void GLErrorHistory::initializeGL()
316 {
317         // Set the clear color to black
318         glClearColor(1.0, 1.0, 1.0, 0.0);
319
320         // glShadeModel( GL_FLAT );
321         glShadeModel( GL_SMOOTH );
322
323         glLoadIdentity();
324 }
325
326 void GLErrorHistory::drawTicksCent(int r, int ticks_size)
327 {
328         // only work within range that is a pure multiple of r
329         float range = int(setting_spinScale->value()/r)*r;
330
331         float scale = 50.0f/setting_spinScale->value();
332         if((height()-ticks_size)*r/100.0f*scale>2)
333         {
334                 for(float i=-range; i<=range; i+=r)
335                 {
336                         int y = int(height()*i/100.0f*scale) + height()/2;
337                         glVertex2i(ticks_size,  y);
338                         glVertex2i(width(),  y);
339                 }
340         }
341 }
342 void GLErrorHistory::drawTextTickCent(int r, int dy)
343 {
344         // only work within range that is a pure multiple of r
345         int range = int(setting_spinScale->value()/r)*r;
346
347         float scale = 50.0f/setting_spinScale->value();
348         QString txt;
349         for(int i=-range; i<range; i+=r)
350         {
351                 txt = QString::number(i);
352                 if(i>=0) txt = QString("  ")+txt;
353                 if(i==0) txt = QString("  ")+txt;
354                 glRasterPos2i(2, int(height()*i/100.0f*scale) + height()/2 - dy);
355                 for(size_t i=0; i<txt.length(); i++)
356                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, txt.latin1()[i]);
357         }
358 }
359
360 void GLErrorHistory::paintGL()
361 {
362 //      cerr << "GLErrorHistory::paintGL " << m_notes.size() << endl;
363
364         glClear(GL_COLOR_BUFFER_BIT);
365
366         glLineWidth(1.0f);
367
368         // name
369         QString str = tr("Error");
370         glColor3f(0.75,0.75,0.75);
371         glRasterPos2i(2, height()-20);
372         for(size_t i = 0; i < str.length(); i++)
373                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str.latin1()[i]);
374
375         int char_size = 9;
376         int ticks_size = 2+3*char_size;
377         int dy = char_size/2;
378
379         // horiz lines
380         if(setting_useCents->isOn())
381         {
382                 glBegin(GL_LINES);
383                 float gray = 0.87;
384 //              glColor3f(gray, gray, gray);
385 //              drawTicksCent(1, ticks_size);
386                 gray = 0.875;
387                 glColor3f(gray, gray, gray);
388                 drawTicksCent(2, ticks_size);
389                 gray = 0.75;
390                 glColor3f(gray, gray, gray);
391                 drawTicksCent(10, ticks_size);
392                 glEnd();
393         }
394         else
395         {
396                 glBegin(GL_LINES);
397                         float gray = 0.5;
398                         glColor3f(gray, gray, gray);
399                         glVertex2i(ticks_size,  height()/2);
400                         glVertex2i(width(),  height()/2);
401                         gray = 0.75;
402                         glColor3f(gray, gray, gray);
403                         glVertex2i(ticks_size,  height()/4);
404                         glVertex2i(width(),  height()/4);
405                         glVertex2i(ticks_size,  3*height()/4);
406                         glVertex2i(width(),  3*height()/4);
407                         gray = 0.87;
408                         glColor3f(gray, gray, gray);
409                         glVertex2i(ticks_size,  height()/8);
410                         glVertex2i(width(),  height()/8);
411                         glVertex2i(ticks_size,  7*height()/8);
412                         glVertex2i(width(),  7*height()/8);
413                         glVertex2i(ticks_size,  3*height()/8);
414                         glVertex2i(width(),  3*height()/8);
415                         glVertex2i(ticks_size,  5*height()/8);
416                         glVertex2i(width(),  5*height()/8);
417                 glEnd();
418         }
419
420         // text marks
421         float gray = 0.5;
422         glColor3f(gray, gray, gray);
423         if(setting_useCents->isOn())
424         {
425                 int grad = 10;
426                 if(setting_spinScale->value() <= 25) grad=5;
427                 if(setting_spinScale->value() <= 10) grad=1;
428                 drawTextTickCent(grad, dy);
429         }
430         else
431         {
432                 string sfraq, sufraq;
433                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).latin1();
434                 sfraq = string("+")+sufraq;
435                 glRasterPos2i(2, 3*height()/4-dy);
436                 for(size_t i = 0; i < sfraq.size(); i++)
437                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
438                 sfraq = string("-")+sufraq;
439                 glRasterPos2i(2, height()/4-dy);
440                 for(size_t i = 0; i < sfraq.size(); i++)
441                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
442
443                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).latin1();
444                 sfraq = string("+")+sufraq;
445                 glRasterPos2i(2, 5*height()/8-dy);
446                 for(size_t i = 0; i < sfraq.size(); i++)
447                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
448                 sfraq = string("-")+sufraq;
449                 glRasterPos2i(2, 3*height()/8-dy);
450                 for(size_t i = 0; i < sfraq.size(); i++)
451                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
452         }
453
454         // errors
455         if(!m_notes.empty())
456         {
457                 int total_size = 0;
458                 for(size_t i=0; i<m_notes.size(); i++)
459                         total_size += m_notes[i].errors.size()-1;
460
461                 float step = float(width()-ticks_size)/total_size;
462
463 //              cerr << "total_size=" << total_size << " step=" << step << endl;
464
465                 int curr_total = 0;
466                 for(size_t i=0; i<m_notes.size(); i++)
467                 {
468                         float x = ticks_size+step*curr_total;
469
470                         // if it's not the first, add a separation
471                         if(i>0)
472                         {
473                                 glColor3f(0.75,0.75,0.75);
474                                 glLineWidth(1.0f);
475                                 glBegin(GL_LINES);
476                                 glVertex2f(x, 0);       glVertex2f(x, height());
477                                 glEnd();
478                         }
479
480                         // the note name
481                         string str = m_notes[i].getName();
482                         glColor3f(0.0,0.0,1.0);
483                         glRasterPos2f(x+2, 2);
484                         for(size_t c=0; c<str.length(); c++)
485                                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[c]);
486
487                         // draw the error graph
488                         glColor3f(0.0f,0.0f,0.0f);
489                         glLineWidth(2.0f);
490                         glBegin(GL_LINE_STRIP);
491
492                         if(setting_useCents->isOn())
493                         {
494                                 float scale = 50.0f/setting_spinScale->value();
495                                 glVertex2f(x, int(scale*m_notes[i].errors[0]*height()) + height()/2);
496                                 for(int j=1; j<int(m_notes[i].errors.size()); j++)
497                                         glVertex2f(x+j*step, scale*m_notes[i].errors[j]*height() + height()/2);
498                         }
499                         else
500                         {
501                                 float scale = int(50/setting_spinScale->value());
502                                 glVertex2f(x, int((scale*m_notes[i].errors[0])*height()) + height()/2);
503                                 for(int j=1; j<int(m_notes[i].errors.size()); j++)
504                                         glVertex2f(x+j*step, (scale*m_notes[i].errors[j])*height() + height()/2);
505                         }
506                         glEnd();
507
508                         curr_total += m_notes[i].errors.size()-1;
509                 }
510         }
511
512         glFlush();
513 }
514
515 void GLErrorHistory::resizeGL( int w, int h )
516 {
517         // Set the new viewport size
518         glViewport(0, 0, (GLint)w, (GLint)h);
519
520         // Choose the projection matrix to be the matrix
521         // manipulated by the following calls
522         glMatrixMode(GL_PROJECTION);
523
524         // Set the projection matrix to be the identity matrix
525         glLoadIdentity();
526
527         // Define the dimensions of the Orthographic Viewing Volume
528         glOrtho(0.0, w, 0.0, h, 0.0, 1.0);
529
530         // Choose the modelview matrix to be the matrix
531         // manipulated by further calls
532         glMatrixMode(GL_MODELVIEW);
533 }
534