Home | History | Annotate | Download | only in jbig2
      1 // Copyright 2015 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_GrdProc.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fxcodec/fx_codec.h"
     13 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
     14 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
     15 #include "core/fxcodec/jbig2/JBig2_Image.h"
     16 #include "core/fxcrt/ifx_pauseindicator.h"
     17 #include "third_party/base/ptr_util.h"
     18 
     19 CJBig2_GRDProc::CJBig2_GRDProc()
     20     : m_loopIndex(0),
     21       m_pLine(nullptr),
     22       m_DecodeType(0),
     23       m_LTP(0) {
     24   m_ReplaceRect.left = 0;
     25   m_ReplaceRect.bottom = 0;
     26   m_ReplaceRect.top = 0;
     27   m_ReplaceRect.right = 0;
     28 }
     29 
     30 CJBig2_GRDProc::~CJBig2_GRDProc() {}
     31 
     32 bool CJBig2_GRDProc::UseTemplate0Opt3() const {
     33   return (GBAT[0] == 3) && (GBAT[1] == -1) && (GBAT[2] == -3) &&
     34          (GBAT[3] == -1) && (GBAT[4] == 2) && (GBAT[5] == -2) &&
     35          (GBAT[6] == -2) && (GBAT[7] == -2);
     36 }
     37 
     38 bool CJBig2_GRDProc::UseTemplate1Opt3() const {
     39   return (GBAT[0] == 3) && (GBAT[1] == -1);
     40 }
     41 
     42 bool CJBig2_GRDProc::UseTemplate23Opt3() const {
     43   return (GBAT[0] == 2) && (GBAT[1] == -1);
     44 }
     45 
     46 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith(
     47     CJBig2_ArithDecoder* pArithDecoder,
     48     JBig2ArithCtx* gbContext) {
     49   if (GBW == 0 || GBW > JBIG2_MAX_IMAGE_SIZE || GBH == 0 ||
     50       GBH > JBIG2_MAX_IMAGE_SIZE) {
     51     return pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
     52   }
     53 
     54   if (GBTEMPLATE == 0) {
     55     if (UseTemplate0Opt3())
     56       return decode_Arith_Template0_opt3(pArithDecoder, gbContext);
     57     return decode_Arith_Template0_unopt(pArithDecoder, gbContext);
     58   } else if (GBTEMPLATE == 1) {
     59     if (UseTemplate1Opt3())
     60       return decode_Arith_Template1_opt3(pArithDecoder, gbContext);
     61     return decode_Arith_Template1_unopt(pArithDecoder, gbContext);
     62   } else if (GBTEMPLATE == 2) {
     63     if (UseTemplate23Opt3())
     64       return decode_Arith_Template2_opt3(pArithDecoder, gbContext);
     65     return decode_Arith_Template2_unopt(pArithDecoder, gbContext);
     66   } else {
     67     if (UseTemplate23Opt3())
     68       return decode_Arith_Template3_opt3(pArithDecoder, gbContext);
     69     return decode_Arith_Template3_unopt(pArithDecoder, gbContext);
     70   }
     71 }
     72 
     73 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template0_opt3(
     74     CJBig2_ArithDecoder* pArithDecoder,
     75     JBig2ArithCtx* gbContext) {
     76   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
     77   if (!GBREG->data())
     78     return nullptr;
     79 
     80   int LTP = 0;
     81   uint8_t* pLine = GBREG->data();
     82   int32_t nStride = GBREG->stride();
     83   int32_t nStride2 = nStride << 1;
     84   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
     85   int32_t nBitsLeft = GBW - (nLineBytes << 3);
     86   uint32_t height = GBH & 0x7fffffff;
     87   for (uint32_t h = 0; h < height; h++) {
     88     if (TPGDON) {
     89       if (pArithDecoder->IsComplete())
     90         return nullptr;
     91 
     92       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]);
     93     }
     94     if (LTP) {
     95       GBREG->copyLine(h, h - 1);
     96     } else {
     97       if (h > 1) {
     98         uint8_t* pLine1 = pLine - nStride2;
     99         uint8_t* pLine2 = pLine - nStride;
    100         uint32_t line1 = (*pLine1++) << 6;
    101         uint32_t line2 = *pLine2++;
    102         uint32_t CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
    103         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    104           line1 = (line1 << 8) | ((*pLine1++) << 6);
    105           line2 = (line2 << 8) | (*pLine2++);
    106           uint8_t cVal = 0;
    107           for (int32_t k = 7; k >= 0; k--) {
    108             if (pArithDecoder->IsComplete())
    109               return nullptr;
    110 
    111             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    112             cVal |= bVal << k;
    113             CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
    114                        ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
    115           }
    116           pLine[cc] = cVal;
    117         }
    118         line1 <<= 8;
    119         line2 <<= 8;
    120         uint8_t cVal1 = 0;
    121         for (int32_t k = 0; k < nBitsLeft; k++) {
    122           if (pArithDecoder->IsComplete())
    123             return nullptr;
    124 
    125           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    126           cVal1 |= bVal << (7 - k);
    127           CONTEXT =
    128               (((CONTEXT & 0x7bf7) << 1) | bVal |
    129                ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
    130         }
    131         pLine[nLineBytes] = cVal1;
    132       } else {
    133         uint8_t* pLine2 = pLine - nStride;
    134         uint32_t line2 = (h & 1) ? (*pLine2++) : 0;
    135         uint32_t CONTEXT = (line2 & 0x07f0);
    136         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    137           if (h & 1) {
    138             line2 = (line2 << 8) | (*pLine2++);
    139           }
    140           uint8_t cVal = 0;
    141           for (int32_t k = 7; k >= 0; k--) {
    142             if (pArithDecoder->IsComplete())
    143               return nullptr;
    144 
    145             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    146             cVal |= bVal << k;
    147             CONTEXT =
    148                 (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
    149           }
    150           pLine[cc] = cVal;
    151         }
    152         line2 <<= 8;
    153         uint8_t cVal1 = 0;
    154         for (int32_t k = 0; k < nBitsLeft; k++) {
    155           if (pArithDecoder->IsComplete())
    156             return nullptr;
    157 
    158           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    159           cVal1 |= bVal << (7 - k);
    160           CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
    161                      (((line2 >> (7 - k))) & 0x0010));
    162         }
    163         pLine[nLineBytes] = cVal1;
    164       }
    165     }
    166     pLine += nStride;
    167   }
    168   return GBREG;
    169 }
    170 
    171 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template0_unopt(
    172     CJBig2_ArithDecoder* pArithDecoder,
    173     JBig2ArithCtx* gbContext) {
    174   int LTP = 0;
    175   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    176   GBREG->fill(0);
    177   for (uint32_t h = 0; h < GBH; h++) {
    178     if (TPGDON) {
    179       if (pArithDecoder->IsComplete())
    180         return nullptr;
    181 
    182       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]);
    183     }
    184     if (LTP) {
    185       GBREG->copyLine(h, h - 1);
    186     } else {
    187       uint32_t line1 = GBREG->getPixel(1, h - 2);
    188       line1 |= GBREG->getPixel(0, h - 2) << 1;
    189       uint32_t line2 = GBREG->getPixel(2, h - 1);
    190       line2 |= GBREG->getPixel(1, h - 1) << 1;
    191       line2 |= GBREG->getPixel(0, h - 1) << 2;
    192       uint32_t line3 = 0;
    193       for (uint32_t w = 0; w < GBW; w++) {
    194         int bVal;
    195         if (USESKIP && SKIP->getPixel(w, h)) {
    196           bVal = 0;
    197         } else {
    198           uint32_t CONTEXT = line3;
    199           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
    200           CONTEXT |= line2 << 5;
    201           CONTEXT |= GBREG->getPixel(w + GBAT[2], h + GBAT[3]) << 10;
    202           CONTEXT |= GBREG->getPixel(w + GBAT[4], h + GBAT[5]) << 11;
    203           CONTEXT |= line1 << 12;
    204           CONTEXT |= GBREG->getPixel(w + GBAT[6], h + GBAT[7]) << 15;
    205           if (pArithDecoder->IsComplete())
    206             return nullptr;
    207 
    208           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    209         }
    210         if (bVal) {
    211           GBREG->setPixel(w, h, bVal);
    212         }
    213         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
    214         line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
    215         line3 = ((line3 << 1) | bVal) & 0x0f;
    216       }
    217     }
    218   }
    219   return GBREG;
    220 }
    221 
    222 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template1_opt3(
    223     CJBig2_ArithDecoder* pArithDecoder,
    224     JBig2ArithCtx* gbContext) {
    225   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    226   if (!GBREG->data())
    227     return nullptr;
    228 
    229   int LTP = 0;
    230   uint8_t* pLine = GBREG->data();
    231   int32_t nStride = GBREG->stride();
    232   int32_t nStride2 = nStride << 1;
    233   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
    234   int32_t nBitsLeft = GBW - (nLineBytes << 3);
    235   for (uint32_t h = 0; h < GBH; h++) {
    236     if (TPGDON) {
    237       if (pArithDecoder->IsComplete())
    238         return nullptr;
    239 
    240       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]);
    241     }
    242     if (LTP) {
    243       GBREG->copyLine(h, h - 1);
    244     } else {
    245       if (h > 1) {
    246         uint8_t* pLine1 = pLine - nStride2;
    247         uint8_t* pLine2 = pLine - nStride;
    248         uint32_t line1 = (*pLine1++) << 4;
    249         uint32_t line2 = *pLine2++;
    250         uint32_t CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
    251         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    252           line1 = (line1 << 8) | ((*pLine1++) << 4);
    253           line2 = (line2 << 8) | (*pLine2++);
    254           uint8_t cVal = 0;
    255           for (int32_t k = 7; k >= 0; k--) {
    256             if (pArithDecoder->IsComplete())
    257               return nullptr;
    258 
    259             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    260             cVal |= bVal << k;
    261             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    262                       ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
    263           }
    264           pLine[cc] = cVal;
    265         }
    266         line1 <<= 8;
    267         line2 <<= 8;
    268         uint8_t cVal1 = 0;
    269         for (int32_t k = 0; k < nBitsLeft; k++) {
    270           if (pArithDecoder->IsComplete())
    271             return nullptr;
    272 
    273           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    274           cVal1 |= bVal << (7 - k);
    275           CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    276                     ((line1 >> (7 - k)) & 0x0200) |
    277                     ((line2 >> (8 - k)) & 0x0008);
    278         }
    279         pLine[nLineBytes] = cVal1;
    280       } else {
    281         uint8_t* pLine2 = pLine - nStride;
    282         uint32_t line2 = (h & 1) ? (*pLine2++) : 0;
    283         uint32_t CONTEXT = (line2 >> 1) & 0x01f8;
    284         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    285           if (h & 1) {
    286             line2 = (line2 << 8) | (*pLine2++);
    287           }
    288           uint8_t cVal = 0;
    289           for (int32_t k = 7; k >= 0; k--) {
    290             if (pArithDecoder->IsComplete())
    291               return nullptr;
    292 
    293             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    294             cVal |= bVal << k;
    295             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    296                       ((line2 >> (k + 1)) & 0x0008);
    297           }
    298           pLine[cc] = cVal;
    299         }
    300         line2 <<= 8;
    301         uint8_t cVal1 = 0;
    302         for (int32_t k = 0; k < nBitsLeft; k++) {
    303           if (pArithDecoder->IsComplete())
    304             return nullptr;
    305 
    306           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    307           cVal1 |= bVal << (7 - k);
    308           CONTEXT =
    309               ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
    310         }
    311         pLine[nLineBytes] = cVal1;
    312       }
    313     }
    314     pLine += nStride;
    315   }
    316   return GBREG;
    317 }
    318 
    319 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template1_unopt(
    320     CJBig2_ArithDecoder* pArithDecoder,
    321     JBig2ArithCtx* gbContext) {
    322   int LTP = 0;
    323   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    324   GBREG->fill(0);
    325   for (uint32_t h = 0; h < GBH; h++) {
    326     if (TPGDON) {
    327       if (pArithDecoder->IsComplete())
    328         return nullptr;
    329 
    330       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]);
    331     }
    332     if (LTP) {
    333       GBREG->copyLine(h, h - 1);
    334     } else {
    335       uint32_t line1 = GBREG->getPixel(2, h - 2);
    336       line1 |= GBREG->getPixel(1, h - 2) << 1;
    337       line1 |= GBREG->getPixel(0, h - 2) << 2;
    338       uint32_t line2 = GBREG->getPixel(2, h - 1);
    339       line2 |= GBREG->getPixel(1, h - 1) << 1;
    340       line2 |= GBREG->getPixel(0, h - 1) << 2;
    341       uint32_t line3 = 0;
    342       for (uint32_t w = 0; w < GBW; w++) {
    343         int bVal;
    344         if (USESKIP && SKIP->getPixel(w, h)) {
    345           bVal = 0;
    346         } else {
    347           uint32_t CONTEXT = line3;
    348           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
    349           CONTEXT |= line2 << 4;
    350           CONTEXT |= line1 << 9;
    351           if (pArithDecoder->IsComplete())
    352             return nullptr;
    353 
    354           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    355         }
    356         if (bVal) {
    357           GBREG->setPixel(w, h, bVal);
    358         }
    359         line1 = ((line1 << 1) | GBREG->getPixel(w + 3, h - 2)) & 0x0f;
    360         line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
    361         line3 = ((line3 << 1) | bVal) & 0x07;
    362       }
    363     }
    364   }
    365   return GBREG;
    366 }
    367 
    368 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template2_opt3(
    369     CJBig2_ArithDecoder* pArithDecoder,
    370     JBig2ArithCtx* gbContext) {
    371   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    372   if (!GBREG->data())
    373     return nullptr;
    374 
    375   int LTP = 0;
    376   uint8_t* pLine = GBREG->data();
    377   int32_t nStride = GBREG->stride();
    378   int32_t nStride2 = nStride << 1;
    379   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
    380   int32_t nBitsLeft = GBW - (nLineBytes << 3);
    381   for (uint32_t h = 0; h < GBH; h++) {
    382     if (TPGDON) {
    383       if (pArithDecoder->IsComplete())
    384         return nullptr;
    385 
    386       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]);
    387     }
    388     if (LTP) {
    389       GBREG->copyLine(h, h - 1);
    390     } else {
    391       if (h > 1) {
    392         uint8_t* pLine1 = pLine - nStride2;
    393         uint8_t* pLine2 = pLine - nStride;
    394         uint32_t line1 = (*pLine1++) << 1;
    395         uint32_t line2 = *pLine2++;
    396         uint32_t CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
    397         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    398           line1 = (line1 << 8) | ((*pLine1++) << 1);
    399           line2 = (line2 << 8) | (*pLine2++);
    400           uint8_t cVal = 0;
    401           for (int32_t k = 7; k >= 0; k--) {
    402             if (pArithDecoder->IsComplete())
    403               return nullptr;
    404 
    405             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    406             cVal |= bVal << k;
    407             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
    408                       ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
    409           }
    410           pLine[cc] = cVal;
    411         }
    412         line1 <<= 8;
    413         line2 <<= 8;
    414         uint8_t cVal1 = 0;
    415         for (int32_t k = 0; k < nBitsLeft; k++) {
    416           if (pArithDecoder->IsComplete())
    417             return nullptr;
    418 
    419           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    420           cVal1 |= bVal << (7 - k);
    421           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
    422                     ((line1 >> (7 - k)) & 0x0080) |
    423                     ((line2 >> (10 - k)) & 0x0004);
    424         }
    425         pLine[nLineBytes] = cVal1;
    426       } else {
    427         uint8_t* pLine2 = pLine - nStride;
    428         uint32_t line2 = (h & 1) ? (*pLine2++) : 0;
    429         uint32_t CONTEXT = (line2 >> 3) & 0x007c;
    430         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    431           if (h & 1) {
    432             line2 = (line2 << 8) | (*pLine2++);
    433           }
    434           uint8_t cVal = 0;
    435           for (int32_t k = 7; k >= 0; k--) {
    436             if (pArithDecoder->IsComplete())
    437               return nullptr;
    438 
    439             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    440             cVal |= bVal << k;
    441             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
    442                       ((line2 >> (k + 3)) & 0x0004);
    443           }
    444           pLine[cc] = cVal;
    445         }
    446         line2 <<= 8;
    447         uint8_t cVal1 = 0;
    448         for (int32_t k = 0; k < nBitsLeft; k++) {
    449           if (pArithDecoder->IsComplete())
    450             return nullptr;
    451 
    452           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    453           cVal1 |= bVal << (7 - k);
    454           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
    455                     (((line2 >> (10 - k))) & 0x0004);
    456         }
    457         pLine[nLineBytes] = cVal1;
    458       }
    459     }
    460     pLine += nStride;
    461   }
    462   return GBREG;
    463 }
    464 
    465 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template2_unopt(
    466     CJBig2_ArithDecoder* pArithDecoder,
    467     JBig2ArithCtx* gbContext) {
    468   int LTP = 0;
    469   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    470   GBREG->fill(0);
    471   for (uint32_t h = 0; h < GBH; h++) {
    472     if (TPGDON) {
    473       if (pArithDecoder->IsComplete())
    474         return nullptr;
    475 
    476       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]);
    477     }
    478     if (LTP) {
    479       GBREG->copyLine(h, h - 1);
    480     } else {
    481       uint32_t line1 = GBREG->getPixel(1, h - 2);
    482       line1 |= GBREG->getPixel(0, h - 2) << 1;
    483       uint32_t line2 = GBREG->getPixel(1, h - 1);
    484       line2 |= GBREG->getPixel(0, h - 1) << 1;
    485       uint32_t line3 = 0;
    486       for (uint32_t w = 0; w < GBW; w++) {
    487         int bVal;
    488         if (USESKIP && SKIP->getPixel(w, h)) {
    489           bVal = 0;
    490         } else {
    491           uint32_t CONTEXT = line3;
    492           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 2;
    493           CONTEXT |= line2 << 3;
    494           CONTEXT |= line1 << 7;
    495           if (pArithDecoder->IsComplete())
    496             return nullptr;
    497 
    498           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    499         }
    500         if (bVal) {
    501           GBREG->setPixel(w, h, bVal);
    502         }
    503         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
    504         line2 = ((line2 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x0f;
    505         line3 = ((line3 << 1) | bVal) & 0x03;
    506       }
    507     }
    508   }
    509   return GBREG;
    510 }
    511 
    512 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template3_opt3(
    513     CJBig2_ArithDecoder* pArithDecoder,
    514     JBig2ArithCtx* gbContext) {
    515   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    516   if (!GBREG->data())
    517     return nullptr;
    518 
    519   int LTP = 0;
    520   uint8_t* pLine = GBREG->data();
    521   int32_t nStride = GBREG->stride();
    522   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
    523   int32_t nBitsLeft = GBW - (nLineBytes << 3);
    524 
    525   for (uint32_t h = 0; h < GBH; h++) {
    526     if (TPGDON) {
    527       if (pArithDecoder->IsComplete())
    528         return nullptr;
    529 
    530       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]);
    531     }
    532 
    533     if (LTP) {
    534       GBREG->copyLine(h, h - 1);
    535     } else {
    536       if (h > 0) {
    537         uint8_t* pLine1 = pLine - nStride;
    538         uint32_t line1 = *pLine1++;
    539         uint32_t CONTEXT = (line1 >> 1) & 0x03f0;
    540         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    541           line1 = (line1 << 8) | (*pLine1++);
    542           uint8_t cVal = 0;
    543           for (int32_t k = 7; k >= 0; k--) {
    544             if (pArithDecoder->IsComplete())
    545               return nullptr;
    546 
    547             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    548             cVal |= bVal << k;
    549             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
    550                       ((line1 >> (k + 1)) & 0x0010);
    551           }
    552           pLine[cc] = cVal;
    553         }
    554         line1 <<= 8;
    555         uint8_t cVal1 = 0;
    556         for (int32_t k = 0; k < nBitsLeft; k++) {
    557           if (pArithDecoder->IsComplete())
    558             return nullptr;
    559 
    560           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    561           cVal1 |= bVal << (7 - k);
    562           CONTEXT =
    563               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
    564         }
    565         pLine[nLineBytes] = cVal1;
    566       } else {
    567         uint32_t CONTEXT = 0;
    568         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    569           uint8_t cVal = 0;
    570           for (int32_t k = 7; k >= 0; k--) {
    571             if (pArithDecoder->IsComplete())
    572               return nullptr;
    573 
    574             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    575             cVal |= bVal << k;
    576             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
    577           }
    578           pLine[cc] = cVal;
    579         }
    580         uint8_t cVal1 = 0;
    581         for (int32_t k = 0; k < nBitsLeft; k++) {
    582           if (pArithDecoder->IsComplete())
    583             return nullptr;
    584 
    585           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    586           cVal1 |= bVal << (7 - k);
    587           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
    588         }
    589         pLine[nLineBytes] = cVal1;
    590       }
    591     }
    592     pLine += nStride;
    593   }
    594   return GBREG;
    595 }
    596 
    597 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::decode_Arith_Template3_unopt(
    598     CJBig2_ArithDecoder* pArithDecoder,
    599     JBig2ArithCtx* gbContext) {
    600   int LTP = 0;
    601   auto GBREG = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    602   GBREG->fill(0);
    603   for (uint32_t h = 0; h < GBH; h++) {
    604     if (TPGDON) {
    605       if (pArithDecoder->IsComplete())
    606         return nullptr;
    607 
    608       LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]);
    609     }
    610     if (LTP == 1) {
    611       GBREG->copyLine(h, h - 1);
    612     } else {
    613       uint32_t line1 = GBREG->getPixel(1, h - 1);
    614       line1 |= GBREG->getPixel(0, h - 1) << 1;
    615       uint32_t line2 = 0;
    616       for (uint32_t w = 0; w < GBW; w++) {
    617         int bVal;
    618         if (USESKIP && SKIP->getPixel(w, h)) {
    619           bVal = 0;
    620         } else {
    621           uint32_t CONTEXT = line2;
    622           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
    623           CONTEXT |= line1 << 5;
    624           if (pArithDecoder->IsComplete())
    625             return nullptr;
    626 
    627           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    628         }
    629         if (bVal) {
    630           GBREG->setPixel(w, h, bVal);
    631         }
    632         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x1f;
    633         line2 = ((line2 << 1) | bVal) & 0x0f;
    634       }
    635     }
    636   }
    637   return GBREG;
    638 }
    639 
    640 FXCODEC_STATUS CJBig2_GRDProc::Start_decode_Arith(
    641     std::unique_ptr<CJBig2_Image>* pImage,
    642     CJBig2_ArithDecoder* pArithDecoder,
    643     JBig2ArithCtx* gbContext,
    644     IFX_PauseIndicator* pPause) {
    645   if (GBW == 0 || GBW > JBIG2_MAX_IMAGE_SIZE || GBH == 0 ||
    646       GBH > JBIG2_MAX_IMAGE_SIZE) {
    647     m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
    648     return FXCODEC_STATUS_DECODE_FINISH;
    649   }
    650   m_ProssiveStatus = FXCODEC_STATUS_DECODE_READY;
    651   if (!*pImage)
    652     *pImage = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    653   if (!(*pImage)->data()) {
    654     *pImage = nullptr;
    655     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
    656     return FXCODEC_STATUS_ERROR;
    657   }
    658   m_DecodeType = 1;
    659   m_pImage = pImage->get();
    660   m_pImage->fill(0);
    661   m_gbContext = gbContext;
    662   m_LTP = 0;
    663   m_pLine = nullptr;
    664   m_loopIndex = 0;
    665   return decode_Arith(pPause, pArithDecoder);
    666 }
    667 
    668 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith(
    669     IFX_PauseIndicator* pPause,
    670     CJBig2_ArithDecoder* pArithDecoder) {
    671   int iline = m_loopIndex;
    672   if (GBTEMPLATE == 0) {
    673     if (UseTemplate0Opt3()) {
    674       m_ProssiveStatus = decode_Arith_Template0_opt3(m_pImage, pArithDecoder,
    675                                                      m_gbContext, pPause);
    676     } else {
    677       m_ProssiveStatus = decode_Arith_Template0_unopt(m_pImage, pArithDecoder,
    678                                                       m_gbContext, pPause);
    679     }
    680   } else if (GBTEMPLATE == 1) {
    681     if (UseTemplate1Opt3()) {
    682       m_ProssiveStatus = decode_Arith_Template1_opt3(m_pImage, pArithDecoder,
    683                                                      m_gbContext, pPause);
    684     } else {
    685       m_ProssiveStatus = decode_Arith_Template1_unopt(m_pImage, pArithDecoder,
    686                                                       m_gbContext, pPause);
    687     }
    688   } else if (GBTEMPLATE == 2) {
    689     if (UseTemplate23Opt3()) {
    690       m_ProssiveStatus = decode_Arith_Template2_opt3(m_pImage, pArithDecoder,
    691                                                      m_gbContext, pPause);
    692     } else {
    693       m_ProssiveStatus = decode_Arith_Template2_unopt(m_pImage, pArithDecoder,
    694                                                       m_gbContext, pPause);
    695     }
    696   } else {
    697     if (UseTemplate23Opt3()) {
    698       m_ProssiveStatus = decode_Arith_Template3_opt3(m_pImage, pArithDecoder,
    699                                                      m_gbContext, pPause);
    700     } else {
    701       m_ProssiveStatus = decode_Arith_Template3_unopt(m_pImage, pArithDecoder,
    702                                                       m_gbContext, pPause);
    703     }
    704   }
    705   m_ReplaceRect.left = 0;
    706   m_ReplaceRect.right = m_pImage->width();
    707   m_ReplaceRect.top = iline;
    708   m_ReplaceRect.bottom = m_loopIndex;
    709   if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH)
    710     m_loopIndex = 0;
    711 
    712   return m_ProssiveStatus;
    713 }
    714 
    715 FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR(
    716     std::unique_ptr<CJBig2_Image>* pImage,
    717     CJBig2_BitStream* pStream) {
    718   int bitpos, i;
    719   auto image = pdfium::MakeUnique<CJBig2_Image>(GBW, GBH);
    720   if (!image->data()) {
    721     *pImage = nullptr;
    722     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
    723     return m_ProssiveStatus;
    724   }
    725   bitpos = static_cast<int>(pStream->getBitPos());
    726   FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos, image->data(),
    727               GBW, GBH, image->stride());
    728   pStream->setBitPos(bitpos);
    729   for (i = 0; (uint32_t)i < image->stride() * GBH; ++i)
    730     image->data()[i] = ~image->data()[i];
    731   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
    732   *pImage = std::move(image);
    733   return m_ProssiveStatus;
    734 }
    735 
    736 FXCODEC_STATUS CJBig2_GRDProc::Continue_decode(
    737     IFX_PauseIndicator* pPause,
    738     CJBig2_ArithDecoder* pArithDecoder) {
    739   if (m_ProssiveStatus != FXCODEC_STATUS_DECODE_TOBECONTINUE)
    740     return m_ProssiveStatus;
    741 
    742   if (m_DecodeType != 1) {
    743     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
    744     return m_ProssiveStatus;
    745   }
    746   return decode_Arith(pPause, pArithDecoder);
    747 }
    748 
    749 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3(
    750     CJBig2_Image* pImage,
    751     CJBig2_ArithDecoder* pArithDecoder,
    752     JBig2ArithCtx* gbContext,
    753     IFX_PauseIndicator* pPause) {
    754   if (!m_pLine)
    755     m_pLine = pImage->data();
    756   int32_t nStride = pImage->stride();
    757   int32_t nStride2 = nStride << 1;
    758   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
    759   int32_t nBitsLeft = GBW - (nLineBytes << 3);
    760   uint32_t height = GBH & 0x7fffffff;
    761 
    762   for (; m_loopIndex < height; m_loopIndex++) {
    763     if (TPGDON) {
    764       if (pArithDecoder->IsComplete())
    765         return FXCODEC_STATUS_ERROR;
    766 
    767       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]);
    768     }
    769     if (m_LTP) {
    770       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
    771     } else {
    772       if (m_loopIndex > 1) {
    773         uint8_t* pLine1 = m_pLine - nStride2;
    774         uint8_t* pLine2 = m_pLine - nStride;
    775         uint32_t line1 = (*pLine1++) << 6;
    776         uint32_t line2 = *pLine2++;
    777         uint32_t CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
    778         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    779           line1 = (line1 << 8) | ((*pLine1++) << 6);
    780           line2 = (line2 << 8) | (*pLine2++);
    781           uint8_t cVal = 0;
    782           for (int32_t k = 7; k >= 0; k--) {
    783             if (pArithDecoder->IsComplete())
    784               return FXCODEC_STATUS_ERROR;
    785 
    786             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    787             cVal |= bVal << k;
    788             CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
    789                        ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
    790           }
    791           m_pLine[cc] = cVal;
    792         }
    793         line1 <<= 8;
    794         line2 <<= 8;
    795         uint8_t cVal1 = 0;
    796         for (int32_t k = 0; k < nBitsLeft; k++) {
    797           if (pArithDecoder->IsComplete())
    798             return FXCODEC_STATUS_ERROR;
    799 
    800           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    801           cVal1 |= bVal << (7 - k);
    802           CONTEXT =
    803               (((CONTEXT & 0x7bf7) << 1) | bVal |
    804                ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
    805         }
    806         m_pLine[nLineBytes] = cVal1;
    807       } else {
    808         uint8_t* pLine2 = m_pLine - nStride;
    809         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
    810         uint32_t CONTEXT = (line2 & 0x07f0);
    811         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    812           if (m_loopIndex & 1) {
    813             line2 = (line2 << 8) | (*pLine2++);
    814           }
    815           uint8_t cVal = 0;
    816           for (int32_t k = 7; k >= 0; k--) {
    817             if (pArithDecoder->IsComplete())
    818               return FXCODEC_STATUS_ERROR;
    819 
    820             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    821             cVal |= bVal << k;
    822             CONTEXT =
    823                 (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
    824           }
    825           m_pLine[cc] = cVal;
    826         }
    827         line2 <<= 8;
    828         uint8_t cVal1 = 0;
    829         for (int32_t k = 0; k < nBitsLeft; k++) {
    830           if (pArithDecoder->IsComplete())
    831             return FXCODEC_STATUS_ERROR;
    832 
    833           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    834           cVal1 |= bVal << (7 - k);
    835           CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
    836                      ((line2 >> (7 - k)) & 0x0010));
    837         }
    838         m_pLine[nLineBytes] = cVal1;
    839       }
    840     }
    841     m_pLine += nStride;
    842     if (pPause && pPause->NeedToPauseNow()) {
    843       m_loopIndex++;
    844       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
    845       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
    846     }
    847   }
    848   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
    849   return FXCODEC_STATUS_DECODE_FINISH;
    850 }
    851 
    852 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_unopt(
    853     CJBig2_Image* pImage,
    854     CJBig2_ArithDecoder* pArithDecoder,
    855     JBig2ArithCtx* gbContext,
    856     IFX_PauseIndicator* pPause) {
    857   for (; m_loopIndex < GBH; m_loopIndex++) {
    858     if (TPGDON) {
    859       if (pArithDecoder->IsComplete())
    860         return FXCODEC_STATUS_ERROR;
    861 
    862       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]);
    863     }
    864     if (m_LTP) {
    865       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
    866     } else {
    867       uint32_t line1 = pImage->getPixel(1, m_loopIndex - 2);
    868       line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
    869       uint32_t line2 = pImage->getPixel(2, m_loopIndex - 1);
    870       line2 |= pImage->getPixel(1, m_loopIndex - 1) << 1;
    871       line2 |= pImage->getPixel(0, m_loopIndex - 1) << 2;
    872       uint32_t line3 = 0;
    873       for (uint32_t w = 0; w < GBW; w++) {
    874         int bVal;
    875         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
    876           bVal = 0;
    877         } else {
    878           uint32_t CONTEXT = line3;
    879           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
    880           CONTEXT |= line2 << 5;
    881           CONTEXT |= pImage->getPixel(w + GBAT[2], m_loopIndex + GBAT[3]) << 10;
    882           CONTEXT |= pImage->getPixel(w + GBAT[4], m_loopIndex + GBAT[5]) << 11;
    883           CONTEXT |= line1 << 12;
    884           CONTEXT |= pImage->getPixel(w + GBAT[6], m_loopIndex + GBAT[7]) << 15;
    885           if (pArithDecoder->IsComplete())
    886             return FXCODEC_STATUS_ERROR;
    887 
    888           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    889         }
    890         if (bVal) {
    891           pImage->setPixel(w, m_loopIndex, bVal);
    892         }
    893         line1 =
    894             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
    895         line2 =
    896             ((line2 << 1) | pImage->getPixel(w + 3, m_loopIndex - 1)) & 0x1f;
    897         line3 = ((line3 << 1) | bVal) & 0x0f;
    898       }
    899     }
    900     if (pPause && pPause->NeedToPauseNow()) {
    901       m_loopIndex++;
    902       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
    903       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
    904     }
    905   }
    906   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
    907   return FXCODEC_STATUS_DECODE_FINISH;
    908 }
    909 
    910 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3(
    911     CJBig2_Image* pImage,
    912     CJBig2_ArithDecoder* pArithDecoder,
    913     JBig2ArithCtx* gbContext,
    914     IFX_PauseIndicator* pPause) {
    915   if (!m_pLine)
    916     m_pLine = pImage->data();
    917   int32_t nStride = pImage->stride();
    918   int32_t nStride2 = nStride << 1;
    919   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
    920   int32_t nBitsLeft = GBW - (nLineBytes << 3);
    921   for (; m_loopIndex < GBH; m_loopIndex++) {
    922     if (TPGDON) {
    923       if (pArithDecoder->IsComplete())
    924         return FXCODEC_STATUS_ERROR;
    925 
    926       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]);
    927     }
    928     if (m_LTP) {
    929       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
    930     } else {
    931       if (m_loopIndex > 1) {
    932         uint8_t* pLine1 = m_pLine - nStride2;
    933         uint8_t* pLine2 = m_pLine - nStride;
    934         uint32_t line1 = (*pLine1++) << 4;
    935         uint32_t line2 = *pLine2++;
    936         uint32_t CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
    937         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    938           line1 = (line1 << 8) | ((*pLine1++) << 4);
    939           line2 = (line2 << 8) | (*pLine2++);
    940           uint8_t cVal = 0;
    941           for (int32_t k = 7; k >= 0; k--) {
    942             if (pArithDecoder->IsComplete())
    943               return FXCODEC_STATUS_ERROR;
    944 
    945             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    946             cVal |= bVal << k;
    947             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    948                       ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
    949           }
    950           m_pLine[cc] = cVal;
    951         }
    952         line1 <<= 8;
    953         line2 <<= 8;
    954         uint8_t cVal1 = 0;
    955         for (int32_t k = 0; k < nBitsLeft; k++) {
    956           if (pArithDecoder->IsComplete())
    957             return FXCODEC_STATUS_ERROR;
    958 
    959           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    960           cVal1 |= bVal << (7 - k);
    961           CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    962                     ((line1 >> (7 - k)) & 0x0200) |
    963                     ((line2 >> (8 - k)) & 0x0008);
    964         }
    965         m_pLine[nLineBytes] = cVal1;
    966       } else {
    967         uint8_t* pLine2 = m_pLine - nStride;
    968         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
    969         uint32_t CONTEXT = (line2 >> 1) & 0x01f8;
    970         for (int32_t cc = 0; cc < nLineBytes; cc++) {
    971           if (m_loopIndex & 1) {
    972             line2 = (line2 << 8) | (*pLine2++);
    973           }
    974           uint8_t cVal = 0;
    975           for (int32_t k = 7; k >= 0; k--) {
    976             if (pArithDecoder->IsComplete())
    977               return FXCODEC_STATUS_ERROR;
    978 
    979             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    980             cVal |= bVal << k;
    981             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
    982                       ((line2 >> (k + 1)) & 0x0008);
    983           }
    984           m_pLine[cc] = cVal;
    985         }
    986         line2 <<= 8;
    987         uint8_t cVal1 = 0;
    988         for (int32_t k = 0; k < nBitsLeft; k++) {
    989           if (pArithDecoder->IsComplete())
    990             return FXCODEC_STATUS_ERROR;
    991 
    992           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
    993           cVal1 |= bVal << (7 - k);
    994           CONTEXT =
    995               ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
    996         }
    997         m_pLine[nLineBytes] = cVal1;
    998       }
    999     }
   1000     m_pLine += nStride;
   1001     if (pPause && pPause->NeedToPauseNow()) {
   1002       m_loopIndex++;
   1003       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1004       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1005     }
   1006   }
   1007   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1008   return FXCODEC_STATUS_DECODE_FINISH;
   1009 }
   1010 
   1011 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_unopt(
   1012     CJBig2_Image* pImage,
   1013     CJBig2_ArithDecoder* pArithDecoder,
   1014     JBig2ArithCtx* gbContext,
   1015     IFX_PauseIndicator* pPause) {
   1016   for (uint32_t h = 0; h < GBH; h++) {
   1017     if (TPGDON) {
   1018       if (pArithDecoder->IsComplete())
   1019         return FXCODEC_STATUS_ERROR;
   1020 
   1021       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]);
   1022     }
   1023     if (m_LTP) {
   1024       pImage->copyLine(h, h - 1);
   1025     } else {
   1026       uint32_t line1 = pImage->getPixel(2, h - 2);
   1027       line1 |= pImage->getPixel(1, h - 2) << 1;
   1028       line1 |= pImage->getPixel(0, h - 2) << 2;
   1029       uint32_t line2 = pImage->getPixel(2, h - 1);
   1030       line2 |= pImage->getPixel(1, h - 1) << 1;
   1031       line2 |= pImage->getPixel(0, h - 1) << 2;
   1032       uint32_t line3 = 0;
   1033       for (uint32_t w = 0; w < GBW; w++) {
   1034         int bVal;
   1035         if (USESKIP && SKIP->getPixel(w, h)) {
   1036           bVal = 0;
   1037         } else {
   1038           uint32_t CONTEXT = line3;
   1039           CONTEXT |= pImage->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
   1040           CONTEXT |= line2 << 4;
   1041           CONTEXT |= line1 << 9;
   1042           if (pArithDecoder->IsComplete())
   1043             return FXCODEC_STATUS_ERROR;
   1044 
   1045           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1046         }
   1047         if (bVal) {
   1048           pImage->setPixel(w, h, bVal);
   1049         }
   1050         line1 = ((line1 << 1) | pImage->getPixel(w + 3, h - 2)) & 0x0f;
   1051         line2 = ((line2 << 1) | pImage->getPixel(w + 3, h - 1)) & 0x1f;
   1052         line3 = ((line3 << 1) | bVal) & 0x07;
   1053       }
   1054     }
   1055     if (pPause && pPause->NeedToPauseNow()) {
   1056       m_loopIndex++;
   1057       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1058       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1059     }
   1060   }
   1061   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1062   return FXCODEC_STATUS_DECODE_FINISH;
   1063 }
   1064 
   1065 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3(
   1066     CJBig2_Image* pImage,
   1067     CJBig2_ArithDecoder* pArithDecoder,
   1068     JBig2ArithCtx* gbContext,
   1069     IFX_PauseIndicator* pPause) {
   1070   if (!m_pLine)
   1071     m_pLine = pImage->data();
   1072   int32_t nStride = pImage->stride();
   1073   int32_t nStride2 = nStride << 1;
   1074   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
   1075   int32_t nBitsLeft = GBW - (nLineBytes << 3);
   1076   for (; m_loopIndex < GBH; m_loopIndex++) {
   1077     if (TPGDON) {
   1078       if (pArithDecoder->IsComplete())
   1079         return FXCODEC_STATUS_ERROR;
   1080 
   1081       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]);
   1082     }
   1083     if (m_LTP) {
   1084       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
   1085     } else {
   1086       if (m_loopIndex > 1) {
   1087         uint8_t* pLine1 = m_pLine - nStride2;
   1088         uint8_t* pLine2 = m_pLine - nStride;
   1089         uint32_t line1 = (*pLine1++) << 1;
   1090         uint32_t line2 = *pLine2++;
   1091         uint32_t CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
   1092         for (int32_t cc = 0; cc < nLineBytes; cc++) {
   1093           line1 = (line1 << 8) | ((*pLine1++) << 1);
   1094           line2 = (line2 << 8) | (*pLine2++);
   1095           uint8_t cVal = 0;
   1096           for (int32_t k = 7; k >= 0; k--) {
   1097             if (pArithDecoder->IsComplete())
   1098               return FXCODEC_STATUS_ERROR;
   1099 
   1100             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1101             cVal |= bVal << k;
   1102             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
   1103                       ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
   1104           }
   1105           m_pLine[cc] = cVal;
   1106         }
   1107         line1 <<= 8;
   1108         line2 <<= 8;
   1109         uint8_t cVal1 = 0;
   1110         for (int32_t k = 0; k < nBitsLeft; k++) {
   1111           if (pArithDecoder->IsComplete())
   1112             return FXCODEC_STATUS_ERROR;
   1113 
   1114           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1115           cVal1 |= bVal << (7 - k);
   1116           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
   1117                     ((line1 >> (7 - k)) & 0x0080) |
   1118                     ((line2 >> (10 - k)) & 0x0004);
   1119         }
   1120         m_pLine[nLineBytes] = cVal1;
   1121       } else {
   1122         uint8_t* pLine2 = m_pLine - nStride;
   1123         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
   1124         uint32_t CONTEXT = (line2 >> 3) & 0x007c;
   1125         for (int32_t cc = 0; cc < nLineBytes; cc++) {
   1126           if (m_loopIndex & 1) {
   1127             line2 = (line2 << 8) | (*pLine2++);
   1128           }
   1129           uint8_t cVal = 0;
   1130           for (int32_t k = 7; k >= 0; k--) {
   1131             if (pArithDecoder->IsComplete())
   1132               return FXCODEC_STATUS_ERROR;
   1133 
   1134             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1135             cVal |= bVal << k;
   1136             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
   1137                       ((line2 >> (k + 3)) & 0x0004);
   1138           }
   1139           m_pLine[cc] = cVal;
   1140         }
   1141         line2 <<= 8;
   1142         uint8_t cVal1 = 0;
   1143         for (int32_t k = 0; k < nBitsLeft; k++) {
   1144           if (pArithDecoder->IsComplete())
   1145             return FXCODEC_STATUS_ERROR;
   1146 
   1147           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1148           cVal1 |= bVal << (7 - k);
   1149           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
   1150                     (((line2 >> (10 - k))) & 0x0004);
   1151         }
   1152         m_pLine[nLineBytes] = cVal1;
   1153       }
   1154     }
   1155     m_pLine += nStride;
   1156     if (pPause && m_loopIndex % 50 == 0 && pPause->NeedToPauseNow()) {
   1157       m_loopIndex++;
   1158       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1159       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1160     }
   1161   }
   1162   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1163   return FXCODEC_STATUS_DECODE_FINISH;
   1164 }
   1165 
   1166 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_unopt(
   1167     CJBig2_Image* pImage,
   1168     CJBig2_ArithDecoder* pArithDecoder,
   1169     JBig2ArithCtx* gbContext,
   1170     IFX_PauseIndicator* pPause) {
   1171   for (; m_loopIndex < GBH; m_loopIndex++) {
   1172     if (TPGDON) {
   1173       if (pArithDecoder->IsComplete())
   1174         return FXCODEC_STATUS_ERROR;
   1175 
   1176       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]);
   1177     }
   1178     if (m_LTP) {
   1179       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
   1180     } else {
   1181       uint32_t line1 = pImage->getPixel(1, m_loopIndex - 2);
   1182       line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
   1183       uint32_t line2 = pImage->getPixel(1, m_loopIndex - 1);
   1184       line2 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
   1185       uint32_t line3 = 0;
   1186       for (uint32_t w = 0; w < GBW; w++) {
   1187         int bVal;
   1188         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
   1189           bVal = 0;
   1190         } else {
   1191           uint32_t CONTEXT = line3;
   1192           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 2;
   1193           CONTEXT |= line2 << 3;
   1194           CONTEXT |= line1 << 7;
   1195           if (pArithDecoder->IsComplete())
   1196             return FXCODEC_STATUS_ERROR;
   1197 
   1198           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1199         }
   1200         if (bVal) {
   1201           pImage->setPixel(w, m_loopIndex, bVal);
   1202         }
   1203         line1 =
   1204             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
   1205         line2 =
   1206             ((line2 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x0f;
   1207         line3 = ((line3 << 1) | bVal) & 0x03;
   1208       }
   1209     }
   1210     if (pPause && pPause->NeedToPauseNow()) {
   1211       m_loopIndex++;
   1212       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1213       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1214     }
   1215   }
   1216   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1217   return FXCODEC_STATUS_DECODE_FINISH;
   1218 }
   1219 
   1220 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3(
   1221     CJBig2_Image* pImage,
   1222     CJBig2_ArithDecoder* pArithDecoder,
   1223     JBig2ArithCtx* gbContext,
   1224     IFX_PauseIndicator* pPause) {
   1225   if (!m_pLine)
   1226     m_pLine = pImage->data();
   1227   int32_t nStride = pImage->stride();
   1228   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
   1229   int32_t nBitsLeft = GBW - (nLineBytes << 3);
   1230   for (; m_loopIndex < GBH; m_loopIndex++) {
   1231     if (TPGDON) {
   1232       if (pArithDecoder->IsComplete())
   1233         return FXCODEC_STATUS_ERROR;
   1234 
   1235       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]);
   1236     }
   1237     if (m_LTP) {
   1238       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
   1239     } else {
   1240       if (m_loopIndex > 0) {
   1241         uint8_t* pLine1 = m_pLine - nStride;
   1242         uint32_t line1 = *pLine1++;
   1243         uint32_t CONTEXT = (line1 >> 1) & 0x03f0;
   1244         for (int32_t cc = 0; cc < nLineBytes; cc++) {
   1245           line1 = (line1 << 8) | (*pLine1++);
   1246           uint8_t cVal = 0;
   1247           for (int32_t k = 7; k >= 0; k--) {
   1248             if (pArithDecoder->IsComplete())
   1249               return FXCODEC_STATUS_ERROR;
   1250 
   1251             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1252             cVal |= bVal << k;
   1253             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
   1254                       ((line1 >> (k + 1)) & 0x0010);
   1255           }
   1256           m_pLine[cc] = cVal;
   1257         }
   1258         line1 <<= 8;
   1259         uint8_t cVal1 = 0;
   1260         for (int32_t k = 0; k < nBitsLeft; k++) {
   1261           if (pArithDecoder->IsComplete())
   1262             return FXCODEC_STATUS_ERROR;
   1263 
   1264           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1265           cVal1 |= bVal << (7 - k);
   1266           CONTEXT =
   1267               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
   1268         }
   1269         m_pLine[nLineBytes] = cVal1;
   1270       } else {
   1271         uint32_t CONTEXT = 0;
   1272         for (int32_t cc = 0; cc < nLineBytes; cc++) {
   1273           uint8_t cVal = 0;
   1274           for (int32_t k = 7; k >= 0; k--) {
   1275             if (pArithDecoder->IsComplete())
   1276               return FXCODEC_STATUS_ERROR;
   1277 
   1278             int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1279             cVal |= bVal << k;
   1280             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
   1281           }
   1282           m_pLine[cc] = cVal;
   1283         }
   1284         uint8_t cVal1 = 0;
   1285         for (int32_t k = 0; k < nBitsLeft; k++) {
   1286           if (pArithDecoder->IsComplete())
   1287             return FXCODEC_STATUS_ERROR;
   1288 
   1289           int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1290           cVal1 |= bVal << (7 - k);
   1291           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
   1292         }
   1293         m_pLine[nLineBytes] = cVal1;
   1294       }
   1295     }
   1296     m_pLine += nStride;
   1297     if (pPause && pPause->NeedToPauseNow()) {
   1298       m_loopIndex++;
   1299       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1300       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1301     }
   1302   }
   1303   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1304   return FXCODEC_STATUS_DECODE_FINISH;
   1305 }
   1306 
   1307 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_unopt(
   1308     CJBig2_Image* pImage,
   1309     CJBig2_ArithDecoder* pArithDecoder,
   1310     JBig2ArithCtx* gbContext,
   1311     IFX_PauseIndicator* pPause) {
   1312   for (; m_loopIndex < GBH; m_loopIndex++) {
   1313     if (TPGDON) {
   1314       if (pArithDecoder->IsComplete())
   1315         return FXCODEC_STATUS_ERROR;
   1316 
   1317       m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]);
   1318     }
   1319     if (m_LTP) {
   1320       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
   1321     } else {
   1322       uint32_t line1 = pImage->getPixel(1, m_loopIndex - 1);
   1323       line1 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
   1324       uint32_t line2 = 0;
   1325       for (uint32_t w = 0; w < GBW; w++) {
   1326         int bVal;
   1327         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
   1328           bVal = 0;
   1329         } else {
   1330           uint32_t CONTEXT = line2;
   1331           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
   1332           CONTEXT |= line1 << 5;
   1333           if (pArithDecoder->IsComplete())
   1334             return FXCODEC_STATUS_ERROR;
   1335 
   1336           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
   1337         }
   1338         if (bVal) {
   1339           pImage->setPixel(w, m_loopIndex, bVal);
   1340         }
   1341         line1 =
   1342             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x1f;
   1343         line2 = ((line2 << 1) | bVal) & 0x0f;
   1344       }
   1345     }
   1346     if (pPause && pPause->NeedToPauseNow()) {
   1347       m_loopIndex++;
   1348       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1349       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
   1350     }
   1351   }
   1352   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
   1353   return FXCODEC_STATUS_DECODE_FINISH;
   1354 }
   1355