1 // Copyright 2014 PDFium Authors. All rights reserved.
\r
2 // Use of this source code is governed by a BSD-style license that can be
\r
3 // found in the LICENSE file.
\r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
\r
8 #include "include/BC_Encoder.h"
\r
9 #include "include/BC_Dimension.h"
\r
10 #include "include/BC_CommonBitMatrix.h"
\r
11 #include "include/BC_SymbolShapeHint.h"
\r
12 #include "include/BC_SymbolInfo.h"
\r
13 #include "include/BC_EncoderContext.h"
\r
14 #include "include/BC_HighLevelEncoder.h"
\r
15 #include "include/BC_C40Encoder.h"
\r
16 CBC_C40Encoder::CBC_C40Encoder()
\r
19 CBC_C40Encoder::~CBC_C40Encoder()
\r
22 FX_INT32 CBC_C40Encoder::getEncodingMode()
\r
24 return C40_ENCODATION;
\r
26 void CBC_C40Encoder::Encode(CBC_EncoderContext &context, FX_INT32 &e)
\r
28 CFX_WideString buffer;
\r
29 while (context.hasMoreCharacters()) {
\r
30 FX_WCHAR c = context.getCurrentChar();
\r
32 FX_INT32 lastCharSize = encodeChar(c, buffer, e);
\r
33 if (e != BCExceptionNO) {
\r
36 FX_INT32 unwritten = (buffer.GetLength() / 3) * 2;
\r
37 FX_INT32 curCodewordCount = context.getCodewordCount() + unwritten;
\r
38 context.updateSymbolInfo(curCodewordCount, e);
\r
39 if (e != BCExceptionNO) {
\r
42 FX_INT32 available = context.m_symbolInfo->m_dataCapacity - curCodewordCount;
\r
43 if (!context.hasMoreCharacters()) {
\r
44 CFX_WideString removed;
\r
45 if ((buffer.GetLength() % 3) == 2) {
\r
46 if (available < 2 || available > 2) {
\r
47 lastCharSize = backtrackOneCharacter(context, buffer, removed, lastCharSize, e);
\r
48 if (e != BCExceptionNO) {
\r
53 while ((buffer.GetLength() % 3) == 1
\r
54 && ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) {
\r
55 lastCharSize = backtrackOneCharacter(context, buffer, removed, lastCharSize, e);
\r
56 if (e != BCExceptionNO) {
\r
62 FX_INT32 count = buffer.GetLength();
\r
63 if ((count % 3) == 0) {
\r
64 FX_INT32 newMode = CBC_HighLevelEncoder::lookAheadTest(context.m_msg, context.m_pos, getEncodingMode());
\r
65 if (newMode != getEncodingMode()) {
\r
66 context.signalEncoderChange(newMode);
\r
71 handleEOD(context, buffer, e);
\r
73 void CBC_C40Encoder::writeNextTriplet(CBC_EncoderContext &context, CFX_WideString &buffer)
\r
75 context.writeCodewords(encodeToCodewords(buffer, 0));
\r
76 buffer.Delete(0, 3);
\r
78 void CBC_C40Encoder::handleEOD(CBC_EncoderContext &context, CFX_WideString &buffer, FX_INT32 &e)
\r
80 FX_INT32 unwritten = (buffer.GetLength() / 3) * 2;
\r
81 FX_INT32 rest = buffer.GetLength() % 3;
\r
82 FX_INT32 curCodewordCount = context.getCodewordCount() + unwritten;
\r
83 context.updateSymbolInfo(curCodewordCount, e);
\r
84 if (e != BCExceptionNO) {
\r
87 FX_INT32 available = context.m_symbolInfo->m_dataCapacity - curCodewordCount;
\r
89 buffer += (FX_WCHAR)'\0';
\r
90 while (buffer.GetLength() >= 3) {
\r
91 writeNextTriplet(context, buffer);
\r
93 if (context.hasMoreCharacters()) {
\r
94 context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH);
\r
96 } else if (available == 1 && rest == 1) {
\r
97 while (buffer.GetLength() >= 3) {
\r
98 writeNextTriplet(context, buffer);
\r
100 if (context.hasMoreCharacters()) {
\r
101 context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH);
\r
104 } else if (rest == 0) {
\r
105 while (buffer.GetLength() >= 3) {
\r
106 writeNextTriplet(context, buffer);
\r
108 if (available > 0 || context.hasMoreCharacters()) {
\r
109 context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH);
\r
112 e = BCExceptionIllegalStateUnexpectedCase;
\r
115 context.signalEncoderChange(ASCII_ENCODATION);
\r
117 FX_INT32 CBC_C40Encoder::encodeChar(FX_WCHAR c, CFX_WideString &sb, FX_INT32 &e)
\r
120 sb += (FX_WCHAR)'\3';
\r
122 } else if ((c >= '0') && (c <= '9')) {
\r
123 sb += (FX_WCHAR)(c - 48 + 4);
\r
125 } else if ((c >= 'A') && (c <= 'Z')) {
\r
126 sb += (FX_WCHAR)(c - 65 + 14);
\r
128 } else if ((c >= '\0') && (c <= 0x1f)) {
\r
129 sb += (FX_WCHAR)'\0';
\r
132 } else if ((c >= '!') && (c <= '/')) {
\r
133 sb += (FX_WCHAR)'\1';
\r
134 sb += (FX_WCHAR)(c - 33);
\r
136 } else if ((c >= ':') && (c <= '@')) {
\r
137 sb += (FX_WCHAR)'\1';
\r
138 sb += (FX_WCHAR)(c - 58 + 15);
\r
140 } else if ((c >= '[') && (c <= '_')) {
\r
141 sb += (FX_WCHAR)'\1';
\r
142 sb += (FX_WCHAR)(c - 91 + 22);
\r
144 } else if ((c >= 60) && (c <= 0x7f)) {
\r
145 sb += (FX_WCHAR)'\2';
\r
146 sb += (FX_WCHAR)(c - 96);
\r
148 } else if (c >= 80) {
\r
149 sb += (FX_WCHAR)'\1';
\r
150 sb += (FX_WCHAR)0x001e;
\r
152 len += encodeChar((c - 128), sb, e);
\r
153 BC_EXCEPTION_CHECK_ReturnValue(e, 0);
\r
156 e = BCExceptionIllegalArgument;
\r
160 FX_INT32 CBC_C40Encoder::backtrackOneCharacter(CBC_EncoderContext &context, CFX_WideString &buffer, CFX_WideString &removed, FX_INT32 lastCharSize, FX_INT32 &e)
\r
162 FX_INT32 count = buffer.GetLength();
\r
163 buffer.Delete(count - lastCharSize, count);
\r
165 FX_WCHAR c = context.getCurrentChar();
\r
166 lastCharSize = encodeChar(c, removed, e);
\r
167 BC_EXCEPTION_CHECK_ReturnValue(e, -1);
\r
168 context.resetSymbolInfo();
\r
169 return lastCharSize;
\r
171 CFX_WideString CBC_C40Encoder::encodeToCodewords(CFX_WideString sb, FX_INT32 startPos)
\r
173 FX_WCHAR c1 = sb.GetAt(startPos);
\r
174 FX_WCHAR c2 = sb.GetAt(startPos + 1);
\r
175 FX_WCHAR c3 = sb.GetAt(startPos + 2);
\r
176 FX_INT32 v = (1600 * c1) + (40 * c2) + c3 + 1;
\r
177 FX_WCHAR cw1 = (FX_WCHAR) (v / 256);
\r
178 FX_WCHAR cw2 = (FX_WCHAR) (v % 256);
\r
179 CFX_WideString b1(cw1);
\r
180 CFX_WideString b2(cw2);
\r