File Coverage

blib/lib/GD/Tab/Ukulele.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package GD::Tab::Ukulele;
2 2     2   92671 use strict;
  2         6  
  2         79  
3 2     2   12 use warnings;
  2         4  
  2         225  
4 2     2   13 use Carp;
  2         8  
  2         205  
5 2     2   2125 use GD;
  0            
  0            
6             use base qw(Class::Accessor::Fast);
7             use List::Util qw(max);
8              
9             __PACKAGE__->mk_accessors(qw(bgcolor color interlaced));
10              
11             our $VERSION = '0.01';
12             my @lines = (
13             [1,15,41,15],
14             [1,21,41,21],
15             [1,27,41,27],
16             [1,33,41,33],
17             [0,15,0,33],
18             [2,15,2,33],
19             [10,15,10,33],
20             [18,15,18,33],
21             [26,15,26,33],
22             [34,15,34,33],
23             );
24              
25             my %chord_lists = (
26             'C' => [3, 0, 0, 0],
27             'Cm' => [3, 3, 3, 0],
28             'C7' => [1, 0, 0, 0],
29             'CM7' => [2, 0, 0, 0],
30             'Cm7' => [3, 3, 3, 3],
31             'Cdim' => [3, 2, 3, 2],
32             'Cm7(b5)' => [3, 2, 3, 3],
33             'Caug' => [3, 0, 0, 1],
34             'Csus4' => [3, 3, 5, 5],
35             'C6' => [0, 0, 0, 0],
36             'C7(9)' => [1, 0, 2, 0],
37             'CM7(9)' => [2, 0, 2, 0],
38             'CmM7' => [3, 3, 3, 4],
39             'Cadd9' => [3, 0, 2, 0],
40             'C#' => [4, 1, 1, 1],
41             'C#m' => [4, 4, 4, 1],
42             'C#7' => [2, 1, 1, 1],
43             'C#M7' => [3, 1, 1, 1],
44             'C#m7' => [2, 0, 1, 1],
45             'C#dim' => [1, 0, 1, 0],
46             'C#m7(b5)' => [3, 2, 3, 3],
47             'C#aug' => [0, 1, 1, 2],
48             'C#sus4' => [2, 2, 1, 1],
49             'C#6' => [1, 1, 1, 1],
50             'C#7(9)' => [2, 1, 3, 1],
51             'C#M7(9)' => [3, 1, 3, 1],
52             'C#mM7' => [3, 0, 1, 1],
53             'C#add9' => [4, 1, 3, 1],
54             'Db' => [4, 1, 1, 1],
55             'Dbm' => [4, 4, 4, 1],
56             'Db7' => [2, 1, 1, 1],
57             'DbM7' => [3, 1, 1, 1],
58             'Dbm7' => [2, 0, 1, 1],
59             'Dbdim' => [1, 0, 1, 0],
60             'Dbm7(b5)' => [3, 2, 3, 3],
61             'Dbaug' => [0, 1, 1, 2],
62             'Dbsus4' => [2, 2, 1, 1],
63             'Db6' => [1, 1, 1, 1],
64             'Db7(9)' => [2, 1, 3, 1],
65             'DbM7(9)' => [3, 1, 3, 1],
66             'DbmM7' => [3, 0, 1, 1],
67             'Dbadd9' => [4, 1, 3, 1],
68             'D' => [0, 2, 2, 2],
69             'Dm' => [0, 1, 2, 2],
70             'D7' => [3, 2, 2, 2],
71             'DM7' => [4, 2, 2, 2],
72             'Dm7' => [3, 1, 2, 2],
73             'Ddim' => [2, 1, 2, 1],
74             'Dm7(b5)' => [3, 1, 2, 1],
75             'Daug' => [1, 2, 2, 3],
76             'Dsus4' => [0, 3, 2, 2],
77             'D6' => [2, 2, 2, 2],
78             'D7(9)' => [3, 2, 4, 2],
79             'DM7(9)' => [4, 2, 4, 2],
80             'DmM7' => [4, 1, 2, 2],
81             'Dadd9' => [5, 2, 4, 2],
82             'D#' => [1, 3, 3, 0],
83             'D#m' => [1, 2, 3, 3],
84             'D#7' => [4, 3, 3, 3],
85             'D#M7' => [5, 3, 3, 3],
86             'D#m7' => [4, 2, 3, 3],
87             'D#dim' => [3, 2, 3, 2],
88             'D#m7(b5)' => [4, 2, 3, 2],
89             'D#aug' => [2, 3, 3, 0],
90             'D#sus4' => [1, 4, 3, 3],
91             'D#6' => [4, 4, 4, 4],
92             'D#7(9)' => [1, 1, 1, 0],
93             'D#M7(9)' => [1, 1, 2, 0],
94             'D#mM7' => [5, 2, 3, 3],
95             'D#add9' => [1, 1, 3, 0],
96             'Eb' => [1, 3, 3, 0],
97             'Ebm' => [1, 2, 3, 3],
98             'Eb7' => [4, 3, 3, 3],
99             'EbM7' => [5, 3, 3, 3],
100             'Ebm7' => [4, 2, 3, 3],
101             'Ebdim' => [3, 2, 3, 2],
102             'Ebm7(b5)' => [4, 2, 3, 2],
103             'Ebaug' => [2, 3, 3, 0],
104             'Ebsus4' => [1, 4, 3, 3],
105             'Eb6' => [4, 4, 4, 4],
106             'Eb7(9)' => [1, 1, 1, 0],
107             'EbM7(9)' => [1, 1, 2, 0],
108             'EbmM7' => [5, 2, 3, 3],
109             'Ebadd9' => [1, 1, 3, 0],
110             'E' => [2, 4, 4, 4],
111             'Em' => [2, 3, 4, 0],
112             'E7' => [2, 0, 2, 1],
113             'EM7' => [2, 0, 3, 1],
114             'Em7' => [2, 0, 2, 0],
115             'Edim' => [1, 0, 1, 0],
116             'Em7(b5)' => [1, 0, 2, 0],
117             'Eaug' => [3, 0, 0, 1],
118             'Esus4' => [2, 5, 4, 4],
119             'E6' => [2, 0, 1, 1],
120             'E7(9)' => [2, 2, 2, 1],
121             'EM7(9)' => [2, 2, 3, 1],
122             'EmM7' => [2, 0, 3, 0],
123             'Eadd9' => [2, 2, 4, 1],
124             'F' => [0, 1, 0, 2],
125             'Fm' => [3, 1, 0, 1],
126             'F7' => [3, 1, 3, 2],
127             'FM7' => [0, 0, 5, 5],
128             'Fm7' => [3, 1, 3, 1],
129             'Fdim' => [2, 1, 2, 1],
130             'Fm7(b5)' => [2, 1, 3, 1],
131             'Faug' => [0, 1, 1, 2],
132             'Fsus4' => [1, 1, 0, 3],
133             'F6' => [3, 1, 2, 2],
134             'F7(9)' => [3, 3, 3, 2],
135             'FM7(9)' => [0, 0, 0, 0],
136             'FmM7' => [3, 1, 4, 1],
137             'Fadd9' => [0, 1, 0, 0],
138             'F#' => [1, 2, 1, 3],
139             'F#m' => [0, 2, 1, 2],
140             'F#7' => [4, 2, 4, 3],
141             'F#M7' => [4, 2, 5, 3],
142             'F#m7' => [4, 2, 4, 2],
143             'F#dim' => [3, 2, 3, 2],
144             'F#m7(b5)' => [3, 2, 4, 2],
145             'F#aug' => [1, 2, 2, 3],
146             'F#sus4' => [4, 2, 4, 4],
147             'F#6' => [4, 2, 3, 3],
148             'F#7(9)' => [4, 4, 4, 3],
149             'F#M7(9)' => [1, 1, 1, 1],
150             'F#mM7' => [4, 2, 5, 2],
151             'F#add9' => [1, 2, 1, 1],
152             'Gb' => [1, 2, 1, 3],
153             'Gbm' => [0, 2, 1, 2],
154             'Gb7' => [4, 2, 4, 3],
155             'GbM7' => [4, 2, 5, 3],
156             'Gbm7' => [4, 2, 4, 2],
157             'Gbdim' => [3, 2, 3, 2],
158             'Gbm7(b5)' => [3, 2, 4, 2],
159             'Gbaug' => [1, 2, 2, 3],
160             'Gbsus4' => [4, 2, 4, 4],
161             'Gb6' => [4, 2, 3, 3],
162             'Gb7(9)' => [4, 4, 4, 3],
163             'GbM7(9)' => [1, 1, 1, 1],
164             'GbmM7' => [4, 2, 5, 2],
165             'Gbadd9' => [1, 2, 1, 1],
166             'G' => [2, 3, 2, 0],
167             'Gm' => [1, 3, 2, 0],
168             'G7' => [2, 1, 2, 0],
169             'GM7' => [2, 2, 2, 0],
170             'Gm7' => [1, 1, 2, 0],
171             'Gdim' => [1, 0, 1, 0],
172             'Gm7(b5)' => [1, 1, 1, 0],
173             'Gaug' => [2, 3, 3, 0],
174             'Gsus4' => [3, 3, 2, 0],
175             'G6' => [2, 0, 2, 0],
176             'G7(9)' => [2, 1, 2, 2],
177             'GM7(9)' => [2, 2, 2, 2],
178             'GmM7' => [5, 3, 6, 3],
179             'Gadd9' => [2, 3, 2, 2],
180             'G#' => [3, 4, 3, 5],
181             'G#m' => [2, 4, 3, 1],
182             'G#7' => [3, 2, 3, 1],
183             'G#M7' => [3, 3, 3, 1],
184             'G#m7' => [2, 2, 3, 1],
185             'G#dim' => [2, 1, 2, 1],
186             'G#m7(b5)' => [2, 2, 2, 1],
187             'G#aug' => [3, 0, 0, 1],
188             'G#sus4' => [4, 4, 3, 1],
189             'G#6' => [3, 1, 3, 1],
190             'G#7(9)' => [3, 2, 3, 3],
191             'G#M7(9)' => [3, 3, 3, 3],
192             'G#mM7' => [6, 4, 7, 4],
193             'G#add9' => [3, 4, 3, 3],
194             'Ab' => [3, 4, 3, 5],
195             'Abm' => [2, 4, 3, 1],
196             'Ab7' => [3, 2, 3, 1],
197             'AbM7' => [3, 3, 3, 1],
198             'Abm7' => [2, 2, 3, 1],
199             'Abdim' => [2, 1, 2, 1],
200             'Abm7(b5)' => [2, 2, 2, 1],
201             'Abaug' => [3, 0, 0, 1],
202             'Absus4' => [4, 4, 3, 1],
203             'Ab6' => [3, 1, 3, 1],
204             'Ab7(9)' => [3, 2, 3, 3],
205             'AbM7(9)' => [3, 3, 3, 3],
206             'AbmM7' => [6, 4, 7, 4],
207             'Abadd9' => [3, 4, 3, 3],
208             'A' => [0, 0, 1, 2],
209             'Am' => [0, 0, 0, 2],
210             'A7' => [0, 0, 1, 0],
211             'AM7' => [0, 0, 1, 1],
212             'Am7' => [0, 0, 0, 0],
213             'Adim' => [3, 2, 3, 2],
214             'Am7(b5)' => [3, 3, 3, 2],
215             'Aaug' => [0, 1, 1, 2],
216             'Asus4' => [0, 0, 2, 2],
217             'A6' => [4, 2, 4, 2],
218             'A7(9)' => [2, 3, 1, 2],
219             'AM7(9)' => [2, 4, 1, 2],
220             'AmM7' => [0, 0, 0, 1],
221             'Aadd9' => [2, 0, 1, 2],
222             'A#' => [1, 1, 2, 3],
223             'A#m' => [1, 1, 1, 3],
224             'A#7' => [1, 1, 2, 1],
225             'A#M7' => [0, 1, 2, 3],
226             'A#m7' => [1, 1, 1, 1],
227             'A#dim' => [1, 0, 1, 0],
228             'A#m7(b5)' => [1, 0, 1, 1],
229             'A#aug' => [1, 2, 2, 3],
230             'A#sus4' => [1, 1, 3, 3],
231             'A#6' => [1, 1, 2, 0],
232             'A#7(9)' => [3, 4, 2, 3],
233             'A#M7(9)' => [5, 5, 5, 5],
234             'A#mM7' => [1, 1, 1, 2],
235             'A#add9' => [3, 1, 2, 3],
236             'Bb' => [1, 1, 2, 3],
237             'Bbm' => [1, 1, 1, 3],
238             'Bb7' => [1, 1, 2, 1],
239             'BbM7' => [0, 1, 2, 3],
240             'Bbm7' => [1, 1, 1, 1],
241             'Bbdim' => [1, 0, 1, 0],
242             'Bbm7(b5)' => [1, 0, 1, 1],
243             'Bbaug' => [1, 2, 2, 3],
244             'Bbsus4' => [1, 1, 3, 3],
245             'Bb6' => [1, 1, 2, 0],
246             'Bb7(9)' => [3, 4, 2, 3],
247             'BbM7(9)' => [5, 5, 5, 5],
248             'BbmM7' => [1, 1, 1, 2],
249             'Bbadd9' => [3, 1, 2, 3],
250             'B' => [2, 2, 3, 4],
251             'Bm' => [2, 2, 2, 4],
252             'B7' => [2, 2, 3, 2],
253             'BM7' => [1, 2, 3, 4],
254             'Bm7' => [2, 2, 2, 2],
255             'Bdim' => [2, 1, 2, 1],
256             'Bm7(b5)' => [2, 1, 2, 2],
257             'Baug' => [2, 3, 3, 4],
258             'Bsus4' => [2, 2, 4, 4],
259             'B6' => [2, 2, 3, 1],
260             'B7(9)' => [4, 2, 3, 2],
261             'BM7(9)' => [4, 1, 3, 3],
262             'BmM7' => [2, 2, 2, 3],
263             'Badd9' => [4, 2, 3, 4],
264             );
265              
266             sub new {
267             my $class = shift;
268             bless {
269             bgcolor => [255, 255, 255],
270             color => [0, 0, 0],
271             interlaced => 'true',
272             }, $class;
273             }
274              
275             sub chord {
276             my ($self, $chord) = @_;
277             return $self->generate($chord, $self->get_flets($chord));
278             }
279              
280             sub get_flets {
281             my ($self, $chord) = @_;
282             return ($chord_lists{$chord} or croak("undefined chord $chord"));
283             }
284              
285             sub generate {
286             my ($self, $chord, $flets) = @_;
287             my @flets = @$flets;
288              
289             my $im = GD::Image->new(48, 44);
290             my $bgcolor = $im->colorAllocate(@{$self->bgcolor});
291             my $color = $im->colorAllocate(@{$self->color});
292              
293             if ($self->interlaced) {
294             $im->transparent($bgcolor);
295             $im->interlaced('true');
296             }
297              
298             $self->_draw_line($im, $color);
299              
300             my $flet_max = max(@flets);
301              
302             if ($flet_max > 5) {
303             $im->filledRectangle(0, 15, 2, 33, $bgcolor);
304             my $flet_num = $flet_max - 5;
305              
306             $_ = $_ - $flet_num for @flets;
307              
308             for my $n (0..4) {
309             $im->string(GD::Font->Tiny, 9 * $n, 35, $flet_num + 1, $color);
310             $flet_num++;
311             }
312             }
313              
314             my $i = 0;
315             for my $flet (@flets) {
316             $im->filledRectangle(
317             5 + 8 * ($flet - 1),
318             14 + 6 * $i,
319             7 + 8 * ($flet - 1),
320             16 + 6 * $i, $color
321             ) if ( $flet > 0 );
322             $i++;
323             }
324              
325             $im->string(GD::Font->Small, 0, 0, $chord, $color);
326              
327             return $im;
328             }
329              
330             sub all_chords {
331             return [keys(%chord_lists)];
332             }
333              
334             sub _draw_line {
335             my ($self, $im, $color) = @_;
336             for my $line (@lines) {
337             $im->line(@$line, $color);
338             }
339             return $im;
340             }
341              
342             1;
343              
344              
345             __END__