File Coverage

blib/lib/Imager/IMBarcode/JP.pm
Criterion Covered Total %
statement 89 89 100.0
branch 18 18 100.0
condition n/a
subroutine 13 13 100.0
pod 1 2 50.0
total 121 122 99.1


line stmt bran cond sub pod time code
1             package Imager::IMBarcode::JP;
2              
3 2     2   69088 use strict;
  2         15  
  2         57  
4 2     2   10 use warnings;
  2         8  
  2         45  
5 2     2   1245 use utf8;
  2         30  
  2         10  
6 2     2   2019 use Imager;
  2         116655  
  2         13  
7 2     2   1086 use Mouse;
  2         58609  
  2         15  
8 2     2   790 use Carp;
  2         5  
  2         862  
9              
10             our $VERSION = '0.02';
11              
12             has zipcode => (
13             is => 'rw',
14             isa => 'Int',
15             default => '0000000',
16             );
17              
18             has address => (
19             is => 'rw',
20             isa => 'Str',
21             default => '',
22             );
23              
24             has _pos => (
25             is => 'rw',
26             isa => 'Int',
27             default => 0,
28             );
29              
30             has _base => (
31             is => 'ro',
32             isa => 'Imager',
33             lazy_build => 1,
34             );
35              
36             has _char_code => (
37             is => 'ro',
38             isa => 'HashRef',
39             default => sub {
40             my %code = (
41             STC => +{
42             bar => 13,
43             },
44             SPC => +{
45             bar => 31,
46             },
47             1 => +{
48             check => 1,
49             bar => 114,
50             },
51             2 => +{
52             check => 2,
53             bar => 132,
54             },
55             3 => +{
56             check => 3,
57             bar => 312,
58             },
59             4 => +{
60             check => 4,
61             bar => 123,
62             },
63             5 => +{
64             check => 5,
65             bar => 141,
66             },
67             6 => +{
68             check => 6,
69             bar => 321,
70             },
71             7 => +{
72             check => 7,
73             bar => 213,
74             },
75             8 => +{
76             check => 8,
77             bar => 231,
78             },
79             9 => +{
80             check => 9,
81             bar => 411,
82             },
83             0 => +{
84             check => 0,
85             bar => 144,
86             },
87             '-' => +{
88             check => 10,
89             bar => 414,
90             },
91             CC1 => +{
92             check => 11,
93             bar => 324,
94             },
95             CC2 => +{
96             check => 12,
97             bar => 342,
98             },
99             CC3 => => +{
100             check => 13,
101             bar => 234,
102             },
103             CC4 => +{
104             check => 14,
105             bar => 432,
106             },
107             CC5 => +{
108             check => 15,
109             bar => 243,
110             },
111             CC6 => +{
112             check => 16,
113             bar => 423,
114             },
115             CC7 => +{
116             check => 17,
117             bar => 441,
118             },
119             CC8 => +{
120             check => 18,
121             bar => 111,
122             },
123             );
124             my @cc = @code{qw(CC1 CC2 CC3)};
125             for my $i (0 .. $#cc) {
126             for my $num (0 .. 9) {
127             my $k = chr(65 + (10 * $i) + $num);
128             my $v = [ $cc[$i], $code{$num} ];
129             $code{$k} = +{
130             check => [ $cc[$i]->{check}, $code{$num}->{check} ],
131             bar => [ $cc[$i]->{bar}, $code{$num}->{bar} ],
132             };
133             last if $k ge 'Z';
134             }
135             }
136             return \%code;
137             },
138             );
139              
140 2     2   17 no Mouse;
  2         12  
  2         19  
