View | Details | Raw Unified | Return to bug 37356
Collapse All | Expand All

(-)a/C4/Barcodes/Drawer.pm (+160 lines)
Line 0 Link Here
1
package C4::Barcodes::Drawer;
2
3
# Copyright 2024 Koha Development Team
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Algorithm::CheckDigits qw( CheckDigits );
22
23
=head1 NAME
24
25
C4::Barcodes::Drawer - Common Barcode Drawer
26
27
=head1 SYNOPSIS
28
29
use C4::Barcodes::Drawer;
30
31
C4::Barcodes::Drawer::draw_barcode();
32
33
=head1 FUNCTIONS
34
35
=head2 draw_barcode()
36
37
    Invoking the I<draw_barcode> method generates a barcode for the label object and inserts it into the current pdf stream. This method accepts the following parameters as key => value
38
    pairs (C<barcode_data> is optional and omitting it will cause the barcode from the current item to be used. C<barcode_type> is also optional. Omission results in the barcode
39
    type of the current template being used.):
40
41
        C<llx>                  The lower-left x coordinate for the barcode block (The point of origin for all PDF's is the lower left of the page per ISO 32000-1)
42
        C<lly>                  The lower-left y coordinate for the barcode block
43
        C<width>                The width of the barcode block
44
        C<y_scale_factor>       The scale factor to be applied to the y axis of the barcode block
45
        C<barcode_data>         The data to be encoded in the barcode
46
        C<barcode_type>         The barcode type (See the C<new()> method for supported barcode types)
47
48
    example:
49
       C<$label->barcode(
50
                    llx                 => $barcode_llx,
51
                    lly                 => $barcode_lly,
52
                    width               => $barcode_width,
53
                    y_scale_factor      => $barcode_y_scale_factor,
54
                    barcode_data        => $barcode,
55
                    barcode_type        => $barcodetype,
56
        );>
57
58
=cut
59
60
sub draw_barcode {
61
    my $self = shift;
62
    my %params = @_;
63
    #    $params{'barcode_data'} = ($self->{'barcode'} || _get_label_item($self->{'item_number'}, 1)) if !$params{'barcode_data'};
64
    $params{'barcode_type'} = $self->{'barcode_type'} if !$params{'barcode_type'};
65
    my $x_scale_factor = 1;
66
    my $num_of_bars = length($params{'barcode_data'});
67
    my $tot_bar_length = 0;
68
    my $bar_length = 0;
69
    my $guard_length = 10;
70
    my $hide_text = 'yes';
71
    if ($params{'barcode_type'} =~ m/CODE39/) {
72
        $bar_length = '17.5';
73
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
74
        $x_scale_factor = ($params{'width'} / $tot_bar_length);
75
        if ($params{'barcode_type'} eq 'CODE39MOD') {
76
            my $c39 = CheckDigits('code_39');   # get modulo43 checksum
77
            $params{'barcode_data'} = $c39->complete($params{'barcode_data'});
78
        }
79
        elsif ($params{'barcode_type'} eq 'CODE39MOD10') {
80
            my $c39_10 = CheckDigits('siret');   # get modulo43 checksum
81
            $params{'barcode_data'} = $c39_10->complete($params{'barcode_data'});
82
            $hide_text = '';
83
        }
84
        eval {
85
            PDF::Reuse::Barcode::Code39(
86
                x                   => $params{'llx'},
87
                y                   => $params{'lly'},
88
                value               => "*$params{barcode_data}*",
89
                xSize               => $x_scale_factor,
90
                ySize               => $params{'y_scale_factor'},
91
                hide_asterisk       => 1,
92
                text                => $hide_text,
93
                mode                => 'graphic',
94
            );
95
        };
96
        if ($@) {
97
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
98
        }
99
    }
100
    elsif ($params{'barcode_type'} eq 'COOP2OF5') {
101
        $bar_length = '9.43333333333333';
102
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
103
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
104
        eval {
105
            PDF::Reuse::Barcode::COOP2of5(
106
                x                   => $params{'llx'},
107
                y                   => $params{'lly'},
108
                value               => $params{barcode_data},
109
                xSize               => $x_scale_factor,
110
                ySize               => $params{'y_scale_factor'},
111
                mode                    => 'graphic',
112
            );
113
        };
114
        if ($@) {
115
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
116
        }
117
    }
118
    elsif ( $params{'barcode_type'} eq 'INDUSTRIAL2OF5' ) {
119
        $bar_length = '13.1333333333333';
120
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
121
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
122
        eval {
123
            PDF::Reuse::Barcode::Industrial2of5(
124
                x                   => $params{'llx'},
125
                y                   => $params{'lly'},
126
                value               => $params{barcode_data},
127
                xSize               => $x_scale_factor,
128
                ySize               => $params{'y_scale_factor'},
129
                mode                    => 'graphic',
130
            );
131
        };
132
        if ($@) {
133
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
134
        }
135
    }
136
    elsif ($params{'barcode_type'} eq 'EAN13') {
137
        $bar_length = 4; # FIXME
138
    $num_of_bars = 13;
139
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
140
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
141
        eval {
142
            PDF::Reuse::Barcode::EAN13(
143
                x                   => $params{'llx'},
144
                y                   => $params{'lly'},
145
                value               => sprintf('%013d',$params{barcode_data}),
146
#                xSize               => $x_scale_factor,
147
#                ySize               => $params{'y_scale_factor'},
148
                mode                    => 'graphic',
149
            );
150
        };
151
        if ($@) {
152
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
153
        }
154
    }
155
    else {
156
    warn "unknown barcode_type: $params{barcode_type}";
157
    }
158
}
159
160
1;
(-)a/C4/Labels/Label.pm (-125 / +3 lines)
Lines 4-10 use strict; Link Here
4
use warnings;
4
use warnings;
5
5
6
use Text::Wrap qw( wrap );
6
use Text::Wrap qw( wrap );
7
use Algorithm::CheckDigits qw( CheckDigits );
8
use Text::CSV_XS;
7
use Text::CSV_XS;
9
use Text::Bidi qw( log2vis );
8
use Text::Bidi qw( log2vis );
10
9
Lines 14-19 use Koha::Biblios; Link Here
14
use Koha::ClassSources;
13
use Koha::ClassSources;
15
use Koha::ClassSortRules;
14
use Koha::ClassSortRules;
16
use Koha::ClassSplitRules;
15
use Koha::ClassSplitRules;
16
use C4::Barcodes::Drawer;
17
use C4::ClassSplitRoutine::Dewey;
17
use C4::ClassSplitRoutine::Dewey;
18
use C4::ClassSplitRoutine::LCC;
18
use C4::ClassSplitRoutine::LCC;
19
use C4::ClassSplitRoutine::Generic;
19
use C4::ClassSplitRoutine::Generic;
Lines 353-363 sub create_label { Link Here
353
                                    );
353
                                    );
