{"spec_id":"barcode-ean13","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' barcode-ean13: EAN-13 Barcode\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 88/100 | Created: 2026-05-21\n\nlibrary(ggplot2)\nlibrary(ragg)\n\nTHEME    <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG  <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK      <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n\n# EAN-13 encoding tables\nL_CODES <- list(\n    \"0\" = c(0,0,0,1,1,0,1), \"1\" = c(0,0,1,1,0,0,1),\n    \"2\" = c(0,0,1,0,0,1,1), \"3\" = c(0,1,1,1,1,0,1),\n    \"4\" = c(0,1,0,0,0,1,1), \"5\" = c(0,1,1,0,0,0,1),\n    \"6\" = c(0,1,0,1,1,1,1), \"7\" = c(0,1,1,1,0,1,1),\n    \"8\" = c(0,1,1,0,1,1,1), \"9\" = c(0,0,0,1,0,1,1)\n)\nG_CODES <- list(\n    \"0\" = c(0,1,0,0,1,1,1), \"1\" = c(0,1,1,0,0,1,1),\n    \"2\" = c(0,0,1,1,0,1,1), \"3\" = c(0,1,0,0,0,0,1),\n    \"4\" = c(0,0,1,1,1,0,1), \"5\" = c(0,1,1,1,0,0,1),\n    \"6\" = c(0,0,0,0,1,0,1), \"7\" = c(0,0,1,0,0,0,1),\n    \"8\" = c(0,0,0,1,0,0,1), \"9\" = c(0,0,1,0,1,1,1)\n)\nR_CODES <- list(\n    \"0\" = c(1,1,1,0,0,1,0), \"1\" = c(1,1,0,0,1,1,0),\n    \"2\" = c(1,1,0,1,1,0,0), \"3\" = c(1,0,0,0,0,1,0),\n    \"4\" = c(1,0,1,1,1,0,0), \"5\" = c(1,0,0,1,1,1,0),\n    \"6\" = c(1,0,1,0,0,0,0), \"7\" = c(1,0,0,0,1,0,0),\n    \"8\" = c(1,0,0,1,0,0,0), \"9\" = c(1,1,1,0,1,0,0)\n)\n# Parity pattern per first digit: 0 = L-code, 1 = G-code\nPARITY <- list(\n    \"0\" = c(0,0,0,0,0,0), \"1\" = c(0,0,1,0,1,1),\n    \"2\" = c(0,0,1,1,0,1), \"3\" = c(0,0,1,1,1,0),\n    \"4\" = c(0,1,0,0,1,1), \"5\" = c(0,1,1,0,0,1),\n    \"6\" = c(0,1,1,1,0,0), \"7\" = c(0,1,0,1,0,1),\n    \"8\" = c(0,1,0,1,1,0), \"9\" = c(0,1,1,0,1,0)\n)\n\n# Build 95-module EAN-13 bitstream; appends check digit when 12 digits supplied\nbuild_ean13 <- function(code) {\n    d <- as.integer(strsplit(code, \"\")[[1]])\n    if (length(d) == 12L) {\n        s <- sum(d[c(1,3,5,7,9,11)]) + 3L * sum(d[c(2,4,6,8,10,12)])\n        d <- c(d, (10L - s %% 10L) %% 10L)\n    }\n    par  <- PARITY[[as.character(d[1])]]\n    bits <- c(1L, 0L, 1L)                            # start guard (101)\n    for (i in seq_len(6L)) {\n        ch   <- as.character(d[i + 1L])\n        bits <- c(bits, if (par[i] == 0L) L_CODES[[ch]] else G_CODES[[ch]])\n    }\n    bits <- c(bits, 0L, 1L, 0L, 1L, 0L)              # center guard (01010)\n    for (i in seq_len(6L)) {\n        bits <- c(bits, R_CODES[[as.character(d[i + 7L])]])\n    }\n    list(bits = c(bits, 1L, 0L, 1L), digits = d)     # end guard (101)\n}\n\n# --- Data ---\nresult <- build_ean13(\"4006381333931\")   # German product (Leifheit AG)\nbits   <- result$bits                    # 95 modules\ndigits <- result$digits                  # 13 digits [4,0,0,6,3,8,1,3,3,3,9,3,1]\n\nquiet     <- 9L    # quiet-zone modules each side (EAN-13 spec minimum)\nbar_h     <- 40    # bar height in module units\nguard_ext <- 3     # guard bar descender below y = 0\n\nguard_idx <- c(0L:2L, 45L:49L, 92L:94L)\nbar_pos   <- which(bits == 1L) - 1L          # 0-indexed positions\nis_guard  <- bar_pos %in% guard_idx\n\nbar_df <- data.frame(\n    xmin = quiet + bar_pos,\n    xmax = quiet + bar_pos + 1L,\n    ymin = ifelse(is_guard, -guard_ext, 0),\n    ymax = bar_h\n)\n\ntotal_w <- quiet + 95L + quiet   # 113 modules total\n\n# Human-readable digit x-coordinates (module units)\nx_first <- quiet / 2                                    # first digit outside left guard\nx_left  <- quiet + 3L + (0L:5L) * 7L + 3.5            # left group: 6 digits\nx_right <- quiet + 3L + 42L + 5L + (0L:5L) * 7L + 3.5 # right group: 6 digits\n\ndigit_df <- data.frame(\n    x     = c(x_first, x_left, x_right),\n    y     = rep(-guard_ext - 2.5, 13L),\n    label = as.character(digits)\n)\n\n# Structural bracket geometry (module-unit coordinates)\n# Left group  occupies bits  3–44 → x = quiet+3 to quiet+45 = 12…54\n# Right group occupies bits 50–91 → x = quiet+50 to quiet+92 = 59…101\nleft_x1  <- quiet + 3L;  left_x2  <- quiet + 45L   # 12, 54\nright_x1 <- quiet + 50L; right_x2 <- quiet + 92L   # 59, 101\nbrk_y    <- bar_h + 5                               # bracket line y\nlbl_y    <- bar_h + 12                              # label y (above bracket)\ntick_h   <- 2                                       # bracket tick descent\n\n# --- Plot ---\np <- ggplot() +\n    # Barcode bars\n    geom_rect(\n        data = bar_df,\n        aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),\n        fill = INK, color = NA\n    ) +\n    # Human-readable digits (increased size for readability at mobile widths)\n    geom_text(\n        data = digit_df,\n        aes(x = x, y = y, label = label),\n        color = INK, size = 4.5, vjust = 1, family = \"sans\"\n    ) +\n    # Left group bracket: horizontal bar + end ticks\n    annotate(\"segment\",\n             x = left_x1, xend = left_x2, y = brk_y, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"segment\",\n             x = left_x1, xend = left_x1, y = brk_y - tick_h, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"segment\",\n             x = left_x2, xend = left_x2, y = brk_y - tick_h, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"text\",\n             x = (left_x1 + left_x2) / 2, y = lbl_y,\n             label = \"Country · Manufacturer\",\n             color = INK_SOFT, size = 3.0, hjust = 0.5, family = \"sans\") +\n    # Right group bracket: horizontal bar + end ticks\n    annotate(\"segment\",\n             x = right_x1, xend = right_x2, y = brk_y, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"segment\",\n             x = right_x1, xend = right_x1, y = brk_y - tick_h, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"segment\",\n             x = right_x2, xend = right_x2, y = brk_y - tick_h, yend = brk_y,\n             color = INK_SOFT, linewidth = 0.4) +\n    annotate(\"text\",\n             x = (right_x1 + right_x2) / 2, y = lbl_y,\n             label = \"Product · Check digit\",\n             color = INK_SOFT, size = 3.0, hjust = 0.5, family = \"sans\") +\n    scale_x_continuous(limits = c(0, total_w), expand = expansion(add = c(1, 1))) +\n    scale_y_continuous(limits = c(-guard_ext - 13, bar_h + 20), expand = c(0, 0)) +\n    labs(\n        title    = \"barcode-ean13 · r · ggplot2 · anyplot.ai\",\n        subtitle = \"EAN-13 · 4006381333931 · GS1 prefix 400 (Germany) · check digit: 1\"\n    ) +\n    theme_void() +\n    theme(\n        plot.background  = element_rect(fill = PAGE_BG, color = PAGE_BG),\n        panel.background = element_rect(fill = PAGE_BG, color = NA),\n        plot.title       = element_text(\n            color = INK, size = 12, hjust = 0.5,\n            margin = margin(t = 15, b = 4)\n        ),\n        plot.subtitle    = element_text(\n            color = INK_SOFT, size = 8, hjust = 0.5,\n            margin = margin(b = 12)\n        ),\n        plot.margin = margin(10, 60, 10, 60)\n    )\n\n# --- Save ---\nggsave(\n    filename = sprintf(\"plot-%s.png\", THEME),\n    plot     = p,\n    device   = ragg::agg_png,\n    width    = 8,\n    height   = 4.5,\n    units    = \"in\",\n    dpi      = 400\n)\n"}