codelayout.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package datamatrix
  2. import (
  3. "github.com/boombuler/barcode/utils"
  4. "strconv"
  5. )
  6. type setValFunc func(byte)
  7. type codeLayout struct {
  8. matrix *utils.BitList
  9. occupy *utils.BitList
  10. size *dmCodeSize
  11. }
  12. func newCodeLayout(size *dmCodeSize) *codeLayout {
  13. result := new(codeLayout)
  14. result.matrix = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
  15. result.occupy = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
  16. result.size = size
  17. return result
  18. }
  19. func (l *codeLayout) Occupied(row, col int) bool {
  20. return l.occupy.GetBit(col + row*l.size.MatrixColumns())
  21. }
  22. func (l *codeLayout) Set(row, col int, value, bitNum byte) {
  23. val := ((value >> (7 - bitNum)) & 1) == 1
  24. if row < 0 {
  25. row += l.size.MatrixRows()
  26. col += 4 - ((l.size.MatrixRows() + 4) % 8)
  27. }
  28. if col < 0 {
  29. col += l.size.MatrixColumns()
  30. row += 4 - ((l.size.MatrixColumns() + 4) % 8)
  31. }
  32. if l.Occupied(row, col) {
  33. panic("Field already occupied row: " + strconv.Itoa(row) + " col: " + strconv.Itoa(col))
  34. }
  35. l.occupy.SetBit(col+row*l.size.MatrixColumns(), true)
  36. l.matrix.SetBit(col+row*l.size.MatrixColumns(), val)
  37. }
  38. func (l *codeLayout) SetSimple(row, col int, value byte) {
  39. l.Set(row-2, col-2, value, 0)
  40. l.Set(row-2, col-1, value, 1)
  41. l.Set(row-1, col-2, value, 2)
  42. l.Set(row-1, col-1, value, 3)
  43. l.Set(row-1, col-0, value, 4)
  44. l.Set(row-0, col-2, value, 5)
  45. l.Set(row-0, col-1, value, 6)
  46. l.Set(row-0, col-0, value, 7)
  47. }
  48. func (l *codeLayout) Corner1(value byte) {
  49. l.Set(l.size.MatrixRows()-1, 0, value, 0)
  50. l.Set(l.size.MatrixRows()-1, 1, value, 1)
  51. l.Set(l.size.MatrixRows()-1, 2, value, 2)
  52. l.Set(0, l.size.MatrixColumns()-2, value, 3)
  53. l.Set(0, l.size.MatrixColumns()-1, value, 4)
  54. l.Set(1, l.size.MatrixColumns()-1, value, 5)
  55. l.Set(2, l.size.MatrixColumns()-1, value, 6)
  56. l.Set(3, l.size.MatrixColumns()-1, value, 7)
  57. }
  58. func (l *codeLayout) Corner2(value byte) {
  59. l.Set(l.size.MatrixRows()-3, 0, value, 0)
  60. l.Set(l.size.MatrixRows()-2, 0, value, 1)
  61. l.Set(l.size.MatrixRows()-1, 0, value, 2)
  62. l.Set(0, l.size.MatrixColumns()-4, value, 3)
  63. l.Set(0, l.size.MatrixColumns()-3, value, 4)
  64. l.Set(0, l.size.MatrixColumns()-2, value, 5)
  65. l.Set(0, l.size.MatrixColumns()-1, value, 6)
  66. l.Set(1, l.size.MatrixColumns()-1, value, 7)
  67. }
  68. func (l *codeLayout) Corner3(value byte) {
  69. l.Set(l.size.MatrixRows()-3, 0, value, 0)
  70. l.Set(l.size.MatrixRows()-2, 0, value, 1)
  71. l.Set(l.size.MatrixRows()-1, 0, value, 2)
  72. l.Set(0, l.size.MatrixColumns()-2, value, 3)
  73. l.Set(0, l.size.MatrixColumns()-1, value, 4)
  74. l.Set(1, l.size.MatrixColumns()-1, value, 5)
  75. l.Set(2, l.size.MatrixColumns()-1, value, 6)
  76. l.Set(3, l.size.MatrixColumns()-1, value, 7)
  77. }
  78. func (l *codeLayout) Corner4(value byte) {
  79. l.Set(l.size.MatrixRows()-1, 0, value, 0)
  80. l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, value, 1)
  81. l.Set(0, l.size.MatrixColumns()-3, value, 2)
  82. l.Set(0, l.size.MatrixColumns()-2, value, 3)
  83. l.Set(0, l.size.MatrixColumns()-1, value, 4)
  84. l.Set(1, l.size.MatrixColumns()-3, value, 5)
  85. l.Set(1, l.size.MatrixColumns()-2, value, 6)
  86. l.Set(1, l.size.MatrixColumns()-1, value, 7)
  87. }
  88. func (l *codeLayout) SetValues(data []byte) {
  89. idx := 0
  90. row := 4
  91. col := 0
  92. for (row < l.size.MatrixRows()) || (col < l.size.MatrixColumns()) {
  93. if (row == l.size.MatrixRows()) && (col == 0) {
  94. l.Corner1(data[idx])
  95. idx++
  96. }
  97. if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%4 != 0) {
  98. l.Corner2(data[idx])
  99. idx++
  100. }
  101. if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%8 == 4) {
  102. l.Corner3(data[idx])
  103. idx++
  104. }
  105. if (row == l.size.MatrixRows()+4) && (col == 2) && (l.size.MatrixColumns()%8 == 0) {
  106. l.Corner4(data[idx])
  107. idx++
  108. }
  109. for true {
  110. if (row < l.size.MatrixRows()) && (col >= 0) && !l.Occupied(row, col) {
  111. l.SetSimple(row, col, data[idx])
  112. idx++
  113. }
  114. row -= 2
  115. col += 2
  116. if (row < 0) || (col >= l.size.MatrixColumns()) {
  117. break
  118. }
  119. }
  120. row += 1
  121. col += 3
  122. for true {
  123. if (row >= 0) && (col < l.size.MatrixColumns()) && !l.Occupied(row, col) {
  124. l.SetSimple(row, col, data[idx])
  125. idx++
  126. }
  127. row += 2
  128. col -= 2
  129. if (row >= l.size.MatrixRows()) || (col < 0) {
  130. break
  131. }
  132. }
  133. row += 3
  134. col += 1
  135. }
  136. if !l.Occupied(l.size.MatrixRows()-1, l.size.MatrixColumns()-1) {
  137. l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, 255, 0)
  138. l.Set(l.size.MatrixRows()-2, l.size.MatrixColumns()-2, 255, 0)
  139. }
  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. }