diff -r 000000000000 -r 4eba9c11703f web/Zend/Barcode/Object/ObjectAbstract.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/Zend/Barcode/Object/ObjectAbstract.php Mon Dec 13 18:29:26 2010 +0100 @@ -0,0 +1,1317 @@ +_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 + * @return void + */ + protected function _getDefaultOptions() + { + } + + /** + * Set barcode state from options array + * @param array $options + * @return Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + */ + public function setConfig(Zend_Config $config) + { + return $this->setOptions($config->toArray()); + } + + /** + * Set barcode namespace for autoloading + * + * @param string $namespace + * @return Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + * @throw 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 float $value + * @return Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + */ + public function setReverseColor() + { + $tmp = $this->_foreColor; + $this->_foreColor = $this->_backgroundColor; + $this->_backgroundColor = $tmp; + return $this; + } + + /** + * Set orientation of barcode and text + * @param float $value + * @return Zend_Barcode_Object + * @throw Zend_Barcode_Object_Exception + */ + public function setOrientation($value) + { + $this->_orientation = floatval($value) - floor(floatval($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 Zend_Barcode_Object + */ + 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 + */ + 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 Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + */ + 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 Zend_Barcode_Object + * @throw 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 + * @return void + */ + 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 Zend_Barcode_Object + * @throw 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 Zend_Barcode_Object + * @throw 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 $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 void + */ + public function checkParams() + { + $this->_checkText(); + $this->_checkFontAndOrientation(); + $this->_checkParams(); + return true; + } + + /** + * Check if a text is really provided to barcode + * @return void + * @throw 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 integer $min + * @param integer $max + * @return void + * @throw 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 + * @return void + * @throw 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 integer + */ + protected function _calculateHeight() + { + return (int) $this->_withBorder * 2 + + $this->_calculateBarcodeHeight() + + (int) $this->_withBorder * 2; + } + + /** + * Height of the barcode + * @return integer + */ + 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 + * @return integer + */ + 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 + * @return integer + */ + 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 boolean $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 boolean $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 + * @return void + */ + 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 + * @return void + */ + 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 + * @return void + */ + 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 + * @return void + */ + public function validateText($value) + { + $this->_validateText($value); + } + + /** + * Standard validation for most of barcode objects + * @param string $value + * @param array $options + */ + 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 + * + * @return void + */ + abstract protected function _checkParams(); + + /** + * Allow each child to draw something else + * + * @return void + */ + protected function _preDrawBarcode() + { + } + + /** + * Allow each child to draw something else + * (ex: bearer bars in interleaved 2 of 5 code) + * + * @return void + */ + protected function _postDrawBarcode() + { + } +}