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