Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_DataMatrixDecodedBitStreamParser.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_DataMatrixDecodedBitStreamParser.h"\r
9 #include "include/BC_CommonDecoderResult.h"\r
10 #include "include/BC_CommonBitSource.h"\r
11 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::C40_BASIC_SET_CHARS[] = {\r
12     '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\r
13     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\r
14     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'\r
15 };\r
16 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::C40_SHIFT2_SET_CHARS[] = {\r
17     '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*',  '+', ',', '-', '.',\r
18     '/', ':', ';', '<', '=', '>', '?',  '@', '[', '\\', ']', '^', '_'\r
19 };\r
20 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::TEXT_BASIC_SET_CHARS[] = {\r
21     '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\r
22     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',\r
23     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'\r
24 };\r
25 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::TEXT_SHIFT3_SET_CHARS[] = {\r
26     '\'', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\r
27     'O',  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (FX_CHAR) 127\r
28 };\r
29 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::PAD_ENCODE = 0;\r
30 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::ASCII_ENCODE = 1;\r
31 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::C40_ENCODE = 2;\r
32 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::TEXT_ENCODE = 3;\r
33 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::ANSIX12_ENCODE = 4;\r
34 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::EDIFACT_ENCODE = 5;\r
35 const FX_INT32 CBC_DataMatrixDecodedBitStreamParser::BASE256_ENCODE = 6;\r
36 CBC_DataMatrixDecodedBitStreamParser::CBC_DataMatrixDecodedBitStreamParser()\r
37 {\r
38 }\r
39 CBC_DataMatrixDecodedBitStreamParser::~CBC_DataMatrixDecodedBitStreamParser()\r
40 {\r
41 }\r
42 CBC_CommonDecoderResult *CBC_DataMatrixDecodedBitStreamParser::Decode(CFX_ByteArray &bytes, FX_INT32 &e)\r
43 {\r
44     CBC_CommonBitSource bits(&bytes);\r
45     CFX_ByteString result;\r
46     CFX_ByteString resultTrailer;\r
47     CFX_Int32Array byteSegments;\r
48     FX_INT32 mode = ASCII_ENCODE;\r
49     do {\r
50         if (mode == 1) {\r
51             mode = DecodeAsciiSegment(&bits, result, resultTrailer, e);\r
52             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
53         } else {\r
54             switch (mode) {\r
55                 case 2:\r
56                     DecodeC40Segment(&bits, result, e);\r
57                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
58                     break;\r
59                 case 3:\r
60                     DecodeTextSegment(&bits, result, e);\r
61                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
62                     break;\r
63                 case 4:\r
64                     DecodeAnsiX12Segment(&bits, result, e);\r
65                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
66                     break;\r
67                 case 5:\r
68                     DecodeEdifactSegment(&bits, result, e);\r
69                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
70                     break;\r
71                 case 6:\r
72                     DecodeBase256Segment(&bits, result, byteSegments, e);\r
73                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
74                     break;\r
75                 default:\r
76                     NULL;\r
77                     e = BCExceptionFormatException;\r
78                     return NULL;\r
79             }\r
80             mode = ASCII_ENCODE;\r
81         }\r
82     } while (mode != PAD_ENCODE && bits.Available() > 0);\r
83     if (resultTrailer.GetLength() > 0) {\r
84         result += resultTrailer;\r
85     }\r
86     CBC_CommonDecoderResult *tempCp =  FX_NEW CBC_CommonDecoderResult();\r
87     tempCp->Init(bytes, result, (byteSegments.GetSize() <= 0) ? CFX_Int32Array() : byteSegments, NULL, e);\r
88     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
89     return tempCp;\r
90 }\r
91 FX_INT32 CBC_DataMatrixDecodedBitStreamParser::DecodeAsciiSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, CFX_ByteString &resultTrailer, FX_INT32 &e)\r
92 {\r
93     FX_CHAR buffer[128];\r
94     FX_BOOL upperShift = FALSE;\r
95     do {\r
96         FX_INT32 oneByte = bits->ReadBits(8, e);\r
97         BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
98         if (oneByte == 0) {\r
99             e = BCExceptionFormatException;\r
100             return 0;\r
101         } else if (oneByte <= 128) {\r
102             oneByte = upperShift ? oneByte + 128 : oneByte;\r
103             upperShift = FALSE;\r
104             result += ((FX_CHAR) (oneByte - 1));\r
105             return ASCII_ENCODE;\r
106         } else if (oneByte == 129) {\r
107             return PAD_ENCODE;\r
108         } else if (oneByte <= 229) {\r
109             FX_INT32 value = oneByte - 130;\r
110 #if defined(_FX_WINAPI_PARTITION_APP_)\r
111             memset(buffer, 0, sizeof(FX_CHAR) * 128);\r
112             _itoa_s(value, buffer, 128, 10);\r
113 #else\r
114             FXSYS_itoa(value, buffer, 10);\r
115 #endif\r
116             if (value < 10) {\r
117                 result += '0';\r
118                 buffer[1] = '\0';\r
119             } else {\r
120                 buffer[2] = '\0';\r
121             }\r
122             result += buffer;\r
123         } else if (oneByte == 230) {\r
124             return C40_ENCODE;\r
125         } else if (oneByte == 231) {\r
126             return BASE256_ENCODE;\r
127         } else if (oneByte == 232 || oneByte == 233 || oneByte == 234) {\r
128         } else if (oneByte == 235) {\r
129             upperShift = TRUE;\r
130         } else if (oneByte == 236) {\r
131             result += "[)>";\r
132             result += 0x1E;\r
133             result += "05";\r
134             result += 0x1D;\r
135             resultTrailer.Insert(0, 0x1E);\r
136             resultTrailer.Insert(0 + 1, 0x04);\r
137         } else if (oneByte == 237) {\r
138             result += "[)>";\r
139             result += 0x1E;\r
140             result += "06";\r
141             result += 0x1D;\r
142             resultTrailer.Insert(0, 0x1E);\r
143             resultTrailer.Insert(0 + 1, 0x04);\r
144         } else if (oneByte == 238) {\r
145             return ANSIX12_ENCODE;\r
146         } else if (oneByte == 239) {\r
147             return TEXT_ENCODE;\r
148         } else if (oneByte == 240) {\r
149             return EDIFACT_ENCODE;\r
150         } else if (oneByte == 241) {\r
151         } else if (oneByte >= 242) {\r
152             if (oneByte == 254 && bits->Available() == 0) {\r
153             } else {\r
154                 e = BCExceptionFormatException;\r
155                 return 0;\r
156             }\r
157         }\r
158     } while (bits->Available() > 0);\r
159     return ASCII_ENCODE;\r
160 }\r
161 void CBC_DataMatrixDecodedBitStreamParser::DecodeC40Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, FX_INT32 &e)\r
162 {\r
163     FX_BOOL upperShift = FALSE;\r
164     CFX_Int32Array cValues;\r
165     cValues.SetSize(3);\r
166     do {\r
167         if (bits->Available() == 8) {\r
168             return;\r
169         }\r
170         FX_INT32 firstByte = bits->ReadBits(8, e);\r
171         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
172         if (firstByte == 254) {\r
173             return;\r
174         }\r
175         FX_INT32 tempp = bits->ReadBits(8, e);\r
176         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
177         ParseTwoBytes(firstByte, tempp, cValues);\r
178         FX_INT32 shift = 0;\r
179         FX_INT32 i;\r
180         for (i = 0; i < 3; i++) {\r
181             FX_INT32 cValue = cValues[i];\r
182             switch (shift) {\r
183                 case 0:\r
184                     if (cValue < 3) {\r
185                         shift = cValue + 1;\r
186                     } else if (cValue < 27) {\r
187                         FX_CHAR c40char = C40_BASIC_SET_CHARS[cValue];\r
188                         if (upperShift) {\r
189                             result += (FX_CHAR) (c40char + 128);\r
190                             upperShift = FALSE;\r
191                         } else {\r
192                             result += c40char;\r
193                         }\r
194                     } else {\r
195                         e = BCExceptionFormatException;\r
196                         return ;\r
197                     }\r
198                     break;\r
199                 case 1:\r
200                     if (upperShift) {\r
201                         result += (FX_CHAR) (cValue + 128);\r
202                         upperShift = FALSE;\r
203                     } else {\r
204                         result += cValue;\r
205                     }\r
206                     shift = 0;\r
207                     break;\r
208                 case 2:\r
209                     if (cValue < 27) {\r
210                         FX_CHAR c40char = C40_SHIFT2_SET_CHARS[cValue];\r
211                         if (upperShift) {\r
212                             result += (FX_CHAR) (c40char + 128);\r
213                             upperShift = FALSE;\r
214                         } else {\r
215                             result += c40char;\r
216                         }\r
217                     } else if (cValue == 27) {\r
218                         e = BCExceptionFormatException;\r
219                         return;\r
220                     } else if (cValue == 30) {\r
221                         upperShift = TRUE;\r
222                     } else {\r
223                         e = BCExceptionFormatException;\r
224                         return;\r
225                     }\r
226                     shift = 0;\r
227                     break;\r
228                 case 3:\r
229                     if (upperShift) {\r
230                         result += (FX_CHAR) (cValue + 224);\r
231                         upperShift = FALSE;\r
232                     } else {\r
233                         result += (FX_CHAR) (cValue + 96);\r
234                     }\r
235                     shift = 0;\r
236                     break;\r
237                 default:\r
238                     break;\r
239                     e = BCExceptionFormatException;\r
240                     return;\r
241             }\r
242         }\r
243     } while (bits->Available() > 0);\r
244 }\r
245 void CBC_DataMatrixDecodedBitStreamParser::DecodeTextSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, FX_INT32 &e)\r
246 {\r
247     FX_BOOL upperShift = FALSE;\r
248     CFX_Int32Array cValues;\r
249     cValues.SetSize(3);\r
250     FX_INT32 shift = 0;\r
251     do {\r
252         if (bits->Available() == 8) {\r
253             return;\r
254         }\r
255         FX_INT32 firstByte = bits->ReadBits(8, e);\r
256         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
257         if (firstByte == 254) {\r
258             return;\r
259         }\r
260         FX_INT32 inTp = bits->ReadBits(8, e);\r
261         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
262         ParseTwoBytes(firstByte, inTp, cValues);\r
263         for (FX_INT32 i = 0; i < 3; i++) {\r
264             FX_INT32 cValue = cValues[i];\r
265             switch (shift) {\r
266                 case 0:\r
267                     if (cValue < 3) {\r
268                         shift = cValue + 1;\r
269                     } else if (cValue < 40) {\r
270                         FX_CHAR textChar = TEXT_BASIC_SET_CHARS[cValue];\r
271                         if (upperShift) {\r
272                             result += (FX_CHAR) (textChar + 128);\r
273                             upperShift = FALSE;\r
274                         } else {\r
275                             result += textChar;\r
276                         }\r
277                     } else {\r
278                         e = BCExceptionFormatException;\r
279                         return;\r
280                     }\r
281                     break;\r
282                 case 1:\r
283                     if (upperShift) {\r
284                         result += (FX_CHAR) (cValue + 128);\r
285                         upperShift = FALSE;\r
286                     } else {\r
287                         result += cValue;\r
288                     }\r
289                     shift = 0;\r
290                     break;\r
291                 case 2:\r
292                     if (cValue < 27) {\r
293                         FX_CHAR c40char = C40_SHIFT2_SET_CHARS[cValue];\r
294                         if (upperShift) {\r
295                             result += (FX_CHAR) (c40char + 128);\r
296                             upperShift = FALSE;\r
297                         } else {\r
298                             result += c40char;\r
299                         }\r
300                     } else if (cValue == 27) {\r
301                         e = BCExceptionFormatException;\r
302                         return;\r
303                     } else if (cValue == 30) {\r
304                         upperShift = TRUE;\r
305                     } else {\r
306                         e = BCExceptionFormatException;\r
307                         return;\r
308                     }\r
309                     shift = 0;\r
310                     break;\r
311                 case 3:\r
312                     if (cValue < 19) {\r
313                         FX_CHAR textChar = TEXT_SHIFT3_SET_CHARS[cValue];\r
314                         if (upperShift) {\r
315                             result += (FX_CHAR) (textChar + 128);\r
316                             upperShift = FALSE;\r
317                         } else {\r
318                             result += textChar;\r
319                         }\r
320                         shift = 0;\r
321                     } else {\r
322                         e = BCExceptionFormatException;\r
323                         return;\r
324                     }\r
325                     break;\r
326                 default:\r
327                     break;\r
328                     e = BCExceptionFormatException;\r
329                     return;\r
330             }\r
331         }\r
332     } while (bits->Available() > 0);\r
333 }\r
334 void CBC_DataMatrixDecodedBitStreamParser::DecodeAnsiX12Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, FX_INT32 &e)\r
335 {\r
336     CFX_Int32Array cValues;\r
337     cValues.SetSize(3);\r
338     do {\r
339         if (bits->Available() == 8) {\r
340             return;\r
341         }\r
342         FX_INT32 firstByte = bits->ReadBits(8, e);\r
343         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
344         if (firstByte == 254) {\r
345             return;\r
346         }\r
347         FX_INT32 iTemp1 = bits->ReadBits(8, e);\r
348         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
349         ParseTwoBytes(firstByte, iTemp1, cValues);\r
350         FX_INT32 i;\r
351         for (i = 0; i < 3; i++) {\r
352             FX_INT32 cValue = cValues[i];\r
353             if (cValue == 0) {\r
354                 BC_FX_ByteString_Append(result, 1, '\r');\r
355             } else if (cValue == 1) {\r
356                 BC_FX_ByteString_Append(result, 1, '*');\r
357             } else if (cValue == 2) {\r
358                 BC_FX_ByteString_Append(result, 1, '>');\r
359             } else if (cValue == 3) {\r
360                 BC_FX_ByteString_Append(result, 1, ' ');\r
361             } else if (cValue < 14) {\r
362                 BC_FX_ByteString_Append(result, 1, (FX_CHAR) (cValue + 44));\r
363             } else if (cValue < 40) {\r
364                 BC_FX_ByteString_Append(result, 1, (FX_CHAR) (cValue + 51));\r
365             } else {\r
366                 e = BCExceptionFormatException;\r
367                 return;\r
368             }\r
369         }\r
370     } while (bits->Available() > 0);\r
371 }\r
372 void CBC_DataMatrixDecodedBitStreamParser::ParseTwoBytes(FX_INT32 firstByte, FX_INT32 secondByte, CFX_Int32Array &result)\r
373 {\r
374     FX_INT32 fullBitValue = (firstByte << 8) + secondByte - 1;\r
375     FX_INT32 temp = fullBitValue / 1600;\r
376     result[0] = temp;\r
377     fullBitValue -= temp * 1600;\r
378     temp = fullBitValue / 40;\r
379     result[1] = temp;\r
380     result[2] = fullBitValue - temp * 40;\r
381 }\r
382 void CBC_DataMatrixDecodedBitStreamParser::DecodeEdifactSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, FX_INT32 &e)\r
383 {\r
384     FX_CHAR buffer[128];\r
385     FX_BOOL unlatch = FALSE;\r
386     do {\r
387         if (bits->Available() <= 16) {\r
388             return;\r
389         }\r
390         FX_INT32 i;\r
391         for (i = 0; i < 4; i++) {\r
392             FX_INT32 edifactValue = bits->ReadBits(6, e);\r
393             BC_EXCEPTION_CHECK_ReturnVoid(e);\r
394             if (edifactValue == 0x1F) {\r
395                 unlatch = TRUE;\r
396             }\r
397             if (!unlatch) {\r
398                 if ((edifactValue & 32) == 0) {\r
399                     edifactValue |= 64;\r
400                 }\r
401 #if defined(_FX_WINAPI_PARTITION_APP_)\r
402                 memset(buffer, 0, sizeof(FX_CHAR) * 128);\r
403                 _itoa_s(edifactValue, buffer, 128, 10);\r
404                 result += buffer;\r
405 #else\r
406                 result += FXSYS_itoa(edifactValue, buffer, 10);\r
407 #endif\r
408             }\r
409         }\r
410     } while (!unlatch && bits->Available() > 0);\r
411 }\r
412 void CBC_DataMatrixDecodedBitStreamParser::DecodeBase256Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, CFX_Int32Array &byteSegments, FX_INT32 &e)\r
413 {\r
414     FX_INT32 codewordPosition = 1 + bits->getByteOffset();\r
415     FX_INT32 iTmp =  bits->ReadBits(8, e);\r
416     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
417     FX_INT32 d1 = Unrandomize255State(iTmp, codewordPosition++);\r
418     FX_INT32 count;\r
419     if (d1 == 0) {\r
420         count = bits->Available() / 8;\r
421     } else if (d1 < 250) {\r
422         count = d1;\r
423     } else {\r
424         FX_INT32 iTmp3 = bits->ReadBits(8, e);\r
425         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
426         count = 250 * (d1 - 249) + Unrandomize255State(iTmp3, codewordPosition++);\r
427     }\r
428     if (count < 0) {\r
429         e = BCExceptionFormatException;\r
430         return;\r
431     }\r
432     CFX_ByteArray *bytes = FX_NEW CFX_ByteArray();\r
433     bytes->SetSize(count);\r
434     FX_INT32 i;\r
435     for (i = 0; i < count; i++) {\r
436         if (bits->Available() < 8) {\r
437             e  = BCExceptionFormatException;\r
438             delete bytes;\r
439             return;\r
440         }\r
441         FX_INT32 iTemp5 = bits->ReadBits(8, e);\r
442         if (e != BCExceptionNO) {\r
443             delete bytes;\r
444             return;\r
445         }\r
446         bytes->SetAt(i, Unrandomize255State(iTemp5, codewordPosition++));\r
447     }\r
448     BC_FX_ByteString_Append(result, *bytes);\r
449     delete bytes;\r
450 }\r
451 FX_BYTE CBC_DataMatrixDecodedBitStreamParser::Unrandomize255State(FX_INT32 randomizedBase256Codeword, FX_INT32 base256CodewordPosition)\r
452 {\r
453     FX_INT32 pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\r
454     FX_INT32 tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\r
455     return (FX_BYTE) (tempVariable >= 0 ? tempVariable : tempVariable + 256);\r
456 }\r