File Coverage

blib/lib/PDF/Builder/Resource/XObject/Form/BarCode.pm
Criterion Covered Total %
statement 105 130 80.7
branch 26 36 72.2
condition 37 70 52.8
subroutine 9 11 81.8
pod 3 6 50.0
total 180 253 71.1


line stmt bran cond sub pod time code
1             package PDF::Builder::Resource::XObject::Form::BarCode;
2              
3 2     2   849 use base 'PDF::Builder::Resource::XObject::Form::Hybrid';
  2         5  
  2         205  
4              
5 2     2   12 use strict;
  2         4  
  2         44  
6 2     2   9 use warnings;
  2         3  
  2         98  
7              
8             our $VERSION = '3.024'; # VERSION
9             our $LAST_UPDATE = '3.024'; # manually update whenever code is changed
10              
11 2     2   11 use PDF::Builder::Util;
  2         4  
  2         252  
12 2     2   14 use PDF::Builder::Basic::PDF::Utils;
  2         3  
  2         2514  
13              
14             =head1 NAME
15              
16             PDF::Builder::Resource::XObject::Form::BarCode - Base class for one-dimensional barcodes
17              
18             =head1 METHODS
19              
20             =over
21              
22             =item $barcode = PDF::Builder::Resource::XObject::Form::BarCode->new($pdf, %options)
23              
24             Creates a barcode form resource.
25              
26             =cut
27              
28             sub new {
29 6     6 1 16 my ($class, $pdf, %options) = @_;
30             # copy dashed option names to preferred undashed names
31 6 100 66     21 if (defined $options{'-font'} && !defined $options{'font'}) { $options{'font'} = delete($options{'-font'}); }
  1         3  
32 6 100 66     15 if (defined $options{'-umzn'} && !defined $options{'umzn'}) { $options{'umzn'} = delete($options{'-umzn'}); }
  1         5  
33 6 100 66     15 if (defined $options{'-lmzn'} && !defined $options{'lmzn'}) { $options{'lmzn'} = delete($options{'-lmzn'}); }
  1         2  
34 6 100 66     15 if (defined $options{'-zone'} && !defined $options{'zone'}) { $options{'zone'} = delete($options{'-zone'}); }
  1         2  
35 6 50 33     14 if (defined $options{'-quzn'} && !defined $options{'quzn'}) { $options{'quzn'} = delete($options{'-quzn'}); }
  0         0  
36 6 50 33     12 if (defined $options{'-ofwt'} && !defined $options{'ofwt'}) { $options{'ofwt'} = delete($options{'-ofwt'}); }
  0         0  
37 6 100 66     14 if (defined $options{'-fnsz'} && !defined $options{'fnsz'}) { $options{'fnsz'} = delete($options{'-fnsz'}); }
  1         2  
38 6 50 33     12 if (defined $options{'-spcr'} && !defined $options{'spcr'}) { $options{'spcr'} = delete($options{'-spcr'}); }
  0         0  
39 6 50 33     11 if (defined $options{'-mils'} && !defined $options{'mils'}) { $options{'mils'} = delete($options{'-mils'}); }
  0         0  
40 6 50 33     14 if (defined $options{'-color'} && !defined $options{'color'}) { $options{'color'} = delete($options{'-color'}); }
  0         0  
41              
42 6         21 my $self = $class->SUPER::new($pdf);
43              
44 6         10 $self->{' bfont'} = $options{'font'};
45              
46 6   50     20 $self->{' umzn'} = $options{'umzn'} || 0; # (u)pper (m)ending (z)o(n)e
47 6   100     19 $self->{' lmzn'} = $options{'lmzn'} || 0; # (l)ower (m)ending (z)o(n)e
48 6   100     39 $self->{' zone'} = $options{'zone'} || 0; # barcode height
49 6   50     17 $self->{' quzn'} = $options{'quzn'} || 0; # (qu)iet (z)o(n)e
50 6   50     19 $self->{' ofwt'} = $options{'ofwt'} || 0.01; # (o)ver(f)low (w)id(t)h
51 6         10 $self->{' fnsz'} = $options{'fnsz'}; # (f)o(n)t(s)i(z)e
52 6   50     17 $self->{' spcr'} = $options{'spcr'} || ''; # (sp)a(c)e(r) between chars in label
53 6   50     15 $self->{' mils'} = $options{'mils'} || 1000/72; # single barcode unit width. 1 mil = 1/1000 of one inch. 1000/72 - for backward compatibility
54 6   50     15 $self->{' color'} = $options{'color'} || 'black'; # barcode color
55              
56 6         20 return $self;
57             }
58              
59             my %bar_widths = (
60             0 => 0,
61             1 => 1, 'a' => 1, 'A' => 1,
62             2 => 2, 'b' => 2, 'B' => 2,
63             3 => 3, 'c' => 3, 'C' => 3,
64             4 => 4, 'd' => 4, 'D' => 4,
65             5 => 5, 'e' => 5, 'E' => 5,
66             6 => 6, 'f' => 6, 'F' => 6,
67             7 => 7, 'g' => 7, 'G' => 7,
68             8 => 8, 'h' => 8, 'H' => 8,
69             9 => 9, 'i' => 9, 'I' => 9,
70             );
71              
72             sub encode {
73 2     2 0 1696 my ($self, $string) = @_;
74              
75 2         10 my @bars = map { [ $self->encode_string($_), $_ ] } split(//, $string);
  17         28  
76 2         7 return @bars;
77             }
78              
79             sub encode_string {
80 17     17 0 34 my ($self, $string) = @_;
81              
82 17         20 my $bar;
83 17         26 foreach my $character (split(//, $string)) {
84 17         32 $bar .= $self->encode_char($character);
85             }
86 17         41 return $bar;
87             }
88              
89             sub drawbar {
90 6     6 0 10 my $self = shift();
91 6         9 my @sets = @{shift()};
  6         16  
92 6         14 my $caption = shift();
93              
94 6         36 $self->fillcolor($self->{' color'});
95 6         30 $self->strokecolor($self->{' color'});
96 6         43 $self->linedash();
97              
98 6         9 my $x = $self->{' quzn'};
99 6         8 my $is_space_next = 0;
100 6         14 my $wdt_factor = $self->{' mils'} / 1000 * 72;
101 6         13 foreach my $set (@sets) {
102 30         39 my ($code, $label);
103 30 100       52 if (ref($set)) {
104 18         22 ($code, $label) = @{$set};
  18         38  
105             } else {
106 12         20 $code = $set;
107 12         16 $label = undef;
108             }
109              
110 30         38 my $code_width = 0;
111 30         46 my ($font_size, $y_label);
112 30         84 foreach my $bar (split(//, $code)) {
113 172         272 my $bar_width = $bar_widths{$bar} * $wdt_factor;
114              
115 172         221 my ($y0, $y1);
116 172 100       448 if ($bar =~ /[0-9]/) {
    50          
    0          
117 115         175 $y0 = $self->{' quzn'} + $self->{' lmzn'};
118 115         167 $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'};
119 115         142 $y_label = $self->{' quzn'};
120 115 50 66     229 if ($self->{' fnsz'} and $self->{' lmzn'} < $self->{' fnsz'}) {
121 0         0 $y_label -= $self->{' fnsz'} * 0.8 - $self->{' lmzn'};
122             }
123 115   66     248 $font_size = $self->{' fnsz'} || $self->{' lmzn'};
124             } elsif ($bar =~ /[a-z]/) {
125 57         76 $y0 = $self->{' quzn'};
126 57         85 $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'};
127 57         84 $y_label = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'} + 2;
128 57   66     116 $font_size = $self->{' fnsz'} || $self->{' umzn'};
129             } elsif ($bar =~ /[A-Z]/) {
130 0         0 $y0 = $self->{' quzn'};
131 0         0 $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'};
132 0   0     0 $font_size = $self->{' fnsz'} || $self->{' umzn'};
133 0         0 $y_label = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'} - $font_size;
134             } else {
135 0         0 $y0 = $self->{' quzn'} + $self->{' lmzn'};
136 0         0 $y1 = $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'};
137 0         0 $y_label = $self->{' quzn'};
138 0   0     0 $font_size = $self->{' fnsz'} || $self->{' lmzn'};
139             }
140              
141 172 100 100     379 unless ($is_space_next or $bar eq '0') {
142 86         288 $self->linewidth($bar_width - $self->{' ofwt'});
143 86         277 $self->move($x + $code_width + $bar_width / 2, $y0);
144 86         284 $self->line($x + $code_width + $bar_width / 2, $y1);
145 86         199 $self->stroke();
146             }
147 172         253 $is_space_next = not $is_space_next;
148              
149 172         266 $code_width += $bar_width;
150             }
151              
152 30 100 100     97 if (defined($label) and $self->{' lmzn'}) {
153 1         4 $label = join($self->{' spcr'}, split(//, $label));
154 1         15 $self->textstart();
155 1         25 $self->translate($x + ($code_width / 2), $y_label);
156 1         9 $self->font($self->{' bfont'}, $font_size);
157 1         12 $self->text_center($label);
158 1         8 $self->textend();
159             }
160              
161 30         50 $x += $code_width;
162             }
163              
164 6         7 $x += $self->{' quzn'};
165              
166 6 50       12 if (defined $caption) {
167 0   0     0 my $font_size = $self->{' fnsz'} || $self->{' lmzn'};
168 0         0 my $y_caption = $self->{' quzn'} - $font_size;
169 0         0 $self->textstart();
170 0         0 $self->translate($x / 2, $y_caption);
171 0         0 $self->font($self->{' bfont'}, $font_size);
172 0         0 $self->text_center($caption);
173 0         0 $self->textend();
174             }
175              
176 6         9 $self->{' w'} = $x;
177 6         15 $self->{' h'} = 2 * $self->{' quzn'} + $self->{' lmzn'} + $self->{' zone'} + $self->{' umzn'};
178 6         49 $self->bbox(0, 0, $self->{' w'}, $self->{' h'});
179 6         15 return;
180             }
181              
182             =item $width = $barcode->width()
183              
184             =cut
185              
186             sub width {
187 0     0 1   my $self = shift;
188              
189 0           return $self->{' w'};
190             }
191              
192             =item $height = $barcode->height()
193              
194             =cut
195              
196             sub height {
197 0     0 1   my $self = shift;
198              
199 0           return $self->{' h'};
200             }
201              
202             =back
203              
204             =cut
205              
206             1;