Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_EdifactEncoder.cpp
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
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "barcode.h"\r
8 #include "include/BC_Encoder.h"\r
9 #include "include/BC_CommonBitMatrix.h"\r
10 #include "include/BC_Dimension.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_EdifactEncoder.h"\r
16 CBC_EdifactEncoder::CBC_EdifactEncoder()\r
17 {\r
18 }\r
19 CBC_EdifactEncoder::~CBC_EdifactEncoder()\r
20 {\r
21 }\r
22 FX_INT32 CBC_EdifactEncoder::getEncodingMode()\r
23 {\r
24     return EDIFACT_ENCODATION;\r
25 }\r
26 void CBC_EdifactEncoder::Encode(CBC_EncoderContext &context, FX_INT32 &e)\r
27 {\r
28     CFX_WideString buffer;\r
29     while (context.hasMoreCharacters()) {\r
30         FX_WCHAR c = context.getCurrentChar();\r
31         encodeChar(c, buffer, e);\r
32         if (e != BCExceptionNO) {\r
33             return;\r
34         }\r
35         context.m_pos++;\r
36         FX_INT32 count = buffer.GetLength();\r
37         if (count >= 4) {\r
38             context.writeCodewords(encodeToCodewords(buffer, 0, e));\r
39             if (e != BCExceptionNO) {\r
40                 return;\r
41             }\r
42             buffer.Delete(0, 4);\r
43             FX_INT32 newMode = CBC_HighLevelEncoder::lookAheadTest(context.m_msg, context.m_pos, getEncodingMode());\r
44             if (newMode != getEncodingMode()) {\r
45                 context.signalEncoderChange(ASCII_ENCODATION);\r
46                 break;\r
47             }\r
48         }\r
49     }\r
50     buffer += (FX_WCHAR)31;\r
51     handleEOD(context, buffer, e);\r
52 }\r
53 void CBC_EdifactEncoder::handleEOD(CBC_EncoderContext &context, CFX_WideString buffer, FX_INT32 &e)\r
54 {\r
55     FX_INT32 count = buffer.GetLength();\r
56     if (count == 0) {\r
57         return;\r
58     }\r
59     if (count == 1) {\r
60         context.updateSymbolInfo(e);\r
61         if (e != BCExceptionNO) {\r
62             return;\r
63         }\r
64         FX_INT32 available = context.m_symbolInfo->m_dataCapacity - context.getCodewordCount();\r
65         FX_INT32 remaining = context.getRemainingCharacters();\r
66         if (remaining == 0 && available <= 2) {\r
67             return;\r
68         }\r
69     }\r
70     if (count > 4) {\r
71         e = BCExceptionIllegalStateCountMustNotExceed4;\r
72         return;\r
73     }\r
74     FX_INT32 restChars = count - 1;\r
75     CFX_WideString encoded = encodeToCodewords(buffer, 0, e);\r
76     if (e != BCExceptionNO) {\r
77         return;\r
78     }\r
79     FX_BOOL endOfSymbolReached = !context.hasMoreCharacters();\r
80     FX_BOOL restInAscii = endOfSymbolReached && restChars <= 2;\r
81     if (restChars <= 2) {\r
82         context.updateSymbolInfo(context.getCodewordCount() + restChars, e);\r
83         if (e != BCExceptionNO) {\r
84             return;\r
85         }\r
86         FX_INT32 available = context.m_symbolInfo->m_dataCapacity - context.getCodewordCount();\r
87         if (available >= 3) {\r
88             restInAscii = FALSE;\r
89             context.updateSymbolInfo(context.getCodewordCount() + encoded.GetLength(), e);\r
90             if (e != BCExceptionNO) {\r
91                 return;\r
92             }\r
93         }\r
94     }\r
95     if (restInAscii) {\r
96         context.resetSymbolInfo();\r
97         context.m_pos -= restChars;\r
98     } else {\r
99         context.writeCodewords(encoded);\r
100     }\r
101     context.signalEncoderChange(ASCII_ENCODATION);\r
102 }\r
103 void CBC_EdifactEncoder::encodeChar(FX_WCHAR c, CFX_WideString &sb, FX_INT32 &e)\r
104 {\r
105     if (c >= ' ' && c <= '?') {\r
106         sb += c;\r
107     } else if (c >= '@' && c <= '^') {\r
108         sb += (FX_WCHAR)(c - 64);\r
109     } else {\r
110         CBC_HighLevelEncoder::illegalCharacter(c, e);\r
111     }\r
112 }\r
113 CFX_WideString CBC_EdifactEncoder::encodeToCodewords(CFX_WideString sb, FX_INT32 startPos, FX_INT32 &e)\r
114 {\r
115     FX_INT32 len = sb.GetLength() - startPos;\r
116     if (len == 0) {\r
117         e = BCExceptionNoContents;\r
118         return (FX_LPWSTR)"";\r
119     }\r
120     FX_WCHAR c1 = sb.GetAt(startPos);\r
121     FX_WCHAR c2 = len >= 2 ? sb.GetAt(startPos + 1) : 0;\r
122     FX_WCHAR c3 = len >= 3 ? sb.GetAt(startPos + 2) : 0;\r
123     FX_WCHAR c4 = len >= 4 ? sb.GetAt(startPos + 3) : 0;\r
124     FX_INT32 v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4;\r
125     FX_WCHAR cw1 = (FX_WCHAR) ((v >> 16) & 255);\r
126     FX_WCHAR cw2 = (FX_WCHAR) ((v >> 8) & 255);\r
127     FX_WCHAR cw3 = (FX_WCHAR) (v & 255);\r
128     CFX_WideString res;\r
129     res += cw1;\r
130     if (len >= 2) {\r
131         res += cw2;\r
132     }\r
133     if (len >= 3) {\r
134         res += cw3;\r
135     }\r
136     return res;\r
137 }\r