Koha/labels/label-print-pdf.pl
Chris Nighswonger d1e03bbf11 Bug 3390 Enabling ZIP compression in pdf generation to reduce file size
Enabling compression gives a ~26% *reduction* over non-compressed Type 3 font embedding.
ie. 4.5 K/pg (compressed graphic) vs. 17.5 K/pg (uncompressed Type 3 font) vs 111 K/pg
(uncompressed graphic).

It also appears that most other applications that export in pdf use compression by
default. (OO Writer, etc.) So this approach appears justified. One could always add code
to allow the user to select embedding mode and compression.

Also correcting mode parameter value.

Signed-off-by: Galen Charlton <galen.charlton@liblime.com>
2009-07-13 08:19:56 -04:00

260 lines
10 KiB
Perl
Executable file

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use C4::Labels; # GetActiveLabelTemplate get_label_options GetAssociatedProfile
# GetPatronCardItems GetLabelItems GetUnitsValue...
use C4::Auth;
use C4::Output;
use C4::Context;
use C4::Members;
use C4::Branch;
use HTML::Template::Pro;
use PDF::Reuse;
use PDF::Reuse::Barcode;
use POSIX; # ceil
use Data::Dumper;
my $DEBUG = 0;
my $DEBUG_LPT = 0;
my $cgi = new CGI;
#### Tons of Initialization ####
# get the printing settings
my $template = GetActiveLabelTemplate();
my $conf_data = get_label_options() or die "get_label_options failed";
my $profile = GetAssociatedProfile($template->{'tmpl_id'});
my $batch_id = $cgi->param('batch_id');
my @resultsloop;
my $batch_type = $conf_data->{'type'};
my $barcodetype = $conf_data->{'barcodetype'};
my $printingtype = $conf_data->{'printingtype'} or die "No printingtype in conf_data";
my $guidebox = $conf_data->{'guidebox'};
my $start_label = $conf_data->{'startlabel'};
if ($cgi->param('startlabel')) {
$start_label = $cgi->param('startlabel'); # A bit of a hack to allow setting the starting label from the address bar... -fbcit
}
warn "Starting on label #$start_label" if $DEBUG;
my $units = $template->{'units'};
if ($printingtype eq 'PATCRD') {
@resultsloop = GetPatronCardItems($batch_id);
} else {
@resultsloop = GetLabelItems($batch_id);
}
#warn "UNITS $units";
#warn "fontsize = $fontsize";
#warn Dumper $template;
my $unitvalue = GetUnitsValue($units);
my $prof_unitvalue = GetUnitsValue($profile->{'unit'});
warn "Template units: $units which converts to $unitvalue PostScript Points" if $DEBUG;
warn "Profile units: $profile->{'unit'} which converts to $prof_unitvalue PostScript Points" if $DEBUG;
my $tmpl_code = $template->{'tmpl_code'};
my $tmpl_desc = $template->{'tmpl_desc'};
my $page_height = ( $template->{'page_height'} * $unitvalue );
my $page_width = ( $template->{'page_width'} * $unitvalue );
my $label_height = ( $template->{'label_height'} * $unitvalue );
my $label_width = ( $template->{'label_width'} * $unitvalue );
my $spine_width = ( $template->{'label_width'} * $unitvalue );
my $circ_width = ( $template->{'label_width'} * $unitvalue );
my $top_margin = ( $template->{'topmargin'} * $unitvalue );
my $left_margin = ( $template->{'leftmargin'} * $unitvalue );
my $colspace = ( $template->{'colgap'} * $unitvalue );
my $rowspace = ( $template->{'rowgap'} * $unitvalue );
warn "Converted dimensions are:" if $DEBUG;
warn "pghth=$page_height, pgwth=$page_width, lblhth=$label_height, lblwth=$label_width, spinwth=$spine_width, circwth=$circ_width, tpmar=$top_margin, lmar=$left_margin, colsp=$colspace, rowsp=$rowspace" if $DEBUG;
my $label_cols = $template->{'cols'};
my $label_rows = $template->{'rows'};
my $margin = $top_margin;
my $left_text_margin = 3; # FIXME: This value should not be hardcoded
my $str;
# Some peritent notes from PDF::Reuse regarding prFont()...
# If a font wasn't found, Helvetica will be set.
# These names are always recognized: Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Courier, Courier-Bold,
# Courier-Oblique, Courier-BoldOblique, Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique
# They can be abbreviated: TR, TB, TI, TBI, C, CB, CO, CBO, H, HB, HO, HBO
my $fontsize = $template->{'fontsize'};
my $fontname = $template->{'font'};
my $text_wrap_cols = GetTextWrapCols( $fontname, $fontsize, $label_width, $left_text_margin );
#warn $label_cols, $label_rows;
# set the paper size
my $lowerLeftX = 0;
my $lowerLeftY = 0;
my $upperRightX = $page_width;
my $upperRightY = $page_height;
my $codetype; # = 'Code39';
warn "Active profile: " . ($profile->{prof_id} || "None") if $DEBUG;
#### PRINT PRELIMINARY DATA ####
print $cgi->header( -type => 'application/pdf', -attachment => 'barcode.pdf' );
# Don't print header until very last possible moment
# That way if error or die occurs, fatals_to_browser will still work.
# After we print this header, there is no way back to HTML. All we can do is deliver PDF.
prInitVars();
$| = 1;
prFile(); # No args means to STDOUT
prCompress(1); # turn on zip compression which dramatically reduces file size
prMbox( $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY );
# drawbox( $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY ); #do page border
# draw margin box for alignment page
drawbox($left_margin, $top_margin, $page_width-(2*$left_margin), $page_height-(2*$top_margin)) if $DEBUG_LPT;
#### TWEAKS and DEBUGGING ###
# Adjustments for image position and creep -fbcit
# NOTE: *All* of these factor in to image position and creep. Keep this in mind when makeing adjustments.
# Suggested proceedure: Adjust margins until both top and left margins are correct. Then adjust the label
# height and width to correct label creep across and down page. Units are PostScript Points (72 per inch).
sub debug_drop {
my $title = @_ || "";
warn "-------------------------$title-----------------------------\n"
. " top margin = $top_margin points\n"
. " left margin = $left_margin points\n"
. "label height = $label_height points\n"
. "label width = $label_width points\n";
}
debug_drop('INITIAL VALUES') if ($DEBUG);
if ( $profile->{'prof_id'} ) {
$top_margin += ($profile->{'offset_vert'} * $prof_unitvalue); # controls vertical offset
$label_height += ($profile->{'creep_vert'} * $prof_unitvalue); # controls vertical creep
$left_margin += ($profile->{'offset_horz'} * $prof_unitvalue); # controls horizontal offset
$label_width += ($profile->{'creep_horz'} * $prof_unitvalue); # controls horizontal creep
}
if ($DEBUG) {
if ($profile->{'prof_id'}) {
debug_drop('ADJUSTED VALUES');
} else {
warn "No profile associated so no adjustment applied.";
}
}
#warn " $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY";
#warn "$label_rows, $label_cols\n";
#warn "$label_height, $label_width\n";
#warn "$page_height, $page_width\n";
my ($rowcount, $colcount, $x_pos, $y_pos, $rowtemp, $coltemp);
if ( $start_label and $start_label == 1 ) {
$rowcount = 1;
$colcount = 1;
$x_pos = $left_margin;
$y_pos = ( $page_height - $top_margin - $label_height );
} else {
$rowcount = ceil( $start_label / $label_cols );
$colcount = ( $start_label - ( ( $rowcount - 1 ) * $label_cols ) );
$x_pos = $left_margin + ( $label_width * ( $colcount - 1 ) ) +
( $colspace * ( $colcount - 1 ) );
$y_pos = $page_height - $top_margin - ( $label_height * $rowcount ) -
( $rowspace * ( $rowcount - 1 ) );
$DEBUG and warn "Start label: $start_label. Beginning in row $rowcount, column $colcount\n"
. "(X,Y) positions = ($x_pos,$y_pos)\n"
. "Rowspace = $rowspace, Label height = $label_height";
}
#
#### main foreach loop ####
#
foreach my $item (@resultsloop) {
warn "Label parameters: xpos=$x_pos, ypos=$y_pos, lblwid=$label_width, lblhig=$label_height" if $DEBUG;
drawbox($x_pos, $y_pos, $label_width, $label_height) if $guidebox; # regardless of printingtype
if ( $printingtype eq 'BAR' ) {
DrawBarcode( $x_pos, $y_pos, $label_height, $label_width, $item->{'barcode'}, $barcodetype );
}
elsif ( $printingtype eq 'BARBIB' ) {
# reposoitioning barcode up the top of label
my $barcode_height = ($label_height / 1.5 ); ## scaling voodoo
my $text_height = $label_height / 2;
my $barcode_y = $y_pos + ( $label_height / 2.5 ); ## scaling voodoo
DrawBarcode( $x_pos, $barcode_y, $barcode_height, $label_width, $item->{'barcode'}, $barcodetype );
DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize,
$left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype );
} # correct
elsif ( $printingtype eq 'BIBBAR' ) {
my $barcode_height = $label_height / 2;
DrawBarcode( $x_pos, $y_pos, $barcode_height, $label_width, $item->{'barcode'}, $barcodetype );
DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize,
$left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype );
}
elsif ( $printingtype eq 'ALT' ) {
DrawBarcode( $x_pos, $y_pos, $label_height, $label_width, $item->{'barcode'}, $barcodetype );
CalcNextLabelPos();
drawbox( $x_pos, $y_pos, $label_width, $label_height ) if $guidebox;
DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize,
$left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype );
}
elsif ( $printingtype eq 'BIB' ) {
DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize,
$left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype );
}
elsif ( $printingtype eq 'PATCRD' ) {
my $patron_data = $item;
#FIXME: This needs to be paramatized and passed in from the user...
#Each element of this hash is a separate line on the patron card. Keys are the text to print and the associated data is the point size.
my $text = {
$patron_data->{'description'} => $fontsize,
$patron_data->{'branchname'} => ($fontsize + 3),
};
$DEBUG and warn "Generating patron card for cardnumber $patron_data->{'cardnumber'}";
my $barcode_height = $label_height / 2.75; #FIXME: Scaling barcode height; this needs to be a user parameter.
DrawBarcode( $x_pos, $y_pos, $barcode_height, $label_width, $patron_data->{'cardnumber'}, $barcodetype );
DrawPatronCardText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize,
$left_text_margin, $text_wrap_cols, $text, $printingtype );
}
else {
die "CANNOT PRINT: Unknown printingtype '$printingtype'";
}
CalcNextLabelPos(); # regardless of printingtype
} # end for item loop
prEnd();
sub CalcNextLabelPos {
if ($colcount < $label_cols) {
# warn "new col";
$x_pos = ( $x_pos + $label_width + $colspace );
$colcount++;
} else {
$x_pos = $left_margin;
if ($rowcount == $label_rows) {
# warn "new page";
prPage();
$y_pos = ( $page_height - $top_margin - $label_height );
$rowcount = 1;
} else {
# warn "new row";
$y_pos = ( $y_pos - $rowspace - $label_height );
$rowcount++;
}
$colcount = 1;
}
}