Import upstream version 0.99.2
[fmit.git] / src / modules / GLFT.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 // TODO zoom with a rectangle
20
21 #include "GLFT.h"
22
23 static const unsigned char g_icon_FT[] = {
24     0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
25         0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
26         0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x06,
27         0x77, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xb5, 0x97, 0x6b, 0x6c, 0x9b,
28         0x57, 0x19, 0xc7, 0x7f, 0xe7, 0xf5, 0xe5, 0x75, 0xec, 0xdc, 0xec, 0xdc,
29         0x5a, 0x27, 0x69, 0x9c, 0x5b, 0xd3, 0xac, 0x6d, 0xda, 0xa8, 0x59, 0x27,
30         0x51, 0x79, 0x43, 0x30, 0x09, 0x56, 0x90, 0xcb, 0x84, 0x26, 0x04, 0x15,
31         0x6c, 0x1f, 0x80, 0x08, 0x89, 0x0f, 0xa8, 0x20, 0x4d, 0x9a, 0x26, 0xa1,
32         0xed, 0x0b, 0xda, 0x47, 0xd6, 0x0f, 0x93, 0x25, 0x10, 0xeb, 0xb6, 0x0a,
33         0x06, 0xa2, 0x13, 0x06, 0x15, 0x16, 0x28, 0x2c, 0x58, 0x29, 0xbb, 0xa4,
34         0x4b, 0xda, 0xa6, 0x49, 0xb3, 0xdc, 0x1a, 0xc7, 0x4d, 0x9a, 0xe6, 0x1e,
35         0xdb, 0x89, 0xef, 0x87, 0x0f, 0xf6, 0xeb, 0xbc, 0x71, 0xec, 0xad, 0x0c,
36         0xf5, 0x2f, 0x1d, 0xbd, 0xe7, 0x7d, 0x7c, 0xce, 0xf3, 0xff, 0xbf, 0xcf,
37         0xf3, 0x9c, 0xe3, 0x73, 0x04, 0x0f, 0x01, 0x6e, 0x4f, 0xaf, 0x05, 0xd8,
38         0x07, 0x54, 0x01, 0x95, 0xc0, 0x1a, 0x30, 0xe4, 0xf7, 0x79, 0x65, 0xfe,
39         0x58, 0xf1, 0x39, 0x9c, 0x2b, 0x40, 0x3d, 0xd0, 0x0c, 0xb8, 0x80, 0x03,
40         0x40, 0x43, 0xd6, 0xd6, 0x90, 0x6d, 0x55, 0x05, 0x7c, 0x8f, 0x00, 0x67,
41         0xfc, 0x3e, 0xef, 0xb4, 0xde, 0x68, 0x2c, 0x42, 0x62, 0x07, 0xda, 0xb3,
42         0x24, 0x5a, 0x73, 0x65, 0x9f, 0x4d, 0x80, 0xb9, 0x98, 0x40, 0xd5, 0x6c,
43         0xa6, 0xd4, 0x56, 0x82, 0xcd, 0x56, 0x42, 0xa9, 0xb5, 0x04, 0xd5, 0x6c,
44         0x62, 0x7c, 0x2a, 0xc0, 0xd6, 0x76, 0xf4, 0x08, 0x70, 0x0e, 0xf8, 0x71,
45         0x41, 0x01, 0x6e, 0x4f, 0xaf, 0x0d, 0xf8, 0x29, 0x70, 0x36, 0x4b, 0x2e,
46         0x00, 0x0c, 0x06, 0x85, 0xba, 0x1a, 0x07, 0x35, 0x0e, 0x3b, 0x95, 0x15,
47         0xa5, 0x54, 0x56, 0x94, 0x61, 0xaf, 0x28, 0xcb, 0x3d, 0x2b, 0x2a, 0xca,
48         0xb0, 0xd9, 0x6c, 0x58, 0xad, 0x36, 0x4c, 0xaa, 0x85, 0x94, 0x54, 0x88,
49         0x25, 0xd2, 0xa4, 0x25, 0x18, 0x15, 0x41, 0x53, 0x8d, 0xca, 0xe5, 0x2b,
50         0x03, 0xbc, 0x72, 0xfe, 0x4d, 0xb2, 0x1f, 0xc0, 0x1e, 0x01, 0x59, 0xf2,
51         0x01, 0xe0, 0x98, 0xa2, 0x28, 0x9c, 0x7a, 0xf4, 0x28, 0x5f, 0x38, 0xd9,
52         0x45, 0x57, 0x67, 0x1b, 0xfb, 0xea, 0xaa, 0x49, 0xa4, 0x04, 0x5b, 0xb1,
53         0x14, 0x91, 0x58, 0x9a, 0xad, 0x78, 0x9a, 0xad, 0x98, 0xd6, 0x52, 0xcc,
54         0x6e, 0xa5, 0x49, 0x85, 0x25, 0x92, 0x14, 0x52, 0x46, 0x90, 0x12, 0x24,
55         0x20, 0xa5, 0x44, 0x4a, 0x70, 0x94, 0x19, 0x39, 0xd8, 0x72, 0x40, 0xe3,
56         0x6b, 0x2c, 0x28, 0x00, 0xf8, 0x01, 0x70, 0xcc, 0xa0, 0x28, 0x9c, 0xff,
57         0xc5, 0xcf, 0x38, 0xd8, 0xd6, 0xcc, 0x9d, 0xfb, 0x31, 0x02, 0x9b, 0x09,
58         0xc6, 0x96, 0xc3, 0xa4, 0xd3, 0x32, 0xeb, 0x58, 0xea, 0x08, 0x32, 0x4d,
59         0x51, 0x04, 0x42, 0xb0, 0xdb, 0xae, 0xfb, 0x3d, 0x1c, 0x4d, 0xe1, 0xb0,
60         0x97, 0x6b, 0x7c, 0xad, 0x6e, 0x4f, 0xaf, 0xd0, 0x17, 0xa3, 0x26, 0xa0,
61         0x05, 0xe0, 0x50, 0x7b, 0x13, 0x1d, 0x6d, 0xcd, 0x0c, 0x4e, 0x87, 0x89,
62         0xc6, 0x33, 0x61, 0x34, 0x28, 0xa0, 0x08, 0xb1, 0xc7, 0x71, 0xee, 0x2b,
63         0x01, 0x29, 0xc5, 0x2e, 0x3b, 0x40, 0x5a, 0x02, 0x12, 0x62, 0x71, 0xc9,
64         0xfe, 0xda, 0x72, 0x2c, 0xaa, 0x99, 0x68, 0x2c, 0x6e, 0x05, 0x9c, 0xc0,
65         0x5d, 0x4d, 0x80, 0xa2, 0x17, 0xb2, 0xaf, 0xae, 0x9a, 0xf9, 0xb5, 0x38,
66         0xc9, 0x54, 0x26, 0x7f, 0xb9, 0x66, 0x10, 0x18, 0x0d, 0xe8, 0xfa, 0x3a,
67         0x7b, 0xa1, 0x31, 0xca, 0xce, 0xfc, 0x58, 0x32, 0x8d, 0x10, 0x82, 0x06,
68         0x67, 0xad, 0xc6, 0xd9, 0xa1, 0x4f, 0x81, 0xa2, 0x7f, 0xb1, 0x5a, 0x54,
69         0x92, 0x29, 0x99, 0x71, 0x64, 0xd0, 0x93, 0xb1, 0x97, 0xb8, 0x98, 0xa0,
70         0xbc, 0xb9, 0x89, 0x64, 0x26, 0x26, 0xae, 0xc6, 0xfd, 0x1a, 0x4d, 0x67,
71         0xa1, 0x1a, 0x88, 0x03, 0x58, 0x54, 0x73, 0x6e, 0x22, 0x32, 0x1b, 0xc6,
72         0x3d, 0x61, 0x2f, 0x9e, 0xef, 0x42, 0x29, 0x48, 0x66, 0x9d, 0xb4, 0x34,
73         0x39, 0x35, 0xce, 0x43, 0x85, 0x04, 0x6c, 0x02, 0xa4, 0xd2, 0x69, 0x4c,
74         0xc6, 0xcc, 0xd7, 0xec, 0x12, 0x50, 0x28, 0xf7, 0x52, 0x14, 0x16, 0x24,
75         0xf5, 0x02, 0x24, 0x26, 0x43, 0x26, 0xc8, 0xcd, 0x07, 0xea, 0x3f, 0x5b,
76         0x40, 0x3c, 0x9e, 0xc0, 0x6c, 0x54, 0x74, 0x11, 0x90, 0x40, 0xb1, 0x02,
77         0xcc, 0xef, 0x4b, 0x64, 0x76, 0x2c, 0x40, 0x79, 0x89, 0x81, 0xfa, 0x2a,
78         0x33, 0x8e, 0xd2, 0x0c, 0x45, 0xf3, 0x83, 0x44, 0x20, 0x9e, 0x48, 0x62,
79         0xca, 0xa6, 0xe0, 0xb7, 0xaf, 0xbf, 0xc3, 0x5c, 0x60, 0x01, 0x00, 0x83,
80         0xc1, 0x40, 0xeb, 0x41, 0x17, 0x5f, 0x7e, 0xea, 0x71, 0x54, 0x55, 0x45,
81         0x4a, 0xc1, 0xf5, 0xa1, 0x51, 0xae, 0xfc, 0xb5, 0x3f, 0x17, 0x72, 0x8d,
82         0xd8, 0xfd, 0x78, 0x37, 0xd1, 0x8d, 0x55, 0x82, 0x81, 0x79, 0x3d, 0x0f,
83         0x52, 0x42, 0x70, 0x62, 0x91, 0x86, 0xf6, 0xba, 0x7a, 0xb7, 0xa7, 0xb7,
84         0xcc, 0xef, 0xf3, 0x86, 0xf4, 0x02, 0x96, 0x01, 0x22, 0x91, 0x6d, 0x4c,
85         0x06, 0x81, 0x90, 0x69, 0x5e, 0xfb, 0xe5, 0x1b, 0x84, 0x42, 0x61, 0xaa,
86         0xab, 0x1d, 0x6c, 0x6f, 0x47, 0x59, 0x5d, 0x59, 0xe7, 0xe4, 0xef, 0x2f,
87         0xf3, 0xda, 0x85, 0x57, 0x30, 0xab, 0x2a, 0x57, 0x2e, 0xbf, 0xc7, 0x9b,
88         0xbf, 0xfe, 0x03, 0x35, 0xb5, 0x55, 0x28, 0x06, 0x05, 0x45, 0x08, 0x0c,
89         0x0a, 0x7c, 0xe5, 0x89, 0x47, 0xf8, 0xcd, 0xc5, 0xcb, 0xcc, 0xcf, 0x2f,
90         0xb1, 0xb1, 0x11, 0x61, 0x73, 0x33, 0x42, 0x6d, 0xad, 0x1d, 0x55, 0x35,
91         0x21, 0x0d, 0x02, 0x32, 0x3b, 0xec, 0x21, 0xe0, 0x23, 0xd8, 0x59, 0x05,
92         0xf7, 0x01, 0x36, 0x42, 0x11, 0x8c, 0x06, 0xc1, 0xf2, 0xe2, 0x32, 0xcb,
93         0x4b, 0xab, 0x9c, 0xf6, 0x7c, 0x89, 0xbf, 0x0f, 0x5c, 0xe4, 0x5f, 0x1f,
94         0xbc, 0xcd, 0xd9, 0xe7, 0xbe, 0xc1, 0x87, 0xff, 0x19, 0xa6, 0xff, 0x1f,
95         0x57, 0x31, 0x1a, 0x04, 0xa3, 0x37, 0xc7, 0x29, 0xaf, 0x28, 0xe5, 0x9f,
96         0x03, 0x17, 0x98, 0x9c, 0xbc, 0xc4, 0xcc, 0xf4, 0x25, 0x26, 0x27, 0x2f,
97         0x71, 0xf6, 0xec, 0x57, 0xe9, 0xef, 0xf7, 0x32, 0x31, 0x71, 0x89, 0xa7,
98         0x9f, 0xfe, 0x22, 0x40, 0xee, 0xfd, 0x47, 0x3f, 0xf9, 0xa6, 0x16, 0x90,
99         0xc3, 0x5a, 0x47, 0x13, 0xb0, 0x04, 0xb0, 0x19, 0x8e, 0x60, 0x34, 0xc0,
100         0xe8, 0xc8, 0x38, 0x00, 0xdd, 0xdd, 0x9d, 0x58, 0x4b, 0xcc, 0x94, 0x97,
101         0x59, 0xf9, 0xd6, 0x77, 0xbe, 0x06, 0xc0, 0x8d, 0xa1, 0x51, 0xe2, 0xb1,
102         0x28, 0x33, 0x53, 0x01, 0x5a, 0x5b, 0x1b, 0x38, 0x50, 0x6b, 0x25, 0x9d,
103         0x4c, 0x10, 0x8b, 0xc5, 0x49, 0x26, 0x53, 0x28, 0x8a, 0x82, 0xaa, 0x9a,
104         0x51, 0x55, 0x33, 0xc3, 0xc3, 0x9f, 0x50, 0x5b, 0x6b, 0xa7, 0xb5, 0xb5,
105         0x01, 0x55, 0x35, 0xeb, 0xb7, 0xe4, 0x23, 0xf9, 0x35, 0x90, 0x89, 0xc0,
106         0x46, 0x18, 0x45, 0x08, 0x46, 0xae, 0x67, 0x04, 0x1c, 0xeb, 0xee, 0xc0,
107         0xa8, 0x08, 0x24, 0x12, 0xd5, 0x9c, 0x19, 0x9a, 0x4e, 0x25, 0x89, 0xad,
108         0x2f, 0xb3, 0xb6, 0xba, 0x4e, 0x68, 0x33, 0x84, 0xcb, 0x75, 0x26, 0x97,
109         0xe7, 0xd3, 0xa7, 0x4f, 0xf1, 0xd6, 0x5b, 0x2f, 0xa3, 0xf9, 0x9a, 0x98,
110         0x08, 0x70, 0xea, 0xd4, 0x31, 0x4c, 0xa6, 0xcc, 0xdc, 0x96, 0xa6, 0xdc,
111         0x4a, 0xd8, 0x2d, 0xc0, 0xef, 0xf3, 0xae, 0xb9, 0x3d, 0xbd, 0x91, 0x8d,
112         0x50, 0xd8, 0x16, 0x8b, 0x27, 0xb8, 0x39, 0x7c, 0x1b, 0x55, 0x35, 0x73,
113         0xf4, 0x48, 0x2b, 0x46, 0xa3, 0x40, 0x4a, 0xc1, 0xed, 0xd1, 0x29, 0x00,
114         0xba, 0x0e, 0x37, 0x31, 0x36, 0xf2, 0x09, 0x52, 0xc2, 0x33, 0xcf, 0x3c,
115         0xc9, 0xe1, 0xc3, 0x2d, 0x39, 0x01, 0x8f, 0x3d, 0x96, 0x8b, 0x2c, 0xb7,
116         0x6e, 0x4d, 0xb3, 0xbd, 0x1d, 0xa3, 0xa7, 0x67, 0x67, 0xdf, 0x69, 0x71,
117         0x15, 0x11, 0x90, 0x45, 0x10, 0xe8, 0xb8, 0xb7, 0xb8, 0xcc, 0x8d, 0xeb,
118         0xe3, 0xb4, 0x1f, 0x6c, 0xa2, 0xb2, 0xc2, 0x46, 0x5a, 0xc2, 0x76, 0x34,
119         0xc6, 0xeb, 0xbf, 0xfa, 0x23, 0x16, 0x8b, 0xca, 0x19, 0x8f, 0x9b, 0x57,
120         0x5f, 0x7d, 0x1b, 0x21, 0xe0, 0xf9, 0xe7, 0xbf, 0x47, 0x57, 0x57, 0x3b,
121         0x85, 0x70, 0xed, 0xda, 0x18, 0x52, 0x42, 0x4f, 0xcf, 0x23, 0x39, 0x5b,
122         0x65, 0x79, 0x29, 0x55, 0xf6, 0x0a, 0x56, 0xd6, 0x36, 0xea, 0xdd, 0x9e,
123         0x5e, 0xbb, 0xdf, 0xe7, 0x5d, 0xd3, 0x6f, 0xc5, 0x73, 0x00, 0xc3, 0x37,
124         0x27, 0x58, 0x5d, 0xdd, 0xc4, 0xe9, 0xac, 0x61, 0xf8, 0xe3, 0x51, 0xde,
125         0xbb, 0xf2, 0x3e, 0xdf, 0x7f, 0xf6, 0x45, 0x86, 0x3e, 0x1e, 0xe3, 0xdc,
126         0xb9, 0x6f, 0xd3, 0xd6, 0xd6, 0xc8, 0xe0, 0xe0, 0x18, 0x0e, 0x47, 0x05,
127         0x2d, 0x2d, 0xf5, 0xf9, 0xbc, 0x39, 0x0c, 0x0e, 0x8e, 0x21, 0x04, 0x9c,
128         0x38, 0xb1, 0x6b, 0xd9, 0xe3, 0x3a, 0x90, 0xdb, 0x92, 0x8f, 0xe4, 0x47,
129         0x60, 0x0e, 0xe0, 0x83, 0xf7, 0x47, 0x00, 0xe8, 0x7b, 0xf7, 0x2a, 0x7d,
130         0xef, 0x5e, 0x45, 0x08, 0x81, 0xdd, 0x5e, 0xc6, 0x4b, 0x2f, 0xfd, 0x90,
131         0x17, 0x5e, 0x78, 0x8e, 0x50, 0x28, 0xc2, 0xf8, 0xf8, 0x2c, 0x9d, 0x9d,
132         0x2e, 0x4a, 0x4b, 0xad, 0x9f, 0x2a, 0x60, 0xff, 0xfe, 0x6a, 0x9c, 0xce,
133         0x9a, 0x5d, 0xf6, 0x46, 0x67, 0x2d, 0xd7, 0xae, 0xdf, 0x06, 0x38, 0x0a,
134         0xf8, 0xf3, 0x53, 0x80, 0xb3, 0xb1, 0x86, 0x0f, 0x3f, 0xba, 0x90, 0x3b,
135         0x03, 0x94, 0x94, 0xa8, 0xb4, 0xb5, 0x3a, 0xb1, 0xd9, 0x4a, 0x00, 0xb0,
136         0x58, 0xa0, 0xaf, 0xef, 0x3c, 0x0e, 0x47, 0x39, 0xc5, 0x20, 0xa5, 0xe4,
137         0xe2, 0xc5, 0x97, 0x51, 0x55, 0x73, 0xae, 0x00, 0x35, 0x34, 0x38, 0xeb,
138         0xb4, 0xee, 0xf1, 0x82, 0x11, 0x88, 0x25, 0x13, 0x3c, 0xda, 0xd3, 0x99,
139         0xdb, 0x66, 0x95, 0xbc, 0xa3, 0xa5, 0xc9, 0x64, 0xe4, 0xc4, 0x89, 0x4e,
140         0x3e, 0x0d, 0x42, 0x08, 0x8e, 0x1f, 0xef, 0x28, 0xf8, 0x5b, 0xe3, 0xce,
141         0xdf, 0x72, 0x77, 0x41, 0x01, 0x8b, 0x4b, 0xab, 0x59, 0x27, 0x9f, 0xe3,
142         0xc8, 0xfc, 0x00, 0xa8, 0xa9, 0xb2, 0x6b, 0xdd, 0x2e, 0xb7, 0xa7, 0xd7,
143         0xaa, 0x2f, 0xc2, 0x00, 0xc0, 0x6c, 0xf0, 0xde, 0x43, 0xa0, 0xdd, 0x81,
144         0xaa, 0x9a, 0xb4, 0xae, 0x19, 0x68, 0xd6, 0x0b, 0x98, 0x06, 0xd2, 0xf7,
145         0xee, 0xaf, 0x10, 0x8b, 0xc5, 0x1f, 0x0a, 0xf9, 0x76, 0x34, 0xc6, 0x5f,
146         0xfa, 0x06, 0xf4, 0xa6, 0xf5, 0x5c, 0x0a, 0xfc, 0x3e, 0x6f, 0xd4, 0xed,
147         0xe9, 0x0d, 0x48, 0x29, 0x5d, 0x81, 0xbb, 0x8b, 0xb4, 0xb7, 0xec, 0x39,
148         0xc0, 0xfe, 0x4f, 0x58, 0x5a, 0x59, 0x67, 0x72, 0x26, 0xc8, 0xe4, 0xcc,
149         0x1c, 0x93, 0x77, 0x82, 0x4c, 0xce, 0x04, 0xb9, 0xbb, 0x70, 0x9f, 0xb4,
150         0x76, 0xc8, 0x80, 0x3f, 0xfb, 0x7d, 0xde, 0xbb, 0xf9, 0x17, 0x93, 0x31,
151         0xc0, 0x35, 0x3b, 0xb7, 0xf0, 0xc0, 0x02, 0x92, 0xc9, 0x14, 0xb3, 0xc1,
152         0x7b, 0x19, 0xb2, 0x3b, 0x73, 0x59, 0xd2, 0x20, 0x1b, 0x9b, 0xe1, 0x62,
153         0x53, 0x66, 0x81, 0x77, 0x80, 0x9f, 0xc3, 0xde, 0x9b, 0xd1, 0x35, 0xe0,
154         0xa9, 0xf1, 0xa9, 0x00, 0x4f, 0x3e, 0x71, 0x72, 0xcf, 0xcc, 0x50, 0x78,
155         0x6b, 0x0f, 0xd1, 0x9d, 0xb9, 0x05, 0x12, 0x89, 0x64, 0x21, 0xa2, 0x34,
156         0x30, 0x05, 0xdc, 0x04, 0x86, 0x81, 0x21, 0x60, 0xd0, 0xef, 0xf3, 0xee,
157         0x2a, 0xb2, 0x7c, 0x01, 0xfd, 0xc0, 0x8b, 0x7f, 0xfa, 0xdb, 0xbf, 0xb1,
158         0x96, 0x58, 0x28, 0x2f, 0xb3, 0xb1, 0xb2, 0xb6, 0xc1, 0x4c, 0x60, 0x9e,
159         0xc9, 0x99, 0x60, 0x6e, 0x85, 0x14, 0xc0, 0x0a, 0x99, 0xbb, 0xdf, 0x8d,
160         0x2c, 0xe1, 0x0d, 0x60, 0xc4, 0xef, 0xf3, 0x46, 0x8a, 0x4d, 0xd0, 0xb0,
161         0x67, 0xa5, 0xb9, 0x3d, 0xbd, 0x6f, 0x00, 0xdf, 0x2d, 0x32, 0x3e, 0x04,
162         0x8c, 0x66, 0xc9, 0x6e, 0x65, 0x9f, 0x23, 0x7e, 0x9f, 0x77, 0xe1, 0xb3,
163         0x88, 0x8a, 0xa1, 0xd0, 0xe5, 0xf4, 0x59, 0xe0, 0x77, 0xc0, 0xd7, 0x81,
164         0x52, 0x1d, 0xe1, 0x08, 0x30, 0x5b, 0xe8, 0x8a, 0xfd, 0xff, 0xe0, 0xbf,
165         0x87, 0xf6, 0xdb, 0x8f, 0xf0, 0x17, 0xa5, 0xe8, 0x00, 0x00, 0x00, 0x00,
166         0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
167 };
168
169 #include <iostream>
170 using namespace std;
171 #include <qtooltip.h>
172 #include <qimage.h>
173 #include <qevent.h>
174 #include <qboxlayout.h>
175 #include <qwidgetaction.h>
176 #include <GL/glut.h>
177 #include <Music/Music.h>
178 #include <Music/SPWindow.h>
179 using namespace Music;
180 #include <CppAddons/CAMath.h>
181 using namespace Math;
182
183 GLFT::GLFT(QWidget* parent)
184 : QGLWidget(parent)
185 , View(tr("Fourier Transform"), this)
186 , m_components_max(1.0)
187 {
188         m_start_move_mouse = true;
189
190         m_os = 2;                                       // over sampling factor
191
192         // settings
193         QPixmap img;
194         img.loadFromData(g_icon_FT, sizeof(g_icon_FT), "PNG");
195         setting_show->setIcon(QIcon(img));
196         setting_show->setChecked(false);
197         hide();
198
199         setting_db_scale = new QAction(tr("dB scale"), this);
200         setting_db_scale->setCheckable(true);
201         connect(setting_db_scale, SIGNAL(toggled(bool)), this, SLOT(dBScaleChanged(bool)));
202         setting_db_scale->setChecked(true);
203         m_popup_menu.addAction(setting_db_scale);
204         resetaxis();
205
206         QHBoxLayout* sizeActionLayout = new QHBoxLayout(&m_popup_menu);
207
208         QLabel* sizeActionTitle = new QLabel(tr("Size"), &m_popup_menu);
209         sizeActionLayout->addWidget(sizeActionTitle);
210
211         setting_winlen = new QSpinBox(&m_popup_menu);
212         setting_winlen->setObjectName("setting_winlen");
213         setting_winlen->setMinimum(1);
214         setting_winlen->setMaximum(1000);
215         setting_winlen->setSingleStep(1);
216         setting_winlen->setValue(20);
217         setting_winlen->setSuffix(" ms");
218         setting_winlen->setToolTip(tr("window length"));
219         connect(setting_winlen, SIGNAL(valueChanged(int)), this, SLOT(spinWinLengthChanged(int)));
220         sizeActionLayout->addWidget(setting_winlen);
221
222         QWidget* sizeActionWidget = new QWidget(&m_popup_menu);
223         sizeActionWidget->setLayout(sizeActionLayout);
224
225         QWidgetAction* sizeAction = new QWidgetAction(&m_popup_menu);
226         sizeAction->setDefaultWidget(sizeActionWidget);
227         m_popup_menu.addAction(sizeAction);
228
229         QWidgetAction* helpCaption01 = new QWidgetAction(&m_popup_menu);
230         helpCaption01->setDefaultWidget(new Title(tr("- Press left mouse button to move the view"), &m_popup_menu));
231         m_popup_menu.addAction(helpCaption01);
232         QWidgetAction* helpCaption02 = new QWidgetAction(&m_popup_menu);
233         helpCaption02->setDefaultWidget(new Title(tr("- Press SHIFT key and left mouse button to zoom in and out"), &m_popup_menu));
234         m_popup_menu.addAction(helpCaption02);
235         QWidgetAction* helpCaption03 = new QWidgetAction(&m_popup_menu);
236         helpCaption03->setDefaultWidget(new Title(tr("- Double-click to reset the view"), &m_popup_menu));
237         m_popup_menu.addAction(helpCaption03);
238
239         s_settings->add(setting_winlen);
240
241         spinWinLengthChanged(setting_winlen->value());
242 }
243
244 void GLFT::refreshGraph()
245 {
246         while(int(buff.size())>m_plan.size())
247                 buff.pop_back();
248 }
249
250 void GLFT::setSamplingRate(int sr)
251 {
252         m_maxf=sr/2;
253 }
254
255 void GLFT::resetaxis()
256 {
257         m_minf=0;
258         m_maxf=Music::GetSamplingRate()/2; // sr is surely -1 because not yet defined
259
260         if(setting_db_scale->isChecked())
261         {
262                 m_minA = -50; // [dB]
263                 m_maxA = 100; // [dB]
264         }
265         else
266         {
267                 m_maxA = 1; // [amplitude]
268         }
269 }
270 void GLFT::dBScaleChanged(bool db)
271 {
272         resetaxis();
273         update();
274 }
275
276 void GLFT::spinWinLengthChanged(int num)
277 {
278         if(Music::GetSamplingRate()>0)
279         {
280                 // Create window
281                 int winlen = int(num/1000.0*Music::GetSamplingRate());
282                 win = hann(winlen);
283                 double win_sum = 0.0;
284                 // normalize the window in energy
285                 for(size_t i=0; i<win.size(); i++)
286                         win_sum += win[i];
287                 for(size_t i=0; i<win.size(); i++)
288                         win[i] *= 2*win.size()/win_sum; // 2* because the positive freq are half of the energy
289
290                 // Create FFTW3 plan
291                 int fftlen=1;
292                 while(fftlen<winlen) fftlen *= 2;
293                 fftlen *= pow(2,m_os);
294                 assert(fftlen<int(Music::GetSamplingRate()));
295                 m_plan.resize(fftlen);
296                 m_components.resize(m_plan.size()/2);
297
298         cerr << "GLFT: INFO: window length=" << win.size() << "ms FFT length=" << m_plan.size() << endl;
299         }
300 }
301
302 void GLFT::initializeGL()
303 {
304         // Set the clear color to black
305         glClearColor(1.0, 1.0, 1.0, 0.0);
306
307         glShadeModel( GL_FLAT );
308 //      glShadeModel( GL_SMOOTH );
309
310         glLoadIdentity();
311 }
312
313 void GLFT::mousePressEvent(QMouseEvent* e)
314 {
315         m_start_move_mouse = true;
316         m_press_x = e->x();
317         m_press_y = e->y();
318         m_press_minf = m_minf;
319         m_press_maxf = m_maxf;
320
321         double f = (m_maxf-m_minf)*double(m_press_x)/width()+m_minf;
322         m_text = tr("Frequency %1 [Hz]").arg(f);
323         updateGL();
324 }
325 void GLFT::mouseDoubleClickEvent(QMouseEvent* e)
326 {
327         m_start_move_mouse = true;
328         m_minf=0;
329         m_maxf=Music::GetSamplingRate()/2; // sr is surely -1 because not yet defined
330         resetaxis();
331         updateGL();
332 }
333 void GLFT::mouseMoveEvent(QMouseEvent* e)
334 {
335         static int old_x;
336         static int old_y;
337         if(m_start_move_mouse)
338         {
339                 old_x = e->x();
340                 old_y = e->y();
341                 m_start_move_mouse = false;
342         }
343         int dx = e->x() - old_x;
344         int dy = e->y() - old_y;
345
346         if(Qt::LeftButton & e->buttons())
347         {
348                 if(Qt::ShiftModifier & e->modifiers())
349                 {
350                         double f = (m_maxf-m_minf)*double(m_press_x)/width()+m_minf;
351                         double zx = double(m_press_x-e->x())/width();
352                         zx = pow(8, zx);
353                         m_minf = f - zx*(f-m_press_minf);
354                         m_maxf = f + zx*(m_press_maxf-f);
355                 }
356                 else
357                 {
358                         m_minf -= (m_maxf-m_minf)*dx/width();
359                         m_maxf -= (m_maxf-m_minf)*dx/width();
360
361                         if(setting_db_scale->isChecked())
362                         {
363                                 m_minA += (m_maxA-m_minA)*dy/height();
364                                 m_maxA += (m_maxA-m_minA)*dy/height();
365                         }
366                         else
367                                 m_maxA -= m_maxA*double(dy)/height();
368                 }
369
370                 updateGL();
371         }
372
373         old_x = e->x();
374         old_y = e->y();
375 }
376
377 void GLFT::paintGL()
378 {
379         glClear(GL_COLOR_BUFFER_BIT);
380
381         if(win.size()>0 && int(buff.size())>=m_plan.size())
382         {
383                 // Use last samples
384                 while(int(buff.size())>m_plan.size())
385                         buff.pop_back();
386
387                 int sr = Music::GetSamplingRate();
388
389 //              cout << m_plan.size() << endl;
390
391                 // name
392                 string str = tr("Fourier Transform").toStdString();
393                 glColor3f(0.75,0.75,0.75);
394                 glRasterPos2i(2, height()-20);
395                 for(size_t i = 0; i < str.size(); i++)
396                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (unsigned char)str[i]);
397
398                 for(int i=0; i<int(win.size()); i++)
399                         m_plan.in[i] = buff[i]*win[i];
400                 for(int i=win.size(); i<int(m_plan.in.size()); i++)
401                         m_plan.in[i] = 0.0;
402
403                 m_plan.execute();
404
405                 for(int i=0; i<int(m_components.size()); i++)
406                         m_components[i] = mod(m_plan.out[i]);
407
408 //              cerr << "m_minA=" << m_minA << " m_maxA=" << m_maxA << endl;
409                 double y;
410                 glBegin(GL_LINE_STRIP);
411                 glColor3f(0.4, 0.4, 0.5);
412                 for(size_t x=0; x<width(); x++)
413                 {
414                         int index = int(0.5+(m_minf+(m_maxf-m_minf)*double(x)/width())*m_components.size()/(sr/2.0));
415                         if(index<0) index=0;
416                         else if(index>=m_components.size()) index=m_components.size();
417                         y = m_components[index];
418                         if(setting_db_scale->isChecked())
419                                 y = height()*(lp(y)-m_minA)/(m_maxA-m_minA);
420                         else
421                                 y = height()*y*m_maxA;
422
423                         glVertex2i(x, int(y));
424                 }
425
426                 glEnd();
427
428                 // scale
429                 /*glColor3f(0,0,0);
430                 for(size_t i=0; i<m_components.size(); i++)
431                 {
432                         glRasterPos2i(int((i+0.5)*step)-3, 2);
433
434 //                      string str = StringAddons::toString(i+1);
435                         string str = QString::number(i+1).toStdString();
436
437                         for(size_t i = 0; i < str.length(); i++)
438                                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, (unsigned char)str[i]);
439                 }*/
440         }
441
442         // Text
443         if(m_text.length()>0)
444         {
445                 glColor3f(0,0,0);
446                 glRasterPos2i(width()/2, 12);
447
448                 string str = m_text.toStdString();
449
450                 for(size_t i = 0; i < str.length(); i++)
451                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, (unsigned char)str[i]);
452         }
453
454         glFlush();
455 }
456
457 void GLFT::resizeGL( int w, int h )
458 {
459         // Set the new viewport size
460         glViewport(0, 0, (GLint)w, (GLint)h);
461
462         // Choose the projection matrix to be the matrix
463         // manipulated by the following calls
464         glMatrixMode(GL_PROJECTION);
465
466         // Set the projection matrix to be the identity matrix
467         glLoadIdentity();
468
469         // Define the dimensions of the Orthographic Viewing Volume
470         glOrtho(0.0, w, 0.0, h, 0.0, 1.0);
471
472         // Choose the modelview matrix to be the matrix
473         // manipulated by further calls
474         glMatrixMode(GL_MODELVIEW);
475 }