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