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