1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6// Original code is licensed as follows:
7/*
8 * Copyright 2006-2007 Jeremias Maerki.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23#include "xfa/fxbarcode/BC_Dimension.h"
24#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h"
25#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h"
26#include "xfa/fxbarcode/datamatrix/BC_Encoder.h"
27#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h"
28#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h"
29#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h"
30#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h"
31#include "xfa/fxbarcode/datamatrix/BC_X12Encoder.h"
32
33CBC_X12Encoder::CBC_X12Encoder() {}
34CBC_X12Encoder::~CBC_X12Encoder() {}
35int32_t CBC_X12Encoder::getEncodingMode() {
36  return X12_ENCODATION;
37}
38void CBC_X12Encoder::Encode(CBC_EncoderContext& context, int32_t& e) {
39  CFX_WideString buffer;
40  while (context.hasMoreCharacters()) {
41    FX_WCHAR c = context.getCurrentChar();
42    context.m_pos++;
43    encodeChar(c, buffer, e);
44    if (e != BCExceptionNO) {
45      return;
46    }
47    int32_t count = buffer.GetLength();
48    if ((count % 3) == 0) {
49      writeNextTriplet(context, buffer);
50      int32_t newMode = CBC_HighLevelEncoder::lookAheadTest(
51          context.m_msg, context.m_pos, getEncodingMode());
52      if (newMode != getEncodingMode()) {
53        context.signalEncoderChange(newMode);
54        break;
55      }
56    }
57  }
58  handleEOD(context, buffer, e);
59}
60void CBC_X12Encoder::handleEOD(CBC_EncoderContext& context,
61                               CFX_WideString& buffer,
62                               int32_t& e) {
63  context.updateSymbolInfo(e);
64  if (e != BCExceptionNO) {
65    return;
66  }
67  int32_t available =
68      context.m_symbolInfo->m_dataCapacity - context.getCodewordCount();
69  int32_t count = buffer.GetLength();
70  if (count == 2) {
71    context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH);
72    context.m_pos -= 2;
73    context.signalEncoderChange(ASCII_ENCODATION);
74  } else if (count == 1) {
75    context.m_pos--;
76    if (available > 1) {
77      context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH);
78    }
79    context.signalEncoderChange(ASCII_ENCODATION);
80  }
81}
82int32_t CBC_X12Encoder::encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e) {
83  if (c == '\r') {
84    sb += (FX_WCHAR)'\0';
85  } else if (c == '*') {
86    sb += (FX_WCHAR)'\1';
87  } else if (c == '>') {
88    sb += (FX_WCHAR)'\2';
89  } else if (c == ' ') {
90    sb += (FX_WCHAR)'\3';
91  } else if (c >= '0' && c <= '9') {
92    sb += (FX_WCHAR)(c - 48 + 4);
93  } else if (c >= 'A' && c <= 'Z') {
94    sb += (FX_WCHAR)(c - 65 + 14);
95  } else {
96    CBC_HighLevelEncoder::illegalCharacter(c, e);
97    if (e != BCExceptionNO)
98      return -1;
99  }
100  return 1;
101}
102