2 * lgl-barcode-onecode.c
3 * Copyright (C) 2010 Jim Evins <evins@snaught.com>.
5 * This file is part of libglbarcode.
7 * libglbarcode is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * libglbarcode is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with libglbarcode. If not, see <http://www.gnu.org/licenses/>.
22 * This module implements the Intelligent Mail (OneCode) barcode
23 * specified in the USPS specification USPS-B-3200E, 07/08/05.
28 #include "lgl-barcode-onecode.h"
34 /*========================================================*/
35 /* Private macros and constants. */
36 /*========================================================*/
49 #define PTS_PER_INCH 72.0
51 #define ONECODE_BAR_WIDTH ( 0.02 * PTS_PER_INCH )
52 #define ONECODE_FULL_HEIGHT ( 0.145 * PTS_PER_INCH )
53 #define ONECODE_ASCENDER_HEIGHT ( 0.0965 * PTS_PER_INCH )
54 #define ONECODE_DESCENDER_HEIGHT ( 0.0965 * PTS_PER_INCH )
55 #define ONECODE_TRACKER_HEIGHT ( 0.048 * PTS_PER_INCH )
56 #define ONECODE_FULL_OFFSET 0
57 #define ONECODE_ASCENDER_OFFSET 0
58 #define ONECODE_DESCENDER_OFFSET ( 0.0485 * PTS_PER_INCH )
59 #define ONECODE_TRACKER_OFFSET ( 0.0485 * PTS_PER_INCH )
60 #define ONECODE_BAR_PITCH ( 0.0458 * PTS_PER_INCH )
61 #define ONECODE_HORIZ_MARGIN ( 0.125 * PTS_PER_INCH )
62 #define ONECODE_VERT_MARGIN ( 0.028 * PTS_PER_INCH )
65 /*========================================================*/
67 /*========================================================*/
74 struct { gint i; gint mask; } descender;
75 struct { gint i; gint mask; } ascender;
79 /*===========================================*/
81 /*===========================================*/
83 static BarMapEntry bar_map[] = {
84 /* 1 */ { { CHAR_H, 1<<2 }, { CHAR_E, 1<<3 } },
85 /* 2 */ { { CHAR_B, 1<<10 }, { CHAR_A, 1<<0 } },
86 /* 3 */ { { CHAR_J, 1<<12 }, { CHAR_C, 1<<8 } },
87 /* 4 */ { { CHAR_F, 1<<5 }, { CHAR_G, 1<<11 } },
88 /* 5 */ { { CHAR_I, 1<<9 }, { CHAR_D, 1<<1 } },
89 /* 6 */ { { CHAR_A, 1<<1 }, { CHAR_F, 1<<12 } },
90 /* 7 */ { { CHAR_C, 1<<5 }, { CHAR_B, 1<<8 } },
91 /* 8 */ { { CHAR_E, 1<<4 }, { CHAR_J, 1<<11 } },
92 /* 9 */ { { CHAR_G, 1<<3 }, { CHAR_I, 1<<10 } },
93 /* 10 */ { { CHAR_D, 1<<9 }, { CHAR_H, 1<<6 } },
94 /* 11 */ { { CHAR_F, 1<<11 }, { CHAR_B, 1<<4 } },
95 /* 12 */ { { CHAR_I, 1<<5 }, { CHAR_C, 1<<12 } },
96 /* 13 */ { { CHAR_J, 1<<10 }, { CHAR_A, 1<<2 } },
97 /* 14 */ { { CHAR_H, 1<<1 }, { CHAR_G, 1<<7 } },
98 /* 15 */ { { CHAR_D, 1<<6 }, { CHAR_E, 1<<9 } },
99 /* 16 */ { { CHAR_A, 1<<3 }, { CHAR_I, 1<<6 } },
100 /* 17 */ { { CHAR_G, 1<<4 }, { CHAR_C, 1<<7 } },
101 /* 18 */ { { CHAR_B, 1<<1 }, { CHAR_J, 1<<9 } },
102 /* 19 */ { { CHAR_H, 1<<10 }, { CHAR_F, 1<<2 } },
103 /* 20 */ { { CHAR_E, 1<<0 }, { CHAR_D, 1<<8 } },
104 /* 21 */ { { CHAR_G, 1<<2 }, { CHAR_A, 1<<4 } },
105 /* 22 */ { { CHAR_I, 1<<11 }, { CHAR_B, 1<<0 } },
106 /* 23 */ { { CHAR_J, 1<<8 }, { CHAR_D, 1<<12 } },
107 /* 24 */ { { CHAR_C, 1<<6 }, { CHAR_H, 1<<7 } },
108 /* 25 */ { { CHAR_F, 1<<1 }, { CHAR_E, 1<<10 } },
109 /* 26 */ { { CHAR_B, 1<<12 }, { CHAR_G, 1<<9 } },
110 /* 27 */ { { CHAR_H, 1<<3 }, { CHAR_I, 1<<0 } },
111 /* 28 */ { { CHAR_F, 1<<8 }, { CHAR_J, 1<<7 } },
112 /* 29 */ { { CHAR_E, 1<<6 }, { CHAR_C, 1<<10 } },
113 /* 30 */ { { CHAR_D, 1<<4 }, { CHAR_A, 1<<5 } },
114 /* 31 */ { { CHAR_I, 1<<4 }, { CHAR_F, 1<<7 } },
115 /* 32 */ { { CHAR_H, 1<<11 }, { CHAR_B, 1<<9 } },
116 /* 33 */ { { CHAR_G, 1<<0 }, { CHAR_J, 1<<6 } },
117 /* 34 */ { { CHAR_A, 1<<6 }, { CHAR_E, 1<<8 } },
118 /* 35 */ { { CHAR_C, 1<<1 }, { CHAR_D, 1<<2 } },
119 /* 36 */ { { CHAR_F, 1<<9 }, { CHAR_I, 1<<12 } },
120 /* 37 */ { { CHAR_E, 1<<11 }, { CHAR_G, 1<<1 } },
121 /* 38 */ { { CHAR_J, 1<<5 }, { CHAR_H, 1<<4 } },
122 /* 39 */ { { CHAR_D, 1<<3 }, { CHAR_B, 1<<2 } },
123 /* 40 */ { { CHAR_A, 1<<7 }, { CHAR_C, 1<<0 } },
124 /* 41 */ { { CHAR_B, 1<<3 }, { CHAR_E, 1<<1 } },
125 /* 42 */ { { CHAR_G, 1<<10 }, { CHAR_D, 1<<5 } },
126 /* 43 */ { { CHAR_I, 1<<7 }, { CHAR_J, 1<<4 } },
127 /* 44 */ { { CHAR_C, 1<<11 }, { CHAR_F, 1<<6 } },
128 /* 45 */ { { CHAR_A, 1<<8 }, { CHAR_H, 1<<12 } },
129 /* 46 */ { { CHAR_E, 1<<2 }, { CHAR_I, 1<<1 } },
130 /* 47 */ { { CHAR_F, 1<<10 }, { CHAR_D, 1<<0 } },
131 /* 48 */ { { CHAR_J, 1<<3 }, { CHAR_A, 1<<9 } },
132 /* 49 */ { { CHAR_G, 1<<5 }, { CHAR_C, 1<<4 } },
133 /* 50 */ { { CHAR_H, 1<<8 }, { CHAR_B, 1<<7 } },
134 /* 51 */ { { CHAR_F, 1<<0 }, { CHAR_E, 1<<5 } },
135 /* 52 */ { { CHAR_C, 1<<3 }, { CHAR_A, 1<<10 } },
136 /* 53 */ { { CHAR_G, 1<<12 }, { CHAR_J, 1<<2 } },
137 /* 54 */ { { CHAR_D, 1<<11 }, { CHAR_B, 1<<6 } },
138 /* 55 */ { { CHAR_I, 1<<8 }, { CHAR_H, 1<<9 } },
139 /* 56 */ { { CHAR_F, 1<<4 }, { CHAR_A, 1<<11 } },
140 /* 57 */ { { CHAR_B, 1<<5 }, { CHAR_C, 1<<2 } },
141 /* 58 */ { { CHAR_J, 1<<1 }, { CHAR_E, 1<<12 } },
142 /* 59 */ { { CHAR_I, 1<<3 }, { CHAR_G, 1<<6 } },
143 /* 60 */ { { CHAR_H, 1<<0 }, { CHAR_D, 1<<7 } },
144 /* 61 */ { { CHAR_E, 1<<7 }, { CHAR_H, 1<<5 } },
145 /* 62 */ { { CHAR_A, 1<<12 }, { CHAR_B, 1<<11 } },
146 /* 63 */ { { CHAR_C, 1<<9 }, { CHAR_J, 1<<0 } },
147 /* 64 */ { { CHAR_G, 1<<8 }, { CHAR_F, 1<<3 } },
148 /* 65 */ { { CHAR_D, 1<<10 }, { CHAR_I, 1<<2 } }
151 static gchar * tdaf_table[4] = { "T", "D", "A", "F" };
153 static guint character_table[] = {
154 /* Table I 5 of 13. */
155 31, 7936, 47, 7808, 55, 7552, 59, 7040, 61, 6016,
156 62, 3968, 79, 7744, 87, 7488, 91, 6976, 93, 5952,
157 94, 3904, 103, 7360, 107, 6848, 109, 5824, 110, 3776,
158 115, 6592, 117, 5568, 118, 3520, 121, 5056, 122, 3008,
159 124, 1984, 143, 7712, 151, 7456, 155, 6944, 157, 5920,
160 158, 3872, 167, 7328, 171, 6816, 173, 5792, 174, 3744,
161 179, 6560, 181, 5536, 182, 3488, 185, 5024, 186, 2976,
162 188, 1952, 199, 7264, 203, 6752, 205, 5728, 206, 3680,
163 211, 6496, 213, 5472, 214, 3424, 217, 4960, 218, 2912,
164 220, 1888, 227, 6368, 229, 5344, 230, 3296, 233, 4832,
165 234, 2784, 236, 1760, 241, 4576, 242, 2528, 244, 1504,
166 248, 992, 271, 7696, 279, 7440, 283, 6928, 285, 5904,
167 286, 3856, 295, 7312, 299, 6800, 301, 5776, 302, 3728,
168 307, 6544, 309, 5520, 310, 3472, 313, 5008, 314, 2960,
169 316, 1936, 327, 7248, 331, 6736, 333, 5712, 334, 3664,
170 339, 6480, 341, 5456, 342, 3408, 345, 4944, 346, 2896,
171 348, 1872, 355, 6352, 357, 5328, 358, 3280, 361, 4816,
172 362, 2768, 364, 1744, 369, 4560, 370, 2512, 372, 1488,
173 376, 976, 391, 7216, 395, 6704, 397, 5680, 398, 3632,
174 403, 6448, 405, 5424, 406, 3376, 409, 4912, 410, 2864,
175 412, 1840, 419, 6320, 421, 5296, 422, 3248, 425, 4784,
176 426, 2736, 428, 1712, 433, 4528, 434, 2480, 436, 1456,
177 440, 944, 451, 6256, 453, 5232, 454, 3184, 457, 4720,
178 458, 2672, 460, 1648, 465, 4464, 466, 2416, 468, 1392,
179 472, 880, 481, 4336, 482, 2288, 484, 1264, 488, 752,
180 527, 7688, 535, 7432, 539, 6920, 541, 5896, 542, 3848,
181 551, 7304, 555, 6792, 557, 5768, 558, 3720, 563, 6536,
182 565, 5512, 566, 3464, 569, 5000, 570, 2952, 572, 1928,
183 583, 7240, 587, 6728, 589, 5704, 590, 3656, 595, 6472,
184 597, 5448, 598, 3400, 601, 4936, 602, 2888, 604, 1864,
185 611, 6344, 613, 5320, 614, 3272, 617, 4808, 618, 2760,
186 620, 1736, 625, 4552, 626, 2504, 628, 1480, 632, 968,
187 647, 7208, 651, 6696, 653, 5672, 654, 3624, 659, 6440,
188 661, 5416, 662, 3368, 665, 4904, 666, 2856, 668, 1832,
189 675, 6312, 677, 5288, 678, 3240, 681, 4776, 682, 2728,
190 684, 1704, 689, 4520, 690, 2472, 692, 1448, 696, 936,
191 707, 6248, 709, 5224, 710, 3176, 713, 4712, 714, 2664,
192 716, 1640, 721, 4456, 722, 2408, 724, 1384, 728, 872,
193 737, 4328, 738, 2280, 740, 1256, 775, 7192, 779, 6680,
194 781, 5656, 782, 3608, 787, 6424, 789, 5400, 790, 3352,
195 793, 4888, 794, 2840, 796, 1816, 803, 6296, 805, 5272,
196 806, 3224, 809, 4760, 810, 2712, 812, 1688, 817, 4504,
197 818, 2456, 820, 1432, 824, 920, 835, 6232, 837, 5208,
198 838, 3160, 841, 4696, 842, 2648, 844, 1624, 849, 4440,
199 850, 2392, 852, 1368, 865, 4312, 866, 2264, 868, 1240,
200 899, 6200, 901, 5176, 902, 3128, 905, 4664, 906, 2616,
201 908, 1592, 913, 4408, 914, 2360, 916, 1336, 929, 4280,
202 930, 2232, 932, 1208, 961, 4216, 962, 2168, 964, 1144,
203 1039, 7684, 1047, 7428, 1051, 6916, 1053, 5892, 1054, 3844,
204 1063, 7300, 1067, 6788, 1069, 5764, 1070, 3716, 1075, 6532,
205 1077, 5508, 1078, 3460, 1081, 4996, 1082, 2948, 1084, 1924,
206 1095, 7236, 1099, 6724, 1101, 5700, 1102, 3652, 1107, 6468,
207 1109, 5444, 1110, 3396, 1113, 4932, 1114, 2884, 1116, 1860,
208 1123, 6340, 1125, 5316, 1126, 3268, 1129, 4804, 1130, 2756,
209 1132, 1732, 1137, 4548, 1138, 2500, 1140, 1476, 1159, 7204,
210 1163, 6692, 1165, 5668, 1166, 3620, 1171, 6436, 1173, 5412,
211 1174, 3364, 1177, 4900, 1178, 2852, 1180, 1828, 1187, 6308,
212 1189, 5284, 1190, 3236, 1193, 4772, 1194, 2724, 1196, 1700,
213 1201, 4516, 1202, 2468, 1204, 1444, 1219, 6244, 1221, 5220,
214 1222, 3172, 1225, 4708, 1226, 2660, 1228, 1636, 1233, 4452,
215 1234, 2404, 1236, 1380, 1249, 4324, 1250, 2276, 1287, 7188,
216 1291, 6676, 1293, 5652, 1294, 3604, 1299, 6420, 1301, 5396,
217 1302, 3348, 1305, 4884, 1306, 2836, 1308, 1812, 1315, 6292,
218 1317, 5268, 1318, 3220, 1321, 4756, 1322, 2708, 1324, 1684,
219 1329, 4500, 1330, 2452, 1332, 1428, 1347, 6228, 1349, 5204,
220 1350, 3156, 1353, 4692, 1354, 2644, 1356, 1620, 1361, 4436,
221 1362, 2388, 1377, 4308, 1378, 2260, 1411, 6196, 1413, 5172,
222 1414, 3124, 1417, 4660, 1418, 2612, 1420, 1588, 1425, 4404,
223 1426, 2356, 1441, 4276, 1442, 2228, 1473, 4212, 1474, 2164,
224 1543, 7180, 1547, 6668, 1549, 5644, 1550, 3596, 1555, 6412,
225 1557, 5388, 1558, 3340, 1561, 4876, 1562, 2828, 1564, 1804,
226 1571, 6284, 1573, 5260, 1574, 3212, 1577, 4748, 1578, 2700,
227 1580, 1676, 1585, 4492, 1586, 2444, 1603, 6220, 1605, 5196,
228 1606, 3148, 1609, 4684, 1610, 2636, 1617, 4428, 1618, 2380,
229 1633, 4300, 1634, 2252, 1667, 6188, 1669, 5164, 1670, 3116,
230 1673, 4652, 1674, 2604, 1681, 4396, 1682, 2348, 1697, 4268,
231 1698, 2220, 1729, 4204, 1730, 2156, 1795, 6172, 1797, 5148,
232 1798, 3100, 1801, 4636, 1802, 2588, 1809, 4380, 1810, 2332,
233 1825, 4252, 1826, 2204, 1857, 4188, 1858, 2140, 1921, 4156,
234 1922, 2108, 2063, 7682, 2071, 7426, 2075, 6914, 2077, 5890,
235 2078, 3842, 2087, 7298, 2091, 6786, 2093, 5762, 2094, 3714,
236 2099, 6530, 2101, 5506, 2102, 3458, 2105, 4994, 2106, 2946,
237 2119, 7234, 2123, 6722, 2125, 5698, 2126, 3650, 2131, 6466,
238 2133, 5442, 2134, 3394, 2137, 4930, 2138, 2882, 2147, 6338,
239 2149, 5314, 2150, 3266, 2153, 4802, 2154, 2754, 2161, 4546,
240 2162, 2498, 2183, 7202, 2187, 6690, 2189, 5666, 2190, 3618,
241 2195, 6434, 2197, 5410, 2198, 3362, 2201, 4898, 2202, 2850,
242 2211, 6306, 2213, 5282, 2214, 3234, 2217, 4770, 2218, 2722,
243 2225, 4514, 2226, 2466, 2243, 6242, 2245, 5218, 2246, 3170,
244 2249, 4706, 2250, 2658, 2257, 4450, 2258, 2402, 2273, 4322,
245 2311, 7186, 2315, 6674, 2317, 5650, 2318, 3602, 2323, 6418,
246 2325, 5394, 2326, 3346, 2329, 4882, 2330, 2834, 2339, 6290,
247 2341, 5266, 2342, 3218, 2345, 4754, 2346, 2706, 2353, 4498,
248 2354, 2450, 2371, 6226, 2373, 5202, 2374, 3154, 2377, 4690,
249 2378, 2642, 2385, 4434, 2401, 4306, 2435, 6194, 2437, 5170,
250 2438, 3122, 2441, 4658, 2442, 2610, 2449, 4402, 2465, 4274,
251 2497, 4210, 2567, 7178, 2571, 6666, 2573, 5642, 2574, 3594,
252 2579, 6410, 2581, 5386, 2582, 3338, 2585, 4874, 2586, 2826,
253 2595, 6282, 2597, 5258, 2598, 3210, 2601, 4746, 2602, 2698,
254 2609, 4490, 2627, 6218, 2629, 5194, 2630, 3146, 2633, 4682,
255 2641, 4426, 2657, 4298, 2691, 6186, 2693, 5162, 2694, 3114,
256 2697, 4650, 2705, 4394, 2721, 4266, 2753, 4202, 2819, 6170,
257 2821, 5146, 2822, 3098, 2825, 4634, 2833, 4378, 2849, 4250,
258 2881, 4186, 2945, 4154, 3079, 7174, 3083, 6662, 3085, 5638,
259 3086, 3590, 3091, 6406, 3093, 5382, 3094, 3334, 3097, 4870,
260 3107, 6278, 3109, 5254, 3110, 3206, 3113, 4742, 3121, 4486,
261 3139, 6214, 3141, 5190, 3145, 4678, 3153, 4422, 3169, 4294,
262 3203, 6182, 3205, 5158, 3209, 4646, 3217, 4390, 3233, 4262,
263 3265, 4198, 3331, 6166, 3333, 5142, 3337, 4630, 3345, 4374,
264 3361, 4246, 3393, 4182, 3457, 4150, 3587, 6158, 3589, 5134,
265 3593, 4622, 3601, 4366, 3617, 4238, 3649, 4174, 3713, 4142,
266 3841, 4126, 4111, 7681, 4119, 7425, 4123, 6913, 4125, 5889,
267 4135, 7297, 4139, 6785, 4141, 5761, 4147, 6529, 4149, 5505,
268 4153, 4993, 4167, 7233, 4171, 6721, 4173, 5697, 4179, 6465,
269 4181, 5441, 4185, 4929, 4195, 6337, 4197, 5313, 4201, 4801,
270 4209, 4545, 4231, 7201, 4235, 6689, 4237, 5665, 4243, 6433,
271 4245, 5409, 4249, 4897, 4259, 6305, 4261, 5281, 4265, 4769,
272 4273, 4513, 4291, 6241, 4293, 5217, 4297, 4705, 4305, 4449,
273 4359, 7185, 4363, 6673, 4365, 5649, 4371, 6417, 4373, 5393,
274 4377, 4881, 4387, 6289, 4389, 5265, 4393, 4753, 4401, 4497,
275 4419, 6225, 4421, 5201, 4425, 4689, 4483, 6193, 4485, 5169,
276 4489, 4657, 4615, 7177, 4619, 6665, 4621, 5641, 4627, 6409,
277 4629, 5385, 4633, 4873, 4643, 6281, 4645, 5257, 4649, 4745,
278 4675, 6217, 4677, 5193, 4739, 6185, 4741, 5161, 4867, 6169,
279 4869, 5145, 5127, 7173, 5131, 6661, 5133, 5637, 5139, 6405,
280 5141, 5381, 5155, 6277, 5157, 5253, 5187, 6213, 5251, 6181,
281 5379, 6165, 5635, 6157, 6151, 7171, 6155, 6659, 6163, 6403,
282 6179, 6275, 6211, 5189, 4681, 4433, 4321, 3142, 2634, 2386,
283 2274, 1612, 1364, 1252, 856, 744, 496,
284 /* Table II 2 of 13. */
285 3, 6144, 5, 5120, 6, 3072, 9, 4608, 10, 2560,
286 12, 1536, 17, 4352, 18, 2304, 20, 1280, 24, 768,
287 33, 4224, 34, 2176, 36, 1152, 40, 640, 48, 384,
288 65, 4160, 66, 2112, 68, 1088, 72, 576, 80, 320,
289 96, 192, 129, 4128, 130, 2080, 132, 1056, 136, 544,
290 144, 288, 257, 4112, 258, 2064, 260, 1040, 264, 528,
291 513, 4104, 514, 2056, 516, 1032, 1025, 4100, 1026, 2052,
292 2049, 4098, 4097, 2050, 1028, 520, 272, 160
298 /*===========================================*/
299 /* Local function prototypes */
300 /*===========================================*/
301 static gboolean is_string_valid (const gchar *data);
303 static gchar *onecode_encode (const gchar *data);
305 static void int104_mult_uint (Int104 *x,
307 static void int104_add_uint (Int104 *x,
309 static void int104_add_uint64 (Int104 *x,
311 static guint int104_div_uint (Int104 *x,
314 static void int104_print (Int104 *x);
317 static unsigned short USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr );
319 static lglBarcode *onecode_vectorize (const gchar *code);
322 /****************************************************************************/
323 /* Generate list of lines that form the barcode for the given digits. */
324 /****************************************************************************/
326 lgl_barcode_onecode_new (lglBarcodeType type,
328 gboolean checksum_flag,
336 if ( type != LGL_BARCODE_TYPE_ONECODE )
338 g_message ("Invalid barcode type for ONECODE backend.");
342 /* First get code string */
343 code = onecode_encode (data);
348 /* Now vectorize encoded data. */
349 bc = onecode_vectorize (code);
357 /*--------------------------------------------------------------------------*/
358 /* PRIVATE. Generate string of symbols, representing barcode. */
359 /*--------------------------------------------------------------------------*/
361 onecode_encode (const gchar *data)
363 Int104 value = {{0}};
371 if ( !is_string_valid (data) )
377 /*-----------------------------------------------------------*/
378 /* Step 1 -- Conversion of Data Fields into Binary Data */
379 /*-----------------------------------------------------------*/
381 /* Step 1.a -- Routing Code */
382 for ( i = 20; data[i] != 0; i++ )
384 int104_mult_uint (&value, 10);
385 int104_add_uint (&value, data[i] - '0');
392 int104_add_uint (&value, 1);
395 int104_add_uint (&value, 1);
396 int104_add_uint (&value, 100000);
399 int104_add_uint (&value, 1);
400 int104_add_uint (&value, 100000);
401 int104_add_uint64 (&value, 1000000000);
404 return NULL; /* Should not happen if length tests passed. */
408 /* Step 1.b -- Tracking Code */
409 int104_mult_uint (&value, 10);
410 int104_add_uint (&value, data[0] - '0');
411 int104_mult_uint (&value, 5);
412 int104_add_uint (&value, data[1] - '0');
414 for ( i = 2; i < 20; i++ )
416 int104_mult_uint (&value, 10);
417 int104_add_uint (&value, data[i] - '0');
421 /*-----------------------------------------------------------*/
422 /* Step 2 -- Generation of 11-Bit CRC on Binary Data */
423 /*-----------------------------------------------------------*/
425 crc11 = USPS_MSB_Math_CRC11GenerateFrameCheckSequence( value.byte );
428 /*-----------------------------------------------------------*/
429 /* Step 3 -- Conversion of Binary Data to Codewords */
430 /*-----------------------------------------------------------*/
432 codeword[9] = int104_div_uint (&value, 636);
433 for ( i = 8; i >= 1; i-- )
435 codeword[i] = int104_div_uint (&value, 1365);
437 codeword[0] = int104_div_uint (&value, 659);
440 /*-----------------------------------------------------------*/
441 /* Step 4 -- Inserting Additional Information into Codewords */
442 /*-----------------------------------------------------------*/
445 codeword[0] += (crc11 & 0x400) ? 659 : 0;
448 /*-----------------------------------------------------------*/
449 /* Step 5 -- Conversion from Codewords to Characters */
450 /*-----------------------------------------------------------*/
452 for ( i = 0; i < 10; i++ )
454 character[i] = character_table[ codeword[i] ];
456 if ( crc11 & (1<<i) )
458 character[i] = ~character[i] & 0x1FFF;
463 /*-----------------------------------------------------------*/
464 /* Step 6 -- Conversion from Characters to IMail Barcode */
465 /*-----------------------------------------------------------*/
467 code = g_string_new ("");
468 for ( i = 0; i < 65; i++ )
470 d = (character[ bar_map[i].descender.i ] & bar_map[i].descender.mask) != 0;
471 a = (character[ bar_map[i].ascender.i ] & bar_map[i].ascender.mask) != 0;
473 code = g_string_append (code, tdaf_table[ (a<<1) + d ]);
477 return g_string_free (code, FALSE);
481 /*--------------------------------------------------------------------------*/
482 /* Validate if string is of proper length & contains only valid characters. */
483 /*--------------------------------------------------------------------------*/
485 is_string_valid (const gchar *data)
494 str_length = strlen (data);
495 if ( (str_length != 20) &&
496 (str_length != 25) &&
497 (str_length != 29) &&
503 for ( p = (gchar *)data; *p != 0; p++ )
505 if (!g_ascii_isdigit (*p))
513 return FALSE; /* Invalid Barcode Identifier. */
520 /*--------------------------------------------------------------------------*/
521 /* Multiply 104 bit integer by unsigned int. */
522 /*--------------------------------------------------------------------------*/
524 int104_mult_uint (Int104 *x,
531 for ( i = 12; i >= 0; i-- )
533 temp = x->byte[i] * y + carry;
535 x->byte[i] = temp & 0xFF;
541 /*--------------------------------------------------------------------------*/
542 /* Add unsigned int to 104 bit integer. */
543 /*--------------------------------------------------------------------------*/
545 int104_add_uint (Int104 *x,
552 for ( i = 12; i >= 0; i-- )
554 temp = x->byte[i] + (y & 0xFF) + carry;
556 x->byte[i] = temp & 0xFF;
563 /*--------------------------------------------------------------------------*/
564 /* Add unsigned 64 bit integer to 104 bit integer. */
565 /*--------------------------------------------------------------------------*/
567 int104_add_uint64 (Int104 *x,
574 for ( i = 12; i >= 0; i-- )
576 temp = x->byte[i] + (y & 0xFF) + carry;
578 x->byte[i] = temp & 0xFF;
585 /*--------------------------------------------------------------------------*/
586 /* Divide 104 bit integer by unsigned int. */
587 /*--------------------------------------------------------------------------*/
589 int104_div_uint (Int104 *x,
595 for ( i = 0; i < 13; i++ )
597 tmp = x->byte[i] + (carry<<8);
598 x->byte[i] = tmp / y;
606 /*--------------------------------------------------------------------------*/
607 /* Print hex representation of 104 bit integer. (For debugging) */
608 /*--------------------------------------------------------------------------*/
611 int104_print (Int104 *x)
615 for ( i = 0; i < 13; i++ )
617 g_print ("%02x ", x->byte[i] & 0xFF);
624 /***************************************************************************
625 ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence
628 ** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which
629 ** are right justified - ie: the leftmost 2 bits of the first byte do not
630 ** hold data and must be set to zero.
633 ** return unsigned short - 11 bit Frame Check Sequence (right justified)
635 ** From Appendix C of USPS publication USPS-B-3200E, 07/08/05.
636 ***************************************************************************/
638 USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr )
640 unsigned short GeneratorPolynomial = 0x0F35;
641 unsigned short FrameCheckSequence = 0x07FF;
645 /* Do most significant byte skipping the 2 most significant bits */
646 Data = *ByteArrayPtr << 5;
648 for ( Bit = 2; Bit < 8; Bit++ )
650 if ( (FrameCheckSequence ^ Data) & 0x400 )
652 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
656 FrameCheckSequence = (FrameCheckSequence << 1);
658 FrameCheckSequence &= 0x7FF;
662 /* Do rest of the bytes */
663 for ( ByteIndex = 1; ByteIndex < 13; ByteIndex++ )
665 Data = *ByteArrayPtr << 3;
667 for ( Bit = 0; Bit < 8; Bit++ )
669 if ( (FrameCheckSequence ^ Data) & 0x0400 )
671 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
675 FrameCheckSequence = (FrameCheckSequence << 1);
677 FrameCheckSequence &= 0x7FF;
682 return FrameCheckSequence;
686 /*--------------------------------------------------------------------------*/
687 /* Vectorize encoded data. */
688 /*--------------------------------------------------------------------------*/
690 onecode_vectorize (const gchar *code)
694 gdouble x, y, length, width;
696 bc = lgl_barcode_new ();
698 /* Now traverse the code string and create a list of lines */
699 x = ONECODE_HORIZ_MARGIN;
700 for (p = (gchar *)code; *p != 0; p++)
702 y = ONECODE_VERT_MARGIN;
706 y += ONECODE_TRACKER_OFFSET;
707 length = ONECODE_TRACKER_HEIGHT;
710 y += ONECODE_DESCENDER_OFFSET;
711 length = ONECODE_DESCENDER_HEIGHT;
714 y += ONECODE_ASCENDER_OFFSET;
715 length = ONECODE_ASCENDER_HEIGHT;
718 y += ONECODE_FULL_OFFSET;
719 length = ONECODE_FULL_HEIGHT;
724 width = ONECODE_BAR_WIDTH;
726 lgl_barcode_add_box (bc, x, y, width, length);
728 x += ONECODE_BAR_PITCH;
731 bc->width = x + ONECODE_HORIZ_MARGIN;
732 bc->height = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN;
741 * Local Variables: -- emacs
743 * c-basic-offset: 8 -- emacs
744 * tab-width: 8 -- emacs
745 * indent-tabs-mode: nil -- emacs