1 /**
2  * libdmtx - Data Matrix Encoding/Decoding Library
3  * Copyright 2008, 2009 Mike Laughton. All rights reserved.
4  * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved.
5  *
6  * See LICENSE file in the main project directory for full
7  * terms of use and distribution.
8  *
9  * Contact:
10  * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
11  * Mike Laughton <mike@dragonflylogic.com>
12  *
13  * \file dmtxplacemod.c
14  * \brief Data Matrix module placement
15  */
16 
17 /**
18  * receives symbol row and col and returns status
19  * DmtxModuleOn / !DmtxModuleOn (DmtxModuleOff)
20  * DmtxModuleAssigned
21  * DmtxModuleVisited
22  * DmtxModuleData / !DmtxModuleData (DmtxModuleAlignment)
23  * row and col are expressed in symbol coordinates, so (0,0) is the intersection of the "L"
24  */
25 int
dmtxSymbolModuleStatus(DmtxMessage * message,int sizeIdx,int symbolRow,int symbolCol)26 dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int symbolCol)
27 {
28    int symbolRowReverse;
29    int mappingRow, mappingCol;
30    int dataRegionRows, dataRegionCols;
31    int symbolRows, mappingCols;
32 
33    dataRegionRows = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionRows, sizeIdx);
34    dataRegionCols = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionCols, sizeIdx);
35    symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx);
36    mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx);
37 
38    symbolRowReverse = symbolRows - symbolRow - 1;
39    mappingRow = symbolRowReverse - 1 - 2 * (symbolRowReverse / (dataRegionRows+2));
40    mappingCol = symbolCol - 1 - 2 * (symbolCol / (dataRegionCols+2));
41 
42    /* Solid portion of alignment patterns */
43    if(symbolRow % (dataRegionRows+2) == 0 ||
44          symbolCol % (dataRegionCols+2) == 0)
45       return (DmtxModuleOnRGB | (!DmtxModuleData));
46 
47    /* Horinzontal calibration bars */
48    if((symbolRow+1) % (dataRegionRows+2) == 0)
49       return (((symbolCol & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData));
50 
51    /* Vertical calibration bars */
52    if((symbolCol+1) % (dataRegionCols+2) == 0)
53       return (((symbolRow & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData));
54 
55    /* Data modules */
56    return (message->array[mappingRow * mappingCols + mappingCol] | DmtxModuleData);
57 }
58 
59 /**
60  * \brief  Logical relationship between bit and module locations
61  * \param  modules
62  * \param  codewords
63  * \param  sizeIdx
64  * \param  moduleOnColor
65  * \return Number of codewords read
66  */
67 static int
ModulePlacementEcc200(unsigned char * modules,unsigned char * codewords,int sizeIdx,int moduleOnColor)68 ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor)
69 {
70    int row, col, chr;
71    int mappingRows, mappingCols;
72 
73    assert(moduleOnColor & (DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue));
74 
75    mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx);
76    mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx);
77 
78    /* Start in the nominal location for the 8th bit of the first character */
79    chr = 0;
80    row = 4;
81    col = 0;
82 
83    do {
84       /* Repeatedly first check for one of the special corner cases */
85       if((row == mappingRows) && (col == 0))
86          PatternShapeSpecial1(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
87       else if((row == mappingRows-2) && (col == 0) && (mappingCols%4 != 0))
88          PatternShapeSpecial2(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
89       else if((row == mappingRows-2) && (col == 0) && (mappingCols%8 == 4))
90          PatternShapeSpecial3(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
91       else if((row == mappingRows+4) && (col == 2) && (mappingCols%8 == 0))
92          PatternShapeSpecial4(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
93 
94       /* Sweep upward diagonally, inserting successive characters */
95       do {
96          if((row < mappingRows) && (col >= 0) &&
97                !(modules[row*mappingCols+col] & DmtxModuleVisited))
98             PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor);
99          row -= 2;
100          col += 2;
101       } while ((row >= 0) && (col < mappingCols));
102       row += 1;
103       col += 3;
104 
105       /* Sweep downward diagonally, inserting successive characters */
106       do {
107          if((row >= 0) && (col < mappingCols) &&
108                !(modules[row*mappingCols+col] & DmtxModuleVisited))
109             PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor);
110          row += 2;
111          col -= 2;
112       } while ((row < mappingRows) && (col >= 0));
113       row += 3;
114       col += 1;
115       /* ... until the entire modules array is scanned */
116    } while ((row < mappingRows) || (col < mappingCols));
117 
118    /* If lower righthand corner is untouched then fill in the fixed pattern */
119    if(!(modules[mappingRows * mappingCols - 1] &
120          DmtxModuleVisited)) {
121 
122       modules[mappingRows * mappingCols - 1] |= moduleOnColor;
123       modules[(mappingRows * mappingCols) - mappingCols - 2] |= moduleOnColor;
124    } /* XXX should this fixed pattern also be used in reading somehow? */
125 
126    /* XXX compare that chr == region->dataSize here */
127    return chr; /* XXX number of codewords read off */
128 }
129 
130 /**
131  * \brief  XXX
132  * \param  modules
133  * \param  mappingRows
134  * \param  mappingCols
135  * \param  row
136  * \param  col
137  * \param  codeword
138  * \param  moduleOnColor
139  * \return void
140  */
141 static void
PatternShapeStandard(unsigned char * modules,int mappingRows,int mappingCols,int row,int col,unsigned char * codeword,int moduleOnColor)142 PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor)
143 {
144    PlaceModule(modules, mappingRows, mappingCols, row-2, col-2, codeword, DmtxMaskBit1, moduleOnColor);
145    PlaceModule(modules, mappingRows, mappingCols, row-2, col-1, codeword, DmtxMaskBit2, moduleOnColor);
146    PlaceModule(modules, mappingRows, mappingCols, row-1, col-2, codeword, DmtxMaskBit3, moduleOnColor);
147    PlaceModule(modules, mappingRows, mappingCols, row-1, col-1, codeword, DmtxMaskBit4, moduleOnColor);
148    PlaceModule(modules, mappingRows, mappingCols, row-1, col,   codeword, DmtxMaskBit5, moduleOnColor);
149    PlaceModule(modules, mappingRows, mappingCols, row,   col-2, codeword, DmtxMaskBit6, moduleOnColor);
150    PlaceModule(modules, mappingRows, mappingCols, row,   col-1, codeword, DmtxMaskBit7, moduleOnColor);
151    PlaceModule(modules, mappingRows, mappingCols, row,   col,   codeword, DmtxMaskBit8, moduleOnColor);
152 }
153 
154 /**
155  * \brief  XXX
156  * \param  modules
157  * \param  mappingRows
158  * \param  mappingCols
159  * \param  codeword
160  * \param  moduleOnColor
161  * \return void
162  */
163 static void
PatternShapeSpecial1(unsigned char * modules,int mappingRows,int mappingCols,unsigned char * codeword,int moduleOnColor)164 PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
165 {
166    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor);
167    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 1, codeword, DmtxMaskBit2, moduleOnColor);
168    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 2, codeword, DmtxMaskBit3, moduleOnColor);
169    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
170    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
171    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor);
172    PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
173    PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
174 }
175 
176 /**
177  * \brief  XXX
178  * \param  modules
179  * \param  mappingRows
180  * \param  mappingCols
181  * \param  codeword
182  * \param  moduleOnColor
183  * \return void
184  */
185 static void
PatternShapeSpecial2(unsigned char * modules,int mappingRows,int mappingCols,unsigned char * codeword,int moduleOnColor)186 PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
187 {
188    PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor);
189    PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor);
190    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor);
191    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-4, codeword, DmtxMaskBit4, moduleOnColor);
192    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit5, moduleOnColor);
193    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit6, moduleOnColor);
194    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
195    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
196 }
197 
198 /**
199  * \brief  XXX
200  * \param  modules
201  * \param  mappingRows
202  * \param  mappingCols
203  * \param  codeword
204  * \param  moduleOnColor
205  * \return void
206  */
207 static void
PatternShapeSpecial3(unsigned char * modules,int mappingRows,int mappingCols,unsigned char * codeword,int moduleOnColor)208 PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
209 {
210    PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor);
211    PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor);
212    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor);
213    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
214    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
215    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor);
216    PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
217    PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
218 }
219 
220 /**
221  * \brief  XXX
222  * \param  modules
223  * \param  mappingRows
224  * \param  mappingCols
225  * \param  codeword
226  * \param  moduleOnColor
227  * \return void
228  */
229 static void
PatternShapeSpecial4(unsigned char * modules,int mappingRows,int mappingCols,unsigned char * codeword,int moduleOnColor)230 PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
231 {
232    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor);
233    PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, mappingCols-1, codeword, DmtxMaskBit2, moduleOnColor);
234    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit3, moduleOnColor);
235    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
236    PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
237    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-3, codeword, DmtxMaskBit6, moduleOnColor);
238    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-2, codeword, DmtxMaskBit7, moduleOnColor);
239    PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
240 }
241 
242 /**
243  * \brief  XXX
244  * \param  modules
245  * \param  mappingRows
246  * \param  mappingCols
247  * \param  row
248  * \param  col
249  * \param  codeword
250  * \param  mask
251  * \param  moduleOnColor
252  * \return void
253  */
254 static void
PlaceModule(unsigned char * modules,int mappingRows,int mappingCols,int row,int col,unsigned char * codeword,int mask,int moduleOnColor)255 PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int mask, int moduleOnColor)
256 {
257    if(row < 0) {
258       row += mappingRows;
259       col += 4 - ((mappingRows+4)%8);
260    }
261    if(col < 0) {
262       col += mappingCols;
263       row += 4 - ((mappingCols+4)%8);
264    }
265 
266    /* If module has already been assigned then we are decoding the pattern into codewords */
267    if((modules[row*mappingCols+col] & DmtxModuleAssigned) != 0) {
268       if((modules[row*mappingCols+col] & moduleOnColor) != 0)
269          *codeword |= mask;
270       else
271          *codeword &= (0xff ^ mask);
272    }
273    /* Otherwise we are encoding the codewords into a pattern */
274    else {
275       if((*codeword & mask) != 0x00)
276          modules[row*mappingCols+col] |= moduleOnColor;
277 
278       modules[row*mappingCols+col] |= DmtxModuleAssigned;
279    }
280 
281    modules[row*mappingCols+col] |= DmtxModuleVisited;
282 }
283