人人商城

BCGintelligentmail.barcode.php 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <?php
  2. /**
  3. *--------------------------------------------------------------------
  4. *
  5. * Sub-Class - Intelligent Mail
  6. *
  7. * A postnet is composed of either 5, 9 or 11 digits used by US postal service.
  8. *
  9. *--------------------------------------------------------------------
  10. * Copyright (C) Jean-Sebastien Goupil
  11. * http://www.barcodephp.com
  12. */
  13. include_once('BCGParseException.php');
  14. include_once('BCGArgumentException.php');
  15. include_once('BCGBarcode.php');
  16. include_once('BCGBarcode1D.php');
  17. class BCGintelligentmail extends BCGBarcode1D {
  18. private $barcodeIdentifier; // string
  19. private $serviceTypeIdentifier; // string
  20. private $mailerIdentifier; // string
  21. private $serialNumber; // string
  22. private $quietZone; // bool
  23. private $data;
  24. private static $characterTable1 = array(
  25. 31, 7936, 47, 7808, 55, 7552, 59, 7040, 61, 6016,
  26. 62, 3968, 79, 7744, 87, 7488, 91, 6976, 93, 5952,
  27. 94, 3904, 103, 7360, 107, 6848, 109, 5824, 110, 3776,
  28. 115, 6592, 117, 5568, 118, 3520, 121, 5056, 122, 3008,
  29. 124, 1984, 143, 7712, 151, 7456, 155, 6944, 157, 5920,
  30. 158, 3872, 167, 7328, 171, 6816, 173, 5792, 174, 3744,
  31. 179, 6560, 181, 5536, 182, 3488, 185, 5024, 186, 2976,
  32. 188, 1952, 199, 7264, 203, 6752, 205, 5728, 206, 3680,
  33. 211, 6496, 213, 5472, 214, 3424, 217, 4960, 218, 2912,
  34. 220, 1888, 227, 6368, 229, 5344, 230, 3296, 233, 4832,
  35. 234, 2784, 236, 1760, 241, 4576, 242, 2528, 244, 1504,
  36. 248, 992, 271, 7696, 279, 7440, 283, 6928, 285, 5904,
  37. 286, 3856, 295, 7312, 299, 6800, 301, 5776, 302, 3728,
  38. 307, 6544, 309, 5520, 310, 3472, 313, 5008, 314, 2960,
  39. 316, 1936, 327, 7248, 331, 6736, 333, 5712, 334, 3664,
  40. 339, 6480, 341, 5456, 342, 3408, 345, 4944, 346, 2896,
  41. 348, 1872, 355, 6352, 357, 5328, 358, 3280, 361, 4816,
  42. 362, 2768, 364, 1744, 369, 4560, 370, 2512, 372, 1488,
  43. 376, 976, 391, 7216, 395, 6704, 397, 5680, 398, 3632,
  44. 403, 6448, 405, 5424, 406, 3376, 409, 4912, 410, 2864,
  45. 412, 1840, 419, 6320, 421, 5296, 422, 3248, 425, 4784,
  46. 426, 2736, 428, 1712, 433, 4528, 434, 2480, 436, 1456,
  47. 440, 944, 451, 6256, 453, 5232, 454, 3184, 457, 4720,
  48. 458, 2672, 460, 1648, 465, 4464, 466, 2416, 468, 1392,
  49. 472, 880, 481, 4336, 482, 2288, 484, 1264, 488, 752,
  50. 527, 7688, 535, 7432, 539, 6920, 541, 5896, 542, 3848,
  51. 551, 7304, 555, 6792, 557, 5768, 558, 3720, 563, 6536,
  52. 565, 5512, 566, 3464, 569, 5000, 570, 2952, 572, 1928,
  53. 583, 7240, 587, 6728, 589, 5704, 590, 3656, 595, 6472,
  54. 597, 5448, 598, 3400, 601, 4936, 602, 2888, 604, 1864,
  55. 611, 6344, 613, 5320, 614, 3272, 617, 4808, 618, 2760,
  56. 620, 1736, 625, 4552, 626, 2504, 628, 1480, 632, 968,
  57. 647, 7208, 651, 6696, 653, 5672, 654, 3624, 659, 6440,
  58. 661, 5416, 662, 3368, 665, 4904, 666, 2856, 668, 1832,
  59. 675, 6312, 677, 5288, 678, 3240, 681, 4776, 682, 2728,
  60. 684, 1704, 689, 4520, 690, 2472, 692, 1448, 696, 936,
  61. 707, 6248, 709, 5224, 710, 3176, 713, 4712, 714, 2664,
  62. 716, 1640, 721, 4456, 722, 2408, 724, 1384, 728, 872,
  63. 737, 4328, 738, 2280, 740, 1256, 775, 7192, 779, 6680,
  64. 781, 5656, 782, 3608, 787, 6424, 789, 5400, 790, 3352,
  65. 793, 4888, 794, 2840, 796, 1816, 803, 6296, 805, 5272,
  66. 806, 3224, 809, 4760, 810, 2712, 812, 1688, 817, 4504,
  67. 818, 2456, 820, 1432, 824, 920, 835, 6232, 837, 5208,
  68. 838, 3160, 841, 4696, 842, 2648, 844, 1624, 849, 4440,
  69. 850, 2392, 852, 1368, 865, 4312, 866, 2264, 868, 1240,
  70. 899, 6200, 901, 5176, 902, 3128, 905, 4664, 906, 2616,
  71. 908, 1592, 913, 4408, 914, 2360, 916, 1336, 929, 4280,
  72. 930, 2232, 932, 1208, 961, 4216, 962, 2168, 964, 1144,
  73. 1039, 7684, 1047, 7428, 1051, 6916, 1053, 5892, 1054, 3844,
  74. 1063, 7300, 1067, 6788, 1069, 5764, 1070, 3716, 1075, 6532,
  75. 1077, 5508, 1078, 3460, 1081, 4996, 1082, 2948, 1084, 1924,
  76. 1095, 7236, 1099, 6724, 1101, 5700, 1102, 3652, 1107, 6468,
  77. 1109, 5444, 1110, 3396, 1113, 4932, 1114, 2884, 1116, 1860,
  78. 1123, 6340, 1125, 5316, 1126, 3268, 1129, 4804, 1130, 2756,
  79. 1132, 1732, 1137, 4548, 1138, 2500, 1140, 1476, 1159, 7204,
  80. 1163, 6692, 1165, 5668, 1166, 3620, 1171, 6436, 1173, 5412,
  81. 1174, 3364, 1177, 4900, 1178, 2852, 1180, 1828, 1187, 6308,
  82. 1189, 5284, 1190, 3236, 1193, 4772, 1194, 2724, 1196, 1700,
  83. 1201, 4516, 1202, 2468, 1204, 1444, 1219, 6244, 1221, 5220,
  84. 1222, 3172, 1225, 4708, 1226, 2660, 1228, 1636, 1233, 4452,
  85. 1234, 2404, 1236, 1380, 1249, 4324, 1250, 2276, 1287, 7188,
  86. 1291, 6676, 1293, 5652, 1294, 3604, 1299, 6420, 1301, 5396,
  87. 1302, 3348, 1305, 4884, 1306, 2836, 1308, 1812, 1315, 6292,
  88. 1317, 5268, 1318, 3220, 1321, 4756, 1322, 2708, 1324, 1684,
  89. 1329, 4500, 1330, 2452, 1332, 1428, 1347, 6228, 1349, 5204,
  90. 1350, 3156, 1353, 4692, 1354, 2644, 1356, 1620, 1361, 4436,
  91. 1362, 2388, 1377, 4308, 1378, 2260, 1411, 6196, 1413, 5172,
  92. 1414, 3124, 1417, 4660, 1418, 2612, 1420, 1588, 1425, 4404,
  93. 1426, 2356, 1441, 4276, 1442, 2228, 1473, 4212, 1474, 2164,
  94. 1543, 7180, 1547, 6668, 1549, 5644, 1550, 3596, 1555, 6412,
  95. 1557, 5388, 1558, 3340, 1561, 4876, 1562, 2828, 1564, 1804,
  96. 1571, 6284, 1573, 5260, 1574, 3212, 1577, 4748, 1578, 2700,
  97. 1580, 1676, 1585, 4492, 1586, 2444, 1603, 6220, 1605, 5196,
  98. 1606, 3148, 1609, 4684, 1610, 2636, 1617, 4428, 1618, 2380,
  99. 1633, 4300, 1634, 2252, 1667, 6188, 1669, 5164, 1670, 3116,
  100. 1673, 4652, 1674, 2604, 1681, 4396, 1682, 2348, 1697, 4268,
  101. 1698, 2220, 1729, 4204, 1730, 2156, 1795, 6172, 1797, 5148,
  102. 1798, 3100, 1801, 4636, 1802, 2588, 1809, 4380, 1810, 2332,
  103. 1825, 4252, 1826, 2204, 1857, 4188, 1858, 2140, 1921, 4156,
  104. 1922, 2108, 2063, 7682, 2071, 7426, 2075, 6914, 2077, 5890,
  105. 2078, 3842, 2087, 7298, 2091, 6786, 2093, 5762, 2094, 3714,
  106. 2099, 6530, 2101, 5506, 2102, 3458, 2105, 4994, 2106, 2946,
  107. 2119, 7234, 2123, 6722, 2125, 5698, 2126, 3650, 2131, 6466,
  108. 2133, 5442, 2134, 3394, 2137, 4930, 2138, 2882, 2147, 6338,
  109. 2149, 5314, 2150, 3266, 2153, 4802, 2154, 2754, 2161, 4546,
  110. 2162, 2498, 2183, 7202, 2187, 6690, 2189, 5666, 2190, 3618,
  111. 2195, 6434, 2197, 5410, 2198, 3362, 2201, 4898, 2202, 2850,
  112. 2211, 6306, 2213, 5282, 2214, 3234, 2217, 4770, 2218, 2722,
  113. 2225, 4514, 2226, 2466, 2243, 6242, 2245, 5218, 2246, 3170,
  114. 2249, 4706, 2250, 2658, 2257, 4450, 2258, 2402, 2273, 4322,
  115. 2311, 7186, 2315, 6674, 2317, 5650, 2318, 3602, 2323, 6418,
  116. 2325, 5394, 2326, 3346, 2329, 4882, 2330, 2834, 2339, 6290,
  117. 2341, 5266, 2342, 3218, 2345, 4754, 2346, 2706, 2353, 4498,
  118. 2354, 2450, 2371, 6226, 2373, 5202, 2374, 3154, 2377, 4690,
  119. 2378, 2642, 2385, 4434, 2401, 4306, 2435, 6194, 2437, 5170,
  120. 2438, 3122, 2441, 4658, 2442, 2610, 2449, 4402, 2465, 4274,
  121. 2497, 4210, 2567, 7178, 2571, 6666, 2573, 5642, 2574, 3594,
  122. 2579, 6410, 2581, 5386, 2582, 3338, 2585, 4874, 2586, 2826,
  123. 2595, 6282, 2597, 5258, 2598, 3210, 2601, 4746, 2602, 2698,
  124. 2609, 4490, 2627, 6218, 2629, 5194, 2630, 3146, 2633, 4682,
  125. 2641, 4426, 2657, 4298, 2691, 6186, 2693, 5162, 2694, 3114,
  126. 2697, 4650, 2705, 4394, 2721, 4266, 2753, 4202, 2819, 6170,
  127. 2821, 5146, 2822, 3098, 2825, 4634, 2833, 4378, 2849, 4250,
  128. 2881, 4186, 2945, 4154, 3079, 7174, 3083, 6662, 3085, 5638,
  129. 3086, 3590, 3091, 6406, 3093, 5382, 3094, 3334, 3097, 4870,
  130. 3107, 6278, 3109, 5254, 3110, 3206, 3113, 4742, 3121, 4486,
  131. 3139, 6214, 3141, 5190, 3145, 4678, 3153, 4422, 3169, 4294,
  132. 3203, 6182, 3205, 5158, 3209, 4646, 3217, 4390, 3233, 4262,
  133. 3265, 4198, 3331, 6166, 3333, 5142, 3337, 4630, 3345, 4374,
  134. 3361, 4246, 3393, 4182, 3457, 4150, 3587, 6158, 3589, 5134,
  135. 3593, 4622, 3601, 4366, 3617, 4238, 3649, 4174, 3713, 4142,
  136. 3841, 4126, 4111, 7681, 4119, 7425, 4123, 6913, 4125, 5889,
  137. 4135, 7297, 4139, 6785, 4141, 5761, 4147, 6529, 4149, 5505,
  138. 4153, 4993, 4167, 7233, 4171, 6721, 4173, 5697, 4179, 6465,
  139. 4181, 5441, 4185, 4929, 4195, 6337, 4197, 5313, 4201, 4801,
  140. 4209, 4545, 4231, 7201, 4235, 6689, 4237, 5665, 4243, 6433,
  141. 4245, 5409, 4249, 4897, 4259, 6305, 4261, 5281, 4265, 4769,
  142. 4273, 4513, 4291, 6241, 4293, 5217, 4297, 4705, 4305, 4449,
  143. 4359, 7185, 4363, 6673, 4365, 5649, 4371, 6417, 4373, 5393,
  144. 4377, 4881, 4387, 6289, 4389, 5265, 4393, 4753, 4401, 4497,
  145. 4419, 6225, 4421, 5201, 4425, 4689, 4483, 6193, 4485, 5169,
  146. 4489, 4657, 4615, 7177, 4619, 6665, 4621, 5641, 4627, 6409,
  147. 4629, 5385, 4633, 4873, 4643, 6281, 4645, 5257, 4649, 4745,
  148. 4675, 6217, 4677, 5193, 4739, 6185, 4741, 5161, 4867, 6169,
  149. 4869, 5145, 5127, 7173, 5131, 6661, 5133, 5637, 5139, 6405,
  150. 5141, 5381, 5155, 6277, 5157, 5253, 5187, 6213, 5251, 6181,
  151. 5379, 6165, 5635, 6157, 6151, 7171, 6155, 6659, 6163, 6403,
  152. 6179, 6275, 6211, 5189, 4681, 4433, 4321, 3142, 2634, 2386,
  153. 2274, 1612, 1364, 1252, 856, 744, 496);
  154. private static $characterTable2 = array(
  155. 3, 6144, 5, 5120, 6, 3072, 9, 4608, 10, 2560,
  156. 12, 1536, 17, 4352, 18, 2304, 20, 1280, 24, 768,
  157. 33, 4224, 34, 2176, 36, 1152, 40, 640, 48, 384,
  158. 65, 4160, 66, 2112, 68, 1088, 72, 576, 80, 320,
  159. 96, 192, 129, 4128, 130, 2080, 132, 1056, 136, 544,
  160. 144, 288, 257, 4112, 258, 2064, 260, 1040, 264, 528,
  161. 513, 4104, 514, 2056, 516, 1032, 1025, 4100, 1026, 2052,
  162. 2049, 4098, 4097, 2050, 1028, 520, 272, 160);
  163. private static $barPositions = array(
  164. array(array(7, 2), array(4, 3)),
  165. array(array(1, 10), array(0, 0)),
  166. array(array(9, 12), array(2, 8)),
  167. array(array(5, 5), array(6, 11)),
  168. array(array(8, 9), array(3, 1)),
  169. array(array(0, 1), array(5, 12)),
  170. array(array(2, 5), array(1, 8)),
  171. array(array(4, 4), array(9, 11)),
  172. array(array(6, 3), array(8, 10)),
  173. array(array(3, 9), array(7, 6)),
  174. array(array(5, 11), array(1, 4)),
  175. array(array(8, 5), array(2, 12)),
  176. array(array(9, 10), array(0, 2)),
  177. array(array(7, 1), array(6, 7)),
  178. array(array(3, 6), array(4, 9)),
  179. array(array(0, 3), array(8, 6)),
  180. array(array(6, 4), array(2, 7)),
  181. array(array(1, 1), array(9, 9)),
  182. array(array(7, 10), array(5, 2)),
  183. array(array(4, 0), array(3, 8)),
  184. array(array(6, 2), array(0, 4)),
  185. array(array(8, 11), array(1, 0)),
  186. array(array(9, 8), array(3, 12)),
  187. array(array(2, 6), array(7, 7)),
  188. array(array(5, 1), array(4, 10)),
  189. array(array(1, 12), array(6, 9)),
  190. array(array(7, 3), array(8, 0)),
  191. array(array(5, 8), array(9, 7)),
  192. array(array(4, 6), array(2, 10)),
  193. array(array(3, 4), array(0, 5)),
  194. array(array(8, 4), array(5, 7)),
  195. array(array(7, 11), array(1, 9)),
  196. array(array(6, 0), array(9, 6)),
  197. array(array(0, 6), array(4, 8)),
  198. array(array(2, 1), array(3, 2)),
  199. array(array(5, 9), array(8, 12)),
  200. array(array(4, 11), array(6, 1)),
  201. array(array(9, 5), array(7, 4)),
  202. array(array(3, 3), array(1, 2)),
  203. array(array(0, 7), array(2, 0)),
  204. array(array(1, 3), array(4, 1)),
  205. array(array(6, 10), array(3, 5)),
  206. array(array(8, 7), array(9, 4)),
  207. array(array(2, 11), array(5, 6)),
  208. array(array(0, 8), array(7, 12)),
  209. array(array(4, 2), array(8, 1)),
  210. array(array(5, 10), array(3, 0)),
  211. array(array(9, 3), array(0, 9)),
  212. array(array(6, 5), array(2, 4)),
  213. array(array(7, 8), array(1, 7)),
  214. array(array(5, 0), array(4, 5)),
  215. array(array(2, 3), array(0, 10)),
  216. array(array(6, 12), array(9, 2)),
  217. array(array(3, 11), array(1, 6)),
  218. array(array(8, 8), array(7, 9)),
  219. array(array(5, 4), array(0, 11)),
  220. array(array(1, 5), array(2, 2)),
  221. array(array(9, 1), array(4, 12)),
  222. array(array(8, 3), array(6, 6)),
  223. array(array(7, 0), array(3, 7)),
  224. array(array(4, 7), array(7, 5)),
  225. array(array(0, 12), array(1, 11)),
  226. array(array(2, 9), array(9, 0)),
  227. array(array(6, 8), array(5, 3)),
  228. array(array(3, 10), array(8, 2))
  229. );
  230. /**
  231. * Constructor.
  232. */
  233. public function __construct() {
  234. parent::__construct();
  235. $this->setQuietZone(true);
  236. $this->setThickness(9);
  237. }
  238. /**
  239. * Gets the Quiet zone.
  240. *
  241. * @return bool
  242. */
  243. public function getQuietZone() {
  244. return $this->quietZone;
  245. }
  246. /**
  247. * Sets the Quiet zone.
  248. *
  249. * @param bool $quietZone
  250. */
  251. public function setQuietZone($quietZone) {
  252. $this->quietZone = (bool)$quietZone;
  253. }
  254. /**
  255. * Sets the tracking code.
  256. *
  257. * @param int $barcodeIdentifier 2-digit number. 2nd digit must be 0-4
  258. * @param int $serviceTypeIdentifier 3 digits
  259. * @param int $mailerIdentifier 6 or 9 digits
  260. * @param int $serialNumber 9 (if mailerId is 6) or 6 digits (if mailerId is 9)
  261. */
  262. public function setTrackingCode($barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) {
  263. $barcodeIdentifier = (string)(int)$barcodeIdentifier;
  264. $serviceTypeIdentifier = (int)$serviceTypeIdentifier;
  265. $mailerIdentifier = (int)$mailerIdentifier;
  266. $serialNumber = (string)(int)$serialNumber;
  267. $barcodeIdentifier = str_pad($barcodeIdentifier, 2, '0', STR_PAD_LEFT);
  268. if (strlen($barcodeIdentifier) !== 2) {
  269. throw new BCGArgumentException('Barcode Identifier must contain 2 digits.', 'barcodeIdentifier');
  270. }
  271. $barcodeIdentifierSecondNumber = $barcodeIdentifier[1];
  272. if ($barcodeIdentifierSecondNumber !== '0' && $barcodeIdentifierSecondNumber !== '1' && $barcodeIdentifierSecondNumber !== '2' && $barcodeIdentifierSecondNumber !== '3' && $barcodeIdentifierSecondNumber !== '4') {
  273. throw new BCGArgumentException('Barcode Identifier second digit must be a number between 0 and 4.', 'barcodeIdentifier');
  274. }
  275. if ($serviceTypeIdentifier < 0 || $serviceTypeIdentifier > 999) {
  276. throw new BCGArgumentException('Service Type Identifier must be between 0 and 999.', 'serviceTypeIdentifier');
  277. }
  278. $mailerIdentifierLength = 6;
  279. if ($mailerIdentifier > 899999) {
  280. $mailerIdentifierLength = 9;
  281. }
  282. if ($mailerIdentifierLength === 9 && strlen($serialNumber) > 6) {
  283. throw new BCGArgumentException('If the Serial Number has more than 6 digits, the Mailer Identifier must be lower than 900000.', 'mailerIdentifier');
  284. }
  285. if ($mailerIdentifierLength === 9) {
  286. if ($mailerIdentifierLength < 0 || $mailerIdentifier > 999999999) {
  287. throw new BCGArgumentException('Mailer Identifier must be between 0 and 999999999.', 'mailerIdentifier');
  288. }
  289. }
  290. $this->barcodeIdentifier = $barcodeIdentifier;
  291. $this->serviceTypeIdentifier = str_pad($serviceTypeIdentifier, 3, '0', STR_PAD_LEFT);
  292. $this->mailerIdentifier = str_pad($mailerIdentifier, $mailerIdentifierLength, '0', STR_PAD_LEFT);
  293. $this->serialNumber = str_pad((int)$serialNumber, $mailerIdentifierLength === 6 ? 9 : 6, '0', STR_PAD_LEFT);
  294. }
  295. /**
  296. * Parses the text before displaying it.
  297. *
  298. * @param mixed $text
  299. */
  300. public function parse($text) {
  301. parent::parse($text);
  302. $number = self::executeStep1($this->text, $this->barcodeIdentifier, $this->serviceTypeIdentifier, $this->mailerIdentifier, $this->serialNumber);
  303. $crc = self::executeStep2($number);
  304. $codewords = self::executeStep3($number);
  305. $codewords = self::executeStep4($codewords, $crc);
  306. $characters = self::executeStep5($codewords, $crc);
  307. $this->data = self::executeStep6($characters);
  308. }
  309. /**
  310. * Draws the barcode.
  311. *
  312. * @param resource $im
  313. */
  314. public function draw($im) {
  315. if ($this->quietZone) {
  316. $this->positionX += 9;
  317. }
  318. $c = strlen($this->data);
  319. for ($i = 0; $i < $c; $i++) {
  320. $this->drawChar($im, $this->data[$i]);
  321. }
  322. $this->drawText($im, 0, 0, $this->positionX, $this->thickness + ($this->quietZone ? 4 : 0));
  323. }
  324. /**
  325. * Returns the maximal size of a barcode.
  326. *
  327. * @param int $w
  328. * @param int $h
  329. * @return int[]
  330. */
  331. public function getDimension($w, $h) {
  332. $w += 65 * 3;
  333. $h += $this->thickness;
  334. // We remove the white on the right
  335. $w -= 1.56;
  336. if ($this->quietZone) {
  337. $w += 18;
  338. $h += 4;
  339. }
  340. return parent::getDimension($w, $h);
  341. }
  342. /**
  343. * Validates the input.
  344. */
  345. protected function validate() {
  346. // Tracking must have been entered
  347. if ($this->barcodeIdentifier === null || $this->serviceTypeIdentifier === null || $this->mailerIdentifier === null || $this->serialNumber === null) {
  348. throw new BCGParseException('intelligentmail', 'The tracking code must be set before calling the parse method.');
  349. }
  350. // Checking if all chars are allowed
  351. $match = array();
  352. if (preg_match('/[^0-9]/', $this->text, $match)) {
  353. throw new BCGParseException('intelligentmail', 'The character \'' . $match[0] . '\' is not allowed.');
  354. }
  355. // Must contain 0, 5, 9 or 11 chars
  356. $c = strlen($this->text);
  357. if ($c !== 0 && $c !== 5 && $c !== 9 && $c !== 11) {
  358. throw new BCGParseException('intelligentmail', 'Must contain 0, 5, 9, or 11 characters.');
  359. }
  360. parent::validate();
  361. }
  362. /**
  363. * Overloaded method for drawing special barcode.
  364. *
  365. * @param resource $im
  366. * @param string $code
  367. * @param boolean $startBar
  368. */
  369. protected function drawChar($im, $code, $startBar = true) {
  370. $y1 = 0;
  371. $y2 = 0;
  372. switch ($code) {
  373. case 'A':
  374. $y1 = 0;
  375. $y2 = $this->thickness - ($this->thickness / 2.5);
  376. break;
  377. case 'D':
  378. $y1 = 3.096;
  379. $y2 = $this->thickness - 1;
  380. break;
  381. case 'F':
  382. $y1 = 0;
  383. $y2 = $this->thickness - 1;
  384. break;
  385. case 'T':
  386. $y1 = 3.096;
  387. $y2 = $this->thickness - ($this->thickness / 2.5);
  388. break;
  389. }
  390. if ($this->quietZone) {
  391. $y1 += 2;
  392. $y2 += 2;
  393. }
  394. $this->drawFilledRectangle($im, $this->positionX, $y1, $this->positionX + 0.44, $y2, BCGBarcode::COLOR_FG);
  395. $this->positionX += 3;
  396. }
  397. /**
  398. * Executes Step 1: Conversion of Data Fields into Binary Data
  399. *
  400. * @param string $text
  401. * @param string $barcodeIdentifier
  402. * @param string $serviceTypeIdentifier
  403. * @param string $mailerIdentifier
  404. * @param string $serialNumber
  405. * @return string BCNumber
  406. */
  407. private static function executeStep1($text, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) {
  408. $number = self::conversionRoutingCode($text);
  409. $number = self::conversionTrackingCode($number, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber);
  410. return $number;
  411. }
  412. /**
  413. * Executes Step 2: Generation of 11-Bit CRC on Binary Data
  414. *
  415. * @param $number BCNumber
  416. * @return int
  417. */
  418. private static function executeStep2($number) {
  419. $byteArray = str_pad(self::bcdecuc($number), 13, chr(0), STR_PAD_LEFT);
  420. $generatorPolynomial = 0x0f35;
  421. $frameCheckSequence = 0x07ff;
  422. $data = 0;
  423. $byteIndex = 0;
  424. $bit = 0;
  425. $data = (ord($byteArray[$byteIndex]) << 5) & 0xffff;
  426. for ($bit = 2; $bit < 8; $bit++) {
  427. if (($frameCheckSequence ^ $data) & 0x400) {
  428. $frameCheckSequence = ($frameCheckSequence << 1) ^ $generatorPolynomial;
  429. } else {
  430. $frameCheckSequence = ($frameCheckSequence << 1);
  431. }
  432. $frameCheckSequence &= 0x7ff;
  433. $data <<= 1;
  434. $data &= 0xffff;
  435. }
  436. for ($byteIndex = 1; $byteIndex < 13; $byteIndex++) {
  437. $data = (ord($byteArray[$byteIndex]) << 3) & 0xffff;
  438. for ($bit = 0; $bit < 8; $bit++) {
  439. if (($frameCheckSequence ^ $data) & 0x0400) {
  440. $frameCheckSequence = ($frameCheckSequence << 1) ^ $generatorPolynomial;
  441. } else {
  442. $frameCheckSequence = ($frameCheckSequence << 1);
  443. }
  444. $frameCheckSequence &= 0x7ff;
  445. $data <<= 1;
  446. $data &= 0xffff;
  447. }
  448. }
  449. return $frameCheckSequence;
  450. }
  451. /**
  452. * Executes Step 3: Conversion from Binary Data to Codewords
  453. *
  454. * @param string $number BCNumber
  455. * @return int[]
  456. */
  457. private static function executeStep3($number) {
  458. $codewords = array();
  459. $codewords[9] = (int)bcmod($number, '636');
  460. $number = bcdiv($number, '636', 0);
  461. for ($i = 8; $i >= 0; $i--) {
  462. $codewords[$i] = (int)bcmod($number, '1365');
  463. $number = bcdiv($number, '1365', 0);
  464. }
  465. return $codewords;
  466. }
  467. /**
  468. * Executes Step 4: Inserting Additional Information into Codewords
  469. *
  470. * @param int[] $codewords
  471. * @param int $crc
  472. * @return int[]
  473. */
  474. private static function executeStep4($codewords, $crc) {
  475. $codewords[9] *= 2;
  476. if ($crc & 0x400) {
  477. $codewords[0] += 659;
  478. }
  479. return $codewords;
  480. }
  481. /**
  482. * Executes Step 5: Conversion from Codewords to Characters
  483. *
  484. * @param int[] $codewords
  485. * @param int $crc
  486. * @return int[]
  487. */
  488. private static function executeStep5($codewords, $crc) {
  489. $characters = array();
  490. for ($i = 0; $i < 10; $i++) {
  491. if ($codewords[$i] <= 1286) {
  492. $characters[$i] = self::$characterTable1[$codewords[$i]];
  493. } else {
  494. $characters[$i] = self::$characterTable2[$codewords[$i] - 1287];
  495. }
  496. }
  497. for ($i = 0; $i < 10; $i++) {
  498. $mask = 1 << $i;
  499. if ($crc & $mask) {
  500. $characters[$i] ^= 0x1fff;
  501. }
  502. }
  503. return $characters;
  504. }
  505. /**
  506. * Executes Step 6: Conversion from Characters to the Intelligent Mail Barcode
  507. *
  508. * @param int[] $characters
  509. * @return string
  510. */
  511. private static function executeStep6($characters) {
  512. $bars = '';
  513. for ($i = 0; $i < 65; $i++) {
  514. $barPosition = self::$barPositions[$i];
  515. $descender = $barPosition[0];
  516. $ascender = $barPosition[1];
  517. $extenderDescender = !!($characters[$descender[0]] & (1 << $descender[1]));
  518. $extenderAscender = !!($characters[$ascender[0]] & (1 << $ascender[1]));
  519. if ($extenderDescender && $extenderAscender) {
  520. $bars .= 'F';
  521. } elseif ($extenderDescender) {
  522. $bars .= 'D';
  523. } elseif ($extenderAscender) {
  524. $bars .= 'A';
  525. } else {
  526. $bars .= 'T';
  527. }
  528. }
  529. return $bars;
  530. }
  531. /**
  532. * Converts the routing code zipcode.
  533. *
  534. * @param string $zipcode
  535. * @return string BCNumber
  536. */
  537. private static function conversionRoutingCode($zipcode) {
  538. $number = $zipcode;
  539. switch (strlen($zipcode)) {
  540. case 11:
  541. $number = bcadd($number, '1000000000', 0);
  542. case 9:
  543. $number = bcadd($number, '100000', 0);
  544. case 5:
  545. $number = bcadd($number, '1', 0);
  546. default:
  547. return $number;
  548. }
  549. }
  550. /**
  551. * Converts the tracking code number.
  552. *
  553. * @param string $number BCNumber
  554. * @param string $barcodeIdentifier
  555. * @param string $serviceTypeIdentifier
  556. * @param string $mailerIdentifier
  557. * @param string $serialNumber
  558. * @return string BCNumber
  559. */
  560. private static function conversionTrackingCode($number, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) {
  561. $number = bcmul($number, 10, 0);
  562. $number = bcadd($number, $barcodeIdentifier[0], 0);
  563. $number = bcmul($number, 5, 0);
  564. $number = bcadd($number, $barcodeIdentifier[1], 0);
  565. $temp = $serviceTypeIdentifier . $mailerIdentifier . $serialNumber;
  566. for ($i = 0; $i < 18; $i++) {
  567. $number = bcmul($number, 10, 0);
  568. $number = bcadd($number, $temp[$i], 0);
  569. }
  570. return $number;
  571. }
  572. /**
  573. * Transforms a BCNumber into unsigned char*.
  574. *
  575. * @param string $dec BCNumber
  576. * @param string
  577. */
  578. private static function bcdecuc($dec) {
  579. $last = bcmod($dec, 256);
  580. $remain = bcdiv(bcsub($dec, $last), 256, 0);
  581. if ($remain == 0) {
  582. return pack('C', $last);
  583. } else {
  584. return self::bcdecuc($remain) . pack('C', $last);
  585. }
  586. }
  587. }
  588. ?>