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
296 /*===========================================*/
297 /* Local function prototypes */
298 /*===========================================*/
299 static gboolean onecode_is_data_valid (const gchar *data);
301 static gchar *onecode_encode (const gchar *data);
303 static lglBarcode *onecode_vectorize (const gchar *code);
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 );
320 /****************************************************************************/
321 /* Generate new One Code barcode structure from data. */
322 /****************************************************************************/
324 lgl_barcode_onecode_new (lglBarcodeType type,
326 gboolean checksum_flag,
334 if ( type != LGL_BARCODE_TYPE_ONECODE )
336 g_message ("Invalid barcode type for ONECODE backend.");
342 if ( !onecode_is_data_valid (data) )
347 /* Now get code string */
348 code = onecode_encode (data);
353 /* Now vectorize encoded data. */
354 bc = onecode_vectorize (code);
362 /*--------------------------------------------------------------------------*/
363 /* Validate if string is of proper length & contains only valid characters. */
364 /*--------------------------------------------------------------------------*/
366 onecode_is_data_valid (const gchar *data)
376 str_length = strlen (data);
377 if ( (str_length != 20) &&
378 (str_length != 25) &&
379 (str_length != 29) &&
385 for ( p = (gchar *)data; *p != 0; p++ )
387 if (!g_ascii_isdigit (*p))
395 return FALSE; /* Invalid Barcode Identifier. */
402 /*--------------------------------------------------------------------------*/
403 /* PRIVATE. Generate string of symbols, representing barcode. */
404 /*--------------------------------------------------------------------------*/
406 onecode_encode (const gchar *data)
408 Int104 value = {{0}};
416 /*-----------------------------------------------------------*/
417 /* Step 1 -- Conversion of Data Fields into Binary Data */
418 /*-----------------------------------------------------------*/
420 /* Step 1.a -- Routing Code */
421 for ( i = 20; data[i] != 0; i++ )
423 int104_mult_uint (&value, 10);
424 int104_add_uint (&value, data[i] - '0');
431 int104_add_uint (&value, 1);
434 int104_add_uint (&value, 1);
435 int104_add_uint (&value, 100000);
438 int104_add_uint (&value, 1);
439 int104_add_uint (&value, 100000);
440 int104_add_uint64 (&value, 1000000000);
443 return NULL; /* Should not happen if length tests passed. */
447 /* Step 1.b -- Tracking Code */
448 int104_mult_uint (&value, 10);
449 int104_add_uint (&value, data[0] - '0');
450 int104_mult_uint (&value, 5);
451 int104_add_uint (&value, data[1] - '0');
453 for ( i = 2; i < 20; i++ )
455 int104_mult_uint (&value, 10);
456 int104_add_uint (&value, data[i] - '0');
460 /*-----------------------------------------------------------*/
461 /* Step 2 -- Generation of 11-Bit CRC on Binary Data */
462 /*-----------------------------------------------------------*/
464 crc11 = USPS_MSB_Math_CRC11GenerateFrameCheckSequence( value.byte );
467 /*-----------------------------------------------------------*/
468 /* Step 3 -- Conversion of Binary Data to Codewords */
469 /*-----------------------------------------------------------*/
471 codeword[9] = int104_div_uint (&value, 636);
472 for ( i = 8; i >= 1; i-- )
474 codeword[i] = int104_div_uint (&value, 1365);
476 codeword[0] = int104_div_uint (&value, 659);
479 /*-----------------------------------------------------------*/
480 /* Step 4 -- Inserting Additional Information into Codewords */
481 /*-----------------------------------------------------------*/
484 codeword[0] += (crc11 & 0x400) ? 659 : 0;
487 /*-----------------------------------------------------------*/
488 /* Step 5 -- Conversion from Codewords to Characters */
489 /*-----------------------------------------------------------*/
491 for ( i = 0; i < 10; i++ )
493 character[i] = character_table[ codeword[i] ];
495 if ( crc11 & (1<<i) )
497 character[i] = ~character[i] & 0x1FFF;
502 /*-----------------------------------------------------------*/
503 /* Step 6 -- Conversion from Characters to IMail Barcode */
504 /*-----------------------------------------------------------*/
506 code = g_string_new ("");
507 for ( i = 0; i < 65; i++ )
509 d = (character[ bar_map[i].descender.i ] & bar_map[i].descender.mask) != 0;
510 a = (character[ bar_map[i].ascender.i ] & bar_map[i].ascender.mask) != 0;
512 code = g_string_append (code, tdaf_table[ (a<<1) + d ]);
516 return g_string_free (code, FALSE);
520 /*--------------------------------------------------------------------------*/
521 /* Vectorize encoded data. */
522 /*--------------------------------------------------------------------------*/
524 onecode_vectorize (const gchar *code)
528 gdouble x, y, length, width;
530 bc = lgl_barcode_new ();
532 /* Now traverse the code string and create a list of lines */
533 x = ONECODE_HORIZ_MARGIN;
534 for (p = (gchar *)code; *p != 0; p++)
536 y = ONECODE_VERT_MARGIN;
540 y += ONECODE_TRACKER_OFFSET;
541 length = ONECODE_TRACKER_HEIGHT;
544 y += ONECODE_DESCENDER_OFFSET;
545 length = ONECODE_DESCENDER_HEIGHT;
548 y += ONECODE_ASCENDER_OFFSET;
549 length = ONECODE_ASCENDER_HEIGHT;
552 y += ONECODE_FULL_OFFSET;
553 length = ONECODE_FULL_HEIGHT;
558 width = ONECODE_BAR_WIDTH;
560 lgl_barcode_add_box (bc, x, y, width, length);
562 x += ONECODE_BAR_PITCH;
565 bc->width = x + ONECODE_HORIZ_MARGIN;
566 bc->height = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN;
572 /*--------------------------------------------------------------------------*/
573 /* Multiply 104 bit integer by unsigned int. */
574 /*--------------------------------------------------------------------------*/
576 int104_mult_uint (Int104 *x,
583 for ( i = 12; i >= 0; i-- )
585 temp = x->byte[i] * y + carry;
587 x->byte[i] = temp & 0xFF;
593 /*--------------------------------------------------------------------------*/
594 /* Add unsigned int to 104 bit integer. */
595 /*--------------------------------------------------------------------------*/
597 int104_add_uint (Int104 *x,
604 for ( i = 12; i >= 0; i-- )
606 temp = x->byte[i] + (y & 0xFF) + carry;
608 x->byte[i] = temp & 0xFF;
615 /*--------------------------------------------------------------------------*/
616 /* Add unsigned 64 bit integer to 104 bit integer. */
617 /*--------------------------------------------------------------------------*/
619 int104_add_uint64 (Int104 *x,
626 for ( i = 12; i >= 0; i-- )
628 temp = x->byte[i] + (y & 0xFF) + carry;
630 x->byte[i] = temp & 0xFF;
637 /*--------------------------------------------------------------------------*/
638 /* Divide 104 bit integer by unsigned int. */
639 /*--------------------------------------------------------------------------*/
641 int104_div_uint (Int104 *x,
647 for ( i = 0; i < 13; i++ )
649 tmp = x->byte[i] + (carry<<8);
650 x->byte[i] = tmp / y;
658 /*--------------------------------------------------------------------------*/
659 /* Print hex representation of 104 bit integer. (For debugging) */
660 /*--------------------------------------------------------------------------*/
663 int104_print (Int104 *x)
667 for ( i = 0; i < 13; i++ )
669 g_print ("%02x ", x->byte[i] & 0xFF);
676 /***************************************************************************
677 ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence
680 ** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which
681 ** are right justified - ie: the leftmost 2 bits of the first byte do not
682 ** hold data and must be set to zero.
685 ** return unsigned short - 11 bit Frame Check Sequence (right justified)
687 ** From Appendix C of USPS publication USPS-B-3200E, 07/08/05.
688 ***************************************************************************/
690 USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr )
692 unsigned short GeneratorPolynomial = 0x0F35;
693 unsigned short FrameCheckSequence = 0x07FF;
697 /* Do most significant byte skipping the 2 most significant bits */
698 Data = *ByteArrayPtr << 5;
700 for ( Bit = 2; Bit < 8; Bit++ )
702 if ( (FrameCheckSequence ^ Data) & 0x400 )
704 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
708 FrameCheckSequence = (FrameCheckSequence << 1);
710 FrameCheckSequence &= 0x7FF;
714 /* Do rest of the bytes */
715 for ( ByteIndex = 1; ByteIndex < 13; ByteIndex++ )
717 Data = *ByteArrayPtr << 3;
719 for ( Bit = 0; Bit < 8; Bit++ )
721 if ( (FrameCheckSequence ^ Data) & 0x0400 )
723 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
727 FrameCheckSequence = (FrameCheckSequence << 1);
729 FrameCheckSequence &= 0x7FF;
734 return FrameCheckSequence;
741 * Local Variables: -- emacs
743 * c-basic-offset: 8 -- emacs
744 * tab-width: 8 -- emacs
745 * indent-tabs-mode: nil -- emacs