Home | History | Annotate | Download | only in qrcode
      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 2007 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/BC_UtilCodingConvert.h"
     25 #include "xfa/src/fxbarcode/common/BC_CommonBitSource.h"
     26 #include "xfa/src/fxbarcode/common/BC_CommonECI.h"
     27 #include "xfa/src/fxbarcode/common/BC_CommonCharacterSetECI.h"
     28 #include "xfa/src/fxbarcode/common/BC_CommonDecoderResult.h"
     29 #include "BC_QRCoderMode.h"
     30 #include "BC_QRDecodedBitStreamParser.h"
     31 const FX_CHAR* CBC_QRDecodedBitStreamParser::UTF_8 = "utf8";
     32 const FX_CHAR CBC_QRDecodedBitStreamParser::ALPHANUMERIC_CHARS[45] = {
     33     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
     34     'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
     35     'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'};
     36 CBC_QRDecodedBitStreamParser::CBC_QRDecodedBitStreamParser() {}
     37 CBC_QRDecodedBitStreamParser::~CBC_QRDecodedBitStreamParser() {}
     38 CBC_CommonDecoderResult* CBC_QRDecodedBitStreamParser::Decode(
     39     CFX_ByteArray* bytes,
     40     CBC_QRCoderVersion* version,
     41     CBC_QRCoderErrorCorrectionLevel* ecLevel,
     42     int32_t byteModeDecode,
     43     int32_t& e) {
     44   CBC_CommonBitSource bits(bytes);
     45   CFX_ByteString result;
     46   CBC_CommonCharacterSetECI* currentCharacterSetECI = NULL;
     47   FX_BOOL fc1Infact = FALSE;
     48   CFX_Int32Array byteSegments;
     49   CBC_QRCoderMode* mode = NULL;
     50   do {
     51     if (bits.Available() < 4) {
     52       mode = CBC_QRCoderMode::sTERMINATOR;
     53     } else {
     54       int32_t iTemp1 = bits.ReadBits(4, e);
     55       BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     56       mode = CBC_QRCoderMode::ForBits(iTemp1, e);
     57       BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     58       if (mode == NULL) {
     59         e = BCExceptionUnSupportMode;
     60         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     61       }
     62     }
     63     if (!(mode == CBC_QRCoderMode::sTERMINATOR)) {
     64       if (mode == CBC_QRCoderMode::sFNC1_FIRST_POSITION ||
     65           mode == CBC_QRCoderMode::sFNC1_SECOND_POSITION) {
     66         fc1Infact = TRUE;
     67       } else if (mode == CBC_QRCoderMode::sSTRUCTURED_APPEND) {
     68         bits.ReadBits(16, e);
     69         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     70       } else if (mode == CBC_QRCoderMode::sECI) {
     71         int32_t value = ParseECIValue(&bits, e);
     72         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     73         currentCharacterSetECI =
     74             CBC_CommonCharacterSetECI::GetCharacterSetECIByValue(value);
     75       } else {
     76         if (mode == CBC_QRCoderMode::sGBK) {
     77           bits.ReadBits(4, e);
     78           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     79         }
     80         int32_t numBits = mode->GetCharacterCountBits(version, e);
     81         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     82         int32_t count = bits.ReadBits(numBits, e);
     83         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     84         if (mode == CBC_QRCoderMode::sNUMERIC) {
     85           DecodeNumericSegment(&bits, result, count, e);
     86           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     87         } else if (mode == CBC_QRCoderMode::sALPHANUMERIC) {
     88           DecodeAlphanumericSegment(&bits, result, count, fc1Infact, e);
     89           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     90         } else if (mode == CBC_QRCoderMode::sBYTE) {
     91           DecodeByteSegment(&bits, result, count, currentCharacterSetECI,
     92                             &byteSegments, byteModeDecode, e);
     93           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     94         } else if (mode == CBC_QRCoderMode::sGBK) {
     95           DecodeGBKSegment(&bits, result, count, e);
     96           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     97         } else if (mode == CBC_QRCoderMode::sKANJI) {
     98           DecodeKanjiSegment(&bits, result, count, e);
     99           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    100         } else {
    101           e = BCExceptionUnSupportMode;
    102           BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    103         }
    104       }
    105     }
    106   } while (!(mode == CBC_QRCoderMode::sTERMINATOR));
    107   CBC_CommonDecoderResult* tempCd = new CBC_CommonDecoderResult();
    108   tempCd->Init(*bytes, result, byteSegments, ecLevel, e);
    109   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    110   return tempCd;
    111 }
    112 void CBC_QRDecodedBitStreamParser::DecodeGBKSegment(CBC_CommonBitSource* bits,
    113                                                     CFX_ByteString& result,
    114                                                     int32_t count,
    115                                                     int32_t& e) {
    116   CFX_ByteString buffer;
    117   while (count > 0) {
    118     int32_t twoBytes = bits->ReadBits(13, e);
    119     BC_EXCEPTION_CHECK_ReturnVoid(e);
    120     int32_t assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
    121     if (assembledTwoBytes <= 0x0095d) {
    122       assembledTwoBytes += 0x0a1a1;
    123     } else {
    124       assembledTwoBytes += 0x0a6a1;
    125     }
    126     buffer += (uint8_t)(assembledTwoBytes >> 8);
    127     buffer += (uint8_t)assembledTwoBytes;
    128     count--;
    129   }
    130   CBC_UtilCodingConvert::LocaleToUtf8(buffer, result);
    131 }
    132 void CBC_QRDecodedBitStreamParser::DecodeKanjiSegment(CBC_CommonBitSource* bits,
    133                                                       CFX_ByteString& result,
    134                                                       int32_t count,
    135                                                       int32_t& e) {
    136   CFX_ByteString buffer;
    137   while (count > 0) {
    138     int32_t twoBytes = bits->ReadBits(13, e);
    139     BC_EXCEPTION_CHECK_ReturnVoid(e);
    140     int32_t assembledTwoBytes = ((twoBytes / 0x0c0) << 8) | (twoBytes % 0x0c0);
    141     if (assembledTwoBytes <= 0x01f00) {
    142       assembledTwoBytes += 0x08140;
    143     } else {
    144       assembledTwoBytes += 0x0c140;
    145     }
    146     buffer += (uint8_t)(assembledTwoBytes >> 8);
    147     buffer += (uint8_t)assembledTwoBytes;
    148     count--;
    149   }
    150   CBC_UtilCodingConvert::LocaleToUtf8(buffer, result);
    151 }
    152 void CBC_QRDecodedBitStreamParser::DecodeByteSegment(
    153     CBC_CommonBitSource* bits,
    154     CFX_ByteString& result,
    155     int32_t count,
    156     CBC_CommonCharacterSetECI* currentCharacterSetECI,
    157     CFX_Int32Array* byteSegments,
    158     int32_t byteModeDecode,
    159     int32_t& e) {
    160   if (count < 0) {
    161     e = BCExceptionNotFound;
    162     BC_EXCEPTION_CHECK_ReturnVoid(e);
    163   }
    164   if ((count << 3) > bits->Available()) {
    165     e = BCExceptionRead;
    166     BC_EXCEPTION_CHECK_ReturnVoid(e);
    167   }
    168   uint8_t* readBytes = FX_Alloc(uint8_t, count);
    169   FXSYS_memset(readBytes, 0x00, count);
    170   for (int32_t i = 0; i < count; i++) {
    171     readBytes[i] = (uint8_t)bits->ReadBits(8, e);
    172     BC_EXCEPTION_CHECK_ReturnVoid(e);
    173   }
    174   CFX_ByteString bs(readBytes, count);
    175   result += bs;
    176   FX_Free(readBytes);
    177 }
    178 void CBC_QRDecodedBitStreamParser::DecodeAlphanumericSegment(
    179     CBC_CommonBitSource* bits,
    180     CFX_ByteString& result,
    181     int32_t count,
    182     FX_BOOL fac1InEffect,
    183     int32_t& e) {
    184   int32_t start = result.GetLength();
    185   while (count > 1) {
    186     int32_t nextTwoCharsBits = bits->ReadBits(11, e);
    187     BC_EXCEPTION_CHECK_ReturnVoid(e);
    188     BC_FX_ByteString_Append(result, 1,
    189                             ALPHANUMERIC_CHARS[nextTwoCharsBits / 45]);
    190     BC_FX_ByteString_Append(result, 1,
    191                             ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]);
    192     count -= 2;
    193   }
    194   if (count == 1) {
    195     int32_t itemp = bits->ReadBits(6, e);
    196     BC_EXCEPTION_CHECK_ReturnVoid(e);
    197     BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[itemp]);
    198   }
    199   if (fac1InEffect) {
    200     for (int32_t i = start; i < result.GetLength(); i++) {
    201       if (result[i] == '%') {
    202         if ((i < result.GetLength() - 1) && result[i + 1] == '%') {
    203           result.Delete(i + 1, 1);
    204         } else {
    205           result.SetAt(i, (FX_CHAR)0x1d);
    206         }
    207       }
    208     }
    209   }
    210 }
    211 void CBC_QRDecodedBitStreamParser::DecodeNumericSegment(
    212     CBC_CommonBitSource* bits,
    213     CFX_ByteString& result,
    214     int32_t count,
    215     int32_t& e) {
    216   while (count >= 3) {
    217     int32_t threeDigitsBits = bits->ReadBits(10, e);
    218     BC_EXCEPTION_CHECK_ReturnVoid(e);
    219     if (threeDigitsBits >= 1000) {
    220       e = BCExceptionRead;
    221       BC_EXCEPTION_CHECK_ReturnVoid(e);
    222     }
    223     BC_FX_ByteString_Append(result, 1,
    224                             ALPHANUMERIC_CHARS[threeDigitsBits / 100]);
    225     BC_FX_ByteString_Append(result, 1,
    226                             ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]);
    227     BC_FX_ByteString_Append(result, 1,
    228                             ALPHANUMERIC_CHARS[threeDigitsBits % 10]);
    229     count -= 3;
    230   }
    231   if (count == 2) {
    232     int32_t twoDigitBits = bits->ReadBits(7, e);
    233     BC_EXCEPTION_CHECK_ReturnVoid(e);
    234     if (twoDigitBits >= 100) {
    235       e = BCExceptionRead;
    236       BC_EXCEPTION_CHECK_ReturnVoid(e);
    237     }
    238     BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[twoDigitBits / 10]);
    239     BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[twoDigitBits % 10]);
    240   } else if (count == 1) {
    241     int32_t digitBits = bits->ReadBits(4, e);
    242     BC_EXCEPTION_CHECK_ReturnVoid(e);
    243     if (digitBits >= 10) {
    244       e = BCExceptionRead;
    245       BC_EXCEPTION_CHECK_ReturnVoid(e);
    246     }
    247     BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[digitBits]);
    248   }
    249 }
    250 const CFX_ByteString CBC_QRDecodedBitStreamParser::GuessEncoding(
    251     CFX_ByteArray* bytes) {
    252   return *UTF_8;
    253 }
    254 int32_t CBC_QRDecodedBitStreamParser::ParseECIValue(CBC_CommonBitSource* bits,
    255                                                     int32_t& e) {
    256   int32_t firstByte = bits->ReadBits(8, e);
    257   BC_EXCEPTION_CHECK_ReturnValue(e, 0);
    258   if ((firstByte & 0x80) == 0) {
    259     return firstByte & 0x7f;
    260   } else if ((firstByte & 0xc0) == 0x80) {
    261     int32_t secondByte = bits->ReadBits(8, e);
    262     BC_EXCEPTION_CHECK_ReturnValue(e, 0);
    263     return ((firstByte & 0x3f) << 8) | secondByte;
    264   } else if ((firstByte & 0xe0) == 0xc0) {
    265     int32_t secondThirdByte = bits->ReadBits(16, e);
    266     BC_EXCEPTION_CHECK_ReturnValue(e, 0);
    267     return ((firstByte & 0x1f) << 16) | secondThirdByte;
    268   }
    269   e = BCExceptionBadECI;
    270   BC_EXCEPTION_CHECK_ReturnValue(e, 0);
    271   return 0;
    272 }
    273