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