2
0
forked from Wavyzz/dolibarr
Files
dolibarr-fork/htdocs/core/lib/barcode.lib.php
Laurent Destailleur 8d206fdfb0 Prepare move to other licence. For the moment all answers for licence
upgrade were not yet received. So we prepare for GPL by uniformizing
licence text keys to GPL-3+. Will move later to AGPL if all answers are
positive.
2013-01-16 15:36:08 +01:00

413 lines
13 KiB
PHP

<?php
/* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004-2010 Folke Ashberg: Some lines of code were inspired from work
* of Folke Ashberg into PHP-Barcode 0.3pl2, available as GPL
* source code at http://www.ashberg.de/bar.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/core/lib/barcode.lib.php
* \brief Set of functions used for barcode generation
* \ingroup core
*/
/* ******************************************************************** */
/* COLORS */
/* ******************************************************************** */
$bar_color=Array(0,0,0);
$bg_color=Array(255,255,255);
$text_color=Array(0,0,0);
/* ******************************************************************** */
/* FONT FILE */
/* ******************************************************************** */
if (defined('DOL_DEFAULT_TTF_BOLD')) $font_loc=constant('DOL_DEFAULT_TTF_BOLD');
// Automatic-Detection of Font if running Windows
// DOL_CHANGE LDR
if (isset($_SERVER['WINDIR']) && @file_exists($_SERVER['WINDIR'])) $font_loc=$_SERVER['WINDIR'].'\Fonts\arialbd.ttf';
if (empty($font_loc)) die('DOL_DEFAULT_TTF_BOLD must de defined with full path to a TTF font.');
/* ******************************************************************** */
/* GENBARCODE */
/* ******************************************************************** */
/* location of 'genbarcode'
* leave blank if you don't have them :(
* genbarcode is needed to render encodings other than EAN-12/EAN-13/ISBN
*/
if (defined('PHP-BARCODE_PATH_COMMAND')) $genbarcode_loc=constant('PHP-BARCODE_PATH_COMMAND');
else $genbarcode_loc = $conf->global->GENBARCODE_LOCATION;
//dol_syslog("genbarcode_loc=".$genbarcode_loc." - env_windows=".$_SERVER['WINDIR']);
/**
* Print barcode
*
* @param string $code Code
* @param string $encoding Encoding
* @param string $scale Scale
* @param string $mode 'png' or 'jpg' ...
*
*
* @return array $bars array('encoding': the encoding which has been used, 'bars': the bars, 'text': text-positioning info)
*/
function barcode_print($code, $encoding="ANY", $scale = 2 ,$mode = "png")
{
// DOLCHANGE LDR Add log
dol_syslog("barcode.lib.php::barcode_print $code $encoding $scale $mode");
$bars=barcode_encode($code,$encoding);
if (! $bars)
{
// DOLCHANGE LDR Return error message instead of array
$error='Bad Value '.$code.' for encoding '.$encoding;
dol_syslog('barcode.lib.php::barcode_print '.$error, LOG_ERR);
return $error;
}
if (! $mode) $mode="png";
//if (preg_match("/^(text|txt|plain)$/i",$mode)) print barcode_outtext($bars['text'],$bars['bars']);
//elseif (preg_match("/^(html|htm)$/i",$mode)) print barcode_outhtml($bars['text'],$bars['bars'], $scale,0, 0);
//else
barcode_outimage($bars['text'], $bars['bars'], $scale, $mode);
return $bars;
}
/**
* Encodes $code with $encoding using genbarcode OR built-in encoder if you don't have genbarcode only EAN-13/ISBN is possible
*
* You can use the following encodings (when you have genbarcode):
* ANY choose best-fit (default)
* EAN 8 or 13 EAN-Code
* UPC 12-digit EAN
* ISBN isbn numbers (still EAN-13)
* 39 code 39
* 128 code 128 (a,b,c: autoselection)
* 128C code 128 (compact form for digits)
* 128B code 128, full printable ascii
* I25 interleaved 2 of 5 (only digits)
* 128RAW Raw code 128 (by Leonid A. Broukhis)
* CBR Codabar (by Leonid A. Broukhis)
* MSI MSI (by Leonid A. Broukhis)
* PLS Plessey (by Leonid A. Broukhis)
*
* @param string $code Code
* @param string $encoding Encoding
* @return array array('encoding': the encoding which has been used, 'bars': the bars, 'text': text-positioning info)
*/
function barcode_encode($code,$encoding)
{
global $genbarcode_loc;
if (
((preg_match("/^ean$/i", $encoding)
&& ( strlen($code)==12 || strlen($code)==13)))
|| (($encoding) && (preg_match("/^isbn$/i", $encoding))
&& (( strlen($code)==9 || strlen($code)==10) ||
(((preg_match("/^978/", $code) && strlen($code)==12) ||
(strlen($code)==13)))))
|| (( !isset($encoding) || !$encoding || (preg_match("/^ANY$/i", $encoding) ))
&& (preg_match("/^[0-9]{12,13}$/", $code)))
)
{
/* use built-in EAN-Encoder */
dol_syslog("barcode.lib.php::barcode_encode Use barcode_encode_ean");
$bars=barcode_encode_ean($code, $encoding);
}
else if (file_exists($genbarcode_loc))
{
/* use genbarcode */
dol_syslog("barcode.lib.php::barcode_encode Use genbarcode ".$genbarcode_loc." code=".$code." encoding=".$encoding);
$bars=barcode_encode_genbarcode($code, $encoding);
}
else
{
print "barcode_encode needs an external programm for encodings other then EAN/ISBN<BR>\n";
print "<UL>\n";
print "<LI>download gnu-barcode from <A href=\"http://www.gnu.org/software/barcode/\">www.gnu.org/software/barcode/</A>\n";
print "<LI>compile and install them\n";
print "<LI>download genbarcode from <A href=\"http://www.ashberg.de/bar/\">www.ashberg.de/bar/</A>\n";
print "<LI>compile and install them\n";
print "<LI>specify path the genbarcode in barcode module setup\n";
print "</UL>\n";
print "<BR>\n";
return false;
}
return $bars;
}
/**
* Calculate EAN sum
*
* @param string $ean EAN to encode
* @return string Sum
*/
function barcode_gen_ean_sum($ean)
{
$even=true; $esum=0; $osum=0;
$ln=strlen($ean)-1;
for ($i=$ln; $i>=0; $i--)
{
if ($even) $esum+=$ean[$i]; else $osum+=$ean[$i];
$even=!$even;
}
return (10-((3*$esum+$osum)%10))%10;
}
/**
* Encode EAN
*
* @param string $ean Code
* @param string $encoding Encoding
* @return array array('encoding': the encoding which has been used, 'bars': the bars, 'text': text-positioning info)
*/
function barcode_encode_ean($ean, $encoding = "EAN-13")
{
$digits=array(3211,2221,2122,1411,1132,1231,1114,1312,1213,3112);
$mirror=array("000000","001011","001101","001110","010011","011001","011100","010101","010110","011010");
$guards=array("9a1a","1a1a1","a1a");
$ean=trim($ean);
if (preg_match("/[^0-9]/i",$ean))
{
return array("text"=>"Invalid EAN-Code");
}
$encoding=strtoupper($encoding);
if ($encoding=="ISBN")
{
if (!preg_match("/^978/", $ean)) $ean="978".$ean;
}
if (preg_match("/^978/", $ean)) $encoding="ISBN";
if (strlen($ean)<12 || strlen($ean)>13)
{
return array("text"=>"Invalid $encoding Code (must have 12/13 numbers)");
}
$ean=substr($ean,0,12);
$eansum=barcode_gen_ean_sum($ean);
$ean.=$eansum;
$line=$guards[0];
for ($i=1;$i<13;$i++)
{
$str=$digits[$ean[$i]];
if ($i<7 && $mirror[$ean[0]][$i-1]==1) $line.=strrev($str); else $line.=$str;
if ($i==6) $line.=$guards[1];
}
$line.=$guards[2];
/* create text */
$pos=0;
$text="";
for ($a=0;$a<13;$a++)
{
if ($a>0) $text.=" ";
$text.="$pos:12:{$ean[$a]}";
if ($a==0) $pos+=12;
else if ($a==6) $pos+=12;
else $pos+=7;
}
return array(
"encoding" => $encoding,
"bars" => $line,
"text" => $text
);
}
/**
* Encode result of genbarcode command
*
* @param string $code Code
* @param string $encoding Encoding
* @return array array('encoding': the encoding which has been used, 'bars': the bars, 'text': text-positioning info)
*/
function barcode_encode_genbarcode($code,$encoding)
{
global $genbarcode_loc;
// Clean parameters
if (preg_match("/^ean$/i", $encoding) && strlen($code)==13) $code=substr($code,0,12);
if (!$encoding) $encoding="ANY";
$encoding=preg_replace("/[\\\|]/", "_", $encoding);
$code=preg_replace("/[\\\|]/", "_", $code);
$command=escapeshellarg($genbarcode_loc);
$paramclear=" \"".str_replace("\"", "\\\"",$code)."\" \"".str_replace("\"", "\\\"",strtoupper($encoding))."\"";
$fullcommandclear=$command." ".$paramclear." 2>&1";
//print $fullcommandclear."<br>\n";
dol_syslog("Run command ".$fullcommandclear);
$fp=popen($fullcommandclear, "r");
if ($fp)
{
$bars=fgets($fp, 1024);
$text=fgets($fp, 1024);
$encoding=fgets($fp, 1024);
pclose($fp);
}
else
{
dol_syslog("barcode.lib.php::barcode_encode_genbarcode failed to run popen ".$fullcommandclear, LOG_ERR);
return false;
}
//var_dump($bars);
$ret=array(
"encoding" => trim($encoding),
"bars" => trim($bars),
"text" => trim($text)
);
//var_dump($ret);
if (!$ret['encoding']) return false;
if (!$ret['bars']) return false;
if (!$ret['text']) return false;
return $ret;
}
/**
* Output image onto standard output, or onto disk if global filebarcode is defined
*
* @param string $text the text-line (<position>:<font-size>:<character> ...)
* @param string $bars where to place the bars (<space-width><bar-width><space-width><bar-width>...)
* @param int $scale scale factor ( 1 < scale < unlimited (scale 50 will produce 5400x300 pixels when using EAN-13!!!))
* @param string $mode png,gif,jpg (default='png')
* @param int $total_y the total height of the image ( default: scale * 60 )
* @param array $space default: $space[top] = 2 * $scale; $space[bottom]= 2 * $scale; $space[left] = 2 * $scale; $space[right] = 2 * $scale;
* @return void
*/
function barcode_outimage($text, $bars, $scale = 1, $mode = "png", $total_y = 0, $space = '')
{
global $bar_color, $bg_color, $text_color;
global $font_loc, $filebarcode;
//print "$text, $bars, $scale, $mode, $total_y, $space, $font_loc, $filebarcode<br>";
//var_dump($text);
//var_dump($bars);
//var_dump($font_loc);
/* set defaults */
if ($scale<1) $scale=2;
$total_y=(int) $total_y;
if ($total_y<1) $total_y=(int) $scale * 60;
if (!$space)
$space=array('top'=>2*$scale,'bottom'=>2*$scale,'left'=>2*$scale,'right'=>2*$scale);
/* count total width */
$xpos=0;
$width=true;
$ln=strlen($bars);
for ($i=0; $i<$ln; $i++)
{
$val=strtolower($bars[$i]);
if ($width)
{
$xpos+=$val*$scale;
$width=false;
continue;
}
if (preg_match("/[a-z]/", $val))
{
/* tall bar */
$val=ord($val)-ord('a')+1;
}
$xpos+=$val*$scale;
$width=true;
}
/* allocate the image */
$total_x=( $xpos )+$space['right']+$space['right'];
$xpos=$space['left'];
if (! function_exists("imagecreate"))
{
print "You don't have the gd2 extension enabled<br>\n";
return "";
}
$im=imagecreate($total_x, $total_y);
/* create two images */
$col_bg=ImageColorAllocate($im,$bg_color[0],$bg_color[1],$bg_color[2]);
$col_bar=ImageColorAllocate($im,$bar_color[0],$bar_color[1],$bar_color[2]);
$col_text=ImageColorAllocate($im,$text_color[0],$text_color[1],$text_color[2]);
$height=round($total_y-($scale*10));
$height2=round($total_y-$space['bottom']);
/* paint the bars */
$width=true;
$ln=strlen($bars);
for ($i=0; $i<$ln; $i++)
{
$val=strtolower($bars[$i]);
if ($width)
{
$xpos+=$val*$scale;
$width=false;
continue;
}
if (preg_match("/[a-z]/", $val))
{
/* tall bar */
$val=ord($val)-ord('a')+1;
$h=$height2;
} else $h=$height;
imagefilledrectangle($im, $xpos, $space['top'], $xpos+($val*$scale)-1, $h, $col_bar);
$xpos+=$val*$scale;
$width=true;
}
$chars=explode(" ", $text);
reset($chars);
while (list($n, $v)=each($chars))
{
if (trim($v))
{
$inf=explode(":", $v);
$fontsize=$scale*($inf[1]/1.8);
$fontheight=$total_y-($fontsize/2.7)+2;
imagettftext($im, $fontsize, 0, $space['left']+($scale*$inf[0])+2, $fontheight, $col_text, $font_loc, $inf[2]);
}
}
/* output the image */
$mode=strtolower($mode);
if ($mode=='jpg' || $mode=='jpeg')
{
header("Content-Type: image/jpeg; name=\"barcode.jpg\"");
imagejpeg($im);
}
else if ($mode=='gif')
{
header("Content-Type: image/gif; name=\"barcode.gif\"");
imagegif($im);
}
else if (! empty($filebarcode)) // To wxrite into afile onto disk
{
imagepng($im,$filebarcode);
}
else
{
header("Content-Type: image/png; name=\"barcode.png\"");
imagepng($im);
}
}
?>