141              
142             __PACKAGE__->meta->make_immutable;
143              
144             sub _to_code {
145 38     38   61 my($self, $char) = @_;
146 38         81 return $self->_char_code->{uc($char)};
147             }
148              
149             sub _find_bar_by_check {
150 2     2   4 my($self, $check) = @_;
151 2         4 my $code = $self->_char_code;
152 2         25 for my $v (values %$code) {
153 28 100       56 next unless exists $v->{check};
154 26         34 my $val = $v->{check};
155 26 100       59 next if ref($val) eq 'ARRAY';
156 16 100       34 next if $val != $check;
157 2         5 return $v->{bar};
158             }
159             }
160              
161             sub draw {
162 4     4 1 3054 my $self = shift;
163 4         11 my $bars = $self->make_bars;
164 2         13 for my $bar (@$bars) {
165 46         156 $self->_draw_num(split //, $bar);
166             }
167 2         10 return $self->_base;
168             }
169              
170             sub make_bars {
171 4     4 0 6 my $self = shift;
172 4 100       30 unless ($self->zipcode =~ /^\d{7}$/) {
173 1         153 croak('Invalid zipcode(): ' . $self->zipcode);
174             }
175 3 100       28 unless ($self->address =~ /^[-0-9A-Z]*$/i) {
176 1         101 croak('Invalid address(): ' . $self->address);
177             }
178 2         3 my @bars = ();
179 2         4 my $checksum = 0;
180              
181 2         6 my $start = $self->_to_code('STC');
182 2         6 push @bars, $start->{bar};
183              
184 2         9 for my $chr (split //, $self->zipcode) {
185 14         25 my $code = $self->_to_code($chr);
186 14         21 $checksum += $code->{check};
187 14         24 push @bars, $code->{bar};
188             }
189              
190 2         13 for my $chr (split //, $self->address) {
191 7         13 my $code = $self->_to_code($chr);
192 7         11 my $check = $code->{check};
193 7 100       14 if (ref($check) eq 'ARRAY') {
194 6         11 my $bar = $code->{bar};
195 6         6 for my $i (0 .. $#{$check}) {
  6         15  
196 12         17 my $c = $check->[$i];
197 12         16 my $b = $bar->[$i];
198 12         17 $checksum += $c;
199 12         18 push @bars, $b;
200 12 100       26 last if @bars >= 21;
201             }
202             }
203             else {
204 1         3 $checksum += $code->{check};
205 1         2 push @bars, $code->{bar};
206             }
207 7 100       15 last if @bars >= 21;
208             }
209              
210 2         7 while (scalar(@bars) < 21) {
211 13         20 my $code = $self->_to_code('CC4');
212 13         18 $checksum += $code->{check};
213 13         29 push @bars, $code->{bar};
214             }
215              
216 2         8 my $checkdigit = 19 - ($checksum % 19);
217 2         6 my $bar = $self->_find_bar_by_check($checkdigit);
218 2         5 push @bars, $bar;
219              
220 2         5 my $stop = $self->_to_code('SPC');
221 2         9 push @bars, $stop->{bar};
222 2         5 return \@bars;
223             }
224              
225             sub _build__base {
226 2     2   3 my $self = shift;
227 2         10 my $img = Imager->new(
228             xsize => 979,
229             ysize => 90,
230             );
231 2         727 $img->settag(name => 'i_xres', value => 300);
232 2         170 $img->settag(name => 'i_yres', value => 300);
233 2         113 $img->box(filled => 1, color => '#ffffff');
234 2         1487 return $img;
235             }
236              
237             sub _draw_num {
238 46     46   71 my $self = shift;
239 46         102 my @nums = @_;
240 46         83 for my $num (@nums) {
241 134         237 my $pos = $self->_pos;
242 134         205 my $x = 24 + $pos * 14;
243 134 100       363 my $ymin = $num =~ m{^[12]$} ? 24 : 38;
244             my $ymax = +{
245             1 => $ymin + 41,
246             2 => $ymin + 27,
247             3 => $ymin + 27,
248             4 => $ymin + 13,
249 134         401 }->{$num};
250 134         525 $self->_base->box(
251             xmin => $x,
252             ymin => $ymin,
253             xmax => $x + 6,
254             ymax => $ymax,
255             color => '#000000',
256             filled => 1,
257             );
258 134         9654 $self->_pos($self->_pos + 1);
259             }
260             }
261              
262             1;
263             __END__