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/common/BC_CommonBitMatrix.h"
     25 #include "BC_QRCoderVersion.h"
     26 #include "BC_QRCoderFormatInformation.h"
     27 #include "BC_QRDataMask.h"
     28 #include "BC_QRBitMatrixParser.h"
     29 CBC_QRBitMatrixParser::CBC_QRBitMatrixParser() {}
     30 void CBC_QRBitMatrixParser::Init(CBC_CommonBitMatrix* bitMatrix, int32_t& e) {
     31   m_dimension = bitMatrix->GetDimension(e);
     32   BC_EXCEPTION_CHECK_ReturnVoid(e);
     33   m_tempBitMatrix = bitMatrix;
     34   if (m_dimension < 21 || (m_dimension & 0x03) != 1) {
     35     e = BCExceptionRead;
     36     BC_EXCEPTION_CHECK_ReturnVoid(e);
     37   }
     38   m_bitMatrix = m_tempBitMatrix;
     39   m_parsedFormatInfo = NULL;
     40   m_version = NULL;
     41 }
     42 CBC_QRBitMatrixParser::~CBC_QRBitMatrixParser() {
     43   if (m_parsedFormatInfo != NULL) {
     44     delete m_parsedFormatInfo;
     45     m_parsedFormatInfo = NULL;
     46   }
     47   m_version = NULL;
     48 }
     49 CBC_QRCoderFormatInformation* CBC_QRBitMatrixParser::ReadFormatInformation(
     50     int32_t& e) {
     51   if (m_parsedFormatInfo != NULL) {
     52     return m_parsedFormatInfo;
     53   }
     54   int32_t formatInfoBits = 0;
     55   int32_t j;
     56   for (j = 0; j < 6; j++) {
     57     formatInfoBits = CopyBit(8, j, formatInfoBits);
     58   }
     59   formatInfoBits = CopyBit(8, 7, formatInfoBits);
     60   formatInfoBits = CopyBit(8, 8, formatInfoBits);
     61   formatInfoBits = CopyBit(7, 8, formatInfoBits);
     62   for (int32_t i = 5; i >= 0; i--) {
     63     formatInfoBits = CopyBit(i, 8, formatInfoBits);
     64   }
     65   m_parsedFormatInfo =
     66       CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);
     67   if (m_parsedFormatInfo != NULL) {
     68     return m_parsedFormatInfo;
     69   }
     70   int32_t dimension = m_bitMatrix->GetDimension(e);
     71   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     72   formatInfoBits = 0;
     73   int32_t iMin = dimension - 8;
     74   for (j = dimension - 1; j >= iMin; j--) {
     75     formatInfoBits = CopyBit(j, 8, formatInfoBits);
     76   }
     77   for (int32_t k = dimension - 7; k < dimension; k++) {
     78     formatInfoBits = CopyBit(8, k, formatInfoBits);
     79   }
     80   m_parsedFormatInfo =
     81       CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);
     82   if (m_parsedFormatInfo != NULL) {
     83     return m_parsedFormatInfo;
     84   }
     85   e = BCExceptionRead;
     86   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     87   return NULL;
     88 }
     89 CBC_QRCoderVersion* CBC_QRBitMatrixParser::ReadVersion(int32_t& e) {
     90   if (m_version != NULL) {
     91     return m_version;
     92   }
     93   int32_t dimension = m_bitMatrix->GetDimension(e);
     94   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
     95   int32_t provisionVersion = (dimension - 17) >> 2;
     96   if (provisionVersion <= 6) {
     97     CBC_QRCoderVersion* qrv =
     98         CBC_QRCoderVersion::GetVersionForNumber(provisionVersion, e);
     99     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    100     return qrv;
    101   }
    102   int32_t versionBits = 0;
    103   for (int32_t i = 5; i >= 0; i--) {
    104     int32_t jMin = dimension - 11;
    105     for (int32_t j = dimension - 9; j >= jMin; j--) {
    106       versionBits = CopyBit(i, j, versionBits);
    107     }
    108   }
    109   m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);
    110   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    111   if (m_version != NULL && m_version->GetDimensionForVersion() == dimension) {
    112     return m_version;
    113   }
    114   versionBits = 0;
    115   for (int32_t j = 5; j >= 0; j--) {
    116     int32_t iMin = dimension - 11;
    117     for (int32_t i = dimension - 9; i >= iMin; i--) {
    118       versionBits = CopyBit(i, j, versionBits);
    119     }
    120   }
    121   m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);
    122   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    123   if (m_version != NULL && m_version->GetDimensionForVersion() == dimension) {
    124     return m_version;
    125   }
    126   e = BCExceptionRead;
    127   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    128   return NULL;
    129 }
    130 int32_t CBC_QRBitMatrixParser::CopyBit(int32_t i,
    131                                        int32_t j,
    132                                        int32_t versionBits) {
    133   return m_bitMatrix->Get(j, i) ? (versionBits << 1) | 0x1 : versionBits << 1;
    134 }
    135 CFX_ByteArray* CBC_QRBitMatrixParser::ReadCodewords(int32_t& e) {
    136   CBC_QRCoderFormatInformation* formatInfo = ReadFormatInformation(e);
    137   BC_EXCEPTION_CHECK_ReturnValue(e, NULL) CBC_QRCoderVersion* version =
    138       ReadVersion(e);
    139   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    140   CBC_QRDataMask* dataMask =
    141       CBC_QRDataMask::ForReference((int32_t)(formatInfo->GetDataMask()), e);
    142   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    143   int32_t dimension = m_bitMatrix->GetDimension(e);
    144   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    145   dataMask->UnmaskBitMatirx(m_bitMatrix, dimension);
    146   CBC_CommonBitMatrix* cbm = version->BuildFunctionPattern(e);
    147   BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    148   CBC_AutoPtr<CBC_CommonBitMatrix> functionPattern(cbm);
    149   FX_BOOL readingUp = TRUE;
    150   CFX_ByteArray* temp = new CFX_ByteArray;
    151   temp->SetSize(version->GetTotalCodeWords());
    152   CBC_AutoPtr<CFX_ByteArray> result(temp);
    153   int32_t resultOffset = 0;
    154   int32_t currentByte = 0;
    155   int32_t bitsRead = 0;
    156   for (int32_t j = dimension - 1; j > 0; j -= 2) {
    157     if (j == 6) {
    158       j--;
    159     }
    160     for (int32_t count = 0; count < dimension; count++) {
    161       int32_t i = readingUp ? dimension - 1 - count : count;
    162       for (int32_t col = 0; col < 2; col++) {
    163         if (!functionPattern->Get(j - col, i)) {
    164           bitsRead++;
    165           currentByte <<= 1;
    166           if (m_bitMatrix->Get(j - col, i)) {
    167             currentByte |= 1;
    168           }
    169           if (bitsRead == 8) {
    170             (*result)[resultOffset++] = (uint8_t)currentByte;
    171             bitsRead = 0;
    172             currentByte = 0;
    173           }
    174         }
    175       }
    176     }
    177     readingUp ^= TRUE;
    178   }
    179   if (resultOffset != version->GetTotalCodeWords()) {
    180     e = BCExceptionRead;
    181     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    182   }
    183   return result.release();
    184 }
    185