354
    }
354
    }
355
    if ($self->{'printing_type'} =~ /BAR/) {
355
    if ($self->{'printing_type'} =~ /BAR/) {
356
        barcode(    $self,
356
        C4::Barcodes::Drawer::draw_barcode(    $self,
357
                    llx                 => $barcode_llx,
357
                    llx                 => $barcode_llx,
358
                    lly                 => $barcode_lly,
358
                    lly                 => $barcode_lly,
359
                    width               => $barcode_width,
359
                    width               => $barcode_width,
360
                    y_scale_factor      => $barcode_y_scale_factor,
360
                    y_scale_factor      => $barcode_y_scale_factor,
361
                    barcode_data        => $self->{'barcode'} || _get_label_item($self->{'item_number'}, 1),
361
        );
362
        );
362
    }
363
    }
363
    return $label_text if $label_text;
364
    return $label_text if $label_text;
Lines 486-591 sub draw_guide_box { Link Here
486
    return $_[0]->{'guidebox'};
487
    return $_[0]->{'guidebox'};
487
}
488
}
488
489
489
sub barcode {
490
    my $self = shift;
491
    my %params = @_;
492
    $params{'barcode_data'} = ($self->{'barcode'} || _get_label_item($self->{'item_number'}, 1)) if !$params{'barcode_data'};
493
    $params{'barcode_type'} = $self->{'barcode_type'} if !$params{'barcode_type'};
494
    my $x_scale_factor = 1;
495
    my $num_of_bars = length($params{'barcode_data'});
496
    my $tot_bar_length = 0;
497
    my $bar_length = 0;
498
    my $guard_length = 10;
499
    my $hide_text = 'yes';
500
    if ($params{'barcode_type'} =~ m/CODE39/) {
501
        $bar_length = '17.5';
502
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
503
        $x_scale_factor = ($params{'width'} / $tot_bar_length);
504
        if ($params{'barcode_type'} eq 'CODE39MOD') {
505
            my $c39 = CheckDigits('code_39');   # get modulo43 checksum
506
            $params{'barcode_data'} = $c39->complete($params{'barcode_data'});
507
        }
508
        elsif ($params{'barcode_type'} eq 'CODE39MOD10') {
509
            my $c39_10 = CheckDigits('siret');   # get modulo43 checksum
510
            $params{'barcode_data'} = $c39_10->complete($params{'barcode_data'});
511
            $hide_text = '';
512
        }
513
        eval {
514
            PDF::Reuse::Barcode::Code39(
515
                x                   => $params{'llx'},
516
                y                   => $params{'lly'},
517
                value               => "*$params{barcode_data}*",
518
                xSize               => $x_scale_factor,
519
                ySize               => $params{'y_scale_factor'},
520
                hide_asterisk       => 1,
521
                text                => $hide_text,
522
                mode                => 'graphic',
523
            );
524
        };
525
        if ($@) {
526
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
527
        }
528
    }
529
    elsif ($params{'barcode_type'} eq 'COOP2OF5') {
530
        $bar_length = '9.43333333333333';
531
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
532
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
533
        eval {
534
            PDF::Reuse::Barcode::COOP2of5(
535
                x                   => $params{'llx'},
536
                y                   => $params{'lly'},
537
                value               => $params{barcode_data},
538
                xSize               => $x_scale_factor,
539
                ySize               => $params{'y_scale_factor'},
540
                mode                    => 'graphic',
541
            );
542
        };
543
        if ($@) {
544
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
545
        }
546
    }
547
    elsif ( $params{'barcode_type'} eq 'INDUSTRIAL2OF5' ) {
548
        $bar_length = '13.1333333333333';
549
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
550
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
551
        eval {
552
            PDF::Reuse::Barcode::Industrial2of5(
553
                x                   => $params{'llx'},
554
                y                   => $params{'lly'},
555
                value               => $params{barcode_data},
556
                xSize               => $x_scale_factor,
557
                ySize               => $params{'y_scale_factor'},
558
                mode                    => 'graphic',
559
            );
560
        };
561
        if ($@) {
562
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
563
        }
564
    }
565
    elsif ($params{'barcode_type'} eq 'EAN13') {
566
        $bar_length = 4; # FIXME
567
    $num_of_bars = 13;
568
        $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2);
569
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
570
        eval {
571
            PDF::Reuse::Barcode::EAN13(
572
                x                   => $params{'llx'},
573
                y                   => $params{'lly'},
574
                value               => sprintf('%013d',$params{barcode_data}),
575
#                xSize               => $x_scale_factor,
576
#                ySize               => $params{'y_scale_factor'},
577
                mode                    => 'graphic',
578
            );
579
        };
580
        if ($@) {
581
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
582
        }
583
    }
