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