Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / qrcode / BC_QRBitMatrixParser.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 "../common/BC_CommonBitMatrix.h"\r
25 #include "BC_QRCoderVersion.h"\r
26 #include "BC_QRCoderFormatInformation.h"\r
27 #include "BC_QRDataMask.h"\r
28 #include "BC_QRBitMatrixParser.h"\r
29 CBC_QRBitMatrixParser::CBC_QRBitMatrixParser()\r
30 {\r
31 }\r
32 void CBC_QRBitMatrixParser::Init(CBC_CommonBitMatrix *bitMatrix, int32_t &e)\r
33 {\r
34     m_dimension = bitMatrix->GetDimension(e);\r
35     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
36     m_tempBitMatrix = bitMatrix;\r
37     if(m_dimension < 21 || (m_dimension & 0x03) != 1) {\r
38         e = BCExceptionRead;\r
39         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
40     }\r
41     m_bitMatrix = m_tempBitMatrix;\r
42     m_parsedFormatInfo = NULL;\r
43     m_version = NULL;\r
44 }\r
45 CBC_QRBitMatrixParser::~CBC_QRBitMatrixParser()\r
46 {\r
47     if(m_parsedFormatInfo != NULL) {\r
48         delete m_parsedFormatInfo;\r
49         m_parsedFormatInfo = NULL;\r
50     }\r
51     m_version = NULL;\r
52 }\r
53 CBC_QRCoderFormatInformation* CBC_QRBitMatrixParser::ReadFormatInformation(int32_t &e)\r
54 {\r
55     if(m_parsedFormatInfo != NULL) {\r
56         return m_parsedFormatInfo;\r
57     }\r
58     int32_t formatInfoBits = 0;\r
59     int32_t j;\r
60     for( j = 0; j < 6; j++) {\r
61         formatInfoBits = CopyBit(8, j, formatInfoBits);\r
62     }\r
63     formatInfoBits = CopyBit(8, 7, formatInfoBits);\r
64     formatInfoBits = CopyBit(8, 8, formatInfoBits);\r
65     formatInfoBits = CopyBit(7, 8, formatInfoBits);\r
66     for(int32_t i = 5; i >= 0; i--) {\r
67         formatInfoBits = CopyBit(i, 8, formatInfoBits);\r
68     }\r
69     m_parsedFormatInfo = CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);\r
70     if(m_parsedFormatInfo != NULL) {\r
71         return m_parsedFormatInfo;\r
72     }\r
73     int32_t dimension = m_bitMatrix->GetDimension(e);\r
74     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
75     formatInfoBits = 0;\r
76     int32_t iMin = dimension - 8;\r
77     for(j = dimension - 1; j >= iMin; j--) {\r
78         formatInfoBits = CopyBit(j, 8, formatInfoBits);\r
79     }\r
80     for(int32_t k = dimension - 7; k < dimension; k++) {\r
81         formatInfoBits = CopyBit(8, k , formatInfoBits);\r
82     }\r
83     m_parsedFormatInfo = CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);\r
84     if(m_parsedFormatInfo != NULL) {\r
85         return m_parsedFormatInfo;\r
86     }\r
87     e = BCExceptionRead;\r
88     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
89     return NULL;\r
90 }\r
91 CBC_QRCoderVersion* CBC_QRBitMatrixParser::ReadVersion(int32_t &e)\r
92 {\r
93     if(m_version != NULL) {\r
94         return m_version;\r
95     }\r
96     int32_t dimension = m_bitMatrix->GetDimension(e);\r
97     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
98     int32_t provisionVersion = (dimension - 17) >> 2;\r
99     if(provisionVersion <= 6) {\r
100         CBC_QRCoderVersion* qrv = CBC_QRCoderVersion::GetVersionForNumber(provisionVersion, e);\r
101         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
102         return qrv;\r
103     }\r
104     int32_t versionBits = 0;\r
105     for (int32_t i = 5; i >= 0; i--) {\r
106         int32_t jMin = dimension - 11;\r
107         for (int32_t j = dimension - 9; j >= jMin; j--) {\r
108             versionBits = CopyBit(i, j, versionBits);\r
109         }\r
110     }\r
111     m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);\r
112     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
113     if (m_version != NULL && m_version->GetDimensionForVersion() == dimension) {\r
114         return m_version;\r
115     }\r
116     versionBits = 0;\r
117     for (int32_t j = 5; j >= 0; j--) {\r
118         int32_t iMin = dimension - 11;\r
119         for (int32_t i = dimension - 9; i >= iMin; i--) {\r
120             versionBits = CopyBit(i, j, versionBits);\r
121         }\r
122     }\r
123     m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);\r
124     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
125     if (m_version != NULL && m_version->GetDimensionForVersion() == dimension) {\r
126         return m_version;\r
127     }\r
128     e = BCExceptionRead;\r
129     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
130     return NULL;\r
131 }\r
132 int32_t CBC_QRBitMatrixParser::CopyBit(int32_t i, int32_t j, int32_t versionBits)\r
133 {\r
134     return m_bitMatrix->Get(j, i) ? (versionBits << 1) | 0x1 : versionBits << 1;\r
135 }\r
136 CFX_ByteArray* CBC_QRBitMatrixParser::ReadCodewords(int32_t &e)\r
137 {\r
138     CBC_QRCoderFormatInformation *formatInfo   = ReadFormatInformation(e);\r
139     BC_EXCEPTION_CHECK_ReturnValue(e, NULL)\r
140     CBC_QRCoderVersion                    *version              = ReadVersion(e);\r
141     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
142     CBC_QRDataMask                *dataMask             = CBC_QRDataMask::ForReference((int32_t)(formatInfo->GetDataMask()), e);\r
143     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
144     int32_t                               dimension             = m_bitMatrix->GetDimension(e);\r
145     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
146     dataMask->UnmaskBitMatirx(m_bitMatrix, dimension);\r
147     CBC_CommonBitMatrix* cbm = version->BuildFunctionPattern(e);\r
148     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
149     CBC_AutoPtr<CBC_CommonBitMatrix > functionPattern(cbm);\r
150     FX_BOOL                       readingUp             = TRUE;\r
151     CFX_ByteArray * temp = FX_NEW CFX_ByteArray;\r
152     temp->SetSize(version->GetTotalCodeWords());\r
153     CBC_AutoPtr<CFX_ByteArray> result(temp);\r
154     int32_t                                resultOffset = 0;\r
155     int32_t                                currentByte  = 0;\r
156     int32_t                                bitsRead             = 0;\r
157     for(int32_t j = dimension - 1; j > 0; j -= 2) {\r
158         if(j == 6) {\r
159             j--;\r
160         }\r
161         for(int32_t count = 0; count < dimension; count++) {\r
162             int32_t i = readingUp ? dimension - 1 - count : count;\r
163             for(int32_t col = 0; col < 2; col++) {\r
164                 if(!functionPattern->Get(j - col, i)) {\r
165                     bitsRead++;\r
166                     currentByte <<= 1;\r
167                     if(m_bitMatrix->Get(j - col, i)) {\r
168                         currentByte |= 1;\r
169                     }\r
170                     if(bitsRead == 8) {\r
171                         (*result)[resultOffset++] = (uint8_t) currentByte;\r
172                         bitsRead = 0;\r
173                         currentByte = 0;\r
174                     }\r
175                 }\r
176             }\r
177         }\r
178         readingUp ^= TRUE;\r
179     }\r
180     if(resultOffset != version->GetTotalCodeWords()) {\r
181         e = BCExceptionRead;\r
182         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
183     }\r
184     return result.release();\r
185 }\r