Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_OnedCode39Writer.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_Writer.h"\r
9 #include "include/BC_Reader.h"\r
10 #include "include/BC_OneDReader.h"\r
11 #include "include/BC_OneDimWriter.h"\r
12 #include "include/BC_OnedCode39Reader.h"\r
13 #include "include/BC_OnedCode39Writer.h"\r
14 #include "include/BC_CommonBitMatrix.h"\r
15 CBC_OnedCode39Writer::CBC_OnedCode39Writer()\r
16 {\r
17     m_extendedMode = FALSE;\r
18     m_iWideNarrRatio = 3;\r
19 }\r
20 CBC_OnedCode39Writer::CBC_OnedCode39Writer(FX_BOOL extendedMode)\r
21 {\r
22     m_iWideNarrRatio = 3;\r
23     m_extendedMode = extendedMode;\r
24 }\r
25 CBC_OnedCode39Writer::~CBC_OnedCode39Writer()\r
26 {\r
27 }\r
28 FX_BOOL CBC_OnedCode39Writer::CheckContentValidity(FX_WSTR contents)\r
29 {\r
30     if (m_extendedMode) {\r
31         return CheckExtendedContentValidity(contents);\r
32     }\r
33     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
34         FX_WCHAR ch = contents.GetAt(i);\r
35         if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z')\r
36                 || ch == (FX_WCHAR)'-' || ch == (FX_WCHAR)'.' || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*'\r
37                 || ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/' || ch == (FX_WCHAR)'+' || ch == (FX_WCHAR)'%') {\r
38             continue;\r
39         }\r
40         return FALSE;\r
41     }\r
42     return TRUE;\r
43 }\r
44 FX_BOOL CBC_OnedCode39Writer::CheckExtendedContentValidity(FX_WSTR contents)\r
45 {\r
46     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
47         FX_WCHAR ch = contents.GetAt(i);\r
48         if (ch > 127) {\r
49             return FALSE;\r
50         }\r
51     }\r
52     return TRUE;\r
53 }\r
54 CFX_WideString CBC_OnedCode39Writer::FilterContents(FX_WSTR contents)\r
55 {\r
56     if (m_extendedMode) {\r
57         return FilterExtendedContents(contents);\r
58     }\r
59     CFX_WideString filtercontents;\r
60     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
61         FX_WCHAR ch = contents.GetAt(i);\r
62         if ( ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1) ) {\r
63             continue;\r
64         }\r
65         if(ch > 175) {\r
66             i++;\r
67             continue;\r
68         } else {\r
69             ch = Upper(ch);\r
70         }\r
71         if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z')\r
72                 || ch == (FX_WCHAR)'-' || ch == (FX_WCHAR)'.' || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*'\r
73                 || ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/' || ch == (FX_WCHAR)'+' || ch == (FX_WCHAR)'%') {\r
74             filtercontents += ch;\r
75         }\r
76     }\r
77     return filtercontents;\r
78 }\r
79 CFX_WideString CBC_OnedCode39Writer::FilterExtendedContents(FX_WSTR contents)\r
80 {\r
81     CFX_WideString filtercontents;\r
82     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
83         FX_WCHAR ch = contents.GetAt(i);\r
84         if ( ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1) ) {\r
85             continue;\r
86         }\r
87         if(ch > 175) {\r
88             i++;\r
89             continue;\r
90         }\r
91         if (ch > 127 && ch < 176) {\r
92             continue;\r
93         }\r
94         if (ch == 0) {\r
95             filtercontents += '%';\r
96             filtercontents += 'U';\r
97         } else if(ch >= 1 && ch <= 26) {\r
98             filtercontents += '$';\r
99             filtercontents += (ch + 64);\r
100         } else if (ch >= 27 && ch <= 31) {\r
101             filtercontents += '%';\r
102             filtercontents += (ch + 38);\r
103         } else if (ch >= 33 && ch <= 47 && ch != 45 && ch != 46) {\r
104             filtercontents += '/';\r
105             filtercontents += (ch + 32);\r
106         } else if (ch == 58) {\r
107             filtercontents += '/';\r
108             filtercontents += 'Z';\r
109         } else if (ch >= 59 && ch <= 63) {\r
110             filtercontents += '%';\r
111             filtercontents += ch + 11;\r
112         } else if (ch == 64) {\r
113             filtercontents += '%';\r
114             filtercontents += 'V';\r
115         } else if (ch >= 91 && ch <= 95) {\r
116             filtercontents += '%';\r
117             filtercontents += ch - 16;\r
118         } else if (ch == 96) {\r
119             filtercontents += '%';\r
120             filtercontents += 'W';\r
121         } else if (ch >= 97 && ch <= 122) {\r
122             filtercontents += '+';\r
123             filtercontents += ch - 32;\r
124         } else if (ch >= 123 && ch <= 126) {\r
125             filtercontents += '%';\r
126             filtercontents += ch - 43;\r
127         } else if (ch == 127) {\r
128             filtercontents += '%';\r
129             filtercontents += 'T';\r
130         } else {\r
131             filtercontents += ch;\r
132         }\r
133     }\r
134     return filtercontents;\r
135 }\r
136 CFX_WideString CBC_OnedCode39Writer::RenderTextContents(FX_WSTR contents)\r
137 {\r
138     if (m_extendedMode) {\r
139         return RenderExtendedTextContents(contents);\r
140     }\r
141     CFX_WideString renderContents;\r
142     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
143         FX_WCHAR ch = contents.GetAt(i);\r
144         if ( ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1) ) {\r
145             continue;\r
146         }\r
147         if(ch > 175) {\r
148             i++;\r
149             continue;\r
150         }\r
151         if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z')\r
152                 || (ch >= (FX_WCHAR)'a' && ch <= (FX_WCHAR)'z') || ch == (FX_WCHAR)'-' || ch == (FX_WCHAR)'.'\r
153                 || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*' || ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/'\r
154                 || ch == (FX_WCHAR)'+' || ch == (FX_WCHAR)'%') {\r
155             renderContents += ch;\r
156         }\r
157     }\r
158     return renderContents;\r
159 }\r
160 CFX_WideString CBC_OnedCode39Writer::RenderExtendedTextContents(FX_WSTR contents)\r
161 {\r
162     CFX_WideString renderContents;\r
163     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
164         FX_WCHAR ch = contents.GetAt(i);\r
165         if ( ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1) ) {\r
166             continue;\r
167         }\r
168         if(ch > 175) {\r
169             i++;\r
170             continue;\r
171         }\r
172         if (ch > 127 && ch < 176) {\r
173             continue;\r
174         }\r
175         renderContents += ch;\r
176     }\r
177     return renderContents;\r
178 }\r
179 FX_BOOL CBC_OnedCode39Writer::SetTextLocation(BC_TEXT_LOC location)\r
180 {\r
181     if ( location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) {\r
182         return FALSE;\r
183     }\r
184     m_locTextLoc = location;\r
185     return TRUE;\r
186 }\r
187 FX_BOOL CBC_OnedCode39Writer::SetWideNarrowRatio(FX_INT32 ratio)\r
188 {\r
189     if ( ratio < 2 || ratio > 3) {\r
190         return FALSE;\r
191     }\r
192     m_iWideNarrRatio = ratio;\r
193     return TRUE;\r
194 }\r
195 FX_BYTE *CBC_OnedCode39Writer::Encode(const CFX_ByteString &contents, BCFORMAT format, FX_INT32 &outWidth, FX_INT32 &outHeight, FX_INT32 &e)\r
196 {\r
197     FX_BYTE *ret = Encode(contents, format, outWidth, outHeight, 0 , e);\r
198     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
199     return ret;\r
200 }\r
201 FX_BYTE *CBC_OnedCode39Writer::Encode(const CFX_ByteString &contents, BCFORMAT format, FX_INT32 &outWidth, FX_INT32 &outHeight, FX_INT32 hints, FX_INT32 &e)\r
202 {\r
203     if(format != BCFORMAT_CODE_39) {\r
204         e = BCExceptionOnlyEncodeCODE_39;\r
205         return NULL;\r
206     }\r
207     FX_BYTE *ret = CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e);\r
208     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
209     return ret;\r
210 }\r
211 void CBC_OnedCode39Writer::ToIntArray(FX_INT32 a, FX_INT32 *toReturn)\r
212 {\r
213     for(FX_INT32 i = 0; i < 9; i++) {\r
214         toReturn[i] = (a & (1 << i) ) == 0 ? 1 : m_iWideNarrRatio;\r
215     }\r
216 }\r
217 FX_CHAR CBC_OnedCode39Writer::CalcCheckSum(const CFX_ByteString &contents, FX_INT32 &e)\r
218 {\r
219     FX_INT32 length = contents.GetLength();\r
220     if (length > 80) {\r
221         e = BCExceptionContentsLengthShouldBetween1and80;\r
222         return '*';\r
223     }\r
224     FX_INT32 checksum = 0;\r
225     FX_INT32 len = (FX_INT32)strlen(CBC_OnedCode39Reader::ALPHABET_STRING);\r
226     for(FX_INT32 i = 0; i < contents.GetLength(); i++) {\r
227         FX_INT32 j = 0;\r
228         for (; j < len; j++) {\r
229             if (CBC_OnedCode39Reader::ALPHABET_STRING[j] == contents[i]) {\r
230                 if(contents[i] != '*') {\r
231                     checksum += j;\r
232                     break;\r
233                 } else {\r
234                     break;\r
235                 }\r
236             }\r
237         }\r
238         if (j >= len) {\r
239             e = BCExceptionUnSupportedString;\r
240             return '*';\r
241         }\r
242     }\r
243     checksum = checksum % 43;\r
244     return CBC_OnedCode39Reader::CHECKSUM_STRING[checksum];\r
245 }\r
246 FX_BYTE *CBC_OnedCode39Writer::Encode(const CFX_ByteString &contents, FX_INT32 &outlength , FX_INT32 &e)\r
247 {\r
248     FX_CHAR checksum = CalcCheckSum(contents, e);\r
249     if (checksum == '*') {\r
250         return NULL;\r
251     }\r
252     FX_INT32 widths[9] = {0};\r
253     FX_INT32 wideStrideNum = 3;\r
254     FX_INT32 narrStrideNum = 9 - wideStrideNum;\r
255     CFX_ByteString encodedContents = contents;\r
256     if ( m_bCalcChecksum ) {\r
257         encodedContents += checksum;\r
258     }\r
259     m_iContentLen = encodedContents.GetLength();\r
260     FX_INT32 codeWidth = (wideStrideNum * m_iWideNarrRatio + narrStrideNum) * 2 + 1 + m_iContentLen;\r
261     FX_INT32 len = (FX_INT32)strlen(CBC_OnedCode39Reader::ALPHABET_STRING);\r
262     for (FX_INT32 j = 0; j < m_iContentLen; j++) {\r
263         for (FX_INT32 i = 0; i < len; i++) {\r
264             if (CBC_OnedCode39Reader::ALPHABET_STRING[i] == encodedContents[j]) {\r
265                 ToIntArray(CBC_OnedCode39Reader::CHARACTER_ENCODINGS[i], widths);\r
266                 for(FX_INT32 k = 0; k < 9; k++) {\r
267                     codeWidth += widths[k];\r
268                 }\r
269             }\r
270         }\r
271     }\r
272     outlength = codeWidth;\r
273     FX_BYTE *result = FX_Alloc(FX_BYTE, codeWidth);\r
274     ToIntArray(CBC_OnedCode39Reader::CHARACTER_ENCODINGS[39], widths);\r
275     FX_INT32 pos = AppendPattern(result, 0, widths, 9, 1 , e);\r
276     if (e != BCExceptionNO) {\r
277         FX_Free (result);\r
278         return NULL;\r
279     }\r
280     FX_INT32 narrowWhite[] = {1};\r
281     pos += AppendPattern(result, pos, narrowWhite, 1, 0, e);\r
282     if (e != BCExceptionNO) {\r
283         FX_Free (result);\r
284         return NULL;\r
285     }\r
286     for(FX_INT32 l = m_iContentLen - 1; l >= 0; l--) {\r
287         for (FX_INT32 i = 0; i < len; i++) {\r
288             if (CBC_OnedCode39Reader::ALPHABET_STRING[i] == encodedContents[l]) {\r
289                 ToIntArray(CBC_OnedCode39Reader::CHARACTER_ENCODINGS[i], widths);\r
290                 pos += AppendPattern(result, pos, widths, 9, 1, e);\r
291                 if (e != BCExceptionNO) {\r
292                     FX_Free (result);\r
293                     return NULL;\r
294                 }\r
295             }\r
296         }\r
297         pos += AppendPattern(result, pos, narrowWhite, 1, 0, e);\r
298         if (e != BCExceptionNO) {\r
299             FX_Free (result);\r
300             return NULL;\r
301         }\r
302     }\r
303     ToIntArray(CBC_OnedCode39Reader::CHARACTER_ENCODINGS[39], widths);\r
304     pos += AppendPattern(result, pos, widths, 9, 1, e);\r
305     if (e != BCExceptionNO) {\r
306         FX_Free (result);\r
307         return NULL;\r
308     }\r
309     for (FX_INT32 i = 0; i < codeWidth / 2; i++) {\r
310         result[i] ^= result[codeWidth - 1 - i];\r
311         result[codeWidth - 1 - i] ^= result[i];\r
312         result[i] ^= result[codeWidth - 1 - i];\r
313     }\r
314     return result;\r
315 }\r
316 CFX_WideString CBC_OnedCode39Writer::encodedContents(FX_WSTR contents, FX_INT32 &e)\r
317 {\r
318     CFX_WideString encodedContents = contents;\r
319     if (m_bCalcChecksum && m_bPrintChecksum) {\r
320         CFX_WideString checksumContent = FilterContents(contents);\r
321         CFX_ByteString str = checksumContent.UTF8Encode();\r
322         FX_CHAR checksum;\r
323         checksum = CalcCheckSum(str, e);\r
324         BC_EXCEPTION_CHECK_ReturnValue(e, FX_WSTRC(L""));\r
325         str += checksum;\r
326         encodedContents += checksum;\r
327     }\r
328     return encodedContents;\r
329 }\r
330 void CBC_OnedCode39Writer::RenderResult(FX_WSTR contents, FX_BYTE* code, FX_INT32 codeLength, FX_BOOL isDevice, FX_INT32 &e)\r
331 {\r
332     CFX_WideString encodedCon = encodedContents(contents, e);\r
333     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
334     CBC_OneDimWriter::RenderResult(encodedCon, code, codeLength, isDevice, e);\r
335 }\r