1 /*------------------------------------------------------------------------
2  *  Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
3  *
4  *  This file is part of the ZBar Bar Code Reader.
5  *
6  *  The ZBar Bar Code Reader is free software; you can redistribute it
7  *  and/or modify it under the terms of the GNU Lesser Public License as
8  *  published by the Free Software Foundation; either version 2.1 of
9  *  the License, or (at your option) any later version.
10  *
11  *  The ZBar Bar Code Reader is distributed in the hope that it will be
12  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser Public License
17  *  along with the ZBar Bar Code Reader; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  *  Boston, MA  02110-1301  USA
20  *
21  *  http://sourceforge.net/projects/zbar
22  *------------------------------------------------------------------------*/
23 
24 #include <config.h>
25 #include <zbar.h>
26 
27 #ifdef DEBUG_EAN
28 # define DEBUG_LEVEL (DEBUG_EAN)
29 #endif
30 #include "debug.h"
31 #include "decoder.h"
32 
33 /* partial decode symbol location */
34 typedef enum symbol_partial_e {
35     EAN_LEFT   = 0x0000,
36     EAN_RIGHT  = 0x1000,
37 } symbol_partial_t;
38 
39 /* convert compact encoded D2E1E2 to character (bit4 is parity) */
40 static const unsigned char digits[] = {  /* E1   E2 */
41     0x06, 0x10, 0x04, 0x13,              /*  2  2-5 */
42     0x19, 0x08, 0x11, 0x05,              /*  3  2-5 (d2 <= thr) */
43     0x09, 0x12, 0x07, 0x15,              /*  4  2-5 (d2 <= thr) */
44     0x16, 0x00, 0x14, 0x03,              /*  5  2-5 */
45     0x18, 0x01, 0x02, 0x17,              /* E1E2=43,44,33,34 (d2 > thr) */
46 };
47 
48 static const unsigned char parity_decode[] = {
49     0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */
50 
51     /* UPC-E check digit encoding */
52     0xff,
53     0xff,
54     0x0f, /* [07] BBBAAA = 0 */
55     0xff,
56     0x1f, /* [0b] BBABAA = 1 */
57     0x2f, /* [0d] BBAABA = 2 */
58     0xf3, /* [0e] BBAAAB = 3 */
59     0xff,
60     0x4f, /* [13] BABBAA = 4 */
61     0x7f, /* [15] BABABA = 7 */
62     0xf8, /* [16] BABAAB = 8 */
63     0x5f, /* [19] BAABBA = 5 */
64     0xf9, /* [1a] BAABAB = 9 */
65     0xf6, /* [1c] BAAABB = 6 */
66     0xff,
67 
68     /* LEFT half EAN-13 leading digit */
69     0xff,
70     0x6f, /* [23] ABBBAA = 6 */
71     0x9f, /* [25] ABBABA = 9 */
72     0xf5, /* [26] ABBAAB = 5 */
73     0x8f, /* [29] ABABBA = 8 */
74     0xf7, /* [2a] ABABAB = 7 */
75     0xf4, /* [2c] ABAABB = 4 */
76     0xff,
77     0x3f, /* [31] AABBBA = 3 */
78     0xf2, /* [32] AABBAB = 2 */
79     0xf1, /* [34] AABABB = 1 */
80     0xff,
81     0xff,
82     0xff,
83     0xff,
84     0x0f, /* [3f] AAAAAA = 0 */
85 };
86 
87 #ifdef DEBUG_EAN
88 static unsigned char debug_buf[0x18];
89 
dsprintbuf(ean_decoder_t * ean)90 static inline const unsigned char *dsprintbuf(ean_decoder_t *ean)
91 {
92     int i;
93     for(i = 0; i < 7; i++)
94         debug_buf[i] = ((ean->buf[0] < 0 || ean->buf[i] < 0)
95                         ? '-'
96                         : ean->buf[i] + '0');
97     debug_buf[i] = ' ';
98     for(; i < 13; i++)
99         debug_buf[i + 1] = ((ean->buf[7] < 0 || ean->buf[i] < 0)
100                             ? '-'
101                             : ean->buf[i] + '0');
102     debug_buf[i + 1] = ' ';
103     for(; i < 18; i++)
104         debug_buf[i + 2] = ((ean->buf[13] < 0 || ean->buf[i] < 0)
105                             ? '-'
106                             : ean->buf[i] + '0');
107     debug_buf[i + 2] = '\0';
108     return(debug_buf);
109 }
110 #endif
111 
check_width(unsigned w0,unsigned w1)112 static inline int check_width (unsigned w0,
113                                unsigned w1)
114 {
115     unsigned dw0 = w0;
116     w0 *= 8;
117     w1 *= 8;
118     return(w0 - dw0 <= w1 && w1 <= w0 + dw0);
119 }
120 
121 /* evaluate previous N (>= 2) widths as auxiliary pattern,
122  * using preceding 4 as character width
123  */
aux_end(zbar_decoder_t * dcode,unsigned char fwd)124 static inline signed char aux_end (zbar_decoder_t *dcode,
125                                    unsigned char fwd)
126 {
127     signed char code, i;
128 
129     /* reference width from previous character */
130     unsigned s = calc_s(dcode, 4 + fwd, 4);
131 
132     /* check quiet zone */
133     unsigned qz = get_width(dcode, 0);
134     if(!fwd && qz && qz <= s * 3 / 4) {
135         dbprintf(2, " [invalid quiet]");
136         return(-1);
137     }
138 
139     dbprintf(2, " (");
140     code = 0;
141     for(i = 1 - fwd; i < 3 + fwd; i++) {
142         unsigned e = get_width(dcode, i) + get_width(dcode, i + 1);
143         dbprintf(2, " %d", e);
144         code = (code << 2) | decode_e(e, s, 7);
145         if(code < 0) {
146             dbprintf(2, " [invalid end guard]");
147             return(-1);
148         }
149     }
150     dbprintf(2, ") s=%d aux=%x", s, code);
151     return(code);
152 }
153 
154 /* determine possible auxiliary pattern
155  * using current 4 as possible character
156  */
aux_start(zbar_decoder_t * dcode)157 static inline signed char aux_start (zbar_decoder_t *dcode)
158 {
159     /* FIXME NB add-on has no guard in reverse */
160     unsigned e1, e2 = get_width(dcode, 5) + get_width(dcode, 6);
161     unsigned char E1;
162     if(dcode->ean.s4 < 6)
163         return(-1);
164 
165     if(decode_e(e2, dcode->ean.s4, 7)) {
166         dbprintf(2, " [invalid any]");
167         return(-1);
168     }
169 
170     e1 = get_width(dcode, 4) + get_width(dcode, 5);
171     E1 = decode_e(e1, dcode->ean.s4, 7);
172 
173     if(get_color(dcode) == ZBAR_BAR) {
174         /* check for quiet-zone */
175         unsigned qz = get_width(dcode, 7);
176         if(!qz || qz > dcode->ean.s4 * 3 / 4) {
177             if(!E1) {
178                 dbprintf(2, " [valid normal]");
179                 return(0); /* normal symbol start */
180             }
181             else if(E1 == 1) {
182                 dbprintf(2, " [valid add-on]");
183                 return(STATE_ADDON); /* add-on symbol start */
184             }
185         }
186         dbprintf(2, " [invalid start]");
187         return(-1);
188     }
189 
190     if(!E1) {
191         /* attempting decode from SPACE => validate center guard */
192         unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7);
193         unsigned e4 = get_width(dcode, 7) + get_width(dcode, 8);
194         if(!decode_e(e3, dcode->ean.s4, 7) &&
195            !decode_e(e4, dcode->ean.s4, 7)) {
196             dbprintf(2, " [valid center]");
197             return(0); /* start after center guard */
198         }
199     }
200     dbprintf(2, " [invalid center]");
201     return(-1);
202 }
203 
204 /* check addon delimiter using current 4 as character
205  */
aux_mid(zbar_decoder_t * dcode)206 static inline signed char aux_mid (zbar_decoder_t *dcode)
207 {
208     unsigned e = get_width(dcode, 4) + get_width(dcode, 5);
209     return(decode_e(e, dcode->ean.s4, 7));
210 }
211 
212 /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */
decode4(zbar_decoder_t * dcode)213 static inline signed char decode4 (zbar_decoder_t *dcode)
214 {
215     signed char code;
216 
217     /* calculate similar edge measurements */
218     unsigned e1 = ((get_color(dcode) == ZBAR_BAR)
219                    ? get_width(dcode, 0) + get_width(dcode, 1)
220                    : get_width(dcode, 2) + get_width(dcode, 3));
221     unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2);
222     dbprintf(2, "\n        e1=%d e2=%d", e1, e2);
223 
224     if(dcode->ean.s4 < 6)
225         return(-1);
226 
227     /* create compacted encoding for direct lookup */
228     code = ((decode_e(e1, dcode->ean.s4, 7) << 2) |
229              decode_e(e2, dcode->ean.s4, 7));
230     if(code < 0)
231         return(-1);
232     dbprintf(2, " code=%x", code);
233 
234     /* 4 combinations require additional determinant (D2)
235        E1E2 == 34 (0110)
236        E1E2 == 43 (1001)
237        E1E2 == 33 (0101)
238        E1E2 == 44 (1010)
239      */
240     if((1 << code) & 0x0660) {
241         unsigned char mid, alt;
242         /* use sum of bar widths */
243         unsigned d2 = ((get_color(dcode) == ZBAR_BAR)
244                        ? get_width(dcode, 0) + get_width(dcode, 2)
245                        : get_width(dcode, 1) + get_width(dcode, 3));
246         d2 *= 7;
247         mid = (((1 << code) & 0x0420)
248                              ? 3     /* E1E2 in 33,44 */
249                              : 4);   /* E1E2 in 34,43 */
250         alt = d2 > (mid * dcode->ean.s4);
251         if(alt)
252             code = ((code >> 1) & 3) | 0x10; /* compress code space */
253         dbprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt);
254     }
255     dbprintf(2, " char=%02x", digits[(unsigned char)code]);
256     zassert(code < 0x14, -1, "code=%02x e1=%x e2=%x s4=%x color=%x\n",
257             code, e1, e2, dcode->ean.s4, get_color(dcode));
258     return(code);
259 }
260 
ean_part_end2(ean_decoder_t * ean,ean_pass_t * pass)261 static inline char ean_part_end2 (ean_decoder_t *ean,
262                                   ean_pass_t *pass)
263 {
264     if(!TEST_CFG(ean->ean2_config, ZBAR_CFG_ENABLE))
265         return(ZBAR_NONE);
266 
267     /* extract parity bits */
268     unsigned char par = ((pass->raw[1] & 0x10) >> 3 |
269                          (pass->raw[2] & 0x10) >> 4);
270     /* calculate "checksum" */
271     unsigned char chk = ~((pass->raw[1] & 0xf) * 10 +
272                           (pass->raw[2] & 0xf)) & 0x3;
273     dbprintf(2, " par=%x chk=%x", par, chk);
274     if(par != chk)
275         return(ZBAR_NONE);
276 
277     dbprintf(2, "\n");
278     dbprintf(1, "decode2=%x%x\n",
279              pass->raw[1] & 0xf, pass->raw[2] & 0xf);
280     return(ZBAR_EAN2);
281 }
282 
ean_part_end4(ean_pass_t * pass,unsigned char fwd)283 static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass,
284                                                 unsigned char fwd)
285 {
286     /* extract parity bits */
287     unsigned char par = ((pass->raw[1] & 0x10) >> 1 |
288                          (pass->raw[2] & 0x10) >> 2 |
289                          (pass->raw[3] & 0x10) >> 3 |
290                          (pass->raw[4] & 0x10) >> 4);
291 
292     dbprintf(2, " par=%x", par);
293     if(par && par != 0xf)
294         /* invalid parity combination */
295         return(ZBAR_NONE);
296 
297     if((!par) == fwd) {
298         /* reverse sampled digits */
299         unsigned char tmp = pass->raw[1];
300         pass->state |= STATE_REV;
301         pass->raw[1] = pass->raw[4];
302         pass->raw[4] = tmp;
303         tmp = pass->raw[2];
304         pass->raw[2] = pass->raw[3];
305         pass->raw[3] = tmp;
306     }
307 
308     dbprintf(2, "\n");
309     dbprintf(1, "decode4=%x%x%x%x\n",
310              pass->raw[1] & 0xf, pass->raw[2] & 0xf,
311              pass->raw[3] & 0xf, pass->raw[4] & 0xf);
312     if(!par)
313         return(ZBAR_EAN8 | EAN_RIGHT);
314     return(ZBAR_EAN8 | EAN_LEFT);
315 }
316 
ean_part_end5(ean_decoder_t * ean,ean_pass_t * pass)317 static inline char ean_part_end5 (ean_decoder_t *ean,
318                                   ean_pass_t *pass)
319 {
320     if(!TEST_CFG(ean->ean5_config, ZBAR_CFG_ENABLE))
321         return(ZBAR_NONE);
322 
323     /* extract parity bits */
324     unsigned char par = ((pass->raw[1] & 0x10) |
325                          (pass->raw[2] & 0x10) >> 1 |
326                          (pass->raw[3] & 0x10) >> 2 |
327                          (pass->raw[4] & 0x10) >> 3 |
328                          (pass->raw[5] & 0x10) >> 4);
329     /* calculate checksum */
330     unsigned char chk = (((pass->raw[1] & 0x0f) +
331                           (pass->raw[2] & 0x0f) * 3 +
332                           (pass->raw[3] & 0x0f) +
333                           (pass->raw[4] & 0x0f) * 3 +
334                           (pass->raw[5] & 0x0f)) * 3) % 10;
335 
336     unsigned char parchk = parity_decode[par >> 1];
337     if(par & 1)
338         parchk >>= 4;
339     parchk &= 0xf;
340     dbprintf(2, " par=%x(%d) chk=%d", par, parchk, chk);
341     if(parchk != chk)
342         return(ZBAR_NONE);
343 
344     dbprintf(2, "\n");
345     dbprintf(1, "decode5=%x%x%x%x%x\n",
346              pass->raw[1] & 0xf, pass->raw[2] & 0xf,
347              pass->raw[3] & 0xf, pass->raw[4] & 0xf,
348              pass->raw[5] & 0xf);
349 
350     return(ZBAR_EAN5);
351 }
352 
ean_part_end7(ean_decoder_t * ean,ean_pass_t * pass,unsigned char fwd)353 static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean,
354                                                 ean_pass_t *pass,
355                                                 unsigned char fwd)
356 {
357     /* calculate parity index */
358     unsigned char par = ((fwd)
359                          ? ((pass->raw[1] & 0x10) << 1 |
360                             (pass->raw[2] & 0x10) |
361                             (pass->raw[3] & 0x10) >> 1 |
362                             (pass->raw[4] & 0x10) >> 2 |
363                             (pass->raw[5] & 0x10) >> 3 |
364                             (pass->raw[6] & 0x10) >> 4)
365                          : ((pass->raw[1] & 0x10) >> 4 |
366                             (pass->raw[2] & 0x10) >> 3 |
367                             (pass->raw[3] & 0x10) >> 2 |
368                             (pass->raw[4] & 0x10) >> 1 |
369                             (pass->raw[5] & 0x10) |
370                             (pass->raw[6] & 0x10) << 1));
371 
372     /* lookup parity combination */
373     pass->raw[0] = parity_decode[par >> 1];
374     if(par & 1)
375         pass->raw[0] >>= 4;
376     pass->raw[0] &= 0xf;
377     dbprintf(2, " par=%02x(%x)", par, pass->raw[0]);
378 
379     if(pass->raw[0] == 0xf)
380         /* invalid parity combination */
381         return(ZBAR_NONE);
382 
383     if((!par) == fwd) {
384         unsigned char i;
385         pass->state |= STATE_REV;
386         /* reverse sampled digits */
387         for(i = 1; i < 4; i++) {
388             unsigned char tmp = pass->raw[i];
389             pass->raw[i] = pass->raw[7 - i];
390             pass->raw[7 - i] = tmp;
391         }
392     }
393 
394     dbprintf(2, "\n");
395     dbprintf(1, "decode=%x%x%x%x%x%x%x(%02x)\n",
396              pass->raw[0] & 0xf, pass->raw[1] & 0xf,
397              pass->raw[2] & 0xf, pass->raw[3] & 0xf,
398              pass->raw[4] & 0xf, pass->raw[5] & 0xf,
399              pass->raw[6] & 0xf, par);
400 
401     if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) {
402         if(!par)
403             return(ZBAR_EAN13 | EAN_RIGHT);
404         if(par & 0x20)
405             return(ZBAR_EAN13 | EAN_LEFT);
406     }
407     if(par && !(par & 0x20))
408         return(ZBAR_UPCE);
409 
410     return(ZBAR_NONE);
411 }
412 
413 /* update state for one of 4 parallel passes */
decode_pass(zbar_decoder_t * dcode,ean_pass_t * pass)414 static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode,
415                                               ean_pass_t *pass)
416 {
417     unsigned char idx, fwd;
418     pass->state++;
419     idx = pass->state & STATE_IDX;
420     fwd = pass->state & 1;
421 
422     if(get_color(dcode) == ZBAR_SPACE) {
423         if(pass->state & STATE_ADDON) {
424             dbprintf(2, " i=%d", idx);
425             if(idx == 0x09 || idx == 0x21) {
426                 unsigned qz = get_width(dcode, 0);
427                 unsigned s = calc_s(dcode, 1, 4);
428                 zbar_symbol_type_t part = !qz || (qz >= s * 3 / 4);
429                 if(part && idx == 0x09)
430                     part = ean_part_end2(&dcode->ean, pass);
431                 else if(part)
432                     part = ean_part_end5(&dcode->ean, pass);
433 
434                 if(part || idx == 0x21) {
435                     dcode->ean.direction = 0;
436                     pass->state = -1;
437                     return(part);
438                 }
439             }
440             if((idx & 7) == 1) {
441                 dbprintf(2, " +");
442                 pass->state += 2;
443                 idx += 2;
444             }
445         }
446         else if((idx == 0x10 || idx == 0x11) &&
447                 TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) &&
448                 !aux_end(dcode, fwd)) {
449             dbprintf(2, " fwd=%x", fwd);
450             zbar_symbol_type_t part = ean_part_end4(pass, fwd);
451             if(part)
452                 dcode->ean.direction = (pass->state & STATE_REV) != 0;
453             pass->state = -1;
454             return(part);
455         }
456 	else if((idx == 0x18 || idx == 0x19)) {
457 	  zbar_symbol_type_t part = ZBAR_NONE;
458 	  dbprintf(2, " fwd=%x", fwd);
459 	  if(!aux_end(dcode, fwd) && pass->raw[5] != 0xff)
460 	    part = ean_part_end7(&dcode->ean, pass, fwd);
461 	  if(part)
462 	    dcode->ean.direction = (pass->state & STATE_REV) != 0;
463 	  pass->state = -1;
464 	  return(part);
465         }
466     }
467 
468     if(pass->state & STATE_ADDON)
469         idx >>= 1;
470 
471     if(!(idx & 0x03) && idx <= 0x14) {
472         signed char code = -1;
473         unsigned w = pass->width;
474         if(!dcode->ean.s4)
475             return(0);
476         /* validate guard bars before decoding first char of symbol */
477         if(!pass->state) {
478             pass->state = aux_start(dcode);
479             pass->width = dcode->ean.s4;
480             if(pass->state < 0)
481                 return(0);
482             idx = pass->state & STATE_IDX;
483         }
484         else {
485             w = check_width(w, dcode->ean.s4);
486             if(w)
487                 pass->width = (pass->width + dcode->ean.s4 * 3) / 4;
488         }
489 
490         if(w)
491             code = decode4(dcode);
492         else
493             dbprintf(2, " [bad width]");
494 
495         if((code < 0 && idx != 0x10) ||
496            (idx > 0 && (pass->state & STATE_ADDON) && aux_mid(dcode)))
497             pass->state = -1;
498         else if(code < 0)
499             pass->raw[5] = 0xff;
500         else {
501             dbprintf(2, "\n        raw[%x]=%02x =>", idx >> 2,
502                      digits[(unsigned char)code]);
503             pass->raw[(idx >> 2) + 1] = digits[(unsigned char)code];
504             dbprintf(2, " raw=%d%d%d%d%d%d%d",
505                      pass->raw[0] & 0xf, pass->raw[1] & 0xf,
506                      pass->raw[2] & 0xf, pass->raw[3] & 0xf,
507                      pass->raw[4] & 0xf, pass->raw[5] & 0xf,
508                      pass->raw[6] & 0xf);
509         }
510     }
511     return(0);
512 }
513 
ean_verify_checksum(ean_decoder_t * ean,int n)514 static inline signed char ean_verify_checksum (ean_decoder_t *ean,
515                                                int n)
516 {
517     unsigned char chk = 0;
518     unsigned char i, d;
519     for(i = 0; i < n; i++) {
520         unsigned char d = ean->buf[i];
521         zassert(d < 10, -1, "i=%x d=%x chk=%x %s\n", i, d, chk,
522                 _zbar_decoder_buf_dump((void*)ean->buf, 18));
523         chk += d;
524         if((i ^ n) & 1) {
525             chk += d << 1;
526             if(chk >= 20)
527                 chk -= 20;
528         }
529         if(chk >= 10)
530             chk -= 10;
531     }
532     zassert(chk < 10, -1, "chk=%x n=%x %s", chk, n,
533             _zbar_decoder_buf_dump((void*)ean->buf, 18));
534     if(chk)
535         chk = 10 - chk;
536     d = ean->buf[n];
537     zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk,
538             _zbar_decoder_buf_dump((void*)ean->buf, 18));
539     if(chk != d) {
540         dbprintf(1, "\nchecksum mismatch %d != %d (%s)\n",
541                  chk, d, dsprintbuf(ean));
542         return(-1);
543     }
544     return(0);
545 }
546 
isbn10_calc_checksum(ean_decoder_t * ean)547 static inline unsigned char isbn10_calc_checksum (ean_decoder_t *ean)
548 {
549     unsigned int chk = 0;
550     unsigned char w;
551     for(w = 10; w > 1; w--) {
552         unsigned char d = ean->buf[13 - w];
553         zassert(d < 10, '?', "w=%x d=%x chk=%x %s\n", w, d, chk,
554                 _zbar_decoder_buf_dump((void*)ean->buf, 18));
555         chk += d * w;
556     }
557     chk = chk % 11;
558     if(!chk)
559         return('0');
560     chk = 11 - chk;
561     if(chk < 10)
562         return(chk + '0');
563     return('X');
564 }
565 
ean_expand_upce(ean_decoder_t * ean,ean_pass_t * pass)566 static inline void ean_expand_upce (ean_decoder_t *ean,
567                                     ean_pass_t *pass)
568 {
569     int i = 0;
570     unsigned char decode;
571     /* parity encoded digit is checksum */
572     ean->buf[12] = pass->raw[i++];
573 
574     decode = pass->raw[6] & 0xf;
575     ean->buf[0] = 0;
576     ean->buf[1] = 0;
577     ean->buf[2] = pass->raw[i++] & 0xf;
578     ean->buf[3] = pass->raw[i++] & 0xf;
579     ean->buf[4] = (decode < 3) ? decode : pass->raw[i++] & 0xf;
580     ean->buf[5] = (decode < 4) ? 0 : pass->raw[i++] & 0xf;
581     ean->buf[6] = (decode < 5) ? 0 : pass->raw[i++] & 0xf;
582     ean->buf[7] = 0;
583     ean->buf[8] = 0;
584     ean->buf[9] = (decode < 3) ? pass->raw[i++] & 0xf : 0;
585     ean->buf[10] = (decode < 4) ? pass->raw[i++] & 0xf : 0;
586     ean->buf[11] = (decode < 5) ? pass->raw[i] & 0xf : decode;
587 }
588 
integrate_partial(ean_decoder_t * ean,ean_pass_t * pass,zbar_symbol_type_t part)589 static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean,
590                                                     ean_pass_t *pass,
591                                                     zbar_symbol_type_t part)
592 {
593     /* copy raw data into holding buffer */
594     /* if same partial is not consistent, reset others */
595     dbprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean));
596     signed char i, j;
597 
598     if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) ||
599        (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) {
600         /* partial mismatch - reset collected parts */
601         dbprintf(2, " rst(type %x %x)", ean->left, ean->right);
602         ean->left = ean->right = ZBAR_NONE;
603     }
604 
605     if((ean->left || ean->right) &&
606        !check_width(ean->width, pass->width)) {
607       dbprintf(2, " rst(width %d)", pass->width);
608       ean->left = ean->right = ZBAR_NONE;
609     }
610 
611 
612     if(part & EAN_RIGHT) {
613         part &= ZBAR_SYMBOL;
614         j = part - 1;
615         for(i = part >> 1; i; i--, j--) {
616             unsigned char digit = pass->raw[i] & 0xf;
617             if(ean->right && ean->buf[j] != digit) {
618                 /* partial mismatch - reset collected parts */
619                 dbprintf(2, " rst(right)");
620                 ean->left = ean->right = ZBAR_NONE;
621             }
622             ean->buf[j] = digit;
623         }
624         ean->right = part;
625         part &= ean->left;  /* FIXME!? */
626     }
627     else if(part == ZBAR_EAN13 || part == ZBAR_EAN8) /* EAN_LEFT */ {
628         j = (part - 1) >> 1;
629         for(i = part >> 1; j >= 0; i--, j--) {
630             unsigned char digit = pass->raw[i] & 0xf;
631             if(ean->left && ean->buf[j] != digit) {
632                 /* partial mismatch - reset collected parts */
633                 dbprintf(2, " rst(left)");
634                 ean->left = ean->right = ZBAR_NONE;
635             }
636             ean->buf[j] = digit;
637         }
638         ean->left = part;
639         part &= ean->right;  /* FIXME!? */
640     }
641     else if(part != ZBAR_UPCE) /* add-ons */ {
642         for(i = part; i > 0; i--)
643             ean->buf[i - 1] = pass->raw[i] & 0xf;
644         ean->left = part;
645     }
646     else
647         ean_expand_upce(ean, pass);
648 
649     ean->width = pass->width;
650 
651     if(!part)
652         part = ZBAR_PARTIAL;
653 
654     if(((part == ZBAR_EAN13 ||
655          part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) ||
656        (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7))) {
657         /* invalid checksum */
658         if(ean->right)
659 	  ean->left = ZBAR_NONE;
660         else
661 	  ean->right = ZBAR_NONE;
662         part = ZBAR_NONE;
663     }
664 
665     if(part == ZBAR_EAN13) {
666         /* special case EAN-13 subsets */
667         if(!ean->buf[0] && TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
668             part = ZBAR_UPCA;
669         else if(ean->buf[0] == 9 && ean->buf[1] == 7) {
670             if((ean->buf[2] == 8 || ean->buf[2] == 9) &&
671                TEST_CFG(ean->isbn13_config, ZBAR_CFG_ENABLE)) {
672                 part = ZBAR_ISBN13;
673             } else if(ean->buf[2] == 8 &&
674                TEST_CFG(ean->isbn10_config, ZBAR_CFG_ENABLE)) {
675                 part = ZBAR_ISBN10;
676             }
677         }
678     } else if(part == ZBAR_UPCE) {
679         if(TEST_CFG(ean->upce_config, ZBAR_CFG_ENABLE)) {
680             /* UPC-E was decompressed for checksum verification,
681              * but user requested compressed result
682              */
683             ean->buf[0] = ean->buf[1] = 0;
684             for(i = 2; i < 8; i++)
685                 ean->buf[i] = pass->raw[i - 1] & 0xf;
686             ean->buf[i] = pass->raw[0] & 0xf;
687         }
688         else if(TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
689             /* UPC-E reported as UPC-A has priority over EAN-13 */
690             part = ZBAR_UPCA;
691         else if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE))
692             part = ZBAR_EAN13;
693         else
694             part = ZBAR_NONE;
695     }
696 
697     dbprintf(2, " dir=%d %x/%x=%x",
698              ean->direction, ean->left, ean->right, part);
699     return(part);
700 }
701 
702 /* copy result to output buffer */
postprocess(zbar_decoder_t * dcode,zbar_symbol_type_t sym)703 static inline void postprocess (zbar_decoder_t *dcode,
704                                 zbar_symbol_type_t sym)
705 {
706     ean_decoder_t *ean = &dcode->ean;
707     zbar_symbol_type_t base = sym;
708     int i = 0, j = 0;
709     if(base > ZBAR_PARTIAL) {
710         if(base == ZBAR_UPCA)
711             i = 1;
712         else if(base == ZBAR_UPCE) {
713             i = 1;
714             base--;
715         }
716         else if(base == ZBAR_ISBN13)
717             base = ZBAR_EAN13;
718         else if(base == ZBAR_ISBN10)
719             i = 3;
720 
721         if(base == ZBAR_ISBN10 ||
722            (base > ZBAR_EAN5 &&
723             !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK)))
724             base--;
725 
726         for(; j < base && ean->buf[i] >= 0; i++, j++)
727             dcode->buf[j] = ean->buf[i] + '0';
728 
729         if(sym == ZBAR_ISBN10 && j == 9 &&
730            TEST_CFG(ean->isbn10_config, ZBAR_CFG_EMIT_CHECK))
731             /* recalculate ISBN-10 check digit */
732             dcode->buf[j++] = isbn10_calc_checksum(ean);
733     }
734     dcode->buflen = j;
735     dcode->buf[j] = '\0';
736     dcode->direction = 1 - 2 * ean->direction;
737     dcode->modifiers = 0;
738     dbprintf(2, " base=%d j=%d (%s)", base, j, dcode->buf);
739 }
740 
_zbar_decode_ean(zbar_decoder_t * dcode)741 zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode)
742 {
743     /* process upto 4 separate passes */
744     zbar_symbol_type_t sym = ZBAR_NONE;
745     unsigned char pass_idx = dcode->idx & 3;
746     unsigned char i;
747 
748     /* update latest character width */
749     dcode->ean.s4 -= get_width(dcode, 4);
750     dcode->ean.s4 += get_width(dcode, 0);
751 
752     for(i = 0; i < 4; i++) {
753         ean_pass_t *pass = &dcode->ean.pass[i];
754         if(pass->state >= 0 ||
755            i == pass_idx)
756         {
757             zbar_symbol_type_t part;
758             dbprintf(2, "      ean[%x/%x]: idx=%x st=%d s=%d",
759                      i, pass_idx, dcode->idx, pass->state, dcode->ean.s4);
760             part = decode_pass(dcode, pass);
761             if(part) {
762                 /* update accumulated data from new partial decode */
763                 sym = integrate_partial(&dcode->ean, pass, part);
764                 if(sym) {
765                     /* this pass valid => _reset_ all passes */
766                     dbprintf(2, " sym=%x", sym);
767                     dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1;
768                     dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1;
769                     if(sym > ZBAR_PARTIAL) {
770                         if(!acquire_lock(dcode, sym))
771                             postprocess(dcode, sym);
772                         else {
773                             dbprintf(1, " [locked %d]", dcode->lock);
774                             sym = ZBAR_PARTIAL;
775                         }
776                     }
777                 }
778             }
779             dbprintf(2, "\n");
780         }
781     }
782     return(sym);
783 }
784