// Author: cirakg & claude ai // Summary: Barcode symbology IDs, option bits, result types and the dispatcher to the encoders (README 12). // // A code entry stores its symbology in Entry.type and its options in // Entry.options (bits below). encode() turns the payload text into either a // LinearCode (one row of modules) or, from M6b, a matrix; validation errors // come back as a CodeError with a message for the user, never an exception. import Toybox.Lang; module Codes { // Symbology IDs (Entry.type of code entries). Stored: never renumber. const QR = 0; const CODE128 = 1; const CODE39 = 2; const EAN13 = 3; const EAN8 = 4; const UPCA = 5; const UPCE = 6; const ITF = 7; const CODABAR = 8; const DATAMATRIX = 9; const PDF417 = 10; const AZTEC = 11; const NAMES = ["QR", "Code 128", "Code 39", "EAN-13", "EAN-8", "UPC-A", "UPC-E", "ITF", "Codabar", "Data Matrix", "PDF417", "Aztec"]; // Entry.options bits. const OPT_EC_MASK = 0x3; // error correction: 0 low, 1 medium, 2 quartile, 3 high const OPT_CHECK_SHIFT = 2; // check digit: 0 add or verify, 1 fix if wrong, 2 off const OPT_CHECK_MASK = 0xC; const OPT_SHOW_TEXT = 0x10; // human-readable text under linear codes const DEFAULT_OPTIONS = 0x11; // medium, add or verify, text on const CHECK_ADD_VERIFY = 0; const CHECK_FIX = 1; const CHECK_OFF = 2; // A row of modules: modules[i] is 1 for a bar, 0 for a space. The quiet // zone is not included (the renderer adds it). class LinearCode { var modules as ByteArray; // The human-readable text (digits as encoded, check digit included). var text as String; // A remark for the user (check digit added or fixed), or null. var note as String? = null; function initialize(rowModules as ByteArray, readable as String) { modules = rowModules; text = readable; } } // Why a payload can't be encoded, in words for the user. class CodeError { var message as String; function initialize(msg as String) { message = msg; } } function checkMode(options as Number) as Number { return (options & OPT_CHECK_MASK) >> OPT_CHECK_SHIFT; } function name(symbology as Number) as String { return symbology >= 0 && symbology < NAMES.size() ? NAMES[symbology] as String : "Code"; } function isLinear(symbology as Number) as Boolean { return symbology >= CODE128 && symbology <= CODABAR; } // Encode a payload; unsupported symbologies give a CodeError until // their milestone (README 16, M6b-M6d). function encode(symbology as Number, payload as String, options as Number) as LinearCode or CodeError { var check = checkMode(options); if (symbology == EAN13) { return Ean.ean13(payload, check, "EAN-13", false); } if (symbology == UPCA) { return Ean.ean13(payload, check, "UPC-A", true); } if (symbology == EAN8) { return Ean.ean8(payload, check); } if (symbology == UPCE) { return Ean.upce(payload, check); } if (symbology == CODE128) { return Code128.encode(payload); } if (symbology == CODE39) { return Code39.encode(payload, check != CHECK_OFF); } if (symbology == ITF) { return Itf.encode(payload, check != CHECK_OFF); } if (symbology == CODABAR) { return Codabar.encode(payload); } return new CodeError(name(symbology) + " is not supported yet"); } // Append bar/space runs to modules: widths alternate bar, space, ..., // starting with a bar when startWithBar. function addRuns(modules as ByteArray, widths as Array, startWithBar as Boolean) as Void { var bar = startWithBar; for (var i = 0; i < widths.size(); i++) { var w = widths[i]; for (var k = 0; k < w; k++) { modules.add(bar ? 1 : 0); } bar = !bar; } } // Append a bit pattern of `count` modules, most significant bit first. function addBits(modules as ByteArray, bits as Number, count as Number) as Void { for (var i = count - 1; i >= 0; i--) { modules.add((bits >> i) & 1); } } // The digit values of text, or null when it holds anything else. function digits(text as String) as Array? { var chars = text.toCharArray(); var out = [] as Array; for (var i = 0; i < chars.size(); i++) { var c = chars[i]; if (c < '0' || c > '9') { return null; } out.add(c.toNumber() - 48); } return out; } function digitsText(values as Array) as String { var s = ""; for (var i = 0; i < values.size(); i++) { s += values[i].toString(); } return s; } }