diff options
Diffstat (limited to 'fxbarcode/qrcode/BC_QRCoderEncoder.cpp')
-rw-r--r-- | fxbarcode/qrcode/BC_QRCoderEncoder.cpp | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/fxbarcode/qrcode/BC_QRCoderEncoder.cpp b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp index fe911f8635..052ad49a05 100644 --- a/fxbarcode/qrcode/BC_QRCoderEncoder.cpp +++ b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp @@ -28,13 +28,11 @@ #include <vector> #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" @@ -46,6 +44,11 @@ using ModeStringPair = std::pair<CBC_QRCoderMode*, ByteString>; namespace { +struct QRCoderBlockPair { + std::vector<uint8_t> data; + std::vector<uint8_t> ecc; +}; + // This is a mapping for an ASCII table, starting at an index of 32. const int8_t g_alphaNumericTable[] = { 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 32-47 @@ -222,20 +225,20 @@ bool InitQRCode(int32_t numInputBytes, return false; } -std::unique_ptr<CBC_CommonByteArray> GenerateECBytes( - CBC_CommonByteArray* dataBytes, - int32_t numEcBytesInBlock) { - 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(); - if (!encode.Encode(&toEncode, numEcBytesInBlock)) - return nullptr; - auto ecBytes = pdfium::MakeUnique<CBC_CommonByteArray>(numEcBytesInBlock); - for (int32_t i = 0; i < numEcBytesInBlock; ++i) - ecBytes->Set(i, toEncode[numDataBytes + i]); +std::vector<uint8_t> GenerateECBytes(const std::vector<uint8_t>& dataBytes, + size_t numEcBytesInBlock) { + // If |numEcBytesInBlock| is 0, the encoder will fail anyway. + ASSERT(numEcBytesInBlock > 0); + std::vector<int32_t> toEncode(dataBytes.size() + numEcBytesInBlock); + std::copy(dataBytes.begin(), dataBytes.end(), toEncode.begin()); + + std::vector<uint8_t> ecBytes; + CBC_ReedSolomonEncoder encoder(CBC_ReedSolomonGF256::QRCodeField); + if (encoder.Encode(&toEncode, numEcBytesInBlock)) { + ecBytes = std::vector<uint8_t>(toEncode.begin() + dataBytes.size(), + toEncode.end()); + ASSERT(ecBytes.size() == static_cast<size_t>(numEcBytesInBlock)); + } return ecBytes; } @@ -272,8 +275,8 @@ void GetNumDataBytesAndNumECBytesForBlockID(int32_t numTotalBytes, int32_t numDataBytes, int32_t numRSBlocks, int32_t blockID, - int32_t& numDataBytesInBlock, - int32_t& numECBytesInBlock) { + int32_t* numDataBytesInBlock, + int32_t* numECBytesInBlock) { if (blockID >= numRSBlocks) return; @@ -286,11 +289,11 @@ void GetNumDataBytesAndNumECBytesForBlockID(int32_t numTotalBytes, int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; if (blockID < numRsBlocksInGroup1) { - numDataBytesInBlock = numDataBytesInGroup1; - numECBytesInBlock = numEcBytesInGroup1; + *numDataBytesInBlock = numDataBytesInGroup1; + *numECBytesInBlock = numEcBytesInGroup1; } else { - numDataBytesInBlock = numDataBytesInGroup2; - numECBytesInBlock = numEcBytesInGroup2; + *numDataBytesInBlock = numDataBytesInGroup2; + *numECBytesInBlock = numEcBytesInGroup2; } } @@ -411,42 +414,47 @@ bool InterleaveWithECBytes(CBC_QRCoderBitVector* bits, return false; int32_t dataBytesOffset = 0; - int32_t maxNumDataBytes = 0; - int32_t maxNumEcBytes = 0; - std::vector<CBC_QRCoderBlockPair> blocks(numRSBlocks); + size_t maxNumDataBytes = 0; + size_t maxNumEcBytes = 0; + std::vector<QRCoderBlockPair> blocks(numRSBlocks); for (int32_t i = 0; i < numRSBlocks; i++) { int32_t numDataBytesInBlock; - int32_t numEcBytesInBlosk; + int32_t numEcBytesInBlock; GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, - numRSBlocks, i, numDataBytesInBlock, - numEcBytesInBlosk); - auto dataBytes = pdfium::MakeUnique<CBC_CommonByteArray>(); - dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock); - std::unique_ptr<CBC_CommonByteArray> ecBytes = - GenerateECBytes(dataBytes.get(), numEcBytesInBlosk); - if (!ecBytes) + numRSBlocks, i, &numDataBytesInBlock, + &numEcBytesInBlock); + if (numDataBytesInBlock < 0 || numEcBytesInBlock <= 0) + return false; + + std::vector<uint8_t> dataBytes(numDataBytesInBlock); + memcpy(dataBytes.data(), bits->GetArray() + dataBytesOffset, + numDataBytesInBlock); + std::vector<uint8_t> ecBytes = + GenerateECBytes(dataBytes, numEcBytesInBlock); + if (ecBytes.empty()) return false; - maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size()); - maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size()); - blocks[i].SetData(std::move(dataBytes), std::move(ecBytes)); + maxNumDataBytes = std::max(maxNumDataBytes, dataBytes.size()); + maxNumEcBytes = std::max(maxNumEcBytes, ecBytes.size()); + blocks[i].data = std::move(dataBytes); + blocks[i].ecc = std::move(ecBytes); dataBytesOffset += numDataBytesInBlock; } if (numDataBytes != dataBytesOffset) return false; - for (int32_t x = 0; x < maxNumDataBytes; x++) { + for (size_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); + const std::vector<uint8_t>& dataBytes = blocks[j].data; + if (x < dataBytes.size()) + result->AppendBits(dataBytes[x], 8); } } - for (int32_t y = 0; y < maxNumEcBytes; y++) { + for (size_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); + const std::vector<uint8_t>& ecBytes = blocks[l].ecc; + if (y < ecBytes.size()) + result->AppendBits(ecBytes[y], 8); } } return static_cast<size_t>(numTotalBytes) == result->sizeInBytes(); |