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 2013 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 "BC_PDF417Codeword.h"
25 #include "BC_PDF417BarcodeMetadata.h"
26 #include "BC_PDF417BoundingBox.h"
27 #include "BC_PDF417DetectionResultColumn.h"
28 #include "BC_PDF417Common.h"
29 #include "BC_PDF417DetectionResultRowIndicatorColumn.h"
30 #include "BC_PDF417DetectionResult.h"
31 int32_t CBC_DetectionResult::ADJUST_ROW_NUMBER_SKIP = 2;
CBC_DetectionResult(CBC_BarcodeMetadata * barcodeMetadata,CBC_BoundingBox * boundingBox)32 CBC_DetectionResult::CBC_DetectionResult(CBC_BarcodeMetadata* barcodeMetadata,
33                                          CBC_BoundingBox* boundingBox) {
34   m_barcodeMetadata = barcodeMetadata;
35   m_barcodeColumnCount = barcodeMetadata->getColumnCount();
36   m_boundingBox = boundingBox;
37   m_detectionResultColumns.SetSize(m_barcodeColumnCount + 2);
38   for (int32_t i = 0; i < m_barcodeColumnCount + 2; i++) {
39     m_detectionResultColumns[i] = NULL;
40   }
41 }
~CBC_DetectionResult()42 CBC_DetectionResult::~CBC_DetectionResult() {
43   delete m_boundingBox;
44   delete m_barcodeMetadata;
45   m_detectionResultColumns.RemoveAll();
46 }
getDetectionResultColumns()47 CFX_PtrArray& CBC_DetectionResult::getDetectionResultColumns() {
48   adjustIndicatorColumnRowNumbers(
49       (CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0));
50   adjustIndicatorColumnRowNumbers(
51       (CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
52           m_barcodeColumnCount + 1));
53   int32_t unadjustedCodewordCount = CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE;
54   int32_t previousUnadjustedCount;
55   do {
56     previousUnadjustedCount = unadjustedCodewordCount;
57     unadjustedCodewordCount = adjustRowNumbers();
58   } while (unadjustedCodewordCount > 0 &&
59            unadjustedCodewordCount < previousUnadjustedCount);
60   return m_detectionResultColumns;
61 }
setBoundingBox(CBC_BoundingBox * boundingBox)62 void CBC_DetectionResult::setBoundingBox(CBC_BoundingBox* boundingBox) {
63   m_boundingBox = boundingBox;
64 }
getBoundingBox()65 CBC_BoundingBox* CBC_DetectionResult::getBoundingBox() {
66   return m_boundingBox;
67 }
setDetectionResultColumn(int32_t barcodeColumn,CBC_DetectionResultColumn * detectionResultColumn)68 void CBC_DetectionResult::setDetectionResultColumn(
69     int32_t barcodeColumn,
70     CBC_DetectionResultColumn* detectionResultColumn) {
71   m_detectionResultColumns[barcodeColumn] = detectionResultColumn;
72 }
getDetectionResultColumn(int32_t barcodeColumn)73 CBC_DetectionResultColumn* CBC_DetectionResult::getDetectionResultColumn(
74     int32_t barcodeColumn) {
75   return (CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn];
76 }
toString()77 CFX_ByteString CBC_DetectionResult::toString() {
78   CBC_DetectionResultColumn* rowIndicatorColumn =
79       (CBC_DetectionResultColumn*)m_detectionResultColumns[0];
80   if (rowIndicatorColumn == NULL) {
81     rowIndicatorColumn = (CBC_DetectionResultColumn*)
82         m_detectionResultColumns[m_barcodeColumnCount + 1];
83   }
84   CFX_ByteString result;
85   for (int32_t codewordsRow = 0;
86        codewordsRow < rowIndicatorColumn->getCodewords()->GetSize();
87        codewordsRow++) {
88     result += (FX_CHAR)codewordsRow;
89     for (int32_t barcodeColumn = 0; barcodeColumn < m_barcodeColumnCount + 2;
90          barcodeColumn++) {
91       if (m_detectionResultColumns[barcodeColumn] == NULL) {
92         result += "    |   ";
93         continue;
94       }
95       CBC_Codeword* codeword =
96           (CBC_Codeword*)((CBC_DetectionResultColumn*)
97                               m_detectionResultColumns[barcodeColumn])
98               ->getCodewords()
99               ->GetAt(codewordsRow);
100       if (codeword == NULL) {
101         result += "    |   ";
102         continue;
103       }
104       result += codeword->getRowNumber();
105       result += codeword->getValue();
106     }
107   }
108   return result;
109 }
adjustIndicatorColumnRowNumbers(CBC_DetectionResultColumn * detectionResultColumn)110 void CBC_DetectionResult::adjustIndicatorColumnRowNumbers(
111     CBC_DetectionResultColumn* detectionResultColumn) {
112   if (detectionResultColumn != NULL) {
113     ((CBC_DetectionResultRowIndicatorColumn*)detectionResultColumn)
114         ->adjustCompleteIndicatorColumnRowNumbers(*m_barcodeMetadata);
115   }
116 }
adjustRowNumbers()117 int32_t CBC_DetectionResult::adjustRowNumbers() {
118   int32_t unadjustedCount = adjustRowNumbersByRow();
119   if (unadjustedCount == 0) {
120     return 0;
121   }
122   for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1;
123        barcodeColumn++) {
124     CFX_PtrArray* codewords =
125         ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])
126             ->getCodewords();
127     for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
128          codewordsRow++) {
129       if (codewords->GetAt(codewordsRow) == NULL) {
130         continue;
131       }
132       if (!((CBC_Codeword*)codewords->GetAt(codewordsRow))
133                ->hasValidRowNumber()) {
134         adjustRowNumbers(barcodeColumn, codewordsRow, codewords);
135       }
136     }
137   }
138   return unadjustedCount;
139 }
adjustRowNumbersByRow()140 int32_t CBC_DetectionResult::adjustRowNumbersByRow() {
141   adjustRowNumbersFromBothRI();
142   int32_t unadjustedCount = adjustRowNumbersFromLRI();
143   return unadjustedCount + adjustRowNumbersFromRRI();
144 }
adjustRowNumbersFromBothRI()145 int32_t CBC_DetectionResult::adjustRowNumbersFromBothRI() {
146   if (m_detectionResultColumns[0] == NULL ||
147       m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {
148     return 0;
149   }
150   CFX_PtrArray* LRIcodewords =
151       ((CBC_DetectionResultColumn*)m_detectionResultColumns[0])->getCodewords();
152   CFX_PtrArray* RRIcodewords =
153       ((CBC_DetectionResultColumn*)
154            m_detectionResultColumns[m_barcodeColumnCount + 1])
155           ->getCodewords();
156   for (int32_t codewordsRow = 0; codewordsRow < LRIcodewords->GetSize();
157        codewordsRow++) {
158     if (LRIcodewords->GetAt(codewordsRow) != NULL &&
159         RRIcodewords->GetAt(codewordsRow) != NULL &&
160         ((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber() ==
161             ((CBC_Codeword*)RRIcodewords->GetAt(codewordsRow))
162                 ->getRowNumber()) {
163       for (int32_t barcodeColumn = 1; barcodeColumn <= m_barcodeColumnCount;
164            barcodeColumn++) {
165         CBC_Codeword* codeword =
166             (CBC_Codeword*)((CBC_DetectionResultColumn*)
167                                 m_detectionResultColumns[barcodeColumn])
168                 ->getCodewords()
169                 ->GetAt(codewordsRow);
170         if (codeword == NULL) {
171           continue;
172         }
173         codeword->setRowNumber(
174             ((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber());
175         if (!codeword->hasValidRowNumber()) {
176           ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])
177               ->getCodewords()
178               ->SetAt(codewordsRow, NULL);
179         }
180       }
181     }
182   }
183   return 0;
184 }
adjustRowNumbersFromRRI()185 int32_t CBC_DetectionResult::adjustRowNumbersFromRRI() {
186   if (m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {
187     return 0;
188   }
189   int32_t unadjustedCount = 0;
190   CFX_PtrArray* codewords =
191       ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
192            m_barcodeColumnCount + 1))
193           ->getCodewords();
194   for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
195        codewordsRow++) {
196     if (codewords->GetAt(codewordsRow) == NULL) {
197       continue;
198     }
199     int32_t rowIndicatorRowNumber =
200         ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();
201     int32_t invalidRowCounts = 0;
202     for (int32_t barcodeColumn = m_barcodeColumnCount + 1;
203          barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
204          barcodeColumn--) {
205       CBC_Codeword* codeword =
206           (CBC_Codeword*)((CBC_DetectionResultColumn*)
207                               m_detectionResultColumns.GetAt(barcodeColumn))
208               ->getCodewords()
209               ->GetAt(codewordsRow);
210       if (codeword != NULL) {
211         invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber,
212                                                   invalidRowCounts, codeword);
213         if (!codeword->hasValidRowNumber()) {
214           unadjustedCount++;
215         }
216       }
217     }
218   }
219   return unadjustedCount;
220 }
adjustRowNumbersFromLRI()221 int32_t CBC_DetectionResult::adjustRowNumbersFromLRI() {
222   if (m_detectionResultColumns[0] == NULL) {
223     return 0;
224   }
225   int32_t unadjustedCount = 0;
226   CFX_PtrArray* codewords =
227       ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0))
228           ->getCodewords();
229   for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
230        codewordsRow++) {
231     if (codewords->GetAt(codewordsRow) == NULL) {
232       continue;
233     }
234     int32_t rowIndicatorRowNumber =
235         ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();
236     int32_t invalidRowCounts = 0;
237     for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1 &&
238                                     invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
239          barcodeColumn++) {
240       CBC_Codeword* codeword =
241           (CBC_Codeword*)((CBC_DetectionResultColumn*)
242                               m_detectionResultColumns[barcodeColumn])
243               ->getCodewords()
244               ->GetAt(codewordsRow);
245       if (codeword != NULL) {
246         invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber,
247                                                   invalidRowCounts, codeword);
248         if (!codeword->hasValidRowNumber()) {
249           unadjustedCount++;
250         }
251       }
252     }
253   }
254   return unadjustedCount;
255 }
adjustRowNumberIfValid(int32_t rowIndicatorRowNumber,int32_t invalidRowCounts,CBC_Codeword * codeword)256 int32_t CBC_DetectionResult::adjustRowNumberIfValid(
257     int32_t rowIndicatorRowNumber,
258     int32_t invalidRowCounts,
259     CBC_Codeword* codeword) {
260   if (codeword == NULL) {
261     return invalidRowCounts;
262   }
263   if (!codeword->hasValidRowNumber()) {
264     if (codeword->isValidRowNumber(rowIndicatorRowNumber)) {
265       codeword->setRowNumber(rowIndicatorRowNumber);
266       invalidRowCounts = 0;
267     } else {
268       ++invalidRowCounts;
269     }
270   }
271   return invalidRowCounts;
272 }
adjustRowNumbers(int32_t barcodeColumn,int32_t codewordsRow,CFX_PtrArray * codewords)273 void CBC_DetectionResult::adjustRowNumbers(int32_t barcodeColumn,
274                                            int32_t codewordsRow,
275                                            CFX_PtrArray* codewords) {
276   CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow);
277   CFX_PtrArray* previousColumnCodewords =
278       ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
279            barcodeColumn - 1))
280           ->getCodewords();
281   CFX_PtrArray* nextColumnCodewords = previousColumnCodewords;
282   if (m_detectionResultColumns[barcodeColumn + 1] != NULL) {
283     nextColumnCodewords = ((CBC_DetectionResultColumn*)
284                                m_detectionResultColumns[barcodeColumn + 1])
285                               ->getCodewords();
286   }
287   CFX_PtrArray otherCodewords;
288   otherCodewords.SetSize(14);
289   otherCodewords[2] = previousColumnCodewords->GetAt(codewordsRow);
290   otherCodewords[3] = nextColumnCodewords->GetAt(codewordsRow);
291   if (codewordsRow > 0) {
292     otherCodewords[0] = codewords->GetAt(codewordsRow - 1);
293     otherCodewords[4] = previousColumnCodewords->GetAt(codewordsRow - 1);
294     otherCodewords[5] = nextColumnCodewords->GetAt(codewordsRow - 1);
295   }
296   if (codewordsRow > 1) {
297     otherCodewords[8] = codewords->GetAt(codewordsRow - 2);
298     otherCodewords[10] = previousColumnCodewords->GetAt(codewordsRow - 2);
299     otherCodewords[11] = nextColumnCodewords->GetAt(codewordsRow - 2);
300   }
301   if (codewordsRow < codewords->GetSize() - 1) {
302     otherCodewords[1] = codewords->GetAt(codewordsRow + 1);
303     otherCodewords[6] = previousColumnCodewords->GetAt(codewordsRow + 1);
304     otherCodewords[7] = nextColumnCodewords->GetAt(codewordsRow + 1);
305   }
306   if (codewordsRow < codewords->GetSize() - 2) {
307     otherCodewords[9] = codewords->GetAt(codewordsRow + 2);
308     otherCodewords[12] = previousColumnCodewords->GetAt(codewordsRow + 2);
309     otherCodewords[13] = nextColumnCodewords->GetAt(codewordsRow + 2);
310   }
311   for (int32_t i = 0; i < otherCodewords.GetSize(); i++) {
312     CBC_Codeword* otherCodeword = (CBC_Codeword*)otherCodewords.GetAt(i);
313     if (adjustRowNumber(codeword, otherCodeword)) {
314       return;
315     }
316   }
317 }
adjustRowNumber(CBC_Codeword * codeword,CBC_Codeword * otherCodeword)318 FX_BOOL CBC_DetectionResult::adjustRowNumber(CBC_Codeword* codeword,
319                                              CBC_Codeword* otherCodeword) {
320   if (otherCodeword == NULL) {
321     return FALSE;
322   }
323   if (otherCodeword->hasValidRowNumber() &&
324       otherCodeword->getBucket() == codeword->getBucket()) {
325     codeword->setRowNumber(otherCodeword->getRowNumber());
326     return TRUE;
327   }
328   return FALSE;
329 }
getBarcodeColumnCount()330 int32_t CBC_DetectionResult::getBarcodeColumnCount() {
331   return m_barcodeColumnCount;
332 }
getBarcodeRowCount()333 int32_t CBC_DetectionResult::getBarcodeRowCount() {
334   return m_barcodeMetadata->getRowCount();
335 }
getBarcodeECLevel()336 int32_t CBC_DetectionResult::getBarcodeECLevel() {
337   return m_barcodeMetadata->getErrorCorrectionLevel();
338 }
339