Home | History | Annotate | Download | only in datamatrix
      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;
     49 CBC_DataMatrixDecodedBitStreamParser::CBC_DataMatrixDecodedBitStreamParser() {}
     50 CBC_DataMatrixDecodedBitStreamParser::~CBC_DataMatrixDecodedBitStreamParser() {}
     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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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