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