File indexing completed on 2024-12-22 05:36:29

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Barcode
0017  * @subpackage Renderer
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id: Image.php 20366 2010-01-18 03:56:52Z ralph $
0021  */
0022 
0023 /** @see Zend_Barcode_Renderer_RendererAbstract*/
0024 // require_once 'Zend/Barcode/Renderer/RendererAbstract.php';
0025 
0026 /**
0027  * Class for rendering the barcode as svg
0028  *
0029  * @category   Zend
0030  * @package    Zend_Barcode
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Barcode_Renderer_Svg extends Zend_Barcode_Renderer_RendererAbstract
0035 {
0036 
0037     /**
0038      * Resource for the image
0039      * @var DOMDocument
0040      */
0041     protected $_resource = null;
0042 
0043     /**
0044      * Root element of the XML structure
0045      * @var DOMElement
0046      */
0047     protected $_rootElement = null;
0048 
0049     /**
0050      * Height of the rendered image wanted by user
0051      * @var integer
0052      */
0053     protected $_userHeight = 0;
0054 
0055     /**
0056      * Width of the rendered image wanted by user
0057      * @var integer
0058      */
0059     protected $_userWidth = 0;
0060 
0061     /**
0062      * Set height of the result image
0063      *
0064      * @param null|integer $value
0065      * @return Zend_Image_Barcode_Abstract
0066      * @throws Zend_Barcode_Renderer_Exception
0067      */
0068     public function setHeight($value)
0069     {
0070         if (!is_numeric($value) || intval($value) < 0) {
0071             // require_once 'Zend/Barcode/Renderer/Exception.php';
0072             throw new Zend_Barcode_Renderer_Exception(
0073                 'Svg height must be greater than or equals 0'
0074             );
0075         }
0076         $this->_userHeight = intval($value);
0077         return $this;
0078     }
0079 
0080     /**
0081      * Get barcode height
0082      *
0083      * @return int
0084      */
0085     public function getHeight()
0086     {
0087         return $this->_userHeight;
0088     }
0089 
0090     /**
0091      * Set barcode width
0092      *
0093      * @param mixed $value
0094      * @return self
0095      * @throws Zend_Barcode_Renderer_Exception
0096      */
0097     public function setWidth($value)
0098     {
0099         if (!is_numeric($value) || intval($value) < 0) {
0100             // require_once 'Zend/Barcode/Renderer/Exception.php';
0101             throw new Zend_Barcode_Renderer_Exception(
0102                 'Svg width must be greater than or equals 0'
0103             );
0104         }
0105         $this->_userWidth = intval($value);
0106         return $this;
0107     }
0108 
0109     /**
0110      * Get barcode width
0111      *
0112      * @return int
0113      */
0114     public function getWidth()
0115     {
0116         return $this->_userWidth;
0117     }
0118 
0119     /**
0120      * Set an image resource to draw the barcode inside
0121      *
0122      * @param $svg
0123      * @return Zend_Barcode_Renderer
0124      * @throws Zend_Barcode_Renderer_Exception
0125      */
0126     public function setResource($svg)
0127     {
0128         if (!$svg instanceof DOMDocument) {
0129             // require_once 'Zend/Barcode/Renderer/Exception.php';
0130             throw new Zend_Barcode_Renderer_Exception(
0131                 'Invalid DOMDocument resource provided to setResource()'
0132             );
0133         }
0134         $this->_resource = $svg;
0135         return $this;
0136     }
0137 
0138     /**
0139      * Initialize the image resource
0140      *
0141      * @return void
0142      */
0143     protected function _initRenderer()
0144     {
0145         $barcodeWidth  = $this->_barcode->getWidth(true);
0146         $barcodeHeight = $this->_barcode->getHeight(true);
0147 
0148         $backgroundColor = $this->_barcode->getBackgroundColor();
0149         $imageBackgroundColor = 'rgb(' . implode(', ', array(($backgroundColor & 0xFF0000) >> 16,
0150                                                              ($backgroundColor & 0x00FF00) >> 8,
0151                                                              ($backgroundColor & 0x0000FF))) . ')';
0152 
0153         $width = $barcodeWidth;
0154         $height = $barcodeHeight;
0155         if ($this->_userWidth && $this->_barcode->getType() != 'error') {
0156             $width = $this->_userWidth;
0157         }
0158         if ($this->_userHeight && $this->_barcode->getType() != 'error') {
0159             $height = $this->_userHeight;
0160         }
0161         if ($this->_resource === null) {
0162             $this->_resource = new DOMDocument('1.0', 'utf-8');
0163             $this->_resource->formatOutput = true;
0164             $this->_rootElement = $this->_resource->createElement('svg');
0165             $this->_rootElement->setAttribute('xmlns', "http://www.w3.org/2000/svg");
0166             $this->_rootElement->setAttribute('version', '1.1');
0167             $this->_rootElement->setAttribute('width', $width);
0168             $this->_rootElement->setAttribute('height', $height);
0169 
0170             $this->_appendRootElement('title',
0171                                       array(),
0172                                       "Barcode " . strtoupper($this->_barcode->getType()) . " " . $this->_barcode->getText());
0173         } else {
0174             $this->_readRootElement();
0175             $width = $this->_rootElement->getAttribute('width');
0176             $height = $this->_rootElement->getAttribute('height');
0177         }
0178         $this->_adjustPosition($height, $width);
0179 
0180         $this->_appendRootElement('rect',
0181                           array('x' => $this->_leftOffset,
0182                                 'y' => $this->_topOffset,
0183                                 'width' => ($this->_leftOffset + $barcodeWidth - 1),
0184                                 'height' => ($this->_topOffset + $barcodeHeight - 1),
0185                                 'fill' => $imageBackgroundColor));
0186     }
0187 
0188     protected function _readRootElement()
0189     {
0190         if ($this->_resource !== null) {
0191             $this->_rootElement = $this->_resource->documentElement;
0192         }
0193     }
0194 
0195     /**
0196      * Append a new DOMElement to the root element
0197      *
0198      * @param string $tagName
0199      * @param array $attributes
0200      * @param string $textContent
0201      */
0202     protected function _appendRootElement($tagName, $attributes = array(), $textContent = null)
0203     {
0204         $newElement = $this->_createElement($tagName, $attributes, $textContent);
0205         $this->_rootElement->appendChild($newElement);
0206     }
0207 
0208     /**
0209      * Create DOMElement
0210      *
0211      * @param string $tagName
0212      * @param array $attributes
0213      * @param string $textContent
0214      * @return DOMElement
0215      */
0216     protected function _createElement($tagName, $attributes = array(), $textContent = null)
0217     {
0218         $element = $this->_resource->createElement($tagName);
0219         foreach ($attributes as $k =>$v) {
0220             $element->setAttribute($k, $v);
0221         }
0222         if ($textContent !== null) {
0223             $element->appendChild(new DOMText((string) $textContent));
0224         }
0225         return $element;
0226     }
0227 
0228     /**
0229      * Check barcode parameters
0230      *
0231      * @return void
0232      */
0233     protected function _checkParams()
0234     {
0235         $this->_checkDimensions();
0236     }
0237 
0238     /**
0239      * Check barcode dimensions
0240      *
0241      * @return void
0242      * @throws Zend_Barcode_Renderer_Exception
0243      */
0244     protected function _checkDimensions()
0245     {
0246         if ($this->_resource !== null) {
0247             $this->_readRootElement();
0248             $height = (float) $this->_rootElement->getAttribute('height');
0249             if ($height < $this->_barcode->getHeight(true)) {
0250                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0251                 throw new Zend_Barcode_Renderer_Exception(
0252                     'Barcode is define outside the image (height)'
0253                 );
0254             }
0255         } else {
0256             if ($this->_userHeight) {
0257                 $height = $this->_barcode->getHeight(true);
0258                 if ($this->_userHeight < $height) {
0259                     // require_once 'Zend/Barcode/Renderer/Exception.php';
0260                     throw new Zend_Barcode_Renderer_Exception(sprintf(
0261                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
0262                         $height,
0263                         $this->_userHeight
0264                     ));
0265                 }
0266             }
0267         }
0268         if ($this->_resource !== null) {
0269             $this->_readRootElement();
0270             $width = $this->_rootElement->getAttribute('width');
0271             if ($width < $this->_barcode->getWidth(true)) {
0272                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0273                 throw new Zend_Barcode_Renderer_Exception(
0274                     'Barcode is define outside the image (width)'
0275                 );
0276             }
0277         } else {
0278             if ($this->_userWidth) {
0279                 $width = (float) $this->_barcode->getWidth(true);
0280                 if ($this->_userWidth < $width) {
0281                     // require_once 'Zend/Barcode/Renderer/Exception.php';
0282                     throw new Zend_Barcode_Renderer_Exception(sprintf(
0283                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
0284                         $width,
0285                         $this->_userWidth
0286                     ));
0287                 }
0288             }
0289         }
0290     }
0291 
0292     /**
0293      * Draw the barcode in the rendering resource
0294      * @return mixed
0295      */
0296     public function draw()
0297     {
0298         parent::draw();
0299         $this->_resource->appendChild($this->_rootElement);
0300         return $this->_resource;
0301     }
0302 
0303     /**
0304      * Draw and render the barcode with correct headers
0305      *
0306      * @return mixed
0307      */
0308     public function render()
0309     {
0310         $this->draw();
0311         header("Content-Type: image/svg+xml");
0312         echo $this->_resource->saveXML();
0313     }
0314 
0315     /**
0316      * Draw a polygon in the svg resource
0317      *
0318      * @param array $points
0319      * @param integer $color
0320      * @param boolean $filled
0321      */
0322     protected function _drawPolygon($points, $color, $filled = true)
0323     {
0324         $color = 'rgb(' . implode(', ', array(($color & 0xFF0000) >> 16,
0325                                               ($color & 0x00FF00) >> 8,
0326                                               ($color & 0x0000FF))) . ')';
0327         $orientation = $this->getBarcode()->getOrientation();
0328         $newPoints = array(
0329             $points[0][0] + $this->_leftOffset,
0330             $points[0][1] + $this->_topOffset,
0331             $points[1][0] + $this->_leftOffset,
0332             $points[1][1] + $this->_topOffset,
0333             $points[2][0] + $this->_leftOffset + cos(-$orientation),
0334             $points[2][1] + $this->_topOffset - sin($orientation),
0335             $points[3][0] + $this->_leftOffset + cos(-$orientation),
0336             $points[3][1] + $this->_topOffset - sin($orientation),
0337         );
0338         $newPoints = implode(' ', $newPoints);
0339         $attributes['points'] = $newPoints;
0340         $attributes['fill'] = $color;
0341         $this->_appendRootElement('polygon', $attributes);
0342     }
0343 
0344     /**
0345      * Draw a polygon in the svg resource
0346      *
0347      * @param string    $text
0348      * @param float     $size
0349      * @param array     $position
0350      * @param string    $font
0351      * @param integer   $color
0352      * @param string    $alignment
0353      * @param float|int $orientation
0354      */
0355     protected function _drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0)
0356     {
0357         $color = 'rgb(' . implode(', ', array(($color & 0xFF0000) >> 16,
0358                                               ($color & 0x00FF00) >> 8,
0359                                               ($color & 0x0000FF))) . ')';
0360         $attributes['x'] = $position[0] + $this->_leftOffset;
0361         $attributes['y'] = $position[1] + $this->_topOffset;
0362         //$attributes['font-family'] = $font;
0363         $attributes['color'] = $color;
0364         $attributes['font-size'] = $size * 1.2;
0365         switch ($alignment) {
0366             case 'left':
0367                 $textAnchor = 'start';
0368                 break;
0369             case 'right':
0370                 $textAnchor = 'end';
0371                 break;
0372             case 'center':
0373             default:
0374                 $textAnchor = 'middle';
0375         }
0376         $attributes['style'] = 'text-anchor: ' . $textAnchor;
0377         $attributes['transform'] = 'rotate('
0378                                  . (- $orientation)
0379                                  . ', '
0380                                  . ($position[0] + $this->_leftOffset)
0381                                  . ', ' . ($position[1] + $this->_topOffset)
0382                                  . ')';
0383         $this->_appendRootElement('text', $attributes, $text);
0384     }
0385 }