diff --git a/application/libraries/Barcode_lib.php b/application/libraries/Barcode_lib.php
index 9d7f83190..2e07a6d96 100644
--- a/application/libraries/Barcode_lib.php
+++ b/application/libraries/Barcode_lib.php
@@ -1,8 +1,14 @@
'Code 39');
+ var $supported_barcodes = array(1 => 'Code 39', 2 => 'Code 128');
function __construct()
{
@@ -16,6 +22,7 @@ class Barcode_lib
function get_barcode_config()
{
+ $data['barcode_type'] = $this->CI->Appconfig->get('barcode_type');
$data['barcode_font'] = $this->CI->Appconfig->get('barcode_font');
$data['barcode_font_size'] = $this->CI->Appconfig->get('barcode_font_size');
$data['barcode_height'] = $this->CI->Appconfig->get('barcode_height');
@@ -30,17 +37,30 @@ class Barcode_lib
return $data;
}
+ private function generate_barcode($item, $barcode_config)
+ {
+ if ($barcode_config['barcode_type'] == '1')
+ {
+ $barcode = new emberlabs\Barcode\Code39();
+ }
+ else
+ {
+ $barcode = new emberlabs\Barcode\Code128();
+ }
+ $barcode_content = $this->CI->Appconfig->get('barcode_content') === "id" ? $item['item_id'] : $item['item_number'];
+ $barcode->setData($barcode_content);
+ $barcode->setDimensions($barcode_config['barcode_width'], $barcode_config['barcode_height']);
+ $barcode->draw();
+ return $barcode->base64();
+ }
+
function create_display_barcode($item, $barcode_config)
{
+
$display_table = "
";
$display_table .= "| ". $this->manage_display_layout($barcode_config['barcode_first_row'], $item, $barcode_config)." |
";
- $display_table .= " CI->Appconfig->get('barcode_content') === "id" ? $item['item_id'] : $item['item_number']).
- "&quality=".$barcode_config['barcode_quality'].
- "&type=".$this->CI->Appconfig->get('barcode_type').
- "' onerror=\"(function(pThis){pThis.onerror = null; pThis.src = pThis.src;})(this)\" /> |
";
+ $barcode = $this->generate_barcode($item,$barcode_config);
+ $display_table .= " |
";
$display_table .= "| ". $this->manage_display_layout($barcode_config['barcode_second_row'], $item, $barcode_config)." |
";
$display_table .= "| ". $this->manage_display_layout($barcode_config['barcode_third_row'], $item, $barcode_config)." |
";
$display_table .= "
";
diff --git a/application/views/barcodes/BarcodeBase.php b/application/views/barcodes/BarcodeBase.php
new file mode 100644
index 000000000..83ee74ffd
--- /dev/null
+++ b/application/views/barcodes/BarcodeBase.php
@@ -0,0 +1,178 @@
+x = (int) $x;
+ $this->y = (int) $y;
+
+ return $this;
+ }
+
+ /*
+ * Set Quality
+ * @param int q - jpeg quality
+ * @return instance of \emberlabs\Barcode\BarcodeBase
+ */
+ public function setQuality($q)
+ {
+ $this->jpgQuality = (int) $q;
+
+ return $this;
+ }
+
+ /*
+ * Display human readable text below the code
+ * @param boolean enable - Enable the human readable text
+ * @return instance of \emberlabs\Barcode\BarcodeBase
+ */
+ public function enableHumanText($enable = true)
+ {
+ $this->humanText = (boolean) $enable;
+
+ return $this;
+ }
+
+ /*
+ * Output Image to the buffer
+ *
+ * @return void
+ */
+ public function output($type = 'png')
+ {
+ switch($type)
+ {
+ case 'jpg':
+ case 'jpeg':
+ imagejpeg($this->img, NULL, $this->jpgQuality);
+ break;
+
+ case 'gif':
+ imagegif($this->img);
+ break;
+
+ case 'png':
+ default:
+ imagepng($this->img);
+ break;
+ }
+ }
+
+ /*
+ * Save Image
+ *
+ * @param string filename - File to write to (needs to have .png, .gif, or
+ * .jpg extension)
+ * @return void
+ * @throws \RuntimeException - If the file could not be written or some
+ * other I/O error.
+ */
+ public function save($filename)
+ {
+ $type = strtolower(substr(strrchr($filename, '.'), 1));
+
+ switch($type)
+ {
+ case 'jpg':
+ case 'jpeg':
+ imagejpeg($this->img, $filename, $this->jpgQuality);
+ break;
+
+ case 'gif':
+ imagegif($this->img, $filename);
+ break;
+
+ case 'png':
+ imagepng($this->img, $filename);
+ break;
+
+ default:
+ throw new \RuntimeException("Could not determine file type.");
+ break;
+ }
+ }
+
+ /*
+ * Base64 Encoded
+ * For ouput in-page
+ * @return void
+ */
+ public function base64()
+ {
+ ob_start();
+ $this->output();
+
+ return base64_encode(ob_get_clean());
+ }
+}
diff --git a/application/views/barcodes/Code128.php b/application/views/barcodes/Code128.php
new file mode 100644
index 000000000..a721da0dd
--- /dev/null
+++ b/application/views/barcodes/Code128.php
@@ -0,0 +1,323 @@
+', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 39
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', // 49
+ 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', // 59
+ '\\', ']', '^', '_', // 63 (We're going into the weird bytes next)
+
+ // Hex is a little more concise in this context
+ "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", // 69
+ "\x06", "\x07", "\x08", "\x09", "\x0A", "\x0B", // 75
+ "\x0C", "\x0D", "\x0E", "\x0F", "\x10", "\x11", // 81
+ "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", // 87
+ "\x18", "\x19", "\x1A", "\x1B", "\x1C", "\x1D", // 93
+ "\x1E", "\x1F", // 95
+
+ // Now for system codes
+ 'FNC_3', 'FNC_2', 'SHIFT_B', 'CODE_C', 'CODE_B', // 100
+ 'FNC_4', 'FNC_1', 'START_A', 'START_B', 'START_C', // 105
+ 'STOP', // 106
+ );
+
+ /*
+ * Same idea from MapA applied here to B.
+ * @var static array
+ */
+ private static $mapB = array(
+ ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', // 9 (end)
+ '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', // 19
+ '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', // 29
+ '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 39
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', // 49
+ 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', // 59
+ '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', // 69
+ 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 79
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', // 89
+ 'z', '{', '|', '}', '~', "\x7F", // 95
+
+ // Now for system codes
+ 'FNC_3', 'FNC_2', 'SHIFT_A', 'CODE_C', 'FNC_4', // 100
+ 'CODE_A', 'FNC_1', 'START_A', 'START_B', 'START_C', // 105
+ 'STOP', // 106
+ );
+
+ /*
+ * Map C works a little different. The index is the value when the mapping
+ * occors.
+ * @var static array
+ */
+ private static $mapC = array(
+ 100 =>
+ 'CODE_B', 'CODE_A', 'FNC_1', 'START_A', 'START_B',
+ 'START_C', 'STOP', // 106
+ );
+
+ /*
+ * Subtypes
+ */
+ const TYPE_AUTO = 0; // Automatically detect the best code
+ const TYPE_A = 1; // ASCII 00-95 (0-9, A-Z, Control codes, and some special chars)
+ const TYPE_B = 2; // ASCII 32-127 (0-9, A-Z, a-z, special chars)
+ const TYPE_C = 3; // Numbers 00-99 (two digits per code)
+
+ /*
+ * Set the data
+ *
+ * @param mixed data - (int or string) Data to be encoded
+ * @return instance of \emberlabs\Barcode\BarcodeInterface
+ * @return throws \OverflowException
+ */
+ public function setData($data)
+ {
+ $this->data = $data;
+ }
+
+ /*
+ * Set the subtype
+ * Defaults to Autodetect
+ * @param int type - Const flag for the type
+ */
+ public function setSubType($type)
+ {
+ $this->type = ($type < 1 || $type > 3) ? self::TYPE_AUTO : (int) $type;
+ }
+
+ /*
+ * Get they key (value of the character)
+ * @return int - pattern
+ */
+ private function getKey($char)
+ {
+ switch ($this->type)
+ {
+ case self::TYPE_A:
+ return array_search($char, self::$mapA);
+ break;
+
+ case self::TYPE_B:
+ return array_search($char, self::$mapB);
+ break;
+
+ case self::TYPE_C:
+ $charInt = (int) $char;
+ if (strlen($char) == 2 && $charInt <= 99 && $charInt >= 0)
+ {
+ return $charInt;
+ }
+
+ return array_search($char, self::$mapC);
+ break;
+
+ default:
+ $this->resolveSubtype();
+ return $this->getKey($char); // recursion!
+ break;
+ }
+ }
+
+ /*
+ * Get the bar
+ * @return int - pattern
+ */
+ private function getBar($char)
+ {
+ $key = $this->getKey($char);
+
+ return self::$barMap[($key !== false) ? $key : 0];
+ }
+
+ /*
+ * Resolve subtype
+ * @todo - Do some better charset checking and enforcement
+ * @return void
+ */
+ private function resolveSubtype()
+ {
+ if ($this->type == self::TYPE_AUTO)
+ {
+ // If it is purely numeric, this is easy
+ if (is_numeric($this->data))
+ {
+ $this->type = self::TYPE_C;
+ }
+ // Are there only capitals?
+ else if(strtoupper($this->data) == $this->data)
+ {
+ $this->type = self::TYPE_A;
+ }
+ else
+ {
+ $this->type = self::TYPE_B;
+ }
+ }
+ }
+
+ /*
+ * Get the name of a start char fr te current subtype
+ * @return string
+ */
+ private function getStartChar()
+ {
+ $this->resolveSubtype();
+
+ switch($this->type)
+ {
+ case self::TYPE_A: return 'START_A'; break;
+ case self::TYPE_B: return 'START_B'; break;
+ case self::TYPE_C: return 'START_C'; break;
+ }
+ }
+
+ /*
+ * Draw the image
+ *
+ * @return void
+ */
+ public function draw()
+ {
+ $this->resolveSubtype();
+ $charAry = str_split($this->data);
+
+ // Calc scaling
+ // Bars is in refrence to a single, 1-level bar
+ $numBarsRequired = ($this->type != self::TYPE_C) ? (sizeof($charAry) * 11) + 35 : ((sizeof($charAry)/2) * 11) + 35;
+ $this->x = ($this->x == 0) ? $numBarsRequired : $this->x;
+ $pxPerBar = (int) ($this->x / $numBarsRequired);
+ $currentX = ($this->x - ($numBarsRequired * $pxPerBar)) / 2;
+
+ if ($pxPerBar < 1)
+ {
+ throw new \LogicException("Not enough space on this barcode for this message, increase the width of the barcode");
+ }
+
+ if ($this->type == self::TYPE_C)
+ {
+ if (sizeof($charAry) % 2)
+ {
+ array_unshift($charAry, '0');
+ }
+
+ $pairs = '';
+ $newAry = array();
+ foreach($charAry as $k => $char)
+ {
+ if (($k % 2) == 0 && $k != 0)
+ {
+ $newAry[] = $pairs;
+ $pairs = '';
+ }
+
+ $pairs .= $char;
+ }
+
+ $newAry[] = $pairs;
+ $charAry = $newAry;
+ }
+
+ // Add the start
+ array_unshift($charAry, $this->getStartChar());
+
+ // Checksum collector
+ $checkSumCollector = $this->getKey($this->getStartChar());
+
+ $this->img = @imagecreate($this->x, $this->y);
+ $white = imagecolorallocate($this->img, 255, 255, 255);
+ $black = imagecolorallocate($this->img, 0, 0, 0);
+
+ // Print the code
+ foreach($charAry as $k => $char)
+ {
+ $code = $this->getBar($char);
+ $checkSumCollector += $this->getKey($char) * $k; // $k will be 0 for our first
+
+ foreach(str_split((string) $code) as $bit)
+ {
+ imagefilledrectangle($this->img, $currentX, 0, ($currentX + $pxPerBar), ($this->y - 1), (($bit == '1') ? $black : $white));
+ $currentX += $pxPerBar;
+ }
+ }
+
+ $ending[] = self::$barMap[$checkSumCollector % 103];
+ $ending[] = self::$barMap[106]; // STOP.
+
+ foreach($ending as $code)
+ {
+ foreach(str_split((string) $code) as $bit)
+ {
+ imagefilledrectangle($this->img, $currentX, 0, ($currentX + $pxPerBar), ($this->y - 1), (($bit == '1') ? $black : $white));
+ $currentX += $pxPerBar;
+ }
+ }
+ }
+}
diff --git a/application/views/barcodes/Code39.php b/application/views/barcodes/Code39.php
new file mode 100644
index 000000000..18418832a
--- /dev/null
+++ b/application/views/barcodes/Code39.php
@@ -0,0 +1,188 @@
+ '011000100',
+ '$' => '010101000',
+ '%' => '000101010',
+ '*' => '010010100', // Start/stop marker
+ '+' => '010001010',
+ '|' => '010000101',
+ '.' => '110000100',
+ '/' => '010100010',
+ '-' => '010000101',
+ '0' => '000110100',
+ '1' => '100100001',
+ '2' => '001100001',
+ '3' => '101100000',
+ '4' => '000110001',
+ '5' => '100110000',
+ '6' => '001110000',
+ '7' => '000100101',
+ '8' => '100100100',
+ '9' => '001100100',
+ 'A' => '100001001',
+ 'B' => '001001001',
+ 'C' => '101001000',
+ 'D' => '000011001',
+ 'E' => '100011000',
+ 'F' => '001011000',
+ 'G' => '000001101',
+ 'H' => '100001100',
+ 'I' => '001001100',
+ 'J' => '000011100',
+ 'K' => '100000011',
+ 'L' => '001000011',
+ 'M' => '101000010',
+ 'N' => '000010011',
+ 'O' => '100010010',
+ 'P' => '001010010',
+ 'Q' => '000000111',
+ 'R' => '100000110',
+ 'S' => '001000110',
+ 'T' => '000010110',
+ 'U' => '110000001',
+ 'V' => '011000001',
+ 'W' => '111000000',
+ 'X' => '010010001',
+ 'Y' => '110010000',
+ 'Z' => '011010000',
+ );
+
+ /*
+ * const bar proportions
+ */
+ const NARROW_BAR = 20;
+ const WIDE_BAR = 55;
+ const QUIET_BAR = 35;
+
+ /*
+ * Set the data
+ *
+ * @param mixed data - (int or string) Data to be encoded
+ * @return instance of \emberlabs\Barcode\BarcodeInterface
+ * @return throws \OverflowException
+ */
+ public function setData($data)
+ {
+ // I know, lots of junk.
+ $this->data = '*' . strtoupper(ltrim(rtrim(trim($data), '*'), '*')) . '*';
+ }
+
+ /*
+ * Get a binary map value
+ */
+ private function getMap($char)
+ {
+ return self::$binMap[$char] ?: self::$this->binMap[' '];
+ }
+
+ /*
+ * Draw the image
+ *
+ * Based on the implentation PHP Barcode Image Generator v1.0
+ * by Charles J. Scheffold - cs@sid6581.net
+ * It was released into the Public Domain by its creator.
+ *
+ * @return void
+ */
+ public function draw()
+ {
+ $this->img = @imagecreate($this->x, $this->y);
+
+ if (!$this->img)
+ {
+ throw new \RuntimeException("Code39: Image failed to initialize");
+ }
+
+ // Length of data X [ 6 narrow bars + 3 wide bars + A single Quiet stop ] - a single quiet stop
+ $pxPerChar = (strlen($this->data) * ((6 * self::NARROW_BAR) + (3 * self::WIDE_BAR) + self::QUIET_BAR)) - self::QUIET_BAR;
+ $widthQuotient = $this->x / $pxPerChar;
+
+ // Lengths per type
+ $narrowBar = (int) (self::NARROW_BAR * $widthQuotient);
+ $wideBar = (int) (self::WIDE_BAR * $widthQuotient);
+ $quietBar = (int) (self::QUIET_BAR * $widthQuotient);
+
+
+ $imageWidth = (strlen($this->data) * ((6 * $narrowBar) + (3 * $wideBar) + $quietBar)) - $quietBar;
+
+ // Do we have degenerate rectangles?
+ if ($narrowBar < 1 || $wideBar < 1 || $quietBar < 1 || $narrowBar == $quietBar || $narrowBar == $wideBar || $wideBar == $quietBar)
+ {
+ throw new \OverflowException("You need to spcify a bigger width to properly display this barcode");
+ }
+
+ $currentBarX = (int)(($this->x - $imageWidth) / 2);
+ $charAry = str_split($this->data);
+
+ // Grab our colors
+ $white = imagecolorallocate($this->img, 255, 255, 255);
+ $black = imagecolorallocate($this->img, 0, 0, 0);
+ $color = $black;
+
+ foreach($charAry as $_k => $char)
+ {
+ $code = str_split($this->getMap($char));
+ $color = $black;
+
+ foreach($code as $k => $bit)
+ {
+ // Narrow bar
+ if ($bit == '0')
+ {
+ imagefilledrectangle($this->img, $currentBarX, 0, ($currentBarX + $narrowBar), ($this->y - 1), $color);
+ $currentBarX += $narrowBar;
+ }
+ // Wide Bar
+ else if($bit == '1')
+ {
+ imagefilledrectangle($this->img, $currentBarX, 0, ($currentBarX + $wideBar), ($this->y - 1), $color);
+ $currentBarX += $wideBar;
+ }
+
+ $color = ($color == $black) ? $white : $black;
+ }
+
+ // Skip the spacer on the last run
+ if ($_k == (sizeof($charAry) - 1))
+ {
+ break;
+ }
+
+ // Draw spacer
+ imagefilledrectangle($this->img, $currentBarX, 0, ($currentBarX + $quietBar), ($this->y - 1), $white);
+ $currentBarX += $quietBar;
+ }
+ }
+}