Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / pdf417 / BC_PDF417DetectionResult.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 // Original code is licensed as follows:\r
7 /*\r
8  * Copyright 2013 ZXing authors\r
9  *\r
10  * Licensed under the Apache License, Version 2.0 (the "License");\r
11  * you may not use this file except in compliance with the License.\r
12  * You may obtain a copy of the License at\r
13  *\r
14  *      http://www.apache.org/licenses/LICENSE-2.0\r
15  *\r
16  * Unless required by applicable law or agreed to in writing, software\r
17  * distributed under the License is distributed on an "AS IS" BASIS,\r
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
19  * See the License for the specific language governing permissions and\r
20  * limitations under the License.\r
21  */\r
22 \r
23 #include "../barcode.h"\r
24 #include "BC_PDF417Codeword.h"\r
25 #include "BC_PDF417BarcodeMetadata.h"\r
26 #include "BC_PDF417BoundingBox.h"\r
27 #include "BC_PDF417DetectionResultColumn.h"\r
28 #include "BC_PDF417Common.h"\r
29 #include "BC_PDF417DetectionResultRowIndicatorColumn.h"\r
30 #include "BC_PDF417DetectionResult.h"\r
31 int32_t CBC_DetectionResult::ADJUST_ROW_NUMBER_SKIP = 2;\r
32 CBC_DetectionResult::CBC_DetectionResult(CBC_BarcodeMetadata* barcodeMetadata, CBC_BoundingBox* boundingBox)\r
33 {\r
34     m_barcodeMetadata = barcodeMetadata;\r
35     m_barcodeColumnCount = barcodeMetadata->getColumnCount();\r
36     m_boundingBox = boundingBox;\r
37     m_detectionResultColumns.SetSize(m_barcodeColumnCount + 2);\r
38     for (int32_t i = 0; i < m_barcodeColumnCount + 2; i++) {\r
39         m_detectionResultColumns[i] = NULL;\r
40     }\r
41 }\r
42 CBC_DetectionResult::~CBC_DetectionResult()\r
43 {\r
44     delete m_boundingBox;\r
45     delete m_barcodeMetadata;\r
46     m_detectionResultColumns.RemoveAll();\r
47 }\r
48 CFX_PtrArray& CBC_DetectionResult::getDetectionResultColumns()\r
49 {\r
50     adjustIndicatorColumnRowNumbers((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0));\r
51     adjustIndicatorColumnRowNumbers((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(m_barcodeColumnCount + 1));\r
52     int32_t unadjustedCodewordCount = CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE;\r
53     int32_t previousUnadjustedCount;\r
54     do {\r
55         previousUnadjustedCount = unadjustedCodewordCount;\r
56         unadjustedCodewordCount = adjustRowNumbers();\r
57     } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount);\r
58     return m_detectionResultColumns;\r
59 }\r
60 void CBC_DetectionResult::setBoundingBox(CBC_BoundingBox* boundingBox)\r
61 {\r
62     m_boundingBox = boundingBox;\r
63 }\r
64 CBC_BoundingBox* CBC_DetectionResult::getBoundingBox()\r
65 {\r
66     return m_boundingBox;\r
67 }\r
68 void CBC_DetectionResult::setDetectionResultColumn(int32_t barcodeColumn, CBC_DetectionResultColumn* detectionResultColumn)\r
69 {\r
70     m_detectionResultColumns[barcodeColumn] = detectionResultColumn;\r
71 }\r
72 CBC_DetectionResultColumn* CBC_DetectionResult::getDetectionResultColumn(int32_t barcodeColumn)\r
73 {\r
74     return (CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn];\r
75 }\r
76 CFX_ByteString CBC_DetectionResult::toString()\r
77 {\r
78     CBC_DetectionResultColumn* rowIndicatorColumn = (CBC_DetectionResultColumn*)m_detectionResultColumns[0];\r
79     if (rowIndicatorColumn == NULL) {\r
80         rowIndicatorColumn = (CBC_DetectionResultColumn*)m_detectionResultColumns[m_barcodeColumnCount + 1];\r
81     }\r
82     CFX_ByteString result;\r
83     for (int32_t codewordsRow = 0; codewordsRow < rowIndicatorColumn->getCodewords()->GetSize(); codewordsRow++) {\r
84         result += (FX_CHAR) codewordsRow;\r
85         for (int32_t barcodeColumn = 0; barcodeColumn < m_barcodeColumnCount + 2; barcodeColumn++) {\r
86             if (m_detectionResultColumns[barcodeColumn] == NULL) {\r
87                 result += "    |   ";\r
88                 continue;\r
89             }\r
90             CBC_Codeword* codeword = (CBC_Codeword*)((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])->getCodewords()->GetAt(codewordsRow);\r
91             if (codeword == NULL) {\r
92                 result += "    |   ";\r
93                 continue;\r
94             }\r
95             result += codeword->getRowNumber();\r
96             result += codeword->getValue();\r
97         }\r
98     }\r
99     return result;\r
100 }\r
101 void CBC_DetectionResult::adjustIndicatorColumnRowNumbers(CBC_DetectionResultColumn* detectionResultColumn)\r
102 {\r
103     if (detectionResultColumn != NULL) {\r
104         ((CBC_DetectionResultRowIndicatorColumn*)detectionResultColumn)->adjustCompleteIndicatorColumnRowNumbers(*m_barcodeMetadata);\r
105     }\r
106 }\r
107 int32_t CBC_DetectionResult::adjustRowNumbers()\r
108 {\r
109     int32_t unadjustedCount = adjustRowNumbersByRow();\r
110     if (unadjustedCount == 0) {\r
111         return 0;\r
112     }\r
113     for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1; barcodeColumn++) {\r
114         CFX_PtrArray* codewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])->getCodewords();\r
115         for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize(); codewordsRow++) {\r
116             if (codewords->GetAt(codewordsRow) == NULL) {\r
117                 continue;\r
118             }\r
119             if (!((CBC_Codeword*)codewords->GetAt(codewordsRow))->hasValidRowNumber()) {\r
120                 adjustRowNumbers(barcodeColumn, codewordsRow, codewords);\r
121             }\r
122         }\r
123     }\r
124     return unadjustedCount;\r
125 }\r
126 int32_t CBC_DetectionResult::adjustRowNumbersByRow()\r
127 {\r
128     adjustRowNumbersFromBothRI();\r
129     int32_t unadjustedCount = adjustRowNumbersFromLRI();\r
130     return unadjustedCount + adjustRowNumbersFromRRI();\r
131 }\r
132 int32_t CBC_DetectionResult::adjustRowNumbersFromBothRI()\r
133 {\r
134     if (m_detectionResultColumns[0] == NULL || m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {\r
135         return 0;\r
136     }\r
137     CFX_PtrArray* LRIcodewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns[0])->getCodewords();\r
138     CFX_PtrArray* RRIcodewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns[m_barcodeColumnCount + 1])->getCodewords();\r
139     for (int32_t codewordsRow = 0; codewordsRow < LRIcodewords->GetSize(); codewordsRow++) {\r
140         if (LRIcodewords->GetAt(codewordsRow) != NULL &&\r
141                 RRIcodewords->GetAt(codewordsRow) != NULL &&\r
142                 ((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber() == ((CBC_Codeword*)RRIcodewords->GetAt(codewordsRow))->getRowNumber()) {\r
143             for (int32_t barcodeColumn = 1; barcodeColumn <= m_barcodeColumnCount; barcodeColumn++) {\r
144                 CBC_Codeword* codeword = (CBC_Codeword*)((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])->getCodewords()->GetAt(codewordsRow);\r
145                 if (codeword == NULL) {\r
146                     continue;\r
147                 }\r
148                 codeword->setRowNumber(((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber());\r
149                 if (!codeword->hasValidRowNumber()) {\r
150                     ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])->getCodewords()->SetAt(codewordsRow, NULL);\r
151                 }\r
152             }\r
153         }\r
154     }\r
155     return 0;\r
156 }\r
157 int32_t CBC_DetectionResult::adjustRowNumbersFromRRI()\r
158 {\r
159     if (m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {\r
160         return 0;\r
161     }\r
162     int32_t unadjustedCount = 0;\r
163     CFX_PtrArray* codewords = ((CBC_DetectionResultColumn*) m_detectionResultColumns.GetAt(m_barcodeColumnCount + 1))->getCodewords();\r
164     for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize(); codewordsRow++) {\r
165         if (codewords->GetAt(codewordsRow) == NULL) {\r
166             continue;\r
167         }\r
168         int32_t rowIndicatorRowNumber = ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();\r
169         int32_t invalidRowCounts = 0;\r
170         for (int32_t barcodeColumn = m_barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) {\r
171             CBC_Codeword* codeword = (CBC_Codeword*)((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(barcodeColumn))->getCodewords()->GetAt(codewordsRow);\r
172             if (codeword != NULL) {\r
173                 invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\r
174                 if (!codeword->hasValidRowNumber()) {\r
175                     unadjustedCount++;\r
176                 }\r
177             }\r
178         }\r
179     }\r
180     return unadjustedCount;\r
181 }\r
182 int32_t CBC_DetectionResult::adjustRowNumbersFromLRI()\r
183 {\r
184     if (m_detectionResultColumns[0] == NULL) {\r
185         return 0;\r
186     }\r
187     int32_t unadjustedCount = 0;\r
188     CFX_PtrArray* codewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0))->getCodewords();\r
189     for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize(); codewordsRow++) {\r
190         if (codewords->GetAt(codewordsRow) == NULL) {\r
191             continue;\r
192         }\r
193         int32_t rowIndicatorRowNumber = ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();\r
194         int32_t invalidRowCounts = 0;\r
195         for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) {\r
196             CBC_Codeword* codeword = (CBC_Codeword*)((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])->getCodewords()->GetAt(codewordsRow);\r
197             if (codeword != NULL) {\r
198                 invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\r
199                 if (!codeword->hasValidRowNumber()) {\r
200                     unadjustedCount++;\r
201                 }\r
202             }\r
203         }\r
204     }\r
205     return unadjustedCount;\r
206 }\r
207 int32_t CBC_DetectionResult::adjustRowNumberIfValid(int32_t rowIndicatorRowNumber, int32_t invalidRowCounts, CBC_Codeword* codeword)\r
208 {\r
209     if (codeword == NULL) {\r
210         return invalidRowCounts;\r
211     }\r
212     if (!codeword->hasValidRowNumber()) {\r
213         if (codeword->isValidRowNumber(rowIndicatorRowNumber)) {\r
214             codeword->setRowNumber(rowIndicatorRowNumber);\r
215             invalidRowCounts = 0;\r
216         } else {\r
217             ++invalidRowCounts;\r
218         }\r
219     }\r
220     return invalidRowCounts;\r
221 }\r
222 void CBC_DetectionResult::adjustRowNumbers(int32_t barcodeColumn, int32_t codewordsRow, CFX_PtrArray* codewords)\r
223 {\r
224     CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow);\r
225     CFX_PtrArray* previousColumnCodewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(barcodeColumn - 1))->getCodewords();\r
226     CFX_PtrArray* nextColumnCodewords = previousColumnCodewords;\r
227     if (m_detectionResultColumns[barcodeColumn + 1] != NULL) {\r
228         nextColumnCodewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn + 1])->getCodewords();\r
229     }\r
230     CFX_PtrArray otherCodewords;\r
231     otherCodewords.SetSize(14);\r
232     otherCodewords[2] = previousColumnCodewords->GetAt(codewordsRow);\r
233     otherCodewords[3] = nextColumnCodewords->GetAt(codewordsRow);\r
234     if (codewordsRow > 0) {\r
235         otherCodewords[0] = codewords->GetAt(codewordsRow - 1);\r
236         otherCodewords[4] = previousColumnCodewords->GetAt(codewordsRow - 1);\r
237         otherCodewords[5] = nextColumnCodewords->GetAt(codewordsRow - 1);\r
238     }\r
239     if (codewordsRow > 1) {\r
240         otherCodewords[8] = codewords->GetAt(codewordsRow - 2);\r
241         otherCodewords[10] = previousColumnCodewords->GetAt(codewordsRow - 2);\r
242         otherCodewords[11] = nextColumnCodewords->GetAt(codewordsRow - 2);\r
243     }\r
244     if (codewordsRow < codewords->GetSize() - 1) {\r
245         otherCodewords[1] = codewords->GetAt(codewordsRow + 1);\r
246         otherCodewords[6] = previousColumnCodewords->GetAt(codewordsRow + 1);\r
247         otherCodewords[7] = nextColumnCodewords->GetAt(codewordsRow + 1);\r
248     }\r
249     if (codewordsRow < codewords->GetSize() - 2) {\r
250         otherCodewords[9] = codewords->GetAt(codewordsRow + 2);\r
251         otherCodewords[12] = previousColumnCodewords->GetAt(codewordsRow + 2);\r
252         otherCodewords[13] = nextColumnCodewords->GetAt(codewordsRow + 2);\r
253     }\r
254     for (int32_t i = 0; i < otherCodewords.GetSize(); i++) {\r
255         CBC_Codeword* otherCodeword = (CBC_Codeword*)otherCodewords.GetAt(i);\r
256         if (adjustRowNumber(codeword, otherCodeword)) {\r
257             return;\r
258         }\r
259     }\r
260 }\r
261 FX_BOOL CBC_DetectionResult::adjustRowNumber(CBC_Codeword* codeword, CBC_Codeword* otherCodeword)\r
262 {\r
263     if (otherCodeword == NULL) {\r
264         return FALSE;\r
265     }\r
266     if (otherCodeword->hasValidRowNumber() && otherCodeword->getBucket() == codeword->getBucket()) {\r
267         codeword->setRowNumber(otherCodeword->getRowNumber());\r
268         return TRUE;\r
269     }\r
270     return FALSE;\r
271 }\r
272 int32_t CBC_DetectionResult::getBarcodeColumnCount()\r
273 {\r
274     return m_barcodeColumnCount;\r
275 }\r
276 int32_t CBC_DetectionResult::getBarcodeRowCount()\r
277 {\r
278     return m_barcodeMetadata->getRowCount();\r
279 }\r
280 int32_t CBC_DetectionResult::getBarcodeECLevel()\r
281 {\r
282     return m_barcodeMetadata->getErrorCorrectionLevel();\r
283 }\r