diff options
Diffstat (limited to 'fxbarcode/qrcode')
24 files changed, 3896 insertions, 0 deletions
diff --git a/fxbarcode/qrcode/BC_QRCodeWriter.cpp b/fxbarcode/qrcode/BC_QRCodeWriter.cpp new file mode 100644 index 0000000000..ac23462ed8 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCodeWriter.cpp @@ -0,0 +1,122 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/BC_TwoDimWriter.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/qrcode/BC_QRCodeWriter.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderEncoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" + +CBC_QRCodeWriter::CBC_QRCodeWriter() { + m_bFixedSize = true; + m_iCorrectLevel = 1; + m_iVersion = 0; +} + +CBC_QRCodeWriter::~CBC_QRCodeWriter() {} + +void CBC_QRCodeWriter::ReleaseAll() { + delete CBC_ReedSolomonGF256::QRCodeField; + CBC_ReedSolomonGF256::QRCodeField = nullptr; + delete CBC_ReedSolomonGF256::DataMatrixField; + CBC_ReedSolomonGF256::DataMatrixField = nullptr; + CBC_QRCoderMode::Destroy(); + CBC_QRCoderErrorCorrectionLevel::Destroy(); + CBC_QRCoderVersion::Destroy(); +} + +bool CBC_QRCodeWriter::SetVersion(int32_t version) { + if (version < 0 || version > 40) { + return false; + } + m_iVersion = version; + return true; +} + +bool CBC_QRCodeWriter::SetErrorCorrectionLevel(int32_t level) { + if (level < 0 || level > 3) { + return false; + } + m_iCorrectLevel = level; + return true; +} + +uint8_t* CBC_QRCodeWriter::Encode(const CFX_WideString& contents, + int32_t ecLevel, + int32_t& outWidth, + int32_t& outHeight, + int32_t& e) { + CBC_QRCoderErrorCorrectionLevel* ec = nullptr; + switch (ecLevel) { + case 0: + ec = CBC_QRCoderErrorCorrectionLevel::L; + break; + case 1: + ec = CBC_QRCoderErrorCorrectionLevel::M; + break; + case 2: + ec = CBC_QRCoderErrorCorrectionLevel::Q; + break; + case 3: + ec = CBC_QRCoderErrorCorrectionLevel::H; + break; + default: { + e = BCExceptionUnSupportEclevel; + return nullptr; + } + } + CBC_QRCoder qr; + if (m_iVersion > 0 && m_iVersion < 41) { + CFX_ByteString byteStr = contents.UTF8Encode(); + CBC_QRCoderEncoder::Encode(byteStr, ec, &qr, e, m_iVersion); + } else { + CBC_QRCoderEncoder::Encode(contents, ec, &qr, e); + } + if (e != BCExceptionNO) + return nullptr; + outWidth = qr.GetMatrixWidth(); + outHeight = qr.GetMatrixWidth(); + uint8_t* result = FX_Alloc2D(uint8_t, outWidth, outHeight); + FXSYS_memcpy(result, qr.GetMatrix()->GetArray(), outWidth * outHeight); + return result; +} + +uint8_t* CBC_QRCodeWriter::Encode(const CFX_ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints, + int32_t& e) { + return nullptr; +} + +uint8_t* CBC_QRCodeWriter::Encode(const CFX_ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t& e) { + return nullptr; +} diff --git a/fxbarcode/qrcode/BC_QRCodeWriter.h b/fxbarcode/qrcode/BC_QRCodeWriter.h new file mode 100644 index 0000000000..185e10aa37 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCodeWriter.h @@ -0,0 +1,45 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ +#define FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ + +#include "fxbarcode/BC_TwoDimWriter.h" + +class CBC_TwoDimWriter; +class CBC_QRCodeWriter : public CBC_TwoDimWriter { + public: + CBC_QRCodeWriter(); + ~CBC_QRCodeWriter() override; + + uint8_t* Encode(const CFX_WideString& contents, + int32_t ecLevel, + int32_t& outWidth, + int32_t& outHeight, + int32_t& e); + uint8_t* Encode(const CFX_ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints, + int32_t& e); + uint8_t* Encode(const CFX_ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t& e); + bool SetVersion(int32_t version); + + // CBC_TwoDimWriter + bool SetErrorCorrectionLevel(int32_t level) override; + + static void ReleaseAll(); + + private: + int32_t m_iVersion; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ diff --git a/fxbarcode/qrcode/BC_QRCoder.cpp b/fxbarcode/qrcode/BC_QRCoder.cpp new file mode 100644 index 0000000000..93f0d00455 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoder.cpp @@ -0,0 +1,145 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <utility> + +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/utils.h" + +CBC_QRCoder::CBC_QRCoder() + : m_mode(nullptr), + m_ecLevel(nullptr), + m_version(-1), + m_matrixWidth(-1), + m_maskPattern(-1), + m_numTotalBytes(-1), + m_numDataBytes(-1), + m_numECBytes(-1), + m_numRSBlocks(-1) {} + +CBC_QRCoder::~CBC_QRCoder() {} + +CBC_QRCoderMode* CBC_QRCoder::GetMode() const { + return m_mode; +} + +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoder::GetECLevel() const { + return m_ecLevel; +} + +int32_t CBC_QRCoder::GetVersion() const { + return m_version; +} + +int32_t CBC_QRCoder::GetMatrixWidth() const { + return m_matrixWidth; +} + +int32_t CBC_QRCoder::GetMaskPattern() const { + return m_maskPattern; +} + +int32_t CBC_QRCoder::GetNumTotalBytes() const { + return m_numTotalBytes; +} + +int32_t CBC_QRCoder::GetNumDataBytes() const { + return m_numDataBytes; +} + +int32_t CBC_QRCoder::GetNumECBytes() const { + return m_numECBytes; +} + +int32_t CBC_QRCoder::GetNumRSBlocks() const { + return m_numRSBlocks; +} + +CBC_CommonByteMatrix* CBC_QRCoder::GetMatrix() const { + return m_matrix.get(); +} + +int32_t CBC_QRCoder::At(int32_t x, int32_t y, int32_t& e) { + int32_t value = m_matrix->Get(x, y); + if (!(value == 0 || value == 1)) { + e = BCExceptionValueMustBeEither0or1; + return 0; + } + return value; +} + +bool CBC_QRCoder::IsValid() { + return m_mode && m_ecLevel && m_version != -1 && m_matrixWidth != -1 && + m_maskPattern != -1 && m_numTotalBytes != -1 && m_numDataBytes != -1 && + m_numECBytes != -1 && m_numRSBlocks != -1 && + IsValidMaskPattern(m_maskPattern) && + m_numTotalBytes == m_numDataBytes + m_numECBytes && m_matrix && + m_matrixWidth == m_matrix->GetWidth() && + m_matrix->GetWidth() == m_matrix->GetHeight(); +} + +void CBC_QRCoder::SetMode(CBC_QRCoderMode* value) { + m_mode = value; +} + +void CBC_QRCoder::SetECLevel(CBC_QRCoderErrorCorrectionLevel* ecLevel) { + m_ecLevel = ecLevel; +} + +void CBC_QRCoder::SetVersion(int32_t version) { + m_version = version; +} + +void CBC_QRCoder::SetMatrixWidth(int32_t width) { + m_matrixWidth = width; +} + +void CBC_QRCoder::SetMaskPattern(int32_t pattern) { + m_maskPattern = pattern; +} + +void CBC_QRCoder::SetNumDataBytes(int32_t bytes) { + m_numDataBytes = bytes; +} + +void CBC_QRCoder::SetNumTotalBytes(int32_t value) { + m_numTotalBytes = value; +} + +void CBC_QRCoder::SetNumRSBlocks(int32_t block) { + m_numRSBlocks = block; +} + +void CBC_QRCoder::SetNumECBytes(int32_t value) { + m_numECBytes = value; +} + +bool CBC_QRCoder::IsValidMaskPattern(int32_t maskPattern) { + return maskPattern >= 0 && maskPattern < kNumMaskPatterns; +} + +void CBC_QRCoder::SetMatrix(std::unique_ptr<CBC_CommonByteMatrix> pMatrix) { + m_matrix = std::move(pMatrix); +} diff --git a/fxbarcode/qrcode/BC_QRCoder.h b/fxbarcode/qrcode/BC_QRCoder.h new file mode 100644 index 0000000000..0925a8e5cd --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoder.h @@ -0,0 +1,63 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODER_H_ +#define FXBARCODE_QRCODE_BC_QRCODER_H_ + +#include <memory> + +class CBC_QRCoderErrorCorrectionLevel; +class CBC_QRCoderMode; +class CBC_CommonByteMatrix; + +class CBC_QRCoder { + public: + static constexpr int32_t kNumMaskPatterns = 8; + + CBC_QRCoder(); + virtual ~CBC_QRCoder(); + + static bool IsValidMaskPattern(int32_t maskPattern); + + CBC_QRCoderMode* GetMode() const; + CBC_QRCoderErrorCorrectionLevel* GetECLevel() const; + int32_t GetVersion() const; + int32_t GetMatrixWidth() const; + int32_t GetMaskPattern() const; + int32_t GetNumTotalBytes() const; + int32_t GetNumDataBytes() const; + int32_t GetNumECBytes() const; + int32_t GetNumRSBlocks() const; + CBC_CommonByteMatrix* GetMatrix() const; + + int32_t At(int32_t x, int32_t y, int32_t& e); + bool IsValid(); + + void SetMode(CBC_QRCoderMode* value); + void SetECLevel(CBC_QRCoderErrorCorrectionLevel* ecLevel); + void SetVersion(int32_t version); + void SetMatrixWidth(int32_t width); + void SetMaskPattern(int32_t pattern); + void SetNumDataBytes(int32_t bytes); + void SetNumTotalBytes(int32_t value); + void SetNumECBytes(int32_t value); + void SetNumRSBlocks(int32_t block); + void SetMatrix(std::unique_ptr<CBC_CommonByteMatrix> pMatrix); + + private: + CBC_QRCoderMode* m_mode; + CBC_QRCoderErrorCorrectionLevel* m_ecLevel; + int32_t m_version; + int32_t m_matrixWidth; + int32_t m_maskPattern; + int32_t m_numTotalBytes; + int32_t m_numDataBytes; + int32_t m_numECBytes; + int32_t m_numRSBlocks; + std::unique_ptr<CBC_CommonByteMatrix> m_matrix; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODER_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderBitVector.cpp b/fxbarcode/qrcode/BC_QRCoderBitVector.cpp new file mode 100644 index 0000000000..08222093a5 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBitVector.cpp @@ -0,0 +1,127 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/fxcrt/fx_memory.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/utils.h" + +CBC_QRCoderBitVector::CBC_QRCoderBitVector() { + m_sizeInBits = 0; + m_size = 32; +} +void CBC_QRCoderBitVector::Init() { + m_array = FX_Alloc(uint8_t, m_size); +} +CBC_QRCoderBitVector::~CBC_QRCoderBitVector() { + FX_Free(m_array); +} +void CBC_QRCoderBitVector::Clear() { + FX_Free(m_array); + m_sizeInBits = 0; + m_size = 32; + m_array = FX_Alloc(uint8_t, m_size); +} +int32_t CBC_QRCoderBitVector::At(int32_t index, int32_t& e) { + if (index < 0 || index >= m_sizeInBits) { + e = BCExceptionBadIndexException; + return 0; + } + int32_t value = m_array[index >> 3] & 0xff; + return (value >> (7 - (index & 0x7))) & 1; +} +int32_t CBC_QRCoderBitVector::sizeInBytes() { + return (m_sizeInBits + 7) >> 3; +} +int32_t CBC_QRCoderBitVector::Size() { + return m_sizeInBits; +} +void CBC_QRCoderBitVector::AppendBit(int32_t bit, int32_t& e) { + if (!(bit == 0 || bit == 1)) { + e = BCExceptionBadValueException; + return; + } + int32_t numBitsInLastByte = m_sizeInBits & 0x7; + if (numBitsInLastByte == 0) { + AppendByte(0); + m_sizeInBits -= 8; + } + m_array[m_sizeInBits >> 3] |= (bit << (7 - numBitsInLastByte)); + ++m_sizeInBits; +} +void CBC_QRCoderBitVector::AppendBits(int32_t value, + int32_t numBits, + int32_t& e) { + if (numBits < 0 || numBits > 32) { + e = BCExceptionBadNumBitsException; + return; + } + int32_t numBitsLeft = numBits; + while (numBitsLeft > 0) { + if ((m_sizeInBits & 0x7) == 0 && numBitsLeft >= 8) { + int32_t newByte = (value >> (numBitsLeft - 8)) & 0xff; + AppendByte(newByte); + numBitsLeft -= 8; + } else { + int32_t bit = (value >> (numBitsLeft - 1)) & 1; + AppendBit(bit, e); + if (e != BCExceptionNO) + return; + --numBitsLeft; + } + } +} +void CBC_QRCoderBitVector::AppendBitVector(CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t size = bits->Size(); + for (int32_t i = 0; i < size; i++) { + int32_t num = bits->At(i, e); + if (e != BCExceptionNO) + return; + AppendBit(num, e); + if (e != BCExceptionNO) + return; + } +} +void CBC_QRCoderBitVector::XOR(CBC_QRCoderBitVector* other, int32_t& e) { + if (m_sizeInBits != other->Size()) { + e = BCExceptioncanNotOperatexorOperator; + return; + } + int32_t sizeInBytes = (m_sizeInBits + 7) >> 3; + for (int32_t i = 0; i < sizeInBytes; ++i) { + m_array[i] ^= (other->GetArray())[i]; + } +} +uint8_t* CBC_QRCoderBitVector::GetArray() { + return m_array; +} +void CBC_QRCoderBitVector::AppendByte(int32_t value) { + if ((m_sizeInBits >> 3) == m_size) { + uint8_t* newArray = FX_Alloc(uint8_t, m_size << 1); + FXSYS_memcpy(newArray, m_array, m_size); + FX_Free(m_array); + m_array = newArray; + m_size = m_size << 1; + } + m_array[m_sizeInBits >> 3] = (uint8_t)value; + m_sizeInBits += 8; +} diff --git a/fxbarcode/qrcode/BC_QRCoderBitVector.h b/fxbarcode/qrcode/BC_QRCoderBitVector.h new file mode 100644 index 0000000000..59c4360c1e --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBitVector.h @@ -0,0 +1,35 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ +#define FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ + +#include <stdint.h> + +class CBC_QRCoderBitVector { + private: + int32_t m_sizeInBits; + uint8_t* m_array; + int32_t m_size; + + void AppendByte(int32_t value); + + public: + CBC_QRCoderBitVector(); + virtual ~CBC_QRCoderBitVector(); + int32_t At(int32_t index, int32_t& e); + int32_t Size(); + int32_t sizeInBytes(); + void AppendBit(int32_t bit, int32_t& e); + void AppendBits(int32_t value, int32_t numBits, int32_t& e); + void AppendBitVector(CBC_QRCoderBitVector* bits, int32_t& e); + void XOR(CBC_QRCoderBitVector* other, int32_t& e); + uint8_t* GetArray(); + void Clear(); + virtual void Init(); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp b/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp new file mode 100644 index 0000000000..9d2a1f8375 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp @@ -0,0 +1,44 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderBlockPair.h" + +#include <utility> + +#include "fxbarcode/common/BC_CommonByteArray.h" + +CBC_QRCoderBlockPair::CBC_QRCoderBlockPair( + std::unique_ptr<CBC_CommonByteArray> data, + std::unique_ptr<CBC_CommonByteArray> errorCorrection) + : m_dataBytes(std::move(data)), + m_errorCorrectionBytes(std::move(errorCorrection)) {} + +CBC_QRCoderBlockPair::~CBC_QRCoderBlockPair() {} + +const CBC_CommonByteArray* CBC_QRCoderBlockPair::GetDataBytes() const { + return m_dataBytes.get(); +} + +const CBC_CommonByteArray* CBC_QRCoderBlockPair::GetErrorCorrectionBytes() + const { + return m_errorCorrectionBytes.get(); +} diff --git a/fxbarcode/qrcode/BC_QRCoderBlockPair.h b/fxbarcode/qrcode/BC_QRCoderBlockPair.h new file mode 100644 index 0000000000..7c24d9f5ec --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBlockPair.h @@ -0,0 +1,28 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ +#define FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ + +#include <memory> + +class CBC_CommonByteArray; + +class CBC_QRCoderBlockPair { + public: + CBC_QRCoderBlockPair(std::unique_ptr<CBC_CommonByteArray> data, + std::unique_ptr<CBC_CommonByteArray> errorCorrection); + virtual ~CBC_QRCoderBlockPair(); + + const CBC_CommonByteArray* GetDataBytes() const; + const CBC_CommonByteArray* GetErrorCorrectionBytes() const; + + private: + std::unique_ptr<CBC_CommonByteArray> m_dataBytes; + std::unique_ptr<CBC_CommonByteArray> m_errorCorrectionBytes; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderECB.cpp b/fxbarcode/qrcode/BC_QRCoderECB.cpp new file mode 100644 index 0000000000..65fbe33447 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECB.cpp @@ -0,0 +1,35 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderECB.h" + +CBC_QRCoderECB::CBC_QRCoderECB(int32_t count, int32_t dataCodeWords) { + m_dataCodeWords = dataCodeWords; + m_count = count; +} +CBC_QRCoderECB::~CBC_QRCoderECB() {} +int32_t CBC_QRCoderECB::GetCount() { + return m_count; +} +int32_t CBC_QRCoderECB::GetDataCodeWords() { + return m_dataCodeWords; +} diff --git a/fxbarcode/qrcode/BC_QRCoderECB.h b/fxbarcode/qrcode/BC_QRCoderECB.h new file mode 100644 index 0000000000..b774a3c19c --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECB.h @@ -0,0 +1,24 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERECB_H_ +#define FXBARCODE_QRCODE_BC_QRCODERECB_H_ + +#include <stdint.h> + +class CBC_QRCoderECB { + private: + int32_t m_count; + int32_t m_dataCodeWords; + + public: + CBC_QRCoderECB(int32_t count, int32_t dataCodeWords); + virtual ~CBC_QRCoderECB(); + int32_t GetCount(); + int32_t GetDataCodeWords(); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERECB_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp b/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp new file mode 100644 index 0000000000..e07197df93 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp @@ -0,0 +1,63 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderECB.h" +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" + +CBC_QRCoderECBlocks::CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, + CBC_QRCoderECB* ecBlocks) + : m_ecCodeWordsPerBlock(ecCodeWordsPerBlock) { + m_ecBlocksArray.push_back(ecBlocks); +} + +CBC_QRCoderECBlocks::CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, + CBC_QRCoderECB* ecBlocks1, + CBC_QRCoderECB* ecBlocks2) + : m_ecCodeWordsPerBlock(ecCodeWordsPerBlock) { + m_ecBlocksArray.push_back(ecBlocks1); + m_ecBlocksArray.push_back(ecBlocks2); +} + +CBC_QRCoderECBlocks::~CBC_QRCoderECBlocks() { + for (size_t i = 0; i < m_ecBlocksArray.size(); i++) + delete m_ecBlocksArray[i]; +} + +int32_t CBC_QRCoderECBlocks::GetECCodeWordsPerBlock() const { + return m_ecCodeWordsPerBlock; +} + +int32_t CBC_QRCoderECBlocks::GetNumBlocks() const { + int32_t total = 0; + for (size_t i = 0; i < m_ecBlocksArray.size(); i++) + total += m_ecBlocksArray[i]->GetCount(); + + return total; +} + +int32_t CBC_QRCoderECBlocks::GetTotalECCodeWords() const { + return m_ecCodeWordsPerBlock * GetNumBlocks(); +} + +std::vector<CBC_QRCoderECB*>* CBC_QRCoderECBlocks::GetECBlocks() { + return &m_ecBlocksArray; +} diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocks.h b/fxbarcode/qrcode/BC_QRCoderECBlocks.h new file mode 100644 index 0000000000..bf4f76dc84 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocks.h @@ -0,0 +1,34 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ +#define FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ + +#include <vector> + +#include "core/fxcrt/fx_basic.h" + +class CBC_QRCoderECB; + +class CBC_QRCoderECBlocks { + public: + CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, CBC_QRCoderECB* ecBlocks); + CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, + CBC_QRCoderECB* ecBlocks1, + CBC_QRCoderECB* ecBlocks2); + ~CBC_QRCoderECBlocks(); + + int32_t GetECCodeWordsPerBlock() const; + int32_t GetNumBlocks() const; + int32_t GetTotalECCodeWords() const; + std::vector<CBC_QRCoderECB*>* GetECBlocks(); + + private: + int32_t m_ecCodeWordsPerBlock; + std::vector<CBC_QRCoderECB*> m_ecBlocksArray; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderEncoder.cpp b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp new file mode 100644 index 0000000000..b07b700c51 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp @@ -0,0 +1,970 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderEncoder.h" + +#include <algorithm> +#include <memory> +#include <utility> + +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/common/BC_CommonByteArray.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomon.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderBlockPair.h" +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" + +namespace { + +const int8_t g_alphaNumericTable[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1}; + +} // namespace + +CBC_QRCoderEncoder::CBC_QRCoderEncoder() {} + +CBC_QRCoderEncoder::~CBC_QRCoderEncoder() {} + +void CBC_QRCoderEncoder::Encode(const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e, + int32_t versionSpecify) { + if (versionSpecify == 0) { + EncodeWithAutoVersion(content, ecLevel, qrCode, e); + if (e != BCExceptionNO) + return; + } else if (versionSpecify > 0 && versionSpecify <= 40) { + EncodeWithSpecifyVersion(content, ecLevel, qrCode, versionSpecify, e); + if (e != BCExceptionNO) + return; + } else { + e = BCExceptionVersionMust1_40; + if (e != BCExceptionNO) + return; + } +} + +void CBC_QRCoderEncoder::AppendECI(CBC_QRCoderBitVector* bits) {} + +void CBC_QRCoderEncoder::AppendDataModeLenghInfo( + const std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>& + splitResults, + CBC_QRCoderBitVector& headerAndDataBits, + CBC_QRCoderMode* tempMode, + CBC_QRCoder* qrCode, + CFX_ByteString& encoding, + int32_t& e) { + for (const auto& splitResult : splitResults) { + tempMode = splitResult.first; + if (tempMode == CBC_QRCoderMode::sGBK) { + AppendModeInfo(tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), + tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, + e); + if (e != BCExceptionNO) + return; + } else if (tempMode == CBC_QRCoderMode::sBYTE) { + std::vector<uint8_t> bytes; + CBC_UtilCodingConvert::LocaleToUtf8(splitResult.second, bytes); + AppendModeInfo(tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendLengthInfo(bytes.size(), qrCode->GetVersion(), tempMode, + &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + Append8BitBytes(bytes, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + } else if (tempMode == CBC_QRCoderMode::sALPHANUMERIC) { + AppendModeInfo(tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), + tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, + e); + if (e != BCExceptionNO) + return; + } else if (tempMode == CBC_QRCoderMode::sNUMERIC) { + AppendModeInfo(tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), + tempMode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, + e); + if (e != BCExceptionNO) + return; + } else { + e = BCExceptionUnknown; + return; + } + } +} + +void CBC_QRCoderEncoder::SplitString( + const CFX_ByteString& content, + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result) { + int32_t index = 0, flag = 0; + while ( + (((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || + ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && + (index < content.GetLength())) { + index += 2; + } + if (index != flag) { + result->push_back({CBC_QRCoderMode::sGBK, content.Mid(flag, index - flag)}); + } + flag = index; + if (index >= content.GetLength()) { + return; + } + while ( + GetAlphaNumericCode((uint8_t)content[index]) == -1 && + !(((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || + ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && + (index < content.GetLength())) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + if (IsDBCSLeadByte((uint8_t)content[index])) +#else + if ((uint8_t)content[index] > 127) +#endif + { + index += 2; + } else { + index++; + } + } + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sBYTE, content.Mid(flag, index - flag)}); + } + flag = index; + if (index >= content.GetLength()) { + return; + } + while (FXSYS_Isdigit((uint8_t)content[index]) && + (index < content.GetLength())) { + index++; + } + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sNUMERIC, content.Mid(flag, index - flag)}); + } + flag = index; + if (index >= content.GetLength()) { + return; + } + while (GetAlphaNumericCode((uint8_t)content[index]) != -1 && + (index < content.GetLength())) { + index++; + } + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sALPHANUMERIC, content.Mid(flag, index - flag)}); + } + flag = index; + if (index < content.GetLength()) + SplitString(content.Mid(index, content.GetLength() - index), result); +} + +int32_t CBC_QRCoderEncoder::GetSpanByVersion(CBC_QRCoderMode* modeFirst, + CBC_QRCoderMode* modeSecond, + int32_t versionNum, + int32_t& e) { + if (versionNum == 0) + return 0; + + if (modeFirst == CBC_QRCoderMode::sALPHANUMERIC && + modeSecond == CBC_QRCoderMode::sBYTE) { + if (versionNum >= 1 && versionNum <= 9) + return 11; + if (versionNum >= 10 && versionNum <= 26) + return 15; + if (versionNum >= 27 && versionNum <= 40) + return 16; + e = BCExceptionNoSuchVersion; + return 0; + } + if (modeSecond == CBC_QRCoderMode::sALPHANUMERIC && + modeFirst == CBC_QRCoderMode::sNUMERIC) { + if (versionNum >= 1 && versionNum <= 9) + return 13; + if (versionNum >= 10 && versionNum <= 26) + return 15; + if (versionNum >= 27 && versionNum <= 40) + return 17; + e = BCExceptionNoSuchVersion; + return 0; + } + if (modeSecond == CBC_QRCoderMode::sBYTE && + modeFirst == CBC_QRCoderMode::sNUMERIC) { + if (versionNum >= 1 && versionNum <= 9) + return 6; + if (versionNum >= 10 && versionNum <= 26) + return 8; + if (versionNum >= 27 && versionNum <= 40) + return 9; + e = BCExceptionNoSuchVersion; + return 0; + } + return -1; +} + +void CBC_QRCoderEncoder::MergeString( + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result, + int32_t versionNum, + int32_t& e) { + size_t mergeNum = 0; + for (size_t i = 0; i + 1 < result->size(); i++) { + auto* element1 = &(*result)[i]; + auto* element2 = &(*result)[i + 1]; + if (element1->first == CBC_QRCoderMode::sALPHANUMERIC) { + int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sALPHANUMERIC, + CBC_QRCoderMode::sBYTE, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2->first == CBC_QRCoderMode::sBYTE && + element1->second.GetLength() < tmp) { + element2->second = element1->second + element2->second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + } else if (element1->first == CBC_QRCoderMode::sBYTE) { + if (element2->first == CBC_QRCoderMode::sBYTE) { + element1->second += element2->second; + result->erase(result->begin() + i + 1); + i--; + mergeNum++; + } + } else if (element1->first == CBC_QRCoderMode::sNUMERIC) { + int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, + CBC_QRCoderMode::sBYTE, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2->first == CBC_QRCoderMode::sBYTE && + element1->second.GetLength() < tmp) { + element2->second = element1->second + element2->second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, + CBC_QRCoderMode::sALPHANUMERIC, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2->first == CBC_QRCoderMode::sALPHANUMERIC && + element1->second.GetLength() < tmp) { + element2->second = element1->second + element2->second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + } + } + if (mergeNum == 0) { + return; + } + MergeString(result, versionNum, e); + if (e != BCExceptionNO) + return; +} + +void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, + int32_t versionNumber, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoderMode* mode, + CBC_QRCoder* qrCode, + int32_t& e) { + qrCode->SetECLevel(ecLevel); + qrCode->SetMode(mode); + CBC_QRCoderVersion* version = + CBC_QRCoderVersion::GetVersionForNumber(versionNumber, e); + if (e != BCExceptionNO) + return; + int32_t numBytes = version->GetTotalCodeWords(); + CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); + int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); + int32_t numRSBlocks = ecBlocks->GetNumBlocks(); + int32_t numDataBytes = numBytes - numEcBytes; + if (numDataBytes < numInputBytes + 3) { + e = BCExceptionCannotFindBlockInfo; + return; + } + qrCode->SetVersion(versionNumber); + qrCode->SetNumTotalBytes(numBytes); + qrCode->SetNumDataBytes(numDataBytes); + qrCode->SetNumRSBlocks(numRSBlocks); + qrCode->SetNumECBytes(numEcBytes); + qrCode->SetMatrixWidth(version->GetDimensionForVersion()); +} + +void CBC_QRCoderEncoder::EncodeWithSpecifyVersion( + const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t versionSpecify, + int32_t& e) { + CFX_ByteString encoding = "utf8"; + CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>> splitResult; + CBC_QRCoderBitVector dataBits; + dataBits.Init(); + SplitString(content, &splitResult); + MergeString(&splitResult, versionSpecify, e); + if (e != BCExceptionNO) + return; + CBC_QRCoderMode* tempMode = nullptr; + for (const auto& result : splitResult) { + AppendBytes(result.second, result.first, &dataBits, encoding, e); + if (e != BCExceptionNO) + return; + } + int32_t numInputBytes = dataBits.sizeInBytes(); + CBC_QRCoderBitVector headerAndDataBits; + headerAndDataBits.Init(); + InitQRCode(numInputBytes, versionSpecify, ecLevel, mode, qrCode, e); + if (e != BCExceptionNO) + return; + + AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, + encoding, e); + if (e != BCExceptionNO) + return; + + numInputBytes = headerAndDataBits.sizeInBytes(); + TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + + CBC_QRCoderBitVector finalBits; + finalBits.Init(); + InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), + qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), + &finalBits, e); + if (e != BCExceptionNO) + return; + + std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( + qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); + matrix->Init(); + int32_t maskPattern = ChooseMaskPattern( + &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); + if (e != BCExceptionNO) + return; + + qrCode->SetMaskPattern(maskPattern); + CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), + qrCode->GetVersion(), + qrCode->GetMaskPattern(), matrix.get(), e); + if (e != BCExceptionNO) + return; + + qrCode->SetMatrix(std::move(matrix)); + if (!qrCode->IsValid()) + e = BCExceptionInvalidQRCode; +} + +void CBC_QRCoderEncoder::EncodeWithAutoVersion( + const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e) { + CFX_ByteString encoding = "utf8"; + CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>> splitResult; + CBC_QRCoderBitVector dataBits; + dataBits.Init(); + SplitString(content, &splitResult); + MergeString(&splitResult, 8, e); + if (e != BCExceptionNO) + return; + CBC_QRCoderMode* tempMode = nullptr; + for (const auto& result : splitResult) { + AppendBytes(result.second, result.first, &dataBits, encoding, e); + if (e != BCExceptionNO) + return; + } + int32_t numInputBytes = dataBits.sizeInBytes(); + InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); + if (e != BCExceptionNO) + return; + CBC_QRCoderBitVector headerAndDataBits; + headerAndDataBits.Init(); + tempMode = nullptr; + int32_t versionNum = qrCode->GetVersion(); +sign: + AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, + encoding, e); + if (e != BCExceptionNO) { + goto catchException; + } + numInputBytes = headerAndDataBits.sizeInBytes(); + TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); + if (e != BCExceptionNO) { + goto catchException; + } +catchException: + if (e != BCExceptionNO) { + int32_t e1 = BCExceptionNO; + InitQRCode(numInputBytes, ecLevel, mode, qrCode, e1); + if (e1 != BCExceptionNO) { + e = e1; + return; + } + versionNum++; + if (versionNum <= 40) { + headerAndDataBits.Clear(); + e = BCExceptionNO; + goto sign; + } else { + return; + } + } + + CBC_QRCoderBitVector finalBits; + finalBits.Init(); + InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), + qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), + &finalBits, e); + if (e != BCExceptionNO) + return; + + std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( + qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); + matrix->Init(); + int32_t maskPattern = ChooseMaskPattern( + &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); + if (e != BCExceptionNO) + return; + + qrCode->SetMaskPattern(maskPattern); + CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), + qrCode->GetVersion(), + qrCode->GetMaskPattern(), matrix.get(), e); + if (e != BCExceptionNO) + return qrCode->SetMatrix(std::move(matrix)); + + if (!qrCode->IsValid()) + e = BCExceptionInvalidQRCode; +} + +void CBC_QRCoderEncoder::Encode(const CFX_WideString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e) { + CFX_ByteString encoding = "utf8"; + CFX_ByteString utf8Data; + CBC_UtilCodingConvert::UnicodeToUTF8(content, utf8Data); + CBC_QRCoderMode* mode = ChooseMode(utf8Data, encoding); + CBC_QRCoderBitVector dataBits; + dataBits.Init(); + AppendBytes(utf8Data, mode, &dataBits, encoding, e); + if (e != BCExceptionNO) + return; + int32_t numInputBytes = dataBits.sizeInBytes(); + InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); + if (e != BCExceptionNO) + return; + CBC_QRCoderBitVector headerAndDataBits; + headerAndDataBits.Init(); + AppendModeInfo(mode, &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + int32_t numLetters = mode == CBC_QRCoderMode::sBYTE ? dataBits.sizeInBytes() + : content.GetLength(); + AppendLengthInfo(numLetters, qrCode->GetVersion(), mode, &headerAndDataBits, + e); + if (e != BCExceptionNO) + return; + headerAndDataBits.AppendBitVector(&dataBits, e); + if (e != BCExceptionNO) + return TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); + if (e != BCExceptionNO) + return; + CBC_QRCoderBitVector finalBits; + finalBits.Init(); + InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), + qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), + &finalBits, e); + if (e != BCExceptionNO) + return; + + std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( + qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); + matrix->Init(); + int32_t maskPattern = ChooseMaskPattern( + &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); + if (e != BCExceptionNO) + return; + + qrCode->SetMaskPattern(maskPattern); + CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), + qrCode->GetVersion(), + qrCode->GetMaskPattern(), matrix.get(), e); + if (e != BCExceptionNO) + return qrCode->SetMatrix(std::move(matrix)); + + if (!qrCode->IsValid()) + e = BCExceptionInvalidQRCode; +} + +void CBC_QRCoderEncoder::TerminateBits(int32_t numDataBytes, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t capacity = numDataBytes << 3; + if (bits->Size() > capacity) { + e = BCExceptionDataTooMany; + return; + } + for (int32_t i = 0; i < 4 && bits->Size() < capacity; ++i) { + bits->AppendBit(0, e); + if (e != BCExceptionNO) + return; + } + int32_t numBitsInLastByte = bits->Size() % 8; + if (numBitsInLastByte > 0) { + int32_t numPaddingBits = 8 - numBitsInLastByte; + for (int32_t j = 0; j < numPaddingBits; ++j) { + bits->AppendBit(0, e); + if (e != BCExceptionNO) + return; + } + } + if (bits->Size() % 8 != 0) { + e = BCExceptionDigitLengthMustBe8; + return; + } + int32_t numPaddingBytes = numDataBytes - bits->sizeInBytes(); + for (int32_t k = 0; k < numPaddingBytes; ++k) { + if (k % 2 == 0) { + bits->AppendBits(0xec, 8, e); + if (e != BCExceptionNO) + return; + } else { + bits->AppendBits(0x11, 8, e); + if (e != BCExceptionNO) + return; + } + } + if (bits->Size() != capacity) + e = BCExceptionBitsNotEqualCacity; +} + +int32_t CBC_QRCoderEncoder::ChooseMaskPattern( + CBC_QRCoderBitVector* bits, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + int32_t minPenalty = 65535; + int32_t bestMaskPattern = -1; + for (int32_t maskPattern = 0; maskPattern < CBC_QRCoder::kNumMaskPatterns; + maskPattern++) { + CBC_QRCoderMatrixUtil::BuildMatrix(bits, ecLevel, version, maskPattern, + matrix, e); + if (e != BCExceptionNO) + return 0; + int32_t penalty = CalculateMaskPenalty(matrix); + if (penalty < minPenalty) { + minPenalty = penalty; + bestMaskPattern = maskPattern; + } + } + return bestMaskPattern; +} + +int32_t CBC_QRCoderEncoder::CalculateMaskPenalty(CBC_CommonByteMatrix* matrix) { + int32_t penalty = 0; + penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(matrix); + penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(matrix); + penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(matrix); + penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(matrix); + return penalty; +} + +CBC_QRCoderMode* CBC_QRCoderEncoder::ChooseMode(const CFX_ByteString& content, + CFX_ByteString encoding) { + if (encoding.Compare("SHIFT_JIS") == 0) { + return CBC_QRCoderMode::sKANJI; + } + bool hasNumeric = false; + bool hasAlphaNumeric = false; + for (int32_t i = 0; i < content.GetLength(); i++) { + if (isdigit((uint8_t)content[i])) { + hasNumeric = true; + } else if (GetAlphaNumericCode((uint8_t)content[i]) != -1) { + hasAlphaNumeric = true; + } else { + return CBC_QRCoderMode::sBYTE; + } + } + if (hasAlphaNumeric) { + return CBC_QRCoderMode::sALPHANUMERIC; + } else if (hasNumeric) { + return CBC_QRCoderMode::sNUMERIC; + } + return CBC_QRCoderMode::sBYTE; +} + +int32_t CBC_QRCoderEncoder::GetAlphaNumericCode(int32_t code) { + return (code >= 0 && code < 96) ? g_alphaNumericTable[code] : -1; +} + +void CBC_QRCoderEncoder::AppendBytes(const CFX_ByteString& content, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + CFX_ByteString encoding, + int32_t& e) { + if (mode == CBC_QRCoderMode::sNUMERIC) + AppendNumericBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sALPHANUMERIC) + AppendAlphaNumericBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sBYTE) + Append8BitBytes(content, bits, encoding, e); + else if (mode == CBC_QRCoderMode::sKANJI) + AppendKanjiBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sGBK) + AppendGBKBytes(content, bits, e); + else + e = BCExceptionUnsupportedMode; +} + +void CBC_QRCoderEncoder::AppendNumericBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + int32_t i = 0; + while (i < length) { + int32_t num1 = content[i] - '0'; + if (i + 2 < length) { + int32_t num2 = content[i + 1] - '0'; + int32_t num3 = content[i + 2] - '0'; + bits->AppendBits(num1 * 100 + num2 * 10 + num3, 10, e); + if (e != BCExceptionNO) + return; + i += 3; + } else if (i + 1 < length) { + int32_t num2 = content[i + 1] - '0'; + bits->AppendBits(num1 * 10 + num2, 7, e); + if (e != BCExceptionNO) + return; + i += 2; + } else { + bits->AppendBits(num1, 4, e); + if (e != BCExceptionNO) + return; + i++; + } + } +} + +void CBC_QRCoderEncoder::AppendAlphaNumericBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + int32_t i = 0; + while (i < length) { + int32_t code1 = GetAlphaNumericCode(content[i]); + if (code1 == -1) { + e = BCExceptionInvalidateCharacter; + return; + } + if (i + 1 < length) { + int32_t code2 = GetAlphaNumericCode(content[i + 1]); + if (code2 == -1) { + e = BCExceptionInvalidateCharacter; + return; + } + bits->AppendBits(code1 * 45 + code2, 11, e); + if (e != BCExceptionNO) + return; + i += 2; + } else { + bits->AppendBits(code1, 6, e); + if (e != BCExceptionNO) + return; + i++; + } + } +} + +void CBC_QRCoderEncoder::AppendGBKBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + uint32_t value = 0; + for (int32_t i = 0; i < length; i += 2) { + value = (uint32_t)((uint8_t)content[i] << 8 | (uint8_t)content[i + 1]); + if (value <= 0xAAFE && value >= 0xA1A1) { + value -= 0xA1A1; + } else if (value <= 0xFAFE && value >= 0xB0A1) { + value -= 0xA6A1; + } else { + e = BCExceptionInvalidateCharacter; + return; + } + value = (uint32_t)((value >> 8) * 0x60) + (uint32_t)(value & 0xff); + bits->AppendBits(value, 13, e); + if (e != BCExceptionNO) + return; + } +} + +void CBC_QRCoderEncoder::Append8BitBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + CFX_ByteString encoding, + int32_t& e) { + for (int32_t i = 0; i < content.GetLength(); i++) { + bits->AppendBits(content[i], 8, e); + if (e != BCExceptionNO) + return; + } +} + +void CBC_QRCoderEncoder::Append8BitBytes(std::vector<uint8_t>& bytes, + CBC_QRCoderBitVector* bits, + int32_t& e) { + for (size_t i = 0; i < bytes.size(); i++) { + bits->AppendBits(bytes[i], 8, e); + if (e != BCExceptionNO) + return; + } +} + +void CBC_QRCoderEncoder::AppendKanjiBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + std::vector<uint8_t> bytes; + uint32_t value = 0; + for (size_t i = 0; i < bytes.size(); i += 2) { + value = (uint32_t)((uint8_t)(content[i] << 8) | (uint8_t)content[i + 1]); + if (value <= 0x9ffc && value >= 0x8140) { + value -= 0x8140; + } else if (value <= 0xebbf && value >= 0xe040) { + value -= 0xc140; + } else { + e = BCExceptionInvalidateCharacter; + return; + } + value = (uint32_t)((value >> 8) * 0xc0) + (uint32_t)(value & 0xff); + bits->AppendBits(value, 13, e); + if (e != BCExceptionNO) + return; + } +} + +void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoderMode* mode, + CBC_QRCoder* qrCode, + int32_t& e) { + qrCode->SetECLevel(ecLevel); + qrCode->SetMode(mode); + for (int32_t versionNum = 1; versionNum <= 40; versionNum++) { + CBC_QRCoderVersion* version = + CBC_QRCoderVersion::GetVersionForNumber(versionNum, e); + if (e != BCExceptionNO) + return; + int32_t numBytes = version->GetTotalCodeWords(); + CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); + int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); + int32_t numRSBlocks = ecBlocks->GetNumBlocks(); + int32_t numDataBytes = numBytes - numEcBytes; + if (numDataBytes >= numInputBytes + 3) { + qrCode->SetVersion(versionNum); + qrCode->SetNumTotalBytes(numBytes); + qrCode->SetNumDataBytes(numDataBytes); + qrCode->SetNumRSBlocks(numRSBlocks); + qrCode->SetNumECBytes(numEcBytes); + qrCode->SetMatrixWidth(version->GetDimensionForVersion()); + return; + } + } + e = BCExceptionCannotFindBlockInfo; +} + +void CBC_QRCoderEncoder::AppendModeInfo(CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + int32_t& e) { + bits->AppendBits(mode->GetBits(), 4, e); + if (mode == CBC_QRCoderMode::sGBK) + bits->AppendBits(1, 4, e); +} + +void CBC_QRCoderEncoder::AppendLengthInfo(int32_t numLetters, + int32_t version, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + int32_t& e) { + CBC_QRCoderVersion* qcv = CBC_QRCoderVersion::GetVersionForNumber(version, e); + if (e != BCExceptionNO) + return; + int32_t numBits = mode->GetCharacterCountBits(qcv, e); + if (e != BCExceptionNO) + return; + if (numBits > ((1 << numBits) - 1)) { + return; + } + if (mode == CBC_QRCoderMode::sGBK) { + bits->AppendBits(numLetters / 2, numBits, e); + if (e != BCExceptionNO) + return; + } + bits->AppendBits(numLetters, numBits, e); +} + +void CBC_QRCoderEncoder::InterleaveWithECBytes(CBC_QRCoderBitVector* bits, + int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + CBC_QRCoderBitVector* result, + int32_t& e) { + if (bits->sizeInBytes() != numDataBytes) { + e = BCExceptionBitsBytesNotMatch; + return; + } + int32_t dataBytesOffset = 0; + int32_t maxNumDataBytes = 0; + int32_t maxNumEcBytes = 0; + std::vector<CBC_QRCoderBlockPair*> blocks; + int32_t i; + for (i = 0; i < numRSBlocks; i++) { + int32_t numDataBytesInBlock; + int32_t numEcBytesInBlosk; + GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, + numRSBlocks, i, numDataBytesInBlock, + numEcBytesInBlosk); + std::unique_ptr<CBC_CommonByteArray> dataBytes(new CBC_CommonByteArray); + dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock); + std::unique_ptr<CBC_CommonByteArray> ecBytes( + GenerateECBytes(dataBytes.get(), numEcBytesInBlosk, e)); + if (e != BCExceptionNO) + return; + maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size()); + maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size()); + blocks.push_back( + new CBC_QRCoderBlockPair(std::move(dataBytes), std::move(ecBytes))); + dataBytesOffset += numDataBytesInBlock; + } + if (numDataBytes != dataBytesOffset) { + e = BCExceptionBytesNotMatchOffset; + return; + } + for (int32_t x = 0; x < maxNumDataBytes; x++) { + for (size_t j = 0; j < blocks.size(); j++) { + const CBC_CommonByteArray* dataBytes = blocks[j]->GetDataBytes(); + if (x < dataBytes->Size()) { + result->AppendBits(dataBytes->At(x), 8, e); + if (e != BCExceptionNO) + return; + } + } + } + for (int32_t y = 0; y < maxNumEcBytes; y++) { + for (size_t l = 0; l < blocks.size(); l++) { + const CBC_CommonByteArray* ecBytes = blocks[l]->GetErrorCorrectionBytes(); + if (y < ecBytes->Size()) { + result->AppendBits(ecBytes->At(y), 8, e); + if (e != BCExceptionNO) + return; + } + } + } + for (size_t k = 0; k < blocks.size(); k++) { + delete blocks[k]; + } + if (numTotalBytes != result->sizeInBytes()) + e = BCExceptionSizeInBytesDiffer; +} + +void CBC_QRCoderEncoder::GetNumDataBytesAndNumECBytesForBlockID( + int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + int32_t blockID, + int32_t& numDataBytesInBlock, + int32_t& numECBytesInBlock) { + if (blockID >= numRSBlocks) { + return; + } + int32_t numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; + int32_t numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; + int32_t numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; + int32_t numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; + int32_t numDataBytesInGroup1 = numDataBytes / numRSBlocks; + int32_t numDataBytesInGroup2 = numDataBytesInGroup1 + 1; + int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; + int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; + if (blockID < numRsBlocksInGroup1) { + numDataBytesInBlock = numDataBytesInGroup1; + numECBytesInBlock = numEcBytesInGroup1; + } else { + numDataBytesInBlock = numDataBytesInGroup2; + numECBytesInBlock = numEcBytesInGroup2; + } +} + +CBC_CommonByteArray* CBC_QRCoderEncoder::GenerateECBytes( + CBC_CommonByteArray* dataBytes, + int32_t numEcBytesInBlock, + int32_t& e) { + int32_t numDataBytes = dataBytes->Size(); + std::vector<int32_t> toEncode(numDataBytes + numEcBytesInBlock); + for (int32_t i = 0; i < numDataBytes; i++) { + toEncode[i] = (dataBytes->At(i)); + } + CBC_ReedSolomonEncoder encode(CBC_ReedSolomonGF256::QRCodeField); + encode.Init(); + encode.Encode(&toEncode, numEcBytesInBlock, e); + if (e != BCExceptionNO) + return nullptr; + CBC_CommonByteArray* ecBytes = new CBC_CommonByteArray(numEcBytesInBlock); + for (int32_t j = 0; j < numEcBytesInBlock; j++) { + ecBytes->Set(j, toEncode[numDataBytes + j]); + } + return ecBytes; +} diff --git a/fxbarcode/qrcode/BC_QRCoderEncoder.h b/fxbarcode/qrcode/BC_QRCoderEncoder.h new file mode 100644 index 0000000000..f46a64e9a9 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderEncoder.h @@ -0,0 +1,140 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ +#define FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ + +#include <utility> +#include <vector> + +#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_string.h" + +class CBC_QRCoder; +class CBC_QRCoderErrorCorrectionLevel; +class CBC_QRCoderMode; +class CBC_QRCoderBitVector; +class CBC_CommonByteArray; +class CBC_CommonByteMatrix; + +class CBC_QRCoderEncoder { + public: + CBC_QRCoderEncoder(); + virtual ~CBC_QRCoderEncoder(); + + static void Encode(const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e, + int32_t versionSpecify = 0); + static void Encode(const CFX_WideString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e); + static void EncodeWithSpecifyVersion(const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t versionSpecify, + int32_t& e); + static void EncodeWithAutoVersion(const CFX_ByteString& content, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode, + int32_t& e); + static CBC_QRCoderMode* ChooseMode(const CFX_ByteString& content, + CFX_ByteString encoding); + static int32_t GetAlphaNumericCode(int32_t code); + static void AppendECI(CBC_QRCoderBitVector* bits); + static void AppendBytes(const CFX_ByteString& content, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + CFX_ByteString encoding, + int32_t& e); + static void AppendNumericBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void AppendAlphaNumericBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void Append8BitBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + CFX_ByteString encoding, + int32_t& e); + static void Append8BitBytes(std::vector<uint8_t>& bytes, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void AppendKanjiBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void AppendGBKBytes(const CFX_ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void InitQRCode(int32_t numInputBytes, + int32_t versionNumber, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoderMode* mode, + CBC_QRCoder* qrCode, + int32_t& e); + static void InitQRCode(int32_t numInputBytes, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoderMode* mode, + CBC_QRCoder* qrCode, + int32_t& e); + static void AppendModeInfo(CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void AppendLengthInfo(int32_t numLetters, + int32_t version, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + int32_t& e); + + static void InterleaveWithECBytes(CBC_QRCoderBitVector* bits, + int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + CBC_QRCoderBitVector* result, + int32_t& e); + static void GetNumDataBytesAndNumECBytesForBlockID( + int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + int32_t blockID, + int32_t& numDataBytesInBlock, + int32_t& numECBytesInBlocks); + static CBC_CommonByteArray* GenerateECBytes(CBC_CommonByteArray* dataBytes, + int32_t numEcBytesInBlock, + int32_t& e); + static int32_t ChooseMaskPattern(CBC_QRCoderBitVector* bits, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static int32_t CalculateMaskPenalty(CBC_CommonByteMatrix* matrix); + static void TerminateBits(int32_t numDataBytes, + CBC_QRCoderBitVector* bits, + int32_t& e); + static int32_t GetSpanByVersion(CBC_QRCoderMode* modeFirst, + CBC_QRCoderMode* modeSecond, + int32_t versionNum, + int32_t& e); + static void MergeString( + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result, + int32_t versionNum, + int32_t& e); + static void SplitString( + const CFX_ByteString& content, + std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result); + static void AppendDataModeLenghInfo( + const std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>& + splitResult, + CBC_QRCoderBitVector& headerAndDataBits, + CBC_QRCoderMode* tempMode, + CBC_QRCoder* qrCode, + CFX_ByteString& encoding, + int32_t& e); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp new file mode 100644 index 0000000000..6fb3233705 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp @@ -0,0 +1,84 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" + +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::L = nullptr; +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::M = nullptr; +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::Q = nullptr; +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::H = nullptr; + +CBC_QRCoderErrorCorrectionLevel::CBC_QRCoderErrorCorrectionLevel( + int32_t ordinal, + int32_t bits, + const char* name) + : m_ordinal(ordinal), m_bits(bits), m_name(name) {} + +CBC_QRCoderErrorCorrectionLevel::~CBC_QRCoderErrorCorrectionLevel() {} + +void CBC_QRCoderErrorCorrectionLevel::Initialize() { + L = new CBC_QRCoderErrorCorrectionLevel(0, 0x01, "L"); + M = new CBC_QRCoderErrorCorrectionLevel(1, 0x00, "M"); + Q = new CBC_QRCoderErrorCorrectionLevel(2, 0x03, "Q"); + H = new CBC_QRCoderErrorCorrectionLevel(3, 0x02, "H"); +} + +void CBC_QRCoderErrorCorrectionLevel::Finalize() { + delete L; + delete M; + delete Q; + delete H; +} + +CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::ForBits( + int32_t bits) { + switch (bits) { + case 0x00: + return M; + case 0x01: + return L; + case 0x02: + return H; + case 0x03: + return Q; + default: + return nullptr; + } +} +void CBC_QRCoderErrorCorrectionLevel::Destroy() { + if (L) { + delete CBC_QRCoderErrorCorrectionLevel::L; + L = nullptr; + } + if (M) { + delete CBC_QRCoderErrorCorrectionLevel::M; + M = nullptr; + } + if (H) { + delete CBC_QRCoderErrorCorrectionLevel::H; + H = nullptr; + } + if (Q) { + delete CBC_QRCoderErrorCorrectionLevel::Q; + Q = nullptr; + } +} diff --git a/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h new file mode 100644 index 0000000000..e153c64395 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h @@ -0,0 +1,41 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ + +#include "core/fxcrt/fx_string.h" + +class CBC_QRCoderErrorCorrectionLevel { + public: + static CBC_QRCoderErrorCorrectionLevel* L; + static CBC_QRCoderErrorCorrectionLevel* M; + static CBC_QRCoderErrorCorrectionLevel* Q; + static CBC_QRCoderErrorCorrectionLevel* H; + + static void Initialize(); + static void Finalize(); + static void Destroy(); + static CBC_QRCoderErrorCorrectionLevel* ForBits(int32_t bits); + + ~CBC_QRCoderErrorCorrectionLevel(); + + int32_t Ordinal() const { return m_ordinal; } + int32_t GetBits() const { return m_bits; } + CFX_ByteString GetName() const { return m_name; } + + private: + CBC_QRCoderErrorCorrectionLevel(int32_t ordinal, + int32_t bits, + const char* name); + CBC_QRCoderErrorCorrectionLevel(); + + int32_t m_ordinal; + int32_t m_bits; + CFX_ByteString m_name; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp new file mode 100644 index 0000000000..cdf1e4caf9 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp @@ -0,0 +1,198 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/utils.h" + +CBC_QRCoderMaskUtil::CBC_QRCoderMaskUtil() {} +CBC_QRCoderMaskUtil::~CBC_QRCoderMaskUtil() {} +int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1( + CBC_CommonByteMatrix* matrix) { + return ApplyMaskPenaltyRule1Internal(matrix, true) + + ApplyMaskPenaltyRule1Internal(matrix, false); +} + +int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2( + CBC_CommonByteMatrix* matrix) { + int32_t penalty = 0; + uint8_t* array = matrix->GetArray(); + int32_t width = matrix->GetWidth(); + int32_t height = matrix->GetHeight(); + for (int32_t y = 0; y < height - 1; y++) { + for (int32_t x = 0; x < width - 1; x++) { + int32_t value = array[y * width + x]; + if (value == array[y * width + x + 1] && + value == array[(y + 1) * width + x] && + value == array[(y + 1) * width + x + 1]) { + penalty++; + } + } + } + return 3 * penalty; +} + +int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3( + CBC_CommonByteMatrix* matrix) { + int32_t penalty = 0; + uint8_t* array = matrix->GetArray(); + int32_t width = matrix->GetWidth(); + int32_t height = matrix->GetHeight(); + for (int32_t y = 0; y < height; ++y) { + for (int32_t x = 0; x < width; ++x) { + if (x == 0 && + ((y >= 0 && y <= 6) || (y >= height - 7 && y <= height - 1))) { + continue; + } + if (x == width - 7 && (y >= 0 && y <= 6)) { + continue; + } + if (y == 0 && + ((x >= 0 && x <= 6) || (x >= width - 7 && x <= width - 1))) { + continue; + } + if (y == height - 7 && (x >= 0 && x <= 6)) { + continue; + } + if (x + 6 < width && array[y * width + x] == 1 && + array[y * width + x + 1] == 0 && array[y * width + x + 2] == 1 && + array[y * width + x + 3] == 1 && array[y * width + x + 4] == 1 && + array[y * width + x + 5] == 0 && array[y * width + x + 6] == 1 && + ((x + 10 < width && array[y * width + x + 7] == 0 && + array[y * width + x + 8] == 0 && array[y * width + x + 9] == 0 && + array[y * width + x + 10] == 0) || + (x - 4 >= 0 && array[y * width + x - 1] == 0 && + array[y * width + x - 2] == 0 && array[y * width + x - 3] == 0 && + array[y * width + x - 4] == 0))) { + penalty += 40; + } + if (y + 6 < height && array[y * width + x] == 1 && + array[(y + 1) * width + x] == 0 && array[(y + 2) * width + x] == 1 && + array[(y + 3) * width + x] == 1 && array[(y + 4) * width + x] == 1 && + array[(y + 5) * width + x] == 0 && array[(y + 6) * width + x] == 1 && + ((y + 10 < height && array[(y + 7) * width + x] == 0 && + array[(y + 8) * width + x] == 0 && + array[(y + 9) * width + x] == 0 && + array[(y + 10) * width + x] == 0) || + (y - 4 >= 0 && array[(y - 1) * width + x] == 0 && + array[(y - 2) * width + x] == 0 && + array[(y - 3) * width + x] == 0 && + array[(y - 4) * width + x] == 0))) { + penalty += 40; + } + } + } + return penalty; +} +int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4( + CBC_CommonByteMatrix* matrix) { + int32_t numDarkCells = 0; + uint8_t* array = matrix->GetArray(); + int32_t width = matrix->GetWidth(); + int32_t height = matrix->GetHeight(); + for (int32_t y = 0; y < height; ++y) { + for (int32_t x = 0; x < width; ++x) { + if (array[y * width + x] == 1) { + numDarkCells += 1; + } + } + } + int32_t numTotalCells = matrix->GetHeight() * matrix->GetWidth(); + double darkRatio = (double)numDarkCells / numTotalCells; + return abs((int32_t)(darkRatio * 100 - 50) / 5) * 5 * 10; +} +bool CBC_QRCoderMaskUtil::GetDataMaskBit(int32_t maskPattern, + int32_t x, + int32_t y, + int32_t& e) { + if (!CBC_QRCoder::IsValidMaskPattern(maskPattern)) { + e = (BCExceptionInvalidateMaskPattern); + return false; + } + int32_t intermediate = 0, temp = 0; + switch (maskPattern) { + case 0: + intermediate = (y + x) & 0x1; + break; + case 1: + intermediate = y & 0x1; + break; + case 2: + intermediate = x % 3; + break; + case 3: + intermediate = (y + x) % 3; + break; + case 4: + intermediate = ((y >> 1) + (x / 3)) & 0x1; + break; + case 5: + temp = y * x; + intermediate = (temp & 0x1) + (temp % 3); + break; + case 6: + temp = y * x; + intermediate = (((temp & 0x1) + (temp % 3)) & 0x1); + break; + case 7: + temp = y * x; + intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1); + break; + default: { + e = BCExceptionInvalidateMaskPattern; + return false; + } + } + return intermediate == 0; +} +int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1Internal( + CBC_CommonByteMatrix* matrix, + bool isHorizontal) { + int32_t penalty = 0; + int32_t numSameBitCells = 0; + int32_t prevBit = -1; + int32_t width = matrix->GetWidth(); + int32_t height = matrix->GetHeight(); + int32_t iLimit = isHorizontal ? height : width; + int32_t jLimit = isHorizontal ? width : height; + uint8_t* array = matrix->GetArray(); + for (int32_t i = 0; i < iLimit; ++i) { + for (int32_t j = 0; j < jLimit; ++j) { + int32_t bit = isHorizontal ? array[i * width + j] : array[j * width + i]; + if (bit == prevBit) { + numSameBitCells += 1; + if (numSameBitCells == 5) { + penalty += 3; + } else if (numSameBitCells > 5) { + penalty += 1; + } + } else { + numSameBitCells = 1; + prevBit = bit; + } + } + numSameBitCells = 0; + } + return penalty; +} diff --git a/fxbarcode/qrcode/BC_QRCoderMaskUtil.h b/fxbarcode/qrcode/BC_QRCoderMaskUtil.h new file mode 100644 index 0000000000..63fccbb8e4 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMaskUtil.h @@ -0,0 +1,27 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ +class CBC_CommonByteMatrix; +class CBC_QRCoderMaskUtil { + public: + CBC_QRCoderMaskUtil(); + virtual ~CBC_QRCoderMaskUtil(); + static bool GetDataMaskBit(int32_t maskPattern, + int32_t x, + int32_t y, + int32_t& e); + + static int32_t ApplyMaskPenaltyRule1(CBC_CommonByteMatrix* matrix); + static int32_t ApplyMaskPenaltyRule2(CBC_CommonByteMatrix* matrix); + static int32_t ApplyMaskPenaltyRule3(CBC_CommonByteMatrix* matrix); + static int32_t ApplyMaskPenaltyRule4(CBC_CommonByteMatrix* matrix); + static int32_t ApplyMaskPenaltyRule1Internal(CBC_CommonByteMatrix* matrix, + bool isHorizontal); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp new file mode 100644 index 0000000000..b6ffaa00fc --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp @@ -0,0 +1,506 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" +#include "fxbarcode/utils.h" + +const int32_t CBC_QRCoderMatrixUtil::POSITION_DETECTION_PATTERN[7][7] = { + {1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, + {1, 0, 1, 1, 1, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 1, 1, 1, 1}}; +const int32_t CBC_QRCoderMatrixUtil::HORIZONTAL_SEPARATION_PATTERN[1][8] = { + {0, 0, 0, 0, 0, 0, 0, 0}}; +const int32_t CBC_QRCoderMatrixUtil::VERTICAL_SEPARATION_PATTERN[7][1] = { + {0}, {0}, {0}, {0}, {0}, {0}, {0}}; +const int32_t CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN[5][5] = { + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 1, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1}}; +const int32_t + CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7] = + // NOLINTNEXTLINE + { + {-1, -1, -1, -1, -1, -1, -1}, {6, 18, -1, -1, -1, -1, -1}, + {6, 22, -1, -1, -1, -1, -1}, {6, 26, -1, -1, -1, -1, -1}, + {6, 30, -1, -1, -1, -1, -1}, {6, 34, -1, -1, -1, -1, -1}, + {6, 22, 38, -1, -1, -1, -1}, {6, 24, 42, -1, -1, -1, -1}, + {6, 26, 46, -1, -1, -1, -1}, {6, 28, 50, -1, -1, -1, -1}, + {6, 30, 54, -1, -1, -1, -1}, {6, 32, 58, -1, -1, -1, -1}, + {6, 34, 62, -1, -1, -1, -1}, {6, 26, 46, 66, -1, -1, -1}, + {6, 26, 48, 70, -1, -1, -1}, {6, 26, 50, 74, -1, -1, -1}, + {6, 30, 54, 78, -1, -1, -1}, {6, 30, 56, 82, -1, -1, -1}, + {6, 30, 58, 86, -1, -1, -1}, {6, 34, 62, 90, -1, -1, -1}, + {6, 28, 50, 72, 94, -1, -1}, {6, 26, 50, 74, 98, -1, -1}, + {6, 30, 54, 78, 102, -1, -1}, {6, 28, 54, 80, 106, -1, -1}, + {6, 32, 58, 84, 110, -1, -1}, {6, 30, 58, 86, 114, -1, -1}, + {6, 34, 62, 90, 118, -1, -1}, {6, 26, 50, 74, 98, 122, -1}, + {6, 30, 54, 78, 102, 126, -1}, {6, 26, 52, 78, 104, 130, -1}, + {6, 30, 56, 82, 108, 134, -1}, {6, 34, 60, 86, 112, 138, -1}, + {6, 30, 58, 86, 114, 142, -1}, {6, 34, 62, 90, 118, 146, -1}, + {6, 30, 54, 78, 102, 126, 150}, {6, 24, 50, 76, 102, 128, 154}, + {6, 28, 54, 80, 106, 132, 158}, {6, 32, 58, 84, 110, 136, 162}, + {6, 26, 54, 82, 110, 138, 166}, {6, 30, 58, 86, 114, 142, 170}, +}; +const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_COORDINATES[15][2] = { + {8, 0}, {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 7}, {8, 8}, + {7, 8}, {5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}, +}; +const int32_t CBC_QRCoderMatrixUtil::VERSION_INFO_POLY = 0x1f25; +const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_POLY = 0x0537; +const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_MASK_PATTERN = 0x5412; + +void CBC_QRCoderMatrixUtil::ClearMatrix(CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + matrix->clear((uint8_t)-1); +} +void CBC_QRCoderMatrixUtil::BuildMatrix( + CBC_QRCoderBitVector* dataBits, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t version, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + ClearMatrix(matrix, e); + if (e != BCExceptionNO) + return; + EmbedBasicPatterns(version, matrix, e); + if (e != BCExceptionNO) + return; + EmbedTypeInfo(ecLevel, maskPattern, matrix, e); + if (e != BCExceptionNO) + return; + MaybeEmbedVersionInfo(version, matrix, e); + if (e != BCExceptionNO) + return; + EmbedDataBits(dataBits, maskPattern, matrix, e); + if (e != BCExceptionNO) + return; +} +void CBC_QRCoderMatrixUtil::EmbedBasicPatterns(int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + EmbedPositionDetectionPatternsAndSeparators(matrix, e); + if (e != BCExceptionNO) + return; + EmbedDarkDotAtLeftBottomCorner(matrix, e); + if (e != BCExceptionNO) + return; + MaybeEmbedPositionAdjustmentPatterns(version, matrix, e); + if (e != BCExceptionNO) + return; + EmbedTimingPatterns(matrix, e); + if (e != BCExceptionNO) + return; +} +void CBC_QRCoderMatrixUtil::EmbedTypeInfo( + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + CBC_QRCoderBitVector typeInfoBits; + typeInfoBits.Init(); + MakeTypeInfoBits(ecLevel, maskPattern, &typeInfoBits, e); + if (e != BCExceptionNO) + return; + for (int32_t i = 0; i < typeInfoBits.Size(); i++) { + int32_t bit = typeInfoBits.At(typeInfoBits.Size() - 1 - i, e); + if (e != BCExceptionNO) + return; + int32_t x1 = TYPE_INFO_COORDINATES[i][0]; + int32_t y1 = TYPE_INFO_COORDINATES[i][1]; + matrix->Set(x1, y1, bit); + if (i < 8) { + int32_t x2 = matrix->GetWidth() - i - 1; + int32_t y2 = 8; + matrix->Set(x2, y2, bit); + } else { + int32_t x2 = 8; + int32_t y2 = matrix->GetHeight() - 7 + (i - 8); + matrix->Set(x2, y2, bit); + } + } +} +void CBC_QRCoderMatrixUtil::MaybeEmbedVersionInfo(int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + if (version < 7) { + return; + } + CBC_QRCoderBitVector versionInfoBits; + versionInfoBits.Init(); + MakeVersionInfoBits(version, &versionInfoBits, e); + if (e != BCExceptionNO) + return; + int32_t bitIndex = 6 * 3 - 1; + for (int32_t i = 0; i < 6; i++) { + for (int32_t j = 0; j < 3; j++) { + int32_t bit = versionInfoBits.At(bitIndex, e); + if (e != BCExceptionNO) + return; + bitIndex--; + matrix->Set(i, matrix->GetHeight() - 11 + j, bit); + matrix->Set(matrix->GetHeight() - 11 + j, i, bit); + } + } +} +void CBC_QRCoderMatrixUtil::EmbedDataBits(CBC_QRCoderBitVector* dataBits, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix || !dataBits) { + e = BCExceptionNullPointer; + return; + } + int32_t bitIndex = 0; + int32_t direction = -1; + int32_t x = matrix->GetWidth() - 1; + int32_t y = matrix->GetHeight() - 1; + while (x > 0) { + if (x == 6) { + x -= 1; + } + while (y >= 0 && y < matrix->GetHeight()) { + if (y == 6) { + y += direction; + continue; + } + for (int32_t i = 0; i < 2; i++) { + int32_t xx = x - i; + if (!IsEmpty(matrix->Get(xx, y))) { + continue; + } + int32_t bit; + if (bitIndex < dataBits->Size()) { + bit = dataBits->At(bitIndex, e); + if (e != BCExceptionNO) + return; + bitIndex++; + } else { + bit = 0; + } + if (maskPattern != -1) { + bool bol = CBC_QRCoderMaskUtil::GetDataMaskBit(maskPattern, xx, y, e); + if (e != BCExceptionNO) + return; + if (bol) { + bit ^= 0x01; + } + } + matrix->Set(xx, y, bit); + } + y += direction; + } + direction = -direction; + y += direction; + x -= 2; + } + if (bitIndex != dataBits->Size()) { + return; + } +} +int32_t CBC_QRCoderMatrixUtil::CalculateBCHCode(int32_t value, int32_t poly) { + int32_t msbSetInPoly = FindMSBSet(poly); + value <<= msbSetInPoly - 1; + while (FindMSBSet(value) >= msbSetInPoly) { + value ^= poly << (FindMSBSet(value) - msbSetInPoly); + } + return value; +} +void CBC_QRCoderMatrixUtil::MakeTypeInfoBits( + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t maskPattern, + CBC_QRCoderBitVector* bits, + int32_t& e) { + if (!bits) { + e = BCExceptionNullPointer; + return; + } + if (!CBC_QRCoder::IsValidMaskPattern(maskPattern)) { + e = BCExceptionBadMask; + return; + } + int32_t typeInfo = (ecLevel->GetBits() << 3) | maskPattern; + if (e != BCExceptionNO) + return; + bits->AppendBits(typeInfo, 5, e); + int32_t bchCode = CalculateBCHCode(typeInfo, TYPE_INFO_POLY); + if (e != BCExceptionNO) + return; + bits->AppendBits(bchCode, 10, e); + CBC_QRCoderBitVector maskBits; + maskBits.Init(); + maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15, e); + if (e != BCExceptionNO) + return; + bits->XOR(&maskBits, e); + if (e != BCExceptionNO) + return; + if (bits->Size() != 15) + e = BCExceptionBitSizeNot15; +} + +void CBC_QRCoderMatrixUtil::MakeVersionInfoBits(int32_t version, + CBC_QRCoderBitVector* bits, + int32_t& e) { + if (!bits) { + e = BCExceptionNullPointer; + return; + } + bits->AppendBits(version, 6, e); + if (e != BCExceptionNO) + return; + + int32_t bchCode = CalculateBCHCode(version, VERSION_INFO_POLY); + bits->AppendBits(bchCode, 12, e); + if (e != BCExceptionNO) + return; + + if (bits->Size() != 18) + e = BCExceptionBitSizeNot18; +} + +bool CBC_QRCoderMatrixUtil::IsEmpty(int32_t value) { + return (uint8_t)value == 0xff; +} +bool CBC_QRCoderMatrixUtil::IsValidValue(int32_t value) { + return ((uint8_t)value == 0xff || (uint8_t)value == 0x00 || + (uint8_t)value == 0x01); +} + +void CBC_QRCoderMatrixUtil::EmbedTimingPatterns(CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + for (int32_t i = 8; i < matrix->GetWidth() - 8; i++) { + int32_t bit = (i + 1) % 2; + if (!IsValidValue(matrix->Get(i, 6))) { + e = BCExceptionInvalidateImageData; + return; + } + if (IsEmpty(matrix->Get(i, 6))) { + matrix->Set(i, 6, bit); + } + if (!IsValidValue(matrix->Get(6, i))) { + e = BCExceptionInvalidateImageData; + return; + } + if (IsEmpty(matrix->Get(6, i))) { + matrix->Set(6, i, bit); + } + } +} +void CBC_QRCoderMatrixUtil::EmbedDarkDotAtLeftBottomCorner( + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + if (matrix->Get(8, matrix->GetHeight() - 8) == 0) { + e = BCExceptionHeight_8BeZero; + return; + } + matrix->Set(8, matrix->GetHeight() - 8, 1); +} +void CBC_QRCoderMatrixUtil::EmbedHorizontalSeparationPattern( + int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + for (int32_t x = 0; x < 8; x++) { + if (!IsEmpty(matrix->Get(xStart + x, yStart))) { + e = BCExceptionInvalidateData; + return; + } + matrix->Set(xStart + x, yStart, HORIZONTAL_SEPARATION_PATTERN[0][x]); + } +} +void CBC_QRCoderMatrixUtil::EmbedVerticalSeparationPattern( + int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + for (int32_t y = 0; y < 7; y++) { + if (!IsEmpty(matrix->Get(xStart, yStart + y))) { + e = BCExceptionInvalidateData; + return; + } + matrix->Set(xStart, yStart + y, VERTICAL_SEPARATION_PATTERN[y][0]); + } +} +void CBC_QRCoderMatrixUtil::EmbedPositionAdjustmentPattern( + int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + if (e != BCExceptionNO) + return; + } + for (int32_t y = 0; y < 5; y++) { + for (int32_t x = 0; x < 5; x++) { + if (!IsEmpty(matrix->Get(xStart + x, y + yStart))) { + e = BCExceptionInvalidateData; + return; + } + matrix->Set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]); + } + } +} +void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPattern( + int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + for (int32_t y = 0; y < 7; y++) { + for (int32_t x = 0; x < 7; x++) { + if (!IsEmpty(matrix->Get(xStart + x, yStart + y))) { + e = BCExceptionInvalidateData; + return; + } + matrix->Set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]); + } + } +} +void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPatternsAndSeparators( + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + int32_t pdpWidth = 7; + EmbedPositionDetectionPattern(0, 0, matrix, e); + if (e != BCExceptionNO) + return; + EmbedPositionDetectionPattern(matrix->GetWidth() - pdpWidth, 0, matrix, e); + if (e != BCExceptionNO) + return; + EmbedPositionDetectionPattern(0, matrix->GetWidth() - pdpWidth, matrix, e); + if (e != BCExceptionNO) + return; + int32_t hspWidth = 8; + EmbedHorizontalSeparationPattern(0, hspWidth - 1, matrix, e); + if (e != BCExceptionNO) + return; + EmbedHorizontalSeparationPattern(matrix->GetWidth() - hspWidth, hspWidth - 1, + matrix, e); + if (e != BCExceptionNO) + return; + EmbedHorizontalSeparationPattern(0, matrix->GetWidth() - hspWidth, matrix, e); + if (e != BCExceptionNO) + return; + int32_t vspSize = 7; + EmbedVerticalSeparationPattern(vspSize, 0, matrix, e); + if (e != BCExceptionNO) + return; + EmbedVerticalSeparationPattern(matrix->GetHeight() - vspSize - 1, 0, matrix, + e); + if (e != BCExceptionNO) + return; + EmbedVerticalSeparationPattern(vspSize, matrix->GetHeight() - vspSize, matrix, + e); + if (e != BCExceptionNO) + return; +} +void CBC_QRCoderMatrixUtil::MaybeEmbedPositionAdjustmentPatterns( + int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + if (!matrix) { + e = BCExceptionNullPointer; + return; + } + if (version < 2) { + return; + } + int32_t index = version - 1; + int32_t const* coordinates = + &(POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index][0]); + int32_t numCoordinate = 7; + for (int32_t i = 0; i < numCoordinate; i++) { + for (int32_t j = 0; j < numCoordinate; j++) { + int32_t y = coordinates[i]; + int32_t x = coordinates[j]; + if (x == -1 || y == -1) { + continue; + } + if (IsEmpty(matrix->Get(x, y))) { + EmbedPositionAdjustmentPattern(x - 2, y - 2, matrix, e); + if (e != BCExceptionNO) + return; + } + } + } +} +int32_t CBC_QRCoderMatrixUtil::FindMSBSet(int32_t value) { + int32_t numDigits = 0; + while (value != 0) { + value >>= 1; + ++numDigits; + } + return numDigits; +} +CBC_QRCoderMatrixUtil::CBC_QRCoderMatrixUtil() {} +CBC_QRCoderMatrixUtil::~CBC_QRCoderMatrixUtil() {} diff --git a/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h new file mode 100644 index 0000000000..3535c43c74 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h @@ -0,0 +1,87 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ + +class CBC_CommonByteMatrix; +class CBC_QRCoderErrorCorrectionLevel; +class CBC_QRCoderBitVector; +class CBC_QRCoderMatrixUtil { + private: + static const int32_t POSITION_DETECTION_PATTERN[7][7]; + static const int32_t VERTICAL_SEPARATION_PATTERN[7][1]; + static const int32_t HORIZONTAL_SEPARATION_PATTERN[1][8]; + static const int32_t POSITION_ADJUSTMENT_PATTERN[5][5]; + static const int32_t POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7]; + static const int32_t TYPE_INFO_COORDINATES[15][2]; + static const int32_t VERSION_INFO_POLY; + static const int32_t TYPE_INFO_POLY; + static const int32_t TYPE_INFO_MASK_PATTERN; + + public: + CBC_QRCoderMatrixUtil(); + virtual ~CBC_QRCoderMatrixUtil(); + static void ClearMatrix(CBC_CommonByteMatrix* matrix, int32_t& e); + static void BuildMatrix(CBC_QRCoderBitVector* dataBits, + CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t version, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedBasicPatterns(int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedTypeInfo(CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedDataBits(CBC_QRCoderBitVector* dataBits, + int32_t maskPattern, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void MaybeEmbedVersionInfo(int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static int32_t FindMSBSet(int32_t value); + static int32_t CalculateBCHCode(int32_t code, int32_t poly); + static void MakeTypeInfoBits(CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t maskPattern, + CBC_QRCoderBitVector* bits, + int32_t& e); + static void MakeVersionInfoBits(int32_t version, + CBC_QRCoderBitVector* bits, + int32_t& e); + static bool IsEmpty(int32_t value); + static bool IsValidValue(int32_t value); + static void EmbedTimingPatterns(CBC_CommonByteMatrix* matrix, int32_t& e); + static void EmbedDarkDotAtLeftBottomCorner(CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedHorizontalSeparationPattern(int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedVerticalSeparationPattern(int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedPositionAdjustmentPattern(int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedPositionDetectionPattern(int32_t xStart, + int32_t yStart, + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void EmbedPositionDetectionPatternsAndSeparators( + CBC_CommonByteMatrix* matrix, + int32_t& e); + static void MaybeEmbedPositionAdjustmentPatterns(int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderMode.cpp b/fxbarcode/qrcode/BC_QRCoderMode.cpp new file mode 100644 index 0000000000..3127145465 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMode.cpp @@ -0,0 +1,174 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderMode.h" + +#include <utility> + +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" +#include "fxbarcode/utils.h" + +CBC_QRCoderMode* CBC_QRCoderMode::sBYTE = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sNUMERIC = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sALPHANUMERIC = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sKANJI = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sECI = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sGBK = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sTERMINATOR = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sFNC1_FIRST_POSITION = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sFNC1_SECOND_POSITION = nullptr; +CBC_QRCoderMode* CBC_QRCoderMode::sSTRUCTURED_APPEND = nullptr; + +CBC_QRCoderMode::CBC_QRCoderMode(std::vector<int32_t> charCountBits, + int32_t bits, + CFX_ByteString name) + : m_characterCountBitsForVersions(std::move(charCountBits)), + m_bits(bits), + m_name(name) {} + +CBC_QRCoderMode::~CBC_QRCoderMode() {} + +void CBC_QRCoderMode::Initialize() { + sBYTE = new CBC_QRCoderMode({8, 16, 16}, 0x4, "BYTE"); + sALPHANUMERIC = new CBC_QRCoderMode({9, 11, 13}, 0x2, "ALPHANUMERIC"); + sECI = new CBC_QRCoderMode(std::vector<int32_t>(), 0x7, "ECI"); + sKANJI = new CBC_QRCoderMode({8, 10, 12}, 0x8, "KANJI"); + sNUMERIC = new CBC_QRCoderMode({10, 12, 14}, 0x1, "NUMERIC"); + sGBK = new CBC_QRCoderMode({8, 10, 12}, 0x0D, "GBK"); + sTERMINATOR = new CBC_QRCoderMode(std::vector<int32_t>(), 0x00, "TERMINATOR"); + sFNC1_FIRST_POSITION = + new CBC_QRCoderMode(std::vector<int32_t>(), 0x05, "FNC1_FIRST_POSITION"); + sFNC1_SECOND_POSITION = + new CBC_QRCoderMode(std::vector<int32_t>(), 0x09, "FNC1_SECOND_POSITION"); + sSTRUCTURED_APPEND = + new CBC_QRCoderMode(std::vector<int32_t>(), 0x03, "STRUCTURED_APPEND"); +} + +void CBC_QRCoderMode::Finalize() { + delete sBYTE; + delete sALPHANUMERIC; + delete sECI; + delete sKANJI; + delete sNUMERIC; + delete sGBK; + delete sTERMINATOR; + delete sFNC1_FIRST_POSITION; + delete sFNC1_SECOND_POSITION; + delete sSTRUCTURED_APPEND; +} + +CBC_QRCoderMode* CBC_QRCoderMode::ForBits(int32_t bits, int32_t& e) { + switch (bits) { + case 0x0: + return sTERMINATOR; + case 0x1: + return sNUMERIC; + case 0x2: + return sALPHANUMERIC; + case 0x3: + return sSTRUCTURED_APPEND; + case 0x4: + return sBYTE; + case 0x5: + return sFNC1_FIRST_POSITION; + case 0x7: + return sECI; + case 0x8: + return sKANJI; + case 0x9: + return sFNC1_SECOND_POSITION; + case 0x0D: + return sGBK; + default: + e = BCExceptionUnsupportedMode; + return nullptr; + } +} + +int32_t CBC_QRCoderMode::GetBits() const { + return m_bits; +} + +CFX_ByteString CBC_QRCoderMode::GetName() const { + return m_name; +} + +int32_t CBC_QRCoderMode::GetCharacterCountBits(CBC_QRCoderVersion* version, + int32_t& e) const { + if (m_characterCountBitsForVersions.empty()) { + e = BCExceptionCharacterNotThisMode; + return 0; + } + int32_t number = version->GetVersionNumber(); + int32_t offset; + if (number <= 9) { + offset = 0; + } else if (number <= 26) { + offset = 1; + } else { + offset = 2; + } + return m_characterCountBitsForVersions[offset]; +} + +void CBC_QRCoderMode::Destroy() { + if (sBYTE) { + delete CBC_QRCoderMode::sBYTE; + sBYTE = nullptr; + } + if (sNUMERIC) { + delete CBC_QRCoderMode::sNUMERIC; + sNUMERIC = nullptr; + } + if (sALPHANUMERIC) { + delete CBC_QRCoderMode::sALPHANUMERIC; + sALPHANUMERIC = nullptr; + } + if (sKANJI) { + delete CBC_QRCoderMode::sKANJI; + sKANJI = nullptr; + } + if (sECI) { + delete CBC_QRCoderMode::sECI; + sECI = nullptr; + } + if (sGBK) { + delete CBC_QRCoderMode::sGBK; + sGBK = nullptr; + } + if (sTERMINATOR) { + delete CBC_QRCoderMode::sTERMINATOR; + sTERMINATOR = nullptr; + } + if (sFNC1_FIRST_POSITION) { + delete CBC_QRCoderMode::sFNC1_FIRST_POSITION; + sFNC1_FIRST_POSITION = nullptr; + } + if (sFNC1_SECOND_POSITION) { + delete CBC_QRCoderMode::sFNC1_SECOND_POSITION; + sFNC1_SECOND_POSITION = nullptr; + } + if (sSTRUCTURED_APPEND) { + delete CBC_QRCoderMode::sSTRUCTURED_APPEND; + sSTRUCTURED_APPEND = nullptr; + } +} diff --git a/fxbarcode/qrcode/BC_QRCoderMode.h b/fxbarcode/qrcode/BC_QRCoderMode.h new file mode 100644 index 0000000000..4402e3fe26 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderMode.h @@ -0,0 +1,53 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERMODE_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMODE_H_ + +#include <stdint.h> + +#include <vector> + +#include "core/fxcrt/fx_string.h" + +class CBC_QRCoderVersion; + +class CBC_QRCoderMode { + public: + virtual ~CBC_QRCoderMode(); + + static void Initialize(); + static void Finalize(); + static CBC_QRCoderMode* ForBits(int32_t bits, int32_t& e); + static void Destroy(); + + int32_t GetCharacterCountBits(CBC_QRCoderVersion* version, int32_t& e) const; + int32_t GetBits() const; + CFX_ByteString GetName() const; + + static CBC_QRCoderMode* sBYTE; + static CBC_QRCoderMode* sNUMERIC; + static CBC_QRCoderMode* sALPHANUMERIC; + static CBC_QRCoderMode* sKANJI; + static CBC_QRCoderMode* sECI; + static CBC_QRCoderMode* sGBK; + static CBC_QRCoderMode* sTERMINATOR; + static CBC_QRCoderMode* sFNC1_FIRST_POSITION; + static CBC_QRCoderMode* sFNC1_SECOND_POSITION; + static CBC_QRCoderMode* sSTRUCTURED_APPEND; + + private: + CBC_QRCoderMode(); + CBC_QRCoderMode(std::vector<int32_t> charCountBits, + int32_t bits, + CFX_ByteString name); + + std::vector<int32_t> m_characterCountBitsForVersions; + const int32_t m_bits; + const CFX_ByteString m_name; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERMODE_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderVersion.cpp b/fxbarcode/qrcode/BC_QRCoderVersion.cpp new file mode 100644 index 0000000000..ff7cbc4007 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderVersion.cpp @@ -0,0 +1,794 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderECB.h" +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" +#include "fxbarcode/utils.h" + +namespace { + +const uint8_t BITS_SET_IN_HALF_BYTE[] = {0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4}; + +int32_t NumBitsDiffering(int32_t a, int32_t b) { + a ^= b; + return BITS_SET_IN_HALF_BYTE[a & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 4) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 8) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 12) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 16) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 20) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 24) & 0x0F] + + BITS_SET_IN_HALF_BYTE[(a >> 28) & 0x0F]; +} + +} // namespace + +const int32_t CBC_QRCoderVersion::VERSION_DECODE_INFO[] = { + 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, + 0x0E60D, 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, + 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, + 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, + 0x2379F, 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69}; + +std::vector<CBC_QRCoderVersion*>* CBC_QRCoderVersion::VERSION = nullptr; + +void CBC_QRCoderVersion::Initialize() { + VERSION = new std::vector<CBC_QRCoderVersion*>(); +} +void CBC_QRCoderVersion::Finalize() { + for (size_t i = 0; i < VERSION->size(); i++) + delete (*VERSION)[i]; + + delete VERSION; + VERSION = nullptr; +} +CBC_QRCoderVersion::CBC_QRCoderVersion(int32_t versionNumber, + CBC_QRCoderECBlocks* ecBlocks1, + CBC_QRCoderECBlocks* ecBlocks2, + CBC_QRCoderECBlocks* ecBlocks3, + CBC_QRCoderECBlocks* ecBlocks4) { + m_versionNumber = versionNumber; + m_ecBlocksArray.push_back(ecBlocks1); + m_ecBlocksArray.push_back(ecBlocks2); + m_ecBlocksArray.push_back(ecBlocks3); + m_ecBlocksArray.push_back(ecBlocks4); + int32_t total = 0; + int32_t ecCodeWords = ecBlocks1->GetECCodeWordsPerBlock(); + std::vector<CBC_QRCoderECB*>* ecbArray = ecBlocks1->GetECBlocks(); + for (size_t i = 0; i < ecbArray->size(); i++) { + CBC_QRCoderECB* ecBlock = (*ecbArray)[i]; + total += ecBlock->GetCount() * (ecBlock->GetDataCodeWords() + ecCodeWords); + } + m_totalCodeWords = total; + switch (versionNumber) { + case 1: + break; + case 2: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(18); + break; + case 3: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(22); + break; + case 4: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + break; + case 5: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + break; + case 6: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + break; + case 7: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(22); + m_alignmentPatternCenters.push_back(38); + break; + case 8: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(24); + m_alignmentPatternCenters.push_back(42); + break; + case 9: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(46); + break; + case 10: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(28); + m_alignmentPatternCenters.push_back(50); + break; + case 11: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(54); + break; + case 12: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(32); + m_alignmentPatternCenters.push_back(58); + break; + case 13: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + m_alignmentPatternCenters.push_back(62); + break; + case 14: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(46); + m_alignmentPatternCenters.push_back(66); + break; + case 15: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(48); + m_alignmentPatternCenters.push_back(70); + break; + case 16: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(50); + m_alignmentPatternCenters.push_back(74); + break; + case 17: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(78); + break; + case 18: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(56); + m_alignmentPatternCenters.push_back(82); + break; + case 19: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(86); + break; + case 20: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + m_alignmentPatternCenters.push_back(62); + m_alignmentPatternCenters.push_back(90); + break; + case 21: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(28); + m_alignmentPatternCenters.push_back(50); + m_alignmentPatternCenters.push_back(72); + m_alignmentPatternCenters.push_back(94); + break; + case 22: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(50); + m_alignmentPatternCenters.push_back(74); + m_alignmentPatternCenters.push_back(98); + break; + case 23: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(74); + m_alignmentPatternCenters.push_back(102); + break; + case 24: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(28); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(80); + m_alignmentPatternCenters.push_back(106); + break; + case 25: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(32); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(84); + m_alignmentPatternCenters.push_back(110); + break; + case 26: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(86); + m_alignmentPatternCenters.push_back(114); + break; + case 27: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + m_alignmentPatternCenters.push_back(62); + m_alignmentPatternCenters.push_back(90); + m_alignmentPatternCenters.push_back(118); + break; + case 28: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(50); + m_alignmentPatternCenters.push_back(74); + m_alignmentPatternCenters.push_back(98); + m_alignmentPatternCenters.push_back(122); + break; + case 29: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(78); + m_alignmentPatternCenters.push_back(102); + m_alignmentPatternCenters.push_back(126); + break; + case 30: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(52); + m_alignmentPatternCenters.push_back(78); + m_alignmentPatternCenters.push_back(104); + m_alignmentPatternCenters.push_back(130); + break; + case 31: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(56); + m_alignmentPatternCenters.push_back(82); + m_alignmentPatternCenters.push_back(108); + m_alignmentPatternCenters.push_back(134); + break; + case 32: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + m_alignmentPatternCenters.push_back(60); + m_alignmentPatternCenters.push_back(86); + m_alignmentPatternCenters.push_back(112); + m_alignmentPatternCenters.push_back(138); + break; + case 33: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(86); + m_alignmentPatternCenters.push_back(114); + m_alignmentPatternCenters.push_back(142); + break; + case 34: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(34); + m_alignmentPatternCenters.push_back(62); + m_alignmentPatternCenters.push_back(90); + m_alignmentPatternCenters.push_back(118); + m_alignmentPatternCenters.push_back(146); + break; + case 35: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(78); + m_alignmentPatternCenters.push_back(102); + m_alignmentPatternCenters.push_back(126); + m_alignmentPatternCenters.push_back(150); + break; + case 36: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(24); + m_alignmentPatternCenters.push_back(50); + m_alignmentPatternCenters.push_back(76); + m_alignmentPatternCenters.push_back(102); + m_alignmentPatternCenters.push_back(128); + m_alignmentPatternCenters.push_back(154); + break; + case 37: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(28); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(80); + m_alignmentPatternCenters.push_back(106); + m_alignmentPatternCenters.push_back(132); + m_alignmentPatternCenters.push_back(158); + break; + case 38: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(32); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(84); + m_alignmentPatternCenters.push_back(110); + m_alignmentPatternCenters.push_back(136); + m_alignmentPatternCenters.push_back(162); + break; + case 39: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(26); + m_alignmentPatternCenters.push_back(54); + m_alignmentPatternCenters.push_back(82); + m_alignmentPatternCenters.push_back(110); + m_alignmentPatternCenters.push_back(138); + m_alignmentPatternCenters.push_back(166); + break; + case 40: + m_alignmentPatternCenters.push_back(6); + m_alignmentPatternCenters.push_back(30); + m_alignmentPatternCenters.push_back(58); + m_alignmentPatternCenters.push_back(86); + m_alignmentPatternCenters.push_back(114); + m_alignmentPatternCenters.push_back(142); + m_alignmentPatternCenters.push_back(170); + break; + } +} + +CBC_QRCoderVersion::~CBC_QRCoderVersion() { + for (size_t i = 0; i < m_ecBlocksArray.size(); ++i) + delete m_ecBlocksArray[i]; +} + +int32_t CBC_QRCoderVersion::GetVersionNumber() { + return m_versionNumber; +} +std::vector<int32_t>* CBC_QRCoderVersion::GetAlignmentPatternCenters() { + return &m_alignmentPatternCenters; +} +int32_t CBC_QRCoderVersion::GetTotalCodeWords() { + return m_totalCodeWords; +} +int32_t CBC_QRCoderVersion::GetDimensionForVersion() { + return 17 + 4 * m_versionNumber; +} +CBC_QRCoderECBlocks* CBC_QRCoderVersion::GetECBlocksForLevel( + CBC_QRCoderErrorCorrectionLevel* ecLevel) { + return m_ecBlocksArray[ecLevel->Ordinal()]; +} +CBC_QRCoderVersion* CBC_QRCoderVersion::GetProvisionalVersionForDimension( + int32_t dimension, + int32_t& e) { + if ((dimension % 4) != 1) { + e = BCExceptionRead; + return nullptr; + } + CBC_QRCoderVersion* qcv = GetVersionForNumber((dimension - 17) >> 2, e); + if (e != BCExceptionNO) + return nullptr; + return qcv; +} +CBC_QRCoderVersion* CBC_QRCoderVersion::DecodeVersionInformation( + int32_t versionBits, + int32_t& e) { + int32_t bestDifference = FXSYS_IntMax; + int32_t bestVersion = 0; + for (int32_t i = 0; i < 34; i++) { + int32_t targetVersion = VERSION_DECODE_INFO[i]; + if (targetVersion == versionBits) { + CBC_QRCoderVersion* qcv = GetVersionForNumber(i + 7, e); + if (e != BCExceptionNO) + return nullptr; + return qcv; + } + int32_t bitsDifference = NumBitsDiffering(versionBits, targetVersion); + if (bitsDifference < bestDifference) { + bestVersion = i + 7; + bestDifference = bitsDifference; + } + } + if (bestDifference <= 3) { + CBC_QRCoderVersion* qcv = GetVersionForNumber(bestVersion, e); + if (e != BCExceptionNO) + return nullptr; + return qcv; + } + return nullptr; +} +CBC_CommonBitMatrix* CBC_QRCoderVersion::BuildFunctionPattern(int32_t& e) { + int32_t dimension = GetDimensionForVersion(); + CBC_CommonBitMatrix* bitMatrix = new CBC_CommonBitMatrix(); + bitMatrix->Init(dimension); + bitMatrix->SetRegion(0, 0, 9, 9, e); + if (e != BCExceptionNO) + return nullptr; + bitMatrix->SetRegion(dimension - 8, 0, 8, 9, e); + if (e != BCExceptionNO) + return nullptr; + bitMatrix->SetRegion(0, dimension - 8, 9, 8, e); + if (e != BCExceptionNO) + return nullptr; + size_t max = m_alignmentPatternCenters.size(); + for (size_t x = 0; x < max; x++) { + int32_t i = m_alignmentPatternCenters[x] - 2; + for (size_t y = 0; y < max; y++) { + if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) { + continue; + } + bitMatrix->SetRegion(m_alignmentPatternCenters[y] - 2, i, 5, 5, e); + if (e != BCExceptionNO) + return nullptr; + } + } + bitMatrix->SetRegion(6, 9, 1, dimension - 17, e); + if (e != BCExceptionNO) + return nullptr; + bitMatrix->SetRegion(9, 6, dimension - 17, 1, e); + if (e != BCExceptionNO) + return nullptr; + if (m_versionNumber > 6) { + bitMatrix->SetRegion(dimension - 11, 0, 3, 6, e); + if (e != BCExceptionNO) + return nullptr; + bitMatrix->SetRegion(0, dimension - 11, 6, 3, e); + if (e != BCExceptionNO) + return nullptr; + } + return bitMatrix; +} +CBC_QRCoderVersion* CBC_QRCoderVersion::GetVersionForNumber( + int32_t versionNumber, + int32_t& e) { + if (VERSION->empty()) { + VERSION->push_back(new CBC_QRCoderVersion( + 1, new CBC_QRCoderECBlocks(7, new CBC_QRCoderECB(1, 19)), + new CBC_QRCoderECBlocks(10, new CBC_QRCoderECB(1, 16)), + new CBC_QRCoderECBlocks(13, new CBC_QRCoderECB(1, 13)), + new CBC_QRCoderECBlocks(17, new CBC_QRCoderECB(1, 9)))); + VERSION->push_back(new CBC_QRCoderVersion( + 2, new CBC_QRCoderECBlocks(10, new CBC_QRCoderECB(1, 34)), + new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(1, 28)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(1, 22)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 3, new CBC_QRCoderECBlocks(15, new CBC_QRCoderECB(1, 55)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(1, 44)), + new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 17)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 4, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(1, 80)), + new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 32)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(2, 24)), + new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(4, 9)))); + VERSION->push_back(new CBC_QRCoderVersion( + 5, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(1, 108)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 43)), + new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 15), + new CBC_QRCoderECB(2, 16)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 11), + new CBC_QRCoderECB(2, 12)))); + VERSION->push_back(new CBC_QRCoderVersion( + 6, new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 68)), + new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(4, 27)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 19)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 15)))); + VERSION->push_back(new CBC_QRCoderVersion( + 7, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(2, 78)), + new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(4, 31)), + new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 14), + new CBC_QRCoderECB(4, 15)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 13), + new CBC_QRCoderECB(1, 14)))); + VERSION->push_back(new CBC_QRCoderVersion( + 8, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 97)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 38), + new CBC_QRCoderECB(2, 39)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(4, 18), + new CBC_QRCoderECB(2, 19)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 14), + new CBC_QRCoderECB(2, 15)))); + VERSION->push_back(new CBC_QRCoderVersion( + 9, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(2, 116)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(3, 36), + new CBC_QRCoderECB(2, 37)), + new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(4, 16), + new CBC_QRCoderECB(4, 17)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 12), + new CBC_QRCoderECB(4, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 10, new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 68), + new CBC_QRCoderECB(2, 69)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 43), + new CBC_QRCoderECB(1, 44)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(6, 19), + new CBC_QRCoderECB(2, 20)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 15), + new CBC_QRCoderECB(2, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 11, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(4, 81)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(1, 50), + new CBC_QRCoderECB(4, 51)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 22), + new CBC_QRCoderECB(4, 23)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(3, 12), + new CBC_QRCoderECB(8, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 12, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 92), + new CBC_QRCoderECB(2, 93)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(6, 36), + new CBC_QRCoderECB(2, 37)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 20), + new CBC_QRCoderECB(6, 21)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(7, 14), + new CBC_QRCoderECB(4, 15)))); + VERSION->push_back(new CBC_QRCoderVersion( + 13, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 107)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(8, 37), + new CBC_QRCoderECB(1, 38)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(8, 20), + new CBC_QRCoderECB(4, 21)), + new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(12, 11), + new CBC_QRCoderECB(4, 12)))); + VERSION->push_back(new CBC_QRCoderVersion( + 14, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 115), + new CBC_QRCoderECB(1, 116)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 40), + new CBC_QRCoderECB(5, 41)), + new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(11, 16), + new CBC_QRCoderECB(5, 17)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(11, 12), + new CBC_QRCoderECB(5, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 15, new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(5, 87), + new CBC_QRCoderECB(1, 88)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(5, 41), + new CBC_QRCoderECB(5, 42)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 24), + new CBC_QRCoderECB(7, 25)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(11, 12), + new CBC_QRCoderECB(7, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 16, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(5, 98), + new CBC_QRCoderECB(1, 99)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(7, 45), + new CBC_QRCoderECB(3, 46)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(15, 19), + new CBC_QRCoderECB(2, 20)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 15), + new CBC_QRCoderECB(13, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 17, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 107), + new CBC_QRCoderECB(5, 108)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 46), + new CBC_QRCoderECB(1, 47)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 22), + new CBC_QRCoderECB(15, 23)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 14), + new CBC_QRCoderECB(17, 15)))); + VERSION->push_back(new CBC_QRCoderVersion( + 18, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 120), + new CBC_QRCoderECB(1, 121)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(9, 43), + new CBC_QRCoderECB(4, 44)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 22), + new CBC_QRCoderECB(1, 23)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 14), + new CBC_QRCoderECB(19, 15)))); + VERSION->push_back(new CBC_QRCoderVersion( + 19, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 113), + new CBC_QRCoderECB(4, 114)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(3, 44), + new CBC_QRCoderECB(11, 45)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(17, 21), + new CBC_QRCoderECB(4, 22)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(9, 13), + new CBC_QRCoderECB(16, 14)))); + VERSION->push_back(new CBC_QRCoderVersion( + 20, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 107), + new CBC_QRCoderECB(5, 108)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(3, 41), + new CBC_QRCoderECB(13, 42)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(15, 24), + new CBC_QRCoderECB(5, 25)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(15, 15), + new CBC_QRCoderECB(10, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 21, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 116), + new CBC_QRCoderECB(4, 117)), + new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(17, 42)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 22), + new CBC_QRCoderECB(6, 23)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 16), + new CBC_QRCoderECB(6, 17)))); + VERSION->push_back(new CBC_QRCoderVersion( + 22, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 111), + new CBC_QRCoderECB(7, 112)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 46)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 24), + new CBC_QRCoderECB(16, 25)), + new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(34, 13)))); + VERSION->push_back(new CBC_QRCoderVersion( + 23, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 121), + new CBC_QRCoderECB(5, 122)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 47), + new CBC_QRCoderECB(14, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 24), + new CBC_QRCoderECB(14, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(16, 15), + new CBC_QRCoderECB(14, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 24, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(6, 117), + new CBC_QRCoderECB(4, 118)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 45), + new CBC_QRCoderECB(14, 46)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 24), + new CBC_QRCoderECB(16, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(30, 16), + new CBC_QRCoderECB(2, 17)))); + VERSION->push_back(new CBC_QRCoderVersion( + 25, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(8, 106), + new CBC_QRCoderECB(4, 107)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(8, 47), + new CBC_QRCoderECB(13, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 24), + new CBC_QRCoderECB(22, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(22, 15), + new CBC_QRCoderECB(13, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 26, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 114), + new CBC_QRCoderECB(2, 115)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(19, 46), + new CBC_QRCoderECB(4, 47)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(28, 22), + new CBC_QRCoderECB(6, 23)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(33, 16), + new CBC_QRCoderECB(4, 17)))); + VERSION->push_back(new CBC_QRCoderVersion( + 27, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(8, 122), + new CBC_QRCoderECB(4, 123)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(22, 45), + new CBC_QRCoderECB(3, 46)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(8, 23), + new CBC_QRCoderECB(26, 24)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(12, 15), + new CBC_QRCoderECB(28, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 28, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 117), + new CBC_QRCoderECB(10, 118)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 45), + new CBC_QRCoderECB(23, 46)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 24), + new CBC_QRCoderECB(31, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 15), + new CBC_QRCoderECB(31, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 29, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 116), + new CBC_QRCoderECB(7, 117)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(21, 45), + new CBC_QRCoderECB(7, 46)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(1, 23), + new CBC_QRCoderECB(37, 24)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 15), + new CBC_QRCoderECB(26, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 30, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 115), + new CBC_QRCoderECB(10, 116)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(19, 47), + new CBC_QRCoderECB(10, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(15, 24), + new CBC_QRCoderECB(25, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(23, 15), + new CBC_QRCoderECB(25, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 31, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(13, 115), + new CBC_QRCoderECB(3, 116)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 46), + new CBC_QRCoderECB(29, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(42, 24), + new CBC_QRCoderECB(1, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(23, 15), + new CBC_QRCoderECB(28, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 32, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 115)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 46), + new CBC_QRCoderECB(23, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(10, 24), + new CBC_QRCoderECB(35, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 15), + new CBC_QRCoderECB(35, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 33, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 115), + new CBC_QRCoderECB(1, 116)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(14, 46), + new CBC_QRCoderECB(21, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(29, 24), + new CBC_QRCoderECB(19, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 15), + new CBC_QRCoderECB(46, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 34, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(13, 115), + new CBC_QRCoderECB(6, 116)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(14, 46), + new CBC_QRCoderECB(23, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(44, 24), + new CBC_QRCoderECB(7, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(59, 16), + new CBC_QRCoderECB(1, 17)))); + VERSION->push_back(new CBC_QRCoderVersion( + 35, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(12, 121), + new CBC_QRCoderECB(7, 122)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(12, 47), + new CBC_QRCoderECB(26, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(39, 24), + new CBC_QRCoderECB(14, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(22, 15), + new CBC_QRCoderECB(41, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 36, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(6, 121), + new CBC_QRCoderECB(14, 122)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 47), + new CBC_QRCoderECB(34, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(46, 24), + new CBC_QRCoderECB(10, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(2, 15), + new CBC_QRCoderECB(64, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 37, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 122), + new CBC_QRCoderECB(4, 123)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(29, 46), + new CBC_QRCoderECB(14, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(49, 24), + new CBC_QRCoderECB(10, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(24, 15), + new CBC_QRCoderECB(46, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 38, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 122), + new CBC_QRCoderECB(18, 123)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(13, 46), + new CBC_QRCoderECB(32, 47)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(48, 24), + new CBC_QRCoderECB(14, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(42, 15), + new CBC_QRCoderECB(32, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 39, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(20, 117), + new CBC_QRCoderECB(4, 118)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(40, 47), + new CBC_QRCoderECB(7, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(43, 24), + new CBC_QRCoderECB(22, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(10, 15), + new CBC_QRCoderECB(67, 16)))); + VERSION->push_back(new CBC_QRCoderVersion( + 40, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 118), + new CBC_QRCoderECB(6, 119)), + new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(18, 47), + new CBC_QRCoderECB(31, 48)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(34, 24), + new CBC_QRCoderECB(34, 25)), + new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(20, 15), + new CBC_QRCoderECB(61, 16)))); + } + if (versionNumber < 1 || versionNumber > 40) { + e = BCExceptionIllegalArgument; + return nullptr; + } + return (*VERSION)[versionNumber - 1]; +} + +void CBC_QRCoderVersion::Destroy() { + for (size_t i = 0; i < VERSION->size(); i++) + delete (*VERSION)[i]; + VERSION->clear(); +} diff --git a/fxbarcode/qrcode/BC_QRCoderVersion.h b/fxbarcode/qrcode/BC_QRCoderVersion.h new file mode 100644 index 0000000000..78ded0d30c --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderVersion.h @@ -0,0 +1,57 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ +#define FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ + +#include <vector> + +#include "core/fxcrt/fx_basic.h" + +class CBC_CommonBitMatrix; +class CBC_QRCoderECBlocks; +class CBC_QRCoderErrorCorrectionLevel; + +class CBC_QRCoderVersion { + public: + virtual ~CBC_QRCoderVersion(); + static void Initialize(); + static void Finalize(); + + int32_t GetVersionNumber(); + int32_t GetTotalCodeWords(); + int32_t GetDimensionForVersion(); + CBC_CommonBitMatrix* BuildFunctionPattern(int32_t& e); + std::vector<int32_t>* GetAlignmentPatternCenters(); + CBC_QRCoderECBlocks* GetECBlocksForLevel( + CBC_QRCoderErrorCorrectionLevel* ecLevel); + static CBC_QRCoderVersion* GetVersionForNumber(int32_t versionNumber, + int32_t& e); + static CBC_QRCoderVersion* GetProvisionalVersionForDimension( + int32_t dimension, + int32_t& e); + static CBC_QRCoderVersion* DecodeVersionInformation(int32_t versionBits, + int32_t& e); + static void Destroy(); + + private: + CBC_QRCoderVersion(); + CBC_QRCoderVersion(int32_t versionNumber, + CBC_QRCoderECBlocks* ecBlocks1, + CBC_QRCoderECBlocks* ecBlocks2, + CBC_QRCoderECBlocks* ecBlocks3, + CBC_QRCoderECBlocks* ecBlocks4); + + static const int32_t VERSION_DECODE_INFO[34]; + static std::vector<CBC_QRCoderVersion*>* VERSION; + + int32_t m_versionNumber; + int32_t m_totalCodeWords; + std::vector<int32_t> m_alignmentPatternCenters; + std::vector<CBC_QRCoderECBlocks*> m_ecBlocksArray; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ |