| Index: xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.cpp
|
| diff --git a/xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.cpp b/xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.cpp
|
| index 1628f68db7b34d3597b080aecb40a1186e73b5a7..4a3e2447f450537265388bde5de21b3adfe05b8c 100644
|
| --- a/xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.cpp
|
| +++ b/xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.cpp
|
| @@ -1,492 +1,492 @@
|
| -// 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 2009 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 "BC_PDF417DecodedBitStreamParser.h"
|
| -
|
| -#include <stdlib.h>
|
| -
|
| -#include "xfa/src/fxbarcode/BC_DecoderResult.h"
|
| -#include "xfa/src/fxbarcode/barcode.h"
|
| -#include "xfa/src/fxbarcode/common/BC_CommonDecoderResult.h"
|
| -#include "BC_PDF417ResultMetadata.h"
|
| -#include "third_party/bigint/BigIntegerLibrary.hh"
|
| -
|
| -#define TEXT_COMPACTION_MODE_LATCH 900
|
| -#define BYTE_COMPACTION_MODE_LATCH 901
|
| -#define NUMERIC_COMPACTION_MODE_LATCH 902
|
| -#define BYTE_COMPACTION_MODE_LATCH_6 924
|
| -#define BEGIN_MACRO_PDF417_CONTROL_BLOCK 928
|
| -#define BEGIN_MACRO_PDF417_OPTIONAL_FIELD 923
|
| -#define MACRO_PDF417_TERMINATOR 922
|
| -#define MODE_SHIFT_TO_BYTE_COMPACTION_MODE 913
|
| -
|
| -int32_t CBC_DecodedBitStreamPaser::MAX_NUMERIC_CODEWORDS = 15;
|
| -int32_t CBC_DecodedBitStreamPaser::NUMBER_OF_SEQUENCE_CODEWORDS = 2;
|
| -int32_t CBC_DecodedBitStreamPaser::PL = 25;
|
| -int32_t CBC_DecodedBitStreamPaser::LL = 27;
|
| -int32_t CBC_DecodedBitStreamPaser::AS = 27;
|
| -int32_t CBC_DecodedBitStreamPaser::ML = 28;
|
| -int32_t CBC_DecodedBitStreamPaser::AL = 28;
|
| -int32_t CBC_DecodedBitStreamPaser::PS = 29;
|
| -int32_t CBC_DecodedBitStreamPaser::PAL = 29;
|
| -FX_CHAR CBC_DecodedBitStreamPaser::PUNCT_CHARS[29] = {
|
| - ';', '<', '>', '@', '[', '\\', '}', '_', '`', '~',
|
| - '!', '\r', '\t', ',', ':', '\n', '-', '.', '$', '/',
|
| - '"', '|', '*', '(', ')', '?', '{', '}', '\''};
|
| -FX_CHAR CBC_DecodedBitStreamPaser::MIXED_CHARS[30] = {
|
| - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', '\r', '\t',
|
| - ',', ':', '#', '-', '.', '$', '/', '+', '%', '*', '=', '^'};
|
| -void CBC_DecodedBitStreamPaser::Initialize() {}
|
| -void CBC_DecodedBitStreamPaser::Finalize() {}
|
| -CBC_DecodedBitStreamPaser::CBC_DecodedBitStreamPaser() {}
|
| -CBC_DecodedBitStreamPaser::~CBC_DecodedBitStreamPaser() {}
|
| -CBC_CommonDecoderResult* CBC_DecodedBitStreamPaser::decode(
|
| - CFX_Int32Array& codewords,
|
| - CFX_ByteString ecLevel,
|
| - int32_t& e) {
|
| - CFX_ByteString result;
|
| - int32_t codeIndex = 1;
|
| - int32_t code = codewords.GetAt(codeIndex);
|
| - codeIndex++;
|
| - CBC_PDF417ResultMetadata* resultMetadata = new CBC_PDF417ResultMetadata;
|
| - while (codeIndex < codewords[0]) {
|
| - switch (code) {
|
| - case TEXT_COMPACTION_MODE_LATCH:
|
| - codeIndex = textCompaction(codewords, codeIndex, result);
|
| - break;
|
| - case BYTE_COMPACTION_MODE_LATCH:
|
| - codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| - break;
|
| - case NUMERIC_COMPACTION_MODE_LATCH:
|
| - codeIndex = numericCompaction(codewords, codeIndex, result, e);
|
| - BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
|
| - break;
|
| - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE:
|
| - codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| - break;
|
| - case BYTE_COMPACTION_MODE_LATCH_6:
|
| - codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| - break;
|
| - case BEGIN_MACRO_PDF417_CONTROL_BLOCK:
|
| - codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata, e);
|
| - if (e != BCExceptionNO) {
|
| - delete resultMetadata;
|
| - return NULL;
|
| - }
|
| - break;
|
| - default:
|
| - codeIndex--;
|
| - codeIndex = textCompaction(codewords, codeIndex, result);
|
| - break;
|
| - }
|
| - if (codeIndex < codewords.GetSize()) {
|
| - code = codewords[codeIndex++];
|
| - } else {
|
| - e = BCExceptionFormatInstance;
|
| - delete resultMetadata;
|
| - return NULL;
|
| - }
|
| - }
|
| - if (result.GetLength() == 0) {
|
| - e = BCExceptionFormatInstance;
|
| - delete resultMetadata;
|
| - return NULL;
|
| - }
|
| - CFX_ByteArray rawBytes;
|
| - CFX_PtrArray byteSegments;
|
| - CBC_CommonDecoderResult* tempCd = new CBC_CommonDecoderResult();
|
| - tempCd->Init(rawBytes, result, byteSegments, ecLevel, e);
|
| - if (e != BCExceptionNO) {
|
| - delete resultMetadata;
|
| - return NULL;
|
| - }
|
| - tempCd->setOther(resultMetadata);
|
| - return tempCd;
|
| -}
|
| -int32_t CBC_DecodedBitStreamPaser::decodeMacroBlock(
|
| - CFX_Int32Array& codewords,
|
| - int32_t codeIndex,
|
| - CBC_PDF417ResultMetadata* resultMetadata,
|
| - int32_t& e) {
|
| - if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {
|
| - e = BCExceptionFormatInstance;
|
| - return -1;
|
| - }
|
| - CFX_Int32Array segmentIndexArray;
|
| - segmentIndexArray.SetSize(NUMBER_OF_SEQUENCE_CODEWORDS);
|
| - for (int32_t i = 0; i < NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {
|
| - segmentIndexArray.SetAt(i, codewords[codeIndex]);
|
| - }
|
| - CFX_ByteString str =
|
| - decodeBase900toBase10(segmentIndexArray, NUMBER_OF_SEQUENCE_CODEWORDS, e);
|
| - BC_EXCEPTION_CHECK_ReturnValue(e, -1);
|
| - resultMetadata->setSegmentIndex(atoi(str.GetBuffer(str.GetLength())));
|
| - CFX_ByteString fileId;
|
| - codeIndex = textCompaction(codewords, codeIndex, fileId);
|
| - resultMetadata->setFileId(fileId);
|
| - if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {
|
| - codeIndex++;
|
| - CFX_Int32Array additionalOptionCodeWords;
|
| - additionalOptionCodeWords.SetSize(codewords[0] - codeIndex);
|
| - int32_t additionalOptionCodeWordsIndex = 0;
|
| - FX_BOOL end = FALSE;
|
| - while ((codeIndex < codewords[0]) && !end) {
|
| - int32_t code = codewords[codeIndex++];
|
| - if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| - additionalOptionCodeWords[additionalOptionCodeWordsIndex++] = code;
|
| - } else {
|
| - switch (code) {
|
| - case MACRO_PDF417_TERMINATOR:
|
| - resultMetadata->setLastSegment(TRUE);
|
| - codeIndex++;
|
| - end = TRUE;
|
| - break;
|
| - default:
|
| - e = BCExceptionFormatInstance;
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| - CFX_Int32Array array;
|
| - array.SetSize(additionalOptionCodeWordsIndex);
|
| - array.Copy(additionalOptionCodeWords);
|
| - resultMetadata->setOptionalData(array);
|
| - } else if (codewords[codeIndex] == MACRO_PDF417_TERMINATOR) {
|
| - resultMetadata->setLastSegment(TRUE);
|
| - codeIndex++;
|
| - }
|
| - return codeIndex;
|
| -}
|
| -int32_t CBC_DecodedBitStreamPaser::textCompaction(CFX_Int32Array& codewords,
|
| - int32_t codeIndex,
|
| - CFX_ByteString& result) {
|
| - CFX_Int32Array textCompactionData;
|
| - textCompactionData.SetSize((codewords[0] - codeIndex) << 1);
|
| - CFX_Int32Array byteCompactionData;
|
| - byteCompactionData.SetSize((codewords[0] - codeIndex) << 1);
|
| - int32_t index = 0;
|
| - FX_BOOL end = FALSE;
|
| - while ((codeIndex < codewords[0]) && !end) {
|
| - int32_t code = codewords[codeIndex++];
|
| - if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| - textCompactionData[index] = code / 30;
|
| - textCompactionData[index + 1] = code % 30;
|
| - index += 2;
|
| - } else {
|
| - switch (code) {
|
| - case TEXT_COMPACTION_MODE_LATCH:
|
| - textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH;
|
| - break;
|
| - case BYTE_COMPACTION_MODE_LATCH:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - case NUMERIC_COMPACTION_MODE_LATCH:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - case BEGIN_MACRO_PDF417_CONTROL_BLOCK:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - case MACRO_PDF417_TERMINATOR:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE:
|
| - textCompactionData[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE;
|
| - code = codewords[codeIndex++];
|
| - byteCompactionData[index] = code;
|
| - index++;
|
| - break;
|
| - case BYTE_COMPACTION_MODE_LATCH_6:
|
| - codeIndex--;
|
| - end = TRUE;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - decodeTextCompaction(textCompactionData, byteCompactionData, index, result);
|
| - return codeIndex;
|
| -}
|
| -void CBC_DecodedBitStreamPaser::decodeTextCompaction(
|
| - CFX_Int32Array& textCompactionData,
|
| - CFX_Int32Array& byteCompactionData,
|
| - int32_t length,
|
| - CFX_ByteString& result) {
|
| - Mode subMode = ALPHA;
|
| - Mode priorToShiftMode = ALPHA;
|
| - int32_t i = 0;
|
| - while (i < length) {
|
| - int32_t subModeCh = textCompactionData[i];
|
| - FX_CHAR ch = 0;
|
| - switch (subMode) {
|
| - case ALPHA:
|
| - if (subModeCh < 26) {
|
| - ch = (FX_CHAR)('A' + subModeCh);
|
| - } else {
|
| - if (subModeCh == 26) {
|
| - ch = ' ';
|
| - } else if (subModeCh == LL) {
|
| - subMode = LOWER;
|
| - } else if (subModeCh == ML) {
|
| - subMode = MIXED;
|
| - } else if (subModeCh == PS) {
|
| - priorToShiftMode = subMode;
|
| - subMode = PUNCT_SHIFT;
|
| - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| - result += (FX_CHAR)byteCompactionData[i];
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - case LOWER:
|
| - if (subModeCh < 26) {
|
| - ch = (FX_CHAR)('a' + subModeCh);
|
| - } else {
|
| - if (subModeCh == 26) {
|
| - ch = ' ';
|
| - } else if (subModeCh == AS) {
|
| - priorToShiftMode = subMode;
|
| - subMode = ALPHA_SHIFT;
|
| - } else if (subModeCh == ML) {
|
| - subMode = MIXED;
|
| - } else if (subModeCh == PS) {
|
| - priorToShiftMode = subMode;
|
| - subMode = PUNCT_SHIFT;
|
| - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| - result += (FX_CHAR)byteCompactionData[i];
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - case MIXED:
|
| - if (subModeCh < PL) {
|
| - ch = MIXED_CHARS[subModeCh];
|
| - } else {
|
| - if (subModeCh == PL) {
|
| - subMode = PUNCT;
|
| - } else if (subModeCh == 26) {
|
| - ch = ' ';
|
| - } else if (subModeCh == LL) {
|
| - subMode = LOWER;
|
| - } else if (subModeCh == AL) {
|
| - subMode = ALPHA;
|
| - } else if (subModeCh == PS) {
|
| - priorToShiftMode = subMode;
|
| - subMode = PUNCT_SHIFT;
|
| - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| - result += (FX_CHAR)byteCompactionData[i];
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - case PUNCT:
|
| - if (subModeCh < PAL) {
|
| - ch = PUNCT_CHARS[subModeCh];
|
| - } else {
|
| - if (subModeCh == PAL) {
|
| - subMode = ALPHA;
|
| - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| - result += (FX_CHAR)byteCompactionData[i];
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - case ALPHA_SHIFT:
|
| - subMode = priorToShiftMode;
|
| - if (subModeCh < 26) {
|
| - ch = (FX_CHAR)('A' + subModeCh);
|
| - } else {
|
| - if (subModeCh == 26) {
|
| - ch = ' ';
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - case PUNCT_SHIFT:
|
| - subMode = priorToShiftMode;
|
| - if (subModeCh < PAL) {
|
| - ch = PUNCT_CHARS[subModeCh];
|
| - } else {
|
| - if (subModeCh == PAL) {
|
| - subMode = ALPHA;
|
| - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| - result += (FX_CHAR)byteCompactionData[i];
|
| - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| - subMode = ALPHA;
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - if (ch != 0) {
|
| - result += ch;
|
| - }
|
| - i++;
|
| - }
|
| -}
|
| -int32_t CBC_DecodedBitStreamPaser::byteCompaction(int32_t mode,
|
| - CFX_Int32Array& codewords,
|
| - int32_t codeIndex,
|
| - CFX_ByteString& result) {
|
| - if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
| - int32_t count = 0;
|
| - int64_t value = 0;
|
| - FX_WORD* decodedData = FX_Alloc(FX_WORD, 6);
|
| - CFX_Int32Array byteCompactedCodewords;
|
| - byteCompactedCodewords.SetSize(6);
|
| - FX_BOOL end = FALSE;
|
| - int32_t nextCode = codewords[codeIndex++];
|
| - while ((codeIndex < codewords[0]) && !end) {
|
| - byteCompactedCodewords[count++] = nextCode;
|
| - value = 900 * value + nextCode;
|
| - nextCode = codewords[codeIndex++];
|
| - if (nextCode == TEXT_COMPACTION_MODE_LATCH ||
|
| - nextCode == BYTE_COMPACTION_MODE_LATCH ||
|
| - nextCode == NUMERIC_COMPACTION_MODE_LATCH ||
|
| - nextCode == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| - nextCode == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| - nextCode == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| - nextCode == MACRO_PDF417_TERMINATOR) {
|
| - codeIndex--;
|
| - end = TRUE;
|
| - } else {
|
| - if ((count % 5 == 0) && (count > 0)) {
|
| - int32_t j = 0;
|
| - for (; j < 6; ++j) {
|
| - decodedData[5 - j] = (FX_WORD)(value % 256);
|
| - value >>= 8;
|
| - }
|
| - for (j = 0; j < 6; ++j) {
|
| - result += (FX_CHAR)decodedData[j];
|
| - }
|
| - count = 0;
|
| - }
|
| - }
|
| - }
|
| - FX_Free(decodedData);
|
| - if (codeIndex == codewords[0] && nextCode < TEXT_COMPACTION_MODE_LATCH) {
|
| - byteCompactedCodewords[count++] = nextCode;
|
| - }
|
| - for (int32_t i = 0; i < count; i++) {
|
| - result += (FX_CHAR)(FX_WORD)byteCompactedCodewords[i];
|
| - }
|
| - } else if (mode == BYTE_COMPACTION_MODE_LATCH_6) {
|
| - int32_t count = 0;
|
| - int64_t value = 0;
|
| - FX_BOOL end = FALSE;
|
| - while (codeIndex < codewords[0] && !end) {
|
| - int32_t code = codewords[codeIndex++];
|
| - if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| - count++;
|
| - value = 900 * value + code;
|
| - } else {
|
| - if (code == TEXT_COMPACTION_MODE_LATCH ||
|
| - code == BYTE_COMPACTION_MODE_LATCH ||
|
| - code == NUMERIC_COMPACTION_MODE_LATCH ||
|
| - code == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| - code == MACRO_PDF417_TERMINATOR) {
|
| - codeIndex--;
|
| - end = TRUE;
|
| - }
|
| - }
|
| - if ((count % 5 == 0) && (count > 0)) {
|
| - FX_WORD* decodedData = FX_Alloc(FX_WORD, 6);
|
| - int32_t j = 0;
|
| - for (; j < 6; ++j) {
|
| - decodedData[5 - j] = (FX_WORD)(value & 0xFF);
|
| - value >>= 8;
|
| - }
|
| - for (j = 0; j < 6; ++j) {
|
| - result += (FX_CHAR)decodedData[j];
|
| - }
|
| - count = 0;
|
| - FX_Free(decodedData);
|
| - }
|
| - }
|
| - }
|
| - return codeIndex;
|
| -}
|
| -int32_t CBC_DecodedBitStreamPaser::numericCompaction(CFX_Int32Array& codewords,
|
| - int32_t codeIndex,
|
| - CFX_ByteString& result,
|
| - int32_t& e) {
|
| - int32_t count = 0;
|
| - FX_BOOL end = FALSE;
|
| - CFX_Int32Array numericCodewords;
|
| - numericCodewords.SetSize(MAX_NUMERIC_CODEWORDS);
|
| - while (codeIndex < codewords[0] && !end) {
|
| - int32_t code = codewords[codeIndex++];
|
| - if (codeIndex == codewords[0]) {
|
| - end = TRUE;
|
| - }
|
| - if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| - numericCodewords[count] = code;
|
| - count++;
|
| - } else {
|
| - if (code == TEXT_COMPACTION_MODE_LATCH ||
|
| - code == BYTE_COMPACTION_MODE_LATCH ||
|
| - code == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| - code == MACRO_PDF417_TERMINATOR) {
|
| - codeIndex--;
|
| - end = TRUE;
|
| - }
|
| - }
|
| - if (count % MAX_NUMERIC_CODEWORDS == 0 ||
|
| - code == NUMERIC_COMPACTION_MODE_LATCH || end) {
|
| - CFX_ByteString s = decodeBase900toBase10(numericCodewords, count, e);
|
| - BC_EXCEPTION_CHECK_ReturnValue(e, -1);
|
| - result += s;
|
| - count = 0;
|
| - }
|
| - }
|
| - return codeIndex;
|
| -}
|
| -CFX_ByteString CBC_DecodedBitStreamPaser::decodeBase900toBase10(
|
| - CFX_Int32Array& codewords,
|
| - int32_t count,
|
| - int32_t& e) {
|
| - BigInteger result = 0;
|
| - BigInteger nineHundred(900);
|
| - for (int32_t i = 0; i < count; i++) {
|
| - result = result * nineHundred + BigInteger(codewords[i]);
|
| - }
|
| - CFX_ByteString resultString(bigIntegerToString(result).c_str());
|
| - if (resultString.GetAt(0) != '1') {
|
| - e = BCExceptionFormatInstance;
|
| - return ' ';
|
| - }
|
| - return resultString.Mid(1, resultString.GetLength() - 1);
|
| -}
|
| +// 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 2009 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 "BC_PDF417DecodedBitStreamParser.h"
|
| +
|
| +#include <stdlib.h>
|
| +
|
| +#include "xfa/src/fxbarcode/BC_DecoderResult.h"
|
| +#include "xfa/src/fxbarcode/barcode.h"
|
| +#include "xfa/src/fxbarcode/common/BC_CommonDecoderResult.h"
|
| +#include "BC_PDF417ResultMetadata.h"
|
| +#include "third_party/bigint/BigIntegerLibrary.hh"
|
| +
|
| +#define TEXT_COMPACTION_MODE_LATCH 900
|
| +#define BYTE_COMPACTION_MODE_LATCH 901
|
| +#define NUMERIC_COMPACTION_MODE_LATCH 902
|
| +#define BYTE_COMPACTION_MODE_LATCH_6 924
|
| +#define BEGIN_MACRO_PDF417_CONTROL_BLOCK 928
|
| +#define BEGIN_MACRO_PDF417_OPTIONAL_FIELD 923
|
| +#define MACRO_PDF417_TERMINATOR 922
|
| +#define MODE_SHIFT_TO_BYTE_COMPACTION_MODE 913
|
| +
|
| +int32_t CBC_DecodedBitStreamPaser::MAX_NUMERIC_CODEWORDS = 15;
|
| +int32_t CBC_DecodedBitStreamPaser::NUMBER_OF_SEQUENCE_CODEWORDS = 2;
|
| +int32_t CBC_DecodedBitStreamPaser::PL = 25;
|
| +int32_t CBC_DecodedBitStreamPaser::LL = 27;
|
| +int32_t CBC_DecodedBitStreamPaser::AS = 27;
|
| +int32_t CBC_DecodedBitStreamPaser::ML = 28;
|
| +int32_t CBC_DecodedBitStreamPaser::AL = 28;
|
| +int32_t CBC_DecodedBitStreamPaser::PS = 29;
|
| +int32_t CBC_DecodedBitStreamPaser::PAL = 29;
|
| +FX_CHAR CBC_DecodedBitStreamPaser::PUNCT_CHARS[29] = {
|
| + ';', '<', '>', '@', '[', '\\', '}', '_', '`', '~',
|
| + '!', '\r', '\t', ',', ':', '\n', '-', '.', '$', '/',
|
| + '"', '|', '*', '(', ')', '?', '{', '}', '\''};
|
| +FX_CHAR CBC_DecodedBitStreamPaser::MIXED_CHARS[30] = {
|
| + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', '\r', '\t',
|
| + ',', ':', '#', '-', '.', '$', '/', '+', '%', '*', '=', '^'};
|
| +void CBC_DecodedBitStreamPaser::Initialize() {}
|
| +void CBC_DecodedBitStreamPaser::Finalize() {}
|
| +CBC_DecodedBitStreamPaser::CBC_DecodedBitStreamPaser() {}
|
| +CBC_DecodedBitStreamPaser::~CBC_DecodedBitStreamPaser() {}
|
| +CBC_CommonDecoderResult* CBC_DecodedBitStreamPaser::decode(
|
| + CFX_Int32Array& codewords,
|
| + CFX_ByteString ecLevel,
|
| + int32_t& e) {
|
| + CFX_ByteString result;
|
| + int32_t codeIndex = 1;
|
| + int32_t code = codewords.GetAt(codeIndex);
|
| + codeIndex++;
|
| + CBC_PDF417ResultMetadata* resultMetadata = new CBC_PDF417ResultMetadata;
|
| + while (codeIndex < codewords[0]) {
|
| + switch (code) {
|
| + case TEXT_COMPACTION_MODE_LATCH:
|
| + codeIndex = textCompaction(codewords, codeIndex, result);
|
| + break;
|
| + case BYTE_COMPACTION_MODE_LATCH:
|
| + codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| + break;
|
| + case NUMERIC_COMPACTION_MODE_LATCH:
|
| + codeIndex = numericCompaction(codewords, codeIndex, result, e);
|
| + BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
|
| + break;
|
| + case MODE_SHIFT_TO_BYTE_COMPACTION_MODE:
|
| + codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| + break;
|
| + case BYTE_COMPACTION_MODE_LATCH_6:
|
| + codeIndex = byteCompaction(code, codewords, codeIndex, result);
|
| + break;
|
| + case BEGIN_MACRO_PDF417_CONTROL_BLOCK:
|
| + codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata, e);
|
| + if (e != BCExceptionNO) {
|
| + delete resultMetadata;
|
| + return NULL;
|
| + }
|
| + break;
|
| + default:
|
| + codeIndex--;
|
| + codeIndex = textCompaction(codewords, codeIndex, result);
|
| + break;
|
| + }
|
| + if (codeIndex < codewords.GetSize()) {
|
| + code = codewords[codeIndex++];
|
| + } else {
|
| + e = BCExceptionFormatInstance;
|
| + delete resultMetadata;
|
| + return NULL;
|
| + }
|
| + }
|
| + if (result.GetLength() == 0) {
|
| + e = BCExceptionFormatInstance;
|
| + delete resultMetadata;
|
| + return NULL;
|
| + }
|
| + CFX_ByteArray rawBytes;
|
| + CFX_PtrArray byteSegments;
|
| + CBC_CommonDecoderResult* tempCd = new CBC_CommonDecoderResult();
|
| + tempCd->Init(rawBytes, result, byteSegments, ecLevel, e);
|
| + if (e != BCExceptionNO) {
|
| + delete resultMetadata;
|
| + return NULL;
|
| + }
|
| + tempCd->setOther(resultMetadata);
|
| + return tempCd;
|
| +}
|
| +int32_t CBC_DecodedBitStreamPaser::decodeMacroBlock(
|
| + CFX_Int32Array& codewords,
|
| + int32_t codeIndex,
|
| + CBC_PDF417ResultMetadata* resultMetadata,
|
| + int32_t& e) {
|
| + if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {
|
| + e = BCExceptionFormatInstance;
|
| + return -1;
|
| + }
|
| + CFX_Int32Array segmentIndexArray;
|
| + segmentIndexArray.SetSize(NUMBER_OF_SEQUENCE_CODEWORDS);
|
| + for (int32_t i = 0; i < NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {
|
| + segmentIndexArray.SetAt(i, codewords[codeIndex]);
|
| + }
|
| + CFX_ByteString str =
|
| + decodeBase900toBase10(segmentIndexArray, NUMBER_OF_SEQUENCE_CODEWORDS, e);
|
| + BC_EXCEPTION_CHECK_ReturnValue(e, -1);
|
| + resultMetadata->setSegmentIndex(atoi(str.GetBuffer(str.GetLength())));
|
| + CFX_ByteString fileId;
|
| + codeIndex = textCompaction(codewords, codeIndex, fileId);
|
| + resultMetadata->setFileId(fileId);
|
| + if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {
|
| + codeIndex++;
|
| + CFX_Int32Array additionalOptionCodeWords;
|
| + additionalOptionCodeWords.SetSize(codewords[0] - codeIndex);
|
| + int32_t additionalOptionCodeWordsIndex = 0;
|
| + FX_BOOL end = FALSE;
|
| + while ((codeIndex < codewords[0]) && !end) {
|
| + int32_t code = codewords[codeIndex++];
|
| + if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| + additionalOptionCodeWords[additionalOptionCodeWordsIndex++] = code;
|
| + } else {
|
| + switch (code) {
|
| + case MACRO_PDF417_TERMINATOR:
|
| + resultMetadata->setLastSegment(TRUE);
|
| + codeIndex++;
|
| + end = TRUE;
|
| + break;
|
| + default:
|
| + e = BCExceptionFormatInstance;
|
| + return -1;
|
| + }
|
| + }
|
| + }
|
| + CFX_Int32Array array;
|
| + array.SetSize(additionalOptionCodeWordsIndex);
|
| + array.Copy(additionalOptionCodeWords);
|
| + resultMetadata->setOptionalData(array);
|
| + } else if (codewords[codeIndex] == MACRO_PDF417_TERMINATOR) {
|
| + resultMetadata->setLastSegment(TRUE);
|
| + codeIndex++;
|
| + }
|
| + return codeIndex;
|
| +}
|
| +int32_t CBC_DecodedBitStreamPaser::textCompaction(CFX_Int32Array& codewords,
|
| + int32_t codeIndex,
|
| + CFX_ByteString& result) {
|
| + CFX_Int32Array textCompactionData;
|
| + textCompactionData.SetSize((codewords[0] - codeIndex) << 1);
|
| + CFX_Int32Array byteCompactionData;
|
| + byteCompactionData.SetSize((codewords[0] - codeIndex) << 1);
|
| + int32_t index = 0;
|
| + FX_BOOL end = FALSE;
|
| + while ((codeIndex < codewords[0]) && !end) {
|
| + int32_t code = codewords[codeIndex++];
|
| + if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| + textCompactionData[index] = code / 30;
|
| + textCompactionData[index + 1] = code % 30;
|
| + index += 2;
|
| + } else {
|
| + switch (code) {
|
| + case TEXT_COMPACTION_MODE_LATCH:
|
| + textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH;
|
| + break;
|
| + case BYTE_COMPACTION_MODE_LATCH:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + case NUMERIC_COMPACTION_MODE_LATCH:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + case BEGIN_MACRO_PDF417_CONTROL_BLOCK:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + case BEGIN_MACRO_PDF417_OPTIONAL_FIELD:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + case MACRO_PDF417_TERMINATOR:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + case MODE_SHIFT_TO_BYTE_COMPACTION_MODE:
|
| + textCompactionData[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE;
|
| + code = codewords[codeIndex++];
|
| + byteCompactionData[index] = code;
|
| + index++;
|
| + break;
|
| + case BYTE_COMPACTION_MODE_LATCH_6:
|
| + codeIndex--;
|
| + end = TRUE;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + decodeTextCompaction(textCompactionData, byteCompactionData, index, result);
|
| + return codeIndex;
|
| +}
|
| +void CBC_DecodedBitStreamPaser::decodeTextCompaction(
|
| + CFX_Int32Array& textCompactionData,
|
| + CFX_Int32Array& byteCompactionData,
|
| + int32_t length,
|
| + CFX_ByteString& result) {
|
| + Mode subMode = ALPHA;
|
| + Mode priorToShiftMode = ALPHA;
|
| + int32_t i = 0;
|
| + while (i < length) {
|
| + int32_t subModeCh = textCompactionData[i];
|
| + FX_CHAR ch = 0;
|
| + switch (subMode) {
|
| + case ALPHA:
|
| + if (subModeCh < 26) {
|
| + ch = (FX_CHAR)('A' + subModeCh);
|
| + } else {
|
| + if (subModeCh == 26) {
|
| + ch = ' ';
|
| + } else if (subModeCh == LL) {
|
| + subMode = LOWER;
|
| + } else if (subModeCh == ML) {
|
| + subMode = MIXED;
|
| + } else if (subModeCh == PS) {
|
| + priorToShiftMode = subMode;
|
| + subMode = PUNCT_SHIFT;
|
| + } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| + result += (FX_CHAR)byteCompactionData[i];
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + case LOWER:
|
| + if (subModeCh < 26) {
|
| + ch = (FX_CHAR)('a' + subModeCh);
|
| + } else {
|
| + if (subModeCh == 26) {
|
| + ch = ' ';
|
| + } else if (subModeCh == AS) {
|
| + priorToShiftMode = subMode;
|
| + subMode = ALPHA_SHIFT;
|
| + } else if (subModeCh == ML) {
|
| + subMode = MIXED;
|
| + } else if (subModeCh == PS) {
|
| + priorToShiftMode = subMode;
|
| + subMode = PUNCT_SHIFT;
|
| + } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| + result += (FX_CHAR)byteCompactionData[i];
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + case MIXED:
|
| + if (subModeCh < PL) {
|
| + ch = MIXED_CHARS[subModeCh];
|
| + } else {
|
| + if (subModeCh == PL) {
|
| + subMode = PUNCT;
|
| + } else if (subModeCh == 26) {
|
| + ch = ' ';
|
| + } else if (subModeCh == LL) {
|
| + subMode = LOWER;
|
| + } else if (subModeCh == AL) {
|
| + subMode = ALPHA;
|
| + } else if (subModeCh == PS) {
|
| + priorToShiftMode = subMode;
|
| + subMode = PUNCT_SHIFT;
|
| + } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| + result += (FX_CHAR)byteCompactionData[i];
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + case PUNCT:
|
| + if (subModeCh < PAL) {
|
| + ch = PUNCT_CHARS[subModeCh];
|
| + } else {
|
| + if (subModeCh == PAL) {
|
| + subMode = ALPHA;
|
| + } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| + result += (FX_CHAR)byteCompactionData[i];
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + case ALPHA_SHIFT:
|
| + subMode = priorToShiftMode;
|
| + if (subModeCh < 26) {
|
| + ch = (FX_CHAR)('A' + subModeCh);
|
| + } else {
|
| + if (subModeCh == 26) {
|
| + ch = ' ';
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + case PUNCT_SHIFT:
|
| + subMode = priorToShiftMode;
|
| + if (subModeCh < PAL) {
|
| + ch = PUNCT_CHARS[subModeCh];
|
| + } else {
|
| + if (subModeCh == PAL) {
|
| + subMode = ALPHA;
|
| + } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
| + result += (FX_CHAR)byteCompactionData[i];
|
| + } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
| + subMode = ALPHA;
|
| + }
|
| + }
|
| + break;
|
| + }
|
| + if (ch != 0) {
|
| + result += ch;
|
| + }
|
| + i++;
|
| + }
|
| +}
|
| +int32_t CBC_DecodedBitStreamPaser::byteCompaction(int32_t mode,
|
| + CFX_Int32Array& codewords,
|
| + int32_t codeIndex,
|
| + CFX_ByteString& result) {
|
| + if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
| + int32_t count = 0;
|
| + int64_t value = 0;
|
| + FX_WORD* decodedData = FX_Alloc(FX_WORD, 6);
|
| + CFX_Int32Array byteCompactedCodewords;
|
| + byteCompactedCodewords.SetSize(6);
|
| + FX_BOOL end = FALSE;
|
| + int32_t nextCode = codewords[codeIndex++];
|
| + while ((codeIndex < codewords[0]) && !end) {
|
| + byteCompactedCodewords[count++] = nextCode;
|
| + value = 900 * value + nextCode;
|
| + nextCode = codewords[codeIndex++];
|
| + if (nextCode == TEXT_COMPACTION_MODE_LATCH ||
|
| + nextCode == BYTE_COMPACTION_MODE_LATCH ||
|
| + nextCode == NUMERIC_COMPACTION_MODE_LATCH ||
|
| + nextCode == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| + nextCode == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| + nextCode == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| + nextCode == MACRO_PDF417_TERMINATOR) {
|
| + codeIndex--;
|
| + end = TRUE;
|
| + } else {
|
| + if ((count % 5 == 0) && (count > 0)) {
|
| + int32_t j = 0;
|
| + for (; j < 6; ++j) {
|
| + decodedData[5 - j] = (FX_WORD)(value % 256);
|
| + value >>= 8;
|
| + }
|
| + for (j = 0; j < 6; ++j) {
|
| + result += (FX_CHAR)decodedData[j];
|
| + }
|
| + count = 0;
|
| + }
|
| + }
|
| + }
|
| + FX_Free(decodedData);
|
| + if (codeIndex == codewords[0] && nextCode < TEXT_COMPACTION_MODE_LATCH) {
|
| + byteCompactedCodewords[count++] = nextCode;
|
| + }
|
| + for (int32_t i = 0; i < count; i++) {
|
| + result += (FX_CHAR)(FX_WORD)byteCompactedCodewords[i];
|
| + }
|
| + } else if (mode == BYTE_COMPACTION_MODE_LATCH_6) {
|
| + int32_t count = 0;
|
| + int64_t value = 0;
|
| + FX_BOOL end = FALSE;
|
| + while (codeIndex < codewords[0] && !end) {
|
| + int32_t code = codewords[codeIndex++];
|
| + if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| + count++;
|
| + value = 900 * value + code;
|
| + } else {
|
| + if (code == TEXT_COMPACTION_MODE_LATCH ||
|
| + code == BYTE_COMPACTION_MODE_LATCH ||
|
| + code == NUMERIC_COMPACTION_MODE_LATCH ||
|
| + code == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| + code == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| + code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| + code == MACRO_PDF417_TERMINATOR) {
|
| + codeIndex--;
|
| + end = TRUE;
|
| + }
|
| + }
|
| + if ((count % 5 == 0) && (count > 0)) {
|
| + FX_WORD* decodedData = FX_Alloc(FX_WORD, 6);
|
| + int32_t j = 0;
|
| + for (; j < 6; ++j) {
|
| + decodedData[5 - j] = (FX_WORD)(value & 0xFF);
|
| + value >>= 8;
|
| + }
|
| + for (j = 0; j < 6; ++j) {
|
| + result += (FX_CHAR)decodedData[j];
|
| + }
|
| + count = 0;
|
| + FX_Free(decodedData);
|
| + }
|
| + }
|
| + }
|
| + return codeIndex;
|
| +}
|
| +int32_t CBC_DecodedBitStreamPaser::numericCompaction(CFX_Int32Array& codewords,
|
| + int32_t codeIndex,
|
| + CFX_ByteString& result,
|
| + int32_t& e) {
|
| + int32_t count = 0;
|
| + FX_BOOL end = FALSE;
|
| + CFX_Int32Array numericCodewords;
|
| + numericCodewords.SetSize(MAX_NUMERIC_CODEWORDS);
|
| + while (codeIndex < codewords[0] && !end) {
|
| + int32_t code = codewords[codeIndex++];
|
| + if (codeIndex == codewords[0]) {
|
| + end = TRUE;
|
| + }
|
| + if (code < TEXT_COMPACTION_MODE_LATCH) {
|
| + numericCodewords[count] = code;
|
| + count++;
|
| + } else {
|
| + if (code == TEXT_COMPACTION_MODE_LATCH ||
|
| + code == BYTE_COMPACTION_MODE_LATCH ||
|
| + code == BYTE_COMPACTION_MODE_LATCH_6 ||
|
| + code == BEGIN_MACRO_PDF417_CONTROL_BLOCK ||
|
| + code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD ||
|
| + code == MACRO_PDF417_TERMINATOR) {
|
| + codeIndex--;
|
| + end = TRUE;
|
| + }
|
| + }
|
| + if (count % MAX_NUMERIC_CODEWORDS == 0 ||
|
| + code == NUMERIC_COMPACTION_MODE_LATCH || end) {
|
| + CFX_ByteString s = decodeBase900toBase10(numericCodewords, count, e);
|
| + BC_EXCEPTION_CHECK_ReturnValue(e, -1);
|
| + result += s;
|
| + count = 0;
|
| + }
|
| + }
|
| + return codeIndex;
|
| +}
|
| +CFX_ByteString CBC_DecodedBitStreamPaser::decodeBase900toBase10(
|
| + CFX_Int32Array& codewords,
|
| + int32_t count,
|
| + int32_t& e) {
|
| + BigInteger result = 0;
|
| + BigInteger nineHundred(900);
|
| + for (int32_t i = 0; i < count; i++) {
|
| + result = result * nineHundred + BigInteger(codewords[i]);
|
| + }
|
| + CFX_ByteString resultString(bigIntegerToString(result).c_str());
|
| + if (resultString.GetAt(0) != '1') {
|
| + e = BCExceptionFormatInstance;
|
| + return ' ';
|
| + }
|
| + return resultString.Mid(1, resultString.GetLength() - 1);
|
| +}
|
|
|