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$
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 image
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_Image extends Zend_Barcode_Renderer_RendererAbstract
0035 {
0036     /**
0037      * List of authorized output format
0038      * @var array
0039      */
0040     protected $_allowedImageType = array(
0041         'png',
0042         'jpeg',
0043         'gif',
0044     );
0045 
0046     /**
0047      * Image format
0048      * @var string
0049      */
0050     protected $_imageType = 'png';
0051 
0052     /**
0053      * Resource for the image
0054      * @var resource
0055      */
0056     protected $_resource = null;
0057 
0058     /**
0059      * Resource for the font and bars color of the image
0060      * @var integer
0061      */
0062     protected $_imageForeColor = null;
0063 
0064     /**
0065      * Resource for the background color of the image
0066      * @var integer
0067      */
0068     protected $_imageBackgroundColor = null;
0069 
0070     /**
0071      * Height of the rendered image wanted by user
0072      * @var integer
0073      */
0074     protected $_userHeight = 0;
0075 
0076     /**
0077      * Width of the rendered image wanted by user
0078      * @var integer
0079      */
0080     protected $_userWidth = 0;
0081 
0082     public function __construct($options = null)
0083     {
0084         if (!function_exists('gd_info')) {
0085             // require_once 'Zend/Barcode/Renderer/Exception.php';
0086             throw new Zend_Barcode_Renderer_Exception('Zend_Barcode_Renderer_Image requires the GD extension');
0087         }
0088 
0089         parent::__construct($options);
0090     }
0091 
0092     /**
0093      * Set height of the result image
0094      *
0095      * @param null|integer $value
0096      * @return Zend_Image_Barcode_Abstract
0097      * @throws Zend_Barcode_Renderer_Exception
0098      */
0099     public function setHeight($value)
0100     {
0101         if (!is_numeric($value) || intval($value) < 0) {
0102             // require_once 'Zend/Barcode/Renderer/Exception.php';
0103             throw new Zend_Barcode_Renderer_Exception(
0104                 'Image height must be greater than or equals 0'
0105             );
0106         }
0107         $this->_userHeight = intval($value);
0108         return $this;
0109     }
0110 
0111     /**
0112      * Get barcode height
0113      *
0114      * @return int
0115      */
0116     public function getHeight()
0117     {
0118         return $this->_userHeight;
0119     }
0120 
0121     /**
0122      * Set barcode width
0123      *
0124      * @param mixed $value
0125      * @return self
0126      * @throws Zend_Barcode_Renderer_Exception
0127      */
0128     public function setWidth($value)
0129     {
0130         if (!is_numeric($value) || intval($value) < 0) {
0131             // require_once 'Zend/Barcode/Renderer/Exception.php';
0132             throw new Zend_Barcode_Renderer_Exception(
0133                 'Image width must be greater than or equals 0'
0134             );
0135         }
0136         $this->_userWidth = intval($value);
0137         return $this;
0138     }
0139 
0140     /**
0141      * Get barcode width
0142      *
0143      * @return int
0144      */
0145     public function getWidth()
0146     {
0147         return $this->_userWidth;
0148     }
0149 
0150     /**
0151      * Set an image resource to draw the barcode inside
0152      *
0153      * @param $image
0154      * @return Zend_Barcode_Renderer
0155      * @throws Zend_Barcode_Renderer_Exception
0156      */
0157     public function setResource($image)
0158     {
0159         if (gettype($image) != 'resource' || get_resource_type($image) != 'gd') {
0160             // require_once 'Zend/Barcode/Renderer/Exception.php';
0161             throw new Zend_Barcode_Renderer_Exception(
0162                 'Invalid image resource provided to setResource()'
0163             );
0164         }
0165         $this->_resource = $image;
0166         return $this;
0167     }
0168 
0169     /**
0170      * Set the image type to produce (png, jpeg, gif)
0171      *
0172      * @param string $value
0173      * @return Zend_Barcode_RendererAbstract
0174      * @throws Zend_Barcode_Renderer_Exception
0175      */
0176     public function setImageType($value)
0177     {
0178         if ($value == 'jpg') {
0179             $value = 'jpeg';
0180         }
0181 
0182         if (!in_array($value, $this->_allowedImageType)) {
0183             // require_once 'Zend/Barcode/Renderer/Exception.php';
0184             throw new Zend_Barcode_Renderer_Exception(sprintf(
0185                 'Invalid type "%s" provided to setImageType()',
0186                 $value
0187             ));
0188         }
0189 
0190         $this->_imageType = $value;
0191         return $this;
0192     }
0193 
0194     /**
0195      * Retrieve the image type to produce
0196      *
0197      * @return string
0198      */
0199     public function getImageType()
0200     {
0201         return $this->_imageType;
0202     }
0203 
0204     /**
0205      * Initialize the image resource
0206      *
0207      * @return void
0208      * @throws Zend_Barcode_Exception
0209      */
0210     protected function _initRenderer()
0211     {
0212         if (!extension_loaded('gd')) {
0213             // require_once 'Zend/Barcode/Exception.php';
0214             $e = new Zend_Barcode_Exception(
0215                 'Gd extension must be loaded to render barcode as image'
0216             );
0217             $e->setIsRenderable(false);
0218             throw $e;
0219         }
0220 
0221         $barcodeWidth  = $this->_barcode->getWidth(true);
0222         $barcodeHeight = $this->_barcode->getHeight(true);
0223 
0224         if ($this->_resource !== null) {
0225             $foreColor       = $this->_barcode->getForeColor();
0226             $backgroundColor = $this->_barcode->getBackgroundColor();
0227             $this->_imageBackgroundColor = imagecolorallocate(
0228                 $this->_resource,
0229                 ($backgroundColor & 0xFF0000) >> 16,
0230                 ($backgroundColor & 0x00FF00) >> 8,
0231                 $backgroundColor & 0x0000FF
0232             );
0233             $this->_imageForeColor = imagecolorallocate(
0234                 $this->_resource,
0235                 ($foreColor & 0xFF0000) >> 16,
0236                 ($foreColor & 0x00FF00) >> 8,
0237                 $foreColor & 0x0000FF
0238             );
0239         } else {
0240             $width = $barcodeWidth;
0241             $height = $barcodeHeight;
0242             if ($this->_userWidth && $this->_barcode->getType() != 'error') {
0243                 $width = $this->_userWidth;
0244             }
0245             if ($this->_userHeight && $this->_barcode->getType() != 'error') {
0246                 $height = $this->_userHeight;
0247             }
0248 
0249             $foreColor       = $this->_barcode->getForeColor();
0250             $backgroundColor = $this->_barcode->getBackgroundColor();
0251             $this->_resource = imagecreatetruecolor($width, $height);
0252 
0253             $this->_imageBackgroundColor = imagecolorallocate(
0254                 $this->_resource,
0255                 ($backgroundColor & 0xFF0000) >> 16,
0256                 ($backgroundColor & 0x00FF00) >> 8,
0257                 $backgroundColor & 0x0000FF
0258             );
0259             $this->_imageForeColor = imagecolorallocate(
0260                 $this->_resource,
0261                 ($foreColor & 0xFF0000) >> 16,
0262                 ($foreColor & 0x00FF00) >> 8,
0263                 $foreColor & 0x0000FF
0264             );
0265             $white = imagecolorallocate($this->_resource, 255, 255, 255);
0266             imagefilledrectangle($this->_resource, 0, 0, $width - 1, $height - 1, $white);
0267         }
0268         $this->_adjustPosition(imagesy($this->_resource), imagesx($this->_resource));
0269         imagefilledrectangle(
0270             $this->_resource,
0271             $this->_leftOffset,
0272             $this->_topOffset,
0273             $this->_leftOffset + $barcodeWidth - 1,
0274             $this->_topOffset + $barcodeHeight - 1,
0275             $this->_imageBackgroundColor
0276         );
0277     }
0278 
0279     /**
0280      * Check barcode parameters
0281      *
0282      * @return void
0283      */
0284     protected function _checkParams()
0285     {
0286         $this->_checkDimensions();
0287     }
0288 
0289     /**
0290      * Check barcode dimensions
0291      *
0292      * @return void
0293      * @throws Zend_Barcode_Renderer_Exception
0294      */
0295     protected function _checkDimensions()
0296     {
0297         if ($this->_resource !== null) {
0298             if (imagesy($this->_resource) < $this->_barcode->getHeight(true)) {
0299                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0300                 throw new Zend_Barcode_Renderer_Exception(
0301                     'Barcode is define outside the image (height)'
0302                 );
0303             }
0304         } else {
0305             if ($this->_userHeight) {
0306                 $height = $this->_barcode->getHeight(true);
0307                 if ($this->_userHeight < $height) {
0308                     // require_once 'Zend/Barcode/Renderer/Exception.php';
0309                     throw new Zend_Barcode_Renderer_Exception(sprintf(
0310                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
0311                         $height,
0312                         $this->_userHeight
0313                     ));
0314                 }
0315             }
0316         }
0317         if ($this->_resource !== null) {
0318             if (imagesx($this->_resource) < $this->_barcode->getWidth(true)) {
0319                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0320                 throw new Zend_Barcode_Renderer_Exception(
0321                     'Barcode is define outside the image (width)'
0322                 );
0323             }
0324         } else {
0325             if ($this->_userWidth) {
0326                 $width = $this->_barcode->getWidth(true);
0327                 if ($this->_userWidth < $width) {
0328                     // require_once 'Zend/Barcode/Renderer/Exception.php';
0329                     throw new Zend_Barcode_Renderer_Exception(sprintf(
0330                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
0331                         $width,
0332                         $this->_userWidth
0333                     ));
0334                 }
0335             }
0336         }
0337     }
0338 
0339     /**
0340      * Draw and render the barcode with correct headers
0341      *
0342      * @return mixed
0343      */
0344     public function render()
0345     {
0346         $this->draw();
0347         header("Content-Type: image/" . $this->_imageType);
0348         $functionName = 'image' . $this->_imageType;
0349         call_user_func($functionName, $this->_resource);
0350         @imagedestroy($this->_resource);
0351     }
0352 
0353     /**
0354      * Draw a polygon in the image resource
0355      *
0356      * @param array $points
0357      * @param integer $color
0358      * @param boolean $filled
0359      */
0360     protected function _drawPolygon($points, $color, $filled = true)
0361     {
0362         $newPoints = array(
0363             $points[0][0] + $this->_leftOffset,
0364             $points[0][1] + $this->_topOffset,
0365             $points[1][0] + $this->_leftOffset,
0366             $points[1][1] + $this->_topOffset,
0367             $points[2][0] + $this->_leftOffset,
0368             $points[2][1] + $this->_topOffset,
0369             $points[3][0] + $this->_leftOffset,
0370             $points[3][1] + $this->_topOffset,
0371         );
0372 
0373         $allocatedColor = imagecolorallocate(
0374             $this->_resource,
0375             ($color & 0xFF0000) >> 16,
0376             ($color & 0x00FF00) >> 8,
0377             $color & 0x0000FF
0378         );
0379 
0380         if ($filled) {
0381             imagefilledpolygon($this->_resource, $newPoints, 4, $allocatedColor);
0382         } else {
0383             imagepolygon($this->_resource, $newPoints, 4, $allocatedColor);
0384         }
0385     }
0386 
0387     /**
0388      * Draw a polygon in the image resource
0389      *
0390      * @param string    $text
0391      * @param float     $size
0392      * @param array     $position
0393      * @param string    $font
0394      * @param integer   $color
0395      * @param string    $alignment
0396      * @param float|int $orientation
0397      * @throws Zend_Barcode_Renderer_Exception
0398      */
0399     protected function _drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0)
0400     {
0401         $allocatedColor = imagecolorallocate(
0402             $this->_resource,
0403             ($color & 0xFF0000) >> 16,
0404             ($color & 0x00FF00) >> 8,
0405             $color & 0x0000FF
0406         );
0407 
0408         if ($font == null) {
0409             $font = 3;
0410         }
0411         $position[0] += $this->_leftOffset;
0412         $position[1] += $this->_topOffset;
0413 
0414         if (is_numeric($font)) {
0415             if ($orientation) {
0416                 /**
0417                  * imagestring() doesn't allow orientation, if orientation
0418                  * needed: a TTF font is required.
0419                  * Throwing an exception here, allow to use automaticRenderError
0420                  * to informe user of the problem instead of simply not drawing
0421                  * the text
0422                  */
0423                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0424                 throw new Zend_Barcode_Renderer_Exception(
0425                     'No orientation possible with GD internal font'
0426                 );
0427             }
0428             $fontWidth = imagefontwidth($font);
0429             $positionY = $position[1] - imagefontheight($font) + 1;
0430             switch ($alignment) {
0431                 case 'left':
0432                     $positionX = $position[0];
0433                     break;
0434                 case 'center':
0435                     $positionX = $position[0] - ceil(($fontWidth * strlen($text)) / 2);
0436                     break;
0437                 case 'right':
0438                     $positionX = $position[0] - ($fontWidth * strlen($text));
0439                     break;
0440             }
0441             imagestring($this->_resource, $font, $positionX, $positionY, $text, $color);
0442         } else {
0443 
0444             if (!function_exists('imagettfbbox')) {
0445                 // require_once 'Zend/Barcode/Renderer/Exception.php';
0446                 throw new Zend_Barcode_Renderer_Exception(
0447                     'A font was provided, but this instance of PHP does not have TTF (FreeType) support'
0448                     );
0449             }
0450 
0451             $box = imagettfbbox($size, 0, $font, $text);
0452             switch ($alignment) {
0453                 case 'left':
0454                     $width = 0;
0455                     break;
0456                 case 'center':
0457                     $width = ($box[2] - $box[0]) / 2;
0458                     break;
0459                 case 'right':
0460                     $width = ($box[2] - $box[0]);
0461                     break;
0462             }
0463             imagettftext(
0464                 $this->_resource,
0465                 $size,
0466                 $orientation,
0467                 $position[0] - ($width * cos(pi() * $orientation / 180)),
0468                 $position[1] + ($width * sin(pi() * $orientation / 180)),
0469                 $allocatedColor,
0470                 $font,
0471                 $text
0472             );
0473         }
0474     }
0475 }