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
19CJBig2_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
30CJBig2_GRDProc::~CJBig2_GRDProc() {}
31
32bool 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
38bool CJBig2_GRDProc::UseTemplate1Opt3() const {
39  return (GBAT[0] == 3) && (GBAT[1] == -1);
40}
41
42bool CJBig2_GRDProc::UseTemplate23Opt3() const {
43  return (GBAT[0] == 2) && (GBAT[1] == -1);
44}
45
46std::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
73std::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
171std::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
222std::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
319std::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
368std::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
465std::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
512std::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
597std::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
640FXCODEC_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
668FXCODEC_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
715FXCODEC_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
736FXCODEC_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
749FXCODEC_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
852FXCODEC_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
910FXCODEC_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
1011FXCODEC_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
1065FXCODEC_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
1166FXCODEC_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
1220FXCODEC_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
1307FXCODEC_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