• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CJBig2_GRDProc()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 
~CJBig2_GRDProc()30 CJBig2_GRDProc::~CJBig2_GRDProc() {}
31 
UseTemplate0Opt3() const32 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 
UseTemplate1Opt3() const38 bool CJBig2_GRDProc::UseTemplate1Opt3() const {
39   return (GBAT[0] == 3) && (GBAT[1] == -1);
40 }
41 
UseTemplate23Opt3() const42 bool CJBig2_GRDProc::UseTemplate23Opt3() const {
43   return (GBAT[0] == 2) && (GBAT[1] == -1);
44 }
45 
decode_Arith(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template0_opt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template0_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template1_opt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template1_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template2_opt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template2_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template3_opt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
decode_Arith_Template3_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)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 
Start_decode_Arith(std::unique_ptr<CJBig2_Image> * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith(IFX_PauseIndicator * pPause,CJBig2_ArithDecoder * pArithDecoder)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 
Start_decode_MMR(std::unique_ptr<CJBig2_Image> * pImage,CJBig2_BitStream * pStream)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 
Continue_decode(IFX_PauseIndicator * pPause,CJBig2_ArithDecoder * pArithDecoder)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 
decode_Arith_Template0_opt3(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template0_unopt(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template1_opt3(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template1_unopt(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template2_opt3(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template2_unopt(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template3_opt3(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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 
decode_Arith_Template3_unopt(CJBig2_Image * pImage,CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,IFX_PauseIndicator * pPause)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