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  * Copyright 2016 Tim Zaman. All rights reserved.
6  *
7  * See LICENSE file in the main project directory for full
8  * terms of use and distribution.
9  *
10  * Contact:
11  * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
12  * Mike Laughton <mike@dragonflylogic.com>
13  *
14  * \file dmtxsymbol.c
15  * \brief Data Matrix symbol attributes
16  */
17 
18 
19 /**
20  * \brief  Retrieve symbol index from rows and columns
21  * \param  rows
22  * \param  cols
23  * \return sizeIdx value
24  */
25 extern int
getSizeIdxFromSymbolDimension(int rows,int cols)26 getSizeIdxFromSymbolDimension(int rows, int cols)
27 {
28   int symbolRows, symbolCols;
29   for (int i=0; i<30; i++){
30     symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, i);
31     symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, i);
32     if (rows==symbolRows && cols==symbolCols){
33       return i;
34     }
35   }
36   return -1;
37 }
38 
39 
40 /**
41  * \brief  Retrieve property based on symbol size
42  * \param  attribute
43  * \param  sizeIdx
44  * \return Attribute value
45  */
46 extern int
dmtxGetSymbolAttribute(int attribute,int sizeIdx)47 dmtxGetSymbolAttribute(int attribute, int sizeIdx)
48 {
49    static const int symbolRows[] = { 10, 12, 14, 16, 18, 20,  22,  24,  26,
50                                                  32, 36, 40,  44,  48,  52,
51                                                  64, 72, 80,  88,  96, 104,
52                                                         120, 132, 144,
53                                                   8,  8, 12,  12,  16,  16 };
54 
55    static const int symbolCols[] = { 10, 12, 14, 16, 18, 20,  22,  24,  26,
56                                                  32, 36, 40,  44,  48,  52,
57                                                  64, 72, 80,  88,  96, 104,
58                                                         120, 132, 144,
59                                                  18, 32, 26,  36,  36,  48 };
60 
61    static const int dataRegionRows[] = { 8, 10, 12, 14, 16, 18, 20, 22, 24,
62                                                     14, 16, 18, 20, 22, 24,
63                                                     14, 16, 18, 20, 22, 24,
64                                                             18, 20, 22,
65                                                      6,  6, 10, 10, 14, 14 };
66 
67    static const int dataRegionCols[] = { 8, 10, 12, 14, 16, 18, 20, 22, 24,
68                                                     14, 16, 18, 20, 22, 24,
69                                                     14, 16, 18, 20, 22, 24,
70                                                             18, 20, 22,
71                                                     16, 14, 24, 16, 16, 22 };
72 
73    static const int horizDataRegions[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1,
74                                                     2, 2, 2, 2, 2, 2,
75                                                     4, 4, 4, 4, 4, 4,
76                                                           6, 6, 6,
77                                                     1, 2, 1, 2, 2, 2 };
78 
79    static const int interleavedBlocks[] = { 1, 1, 1, 1, 1, 1, 1,  1, 1,
80                                                      1, 1, 1, 1,  1, 2,
81                                                      2, 4, 4, 4,  4, 6,
82                                                            6, 8, 10,
83                                                      1, 1, 1, 1,  1, 1 };
84 
85    static const int symbolDataWords[] = { 3, 5, 8,  12,   18,   22,   30,   36,  44,
86                                                     62,   86,  114,  144,  174, 204,
87                                                    280,  368,  456,  576,  696, 816,
88                                                               1050, 1304, 1558,
89                                                      5,   10,   16,   22,   32,  49 };
90 
91    static const int blockErrorWords[] = { 5, 7, 10, 12, 14, 18, 20, 24, 28,
92                                                     36, 42, 48, 56, 68, 42,
93                                                     56, 36, 48, 56, 68, 56,
94                                                             68, 62, 62,
95                                                      7, 11, 14, 18, 24, 28 };
96 
97    static const int blockMaxCorrectable[] = { 2, 3, 5,  6,  7,  9,  10,  12,  14,
98                                                        18, 21, 24,  28,  34,  21,
99                                                        28, 18, 24,  28,  34,  28,
100                                                                34,  31,  31,
101                                                    3,  5,  7,   9,  12,  14 };
102 
103    if(sizeIdx < 0 || sizeIdx >= DmtxSymbolSquareCount + DmtxSymbolRectCount)
104       return DmtxUndefined;
105 
106    switch(attribute) {
107       case DmtxSymAttribSymbolRows:
108          return symbolRows[sizeIdx];
109       case DmtxSymAttribSymbolCols:
110          return symbolCols[sizeIdx];
111       case DmtxSymAttribDataRegionRows:
112          return dataRegionRows[sizeIdx];
113       case DmtxSymAttribDataRegionCols:
114          return dataRegionCols[sizeIdx];
115       case DmtxSymAttribHorizDataRegions:
116          return horizDataRegions[sizeIdx];
117       case DmtxSymAttribVertDataRegions:
118          return (sizeIdx < DmtxSymbolSquareCount) ? horizDataRegions[sizeIdx] : 1;
119       case DmtxSymAttribMappingMatrixRows:
120          return dataRegionRows[sizeIdx] *
121                dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, sizeIdx);
122       case DmtxSymAttribMappingMatrixCols:
123          return dataRegionCols[sizeIdx] * horizDataRegions[sizeIdx];
124       case DmtxSymAttribInterleavedBlocks:
125          return interleavedBlocks[sizeIdx];
126       case DmtxSymAttribBlockErrorWords:
127          return blockErrorWords[sizeIdx];
128       case DmtxSymAttribBlockMaxCorrectable:
129          return blockMaxCorrectable[sizeIdx];
130       case DmtxSymAttribSymbolDataWords:
131          return symbolDataWords[sizeIdx];
132       case DmtxSymAttribSymbolErrorWords:
133          return blockErrorWords[sizeIdx] * interleavedBlocks[sizeIdx];
134       case DmtxSymAttribSymbolMaxCorrectable:
135          return blockMaxCorrectable[sizeIdx] * interleavedBlocks[sizeIdx];
136    }
137 
138    return DmtxUndefined;
139 }
140 
141 /**
142  * \brief  Retrieve data size for a specific symbol size and block number
143  * \param  sizeIdx
144  * \param  blockIdx
145  * \return Attribute value
146  */
147 extern int
dmtxGetBlockDataSize(int sizeIdx,int blockIdx)148 dmtxGetBlockDataSize(int sizeIdx, int blockIdx)
149 {
150    int symbolDataWords;
151    int interleavedBlocks;
152    int count;
153 
154    symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx);
155    interleavedBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx);
156 
157    if(symbolDataWords < 1 || interleavedBlocks < 1)
158       return DmtxUndefined;
159 
160    count = (int)(symbolDataWords/interleavedBlocks);
161 
162    return (sizeIdx == DmtxSymbol144x144 && blockIdx < 8) ? count + 1 : count;
163 }
164 
165 /**
166  * \brief  Determine symbol size based on data size and requested properties
167  * \param  dataWords
168  * \param  sizeIdxRequest
169  * \return Symbol size index (or DmtxUndefined if none)
170  */
171 static int
FindSymbolSize(int dataWords,int sizeIdxRequest)172 FindSymbolSize(int dataWords, int sizeIdxRequest)
173 {
174    int sizeIdx;
175    int idxBeg, idxEnd;
176 
177    if(dataWords <= 0)
178       return DmtxUndefined;
179 
180    if(sizeIdxRequest == DmtxSymbolSquareAuto || sizeIdxRequest == DmtxSymbolRectAuto) {
181 
182       if(sizeIdxRequest == DmtxSymbolSquareAuto) {
183          idxBeg = 0;
184          idxEnd = DmtxSymbolSquareCount;
185       }
186       else {
187          idxBeg = DmtxSymbolSquareCount;
188          idxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount;
189       }
190 
191       for(sizeIdx = idxBeg; sizeIdx < idxEnd; sizeIdx++) {
192          if(dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) >= dataWords)
193             break;
194       }
195 
196       if(sizeIdx == idxEnd)
197          return DmtxUndefined;
198    }
199    else {
200       sizeIdx = sizeIdxRequest;
201    }
202 
203    if(dataWords > dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx))
204       return DmtxUndefined;
205 
206    return sizeIdx;
207 }
208