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