{"spec_id":"barcode-code128","library":"echarts","language":"javascript","code":"// anyplot.ai\n// barcode-code128: Code 128 Barcode\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 92/100 | Created: 2026-09-01\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Code 128 Subset B pattern table -----------------------------------------\n// Standard-compliant bar/space module widths for symbol values 0-102 (each sums\n// to 11 modules). Used both for character data (value = ASCII code - 32) and for\n// looking up the modulo-103 check symbol. Start-B and Stop are fixed patterns.\nconst PATTERNS = [\n  [2,1,2,2,2,2], [2,2,2,1,2,2], [2,2,2,2,2,1], [1,2,1,2,2,3], [1,2,1,3,2,2],\n  [1,3,1,2,2,2], [1,2,2,2,1,3], [1,2,2,3,1,2], [1,3,2,2,1,2], [2,2,1,2,1,3],\n  [2,2,1,3,1,2], [2,3,1,2,1,2], [1,1,2,2,3,2], [1,2,2,1,3,2], [1,2,2,2,3,1],\n  [1,1,3,2,2,2], [1,2,3,1,2,2], [1,2,3,2,2,1], [2,2,3,2,1,1], [2,2,1,1,3,2],\n  [2,2,1,2,3,1], [2,1,3,2,1,2], [2,2,3,1,1,2], [3,1,2,1,3,1], [3,1,1,2,2,2],\n  [3,2,1,1,2,2], [3,2,1,2,2,1], [3,1,2,2,1,2], [3,2,2,1,1,2], [3,2,2,2,1,1],\n  [2,1,2,1,2,3], [2,1,2,3,2,1], [2,3,2,1,2,1], [1,1,1,3,2,3], [1,3,1,1,2,3],\n  [1,3,1,3,2,1], [1,1,2,3,1,3], [1,3,2,1,1,3], [1,3,2,3,1,1], [2,1,1,3,1,3],\n  [2,3,1,1,1,3], [2,3,1,3,1,1], [1,1,2,1,3,3], [1,1,2,3,3,1], [1,3,2,1,3,1],\n  [1,1,3,1,2,3], [1,1,3,3,2,1], [1,3,3,1,2,1], [3,1,3,1,2,1], [2,1,1,3,3,1],\n  [2,3,1,1,3,1], [2,1,3,1,1,3], [2,1,3,3,1,1], [2,1,3,1,3,1], [3,1,1,1,2,3],\n  [3,1,1,3,2,1], [3,3,1,1,2,1], [3,1,2,1,1,3], [3,1,2,3,1,1], [3,3,2,1,1,1],\n  [3,1,4,1,1,1], [2,2,1,4,1,1], [4,3,1,1,1,1], [1,1,1,2,2,4], [1,1,1,4,2,2],\n  [1,2,1,1,2,4], [1,2,1,4,2,1], [1,4,1,1,2,2], [1,4,1,2,2,1], [1,1,2,2,1,4],\n  [1,1,2,4,1,2], [1,2,2,1,1,4], [1,2,2,4,1,1], [1,4,2,1,1,2], [1,4,2,2,1,1],\n  [2,4,1,2,1,1], [2,2,1,1,1,4], [4,1,3,1,1,1], [2,4,1,1,1,2], [1,3,4,1,1,1],\n  [1,1,1,2,4,2], [1,2,1,1,4,2], [1,2,1,2,4,1], [1,1,4,2,1,2], [1,2,4,1,1,2],\n  [1,2,4,2,1,1], [4,1,1,2,1,2], [4,2,1,1,1,2], [4,2,1,2,1,1], [2,1,2,1,4,1],\n  [2,1,4,1,2,1], [4,1,2,1,2,1], [1,1,1,1,4,3], [1,1,1,3,4,1], [1,3,1,1,4,1],\n  [1,1,4,1,1,3], [1,1,4,3,1,1], [4,1,1,1,1,3], [4,1,1,3,1,1], [1,1,3,1,4,1],\n  [1,1,4,1,3,1], [3,1,1,1,4,1], [4,1,1,1,3,1],\n];\nconst START_B = [2, 1, 1, 4, 1, 2];\nconst START_B_VALUE = 104;\nconst STOP = [2, 3, 3, 1, 1, 1, 2];\nconst QUIET_MODULES = 10; // >=10x per the Code 128 spec's minimum quiet-zone width\n\n// --- Data: a logistics package-tracking label --------------------------------\nconst content = \"PKG-48213-RX\";\n\n// --- Encode: Start B + data symbols + check symbol (mod 103) + Stop ----------\nconst symbolPatterns = [START_B];\nlet checksum = START_B_VALUE;\nfor (let i = 0; i < content.length; i++) {\n  const value = content.charCodeAt(i) - 32;\n  symbolPatterns.push(PATTERNS[value]);\n  checksum += value * (i + 1);\n}\nconst checkValue = checksum % 103;\nsymbolPatterns.push(PATTERNS[checkValue]);\nsymbolPatterns.push(STOP);\n\n// --- Flatten to a module-width sequence, keep only the drawn bar segments ----\nconst widths = symbolPatterns.flat();\nconst bars = [];\nlet isBar = true;\nlet pos = QUIET_MODULES;\nfor (const width of widths) {\n  if (isBar) bars.push([pos, width]);\n  pos += width;\n  isBar = !isBar;\n}\nconst totalModules = pos + QUIET_MODULES;\n\n// --- Structural segments (Start B / data / check / Stop), for the bracket\n// annotations below the human-readable text -----------------------------------\nconst symbolWidths = symbolPatterns.map((p) => p.reduce((a, b) => a + b, 0));\nconst dataWidths = symbolWidths.slice(1, 1 + content.length);\nconst startBEnd = QUIET_MODULES + symbolWidths[0];\nconst dataStart = startBEnd;\nconst dataEnd = dataStart + dataWidths.reduce((a, b) => a + b, 0);\nconst checkStart = dataEnd;\nconst checkEnd = checkStart + symbolWidths[1 + content.length];\nconst stopStart = checkEnd;\nconst stopEnd = stopStart + symbolWidths[2 + content.length];\nconst segments = [\n  { label: \"Start B\", start: QUIET_MODULES, end: startBEnd },\n  { label: `data (${content.length} chars)`, start: dataStart, end: dataEnd },\n  { label: \"check\", start: checkStart, end: checkEnd },\n  { label: \"Stop\", start: stopStart, end: stopEnd },\n];\n\n// --- Layout (1600x900 CSS mount -> 3200x1800 px) ------------------------------\nconst AREA_LEFT = 220;\nconst AREA_RIGHT = 220;\nconst BAR_TOP = 220;\nconst BAR_BOTTOM_GAP = 250; // grid \"bottom\" = distance from mount bottom to bar baseline\nconst barBaselineY = 900 - BAR_BOTTOM_GAP;\nconst pxPerModule = (1600 - AREA_LEFT - AREA_RIGHT) / totalModules;\nconst toPx = (moduleValue) => AREA_LEFT + moduleValue * pxPerModule;\n\nconst chart = echarts.init(document.getElementById(\"container\"));\n\nchart.setOption({\n  animation: false,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"barcode-code128 · javascript · echarts · anyplot.ai\",\n    subtext: `Code 128, Subset B of 3 switchable subsets (A/B/C)  ·  check digit ${checkValue} (mod 103)  ·  ${content.length} data characters`,\n    left: \"center\",\n    top: 34,\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: \"bold\" },\n    subtextStyle: { color: t.inkSoft, fontSize: 14 },\n  },\n  grid: {\n    left: AREA_LEFT,\n    right: AREA_RIGHT,\n    top: BAR_TOP,\n    bottom: BAR_BOTTOM_GAP,\n  },\n  xAxis: { type: \"value\", min: 0, max: totalModules, show: false },\n  yAxis: { type: \"value\", min: 0, max: 1, show: false },\n  graphic: [\n    {\n      type: \"text\",\n      bounding: \"raw\",\n      x: toPx(QUIET_MODULES / 2),\n      y: BAR_TOP - 24,\n      style: { text: \"quiet zone\", fill: t.inkSoft, fontSize: 13, fontStyle: \"italic\", textAlign: \"center\" },\n      z: 40,\n    },\n    {\n      type: \"text\",\n      bounding: \"raw\",\n      x: toPx(totalModules - QUIET_MODULES / 2),\n      y: BAR_TOP - 24,\n      style: { text: \"quiet zone\", fill: t.inkSoft, fontSize: 13, fontStyle: \"italic\", textAlign: \"center\" },\n      z: 40,\n    },\n    {\n      type: \"text\",\n      bounding: \"raw\",\n      x: 800,\n      y: barBaselineY + 40,\n      style: {\n        text: content.split(\"\").join(\" \"),\n        fill: t.ink,\n        fontSize: 30,\n        fontWeight: \"bold\",\n        fontFamily: \"monospace\",\n        textAlign: \"center\",\n      },\n      z: 40,\n    },\n    // Per-segment bracket annotations: a tick-and-line bracket under each\n    // structural group (Start B / data / check / Stop), labeled directly\n    // below the bar range it covers.\n    ...segments.flatMap(({ label, start, end }) => {\n      const x1 = toPx(start);\n      const x2 = toPx(end);\n      const bracketY = barBaselineY + 96;\n      const tickTop = bracketY - 10;\n      return [\n        {\n          type: \"line\",\n          shape: { x1, y1: bracketY, x2, y2: bracketY },\n          style: { stroke: t.inkSoft, lineWidth: 1.5 },\n          z: 35,\n        },\n        {\n          type: \"line\",\n          shape: { x1, y1: tickTop, x2: x1, y2: bracketY },\n          style: { stroke: t.inkSoft, lineWidth: 1.5 },\n          z: 35,\n        },\n        {\n          type: \"line\",\n          shape: { x1: x2, y1: tickTop, x2, y2: bracketY },\n          style: { stroke: t.inkSoft, lineWidth: 1.5 },\n          z: 35,\n        },\n        {\n          type: \"text\",\n          bounding: \"raw\",\n          x: (x1 + x2) / 2,\n          y: bracketY + 10,\n          style: { text: label, fill: t.inkSoft, fontSize: 14, textAlign: \"center\" },\n          z: 35,\n        },\n      ];\n    }),\n  ],\n  series: [\n    {\n      type: \"custom\",\n      clip: true,\n      renderItem: (params, api) => {\n        const start = api.value(0);\n        const width = api.value(1);\n        const topLeft = api.coord([start, 1]);\n        const bottomRight = api.coord([start + width, 0]);\n        return {\n          type: \"rect\",\n          shape: {\n            x: topLeft[0],\n            y: topLeft[1],\n            width: bottomRight[0] - topLeft[0],\n            height: bottomRight[1] - topLeft[1],\n          },\n          style: { fill: t.ink },\n        };\n      },\n      data: bars,\n    },\n  ],\n});\n"}