aboutsummaryrefslogtreecommitdiff
path: root/source/codes/Code39.mc
blob: e17ae8f71ad342046d39ab7ce3cea381b59991d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Author:  cirakg & claude ai
// Summary: Code 39 encoder: 43 characters, optional mod-43 check character, wide bars 2 modules (as zxing).

import Toybox.Lang;

module Code39 {

    const ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; // lint: allow-literal (Code 39 character set)
    // Nine elements per character, bit 8 first, 1 = wide; index 43 is '*'.
    const PATTERNS = [
        0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064,
        0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C,
        0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016,
        0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8,
        0x0A2, 0x08A, 0x02A, 0x094
    ];
    const STAR = 43;

    // withCheck adds the mod-43 check character (the sum of the character
    // values modulo 43).
    function encode(text as String, withCheck as Boolean) as Codes.LinearCode or Codes.CodeError {
        var chars = text.toCharArray();
        if (chars.size() == 0) {
            return new Codes.CodeError("Code 39 needs some text");
        }
        var values = [] as Array<Number>;
        var sum = 0;
        for (var i = 0; i < chars.size(); i++) {
            var v = ALPHABET.find(chars[i].toString());
            if (v == null) {
                return new Codes.CodeError("Code 39: '" + chars[i] + "' (position " + (i + 1)
                    + ") isn't allowed (0-9, A-Z, space, - . $ / + %)");
            }
            values.add(v);
            sum += v;
        }
        var readable = text;
        if (withCheck) {
            values.add(sum % 43);
            readable += ALPHABET.substring(sum % 43, sum % 43 + 1);
        }
        var m = []b;
        addChar(m, STAR);
        for (var i = 0; i < values.size(); i++) {
            m.add(0); // narrow gap between characters
            addChar(m, values[i]);
        }
        m.add(0);
        addChar(m, STAR);
        return new Codes.LinearCode(m, readable);
    }

    function addChar(m as ByteArray, value as Number) as Void {
        var pattern = PATTERNS[value] as Number;
        for (var i = 8; i >= 0; i--) {
            var width = ((pattern >> i) & 1) == 1 ? 2 : 1;
            var bar = (8 - i) % 2 == 0;
            for (var k = 0; k < width; k++) {
                m.add(bar ? 1 : 0);
            }
        }
    }
}