PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Barcode/Renderer/Image.php

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