_getDefaultOptions(); if (self::$_staticFont !== null) { $this->_font = self::$_staticFont; } if ($options instanceof Zend_Config) { $options = $options->toArray(); } if (is_array($options)) { $this->setOptions($options); } $this->_type = strtolower( substr(get_class($this), strlen($this->_barcodeNamespace) + 1) ); if ($this->_mandatoryChecksum) { $this->_withChecksum = true; $this->_withChecksumInText = true; } } /** * Set default options for particular object */ protected function _getDefaultOptions() { } /** * Set barcode state from options array * * @param array $options * @return $this */ public function setOptions($options) { foreach ($options as $key => $value) { $method = 'set' . $key; if (method_exists($this, $method)) { $this->$method($value); } } return $this; } /** * Set barcode state from config object * * @param Zend_Config $config * @return $this */ public function setConfig(Zend_Config $config) { return $this->setOptions($config->toArray()); } /** * Set barcode namespace for autoloading * * @param string $namespace * @return $this */ public function setBarcodeNamespace($namespace) { $this->_barcodeNamespace = $namespace; return $this; } /** * Retrieve barcode namespace * * @return string */ public function getBarcodeNamespace() { return $this->_barcodeNamespace; } /** * Retrieve type of barcode * * @return string */ public function getType() { return $this->_type; } /** * Set height of the barcode bar * * @param integer $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setBarHeight($value) { if (intval($value) <= 0) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Bar height must be greater than 0' ); } $this->_barHeight = intval($value); return $this; } /** * Get height of the barcode bar * * @return integer */ public function getBarHeight() { return $this->_barHeight; } /** * Set thickness of thin bar * * @param integer $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setBarThinWidth($value) { if (intval($value) <= 0) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Bar width must be greater than 0' ); } $this->_barThinWidth = intval($value); return $this; } /** * Get thickness of thin bar * * @return integer */ public function getBarThinWidth() { return $this->_barThinWidth; } /** * Set thickness of thick bar * * @param integer $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setBarThickWidth($value) { if (intval($value) <= 0) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Bar width must be greater than 0' ); } $this->_barThickWidth = intval($value); return $this; } /** * Get thickness of thick bar * * @return integer */ public function getBarThickWidth() { return $this->_barThickWidth; } /** * Set factor applying to * thinBarWidth - thickBarWidth - barHeight - fontSize * * @param int|float|string|bool $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setFactor($value) { if (floatval($value) <= 0) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Factor must be greater than 0' ); } $this->_factor = floatval($value); return $this; } /** * Get factor applying to * thinBarWidth - thickBarWidth - barHeight - fontSize * * @return integer */ public function getFactor() { return $this->_factor; } /** * Set color of the barcode and text * * @param string $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setForeColor($value) { if (preg_match('`\#[0-9A-F]{6}`', $value)) { $this->_foreColor = hexdec($value); } elseif (is_numeric($value) && $value >= 0 && $value <= 16777125) { $this->_foreColor = intval($value); } else { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Text color must be set as #[0-9A-F]{6}' ); } return $this; } /** * Retrieve color of the barcode and text * * @return unknown */ public function getForeColor() { return $this->_foreColor; } /** * Set the color of the background * * @param integer $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setBackgroundColor($value) { if (preg_match('`\#[0-9A-F]{6}`', $value)) { $this->_backgroundColor = hexdec($value); } elseif (is_numeric($value) && $value >= 0 && $value <= 16777125) { $this->_backgroundColor = intval($value); } else { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Background color must be set as #[0-9A-F]{6}' ); } return $this; } /** * Retrieve background color of the image * * @return integer */ public function getBackgroundColor() { return $this->_backgroundColor; } /** * Activate/deactivate drawing of the bar * * @param boolean $value * @return $this */ public function setWithBorder($value) { $this->_withBorder = (bool) $value; return $this; } /** * Retrieve if border are draw or not * * @return boolean */ public function getWithBorder() { return $this->_withBorder; } /** * Activate/deactivate drawing of the quiet zones * * @param boolean $value * @return $this */ public function setWithQuietZones($value) { $this->_withQuietZones = (bool) $value; return $this; } /** * Retrieve if quiet zones are draw or not * * @return boolean */ public function getWithQuietZones() { return $this->_withQuietZones; } /** * Allow fast inversion of font/bars color and background color * * @return $this */ public function setReverseColor() { $tmp = $this->_foreColor; $this->_foreColor = $this->_backgroundColor; $this->_backgroundColor = $tmp; return $this; } /** * Set orientation of barcode and text * * @param int|float|string|bool $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setOrientation($value) { $value = floatval($value); $this->_orientation = $value - floor($value / 360) * 360; return $this; } /** * Retrieve orientation of barcode and text * * @return float */ public function getOrientation() { return $this->_orientation; } /** * Set text to encode * * @param string $value * @return $this */ public function setText($value) { $this->_text = trim($value); return $this; } /** * Retrieve text to encode * * @return string */ public function getText() { $text = $this->_text; if ($this->_withChecksum) { $text .= $this->getChecksum($this->_text); } return $this->_addLeadingZeros($text); } /** * Automatically add leading zeros if barcode length is fixed * * @param string $text * @param boolean $withoutChecksum * @return string */ protected function _addLeadingZeros($text, $withoutChecksum = false) { if ($this->_barcodeLength && $this->_addLeadingZeros) { $omitChecksum = (int) ($this->_withChecksum && $withoutChecksum); if (is_int($this->_barcodeLength)) { $length = $this->_barcodeLength - $omitChecksum; if (strlen($text) < $length) { $text = str_repeat('0', $length - strlen($text)) . $text; } } else { if ($this->_barcodeLength == 'even') { $text = ((strlen($text) - $omitChecksum) % 2 ? '0' . $text : $text); } } } return $text; } /** * Retrieve text to encode * * @return string */ public function getRawText() { return $this->_text; } /** * Retrieve text to display * * @return string */ public function getTextToDisplay() { if ($this->_withChecksumInText) { return $this->getText(); } else { return $this->_addLeadingZeros($this->_text, true); } } /** * Activate/deactivate drawing of text to encode * * @param boolean $value * @return $this */ public function setDrawText($value) { $this->_drawText = (bool) $value; return $this; } /** * Retrieve if drawing of text to encode is enabled * * @return boolean */ public function getDrawText() { return $this->_drawText; } /** * Activate/deactivate the adjustment of the position * of the characters to the position of the bars * * @param boolean $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setStretchText($value) { $this->_stretchText = (bool) $value; return $this; } /** * Retrieve if the adjustment of the position of the characters * to the position of the bars is enabled * * @return boolean */ public function getStretchText() { return $this->_stretchText; } /** * Activate/deactivate the automatic generation * of the checksum character * added to the barcode text * * @param boolean $value * @return $this */ public function setWithChecksum($value) { if (!$this->_mandatoryChecksum) { $this->_withChecksum = (bool) $value; } return $this; } /** * Retrieve if the checksum character is automatically * added to the barcode text * * @return boolean */ public function getWithChecksum() { return $this->_withChecksum; } /** * Activate/deactivate the automatic generation * of the checksum character * added to the barcode text * * @param boolean $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setWithChecksumInText($value) { if (!$this->_mandatoryChecksum) { $this->_withChecksumInText = (bool) $value; } return $this; } /** * Retrieve if the checksum character is automatically * added to the barcode text * * @return boolean */ public function getWithChecksumInText() { return $this->_withChecksumInText; } /** * Set the font for all instances of barcode * * @param string $font */ public static function setBarcodeFont($font) { if (is_string($font) || (is_int($font) && $font >= 1 && $font <= 5)) { self::$_staticFont = $font; } } /** * Set the font: * - if integer between 1 and 5, use gd built-in fonts * - if string, $value is assumed to be the path to a TTF font * * @param integer|string $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setFont($value) { if (is_int($value) && $value >= 1 && $value <= 5) { if (!extension_loaded('gd')) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'GD extension is required to use numeric font' ); } // Case of numeric font with GD $this->_font = $value; // In this case font size is given by: $this->_fontSize = imagefontheight($value); } elseif (is_string($value)) { $this->_font = $value; } else { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( sprintf( 'Invalid font "%s" provided to setFont()', $value ) ); } return $this; } /** * Retrieve the font * * @return integer|string */ public function getFont() { return $this->_font; } /** * Set the size of the font in case of TTF * * @param float $value * @return $this * @throws Zend_Barcode_Object_Exception */ public function setFontSize($value) { if (is_numeric($this->_font)) { // Case of numeric font with GD return $this; } if (!is_numeric($value)) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Font size must be a numeric value' ); } $this->_fontSize = $value; return $this; } /** * Retrieve the size of the font in case of TTF * * @return float */ public function getFontSize() { return $this->_fontSize; } /** * Quiet zone before first bar * and after the last bar * * @return integer */ public function getQuietZone() { if ($this->_withQuietZones || $this->_mandatoryQuietZones) { return 10 * $this->_barThinWidth * $this->_factor; } else { return 0; } } /** * Add an instruction in the array of instructions * * @param array $instruction */ protected function _addInstruction(array $instruction) { $this->_instructions[] = $instruction; } /** * Retrieve the set of drawing instructions * * @return array */ public function getInstructions() { return $this->_instructions; } /** * Add a polygon drawing instruction in the set of instructions * * @param array $points * @param integer $color * @param boolean $filled */ protected function _addPolygon(array $points, $color = null, $filled = true) { if ($color === null) { $color = $this->_foreColor; } $this->_addInstruction( array( 'type' => 'polygon', 'points' => $points, 'color' => $color, 'filled' => $filled, ) ); } /** * Add a text drawing instruction in the set of instructions * * @param string $text * @param float $size * @param array $position * @param string $font * @param integer $color * @param string $alignment * @param float|int $orientation */ protected function _addText( $text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0 ) { if ($color === null) { $color = $this->_foreColor; } $this->_addInstruction( array( 'type' => 'text', 'text' => $text, 'size' => $size, 'position' => $position, 'font' => $font, 'color' => $color, 'alignment' => $alignment, 'orientation' => $orientation, ) ); } /** * Checking of parameters after all settings * * @return bool */ public function checkParams() { $this->_checkText(); $this->_checkFontAndOrientation(); $this->_checkParams(); return true; } /** * Check if a text is really provided to barcode * * @param string|null $value * @throws Zend_Barcode_Object_Exception */ protected function _checkText($value = null) { if ($value === null) { $value = $this->_text; } if (!strlen($value)) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'A text must be provide to Barcode before drawing' ); } $this->validateText($value); } /** * Check the ratio between the thick and the thin bar * * @param int $min * @param int $max * @throws Zend_Barcode_Object_Exception */ protected function _checkRatio($min = 2, $max = 3) { $ratio = $this->_barThickWidth / $this->_barThinWidth; if (!($ratio >= $min && $ratio <= $max)) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( sprintf( 'Ratio thick/thin bar must be between %0.1f and %0.1f (actual %0.3f)', $min, $max, $ratio ) ); } } /** * Drawing with an angle is just allow TTF font * * @throws Zend_Barcode_Object_Exception */ protected function _checkFontAndOrientation() { if (is_numeric($this->_font) && $this->_orientation != 0) { require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception( 'Only drawing with TTF font allow orientation of the barcode.' ); } } /** * Width of the result image (before any rotation) * * @return integer */ protected function _calculateWidth() { return (int) $this->_withBorder + $this->_calculateBarcodeWidth() + (int) $this->_withBorder; } /** * Calculate the width of the barcode * * @return integer */ abstract protected function _calculateBarcodeWidth(); /** * Height of the result object * * @return int */ protected function _calculateHeight() { return (int) $this->_withBorder * 2 + $this->_calculateBarcodeHeight() + (int) $this->_withBorder * 2; } /** * Height of the barcode * * @return int */ protected function _calculateBarcodeHeight() { $textHeight = 0; $extraHeight = 0; if ($this->_drawText) { $textHeight += $this->_fontSize; $extraHeight = 2; } return ($this->_barHeight + $textHeight) * $this->_factor + $extraHeight; } /** * Get height of the result object * * @param bool $recalculate * @return int */ public function getHeight($recalculate = false) { if ($this->_height === null || $recalculate) { $this->_height = abs( $this->_calculateHeight() * cos( $this->_orientation / 180 * pi() ) ) + abs( $this->_calculateWidth() * sin( $this->_orientation / 180 * pi() ) ); } return $this->_height; } /** * Get width of the result object * * @param bool $recalculate * @return int */ public function getWidth($recalculate = false) { if ($this->_width === null || $recalculate) { $this->_width = abs( $this->_calculateWidth() * cos( $this->_orientation / 180 * pi() ) ) + abs( $this->_calculateHeight() * sin( $this->_orientation / 180 * pi() ) ); } return $this->_width; } /** * Calculate the offset from the left of the object * if an orientation is activated * * @param bool $recalculate * @return float */ public function getOffsetLeft($recalculate = false) { if ($this->_offsetLeft === null || $recalculate) { $this->_offsetLeft = - min(array( 0 * cos( $this->_orientation / 180 * pi()) - 0 * sin( $this->_orientation / 180 * pi()), 0 * cos( $this->_orientation / 180 * pi()) - $this->_calculateBarcodeHeight() * sin( $this->_orientation / 180 * pi()), $this->_calculateBarcodeWidth() * cos( $this->_orientation / 180 * pi()) - $this->_calculateBarcodeHeight() * sin( $this->_orientation / 180 * pi()), $this->_calculateBarcodeWidth() * cos( $this->_orientation / 180 * pi()) - 0 * sin( $this->_orientation / 180 * pi()), )); } return $this->_offsetLeft; } /** * Calculate the offset from the top of the object * if an orientation is activated * * @param bool $recalculate * @return float */ public function getOffsetTop($recalculate = false) { if ($this->_offsetTop === null || $recalculate) { $this->_offsetTop = - min(array( 0 * cos( $this->_orientation / 180 * pi()) + 0 * sin( $this->_orientation / 180 * pi()), $this->_calculateBarcodeHeight() * cos( $this->_orientation / 180 * pi()) + 0 * sin( $this->_orientation / 180 * pi()), $this->_calculateBarcodeHeight() * cos( $this->_orientation / 180 * pi()) + $this->_calculateBarcodeWidth() * sin( $this->_orientation / 180 * pi()), 0 * cos( $this->_orientation / 180 * pi()) + $this->_calculateBarcodeWidth() * sin( $this->_orientation / 180 * pi()), )); } return $this->_offsetTop; } /** * Apply rotation on a point in X/Y dimensions * * @param float $x1 x-position before rotation * @param float $y1 y-position before rotation * @return array Array of two elements corresponding to the new XY point */ protected function _rotate($x1, $y1) { $x2 = $x1 * cos($this->_orientation / 180 * pi()) - $y1 * sin($this->_orientation / 180 * pi()) + $this->getOffsetLeft(); $y2 = $y1 * cos($this->_orientation / 180 * pi()) + $x1 * sin($this->_orientation / 180 * pi()) + $this->getOffsetTop(); return array( intval($x2), intval($y2) ); } /** * Complete drawing of the barcode * * @return array Table of instructions */ public function draw() { $this->checkParams(); $this->_drawBarcode(); $this->_drawBorder(); $this->_drawText(); return $this->getInstructions(); } /** * Draw the barcode */ protected function _drawBarcode() { $barcodeTable = $this->_prepareBarcode(); $this->_preDrawBarcode(); $xpos = (int) $this->_withBorder; $ypos = (int) $this->_withBorder; $point1 = $this->_rotate(0, 0); $point2 = $this->_rotate(0, $this->_calculateHeight() - 1); $point3 = $this->_rotate( $this->_calculateWidth() - 1, $this->_calculateHeight() - 1 ); $point4 = $this->_rotate($this->_calculateWidth() - 1, 0); $this->_addPolygon( array( $point1, $point2, $point3, $point4 ), $this->_backgroundColor ); $xpos += $this->getQuietZone(); $barLength = $this->_barHeight * $this->_factor; foreach ($barcodeTable as $bar) { $width = $bar[1] * $this->_factor; if ($bar[0]) { $point1 = $this->_rotate($xpos, $ypos + $bar[2] * $barLength); $point2 = $this->_rotate($xpos, $ypos + $bar[3] * $barLength); $point3 = $this->_rotate( $xpos + $width - 1, $ypos + $bar[3] * $barLength ); $point4 = $this->_rotate( $xpos + $width - 1, $ypos + $bar[2] * $barLength ); $this->_addPolygon( array( $point1, $point2, $point3, $point4, ) ); } $xpos += $width; } $this->_postDrawBarcode(); } /** * Partial function to draw border */ protected function _drawBorder() { if ($this->_withBorder) { $point1 = $this->_rotate(0, 0); $point2 = $this->_rotate($this->_calculateWidth() - 1, 0); $point3 = $this->_rotate( $this->_calculateWidth() - 1, $this->_calculateHeight() - 1 ); $point4 = $this->_rotate(0, $this->_calculateHeight() - 1); $this->_addPolygon( array( $point1, $point2, $point3, $point4, $point1, ), $this->_foreColor, false ); } } /** * Partial function to draw text */ protected function _drawText() { if ($this->_drawText) { $text = $this->getTextToDisplay(); if ($this->_stretchText) { $textLength = strlen($text); $space = ($this->_calculateWidth() - 2 * $this->getQuietZone()) / $textLength; for ($i = 0; $i < $textLength; $i ++) { $leftPosition = $this->getQuietZone() + $space * ($i + 0.5); $this->_addText( $text{$i}, $this->_fontSize * $this->_factor, $this->_rotate( $leftPosition, (int) $this->_withBorder * 2 + $this->_factor * ($this->_barHeight + $this->_fontSize) + 1 ), $this->_font, $this->_foreColor, 'center', - $this->_orientation ); } } else { $this->_addText( $text, $this->_fontSize * $this->_factor, $this->_rotate( $this->_calculateWidth() / 2, (int) $this->_withBorder * 2 + $this->_factor * ($this->_barHeight + $this->_fontSize) + 1 ), $this->_font, $this->_foreColor, 'center', - $this->_orientation ); } } } /** * Check for invalid characters * * @param string $value Text to be ckecked */ public function validateText($value) { $this->_validateText($value); } /** * Standard validation for most of barcode objects * * @param string $value * @param array $options * @throws Zend_Barcode_Object_Exception */ protected function _validateText($value, $options = array()) { $validatorName = (isset($options['validator'])) ? $options['validator'] : $this->getType(); $validator = new Zend_Validate_Barcode( array( 'adapter' => $validatorName, 'checksum' => false, ) ); $checksumCharacter = ''; $withChecksum = false; if ($this->_mandatoryChecksum) { $checksumCharacter = $this->_substituteChecksumCharacter; $withChecksum = true; } $value = $this->_addLeadingZeros($value, $withChecksum) . $checksumCharacter; if (!$validator->isValid($value)) { $message = implode("\n", $validator->getMessages()); /** * @see Zend_Barcode_Object_Exception */ require_once 'Zend/Barcode/Object/Exception.php'; throw new Zend_Barcode_Object_Exception($message); } } /** * Each child must prepare the barcode and return * a table like array( * 0 => array( * 0 => int (visible(black) or not(white)) * 1 => int (width of the bar) * 2 => float (0->1 position from the top of the beginning of the bar in %) * 3 => float (0->1 position from the top of the end of the bar in %) * ), * 1 => ... * ) * * @return array */ abstract protected function _prepareBarcode(); /** * Checking of parameters after all settings */ abstract protected function _checkParams(); /** * Allow each child to draw something else */ protected function _preDrawBarcode() { } /** * Allow each child to draw something else * (ex: bearer bars in interleaved 2 of 5 code) */ protected function _postDrawBarcode() { } }