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