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