ObjectAbstract.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  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 Object
  18. * @copyright Copyright (c) 2005-2015 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. * Class for generate Barcode
  24. *
  25. * @category Zend
  26. * @package Zend_Barcode
  27. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  28. * @license http://framework.zend.com/license/new-bsd New BSD License
  29. */
  30. abstract class Zend_Barcode_Object_ObjectAbstract
  31. {
  32. /**
  33. * Namespace of the barcode for autoloading
  34. *
  35. * @var string
  36. */
  37. protected $_barcodeNamespace = 'Zend_Barcode_Object';
  38. /**
  39. * Set of drawing instructions
  40. *
  41. * @var array
  42. */
  43. protected $_instructions = array();
  44. /**
  45. * Barcode type
  46. *
  47. * @var string
  48. */
  49. protected $_type = null;
  50. /**
  51. * Height of the object
  52. *
  53. * @var integer
  54. */
  55. protected $_height = null;
  56. /**
  57. * Width of the object
  58. *
  59. * @var integer
  60. */
  61. protected $_width = null;
  62. /**
  63. * Height of the bar
  64. *
  65. * @var integer
  66. */
  67. protected $_barHeight = 50;
  68. /**
  69. * Width of a thin bar
  70. *
  71. * @var integer
  72. */
  73. protected $_barThinWidth = 1;
  74. /**
  75. * Width of a thick bar
  76. *
  77. * @var integer
  78. */
  79. protected $_barThickWidth = 3;
  80. /**
  81. * Factor to multiply bar and font measure
  82. * (barHeight, barThinWidth, barThickWidth & fontSize)
  83. *
  84. * @var integer
  85. */
  86. protected $_factor = 1;
  87. /**
  88. * Font and bars color of the object
  89. *
  90. * @var integer
  91. */
  92. protected $_foreColor = 0x000000;
  93. /**
  94. * Background color of the object
  95. *
  96. * @var integer
  97. */
  98. protected $_backgroundColor = 0xFFFFFF;
  99. /**
  100. * Activate/deactivate border of the object
  101. *
  102. * @var boolean
  103. */
  104. protected $_withBorder = false;
  105. /**
  106. * Activate/deactivate drawing of quiet zones
  107. *
  108. * @var boolean
  109. */
  110. protected $_withQuietZones = true;
  111. /**
  112. * Force quiet zones even if
  113. *
  114. * @var boolean
  115. */
  116. protected $_mandatoryQuietZones = false;
  117. /**
  118. * Orientation of the barcode in degrees
  119. *
  120. * @var float
  121. */
  122. protected $_orientation = 0;
  123. /**
  124. * Offset from the top the object
  125. * (calculated from the orientation)
  126. *
  127. * @var integer
  128. */
  129. protected $_offsetTop = null;
  130. /**
  131. * Offset from the left the object
  132. * (calculated from the orientation)
  133. *
  134. * @var integer
  135. */
  136. protected $_offsetLeft = null;
  137. /**
  138. * Text to display
  139. *
  140. * @var string
  141. */
  142. protected $_text = null;
  143. /**
  144. * Display (or not) human readable text
  145. *
  146. * @var boolean
  147. */
  148. protected $_drawText = true;
  149. /**
  150. * Adjust (or not) position of human readable characters with barcode
  151. *
  152. * @var boolean
  153. */
  154. protected $_stretchText = false;
  155. /**
  156. * Font resource
  157. * - integer (1 to 5): corresponds to GD included fonts
  158. * - string: corresponds to path of a TTF font
  159. *
  160. * @var integer|string
  161. */
  162. protected $_font = null;
  163. /**
  164. * Font size
  165. *
  166. * @var float
  167. */
  168. protected $_fontSize = 10;
  169. /**
  170. * Drawing of checksum
  171. *
  172. * @var boolean
  173. */
  174. protected $_withChecksum = false;
  175. /**
  176. * Drawing of checksum inside text
  177. *
  178. * @var boolean
  179. */
  180. protected $_withChecksumInText = false;
  181. /**
  182. * Fix barcode length (numeric or string like 'even')
  183. *
  184. * @var $_barcodeLength integer | string
  185. */
  186. protected $_barcodeLength = null;
  187. /**
  188. * Activate automatic addition of leading zeros
  189. * if barcode length is fixed
  190. *
  191. * @var $_addLeadingZeros boolean
  192. */
  193. protected $_addLeadingZeros = true;
  194. /**
  195. * Activation of mandatory checksum
  196. * to deactivate unauthorized modification
  197. *
  198. * @var $_mandatoryChecksum boolean
  199. */
  200. protected $_mandatoryChecksum = false;
  201. /**
  202. * Character used to substitute checksum character for validation
  203. *
  204. * @var $_substituteChecksumCharacter mixed
  205. */
  206. protected $_substituteChecksumCharacter = 0;
  207. /**
  208. * TTF font name: can be set before instanciation of the object
  209. *
  210. * @var string
  211. */
  212. protected static $_staticFont = null;
  213. /**
  214. * Constructor
  215. *
  216. * @param array|Zend_Config $options
  217. */
  218. public function __construct($options = null)
  219. {
  220. $this->_getDefaultOptions();
  221. if (self::$_staticFont !== null) {
  222. $this->_font = self::$_staticFont;
  223. }
  224. if ($options instanceof Zend_Config) {
  225. $options = $options->toArray();
  226. }
  227. if (is_array($options)) {
  228. $this->setOptions($options);
  229. }
  230. $this->_type = strtolower(substr(get_class($this), strlen($this->_barcodeNamespace) + 1));
  231. if ($this->_mandatoryChecksum) {
  232. $this->_withChecksum = true;
  233. $this->_withChecksumInText = true;
  234. }
  235. }
  236. /**
  237. * Set default options for particular object
  238. */
  239. protected function _getDefaultOptions()
  240. {
  241. }
  242. /**
  243. * Set barcode state from options array
  244. *
  245. * @param array $options
  246. * @return $this
  247. */
  248. public function setOptions($options)
  249. {
  250. foreach ($options as $key => $value) {
  251. $method = 'set' . $key;
  252. if (method_exists($this, $method)) {
  253. $this->$method($value);
  254. }
  255. }
  256. return $this;
  257. }
  258. /**
  259. * Set barcode state from config object
  260. *
  261. * @param Zend_Config $config
  262. * @return $this
  263. */
  264. public function setConfig(Zend_Config $config)
  265. {
  266. return $this->setOptions($config->toArray());
  267. }
  268. /**
  269. * Set barcode namespace for autoloading
  270. *
  271. * @param string $namespace
  272. * @return $this
  273. */
  274. public function setBarcodeNamespace($namespace)
  275. {
  276. $this->_barcodeNamespace = $namespace;
  277. return $this;
  278. }
  279. /**
  280. * Retrieve barcode namespace
  281. *
  282. * @return string
  283. */
  284. public function getBarcodeNamespace()
  285. {
  286. return $this->_barcodeNamespace;
  287. }
  288. /**
  289. * Retrieve type of barcode
  290. *
  291. * @return string
  292. */
  293. public function getType()
  294. {
  295. return $this->_type;
  296. }
  297. /**
  298. * Set height of the barcode bar
  299. *
  300. * @param integer $value
  301. * @return $this
  302. * @throws Zend_Barcode_Object_Exception
  303. */
  304. public function setBarHeight($value)
  305. {
  306. if (intval($value) <= 0) {
  307. require_once 'Zend/Barcode/Object/Exception.php';
  308. throw new Zend_Barcode_Object_Exception(
  309. 'Bar height must be greater than 0'
  310. );
  311. }
  312. $this->_barHeight = intval($value);
  313. return $this;
  314. }
  315. /**
  316. * Get height of the barcode bar
  317. *
  318. * @return integer
  319. */
  320. public function getBarHeight()
  321. {
  322. return $this->_barHeight;
  323. }
  324. /**
  325. * Set thickness of thin bar
  326. *
  327. * @param integer $value
  328. * @return $this
  329. * @throws Zend_Barcode_Object_Exception
  330. */
  331. public function setBarThinWidth($value)
  332. {
  333. if (intval($value) <= 0) {
  334. require_once 'Zend/Barcode/Object/Exception.php';
  335. throw new Zend_Barcode_Object_Exception(
  336. 'Bar width must be greater than 0'
  337. );
  338. }
  339. $this->_barThinWidth = intval($value);
  340. return $this;
  341. }
  342. /**
  343. * Get thickness of thin bar
  344. *
  345. * @return integer
  346. */
  347. public function getBarThinWidth()
  348. {
  349. return $this->_barThinWidth;
  350. }
  351. /**
  352. * Set thickness of thick bar
  353. *
  354. * @param integer $value
  355. * @return $this
  356. * @throws Zend_Barcode_Object_Exception
  357. */
  358. public function setBarThickWidth($value)
  359. {
  360. if (intval($value) <= 0) {
  361. require_once 'Zend/Barcode/Object/Exception.php';
  362. throw new Zend_Barcode_Object_Exception(
  363. 'Bar width must be greater than 0'
  364. );
  365. }
  366. $this->_barThickWidth = intval($value);
  367. return $this;
  368. }
  369. /**
  370. * Get thickness of thick bar
  371. *
  372. * @return integer
  373. */
  374. public function getBarThickWidth()
  375. {
  376. return $this->_barThickWidth;
  377. }
  378. /**
  379. * Set factor applying to
  380. * thinBarWidth - thickBarWidth - barHeight - fontSize
  381. *
  382. * @param int|float|string|bool $value
  383. * @return $this
  384. * @throws Zend_Barcode_Object_Exception
  385. */
  386. public function setFactor($value)
  387. {
  388. if (floatval($value) <= 0) {
  389. require_once 'Zend/Barcode/Object/Exception.php';
  390. throw new Zend_Barcode_Object_Exception(
  391. 'Factor must be greater than 0'
  392. );
  393. }
  394. $this->_factor = floatval($value);
  395. return $this;
  396. }
  397. /**
  398. * Get factor applying to
  399. * thinBarWidth - thickBarWidth - barHeight - fontSize
  400. *
  401. * @return integer
  402. */
  403. public function getFactor()
  404. {
  405. return $this->_factor;
  406. }
  407. /**
  408. * Set color of the barcode and text
  409. *
  410. * @param string $value
  411. * @return $this
  412. * @throws Zend_Barcode_Object_Exception
  413. */
  414. public function setForeColor($value)
  415. {
  416. if (preg_match('`\#[0-9A-F]{6}`', $value)) {
  417. $this->_foreColor = hexdec($value);
  418. } elseif (is_numeric($value) && $value >= 0 && $value <= 16777125) {
  419. $this->_foreColor = intval($value);
  420. } else {
  421. require_once 'Zend/Barcode/Object/Exception.php';
  422. throw new Zend_Barcode_Object_Exception(
  423. 'Text color must be set as #[0-9A-F]{6}'
  424. );
  425. }
  426. return $this;
  427. }
  428. /**
  429. * Retrieve color of the barcode and text
  430. *
  431. * @return unknown
  432. */
  433. public function getForeColor()
  434. {
  435. return $this->_foreColor;
  436. }
  437. /**
  438. * Set the color of the background
  439. *
  440. * @param integer $value
  441. * @return $this
  442. * @throws Zend_Barcode_Object_Exception
  443. */
  444. public function setBackgroundColor($value)
  445. {
  446. if (preg_match('`\#[0-9A-F]{6}`', $value)) {
  447. $this->_backgroundColor = hexdec($value);
  448. } elseif (is_numeric($value) && $value >= 0 && $value <= 16777125) {
  449. $this->_backgroundColor = intval($value);
  450. } else {
  451. require_once 'Zend/Barcode/Object/Exception.php';
  452. throw new Zend_Barcode_Object_Exception(
  453. 'Background color must be set as #[0-9A-F]{6}'
  454. );
  455. }
  456. return $this;
  457. }
  458. /**
  459. * Retrieve background color of the image
  460. *
  461. * @return integer
  462. */
  463. public function getBackgroundColor()
  464. {
  465. return $this->_backgroundColor;
  466. }
  467. /**
  468. * Activate/deactivate drawing of the bar
  469. *
  470. * @param boolean $value
  471. * @return $this
  472. */
  473. public function setWithBorder($value)
  474. {
  475. $this->_withBorder = (bool) $value;
  476. return $this;
  477. }
  478. /**
  479. * Retrieve if border are draw or not
  480. *
  481. * @return boolean
  482. */
  483. public function getWithBorder()
  484. {
  485. return $this->_withBorder;
  486. }
  487. /**
  488. * Activate/deactivate drawing of the quiet zones
  489. *
  490. * @param boolean $value
  491. * @return $this
  492. */
  493. public function setWithQuietZones($value)
  494. {
  495. $this->_withQuietZones = (bool) $value;
  496. return $this;
  497. }
  498. /**
  499. * Retrieve if quiet zones are draw or not
  500. *
  501. * @return boolean
  502. */
  503. public function getWithQuietZones()
  504. {
  505. return $this->_withQuietZones;
  506. }
  507. /**
  508. * Allow fast inversion of font/bars color and background color
  509. *
  510. * @return $this
  511. */
  512. public function setReverseColor()
  513. {
  514. $tmp = $this->_foreColor;
  515. $this->_foreColor = $this->_backgroundColor;
  516. $this->_backgroundColor = $tmp;
  517. return $this;
  518. }
  519. /**
  520. * Set orientation of barcode and text
  521. *
  522. * @param int|float|string|bool $value
  523. * @return $this
  524. * @throws Zend_Barcode_Object_Exception
  525. */
  526. public function setOrientation($value)
  527. {
  528. $this->_orientation = floatval($value) - floor(floatval($value) / 360) * 360;
  529. return $this;
  530. }
  531. /**
  532. * Retrieve orientation of barcode and text
  533. *
  534. * @return float
  535. */
  536. public function getOrientation()
  537. {
  538. return $this->_orientation;
  539. }
  540. /**
  541. * Set text to encode
  542. *
  543. * @param string $value
  544. * @return $this
  545. */
  546. public function setText($value)
  547. {
  548. $this->_text = trim($value);
  549. return $this;
  550. }
  551. /**
  552. * Retrieve text to encode
  553. *
  554. * @return string
  555. */
  556. public function getText()
  557. {
  558. $text = $this->_text;
  559. if ($this->_withChecksum) {
  560. $text .= $this->getChecksum($this->_text);
  561. }
  562. return $this->_addLeadingZeros($text);
  563. }
  564. /**
  565. * Automatically add leading zeros if barcode length is fixed
  566. *
  567. * @param string $text
  568. * @param boolean $withoutChecksum
  569. * @return string
  570. */
  571. protected function _addLeadingZeros($text, $withoutChecksum = false)
  572. {
  573. if ($this->_barcodeLength && $this->_addLeadingZeros) {
  574. $omitChecksum = (int) ($this->_withChecksum && $withoutChecksum);
  575. if (is_int($this->_barcodeLength)) {
  576. $length = $this->_barcodeLength - $omitChecksum;
  577. if (strlen($text) < $length) {
  578. $text = str_repeat('0', $length - strlen($text)) . $text;
  579. }
  580. } else {
  581. if ($this->_barcodeLength == 'even') {
  582. $text = ((strlen($text) - $omitChecksum) % 2 ? '0' . $text : $text);
  583. }
  584. }
  585. }
  586. return $text;
  587. }
  588. /**
  589. * Retrieve text to encode
  590. *
  591. * @return string
  592. */
  593. public function getRawText()
  594. {
  595. return $this->_text;
  596. }
  597. /**
  598. * Retrieve text to display
  599. *
  600. * @return string
  601. */
  602. public function getTextToDisplay()
  603. {
  604. if ($this->_withChecksumInText) {
  605. return $this->getText();
  606. } else {
  607. return $this->_addLeadingZeros($this->_text, true);
  608. }
  609. }
  610. /**
  611. * Activate/deactivate drawing of text to encode
  612. *
  613. * @param boolean $value
  614. * @return $this
  615. */
  616. public function setDrawText($value)
  617. {
  618. $this->_drawText = (bool) $value;
  619. return $this;
  620. }
  621. /**
  622. * Retrieve if drawing of text to encode is enabled
  623. *
  624. * @return boolean
  625. */
  626. public function getDrawText()
  627. {
  628. return $this->_drawText;
  629. }
  630. /**
  631. * Activate/deactivate the adjustment of the position
  632. * of the characters to the position of the bars
  633. *
  634. * @param boolean $value
  635. * @return $this
  636. * @throws Zend_Barcode_Object_Exception
  637. */
  638. public function setStretchText($value)
  639. {
  640. $this->_stretchText = (bool) $value;
  641. return $this;
  642. }
  643. /**
  644. * Retrieve if the adjustment of the position of the characters
  645. * to the position of the bars is enabled
  646. *
  647. * @return boolean
  648. */
  649. public function getStretchText()
  650. {
  651. return $this->_stretchText;
  652. }
  653. /**
  654. * Activate/deactivate the automatic generation
  655. * of the checksum character
  656. * added to the barcode text
  657. *
  658. * @param boolean $value
  659. * @return $this
  660. */
  661. public function setWithChecksum($value)
  662. {
  663. if (!$this->_mandatoryChecksum) {
  664. $this->_withChecksum = (bool) $value;
  665. }
  666. return $this;
  667. }
  668. /**
  669. * Retrieve if the checksum character is automatically
  670. * added to the barcode text
  671. *
  672. * @return boolean
  673. */
  674. public function getWithChecksum()
  675. {
  676. return $this->_withChecksum;
  677. }
  678. /**
  679. * Activate/deactivate the automatic generation
  680. * of the checksum character
  681. * added to the barcode text
  682. *
  683. * @param boolean $value
  684. * @return $this
  685. * @throws Zend_Barcode_Object_Exception
  686. */
  687. public function setWithChecksumInText($value)
  688. {
  689. if (!$this->_mandatoryChecksum) {
  690. $this->_withChecksumInText = (bool) $value;
  691. }
  692. return $this;
  693. }
  694. /**
  695. * Retrieve if the checksum character is automatically
  696. * added to the barcode text
  697. *
  698. * @return boolean
  699. */
  700. public function getWithChecksumInText()
  701. {
  702. return $this->_withChecksumInText;
  703. }
  704. /**
  705. * Set the font for all instances of barcode
  706. *
  707. * @param string $font
  708. */
  709. public static function setBarcodeFont($font)
  710. {
  711. if (is_string($font) || (is_int($font) && $font >= 1 && $font <= 5)) {
  712. self::$_staticFont = $font;
  713. }
  714. }
  715. /**
  716. * Set the font:
  717. * - if integer between 1 and 5, use gd built-in fonts
  718. * - if string, $value is assumed to be the path to a TTF font
  719. *
  720. * @param integer|string $value
  721. * @return $this
  722. * @throws Zend_Barcode_Object_Exception
  723. */
  724. public function setFont($value)
  725. {
  726. if (is_int($value) && $value >= 1 && $value <= 5) {
  727. if (!extension_loaded('gd')) {
  728. require_once 'Zend/Barcode/Object/Exception.php';
  729. throw new Zend_Barcode_Object_Exception(
  730. 'GD extension is required to use numeric font'
  731. );
  732. }
  733. // Case of numeric font with GD
  734. $this->_font = $value;
  735. // In this case font size is given by:
  736. $this->_fontSize = imagefontheight($value);
  737. } elseif (is_string($value)) {
  738. $this->_font = $value;
  739. } else {
  740. require_once 'Zend/Barcode/Object/Exception.php';
  741. throw new Zend_Barcode_Object_Exception(sprintf(
  742. 'Invalid font "%s" provided to setFont()',
  743. $value
  744. ));
  745. }
  746. return $this;
  747. }
  748. /**
  749. * Retrieve the font
  750. *
  751. * @return integer|string
  752. */
  753. public function getFont()
  754. {
  755. return $this->_font;
  756. }
  757. /**
  758. * Set the size of the font in case of TTF
  759. *
  760. * @param float $value
  761. * @return $this
  762. * @throws Zend_Barcode_Object_Exception
  763. */
  764. public function setFontSize($value)
  765. {
  766. if (is_numeric($this->_font)) {
  767. // Case of numeric font with GD
  768. return $this;
  769. }
  770. if (!is_numeric($value)) {
  771. require_once 'Zend/Barcode/Object/Exception.php';
  772. throw new Zend_Barcode_Object_Exception(
  773. 'Font size must be a numeric value'
  774. );
  775. }
  776. $this->_fontSize = $value;
  777. return $this;
  778. }
  779. /**
  780. * Retrieve the size of the font in case of TTF
  781. *
  782. * @return float
  783. */
  784. public function getFontSize()
  785. {
  786. return $this->_fontSize;
  787. }
  788. /**
  789. * Quiet zone before first bar
  790. * and after the last bar
  791. *
  792. * @return integer
  793. */
  794. public function getQuietZone()
  795. {
  796. if ($this->_withQuietZones || $this->_mandatoryQuietZones) {
  797. return 10 * $this->_barThinWidth * $this->_factor;
  798. } else {
  799. return 0;
  800. }
  801. }
  802. /**
  803. * Add an instruction in the array of instructions
  804. *
  805. * @param array $instruction
  806. */
  807. protected function _addInstruction(array $instruction)
  808. {
  809. $this->_instructions[] = $instruction;
  810. }
  811. /**
  812. * Retrieve the set of drawing instructions
  813. *
  814. * @return array
  815. */
  816. public function getInstructions()
  817. {
  818. return $this->_instructions;
  819. }
  820. /**
  821. * Add a polygon drawing instruction in the set of instructions
  822. *
  823. * @param array $points
  824. * @param integer $color
  825. * @param boolean $filled
  826. */
  827. protected function _addPolygon(array $points, $color = null, $filled = true)
  828. {
  829. if ($color === null) {
  830. $color = $this->_foreColor;
  831. }
  832. $this->_addInstruction(array(
  833. 'type' => 'polygon',
  834. 'points' => $points,
  835. 'color' => $color,
  836. 'filled' => $filled,
  837. ));
  838. }
  839. /**
  840. * Add a text drawing instruction in the set of instructions
  841. *
  842. * @param string $text
  843. * @param float $size
  844. * @param array $position
  845. * @param string $font
  846. * @param integer $color
  847. * @param string $alignment
  848. * @param float|int $orientation
  849. */
  850. protected function _addText(
  851. $text,
  852. $size,
  853. $position,
  854. $font,
  855. $color,
  856. $alignment = 'center',
  857. $orientation = 0
  858. ) {
  859. if ($color === null) {
  860. $color = $this->_foreColor;
  861. }
  862. $this->_addInstruction(array(
  863. 'type' => 'text',
  864. 'text' => $text,
  865. 'size' => $size,
  866. 'position' => $position,
  867. 'font' => $font,
  868. 'color' => $color,
  869. 'alignment' => $alignment,
  870. 'orientation' => $orientation,
  871. ));
  872. }
  873. /**
  874. * Checking of parameters after all settings
  875. *
  876. * @return bool
  877. */
  878. public function checkParams()
  879. {
  880. $this->_checkText();
  881. $this->_checkFontAndOrientation();
  882. $this->_checkParams();
  883. return true;
  884. }
  885. /**
  886. * Check if a text is really provided to barcode
  887. *
  888. * @param string|null $value
  889. * @throws Zend_Barcode_Object_Exception
  890. */
  891. protected function _checkText($value = null)
  892. {
  893. if ($value === null) {
  894. $value = $this->_text;
  895. }
  896. if (!strlen($value)) {
  897. require_once 'Zend/Barcode/Object/Exception.php';
  898. throw new Zend_Barcode_Object_Exception(
  899. 'A text must be provide to Barcode before drawing'
  900. );
  901. }
  902. $this->validateText($value);
  903. }
  904. /**
  905. * Check the ratio between the thick and the thin bar
  906. *
  907. * @param int $min
  908. * @param int $max
  909. * @throws Zend_Barcode_Object_Exception
  910. */
  911. protected function _checkRatio($min = 2, $max = 3)
  912. {
  913. $ratio = $this->_barThickWidth / $this->_barThinWidth;
  914. if (!($ratio >= $min && $ratio <= $max)) {
  915. require_once 'Zend/Barcode/Object/Exception.php';
  916. throw new Zend_Barcode_Object_Exception(sprintf(
  917. 'Ratio thick/thin bar must be between %0.1f and %0.1f (actual %0.3f)',
  918. $min,
  919. $max,
  920. $ratio
  921. ));
  922. }
  923. }
  924. /**
  925. * Drawing with an angle is just allow TTF font
  926. *
  927. * @throws Zend_Barcode_Object_Exception
  928. */
  929. protected function _checkFontAndOrientation()
  930. {
  931. if (is_numeric($this->_font) && $this->_orientation != 0) {
  932. require_once 'Zend/Barcode/Object/Exception.php';
  933. throw new Zend_Barcode_Object_Exception(
  934. 'Only drawing with TTF font allow orientation of the barcode.'
  935. );
  936. }
  937. }
  938. /**
  939. * Width of the result image (before any rotation)
  940. *
  941. * @return integer
  942. */
  943. protected function _calculateWidth()
  944. {
  945. return (int) $this->_withBorder
  946. + $this->_calculateBarcodeWidth()
  947. + (int) $this->_withBorder;
  948. }
  949. /**
  950. * Calculate the width of the barcode
  951. *
  952. * @return integer
  953. */
  954. abstract protected function _calculateBarcodeWidth();
  955. /**
  956. * Height of the result object
  957. *
  958. * @return int
  959. */
  960. protected function _calculateHeight()
  961. {
  962. return (int) $this->_withBorder * 2
  963. + $this->_calculateBarcodeHeight()
  964. + (int) $this->_withBorder * 2;
  965. }
  966. /**
  967. * Height of the barcode
  968. *
  969. * @return int
  970. */
  971. protected function _calculateBarcodeHeight()
  972. {
  973. $textHeight = 0;
  974. $extraHeight = 0;
  975. if ($this->_drawText) {
  976. $textHeight += $this->_fontSize;
  977. $extraHeight = 2;
  978. }
  979. return ($this->_barHeight + $textHeight) * $this->_factor + $extraHeight;
  980. }
  981. /**
  982. * Get height of the result object
  983. *
  984. * @param bool $recalculate
  985. * @return int
  986. */
  987. public function getHeight($recalculate = false)
  988. {
  989. if ($this->_height === null || $recalculate) {
  990. $this->_height =
  991. abs($this->_calculateHeight() * cos($this->_orientation / 180 * pi()))
  992. + abs($this->_calculateWidth() * sin($this->_orientation / 180 * pi()));
  993. }
  994. return $this->_height;
  995. }
  996. /**
  997. * Get width of the result object
  998. *
  999. * @param bool $recalculate
  1000. * @return int
  1001. */
  1002. public function getWidth($recalculate = false)
  1003. {
  1004. if ($this->_width === null || $recalculate) {
  1005. $this->_width =
  1006. abs($this->_calculateWidth() * cos($this->_orientation / 180 * pi()))
  1007. + abs($this->_calculateHeight() * sin($this->_orientation / 180 * pi()));
  1008. }
  1009. return $this->_width;
  1010. }
  1011. /**
  1012. * Calculate the offset from the left of the object
  1013. * if an orientation is activated
  1014. *
  1015. * @param bool $recalculate
  1016. * @return float
  1017. */
  1018. public function getOffsetLeft($recalculate = false)
  1019. {
  1020. if ($this->_offsetLeft === null || $recalculate) {
  1021. $this->_offsetLeft = - min(array(
  1022. 0 * cos(
  1023. $this->_orientation / 180 * pi()) - 0 * sin(
  1024. $this->_orientation / 180 * pi()),
  1025. 0 * cos(
  1026. $this->_orientation / 180 * pi()) - $this->_calculateBarcodeHeight() * sin(
  1027. $this->_orientation / 180 * pi()),
  1028. $this->_calculateBarcodeWidth() * cos(
  1029. $this->_orientation / 180 * pi()) - $this->_calculateBarcodeHeight() * sin(
  1030. $this->_orientation / 180 * pi()),
  1031. $this->_calculateBarcodeWidth() * cos(
  1032. $this->_orientation / 180 * pi()) - 0 * sin(
  1033. $this->_orientation / 180 * pi()),
  1034. ));
  1035. }
  1036. return $this->_offsetLeft;
  1037. }
  1038. /**
  1039. * Calculate the offset from the top of the object
  1040. * if an orientation is activated
  1041. *
  1042. * @param bool $recalculate
  1043. * @return float
  1044. */
  1045. public function getOffsetTop($recalculate = false)
  1046. {
  1047. if ($this->_offsetTop === null || $recalculate) {
  1048. $this->_offsetTop = - min(array(
  1049. 0 * cos(
  1050. $this->_orientation / 180 * pi()) + 0 * sin(
  1051. $this->_orientation / 180 * pi()),
  1052. $this->_calculateBarcodeHeight() * cos(
  1053. $this->_orientation / 180 * pi()) + 0 * sin(
  1054. $this->_orientation / 180 * pi()),
  1055. $this->_calculateBarcodeHeight() * cos(
  1056. $this->_orientation / 180 * pi()) + $this->_calculateBarcodeWidth() * sin(
  1057. $this->_orientation / 180 * pi()),
  1058. 0 * cos(
  1059. $this->_orientation / 180 * pi()) + $this->_calculateBarcodeWidth() * sin(
  1060. $this->_orientation / 180 * pi()),
  1061. ));
  1062. }
  1063. return $this->_offsetTop;
  1064. }
  1065. /**
  1066. * Apply rotation on a point in X/Y dimensions
  1067. *
  1068. * @param float $x1 x-position before rotation
  1069. * @param float $y1 y-position before rotation
  1070. * @return array Array of two elements corresponding to the new XY point
  1071. */
  1072. protected function _rotate($x1, $y1)
  1073. {
  1074. $x2 = $x1 * cos($this->_orientation / 180 * pi())
  1075. - $y1 * sin($this->_orientation / 180 * pi())
  1076. + $this->getOffsetLeft();
  1077. $y2 = $y1 * cos($this->_orientation / 180 * pi())
  1078. + $x1 * sin($this->_orientation / 180 * pi())
  1079. + $this->getOffsetTop();
  1080. return array(intval($x2) , intval($y2));
  1081. }
  1082. /**
  1083. * Complete drawing of the barcode
  1084. *
  1085. * @return array Table of instructions
  1086. */
  1087. public function draw()
  1088. {
  1089. $this->checkParams();
  1090. $this->_drawBarcode();
  1091. $this->_drawBorder();
  1092. $this->_drawText();
  1093. return $this->getInstructions();
  1094. }
  1095. /**
  1096. * Draw the barcode
  1097. */
  1098. protected function _drawBarcode()
  1099. {
  1100. $barcodeTable = $this->_prepareBarcode();
  1101. $this->_preDrawBarcode();
  1102. $xpos = (int) $this->_withBorder;
  1103. $ypos = (int) $this->_withBorder;
  1104. $point1 = $this->_rotate(0, 0);
  1105. $point2 = $this->_rotate(0, $this->_calculateHeight() - 1);
  1106. $point3 = $this->_rotate(
  1107. $this->_calculateWidth() - 1,
  1108. $this->_calculateHeight() - 1
  1109. );
  1110. $point4 = $this->_rotate($this->_calculateWidth() - 1, 0);
  1111. $this->_addPolygon(array(
  1112. $point1,
  1113. $point2,
  1114. $point3,
  1115. $point4
  1116. ), $this->_backgroundColor);
  1117. $xpos += $this->getQuietZone();
  1118. $barLength = $this->_barHeight * $this->_factor;
  1119. foreach ($barcodeTable as $bar) {
  1120. $width = $bar[1] * $this->_factor;
  1121. if ($bar[0]) {
  1122. $point1 = $this->_rotate($xpos, $ypos + $bar[2] * $barLength);
  1123. $point2 = $this->_rotate($xpos, $ypos + $bar[3] * $barLength);
  1124. $point3 = $this->_rotate(
  1125. $xpos + $width - 1,
  1126. $ypos + $bar[3] * $barLength
  1127. );
  1128. $point4 = $this->_rotate(
  1129. $xpos + $width - 1,
  1130. $ypos + $bar[2] * $barLength
  1131. );
  1132. $this->_addPolygon(array(
  1133. $point1,
  1134. $point2,
  1135. $point3,
  1136. $point4,
  1137. ));
  1138. }
  1139. $xpos += $width;
  1140. }
  1141. $this->_postDrawBarcode();
  1142. }
  1143. /**
  1144. * Partial function to draw border
  1145. */
  1146. protected function _drawBorder()
  1147. {
  1148. if ($this->_withBorder) {
  1149. $point1 = $this->_rotate(0, 0);
  1150. $point2 = $this->_rotate($this->_calculateWidth() - 1, 0);
  1151. $point3 = $this->_rotate(
  1152. $this->_calculateWidth() - 1,
  1153. $this->_calculateHeight() - 1
  1154. );
  1155. $point4 = $this->_rotate(0, $this->_calculateHeight() - 1);
  1156. $this->_addPolygon(array(
  1157. $point1,
  1158. $point2,
  1159. $point3,
  1160. $point4,
  1161. $point1,
  1162. ), $this->_foreColor, false);
  1163. }
  1164. }
  1165. /**
  1166. * Partial function to draw text
  1167. */
  1168. protected function _drawText()
  1169. {
  1170. if ($this->_drawText) {
  1171. $text = $this->getTextToDisplay();
  1172. if ($this->_stretchText) {
  1173. $textLength = strlen($text);
  1174. $space = ($this->_calculateWidth() - 2 * $this->getQuietZone()) / $textLength;
  1175. for ($i = 0; $i < $textLength; $i ++) {
  1176. $leftPosition = $this->getQuietZone() + $space * ($i + 0.5);
  1177. $this->_addText(
  1178. $text{$i},
  1179. $this->_fontSize * $this->_factor,
  1180. $this->_rotate(
  1181. $leftPosition,
  1182. (int) $this->_withBorder * 2
  1183. + $this->_factor * ($this->_barHeight + $this->_fontSize) + 1
  1184. ),
  1185. $this->_font,
  1186. $this->_foreColor,
  1187. 'center',
  1188. - $this->_orientation
  1189. );
  1190. }
  1191. } else {
  1192. $this->_addText(
  1193. $text,
  1194. $this->_fontSize * $this->_factor,
  1195. $this->_rotate(
  1196. $this->_calculateWidth() / 2,
  1197. (int) $this->_withBorder * 2
  1198. + $this->_factor * ($this->_barHeight + $this->_fontSize) + 1
  1199. ),
  1200. $this->_font,
  1201. $this->_foreColor,
  1202. 'center',
  1203. - $this->_orientation
  1204. );
  1205. }
  1206. }
  1207. }
  1208. /**
  1209. * Check for invalid characters
  1210. *
  1211. * @param string $value Text to be ckecked
  1212. */
  1213. public function validateText($value)
  1214. {
  1215. $this->_validateText($value);
  1216. }
  1217. /**
  1218. * Standard validation for most of barcode objects
  1219. *
  1220. * @param string $value
  1221. * @param array $options
  1222. * @throws Zend_Barcode_Object_Exception
  1223. */
  1224. protected function _validateText($value, $options = array())
  1225. {
  1226. $validatorName = (isset($options['validator'])) ? $options['validator'] : $this->getType();
  1227. $validator = new Zend_Validate_Barcode(array(
  1228. 'adapter' => $validatorName,
  1229. 'checksum' => false,
  1230. ));
  1231. $checksumCharacter = '';
  1232. $withChecksum = false;
  1233. if ($this->_mandatoryChecksum) {
  1234. $checksumCharacter = $this->_substituteChecksumCharacter;
  1235. $withChecksum = true;
  1236. }
  1237. $value = $this->_addLeadingZeros($value, $withChecksum) . $checksumCharacter;
  1238. if (!$validator->isValid($value)) {
  1239. $message = implode("\n", $validator->getMessages());
  1240. /**
  1241. * @see Zend_Barcode_Object_Exception
  1242. */
  1243. require_once 'Zend/Barcode/Object/Exception.php';
  1244. throw new Zend_Barcode_Object_Exception($message);
  1245. }
  1246. }
  1247. /**
  1248. * Each child must prepare the barcode and return
  1249. * a table like array(
  1250. * 0 => array(
  1251. * 0 => int (visible(black) or not(white))
  1252. * 1 => int (width of the bar)
  1253. * 2 => float (0->1 position from the top of the beginning of the bar in %)
  1254. * 3 => float (0->1 position from the top of the end of the bar in %)
  1255. * ),
  1256. * 1 => ...
  1257. * )
  1258. *
  1259. * @return array
  1260. */
  1261. abstract protected function _prepareBarcode();
  1262. /**
  1263. * Checking of parameters after all settings
  1264. */
  1265. abstract protected function _checkParams();
  1266. /**
  1267. * Allow each child to draw something else
  1268. */
  1269. protected function _preDrawBarcode()
  1270. {
  1271. }
  1272. /**
  1273. * Allow each child to draw something else
  1274. * (ex: bearer bars in interleaved 2 of 5 code)
  1275. */
  1276. protected function _postDrawBarcode()
  1277. {
  1278. }
  1279. }