summaryrefslogtreecommitdiff
path: root/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp')
-rw-r--r--xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp375
1 files changed, 375 insertions, 0 deletions
diff --git a/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp b/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
new file mode 100644
index 0000000000..d8e7bb1dc5
--- /dev/null
+++ b/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
@@ -0,0 +1,375 @@
+// 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 2006-2007 Jeremias Maerki.
+ *
+ * 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 <limits>
+
+#include "xfa/fxbarcode/BC_Dimension.h"
+#include "xfa/fxbarcode/BC_UtilCodingConvert.h"
+#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h"
+#include "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_Base256Encoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_Encoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h"
+#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h"
+#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h"
+#include "xfa/fxbarcode/datamatrix/BC_TextEncoder.h"
+#include "xfa/fxbarcode/datamatrix/BC_X12Encoder.h"
+#include "xfa/fxbarcode/utils.h"
+
+FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_C40 = 230;
+FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_BASE256 = 231;
+FX_WCHAR CBC_HighLevelEncoder::UPPER_SHIFT = 235;
+FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_ANSIX12 = 238;
+FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_TEXT = 239;
+FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_EDIFACT = 240;
+FX_WCHAR CBC_HighLevelEncoder::C40_UNLATCH = 254;
+FX_WCHAR CBC_HighLevelEncoder::X12_UNLATCH = 254;
+FX_WCHAR CBC_HighLevelEncoder::PAD = 129;
+FX_WCHAR CBC_HighLevelEncoder::MACRO_05 = 236;
+FX_WCHAR CBC_HighLevelEncoder::MACRO_06 = 237;
+const wchar_t* CBC_HighLevelEncoder::MACRO_05_HEADER = L"[)>05";
+const wchar_t* CBC_HighLevelEncoder::MACRO_06_HEADER = L"[)>06";
+const wchar_t CBC_HighLevelEncoder::MACRO_TRAILER = 0x0004;
+
+CBC_HighLevelEncoder::CBC_HighLevelEncoder() {}
+CBC_HighLevelEncoder::~CBC_HighLevelEncoder() {}
+CFX_ByteArray& CBC_HighLevelEncoder::getBytesForMessage(CFX_WideString msg) {
+ CFX_ByteString bytestr;
+ CBC_UtilCodingConvert::UnicodeToUTF8(msg, bytestr);
+ for (int32_t i = 0; i < bytestr.GetLength(); i++) {
+ m_bytearray.Add(bytestr.GetAt(i));
+ }
+ return m_bytearray;
+}
+CFX_WideString CBC_HighLevelEncoder::encodeHighLevel(CFX_WideString msg,
+ CFX_WideString ecLevel,
+ int32_t& e) {
+ return encodeHighLevel(msg, ecLevel, FORCE_NONE, NULL, NULL, e);
+}
+CFX_WideString CBC_HighLevelEncoder::encodeHighLevel(CFX_WideString msg,
+ CFX_WideString ecLevel,
+ SymbolShapeHint shape,
+ CBC_Dimension* minSize,
+ CBC_Dimension* maxSize,
+ int32_t& e) {
+ CBC_EncoderContext context(msg, ecLevel, e);
+ BC_EXCEPTION_CHECK_ReturnValue(e, (FX_WCHAR*)"");
+ context.setSymbolShape(shape);
+ context.setSizeConstraints(minSize, maxSize);
+ if ((msg.Mid(0, 6) == MACRO_05_HEADER) &&
+ (msg.Mid(msg.GetLength() - 1, 1) == MACRO_TRAILER)) {
+ context.writeCodeword(MACRO_05);
+ context.setSkipAtEnd(2);
+ context.m_pos += 6;
+ } else if ((msg.Mid(0, 6) == MACRO_06_HEADER) &&
+ (msg.Mid(msg.GetLength() - 1, 1) == MACRO_TRAILER)) {
+ context.writeCodeword(MACRO_06);
+ context.setSkipAtEnd(2);
+ context.m_pos += 6;
+ }
+ CFX_PtrArray encoders;
+ encoders.Add(new CBC_ASCIIEncoder());
+ encoders.Add(new CBC_C40Encoder());
+ encoders.Add(new CBC_TextEncoder());
+ encoders.Add(new CBC_X12Encoder());
+ encoders.Add(new CBC_EdifactEncoder());
+ encoders.Add(new CBC_Base256Encoder());
+ int32_t encodingMode = ASCII_ENCODATION;
+ while (context.hasMoreCharacters()) {
+ ((CBC_Encoder*)encoders.GetAt(encodingMode))->Encode(context, e);
+ if (e != BCExceptionNO) {
+ for (int32_t i = 0; i < encoders.GetSize(); i++) {
+ delete (CBC_Encoder*)encoders.GetAt(i);
+ }
+ encoders.RemoveAll();
+ return (FX_WCHAR*)"";
+ }
+ if (context.m_newEncoding >= 0) {
+ encodingMode = context.m_newEncoding;
+ context.resetEncoderSignal();
+ }
+ }
+ int32_t len = context.m_codewords.GetLength();
+ context.updateSymbolInfo(e);
+ if (e != BCExceptionNO) {
+ for (int32_t i = 0; i < encoders.GetSize(); i++) {
+ delete (CBC_Encoder*)encoders.GetAt(i);
+ }
+ encoders.RemoveAll();
+ return (FX_WCHAR*)"";
+ }
+ int32_t capacity = context.m_symbolInfo->m_dataCapacity;
+ if (len < capacity) {
+ if (encodingMode != ASCII_ENCODATION &&
+ encodingMode != BASE256_ENCODATION) {
+ context.writeCodeword(0x00fe);
+ }
+ }
+ CFX_WideString codewords = context.m_codewords;
+ if (codewords.GetLength() < capacity) {
+ codewords += PAD;
+ }
+ while (codewords.GetLength() < capacity) {
+ codewords += (randomize253State(PAD, codewords.GetLength() + 1));
+ }
+ for (int32_t i = 0; i < encoders.GetSize(); i++) {
+ delete (CBC_Encoder*)encoders.GetAt(i);
+ }
+ encoders.RemoveAll();
+ return codewords;
+}
+int32_t CBC_HighLevelEncoder::lookAheadTest(CFX_WideString msg,
+ int32_t startpos,
+ int32_t currentMode) {
+ if (startpos >= msg.GetLength()) {
+ return currentMode;
+ }
+ CFX_FloatArray charCounts;
+ if (currentMode == ASCII_ENCODATION) {
+ charCounts.Add(0);
+ charCounts.Add(1);
+ charCounts.Add(1);
+ charCounts.Add(1);
+ charCounts.Add(1);
+ charCounts.Add(1.25f);
+ } else {
+ charCounts.Add(1);
+ charCounts.Add(2);
+ charCounts.Add(2);
+ charCounts.Add(2);
+ charCounts.Add(2);
+ charCounts.Add(2.25f);
+ charCounts[currentMode] = 0;
+ }
+ int32_t charsProcessed = 0;
+ while (TRUE) {
+ if ((startpos + charsProcessed) == msg.GetLength()) {
+ FX_DWORD min = std::numeric_limits<int32_t>::max();
+ CFX_ByteArray mins;
+ mins.SetSize(6);
+ CFX_Int32Array intCharCounts;
+ intCharCounts.SetSize(6);
+ min = findMinimums(charCounts, intCharCounts, min, mins);
+ int32_t minCount = getMinimumCount(mins);
+ if (intCharCounts[ASCII_ENCODATION] == min) {
+ return ASCII_ENCODATION;
+ }
+ if (minCount == 1 && mins[BASE256_ENCODATION] > 0) {
+ return BASE256_ENCODATION;
+ }
+ if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) {
+ return EDIFACT_ENCODATION;
+ }
+ if (minCount == 1 && mins[TEXT_ENCODATION] > 0) {
+ return TEXT_ENCODATION;
+ }
+ if (minCount == 1 && mins[X12_ENCODATION] > 0) {
+ return X12_ENCODATION;
+ }
+ return C40_ENCODATION;
+ }
+ FX_WCHAR c = msg.GetAt(startpos + charsProcessed);
+ charsProcessed++;
+ if (isDigit(c)) {
+ charCounts[ASCII_ENCODATION] += 0.5;
+ } else if (isExtendedASCII(c)) {
+ charCounts[ASCII_ENCODATION] =
+ (FX_FLOAT)ceil(charCounts[ASCII_ENCODATION]);
+ charCounts[ASCII_ENCODATION] += 2;
+ } else {
+ charCounts[ASCII_ENCODATION] =
+ (FX_FLOAT)ceil(charCounts[ASCII_ENCODATION]);
+ charCounts[ASCII_ENCODATION]++;
+ }
+ if (isNativeC40(c)) {
+ charCounts[C40_ENCODATION] += 2.0f / 3.0f;
+ } else if (isExtendedASCII(c)) {
+ charCounts[C40_ENCODATION] += 8.0f / 3.0f;
+ } else {
+ charCounts[C40_ENCODATION] += 4.0f / 3.0f;
+ }
+ if (isNativeText(c)) {
+ charCounts[TEXT_ENCODATION] += 2.0f / 3.0f;
+ } else if (isExtendedASCII(c)) {
+ charCounts[TEXT_ENCODATION] += 8.0f / 3.0f;
+ } else {
+ charCounts[TEXT_ENCODATION] += 4.0f / 3.0f;
+ }
+ if (isNativeX12(c)) {
+ charCounts[X12_ENCODATION] += 2.0f / 3.0f;
+ } else if (isExtendedASCII(c)) {
+ charCounts[X12_ENCODATION] += 13.0f / 3.0f;
+ } else {
+ charCounts[X12_ENCODATION] += 10.0f / 3.0f;
+ }
+ if (isNativeEDIFACT(c)) {
+ charCounts[EDIFACT_ENCODATION] += 3.0f / 4.0f;
+ } else if (isExtendedASCII(c)) {
+ charCounts[EDIFACT_ENCODATION] += 17.0f / 4.0f;
+ } else {
+ charCounts[EDIFACT_ENCODATION] += 13.0f / 4.0f;
+ }
+ if (isSpecialB256(c)) {
+ charCounts[BASE256_ENCODATION] += 4;
+ } else {
+ charCounts[BASE256_ENCODATION]++;
+ }
+ if (charsProcessed >= 4) {
+ CFX_Int32Array intCharCounts;
+ intCharCounts.SetSize(6);
+ CFX_ByteArray mins;
+ mins.SetSize(6);
+ findMinimums(charCounts, intCharCounts,
+ std::numeric_limits<int32_t>::max(), mins);
+ int32_t minCount = getMinimumCount(mins);
+ if (intCharCounts[ASCII_ENCODATION] < intCharCounts[BASE256_ENCODATION] &&
+ intCharCounts[ASCII_ENCODATION] < intCharCounts[C40_ENCODATION] &&
+ intCharCounts[ASCII_ENCODATION] < intCharCounts[TEXT_ENCODATION] &&
+ intCharCounts[ASCII_ENCODATION] < intCharCounts[X12_ENCODATION] &&
+ intCharCounts[ASCII_ENCODATION] < intCharCounts[EDIFACT_ENCODATION]) {
+ return ASCII_ENCODATION;
+ }
+ if (intCharCounts[BASE256_ENCODATION] < intCharCounts[ASCII_ENCODATION] ||
+ (mins[C40_ENCODATION] + mins[TEXT_ENCODATION] + mins[X12_ENCODATION] +
+ mins[EDIFACT_ENCODATION]) == 0) {
+ return BASE256_ENCODATION;
+ }
+ if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) {
+ return EDIFACT_ENCODATION;
+ }
+ if (minCount == 1 && mins[TEXT_ENCODATION] > 0) {
+ return TEXT_ENCODATION;
+ }
+ if (minCount == 1 && mins[X12_ENCODATION] > 0) {
+ return X12_ENCODATION;
+ }
+ if (intCharCounts[C40_ENCODATION] + 1 < intCharCounts[ASCII_ENCODATION] &&
+ intCharCounts[C40_ENCODATION] + 1 <
+ intCharCounts[BASE256_ENCODATION] &&
+ intCharCounts[C40_ENCODATION] + 1 <
+ intCharCounts[EDIFACT_ENCODATION] &&
+ intCharCounts[C40_ENCODATION] + 1 < intCharCounts[TEXT_ENCODATION]) {
+ if (intCharCounts[C40_ENCODATION] < intCharCounts[X12_ENCODATION]) {
+ return C40_ENCODATION;
+ }
+ if (intCharCounts[C40_ENCODATION] == intCharCounts[X12_ENCODATION]) {
+ int32_t p = startpos + charsProcessed + 1;
+ while (p < msg.GetLength()) {
+ FX_WCHAR tc = msg.GetAt(p);
+ if (isX12TermSep(tc)) {
+ return X12_ENCODATION;
+ }
+ if (!isNativeX12(tc)) {
+ break;
+ }
+ p++;
+ }
+ return C40_ENCODATION;
+ }
+ }
+ }
+ }
+}
+FX_BOOL CBC_HighLevelEncoder::isDigit(FX_WCHAR ch) {
+ return ch >= '0' && ch <= '9';
+}
+FX_BOOL CBC_HighLevelEncoder::isExtendedASCII(FX_WCHAR ch) {
+ return ch >= 128 && ch <= 255;
+}
+int32_t CBC_HighLevelEncoder::determineConsecutiveDigitCount(CFX_WideString msg,
+ int32_t startpos) {
+ int32_t count = 0;
+ int32_t len = msg.GetLength();
+ int32_t idx = startpos;
+ if (idx < len) {
+ FX_WCHAR ch = msg.GetAt(idx);
+ while (isDigit(ch) && idx < len) {
+ count++;
+ idx++;
+ if (idx < len) {
+ ch = msg.GetAt(idx);
+ }
+ }
+ }
+ return count;
+}
+void CBC_HighLevelEncoder::illegalCharacter(FX_WCHAR c, int32_t& e) {
+ e = BCExceptionIllegalArgument;
+}
+FX_WCHAR CBC_HighLevelEncoder::randomize253State(FX_WCHAR ch,
+ int32_t codewordPosition) {
+ int32_t pseudoRandom = ((149 * codewordPosition) % 253) + 1;
+ int32_t tempVariable = ch + pseudoRandom;
+ return tempVariable <= 254 ? (FX_WCHAR)tempVariable
+ : (FX_WCHAR)(tempVariable - 254);
+}
+int32_t CBC_HighLevelEncoder::findMinimums(CFX_FloatArray& charCounts,
+ CFX_Int32Array& intCharCounts,
+ int32_t min,
+ CFX_ByteArray& mins) {
+ for (int32_t l = 0; l < mins.GetSize(); l++) {
+ mins[l] = (uint8_t)0;
+ }
+ for (int32_t i = 0; i < 6; i++) {
+ intCharCounts[i] = (int32_t)ceil(charCounts[i]);
+ int32_t current = intCharCounts[i];
+ if (min > current) {
+ min = current;
+ for (int32_t j = 0; j < mins.GetSize(); j++) {
+ mins[j] = (uint8_t)0;
+ }
+ }
+ if (min == current) {
+ mins[i]++;
+ }
+ }
+ return min;
+}
+int32_t CBC_HighLevelEncoder::getMinimumCount(CFX_ByteArray& mins) {
+ int32_t minCount = 0;
+ for (int32_t i = 0; i < 6; i++) {
+ minCount += mins[i];
+ }
+ return minCount;
+}
+FX_BOOL CBC_HighLevelEncoder::isNativeC40(FX_WCHAR ch) {
+ return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z');
+}
+FX_BOOL CBC_HighLevelEncoder::isNativeText(FX_WCHAR ch) {
+ return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z');
+}
+FX_BOOL CBC_HighLevelEncoder::isNativeX12(FX_WCHAR ch) {
+ return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'Z');
+}
+FX_BOOL CBC_HighLevelEncoder::isX12TermSep(FX_WCHAR ch) {
+ return (ch == '\r') || (ch == '*') || (ch == '>');
+}
+FX_BOOL CBC_HighLevelEncoder::isNativeEDIFACT(FX_WCHAR ch) {
+ return ch >= ' ' && ch <= '^';
+}
+FX_BOOL CBC_HighLevelEncoder::isSpecialB256(FX_WCHAR ch) {
+ return FALSE;
+}