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