Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_DataMatrixBitMatrixParser.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "barcode.h"\r
8 #include "include/BC_CommonBitMatrix.h"\r
9 #include "include/BC_DataMatrixVersion.h"\r
10 #include "include/BC_DataMatrixBitMatrixParser.h"\r
11 CBC_DataMatrixBitMatrixParser::CBC_DataMatrixBitMatrixParser()\r
12 {\r
13     m_mappingBitMatrix = NULL;\r
14     m_version = NULL;\r
15     m_readMappingMatrix = NULL;\r
16 }\r
17 void CBC_DataMatrixBitMatrixParser::Init(CBC_CommonBitMatrix *bitMatrix, FX_INT32 &e)\r
18 {\r
19     FX_INT32 dimension = bitMatrix->GetHeight();\r
20     if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0) {\r
21         e = BCExceptionFormatException;\r
22         return;\r
23     }\r
24     m_version = ReadVersion(bitMatrix, e);\r
25     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
26     m_mappingBitMatrix = ExtractDataRegion(bitMatrix, e);\r
27     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
28     m_readMappingMatrix = FX_NEW CBC_CommonBitMatrix();\r
29     m_readMappingMatrix->Init(m_mappingBitMatrix->GetWidth(), m_mappingBitMatrix->GetHeight());\r
30 }\r
31 CBC_DataMatrixBitMatrixParser::~CBC_DataMatrixBitMatrixParser()\r
32 {\r
33     if(m_mappingBitMatrix != NULL) {\r
34         delete m_mappingBitMatrix;\r
35     }\r
36     m_mappingBitMatrix = NULL;\r
37     if(m_readMappingMatrix != NULL) {\r
38         delete m_readMappingMatrix;\r
39     }\r
40     m_readMappingMatrix = NULL;\r
41 }\r
42 CBC_DataMatrixVersion *CBC_DataMatrixBitMatrixParser::GetVersion()\r
43 {\r
44     return m_version;\r
45 }\r
46 CBC_DataMatrixVersion *CBC_DataMatrixBitMatrixParser::ReadVersion(CBC_CommonBitMatrix *bitMatrix, FX_INT32 &e)\r
47 {\r
48     FX_INT32 rows = bitMatrix->GetHeight();\r
49     FX_INT32 columns = bitMatrix->GetWidth();\r
50     CBC_DataMatrixVersion *temp = CBC_DataMatrixVersion::GetVersionForDimensions(rows, columns, e);\r
51     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
52     return temp;\r
53 }\r
54 CFX_ByteArray *CBC_DataMatrixBitMatrixParser::ReadCodewords(FX_INT32 &e)\r
55 {\r
56     CBC_AutoPtr<CFX_ByteArray> result(FX_NEW CFX_ByteArray());\r
57     result->SetSize(m_version->GetTotalCodewords());\r
58     FX_INT32 resultOffset = 0;\r
59     FX_INT32 row = 4;\r
60     FX_INT32 column = 0;\r
61     FX_INT32 numRows = m_mappingBitMatrix->GetHeight();\r
62     FX_INT32 numColumns = m_mappingBitMatrix->GetWidth();\r
63     FX_BOOL corner1Read = FALSE;\r
64     FX_BOOL corner2Read = FALSE;\r
65     FX_BOOL corner3Read = FALSE;\r
66     FX_BOOL corner4Read = FALSE;\r
67     do {\r
68         if ((row == numRows) && (column == 0) && !corner1Read) {\r
69             (*result)[resultOffset++] = (FX_BYTE) ReadCorner1(numRows, numColumns);\r
70             row -= 2;\r
71             column += 2;\r
72             corner1Read = TRUE;\r
73         } else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read) {\r
74             (*result)[resultOffset++] = (FX_BYTE) ReadCorner2(numRows, numColumns);\r
75             row -= 2;\r
76             column += 2;\r
77             corner2Read = TRUE;\r
78         } else if ((row == numRows + 4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read) {\r
79             (*result)[resultOffset++] = (FX_BYTE) ReadCorner3(numRows, numColumns);\r
80             row -= 2;\r
81             column += 2;\r
82             corner3Read = TRUE;\r
83         } else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read) {\r
84             (*result)[resultOffset++] = (FX_BYTE) ReadCorner4(numRows, numColumns);\r
85             row -= 2;\r
86             column += 2;\r
87             corner4Read = TRUE;\r
88         } else {\r
89             do {\r
90                 if ((row < numRows) && (column >= 0) && !m_readMappingMatrix->Get(column, row)) {\r
91                     if (resultOffset < (*result).GetSize() ) {\r
92                         (*result)[resultOffset++] = (FX_BYTE) ReadUtah(row, column, numRows, numColumns);\r
93                     }\r
94                 }\r
95                 row -= 2;\r
96                 column += 2;\r
97             } while ((row >= 0) && (column < numColumns));\r
98             row += 1;\r
99             column += 3;\r
100             do {\r
101                 if ((row >= 0) && (column < numColumns) && !m_readMappingMatrix->Get(column, row)) {\r
102                     if (resultOffset < (*result).GetSize() ) {\r
103                         (*result)[resultOffset++] = (FX_BYTE) ReadUtah(row, column, numRows, numColumns);\r
104                     }\r
105                 }\r
106                 row += 2;\r
107                 column -= 2;\r
108             } while ((row < numRows) && (column >= 0));\r
109             row += 3;\r
110             column += 1;\r
111         }\r
112     } while ((row < numRows) || (column < numColumns));\r
113     if (resultOffset != m_version->GetTotalCodewords()) {\r
114         e = BCExceptionFormatException;\r
115         return NULL;\r
116     }\r
117     return result.release();\r
118 }\r
119 FX_BOOL CBC_DataMatrixBitMatrixParser::ReadModule(FX_INT32 row, FX_INT32 column, FX_INT32 numRows, FX_INT32 numColumns)\r
120 {\r
121     if (row < 0) {\r
122         row += numRows;\r
123         column += 4 - ((numRows + 4) & 0x07);\r
124     }\r
125     if (column < 0) {\r
126         column += numColumns;\r
127         row += 4 - ((numColumns + 4) & 0x07);\r
128     }\r
129     m_readMappingMatrix->Set(column, row);\r
130     return m_mappingBitMatrix->Get(column, row);\r
131 }\r
132 FX_INT32 CBC_DataMatrixBitMatrixParser::ReadUtah(FX_INT32 row, FX_INT32 column, FX_INT32 numRows, FX_INT32 numColumns)\r
133 {\r
134     FX_INT32 currentByte = 0;\r
135     if (ReadModule(row - 2, column - 2, numRows, numColumns)) {\r
136         currentByte |= 1;\r
137     }\r
138     currentByte <<= 1;\r
139     if (ReadModule(row - 2, column - 1, numRows, numColumns)) {\r
140         currentByte |= 1;\r
141     }\r
142     currentByte <<= 1;\r
143     if (ReadModule(row - 1, column - 2, numRows, numColumns)) {\r
144         currentByte |= 1;\r
145     }\r
146     currentByte <<= 1;\r
147     if (ReadModule(row - 1, column - 1, numRows, numColumns)) {\r
148         currentByte |= 1;\r
149     }\r
150     currentByte <<= 1;\r
151     if (ReadModule(row - 1, column, numRows, numColumns)) {\r
152         currentByte |= 1;\r
153     }\r
154     currentByte <<= 1;\r
155     if (ReadModule(row, column - 2, numRows, numColumns)) {\r
156         currentByte |= 1;\r
157     }\r
158     currentByte <<= 1;\r
159     if (ReadModule(row, column - 1, numRows, numColumns)) {\r
160         currentByte |= 1;\r
161     }\r
162     currentByte <<= 1;\r
163     if (ReadModule(row, column, numRows, numColumns)) {\r
164         currentByte |= 1;\r
165     }\r
166     return currentByte;\r
167 }\r
168 FX_INT32 CBC_DataMatrixBitMatrixParser::ReadCorner1(FX_INT32 numRows, FX_INT32 numColumns)\r
169 {\r
170     FX_INT32 currentByte = 0;\r
171     if (ReadModule(numRows - 1, 0, numRows, numColumns)) {\r
172         currentByte |= 1;\r
173     }\r
174     currentByte <<= 1;\r
175     if (ReadModule(numRows - 1, 1, numRows, numColumns)) {\r
176         currentByte |= 1;\r
177     }\r
178     currentByte <<= 1;\r
179     if (ReadModule(numRows - 1, 2, numRows, numColumns)) {\r
180         currentByte |= 1;\r
181     }\r
182     currentByte <<= 1;\r
183     if (ReadModule(0, numColumns - 2, numRows, numColumns)) {\r
184         currentByte |= 1;\r
185     }\r
186     currentByte <<= 1;\r
187     if (ReadModule(0, numColumns - 1, numRows, numColumns)) {\r
188         currentByte |= 1;\r
189     }\r
190     currentByte <<= 1;\r
191     if (ReadModule(1, numColumns - 1, numRows, numColumns)) {\r
192         currentByte |= 1;\r
193     }\r
194     currentByte <<= 1;\r
195     if (ReadModule(2, numColumns - 1, numRows, numColumns)) {\r
196         currentByte |= 1;\r
197     }\r
198     currentByte <<= 1;\r
199     if (ReadModule(3, numColumns - 1, numRows, numColumns)) {\r
200         currentByte |= 1;\r
201     }\r
202     return currentByte;\r
203 }\r
204 FX_INT32 CBC_DataMatrixBitMatrixParser::ReadCorner2(FX_INT32 numRows, FX_INT32 numColumns)\r
205 {\r
206     FX_INT32 currentByte = 0;\r
207     if (ReadModule(numRows - 3, 0, numRows, numColumns)) {\r
208         currentByte |= 1;\r
209     }\r
210     currentByte <<= 1;\r
211     if (ReadModule(numRows - 2, 0, numRows, numColumns)) {\r
212         currentByte |= 1;\r
213     }\r
214     currentByte <<= 1;\r
215     if (ReadModule(numRows - 1, 0, numRows, numColumns)) {\r
216         currentByte |= 1;\r
217     }\r
218     currentByte <<= 1;\r
219     if (ReadModule(0, numColumns - 4, numRows, numColumns)) {\r
220         currentByte |= 1;\r
221     }\r
222     currentByte <<= 1;\r
223     if (ReadModule(0, numColumns - 3, numRows, numColumns)) {\r
224         currentByte |= 1;\r
225     }\r
226     currentByte <<= 1;\r
227     if (ReadModule(0, numColumns - 2, numRows, numColumns)) {\r
228         currentByte |= 1;\r
229     }\r
230     currentByte <<= 1;\r
231     if (ReadModule(0, numColumns - 1, numRows, numColumns)) {\r
232         currentByte |= 1;\r
233     }\r
234     currentByte <<= 1;\r
235     if (ReadModule(1, numColumns - 1, numRows, numColumns)) {\r
236         currentByte |= 1;\r
237     }\r
238     return currentByte;\r
239 }\r
240 FX_INT32 CBC_DataMatrixBitMatrixParser::ReadCorner3(FX_INT32 numRows, FX_INT32 numColumns)\r
241 {\r
242     FX_INT32 currentByte = 0;\r
243     if (ReadModule(numRows - 1, 0, numRows, numColumns)) {\r
244         currentByte |= 1;\r
245     }\r
246     currentByte <<= 1;\r
247     if (ReadModule(numRows - 1, numColumns - 1, numRows, numColumns)) {\r
248         currentByte |= 1;\r
249     }\r
250     currentByte <<= 1;\r
251     if (ReadModule(0, numColumns - 3, numRows, numColumns)) {\r
252         currentByte |= 1;\r
253     }\r
254     currentByte <<= 1;\r
255     if (ReadModule(0, numColumns - 2, numRows, numColumns)) {\r
256         currentByte |= 1;\r
257     }\r
258     currentByte <<= 1;\r
259     if (ReadModule(0, numColumns - 1, numRows, numColumns)) {\r
260         currentByte |= 1;\r
261     }\r
262     currentByte <<= 1;\r
263     if (ReadModule(1, numColumns - 3, numRows, numColumns)) {\r
264         currentByte |= 1;\r
265     }\r
266     currentByte <<= 1;\r
267     if (ReadModule(1, numColumns - 2, numRows, numColumns)) {\r
268         currentByte |= 1;\r
269     }\r
270     currentByte <<= 1;\r
271     if (ReadModule(1, numColumns - 1, numRows, numColumns)) {\r
272         currentByte |= 1;\r
273     }\r
274     return currentByte;\r
275 }\r
276 FX_INT32 CBC_DataMatrixBitMatrixParser::ReadCorner4(FX_INT32 numRows, FX_INT32 numColumns)\r
277 {\r
278     FX_INT32 currentByte = 0;\r
279     if (ReadModule(numRows - 3, 0, numRows, numColumns)) {\r
280         currentByte |= 1;\r
281     }\r
282     currentByte <<= 1;\r
283     if (ReadModule(numRows - 2, 0, numRows, numColumns)) {\r
284         currentByte |= 1;\r
285     }\r
286     currentByte <<= 1;\r
287     if (ReadModule(numRows - 1, 0, numRows, numColumns)) {\r
288         currentByte |= 1;\r
289     }\r
290     currentByte <<= 1;\r
291     if (ReadModule(0, numColumns - 2, numRows, numColumns)) {\r
292         currentByte |= 1;\r
293     }\r
294     currentByte <<= 1;\r
295     if (ReadModule(0, numColumns - 1, numRows, numColumns)) {\r
296         currentByte |= 1;\r
297     }\r
298     currentByte <<= 1;\r
299     if (ReadModule(1, numColumns - 1, numRows, numColumns)) {\r
300         currentByte |= 1;\r
301     }\r
302     currentByte <<= 1;\r
303     if (ReadModule(2, numColumns - 1, numRows, numColumns)) {\r
304         currentByte |= 1;\r
305     }\r
306     currentByte <<= 1;\r
307     if (ReadModule(3, numColumns - 1, numRows, numColumns)) {\r
308         currentByte |= 1;\r
309     }\r
310     return currentByte;\r
311 }\r
312 CBC_CommonBitMatrix *CBC_DataMatrixBitMatrixParser::ExtractDataRegion(CBC_CommonBitMatrix *bitMatrix , FX_INT32 &e)\r
313 {\r
314     FX_INT32 symbolSizeRows = m_version->GetSymbolSizeRows();\r
315     FX_INT32 symbolSizeColumns = m_version->GetSymbolSizeColumns();\r
316     if (bitMatrix->GetHeight() != symbolSizeRows) {\r
317         e = BCExceptionCanNotCallGetDimensionOnNonSquareMatrix;\r
318         return NULL;\r
319     }\r
320     FX_INT32 dataRegionSizeRows = m_version->GetDataRegionSizeRows();\r
321     FX_INT32 dataRegionSizeColumns = m_version->GetDataRegionSizeColumns();\r
322     FX_INT32 numDataRegionsRow = symbolSizeRows / dataRegionSizeRows;\r
323     FX_INT32 numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns;\r
324     FX_INT32 sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;\r
325     FX_INT32 sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;\r
326     CBC_CommonBitMatrix *bitMatrixWithoutAlignment = FX_NEW CBC_CommonBitMatrix();\r
327     bitMatrixWithoutAlignment->Init(sizeDataRegionColumn, sizeDataRegionRow);\r
328     FX_INT32 dataRegionRow;\r
329     for (dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {\r
330         FX_INT32 dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;\r
331         FX_INT32 dataRegionColumn;\r
332         for (dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {\r
333             FX_INT32 dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;\r
334             FX_INT32 i;\r
335             for (i = 0; i < dataRegionSizeRows; ++i) {\r
336                 FX_INT32 readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;\r
337                 FX_INT32 writeRowOffset = dataRegionRowOffset + i;\r
338                 FX_INT32 j;\r
339                 for (j = 0; j < dataRegionSizeColumns; ++j) {\r
340                     FX_INT32 readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;\r
341                     if (bitMatrix->Get(readColumnOffset, readRowOffset)) {\r
342                         FX_INT32 writeColumnOffset = dataRegionColumnOffset + j;\r
343                         bitMatrixWithoutAlignment->Set(writeColumnOffset, writeRowOffset);\r
344                     }\r
345                 }\r
346             }\r
347         }\r
348     }\r
349     return bitMatrixWithoutAlignment;\r
350 }\r