Home | History | Annotate | Download | only in jbig2
      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 
      7 #include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
      8 
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
     13 #include "core/fxcodec/jbig2/JBig2_Define.h"
     14 #include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
     15 #include "core/fxcrt/fx_memory.h"
     16 #include "third_party/base/numerics/safe_math.h"
     17 
     18 CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable,
     19                                          uint32_t nLines,
     20                                          bool bHTOOB)
     21     : m_bOK(true), HTOOB(bHTOOB), NTEMP(nLines) {
     22   ParseFromStandardTable(pTable);
     23 }
     24 
     25 CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream)
     26     : HTOOB(false), NTEMP(0) {
     27   m_bOK = ParseFromCodedBuffer(pStream);
     28 }
     29 
     30 CJBig2_HuffmanTable::~CJBig2_HuffmanTable() {}
     31 
     32 void CJBig2_HuffmanTable::ParseFromStandardTable(const JBig2TableLine* pTable) {
     33   PREFLEN.resize(NTEMP);
     34   RANGELEN.resize(NTEMP);
     35   RANGELOW.resize(NTEMP);
     36   for (uint32_t i = 0; i < NTEMP; ++i) {
     37     PREFLEN[i] = pTable[i].PREFLEN;
     38     RANGELEN[i] = pTable[i].RANDELEN;
     39     RANGELOW[i] = pTable[i].RANGELOW;
     40   }
     41   InitCodes();
     42 }
     43 
     44 bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) {
     45   unsigned char cTemp;
     46   if (pStream->read1Byte(&cTemp) == -1)
     47     return false;
     48 
     49   HTOOB = !!(cTemp & 0x01);
     50   unsigned char HTPS = ((cTemp >> 1) & 0x07) + 1;
     51   unsigned char HTRS = ((cTemp >> 4) & 0x07) + 1;
     52   uint32_t HTLOW;
     53   uint32_t HTHIGH;
     54   if (pStream->readInteger(&HTLOW) == -1 ||
     55       pStream->readInteger(&HTHIGH) == -1) {
     56     return false;
     57   }
     58 
     59   const int low = static_cast<int>(HTLOW);
     60   const int high = static_cast<int>(HTHIGH);
     61   if (low > high)
     62     return false;
     63 
     64   ExtendBuffers(false);
     65   pdfium::base::CheckedNumeric<int> cur_low = low;
     66   do {
     67     if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) ||
     68         (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1) ||
     69         (static_cast<size_t>(RANGELEN[NTEMP]) >= 8 * sizeof(cur_low))) {
     70       return false;
     71     }
     72     RANGELOW[NTEMP] = cur_low.ValueOrDie();
     73     cur_low += (1 << RANGELEN[NTEMP]);
     74     if (!cur_low.IsValid())
     75       return false;
     76     ExtendBuffers(true);
     77   } while (cur_low.ValueOrDie() < high);
     78 
     79   if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     80     return false;
     81 
     82   RANGELEN[NTEMP] = 32;
     83   RANGELOW[NTEMP] = low - 1;
     84   ExtendBuffers(true);
     85 
     86   if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     87     return false;
     88 
     89   RANGELEN[NTEMP] = 32;
     90   RANGELOW[NTEMP] = high;
     91   ExtendBuffers(true);
     92 
     93   if (HTOOB) {
     94     if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     95       return false;
     96 
     97     ++NTEMP;
     98   }
     99 
    100   InitCodes();
    101   return true;
    102 }
    103 
    104 void CJBig2_HuffmanTable::InitCodes() {
    105   int lenmax = 0;
    106   for (uint32_t i = 0; i < NTEMP; ++i)
    107     lenmax = std::max(PREFLEN[i], lenmax);
    108 
    109   CODES.resize(NTEMP);
    110   std::vector<int> LENCOUNT(lenmax + 1);
    111   std::vector<int> FIRSTCODE(lenmax + 1);
    112   for (int len : PREFLEN)
    113     ++LENCOUNT[len];
    114 
    115   FIRSTCODE[0] = 0;
    116   LENCOUNT[0] = 0;
    117   for (int i = 1; i <= lenmax; ++i) {
    118     FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1;
    119     int CURCODE = FIRSTCODE[i];
    120     for (uint32_t j = 0; j < NTEMP; ++j) {
    121       if (PREFLEN[j] == i)
    122         CODES[j] = CURCODE++;
    123     }
    124   }
    125 }
    126 
    127 void CJBig2_HuffmanTable::ExtendBuffers(bool increment) {
    128   if (increment)
    129     ++NTEMP;
    130 
    131   size_t size = PREFLEN.size();
    132   if (NTEMP < size)
    133     return;
    134 
    135   size += 16;
    136   ASSERT(NTEMP < size);
    137   PREFLEN.resize(size);
    138   RANGELEN.resize(size);
    139   RANGELOW.resize(size);
    140 }
    141