ObjectAbstract.php 35 KB

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