encoder.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package code39
  2. import (
  3. "errors"
  4. "github.com/boombuler/barcode"
  5. "github.com/boombuler/barcode/utils"
  6. "strings"
  7. )
  8. type encodeInfo struct {
  9. value int
  10. data []bool
  11. }
  12. var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{
  13. '0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}},
  14. '1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}},
  15. '2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
  16. '3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}},
  17. '4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}},
  18. '5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}},
  19. '6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}},
  20. '7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}},
  21. '8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}},
  22. '9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}},
  23. 'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}},
  24. 'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}},
  25. 'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}},
  26. 'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}},
  27. 'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}},
  28. 'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}},
  29. 'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}},
  30. 'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}},
  31. 'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}},
  32. 'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}},
  33. 'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}},
  34. 'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}},
  35. 'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}},
  36. 'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}},
  37. 'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}},
  38. 'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}},
  39. 'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}},
  40. 'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}},
  41. 'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}},
  42. 'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}},
  43. 'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}},
  44. 'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}},
  45. 'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}},
  46. 'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}},
  47. 'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}},
  48. 'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}},
  49. '-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}},
  50. '.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}},
  51. ' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}},
  52. '$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}},
  53. '/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}},
  54. '+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}},
  55. '%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}},
  56. '*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
  57. }
  58. func getChecksum(content string) string {
  59. sum := 0
  60. for _, r := range content {
  61. info, ok := encodeTable[r]
  62. if !ok || info.value < 0 {
  63. return "#"
  64. }
  65. sum += info.value
  66. }
  67. sum = sum % 43
  68. for r, v := range encodeTable {
  69. if v.value == sum {
  70. return string(r)
  71. }
  72. }
  73. return "#"
  74. }
  75. // encodes the given string as a code39 barcode
  76. // if includeChecksum is set to true, a checksum character is calculated and added to the content
  77. func Encode(content string, includeChecksum bool) (barcode.Barcode, error) {
  78. if strings.ContainsRune(content, '*') {
  79. return nil, errors.New("invalid data")
  80. }
  81. data := "*" + content
  82. if includeChecksum {
  83. data += getChecksum(content)
  84. }
  85. data += "*"
  86. result := new(utils.BitList)
  87. for i, r := range data {
  88. if i != 0 {
  89. result.AddBit(false)
  90. }
  91. info, ok := encodeTable[r]
  92. if !ok {
  93. return nil, errors.New("invalid data")
  94. }
  95. result.AddBit(info.data...)
  96. }
  97. return utils.New1DCode("Code 39", content, result), nil
  98. }