Home | History | Annotate | Download | only in qrcode
      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};
     48 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:
     56   Make_Pair(const 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:
     67   Make_Pair(CBC_QRCoderMode* mode, const CFX_ByteString& str)
     68       : m_mode(mode), m_string(str) {}
     69   ~Make_Pair() {}
     70 };
     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 }
     87 void CBC_QRCoderEncoder::AppendECI(CBC_QRCoderBitVector* bits) {}
     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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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