codelayout.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package datamatrix
  2. import (
  3. "github.com/boombuler/barcode"
  4. )
  5. type setValFunc func(byte)
  6. type codeLayout struct {
  7. matrix *barcode.BitList
  8. occupy *barcode.BitList
  9. size *dmCodeSize
  10. }
  11. func newCodeLayout(size *dmCodeSize) *codeLayout {
  12. result := new(codeLayout)
  13. result.matrix = barcode.NewBitList(size.MatrixColumns() * size.MatrixRows())
  14. result.occupy = barcode.NewBitList(size.MatrixColumns() * size.MatrixRows())
  15. result.size = size
  16. return result
  17. }
  18. func (l *codeLayout) Occupied(row, col int) bool {
  19. return l.occupy.GetBit(col + row*l.size.MatrixColumns())
  20. }
  21. func (l *codeLayout) Set(row, col int, value, bitNum byte, occupy bool) {
  22. val := ((value >> (7 - bitNum)) & 1) == 1
  23. if row < 0 {
  24. row += l.size.MatrixRows()
  25. col += 4 - ((l.size.MatrixRows() + 4) % 8)
  26. }
  27. if col < 0 {
  28. col += l.size.MatrixColumns()
  29. row += 4 - ((l.size.MatrixColumns() + 4) % 8)
  30. }
  31. l.matrix.SetBit(col+row*l.size.MatrixColumns(), val)
  32. if occupy {
  33. l.occupy.SetBit(col+row*l.size.MatrixColumns(), true)
  34. }
  35. }
  36. func (l *codeLayout) SetSimple(row, col int, value byte) {
  37. l.Set(row-2, col-2, value, 0, true)
  38. l.Set(row-2, col-1, value, 1, true)
  39. l.Set(row-1, col-2, value, 2, true)
  40. l.Set(row-1, col-1, value, 3, true)
  41. l.Set(row-1, col-0, value, 4, true)
  42. l.Set(row-0, col-2, value, 5, true)
  43. l.Set(row-0, col-1, value, 6, true)
  44. l.Set(row-0, col-0, value, 7, true)
  45. }
  46. func (l *codeLayout) Corner1(value byte) {
  47. l.Set(l.size.MatrixRows()-1, 0, value, 0, true)
  48. l.Set(l.size.MatrixRows()-1, 1, value, 1, true)
  49. l.Set(l.size.MatrixRows()-1, 2, value, 2, true)
  50. l.Set(0, l.size.MatrixColumns()-2, value, 3, true)
  51. l.Set(0, l.size.MatrixColumns()-1, value, 4, true)
  52. l.Set(1, l.size.MatrixColumns()-1, value, 5, true)
  53. l.Set(2, l.size.MatrixColumns()-1, value, 6, true)
  54. l.Set(3, l.size.MatrixColumns()-1, value, 7, true)
  55. }
  56. func (l *codeLayout) Corner2(value byte) {
  57. l.Set(l.size.MatrixRows()-3, 0, value, 0, true)
  58. l.Set(l.size.MatrixRows()-2, 0, value, 1, true)
  59. l.Set(l.size.MatrixRows()-1, 0, value, 2, true)
  60. l.Set(0, l.size.MatrixColumns()-4, value, 3, true)
  61. l.Set(0, l.size.MatrixColumns()-3, value, 4, true)
  62. l.Set(0, l.size.MatrixColumns()-2, value, 5, true)
  63. l.Set(0, l.size.MatrixColumns()-1, value, 6, true)
  64. l.Set(1, l.size.MatrixColumns()-1, value, 7, true)
  65. }
  66. func (l *codeLayout) Corner3(value byte) {
  67. l.Set(l.size.MatrixRows()-3, 0, value, 0, true)
  68. l.Set(l.size.MatrixRows()-2, 0, value, 1, true)
  69. l.Set(l.size.MatrixRows()-1, 0, value, 2, true)
  70. l.Set(0, l.size.MatrixColumns()-2, value, 3, true)
  71. l.Set(0, l.size.MatrixColumns()-1, value, 4, true)
  72. l.Set(1, l.size.MatrixColumns()-1, value, 5, true)
  73. l.Set(2, l.size.MatrixColumns()-1, value, 6, true)
  74. l.Set(3, l.size.MatrixColumns()-1, value, 7, true)
  75. }
  76. func (l *codeLayout) Corner4(value byte) {
  77. l.Set(l.size.MatrixRows()-1, 0, value, 0, true)
  78. l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, value, 1, true)
  79. l.Set(0, l.size.MatrixColumns()-3, value, 2, true)
  80. l.Set(0, l.size.MatrixColumns()-2, value, 3, true)
  81. l.Set(0, l.size.MatrixColumns()-1, value, 4, true)
  82. l.Set(1, l.size.MatrixColumns()-3, value, 5, true)
  83. l.Set(1, l.size.MatrixColumns()-2, value, 6, true)
  84. l.Set(1, l.size.MatrixColumns()-1, value, 7, true)
  85. }
  86. func (l *codeLayout) IterateSetter() <-chan setValFunc {
  87. result := make(chan setValFunc)
  88. go func() {
  89. row := 4
  90. col := 0
  91. for (row < l.size.MatrixRows()) || (col < l.size.MatrixColumns()) {
  92. if (row == l.size.MatrixRows()) && (col == 0) {
  93. result <- l.Corner1
  94. }
  95. if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%4 != 0) {
  96. result <- l.Corner2
  97. }
  98. if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%8 == 4) {
  99. result <- l.Corner3
  100. }
  101. if (row == l.size.MatrixRows()+4) && (col == 2) && (l.size.MatrixColumns()%8 == 0) {
  102. result <- l.Corner4
  103. }
  104. for true {
  105. if (row < l.size.MatrixRows()) && (col >= 0) && !l.Occupied(row, col) {
  106. r := row
  107. c := col
  108. result <- func(b byte) {
  109. l.SetSimple(r, c, b)
  110. }
  111. }
  112. row -= 2
  113. col += 2
  114. if (row < 0) || (col >= l.size.MatrixColumns()) {
  115. break
  116. }
  117. }
  118. row += 1
  119. col += 3
  120. for true {
  121. if (row >= 0) && (col < l.size.MatrixColumns()) && !l.Occupied(row, col) {
  122. r := row
  123. c := col
  124. result <- func(b byte) {
  125. l.SetSimple(r, c, b)
  126. }
  127. }
  128. row += 2
  129. col -= 2
  130. if (row >= l.size.MatrixRows()) || (col < 0) {
  131. break
  132. }
  133. }
  134. row += 3
  135. col += 1
  136. }
  137. close(result)
  138. }()
  139. return result
  140. }
  141. func (l *codeLayout) Merge() *datamatrixCode {
  142. result := newDataMatrixCode(l.size)
  143. //dotted horizontal lines
  144. for r := 0; r < l.size.Rows; r += (l.size.RegionRows() + 2) {
  145. for c := 0; c < l.size.Columns; c += 2 {
  146. result.set(c, r, true)
  147. }
  148. }
  149. //solid horizontal line
  150. for r := l.size.RegionRows() + 1; r < l.size.Rows; r += (l.size.RegionRows() + 2) {
  151. for c := 0; c < l.size.Columns; c++ {
  152. result.set(c, r, true)
  153. }
  154. }
  155. //dotted vertical lines
  156. for c := l.size.RegionColumns() + 1; c < l.size.Columns; c += (l.size.RegionColumns() + 2) {
  157. for r := 1; r < l.size.Rows; r += 2 {
  158. result.set(c, r, true)
  159. }
  160. }
  161. //solid vertical line
  162. for c := 0; c < l.size.Columns; c += (l.size.RegionColumns() + 2) {
  163. for r := 0; r < l.size.Rows; r++ {
  164. result.set(c, r, true)
  165. }
  166. }
  167. count := 0
  168. for hRegion := 0; hRegion < l.size.RegionCountHorizontal; hRegion++ {
  169. for vRegion := 0; vRegion < l.size.RegionCountVertical; vRegion++ {
  170. for x := 0; x < l.size.RegionColumns(); x++ {
  171. colMatrix := (l.size.RegionColumns() * hRegion) + x
  172. colResult := ((2 + l.size.RegionColumns()) * hRegion) + x + 1
  173. for y := 0; y < l.size.RegionRows(); y++ {
  174. rowMatrix := (l.size.RegionRows() * vRegion) + y
  175. rowResult := ((2 + l.size.RegionRows()) * vRegion) + y + 1
  176. val := l.matrix.GetBit(colMatrix + rowMatrix*l.size.MatrixColumns())
  177. if val {
  178. count++
  179. }
  180. result.set(colResult, rowResult, val)
  181. }
  182. }
  183. }
  184. }
  185. return result
  186. }