584
    else {
585
    warn "unknown barcode_type: $params{barcode_type}";
586
    }
587
}
588
589
sub csv_data {
490
sub csv_data {
590
    my $self = shift;
491
    my $self = shift;
591
    my $label_fields = _get_text_fields($self->{'format_string'});
492
    my $label_fields = _get_text_fields($self->{'format_string'});
Lines 776-804 R = Right Link Here
776
                                                justify             => $text_justification,
677
                                                justify             => $text_justification,
777
                        );>
678
                        );>
778
679
779
=head2 barcode()
780
781
    Invoking the I<barcode> method generates a barcode for the label object and inserts it into the current pdf stream. This method accepts the following parameters as key => value
782
    pairs (C<barcode_data> is optional and omitting it will cause the barcode from the current item to be used. C<barcode_type> is also optional. Omission results in the barcode
783
    type of the current template being used.):
784
785
        C<llx>                  The lower-left x coordinate for the barcode block (The point of origin for all PDF's is the lower left of the page per ISO 32000-1)
786
        C<lly>                  The lower-left y coordinate for the barcode block
787
        C<width>                The width of the barcode block
788
        C<y_scale_factor>       The scale factor to be applied to the y axis of the barcode block
789
        C<barcode_data>         The data to be encoded in the barcode
790
        C<barcode_type>         The barcode type (See the C<new()> method for supported barcode types)
791
792
    example:
793
       C<$label->barcode(
794
                    llx                 => $barcode_llx,
795
                    lly                 => $barcode_lly,
796
                    width               => $barcode_width,
797
                    y_scale_factor      => $barcode_y_scale_factor,
798
                    barcode_data        => $barcode,
799
                    barcode_type        => $barcodetype,
800
        );>
801
802
=head2 csv_data()
680
=head2 csv_data()
803
681
804
    Invoking the I<csv_data> method returns an arrayref of an array containing the label data suitable for passing to Text::CSV_XS->combine() to produce csv output.
682
    Invoking the I<csv_data> method returns an arrayref of an array containing the label data suitable for passing to Text::CSV_XS->combine() to produce csv output.
(-)a/C4/Patroncards/Patroncard.pm (-85 / +2 lines)
Lines 23-28 use warnings; Link Here
23
use autouse 'Data::Dumper' => qw(Dumper);
23
use autouse 'Data::Dumper' => qw(Dumper);
24
#use Font::TTFMetrics;
24
#use Font::TTFMetrics;
25
25
26
use C4::Barcodes::Drawer;
26
use C4::Creators::Lib qw( get_unit_values );
27
use C4::Creators::Lib qw( get_unit_values );
27
use C4::Creators::PDF qw(StrWidth);
28
use C4::Creators::PDF qw(StrWidth);
28
use C4::Patroncards::Lib qw(
29
use C4::Patroncards::Lib qw(
Lines 100-106 sub draw_barcode { Link Here
100
    my $llx_layout           = $self->{'layout'}->{'barcode'}->[0]->{'llx'} || 0;
101
    my $llx_layout           = $self->{'layout'}->{'barcode'}->[0]->{'llx'} || 0;
101
    my $lly                  = $self->{'lly'} || 0;
102
    my $lly                  = $self->{'lly'} || 0;
102
    my $lly_layout           = $self->{'layout'}->{'barcode'}->[0]->{'lly'} || 0;
103
    my $lly_layout           = $self->{'layout'}->{'barcode'}->[0]->{'lly'} || 0;
103
    _draw_barcode(
104
    C4::Barcodes::Drawer::draw_barcode(
104
        $self,
105
        $self,
105
        llx            => $llx + $llx_layout * $self->{'unitvalue'},
106
        llx            => $llx + $llx_layout * $self->{'unitvalue'},
106
        lly            => $lly + $lly_layout * $self->{'unitvalue'},
107
        lly            => $lly + $lly_layout * $self->{'unitvalue'},
Lines 378-466 sub draw_image { Link Here
378
    }
379
    }
379
}
380
}
380
381
381
=head2 draw_barcode
382
383
    $patron_card->draw_barcode($pdf)
384
385
Draws a barcode to PDF output ($pdf)
386
387
=cut
388
389
sub _draw_barcode {   # this is cut-and-paste from Label.pm because there is no common place for it atm...
390
    my $self = shift;
391
    my %params = @_;
392
393
    my $x_scale_factor = 1;
394
    my $num_of_chars = length($params{'barcode_data'});
395
    my $tot_bar_length = 0;
396
    my $bar_length = 0;
397
    my $guard_length = 10;
398
    if ($params{'barcode_type'} =~ m/CODE39/) {
399
        $bar_length = '17.5';
400
        $tot_bar_length = ($bar_length * $num_of_chars) + ($guard_length * 2);  # not sure what all is going on here and on the next line; this is old (very) code
401
        $x_scale_factor = ($params{'width'} / $tot_bar_length);
402
        if ($params{'barcode_type'} eq 'CODE39MOD') {
403
            my $c39 = CheckDigits('code_39');   # get modulo 43 checksum
404
            $params{'barcode_data'} = $c39->complete($params{'barcode_data'});
405
        }
406
        elsif ($params{'barcode_type'} eq 'CODE39MOD10') {
407
            my $c39_10 = CheckDigits('siret');   # get modulo 10 checksum
408
            $params{'barcode_data'} = $c39_10->complete($params{'barcode_data'});
409
        }
410
        eval {
411
            PDF::Reuse::Barcode::Code39(
412
                x                   => $params{'llx'},
413
                y                   => $params{'lly'},
414
                value               => "*$params{barcode_data}*",
415
                xSize               => $x_scale_factor,
416
                ySize               => $params{'y_scale_factor'},
417
                hide_asterisk       => 1,
418
                text                => $params{'text'},
419
                mode                => 'graphic',
420
            );
421
        };
422
        if ($@) {
423
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
424
        }
425
    }
426
    elsif ($params{'barcode_type'} eq 'COOP2OF5') {
427
        $bar_length = '9.43333333333333';
428
        $tot_bar_length = ($bar_length * $num_of_chars) + ($guard_length * 2);
429
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
430
        eval {
431
            PDF::Reuse::Barcode::COOP2of5(
432
                x                   => $params{'llx'},
433
                y                   => $params{'lly'},
434
                value               => $params{barcode_data},
435
                xSize               => $x_scale_factor,
436
                ySize               => $params{'y_scale_factor'},
437
                mode                    => 'graphic',
438
            );
439
        };
440
        if ($@) {
441
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
442
        }
443
    }
444
    elsif ( $params{'barcode_type'} eq 'INDUSTRIAL2OF5' ) {
445
        $bar_length = '13.1333333333333';
446
        $tot_bar_length = ($bar_length * $num_of_chars) + ($guard_length * 2);
447
        $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9;
448
        eval {
449
            PDF::Reuse::Barcode::Industrial2of5(
450
                x                   => $params{'llx'},
451
                y                   => $params{'lly'},
452
                value               => $params{barcode_data},
453
                xSize               => $x_scale_factor,
454
                ySize               => $params{'y_scale_factor'},
455
                mode                    => 'graphic',
456
            );
457
        };
458
        if ($@) {
459
            warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@);
460
        }
461
    }
462
}
463
464
1;
382
1;
465
__END__
383
__END__
466
384
467
- 

Return to bug 37356