Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / qrcode / BC_QRAlignmentPatternFinder.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 2007 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_ResultPoint.h"\r
25 #include "../common/BC_CommonBitMatrix.h"\r
26 #include "BC_QRAlignmentPattern.h"\r
27 #include "BC_QRAlignmentPatternFinder.h"\r
28 CBC_QRAlignmentPatternFinder::CBC_QRAlignmentPatternFinder(CBC_CommonBitMatrix *image,\r
29         int32_t startX,\r
30         int32_t startY,\r
31         int32_t width,\r
32         int32_t height,\r
33         FX_FLOAT moduleSize): m_image(image),\r
34     m_startX(startX),\r
35     m_startY(startY),\r
36     m_width(width),\r
37     m_height(height),\r
38     m_moduleSize(moduleSize)\r
39 \r
40 {\r
41     m_crossCheckStateCount.SetSize(3);\r
42 }\r
43 CBC_QRAlignmentPatternFinder::~CBC_QRAlignmentPatternFinder()\r
44 {\r
45     for (int32_t i = 0; i < m_possibleCenters.GetSize(); i++) {\r
46         delete (CBC_QRAlignmentPattern*)m_possibleCenters[i];\r
47     }\r
48     m_possibleCenters.RemoveAll();\r
49 }\r
50 CBC_QRAlignmentPattern  *CBC_QRAlignmentPatternFinder::Find(int32_t &e)\r
51 {\r
52     int32_t startX = m_startX;\r
53     int32_t height = m_height;\r
54     int32_t maxJ = startX + m_width;\r
55     int32_t middleI = m_startY + (height >> 1);\r
56     CFX_Int32Array stateCount;\r
57     stateCount.SetSize(3);\r
58     for (int32_t iGen = 0; iGen < height; iGen++) {\r
59         int32_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));\r
60         stateCount[0] = 0;\r
61         stateCount[1] = 0;\r
62         stateCount[2] = 0;\r
63         int32_t j = startX;\r
64         while (j < maxJ && !m_image->Get(j, i)) {\r
65             j++;\r
66         }\r
67         int32_t currentState = 0;\r
68         while (j < maxJ) {\r
69             if (m_image->Get(j, i)) {\r
70                 if (currentState == 1) {\r
71                     stateCount[currentState]++;\r
72                 } else {\r
73                     if (currentState == 2) {\r
74                         if (FoundPatternCross(stateCount)) {\r
75                             CBC_QRAlignmentPattern  *confirmed = HandlePossibleCenter(stateCount, i, j);\r
76                             if (confirmed != NULL) {\r
77                                 return confirmed;\r
78                             }\r
79                         }\r
80                         stateCount[0] = stateCount[2];\r
81                         stateCount[1] = 1;\r
82                         stateCount[2] = 0;\r
83                         currentState = 1;\r
84                     } else {\r
85                         stateCount[++currentState]++;\r
86                     }\r
87                 }\r
88             } else {\r
89                 if (currentState == 1) {\r
90                     currentState++;\r
91                 }\r
92                 stateCount[currentState]++;\r
93             }\r
94             j++;\r
95         }\r
96         if (FoundPatternCross(stateCount)) {\r
97             CBC_QRAlignmentPattern *confirmed = HandlePossibleCenter(stateCount, i, maxJ);\r
98             if (confirmed != NULL) {\r
99                 return confirmed;\r
100             }\r
101         }\r
102     }\r
103     if (m_possibleCenters.GetSize() != 0) {\r
104         return  ((CBC_QRAlignmentPattern*) (m_possibleCenters[0]) )->Clone();\r
105     }\r
106     e = BCExceptionRead;\r
107     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
108     return NULL;\r
109 }\r
110 FX_FLOAT CBC_QRAlignmentPatternFinder::CenterFromEnd(const CFX_Int32Array &stateCount, int32_t end)\r
111 {\r
112     return (FX_FLOAT) (end - stateCount[2]) - stateCount[1] / 2.0f;\r
113 }\r
114 FX_BOOL CBC_QRAlignmentPatternFinder::FoundPatternCross(const CFX_Int32Array &stateCount)\r
115 {\r
116     FX_FLOAT moduleSize = m_moduleSize;\r
117     FX_FLOAT maxVariance = moduleSize / 2.0f;\r
118     for (int32_t i = 0; i < 3; i++) {\r
119         if (fabs(moduleSize - stateCount[i]) >= maxVariance) {\r
120             return false;\r
121         }\r
122     }\r
123     return TRUE;\r
124 }\r
125 FX_FLOAT CBC_QRAlignmentPatternFinder::CrossCheckVertical(int32_t startI, int32_t centerJ, int32_t maxCount, int32_t originalStateCountTotal)\r
126 {\r
127     CBC_CommonBitMatrix *image = m_image;\r
128     int32_t maxI = m_image->GetHeight();\r
129     CFX_Int32Array stateCount;\r
130     stateCount.Copy(m_crossCheckStateCount);\r
131     stateCount[0] = 0;\r
132     stateCount[1] = 0;\r
133     stateCount[2] = 0;\r
134     int32_t i = startI;\r
135     while (i >= 0 && m_image->Get(centerJ, i) && stateCount[1] <= maxCount) {\r
136         stateCount[1]++;\r
137         i--;\r
138     }\r
139     if (i < 0 || stateCount[1] > maxCount) {\r
140         return FXSYS_nan();\r
141     }\r
142     while (i >= 0 && !m_image->Get(centerJ, i) && stateCount[0] <= maxCount) {\r
143         stateCount[0]++;\r
144         i--;\r
145     }\r
146     if (stateCount[0] > maxCount) {\r
147         return FXSYS_nan();\r
148     }\r
149     i = startI + 1;\r
150     while (i < maxI && m_image->Get(centerJ, i) && stateCount[1] <= maxCount) {\r
151         stateCount[1]++;\r
152         i++;\r
153     }\r
154     if (i == maxI || stateCount[1] > maxCount) {\r
155         return FXSYS_nan();\r
156     }\r
157     while (i < maxI && !m_image->Get(centerJ, i) && stateCount[2] <= maxCount) {\r
158         stateCount[2]++;\r
159         i++;\r
160     }\r
161     if (stateCount[2] > maxCount) {\r
162         return FXSYS_nan();\r
163     }\r
164     int32_t stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\r
165     if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {\r
166         return FXSYS_nan();\r
167     }\r
168     return FoundPatternCross(stateCount) ? CenterFromEnd(stateCount, i) : FXSYS_nan();\r
169 }\r
170 CBC_QRAlignmentPattern *CBC_QRAlignmentPatternFinder::HandlePossibleCenter(const CFX_Int32Array &stateCount, int32_t i, int32_t j)\r
171 {\r
172     int32_t stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\r
173     FX_FLOAT centerJ = CenterFromEnd(stateCount, j);\r
174     FX_FLOAT centerI = CrossCheckVertical(i, (int32_t) centerJ, 2 * stateCount[1], stateCountTotal);\r
175     if (!FXSYS_isnan(centerI)) {\r
176         FX_FLOAT estimatedModuleSize = (FX_FLOAT) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;\r
177         int32_t max = m_possibleCenters.GetSize();\r
178         for (int32_t index = 0; index < max; index++) {\r
179             CBC_QRAlignmentPattern *center = (CBC_QRAlignmentPattern *)(m_possibleCenters[index]);\r
180             if (center->AboutEquals(estimatedModuleSize, centerI, centerJ)) {\r
181                 return FX_NEW CBC_QRAlignmentPattern(centerJ, centerI, estimatedModuleSize);\r
182             }\r
183         }\r
184         m_possibleCenters.Add(FX_NEW CBC_QRAlignmentPattern(centerJ, centerI, estimatedModuleSize));\r
185     }\r
186     return NULL;\r
187 }\r