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 2008 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 <algorithm>
24
25 #include "xfa/src/fxbarcode/barcode.h"
26 #include "xfa/src/fxbarcode/BC_UtilCodingConvert.h"
27 #include "xfa/src/fxbarcode/common/BC_CommonByteArray.h"
28 #include "xfa/src/fxbarcode/common/BC_CommonByteMatrix.h"
29 #include "xfa/src/fxbarcode/common/reedsolomon/BC_ReedSolomon.h"
30 #include "xfa/src/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h"
31 #include "BC_QRCoder.h"
32 #include "BC_QRCoderEncoder.h"
33 #include "BC_QRCoderMode.h"
34 #include "BC_QRCoderEncoder.h"
35 #include "BC_QRCoderECBlocks.h"
36 #include "BC_QRCoderVersion.h"
37 #include "BC_QRCoderBlockPair.h"
38 #include "BC_QRCoderMaskUtil.h"
39 #include "BC_QRCoderMatrixUtil.h"
40 #include "BC_QRCoderBitVector.h"
41 const int32_t CBC_QRCoderEncoder::m_alphaNumbericTable[] = {
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
45 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
46 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
47 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1};
CBC_QRCoderEncoder()48 CBC_QRCoderEncoder::CBC_QRCoderEncoder() {}
~CBC_QRCoderEncoder()49 CBC_QRCoderEncoder::~CBC_QRCoderEncoder() {}
50 class Make_Pair {
51 public:
52 CBC_QRCoderMode* m_mode;
53 CFX_ByteString m_string;
54
55 private:
Make_Pair(const Make_Pair & mode_string)56 Make_Pair(const Make_Pair& mode_string) {}
operator =(Make_Pair & mode_string)57 Make_Pair& operator=(Make_Pair& mode_string) {
58 if (this == &mode_string) {
59 return *this;
60 }
61 m_mode = mode_string.m_mode;
62 m_string = mode_string.m_string;
63 return *this;
64 }
65
66 public:
Make_Pair(CBC_QRCoderMode * mode,const CFX_ByteString & str)67 Make_Pair(CBC_QRCoderMode* mode, const CFX_ByteString& str)
68 : m_mode(mode), m_string(str) {}
~Make_Pair()69 ~Make_Pair() {}
70 };
Encode(const CFX_ByteString & content,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoder * qrCode,int32_t & e,int32_t versionSpecify)71 void CBC_QRCoderEncoder::Encode(const CFX_ByteString& content,
72 CBC_QRCoderErrorCorrectionLevel* ecLevel,
73 CBC_QRCoder* qrCode,
74 int32_t& e,
75 int32_t versionSpecify) {
76 if (versionSpecify == 0) {
77 EncodeWithAutoVersion(content, ecLevel, qrCode, e);
78 BC_EXCEPTION_CHECK_ReturnVoid(e)
79 } else if (versionSpecify > 0 && versionSpecify <= 40) {
80 EncodeWithSpecifyVersion(content, ecLevel, qrCode, versionSpecify, e);
81 BC_EXCEPTION_CHECK_ReturnVoid(e);
82 } else {
83 e = BCExceptionVersionMust1_40;
84 BC_EXCEPTION_CHECK_ReturnVoid(e);
85 }
86 }
AppendECI(CBC_QRCoderBitVector * bits)87 void CBC_QRCoderEncoder::AppendECI(CBC_QRCoderBitVector* bits) {}
AppendDataModeLenghInfo(CFX_PtrArray & splitResult,CBC_QRCoderBitVector & headerAndDataBits,CBC_QRCoderMode * tempMode,CBC_QRCoder * qrCode,CFX_ByteString & encoding,int32_t & e)88 void CBC_QRCoderEncoder::AppendDataModeLenghInfo(
89 CFX_PtrArray& splitResult,
90 CBC_QRCoderBitVector& headerAndDataBits,
91 CBC_QRCoderMode* tempMode,
92 CBC_QRCoder* qrCode,
93 CFX_ByteString& encoding,
94 int32_t& e) {
95 for (int32_t i = 0; i < splitResult.GetSize(); i++) {
96 tempMode = ((Make_Pair*)splitResult[i])->m_mode;
97 if (tempMode == CBC_QRCoderMode::sGBK) {
98 AppendModeInfo(tempMode, &headerAndDataBits, e);
99 BC_EXCEPTION_CHECK_ReturnVoid(e);
100 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(),
101 qrCode->GetVersion(), tempMode, &headerAndDataBits, e);
102 BC_EXCEPTION_CHECK_ReturnVoid(e);
103 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode,
104 &headerAndDataBits, encoding, e);
105 BC_EXCEPTION_CHECK_ReturnVoid(e);
106 } else if (tempMode == CBC_QRCoderMode::sBYTE) {
107 CFX_ByteArray bytes;
108 CBC_UtilCodingConvert::LocaleToUtf8(
109 ((Make_Pair*)splitResult[i])->m_string, bytes);
110 AppendModeInfo(tempMode, &headerAndDataBits, e);
111 BC_EXCEPTION_CHECK_ReturnVoid(e);
112 AppendLengthInfo(bytes.GetSize(), qrCode->GetVersion(), tempMode,
113 &headerAndDataBits, e);
114 BC_EXCEPTION_CHECK_ReturnVoid(e);
115 Append8BitBytes(bytes, &headerAndDataBits, e);
116 BC_EXCEPTION_CHECK_ReturnVoid(e);
117 } else if (tempMode == CBC_QRCoderMode::sALPHANUMERIC) {
118 AppendModeInfo(tempMode, &headerAndDataBits, e);
119 BC_EXCEPTION_CHECK_ReturnVoid(e);
120 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(),
121 qrCode->GetVersion(), tempMode, &headerAndDataBits, e);
122 BC_EXCEPTION_CHECK_ReturnVoid(e);
123 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode,
124 &headerAndDataBits, encoding, e);
125 BC_EXCEPTION_CHECK_ReturnVoid(e);
126 } else if (tempMode == CBC_QRCoderMode::sNUMERIC) {
127 AppendModeInfo(tempMode, &headerAndDataBits, e);
128 BC_EXCEPTION_CHECK_ReturnVoid(e);
129 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(),
130 qrCode->GetVersion(), tempMode, &headerAndDataBits, e);
131 BC_EXCEPTION_CHECK_ReturnVoid(e);
132 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode,
133 &headerAndDataBits, encoding, e);
134 BC_EXCEPTION_CHECK_ReturnVoid(e);
135 } else {
136 e = BCExceptionUnknown;
137 BC_EXCEPTION_CHECK_ReturnVoid(e);
138 }
139 }
140 }
SplitString(const CFX_ByteString & content,CFX_PtrArray & result)141 void CBC_QRCoderEncoder::SplitString(const CFX_ByteString& content,
142 CFX_PtrArray& result) {
143 int32_t index = 0, flag = 0;
144 while (
145 (((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) ||
146 ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) &&
147 (index < content.GetLength())) {
148 index += 2;
149 }
150 if (index != flag) {
151 result.Add(
152 new Make_Pair(CBC_QRCoderMode::sGBK, content.Mid(flag, index - flag)));
153 }
154 flag = index;
155 if (index >= content.GetLength()) {
156 return;
157 }
158 while (
159 GetAlphaNumericCode((uint8_t)content[index]) == -1 &&
160 !(((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) ||
161 ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) &&
162 (index < content.GetLength())) {
163 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
164 if (IsDBCSLeadByte((uint8_t)content[index]))
165 #else
166 if ((uint8_t)content[index] > 127)
167 #endif
168 {
169 index += 2;
170 } else {
171 index++;
172 }
173 }
174 if (index != flag) {
175 result.Add(
176 new Make_Pair(CBC_QRCoderMode::sBYTE, content.Mid(flag, index - flag)));
177 }
178 flag = index;
179 if (index >= content.GetLength()) {
180 return;
181 }
182 while (FXSYS_Isdigit((uint8_t)content[index]) &&
183 (index < content.GetLength())) {
184 index++;
185 }
186 if (index != flag) {
187 result.Add(new Make_Pair(CBC_QRCoderMode::sNUMERIC,
188 content.Mid(flag, index - flag)));
189 }
190 flag = index;
191 if (index >= content.GetLength()) {
192 return;
193 }
194 while (GetAlphaNumericCode((uint8_t)content[index]) != -1 &&
195 (index < content.GetLength())) {
196 index++;
197 }
198 if (index != flag) {
199 result.Add(new Make_Pair(CBC_QRCoderMode::sALPHANUMERIC,
200 content.Mid(flag, index - flag)));
201 }
202 flag = index;
203 if (index >= content.GetLength()) {
204 return;
205 }
206 SplitString(content.Mid(index, content.GetLength() - index), result);
207 }
GetSpanByVersion(CBC_QRCoderMode * modeFirst,CBC_QRCoderMode * modeSecond,int32_t versionNum,int32_t & e)208 int32_t CBC_QRCoderEncoder::GetSpanByVersion(CBC_QRCoderMode* modeFirst,
209 CBC_QRCoderMode* modeSecond,
210 int32_t versionNum,
211 int32_t& e) {
212 if (versionNum == 0) {
213 return 0;
214 }
215 if ((modeFirst == CBC_QRCoderMode::sALPHANUMERIC) &&
216 (modeSecond == CBC_QRCoderMode::sBYTE)) {
217 if (versionNum >= 1 && versionNum <= 9) {
218 return 11;
219 } else if (versionNum >= 10 && versionNum <= 26) {
220 return 15;
221 } else if (versionNum >= 27 && versionNum <= 40) {
222 return 16;
223 } else {
224 e = BCExceptionNoSuchVersion;
225 BC_EXCEPTION_CHECK_ReturnValue(e, 0);
226 }
227 } else if ((modeSecond == CBC_QRCoderMode::sALPHANUMERIC) &&
228 (modeFirst == CBC_QRCoderMode::sNUMERIC)) {
229 if (versionNum >= 1 && versionNum <= 9) {
230 return 13;
231 } else if (versionNum >= 10 && versionNum <= 26) {
232 return 15;
233 } else if (versionNum >= 27 && versionNum <= 40) {
234 return 17;
235 } else {
236 e = BCExceptionNoSuchVersion;
237 BC_EXCEPTION_CHECK_ReturnValue(e, 0);
238 }
239 } else if ((modeSecond == CBC_QRCoderMode::sBYTE) &&
240 (modeFirst == CBC_QRCoderMode::sNUMERIC)) {
241 if (versionNum >= 1 && versionNum <= 9) {
242 return 6;
243 } else if (versionNum >= 10 && versionNum <= 26) {
244 return 8;
245 } else if (versionNum >= 27 && versionNum <= 40) {
246 return 9;
247 } else {
248 e = BCExceptionNoSuchVersion;
249 BC_EXCEPTION_CHECK_ReturnValue(e, 0);
250 }
251 }
252 return -1;
253 }
MergeString(CFX_PtrArray & result,int32_t versionNum,int32_t & e)254 void CBC_QRCoderEncoder::MergeString(CFX_PtrArray& result,
255 int32_t versionNum,
256 int32_t& e) {
257 Make_Pair* first = NULL;
258 Make_Pair* second = NULL;
259 size_t mergeNum = 0;
260 int32_t i;
261 for (i = 0; ((i < result.GetSize()) && (i + 1 < result.GetSize())); i++) {
262 first = (Make_Pair*)result[i];
263 second = (Make_Pair*)result[i + 1];
264 if (first->m_mode == CBC_QRCoderMode::sALPHANUMERIC) {
265 int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sALPHANUMERIC,
266 CBC_QRCoderMode::sBYTE, versionNum, e);
267 BC_EXCEPTION_CHECK_ReturnVoid(e);
268 if ((second->m_mode == CBC_QRCoderMode::sBYTE) &&
269 (first->m_string.GetLength() < tmp)) {
270 CFX_ByteString str = first->m_string + second->m_string;
271 second->m_string = str;
272 delete first;
273 result.RemoveAt(i);
274 i--;
275 mergeNum++;
276 }
277 } else if (first->m_mode == CBC_QRCoderMode::sBYTE) {
278 if (second->m_mode == CBC_QRCoderMode::sBYTE) {
279 first->m_string += second->m_string;
280 delete second;
281 result.RemoveAt(i + 1);
282 i--;
283 mergeNum++;
284 }
285 } else if (first->m_mode == CBC_QRCoderMode::sNUMERIC) {
286 int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC,
287 CBC_QRCoderMode::sBYTE, versionNum, e);
288 BC_EXCEPTION_CHECK_ReturnVoid(e);
289 if ((second->m_mode == CBC_QRCoderMode::sBYTE) &&
290 (first->m_string.GetLength() < tmp)) {
291 CFX_ByteString str = first->m_string + second->m_string;
292 second->m_string = str;
293 delete first;
294 result.RemoveAt(i);
295 i--;
296 mergeNum++;
297 }
298 tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC,
299 CBC_QRCoderMode::sALPHANUMERIC, versionNum, e);
300 BC_EXCEPTION_CHECK_ReturnVoid(e);
301 if ((second->m_mode == CBC_QRCoderMode::sALPHANUMERIC) &&
302 (first->m_string.GetLength() < tmp)) {
303 CFX_ByteString str = first->m_string + second->m_string;
304 second->m_string = str;
305 delete first;
306 result.RemoveAt(i);
307 i--;
308 mergeNum++;
309 }
310 }
311 }
312 if (mergeNum == 0) {
313 return;
314 }
315 MergeString(result, versionNum, e);
316 BC_EXCEPTION_CHECK_ReturnVoid(e);
317 }
InitQRCode(int32_t numInputBytes,int32_t versionNumber,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoderMode * mode,CBC_QRCoder * qrCode,int32_t & e)318 void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes,
319 int32_t versionNumber,
320 CBC_QRCoderErrorCorrectionLevel* ecLevel,
321 CBC_QRCoderMode* mode,
322 CBC_QRCoder* qrCode,
323 int32_t& e) {
324 qrCode->SetECLevel(ecLevel);
325 qrCode->SetMode(mode);
326 CBC_QRCoderVersion* version =
327 CBC_QRCoderVersion::GetVersionForNumber(versionNumber, e);
328 BC_EXCEPTION_CHECK_ReturnVoid(e);
329 int32_t numBytes = version->GetTotalCodeWords();
330 CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel);
331 int32_t numEcBytes = ecBlocks->GetTotalECCodeWords();
332 int32_t numRSBlocks = ecBlocks->GetNumBlocks();
333 int32_t numDataBytes = numBytes - numEcBytes;
334 if (numDataBytes >= numInputBytes + 3) {
335 qrCode->SetVersion(versionNumber);
336 qrCode->SetNumTotalBytes(numBytes);
337 qrCode->SetNumDataBytes(numDataBytes);
338 qrCode->SetNumRSBlocks(numRSBlocks);
339 qrCode->SetNumECBytes(numEcBytes);
340 qrCode->SetMatrixWidth(version->GetDimensionForVersion());
341 return;
342 }
343 e = BCExceptionCannotFindBlockInfo;
344 BC_EXCEPTION_CHECK_ReturnVoid(e);
345 }
EncodeWithSpecifyVersion(const CFX_ByteString & content,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoder * qrCode,int32_t versionSpecify,int32_t & e)346 void CBC_QRCoderEncoder::EncodeWithSpecifyVersion(
347 const CFX_ByteString& content,
348 CBC_QRCoderErrorCorrectionLevel* ecLevel,
349 CBC_QRCoder* qrCode,
350 int32_t versionSpecify,
351 int32_t& e) {
352 CFX_ByteString encoding = "utf8";
353 CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE;
354 CFX_PtrArray splitResult;
355 CBC_QRCoderBitVector dataBits;
356 dataBits.Init();
357 SplitString(content, splitResult);
358 MergeString(splitResult, versionSpecify, e);
359 BC_EXCEPTION_CHECK_ReturnVoid(e) CBC_QRCoderMode* tempMode = NULL;
360 for (int32_t i = 0; i < splitResult.GetSize(); i++) {
361 AppendBytes(((Make_Pair*)splitResult[i])->m_string,
362 ((Make_Pair*)splitResult[i])->m_mode, &dataBits, encoding, e);
363 if (e != BCExceptionNO) {
364 for (int32_t y = 0; y < splitResult.GetSize(); y++) {
365 delete (Make_Pair*)splitResult[y];
366 }
367 splitResult.RemoveAll();
368 return;
369 }
370 }
371 int32_t numInputBytes = dataBits.sizeInBytes();
372 CBC_QRCoderBitVector headerAndDataBits;
373 headerAndDataBits.Init();
374 InitQRCode(numInputBytes, versionSpecify, ecLevel, mode, qrCode, e);
375 if (e != BCExceptionNO) {
376 for (int32_t k = 0; k < splitResult.GetSize(); k++) {
377 delete (Make_Pair*)splitResult[k];
378 }
379 splitResult.RemoveAll();
380 return;
381 }
382 AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode,
383 encoding, e);
384 if (e != BCExceptionNO) {
385 for (int32_t k = 0; k < splitResult.GetSize(); k++) {
386 delete (Make_Pair*)splitResult[k];
387 }
388 splitResult.RemoveAll();
389 return;
390 }
391 numInputBytes = headerAndDataBits.sizeInBytes();
392 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e);
393 if (e != BCExceptionNO) {
394 for (int32_t k = 0; k < splitResult.GetSize(); k++) {
395 delete (Make_Pair*)splitResult[k];
396 }
397 splitResult.RemoveAll();
398 return;
399 }
400 for (int32_t j = 0; j < splitResult.GetSize(); j++) {
401 delete (Make_Pair*)splitResult[j];
402 }
403 splitResult.RemoveAll();
404 CBC_QRCoderBitVector finalBits;
405 finalBits.Init();
406 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(),
407 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(),
408 &finalBits, e);
409 BC_EXCEPTION_CHECK_ReturnVoid(e);
410 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix(
411 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth());
412 pDecoder->Init();
413 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder);
414 int32_t maskPattern = ChooseMaskPattern(
415 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e);
416 BC_EXCEPTION_CHECK_ReturnVoid(e);
417 qrCode->SetMaskPattern(maskPattern);
418 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(),
419 qrCode->GetVersion(),
420 qrCode->GetMaskPattern(), matrix.get(), e);
421 BC_EXCEPTION_CHECK_ReturnVoid(e);
422 qrCode->SetMatrix(matrix.release());
423 if (!qrCode->IsValid()) {
424 e = BCExceptionInvalidQRCode;
425 BC_EXCEPTION_CHECK_ReturnVoid(e);
426 }
427 }
EncodeWithAutoVersion(const CFX_ByteString & content,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoder * qrCode,int32_t & e)428 void CBC_QRCoderEncoder::EncodeWithAutoVersion(
429 const CFX_ByteString& content,
430 CBC_QRCoderErrorCorrectionLevel* ecLevel,
431 CBC_QRCoder* qrCode,
432 int32_t& e) {
433 CFX_ByteString encoding = "utf8";
434 CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE;
435 CFX_PtrArray splitResult;
436 CBC_QRCoderBitVector dataBits;
437 dataBits.Init();
438 SplitString(content, splitResult);
439 MergeString(splitResult, 8, e);
440 BC_EXCEPTION_CHECK_ReturnVoid(e);
441 CBC_QRCoderMode* tempMode = NULL;
442 for (int32_t i = 0; i < splitResult.GetSize(); i++) {
443 AppendBytes(((Make_Pair*)splitResult[i])->m_string,
444 ((Make_Pair*)splitResult[i])->m_mode, &dataBits, encoding, e);
445 if (e != BCExceptionNO) {
446 for (int32_t l = 0; l < splitResult.GetSize(); l++) {
447 delete (Make_Pair*)splitResult[l];
448 }
449 splitResult.RemoveAll();
450 return;
451 }
452 }
453 int32_t numInputBytes = dataBits.sizeInBytes();
454 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e);
455 BC_EXCEPTION_CHECK_ReturnVoid(e) CBC_QRCoderBitVector headerAndDataBits;
456 headerAndDataBits.Init();
457 tempMode = NULL;
458 int32_t versionNum = qrCode->GetVersion();
459 sign:
460 AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode,
461 encoding, e);
462 if (e != BCExceptionNO) {
463 goto catchException;
464 }
465 numInputBytes = headerAndDataBits.sizeInBytes();
466 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e);
467 if (e != BCExceptionNO) {
468 goto catchException;
469 }
470 catchException:
471 if (e != BCExceptionNO) {
472 int32_t e1 = BCExceptionNO;
473 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e1);
474 if (e1 != BCExceptionNO) {
475 e = e1;
476 return;
477 }
478 versionNum++;
479 if (versionNum <= 40) {
480 headerAndDataBits.Clear();
481 e = BCExceptionNO;
482 goto sign;
483 } else {
484 for (int32_t j = 0; j < splitResult.GetSize(); j++) {
485 delete (Make_Pair*)splitResult[j];
486 }
487 splitResult.RemoveAll();
488 return;
489 }
490 }
491 for (int32_t k = 0; k < splitResult.GetSize(); k++) {
492 delete (Make_Pair*)splitResult[k];
493 }
494 splitResult.RemoveAll();
495 CBC_QRCoderBitVector finalBits;
496 finalBits.Init();
497 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(),
498 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(),
499 &finalBits, e);
500 BC_EXCEPTION_CHECK_ReturnVoid(e);
501 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix(
502 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth());
503 pDecoder->Init();
504 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder);
505 int32_t maskPattern = ChooseMaskPattern(
506 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e);
507 BC_EXCEPTION_CHECK_ReturnVoid(e);
508 qrCode->SetMaskPattern(maskPattern);
509 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(),
510 qrCode->GetVersion(),
511 qrCode->GetMaskPattern(), matrix.get(), e);
512 BC_EXCEPTION_CHECK_ReturnVoid(e) qrCode->SetMatrix(matrix.release());
513 if (!qrCode->IsValid()) {
514 e = BCExceptionInvalidQRCode;
515 BC_EXCEPTION_CHECK_ReturnVoid(e);
516 }
517 }
Encode(const CFX_WideString & content,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoder * qrCode,int32_t & e)518 void CBC_QRCoderEncoder::Encode(const CFX_WideString& content,
519 CBC_QRCoderErrorCorrectionLevel* ecLevel,
520 CBC_QRCoder* qrCode,
521 int32_t& e) {
522 CFX_ByteString encoding = "utf8";
523 CFX_ByteString utf8Data;
524 CBC_UtilCodingConvert::UnicodeToUTF8(content, utf8Data);
525 CBC_QRCoderMode* mode = ChooseMode(utf8Data, encoding);
526 CBC_QRCoderBitVector dataBits;
527 dataBits.Init();
528 AppendBytes(utf8Data, mode, &dataBits, encoding, e);
529 BC_EXCEPTION_CHECK_ReturnVoid(e);
530 int32_t numInputBytes = dataBits.sizeInBytes();
531 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e);
532 BC_EXCEPTION_CHECK_ReturnVoid(e);
533 CBC_QRCoderBitVector headerAndDataBits;
534 headerAndDataBits.Init();
535 AppendModeInfo(mode, &headerAndDataBits, e);
536 BC_EXCEPTION_CHECK_ReturnVoid(e);
537 int32_t numLetters = mode == CBC_QRCoderMode::sBYTE ? dataBits.sizeInBytes()
538 : content.GetLength();
539 AppendLengthInfo(numLetters, qrCode->GetVersion(), mode, &headerAndDataBits,
540 e);
541 BC_EXCEPTION_CHECK_ReturnVoid(e);
542 headerAndDataBits.AppendBitVector(&dataBits, e);
543 BC_EXCEPTION_CHECK_ReturnVoid(e)
544 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e);
545 BC_EXCEPTION_CHECK_ReturnVoid(e);
546 CBC_QRCoderBitVector finalBits;
547 finalBits.Init();
548 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(),
549 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(),
550 &finalBits, e);
551 BC_EXCEPTION_CHECK_ReturnVoid(e);
552 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix(
553 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth());
554 pDecoder->Init();
555 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder);
556 int32_t maskPattern = ChooseMaskPattern(
557 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e);
558 BC_EXCEPTION_CHECK_ReturnVoid(e);
559 qrCode->SetMaskPattern(maskPattern);
560 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(),
561 qrCode->GetVersion(),
562 qrCode->GetMaskPattern(), matrix.get(), e);
563 BC_EXCEPTION_CHECK_ReturnVoid(e) qrCode->SetMatrix(matrix.release());
564 if (!qrCode->IsValid()) {
565 e = BCExceptionInvalidQRCode;
566 BC_EXCEPTION_CHECK_ReturnVoid(e);
567 }
568 }
TerminateBits(int32_t numDataBytes,CBC_QRCoderBitVector * bits,int32_t & e)569 void CBC_QRCoderEncoder::TerminateBits(int32_t numDataBytes,
570 CBC_QRCoderBitVector* bits,
571 int32_t& e) {
572 int32_t capacity = numDataBytes << 3;
573 if (bits->Size() > capacity) {
574 e = BCExceptionDataTooMany;
575 BC_EXCEPTION_CHECK_ReturnVoid(e);
576 }
577 for (int32_t i = 0; i < 4 && bits->Size() < capacity; ++i) {
578 bits->AppendBit(0, e);
579 BC_EXCEPTION_CHECK_ReturnVoid(e);
580 }
581 int32_t numBitsInLastByte = bits->Size() % 8;
582 if (numBitsInLastByte > 0) {
583 int32_t numPaddingBits = 8 - numBitsInLastByte;
584 for (int32_t j = 0; j < numPaddingBits; ++j) {
585 bits->AppendBit(0, e);
586 BC_EXCEPTION_CHECK_ReturnVoid(e)
587 }
588 }
589 if (bits->Size() % 8 != 0) {
590 e = BCExceptionDigitLengthMustBe8;
591 BC_EXCEPTION_CHECK_ReturnVoid(e);
592 }
593 int32_t numPaddingBytes = numDataBytes - bits->sizeInBytes();
594 for (int32_t k = 0; k < numPaddingBytes; ++k) {
595 if (k % 2 == 0) {
596 bits->AppendBits(0xec, 8, e);
597 BC_EXCEPTION_CHECK_ReturnVoid(e);
598 } else {
599 bits->AppendBits(0x11, 8, e);
600 BC_EXCEPTION_CHECK_ReturnVoid(e);
601 }
602 }
603 if (bits->Size() != capacity) {
604 e = BCExceptionBitsNotEqualCacity;
605 BC_EXCEPTION_CHECK_ReturnVoid(e);
606 }
607 }
ChooseMaskPattern(CBC_QRCoderBitVector * bits,CBC_QRCoderErrorCorrectionLevel * ecLevel,int32_t version,CBC_CommonByteMatrix * matrix,int32_t & e)608 int32_t CBC_QRCoderEncoder::ChooseMaskPattern(
609 CBC_QRCoderBitVector* bits,
610 CBC_QRCoderErrorCorrectionLevel* ecLevel,
611 int32_t version,
612 CBC_CommonByteMatrix* matrix,
613 int32_t& e) {
614 int32_t minPenalty = 65535;
615 int32_t bestMaskPattern = -1;
616 for (int32_t maskPattern = 0; maskPattern < CBC_QRCoder::NUM_MASK_PATTERNS;
617 maskPattern++) {
618 CBC_QRCoderMatrixUtil::BuildMatrix(bits, ecLevel, version, maskPattern,
619 matrix, e);
620 BC_EXCEPTION_CHECK_ReturnValue(e, 0);
621 int32_t penalty = CalculateMaskPenalty(matrix);
622 if (penalty < minPenalty) {
623 minPenalty = penalty;
624 bestMaskPattern = maskPattern;
625 }
626 }
627 return bestMaskPattern;
628 }
CalculateMaskPenalty(CBC_CommonByteMatrix * matrix)629 int32_t CBC_QRCoderEncoder::CalculateMaskPenalty(CBC_CommonByteMatrix* matrix) {
630 int32_t penalty = 0;
631 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(matrix);
632 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(matrix);
633 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(matrix);
634 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(matrix);
635 return penalty;
636 }
ChooseMode(const CFX_ByteString & content,CFX_ByteString encoding)637 CBC_QRCoderMode* CBC_QRCoderEncoder::ChooseMode(const CFX_ByteString& content,
638 CFX_ByteString encoding) {
639 if (encoding.Compare("SHIFT_JIS") == 0) {
640 return CBC_QRCoderMode::sKANJI;
641 }
642 FX_BOOL hasNumeric = FALSE;
643 FX_BOOL hasAlphaNumeric = FALSE;
644 for (int32_t i = 0; i < content.GetLength(); i++) {
645 if (isdigit((uint8_t)content[i])) {
646 hasNumeric = TRUE;
647 } else if (GetAlphaNumericCode((uint8_t)content[i]) != -1) {
648 hasAlphaNumeric = TRUE;
649 } else {
650 return CBC_QRCoderMode::sBYTE;
651 }
652 }
653 if (hasAlphaNumeric) {
654 return CBC_QRCoderMode::sALPHANUMERIC;
655 } else if (hasNumeric) {
656 return CBC_QRCoderMode::sNUMERIC;
657 }
658 return CBC_QRCoderMode::sBYTE;
659 }
GetAlphaNumericCode(int32_t code)660 int32_t CBC_QRCoderEncoder::GetAlphaNumericCode(int32_t code) {
661 if (code < 96 && code >= 0) {
662 return m_alphaNumbericTable[code];
663 }
664 return -1;
665 }
AppendBytes(const CFX_ByteString & content,CBC_QRCoderMode * mode,CBC_QRCoderBitVector * bits,CFX_ByteString encoding,int32_t & e)666 void CBC_QRCoderEncoder::AppendBytes(const CFX_ByteString& content,
667 CBC_QRCoderMode* mode,
668 CBC_QRCoderBitVector* bits,
669 CFX_ByteString encoding,
670 int32_t& e) {
671 if (mode == CBC_QRCoderMode::sNUMERIC) {
672 AppendNumericBytes(content, bits, e);
673 BC_EXCEPTION_CHECK_ReturnVoid(e);
674 } else if (mode == CBC_QRCoderMode::sALPHANUMERIC) {
675 AppendAlphaNumericBytes(content, bits, e);
676 BC_EXCEPTION_CHECK_ReturnVoid(e);
677 } else if (mode == CBC_QRCoderMode::sBYTE) {
678 Append8BitBytes(content, bits, encoding, e);
679 BC_EXCEPTION_CHECK_ReturnVoid(e);
680 } else if (mode == CBC_QRCoderMode::sKANJI) {
681 AppendKanjiBytes(content, bits, e);
682 BC_EXCEPTION_CHECK_ReturnVoid(e);
683 } else if (mode == CBC_QRCoderMode::sGBK) {
684 AppendGBKBytes(content, bits, e);
685 BC_EXCEPTION_CHECK_ReturnVoid(e);
686 } else {
687 e = BCExceptionUnsupportedMode;
688 BC_EXCEPTION_CHECK_ReturnVoid(e);
689 }
690 }
AppendNumericBytes(const CFX_ByteString & content,CBC_QRCoderBitVector * bits,int32_t & e)691 void CBC_QRCoderEncoder::AppendNumericBytes(const CFX_ByteString& content,
692 CBC_QRCoderBitVector* bits,
693 int32_t& e) {
694 int32_t length = content.GetLength();
695 int32_t i = 0;
696 while (i < length) {
697 int32_t num1 = content[i] - '0';
698 if (i + 2 < length) {
699 int32_t num2 = content[i + 1] - '0';
700 int32_t num3 = content[i + 2] - '0';
701 bits->AppendBits(num1 * 100 + num2 * 10 + num3, 10, e);
702 BC_EXCEPTION_CHECK_ReturnVoid(e) i += 3;
703 } else if (i + 1 < length) {
704 int32_t num2 = content[i + 1] - '0';
705 bits->AppendBits(num1 * 10 + num2, 7, e);
706 BC_EXCEPTION_CHECK_ReturnVoid(e) i += 2;
707 } else {
708 bits->AppendBits(num1, 4, e);
709 BC_EXCEPTION_CHECK_ReturnVoid(e);
710 i++;
711 }
712 }
713 }
AppendAlphaNumericBytes(const CFX_ByteString & content,CBC_QRCoderBitVector * bits,int32_t & e)714 void CBC_QRCoderEncoder::AppendAlphaNumericBytes(const CFX_ByteString& content,
715 CBC_QRCoderBitVector* bits,
716 int32_t& e) {
717 int32_t length = content.GetLength();
718 int32_t i = 0;
719 while (i < length) {
720 int32_t code1 = GetAlphaNumericCode(content[i]);
721 if (code1 == -1) {
722 e = BCExceptionInvalidateCharacter;
723 BC_EXCEPTION_CHECK_ReturnVoid(e);
724 }
725 if (i + 1 < length) {
726 int32_t code2 = GetAlphaNumericCode(content[i + 1]);
727 if (code2 == -1) {
728 e = BCExceptionInvalidateCharacter;
729 BC_EXCEPTION_CHECK_ReturnVoid(e);
730 }
731 bits->AppendBits(code1 * 45 + code2, 11, e);
732 BC_EXCEPTION_CHECK_ReturnVoid(e);
733 i += 2;
734 } else {
735 bits->AppendBits(code1, 6, e);
736 BC_EXCEPTION_CHECK_ReturnVoid(e) i++;
737 }
738 }
739 }
AppendGBKBytes(const CFX_ByteString & content,CBC_QRCoderBitVector * bits,int32_t & e)740 void CBC_QRCoderEncoder::AppendGBKBytes(const CFX_ByteString& content,
741 CBC_QRCoderBitVector* bits,
742 int32_t& e) {
743 int32_t length = content.GetLength();
744 FX_DWORD value = 0;
745 for (int32_t i = 0; i < length; i += 2) {
746 value = (FX_DWORD)((uint8_t)content[i] << 8 | (uint8_t)content[i + 1]);
747 if (value <= 0xAAFE && value >= 0xA1A1) {
748 value -= 0xA1A1;
749 } else if (value <= 0xFAFE && value >= 0xB0A1) {
750 value -= 0xA6A1;
751 } else {
752 e = BCExceptionInvalidateCharacter;
753 BC_EXCEPTION_CHECK_ReturnVoid(e);
754 }
755 value = (FX_DWORD)((value >> 8) * 0x60) + (FX_DWORD)(value & 0xff);
756 bits->AppendBits(value, 13, e);
757 BC_EXCEPTION_CHECK_ReturnVoid(e);
758 }
759 }
Append8BitBytes(const CFX_ByteString & content,CBC_QRCoderBitVector * bits,CFX_ByteString encoding,int32_t & e)760 void CBC_QRCoderEncoder::Append8BitBytes(const CFX_ByteString& content,
761 CBC_QRCoderBitVector* bits,
762 CFX_ByteString encoding,
763 int32_t& e) {
764 for (int32_t i = 0; i < content.GetLength(); i++) {
765 bits->AppendBits(content[i], 8, e);
766 BC_EXCEPTION_CHECK_ReturnVoid(e);
767 }
768 }
Append8BitBytes(CFX_ByteArray & bytes,CBC_QRCoderBitVector * bits,int32_t & e)769 void CBC_QRCoderEncoder::Append8BitBytes(CFX_ByteArray& bytes,
770 CBC_QRCoderBitVector* bits,
771 int32_t& e) {
772 for (int32_t i = 0; i < bytes.GetSize(); i++) {
773 bits->AppendBits(bytes[i], 8, e);
774 BC_EXCEPTION_CHECK_ReturnVoid(e);
775 }
776 }
AppendKanjiBytes(const CFX_ByteString & content,CBC_QRCoderBitVector * bits,int32_t & e)777 void CBC_QRCoderEncoder::AppendKanjiBytes(const CFX_ByteString& content,
778 CBC_QRCoderBitVector* bits,
779 int32_t& e) {
780 CFX_ByteArray bytes;
781 FX_DWORD value = 0;
782 for (int32_t i = 0; i < bytes.GetSize(); i += 2) {
783 value = (FX_DWORD)((uint8_t)(content[i] << 8) | (uint8_t)content[i + 1]);
784 if (value <= 0x9ffc && value >= 0x8140) {
785 value -= 0x8140;
786 } else if (value <= 0xebbf && value >= 0xe040) {
787 value -= 0xc140;
788 } else {
789 e = BCExceptionInvalidateCharacter;
790 BC_EXCEPTION_CHECK_ReturnVoid(e);
791 }
792 value = (FX_DWORD)((value >> 8) * 0xc0) + (FX_DWORD)(value & 0xff);
793 bits->AppendBits(value, 13, e);
794 BC_EXCEPTION_CHECK_ReturnVoid(e);
795 }
796 }
InitQRCode(int32_t numInputBytes,CBC_QRCoderErrorCorrectionLevel * ecLevel,CBC_QRCoderMode * mode,CBC_QRCoder * qrCode,int32_t & e)797 void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes,
798 CBC_QRCoderErrorCorrectionLevel* ecLevel,
799 CBC_QRCoderMode* mode,
800 CBC_QRCoder* qrCode,
801 int32_t& e) {
802 qrCode->SetECLevel(ecLevel);
803 qrCode->SetMode(mode);
804 for (int32_t versionNum = 1; versionNum <= 40; versionNum++) {
805 CBC_QRCoderVersion* version =
806 CBC_QRCoderVersion::GetVersionForNumber(versionNum, e);
807 BC_EXCEPTION_CHECK_ReturnVoid(e);
808 int32_t numBytes = version->GetTotalCodeWords();
809 CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel);
810 int32_t numEcBytes = ecBlocks->GetTotalECCodeWords();
811 int32_t numRSBlocks = ecBlocks->GetNumBlocks();
812 int32_t numDataBytes = numBytes - numEcBytes;
813 if (numDataBytes >= numInputBytes + 3) {
814 qrCode->SetVersion(versionNum);
815 qrCode->SetNumTotalBytes(numBytes);
816 qrCode->SetNumDataBytes(numDataBytes);
817 qrCode->SetNumRSBlocks(numRSBlocks);
818 qrCode->SetNumECBytes(numEcBytes);
819 qrCode->SetMatrixWidth(version->GetDimensionForVersion());
820 return;
821 }
822 }
823 e = BCExceptionCannotFindBlockInfo;
824 BC_EXCEPTION_CHECK_ReturnVoid(e);
825 }
AppendModeInfo(CBC_QRCoderMode * mode,CBC_QRCoderBitVector * bits,int32_t & e)826 void CBC_QRCoderEncoder::AppendModeInfo(CBC_QRCoderMode* mode,
827 CBC_QRCoderBitVector* bits,
828 int32_t& e) {
829 bits->AppendBits(mode->GetBits(), 4, e);
830 if (mode == CBC_QRCoderMode::sGBK) {
831 bits->AppendBits(1, 4, e);
832 BC_EXCEPTION_CHECK_ReturnVoid(e);
833 }
834 }
AppendLengthInfo(int32_t numLetters,int32_t version,CBC_QRCoderMode * mode,CBC_QRCoderBitVector * bits,int32_t & e)835 void CBC_QRCoderEncoder::AppendLengthInfo(int32_t numLetters,
836 int32_t version,
837 CBC_QRCoderMode* mode,
838 CBC_QRCoderBitVector* bits,
839 int32_t& e) {
840 CBC_QRCoderVersion* qcv = CBC_QRCoderVersion::GetVersionForNumber(version, e);
841 BC_EXCEPTION_CHECK_ReturnVoid(e);
842 int32_t numBits = mode->GetCharacterCountBits(qcv, e);
843 BC_EXCEPTION_CHECK_ReturnVoid(e);
844 if (numBits > ((1 << numBits) - 1)) {
845 return;
846 }
847 if (mode == CBC_QRCoderMode::sGBK) {
848 bits->AppendBits(numLetters / 2, numBits, e);
849 BC_EXCEPTION_CHECK_ReturnVoid(e);
850 }
851 bits->AppendBits(numLetters, numBits, e);
852 BC_EXCEPTION_CHECK_ReturnVoid(e);
853 }
InterleaveWithECBytes(CBC_QRCoderBitVector * bits,int32_t numTotalBytes,int32_t numDataBytes,int32_t numRSBlocks,CBC_QRCoderBitVector * result,int32_t & e)854 void CBC_QRCoderEncoder::InterleaveWithECBytes(CBC_QRCoderBitVector* bits,
855 int32_t numTotalBytes,
856 int32_t numDataBytes,
857 int32_t numRSBlocks,
858 CBC_QRCoderBitVector* result,
859 int32_t& e) {
860 if (bits->sizeInBytes() != numDataBytes) {
861 e = BCExceptionBitsBytesNotMatch;
862 BC_EXCEPTION_CHECK_ReturnVoid(e);
863 }
864 int32_t dataBytesOffset = 0;
865 int32_t maxNumDataBytes = 0;
866 int32_t maxNumEcBytes = 0;
867 CFX_PtrArray blocks;
868 int32_t i;
869 for (i = 0; i < numRSBlocks; i++) {
870 int32_t numDataBytesInBlock;
871 int32_t numEcBytesInBlosk;
872 GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes,
873 numRSBlocks, i, numDataBytesInBlock,
874 numEcBytesInBlosk);
875 CBC_CommonByteArray* dataBytes = new CBC_CommonByteArray;
876 dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock);
877 CBC_CommonByteArray* ecBytes =
878 GenerateECBytes(dataBytes, numEcBytesInBlosk, e);
879 BC_EXCEPTION_CHECK_ReturnVoid(e);
880 blocks.Add(new CBC_QRCoderBlockPair(dataBytes, ecBytes));
881 maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size());
882 maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size());
883 dataBytesOffset += numDataBytesInBlock;
884 }
885 if (numDataBytes != dataBytesOffset) {
886 e = BCExceptionBytesNotMatchOffset;
887 BC_EXCEPTION_CHECK_ReturnVoid(e);
888 }
889 for (int32_t x = 0; x < maxNumDataBytes; x++) {
890 for (int32_t j = 0; j < blocks.GetSize(); j++) {
891 CBC_CommonByteArray* dataBytes =
892 ((CBC_QRCoderBlockPair*)blocks[j])->GetDataBytes();
893 if (x < dataBytes->Size()) {
894 result->AppendBits(dataBytes->At(x), 8, e);
895 BC_EXCEPTION_CHECK_ReturnVoid(e);
896 }
897 }
898 }
899 for (int32_t y = 0; y < maxNumEcBytes; y++) {
900 for (int32_t l = 0; l < blocks.GetSize(); l++) {
901 CBC_CommonByteArray* ecBytes =
902 ((CBC_QRCoderBlockPair*)blocks[l])->GetErrorCorrectionBytes();
903 if (y < ecBytes->Size()) {
904 result->AppendBits(ecBytes->At(y), 8, e);
905 BC_EXCEPTION_CHECK_ReturnVoid(e);
906 }
907 }
908 }
909 for (int32_t k = 0; k < blocks.GetSize(); k++) {
910 delete (CBC_QRCoderBlockPair*)blocks[k];
911 }
912 if (numTotalBytes != result->sizeInBytes()) {
913 e = BCExceptionSizeInBytesDiffer;
914 BC_EXCEPTION_CHECK_ReturnVoid(e);
915 }
916 }
GetNumDataBytesAndNumECBytesForBlockID(int32_t numTotalBytes,int32_t numDataBytes,int32_t numRSBlocks,int32_t blockID,int32_t & numDataBytesInBlock,int32_t & numECBytesInBlock)917 void CBC_QRCoderEncoder::GetNumDataBytesAndNumECBytesForBlockID(
918 int32_t numTotalBytes,
919 int32_t numDataBytes,
920 int32_t numRSBlocks,
921 int32_t blockID,
922 int32_t& numDataBytesInBlock,
923 int32_t& numECBytesInBlock) {
924 if (blockID >= numRSBlocks) {
925 return;
926 }
927 int32_t numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;
928 int32_t numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;
929 int32_t numTotalBytesInGroup1 = numTotalBytes / numRSBlocks;
930 int32_t numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;
931 int32_t numDataBytesInGroup1 = numDataBytes / numRSBlocks;
932 int32_t numDataBytesInGroup2 = numDataBytesInGroup1 + 1;
933 int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;
934 int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;
935 if (blockID < numRsBlocksInGroup1) {
936 numDataBytesInBlock = numDataBytesInGroup1;
937 numECBytesInBlock = numEcBytesInGroup1;
938 } else {
939 numDataBytesInBlock = numDataBytesInGroup2;
940 numECBytesInBlock = numEcBytesInGroup2;
941 }
942 }
GenerateECBytes(CBC_CommonByteArray * dataBytes,int32_t numEcBytesInBlock,int32_t & e)943 CBC_CommonByteArray* CBC_QRCoderEncoder::GenerateECBytes(
944 CBC_CommonByteArray* dataBytes,
945 int32_t numEcBytesInBlock,
946 int32_t& e) {
947 int32_t numDataBytes = dataBytes->Size();
948 CFX_Int32Array toEncode;
949 toEncode.SetSize(numDataBytes + numEcBytesInBlock);
950 for (int32_t i = 0; i < numDataBytes; i++) {
951 toEncode[i] = (dataBytes->At(i));
952 }
953 CBC_ReedSolomonEncoder encode(CBC_ReedSolomonGF256::QRCodeFild);
954 encode.Init();
955 encode.Encode(&toEncode, numEcBytesInBlock, e);
956 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
957 CBC_CommonByteArray* ecBytes = new CBC_CommonByteArray(numEcBytesInBlock);
958 for (int32_t j = 0; j < numEcBytesInBlock; j++) {
959 ecBytes->Set(j, toEncode[numDataBytes + j]);
960 }
961 return ecBytes;
962 }
963