web/lib/Zend/Barcode/Renderer/Image.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Barcode
       
    17  * @subpackage Renderer
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Image.php 22999 2010-09-23 19:43:14Z mikaelkael $
       
    21  */
       
    22 
       
    23 /** @see Zend_Barcode_Renderer_RendererAbstract*/
       
    24 require_once 'Zend/Barcode/Renderer/RendererAbstract.php';
       
    25 
       
    26 /**
       
    27  * Class for rendering the barcode as image
       
    28  *
       
    29  * @category   Zend
       
    30  * @package    Zend_Barcode
       
    31  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    32  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    33  */
       
    34 class Zend_Barcode_Renderer_Image extends Zend_Barcode_Renderer_RendererAbstract
       
    35 {
       
    36     /**
       
    37      * List of authorized output format
       
    38      * @var array
       
    39      */
       
    40     protected $_allowedImageType = array(
       
    41         'png',
       
    42         'jpeg',
       
    43         'gif',
       
    44     );
       
    45 
       
    46     /**
       
    47      * Image format
       
    48      * @var string
       
    49      */
       
    50     protected $_imageType = 'png';
       
    51 
       
    52     /**
       
    53      * Resource for the image
       
    54      * @var resource
       
    55      */
       
    56     protected $_resource = null;
       
    57 
       
    58     /**
       
    59      * Resource for the font and bars color of the image
       
    60      * @var integer
       
    61      */
       
    62     protected $_imageForeColor = null;
       
    63 
       
    64     /**
       
    65      * Resource for the background color of the image
       
    66      * @var integer
       
    67      */
       
    68     protected $_imageBackgroundColor = null;
       
    69 
       
    70     /**
       
    71      * Height of the rendered image wanted by user
       
    72      * @var integer
       
    73      */
       
    74     protected $_userHeight = 0;
       
    75 
       
    76     /**
       
    77      * Width of the rendered image wanted by user
       
    78      * @var integer
       
    79      */
       
    80     protected $_userWidth = 0;
       
    81 
       
    82     public function __construct($options = null)
       
    83     {
       
    84         if (!function_exists('gd_info')) {
       
    85             require_once 'Zend/Barcode/Renderer/Exception.php';
       
    86             throw new Zend_Barcode_Renderer_Exception('Zend_Barcode_Renderer_Image requires the GD extension');
       
    87         }
       
    88 
       
    89         parent::__construct($options);
       
    90     }
       
    91 
       
    92     /**
       
    93      * Set height of the result image
       
    94      * @param null|integer $value
       
    95      * @return Zend_Image_Barcode_Abstract
       
    96      * @throw Zend_Image_Barcode_Exception
       
    97      */
       
    98     public function setHeight($value)
       
    99     {
       
   100         if (!is_numeric($value) || intval($value) < 0) {
       
   101             require_once 'Zend/Barcode/Renderer/Exception.php';
       
   102             throw new Zend_Barcode_Renderer_Exception(
       
   103                 'Image height must be greater than or equals 0'
       
   104             );
       
   105         }
       
   106         $this->_userHeight = intval($value);
       
   107         return $this;
       
   108     }
       
   109 
       
   110     /**
       
   111      * Get barcode height
       
   112      *
       
   113      * @return int
       
   114      */
       
   115     public function getHeight()
       
   116     {
       
   117         return $this->_userHeight;
       
   118     }
       
   119 
       
   120     /**
       
   121      * Set barcode width
       
   122      *
       
   123      * @param mixed $value
       
   124      * @return void
       
   125      */
       
   126     public function setWidth($value)
       
   127     {
       
   128         if (!is_numeric($value) || intval($value) < 0) {
       
   129             require_once 'Zend/Barcode/Renderer/Exception.php';
       
   130             throw new Zend_Barcode_Renderer_Exception(
       
   131                 'Image width must be greater than or equals 0'
       
   132             );
       
   133         }
       
   134         $this->_userWidth = intval($value);
       
   135         return $this;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Get barcode width
       
   140      *
       
   141      * @return int
       
   142      */
       
   143     public function getWidth()
       
   144     {
       
   145         return $this->_userWidth;
       
   146     }
       
   147 
       
   148     /**
       
   149      * Set an image resource to draw the barcode inside
       
   150      *
       
   151      * @param resource $value
       
   152      * @return Zend_Barcode_Renderer
       
   153      * @throw Zend_Barcode_Renderer_Exception
       
   154      */
       
   155     public function setResource($image)
       
   156     {
       
   157         if (gettype($image) != 'resource' || get_resource_type($image) != 'gd') {
       
   158             require_once 'Zend/Barcode/Renderer/Exception.php';
       
   159             throw new Zend_Barcode_Renderer_Exception(
       
   160                 'Invalid image resource provided to setResource()'
       
   161             );
       
   162         }
       
   163         $this->_resource = $image;
       
   164         return $this;
       
   165     }
       
   166 
       
   167     /**
       
   168      * Set the image type to produce (png, jpeg, gif)
       
   169      *
       
   170      * @param string $value
       
   171      * @return Zend_Barcode_RendererAbstract
       
   172      * @throw Zend_Barcode_Renderer_Exception
       
   173      */
       
   174     public function setImageType($value)
       
   175     {
       
   176         if ($value == 'jpg') {
       
   177             $value = 'jpeg';
       
   178         }
       
   179 
       
   180         if (!in_array($value, $this->_allowedImageType)) {
       
   181             require_once 'Zend/Barcode/Renderer/Exception.php';
       
   182             throw new Zend_Barcode_Renderer_Exception(sprintf(
       
   183                 'Invalid type "%s" provided to setImageType()',
       
   184                 $value
       
   185             ));
       
   186         }
       
   187 
       
   188         $this->_imageType = $value;
       
   189         return $this;
       
   190     }
       
   191 
       
   192     /**
       
   193      * Retrieve the image type to produce
       
   194      *
       
   195      * @return string
       
   196      */
       
   197     public function getImageType()
       
   198     {
       
   199         return $this->_imageType;
       
   200     }
       
   201 
       
   202     /**
       
   203      * Initialize the image resource
       
   204      *
       
   205      * @return void
       
   206      */
       
   207     protected function _initRenderer()
       
   208     {
       
   209         if (!extension_loaded('gd')) {
       
   210             require_once 'Zend/Barcode/Exception.php';
       
   211             $e = new Zend_Barcode_Exception(
       
   212                 'Gd extension must be loaded to render barcode as image'
       
   213             );
       
   214             $e->setIsRenderable(false);
       
   215             throw $e;
       
   216         }
       
   217 
       
   218         $barcodeWidth  = $this->_barcode->getWidth(true);
       
   219         $barcodeHeight = $this->_barcode->getHeight(true);
       
   220 
       
   221         if ($this->_resource !== null) {
       
   222             $foreColor       = $this->_barcode->getForeColor();
       
   223             $backgroundColor = $this->_barcode->getBackgroundColor();
       
   224             $this->_imageBackgroundColor = imagecolorallocate(
       
   225                 $this->_resource,
       
   226                 ($backgroundColor & 0xFF0000) >> 16,
       
   227                 ($backgroundColor & 0x00FF00) >> 8,
       
   228                 $backgroundColor & 0x0000FF
       
   229             );
       
   230             $this->_imageForeColor = imagecolorallocate(
       
   231                 $this->_resource,
       
   232                 ($foreColor & 0xFF0000) >> 16,
       
   233                 ($foreColor & 0x00FF00) >> 8,
       
   234                 $foreColor & 0x0000FF
       
   235             );
       
   236         } else {
       
   237             $width = $barcodeWidth;
       
   238             $height = $barcodeHeight;
       
   239             if ($this->_userWidth && $this->_barcode->getType() != 'error') {
       
   240                 $width = $this->_userWidth;
       
   241             }
       
   242             if ($this->_userHeight && $this->_barcode->getType() != 'error') {
       
   243                 $height = $this->_userHeight;
       
   244             }
       
   245 
       
   246             $foreColor       = $this->_barcode->getForeColor();
       
   247             $backgroundColor = $this->_barcode->getBackgroundColor();
       
   248             $this->_resource = imagecreatetruecolor($width, $height);
       
   249 
       
   250             $this->_imageBackgroundColor = imagecolorallocate(
       
   251                 $this->_resource,
       
   252                 ($backgroundColor & 0xFF0000) >> 16,
       
   253                 ($backgroundColor & 0x00FF00) >> 8,
       
   254                 $backgroundColor & 0x0000FF
       
   255             );
       
   256             $this->_imageForeColor = imagecolorallocate(
       
   257                 $this->_resource,
       
   258                 ($foreColor & 0xFF0000) >> 16,
       
   259                 ($foreColor & 0x00FF00) >> 8,
       
   260                 $foreColor & 0x0000FF
       
   261             );
       
   262             $white = imagecolorallocate($this->_resource, 255, 255, 255);
       
   263             imagefilledrectangle($this->_resource, 0, 0, $width - 1, $height - 1, $white);
       
   264         }
       
   265         $this->_adjustPosition(imagesy($this->_resource), imagesx($this->_resource));
       
   266         imagefilledrectangle(
       
   267             $this->_resource,
       
   268             $this->_leftOffset,
       
   269             $this->_topOffset,
       
   270             $this->_leftOffset + $barcodeWidth - 1,
       
   271             $this->_topOffset + $barcodeHeight - 1,
       
   272             $this->_imageBackgroundColor
       
   273         );
       
   274     }
       
   275 
       
   276     /**
       
   277      * Check barcode parameters
       
   278      *
       
   279      * @return void
       
   280      */
       
   281     protected function _checkParams()
       
   282     {
       
   283         $this->_checkDimensions();
       
   284     }
       
   285 
       
   286     /**
       
   287      * Check barcode dimensions
       
   288      *
       
   289      * @return void
       
   290      */
       
   291     protected function _checkDimensions()
       
   292     {
       
   293         if ($this->_resource !== null) {
       
   294             if (imagesy($this->_resource) < $this->_barcode->getHeight(true)) {
       
   295                 require_once 'Zend/Barcode/Renderer/Exception.php';
       
   296                 throw new Zend_Barcode_Renderer_Exception(
       
   297                     'Barcode is define outside the image (height)'
       
   298                 );
       
   299             }
       
   300         } else {
       
   301             if ($this->_userHeight) {
       
   302                 $height = $this->_barcode->getHeight(true);
       
   303                 if ($this->_userHeight < $height) {
       
   304                     require_once 'Zend/Barcode/Renderer/Exception.php';
       
   305                     throw new Zend_Barcode_Renderer_Exception(sprintf(
       
   306                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
       
   307                         $height,
       
   308                         $this->_userHeight
       
   309                     ));
       
   310                 }
       
   311             }
       
   312         }
       
   313         if ($this->_resource !== null) {
       
   314             if (imagesx($this->_resource) < $this->_barcode->getWidth(true)) {
       
   315                 require_once 'Zend/Barcode/Renderer/Exception.php';
       
   316                 throw new Zend_Barcode_Renderer_Exception(
       
   317                     'Barcode is define outside the image (width)'
       
   318                 );
       
   319             }
       
   320         } else {
       
   321             if ($this->_userWidth) {
       
   322                 $width = $this->_barcode->getWidth(true);
       
   323                 if ($this->_userWidth < $width) {
       
   324                     require_once 'Zend/Barcode/Renderer/Exception.php';
       
   325                     throw new Zend_Barcode_Renderer_Exception(sprintf(
       
   326                         "Barcode is define outside the image (calculated: '%d', provided: '%d')",
       
   327                         $width,
       
   328                         $this->_userWidth
       
   329                     ));
       
   330                 }
       
   331             }
       
   332         }
       
   333     }
       
   334 
       
   335     /**
       
   336      * Draw and render the barcode with correct headers
       
   337      *
       
   338      * @return mixed
       
   339      */
       
   340     public function render()
       
   341     {
       
   342         $this->draw();
       
   343         header("Content-Type: image/" . $this->_imageType);
       
   344         $functionName = 'image' . $this->_imageType;
       
   345         call_user_func($functionName, $this->_resource);
       
   346         @imagedestroy($this->_resource);
       
   347     }
       
   348 
       
   349     /**
       
   350      * Draw a polygon in the image resource
       
   351      *
       
   352      * @param array $points
       
   353      * @param integer $color
       
   354      * @param boolean $filled
       
   355      */
       
   356     protected function _drawPolygon($points, $color, $filled = true)
       
   357     {
       
   358         $newPoints = array(
       
   359             $points[0][0] + $this->_leftOffset,
       
   360             $points[0][1] + $this->_topOffset,
       
   361             $points[1][0] + $this->_leftOffset,
       
   362             $points[1][1] + $this->_topOffset,
       
   363             $points[2][0] + $this->_leftOffset,
       
   364             $points[2][1] + $this->_topOffset,
       
   365             $points[3][0] + $this->_leftOffset,
       
   366             $points[3][1] + $this->_topOffset,
       
   367         );
       
   368 
       
   369         $allocatedColor = imagecolorallocate(
       
   370             $this->_resource,
       
   371             ($color & 0xFF0000) >> 16,
       
   372             ($color & 0x00FF00) >> 8,
       
   373             $color & 0x0000FF
       
   374         );
       
   375 
       
   376         if ($filled) {
       
   377             imagefilledpolygon($this->_resource, $newPoints, 4, $allocatedColor);
       
   378         } else {
       
   379             imagepolygon($this->_resource, $newPoints, 4, $allocatedColor);
       
   380         }
       
   381     }
       
   382 
       
   383     /**
       
   384      * Draw a polygon in the image resource
       
   385      *
       
   386      * @param string $text
       
   387      * @param float $size
       
   388      * @param array $position
       
   389      * @param string $font
       
   390      * @param integer $color
       
   391      * @param string $alignment
       
   392      * @param float $orientation
       
   393      */
       
   394     protected function _drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0)
       
   395     {
       
   396         $allocatedColor = imagecolorallocate(
       
   397             $this->_resource,
       
   398             ($color & 0xFF0000) >> 16,
       
   399             ($color & 0x00FF00) >> 8,
       
   400             $color & 0x0000FF
       
   401         );
       
   402 
       
   403         if ($font == null) {
       
   404             $font = 3;
       
   405         }
       
   406         $position[0] += $this->_leftOffset;
       
   407         $position[1] += $this->_topOffset;
       
   408 
       
   409         if (is_numeric($font)) {
       
   410             if ($orientation) {
       
   411                 /**
       
   412                  * imagestring() doesn't allow orientation, if orientation
       
   413                  * needed: a TTF font is required.
       
   414                  * Throwing an exception here, allow to use automaticRenderError
       
   415                  * to informe user of the problem instead of simply not drawing
       
   416                  * the text
       
   417                  */
       
   418                 require_once 'Zend/Barcode/Renderer/Exception.php';
       
   419                 throw new Zend_Barcode_Renderer_Exception(
       
   420                     'No orientation possible with GD internal font'
       
   421                 );
       
   422             }
       
   423             $fontWidth = imagefontwidth($font);
       
   424             $positionY = $position[1] - imagefontheight($font) + 1;
       
   425             switch ($alignment) {
       
   426                 case 'left':
       
   427                     $positionX = $position[0];
       
   428                     break;
       
   429                 case 'center':
       
   430                     $positionX = $position[0] - ceil(($fontWidth * strlen($text)) / 2);
       
   431                     break;
       
   432                 case 'right':
       
   433                     $positionX = $position[0] - ($fontWidth * strlen($text));
       
   434                     break;
       
   435             }
       
   436             imagestring($this->_resource, $font, $positionX, $positionY, $text, $color);
       
   437         } else {
       
   438 
       
   439             if (!function_exists('imagettfbbox')) {
       
   440                 require_once 'Zend/Barcode/Renderer/Exception.php';
       
   441                 throw new Zend_Barcode_Renderer_Exception(
       
   442                     'A font was provided, but this instance of PHP does not have TTF (FreeType) support'
       
   443                     );
       
   444             }
       
   445 
       
   446             $box = imagettfbbox($size, 0, $font, $text);
       
   447             switch ($alignment) {
       
   448                 case 'left':
       
   449                     $width = 0;
       
   450                     break;
       
   451                 case 'center':
       
   452                     $width = ($box[2] - $box[0]) / 2;
       
   453                     break;
       
   454                 case 'right':
       
   455                     $width = ($box[2] - $box[0]);
       
   456                     break;
       
   457             }
       
   458             imagettftext(
       
   459                 $this->_resource,
       
   460                 $size,
       
   461                 $orientation,
       
   462                 $position[0] - ($width * cos(pi() * $orientation / 180)),
       
   463                 $position[1] + ($width * sin(pi() * $orientation / 180)),
       
   464                 $allocatedColor,
       
   465                 $font,
       
   466                 $text
       
   467             );
       
   468         }
       
   469     }
       
   470 }